diff --git a/.gitignore b/.gitignore index 9947219..069fb21 100644 --- a/.gitignore +++ b/.gitignore @@ -62,6 +62,7 @@ build/ docs/doxygen/html/ client/godonnie/Log/ +Log/ # gtts resource download.mp3 @@ -84,3 +85,9 @@ GoDonnieLexer.c GoDonnieLexer.h GoDonnieParser.c GoDonnieParser.h + +# Files generated by install.sh +Player +Stage +docs/_build +donnie-assistive-robot-sw diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5819a5a --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "docs/wiki/player-stage"] + path = docs/wiki/player-stage + url = https://github.com/lsa-pucrs/Player-Stage-Manual diff --git a/.travis.yml b/.travis.yml index 542da50..c3566ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,7 @@ before_install: # install Player/Stage depedencies - sudo apt-get install -y libfltk1.1-dev freeglut3-dev libpng12-dev libltdl-dev libdb5.1-stl libgnomecanvasmm-2.6-dev python-gnome2 #sudo apt-get install -y libboost-all-dev # overkill, the actually required libraries are boostthread, boostsignal, boostsystem -- sudo apt-get install -y libboost-signals-dev libboost-system-dev libboost-thread-dev +- sudo apt-get install -y libboost-signals-dev libboost-system-dev libboost-thread-dev libboost-locale-dev # old OpenCV for older Player drivers - sudo apt-get install -y libopencv-dev libopencv-core-dev libcv-dev libcvaux-dev libhighgui-dev - sudo apt-get install -y libasound2-dev libgsl0-dev libxmu-dev libpq-dev libpqxx-dev diff --git a/CMakeLists.txt b/CMakeLists.txt index dddcb2f..249f793 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,8 @@ project(Donnie) #ENDIF (POLICY CMP0048) #set(PROJECT_VERSION "0.1") +cmake_policy(SET CMP0017 OLD) + ##################################### # check DONNIE_PATH if(DEFINED ENV{DONNIE_PATH}) @@ -27,15 +29,23 @@ message(STATUS "DONNIE_SOURCE_PATH = ${DONNIE_SOURCE_PATH}") ##################################### # important varaiable used to find packages if(DEFINED ENV{PKG_CONFIG_PATH}) - SET (PKG_CONFIG_PATH $ENV{PKG_CONFIG_PATH}) - MESSAGE(STATUS "PKG_CONFIG_PATH = $ENV{PKG_CONFIG_PATH}") + #SET (PKG_CONFIG_PATH $ENV{PKG_CONFIG_PATH}) + # get the CMake module paths from the environmental variable CMAKE_MODULE_PATH + set(AUX_PKG_CONFIG_PATH "$ENV{PKG_CONFIG_PATH}") + # PKG_CONFIG_PATH must be a list, with ; as delimitation character + string(REPLACE ":" ";" PKG_CONFIG_PATH ${AUX_PKG_CONFIG_PATH}) + MESSAGE(STATUS "PKG_CONFIG_PATH = ${PKG_CONFIG_PATH}") else() message(FATAL_ERROR "PKG_CONFIG_PATH is NOT defined. Set where to find the pkg-config files.") endif() if(DEFINED ENV{CMAKE_MODULE_PATH}) - SET (CMAKE_MODULE_PATH $ENV{CMAKE_MODULE_PATH}) - MESSAGE(STATUS "CMAKE_MODULE_PATH = $ENV{CMAKE_MODULE_PATH}") + #SET (CMAKE_MODULE_PATH $ENV{CMAKE_MODULE_PATH}) + # get the CMake module paths from the environmental variable CMAKE_MODULE_PATH + set(AUX_CMAKE_MODULE_PATH "$ENV{CMAKE_MODULE_PATH}") + # CMAKE_MODULE_PATH must be a list, with ; as delimitation character + string(REPLACE ":" ";" CMAKE_MODULE_PATH ${AUX_CMAKE_MODULE_PATH}) + MESSAGE(STATUS "CMAKE_MODULE_PATH = ${CMAKE_MODULE_PATH}") else() message(FATAL_ERROR "CMAKE_MODULE_PATH is NOT defined. Set where to find the cmake files.") endif() @@ -130,6 +140,7 @@ MESSAGE (STATUS "----- Identification Done -----") ###################################### # Compile/Install Donnie + MESSAGE (STATUS) MESSAGE (STATUS "----- Processing client makefiles -----") add_subdirectory(client) diff --git a/README.md b/README.md index b7aad7e..d53d767 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ most of the programming environments for kids are high visual, based on grab and Donnie project proposes an inclusive robotic programming environment where all students (with or without visual disabilities) can use. -Donnie comes with two usage options: simulated robot and physical robot. It is recommend to start with the simulated since it does not require building the robot. Moreover, the physical robot is functional, but still under test. +Donnie comes with two usage options: simulated robot and physical robot. It is recommended to start with the simulated since it does not require building the robot. Moreover, currently the physical robot is functional, but it is still under test. Contents -------- @@ -58,7 +58,7 @@ alt="IMAGE ALT TEXT HERE" width="240" height="180" border="10" /> ## Run Donnie Software from a Virtual Machine - Download this [VM](link) all Donnie software pre-installed and ready to run. + Download this [VM](http://www.osboxes.org/linux-mint/), select the Linux Mint 17.3 'Rosa', and selected the [Mate](https://drive.google.com/file/d/0B_HAFnYs6Ur-NGFCZWNFV2dBN2M/view?usp=sharing) version. Finally, follow the instructions to install Donnie package. ## Install Donnie Software on a Desktop Computer Using the Packages @@ -70,11 +70,11 @@ alt="IMAGE ALT TEXT HERE" width="240" height="180" border="10" /> * It is recommended to update your packages before the instalation: > sudo apt-get update * To install, you can double-click it or execute: -> sudo dpkg -i donnie_1.0.0_amd64.deb -* In case of missing dependencies, try: -> sudo apt-get install -f +> sudo dpkg -i donnie-player-stage_0.1_amd64.deb +* In case of missing dependencies, try: +> sudo apt-get -f install * To unistall: -> sudo dpkg -r donnie +> sudo dpkg -r donnie-player-stage ## Compile and Install Donnie Software on a Desktop Computer @@ -88,6 +88,7 @@ alt="IMAGE ALT TEXT HERE" width="240" height="180" border="10" /> mkdir ~/donnie; cd ~/donnie wget https://github.com/lsa-pucrs/donnie-assistive-robot-sw/raw/devel/install.sh chmod +x ./install.sh + export DONNIE_PATH=/opt/donnie ./install.sh ### Configuring Donnie @@ -99,8 +100,8 @@ The build system is based on CMake, so it is required to have some experience wi Every part of Donnie Software Stack is also based on CMake. These are the software parts that can be customized: - raspicam driver -- Player -- Stage +- [Player](https://github.com/playerproject/player) +- [Stage](https://github.com/rtv/Stage) - Donnie Software each of these packages have their one sets of parameters. @@ -113,6 +114,12 @@ Developers interested in customization might want to read the following files: - [install/setup-rpi.sh](install/setup-rpi.sh) - and all the CMakeLists.txt files +### Learning Player and Stage + +Donnie is based on Player/Stage robotic middlware and simulator. It is higly +recommended for Donnie developers to understand Player/Stage to add more features, +create new elaborated scenarios, etc. The official documents are [Player](https://playerproject.github.io/), [Player wiki](https://github.com/playerproject/player/wiki) and [Stage](http://rtv.github.io/Stage/). +However, the best documentation is the [Player/Stage tutorial](http://player-stage-manual.readthedocs.io). ### Parameter for Donnie Software @@ -157,7 +164,8 @@ To build your own Donnie robot, please refer to the following repositories (gith mkdir ~/donnie; cd ~/donnie wget https://github.com/lsa-pucrs/donnie-assistive-robot-sw/raw/devel/install-rpi.sh - chmod +x ./install-rpi.sh + chmod +x ./install-rpi.sh + export DONNIE_PATH=/opt/donnie ./install-rpi.sh Experienced programmers can configure the same paramerters presented before for the Raspberry Pi. diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 4fc79f0..d73b8d7 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -5,10 +5,9 @@ IF(NOT ROBOT_COMPUTER) # if it is compiling for the desktop computer, then compile the following modules add_subdirectory(godonnie) add_subdirectory(alerts) + #add_subdirectory(vib_belt) add_subdirectory(test) ELSE() # if it is compiling for robot`s computer (RPi) add_subdirectory(alerts) ENDIF() - - diff --git a/client/alerts/CMakeLists.txt b/client/alerts/CMakeLists.txt index 85e7fb7..2aaf88a 100644 --- a/client/alerts/CMakeLists.txt +++ b/client/alerts/CMakeLists.txt @@ -5,25 +5,28 @@ PROJECT (${CLIENTNAME}) message(STATUS "Configuring '${CLIENTNAME}'") ######### -# check depedencies - libsox +# check DONNIE_PATH ######### -find_path( LSOX_INCLUDE_DIR sox.h DOC "Libsox include dir" ) -find_library( LSOX_LIB - NAMES sox - HINTS /usr/lib/x86_64-linux-gnu/ - DOC "Libsox lib" REQUIRED) - -IF( NOT LSOX_LIB ) - MESSAGE( FATAL_ERROR "libSoX not found. Please install 'sudo apt-get install libsox-dev'. aborting" ) +if(DEFINED ENV{DONNIE_PATH}) + SET(DONNIE_PATH "$ENV{DONNIE_PATH}") + #message(STATUS "DONNIE_PATH = ${DONNIE_PATH}") +else() + message(FATAL_ERROR "DONNIE_PATH is NOT defined") +endif() + +######### +# check depedencies - boost locale +######### +FIND_PACKAGE (Boost REQUIRED COMPONENTS locale) +IF( NOT Boost_FOUND ) + MESSAGE( FATAL_ERROR "Libboost-locale not found. Please install 'sudo apt-get install libboost-locale-dev'. aborting" ) ENDIF() -message(STATUS "SoX Library -- ${LSOX_LIB}") -message(STATUS "SoX Include -- ${LSOX_INCLUDE_DIR}") +######### +# set Player cmake modules +######### # Include this CMake module to get most of the settings needed to build -SET (CMAKE_MODULE_PATH "/usr/local/share/cmake/Modules") - -# required to support 'acentos' in Portuguese -#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexec-charset=iso-8859-1") +#SET (CMAKE_MODULE_PATH "/usr/local/share/cmake/Modules") INCLUDE (UsePlayerC++) @@ -31,8 +34,8 @@ PLAYER_ADD_PLAYERCPP_CLIENT (${CLIENTNAME} SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/alerts.cc ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/utils.cpp INCLUDEDIRS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/) -TARGET_LINK_LIBRARIES (${CLIENTNAME} sox) -INCLUDE_DIRECTORIES (${CMAKE_CURRENT_SOURCE_DIR} ${LSOX_INCLUDE_DIR}) +TARGET_LINK_LIBRARIES (${CLIENTNAME} ${Boost_LIBRARIES}) +INCLUDE_DIRECTORIES (${CMAKE_CURRENT_SOURCE_DIR} ${Boost_INCLUDE_DIR}) # Install executables with -x permission INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${CLIENTNAME} DESTINATION ${DONNIE_PATH}/bin) diff --git a/client/alerts/alerts.cc b/client/alerts/alerts.cc index 9feb900..5ffe61e 100644 --- a/client/alerts/alerts.cc +++ b/client/alerts/alerts.cc @@ -14,15 +14,29 @@ DonnieClient::DonnieClient() { string host = GetEnv("DONNIE_IP"); string donnie_path = GetEnv("DONNIE_PATH"); + string donnie_lang = GetEnv("DONNIE_LANG"); + int port = atoi(GetEnv("DONNIE_PORT").c_str()); if(host.size()==0) host = "localhost"; if(port==0) port = 6665; if (donnie_path=="") { - cerr << "variable DONNIE_PATH not defined. Please execute 'export DONNIE_PATH='" << endl; + cerr << translate("variable DONNIE_PATH not defined. Please execute 'export DONNIE_PATH='") << endl; exit(1); } - - // TODO: read a configuration file so user can change these sounds + if (donnie_lang=="") { + cerr << translate("variable DONNIE_LANG not defined. Please execute 'export DONNIE_LANG=$LANGUAGE'") << endl; + exit(1); + } + // Set up language environment + generator gen; + gen.add_messages_path(donnie_path + "/resources/loc"); + gen.add_messages_domain("alerts"); + locale loc = gen(donnie_lang + ".UTF-8"); + locale::global(loc); + cout.imbue(loc); + cerr.imbue(loc); + + // TODO: read a configuration file so user can change these sounds SSTEP = donnie_path+"/resources/sounds/HIT.wav"; //Sound STEP SSBACK = donnie_path+"/resources/sounds/192805sound13.wav"; //Sound Step BACK STRIGHT = donnie_path+"/resources/sounds/126413specialcoin.wav"; //Sound Turn RIGHT @@ -45,8 +59,8 @@ DonnieClient::DonnieClient() #ifndef NDEBUG cerr << e << endl; #endif - cerr << "Não foi possível conectar no robô " << endl; - cerr << "Possivelmente o arquivo cfg está incorreto." << endl; + cerr << translate("Não foi possível conectar no robô ") << endl; + cerr << translate("Possivelmente o arquivo cfg está incorreto.") << endl; exit(1); } @@ -96,7 +110,7 @@ void DonnieClient::checkSteps(){ /*if(dir>0)sound->play((char *)SSTEP.c_str()); if(dir<0)sound->play((char *)SSBACK.c_str());*/ #ifndef NDEBUG - cout << "translation>=STEP_LENGHT_ERROR:" << translation << endl; + cout << translate("translation>=STEP_LENGHT_ERROR:") << translation << endl; #endif } translation=0; diff --git a/client/alerts/alerts.h b/client/alerts/alerts.h index 747922c..2d3e8d8 100644 --- a/client/alerts/alerts.h +++ b/client/alerts/alerts.h @@ -7,8 +7,14 @@ #include "utils.h" #include +// Localization libraries +#include + using namespace std; using namespace PlayerCc; +using namespace boost::locale; +using boost::locale::translate; +using boost::locale::format; typedef struct PathNodes{ double x, y, a; diff --git a/client/godonnie/CMakeLists.txt b/client/godonnie/CMakeLists.txt index 7779058..daa5217 100644 --- a/client/godonnie/CMakeLists.txt +++ b/client/godonnie/CMakeLists.txt @@ -1,4 +1,6 @@ CMAKE_MINIMUM_REQUIRED (VERSION 2.8 FATAL_ERROR) +cmake_policy(SET CMP0017 OLD) + SET (CLIENTNAME "GoDonnie") PROJECT (${CLIENTNAME}) @@ -27,7 +29,7 @@ endif() # Include this CMake module to get most of the settings needed to build -SET (CMAKE_MODULE_PATH "/usr/local/share/cmake/Modules") +#SET (CMAKE_MODULE_PATH "/usr/local/share/cmake/Modules") ######### # check depedencies - java -lreadline -lantlr3c @@ -62,14 +64,28 @@ find_library( LANTLR3_LIB DOC "Liantlr3 lib" REQUIRED) IF( NOT LANTLR3_LIB ) - MESSAGE( FATAL_ERROR "Liantlr3 not found. Please install 'sudo apt-get install libantlr3c-dev'. aborting" ) + MESSAGE( FATAL_ERROR "Libantlr3 not found. Please install 'sudo apt-get install libantlr3c-dev'. aborting" ) ENDIF() message(STATUS "ANTLR3 Library -- ${LANTLR3_LIB}") message(STATUS "ANTLR3 Include -- ${LANTLR3_INCLUDE_DIR}") +######### +# check depedencies - boost locale +######### +FIND_PACKAGE (Boost REQUIRED COMPONENTS locale) +IF( NOT Boost_FOUND ) + MESSAGE( FATAL_ERROR "Libboost-locale not found. Please install 'sudo apt-get install libboost-locale-dev'. aborting" ) +ENDIF() + ######### # run antlr ######### +# Check for DONNIE_LANG variable +IF (NOT DEFINED ENV{DONNIE_LANG}) + # If not defined, set to system language + SET (ENV{DONNIE_LANG} ENV{LANGUAGE}) +ENDIF() + ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/GoDonnie.tokens COMMAND java -jar ${CMAKE_CURRENT_SOURCE_DIR}/Antlr/antlr-3.2.jar -o ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/GoDonnie.g DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/GoDonnie.g @@ -104,8 +120,8 @@ PLAYER_ADD_PLAYERCPP_CLIENT (${CLIENTNAME} INCLUDEDIRS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/) # add the includes and libs to build it -TARGET_LINK_LIBRARIES (${CLIENTNAME} ${LREADLINE_LIB} ${LANTLR3_LIB}) -INCLUDE_DIRECTORIES (${CMAKE_CURRENT_SOURCE_DIR} ${LANTLR3_INCLUDE_DIR} ${LREADLINE_INCLUDE_DIR} ) +TARGET_LINK_LIBRARIES (${CLIENTNAME} ${LREADLINE_LIB} ${LANTLR3_LIB} ${Boost_LIBRARIES}) +INCLUDE_DIRECTORIES (${CMAKE_CURRENT_SOURCE_DIR} ${LANTLR3_INCLUDE_DIR} ${LREADLINE_INCLUDE_DIR} ${Boost_INCLUDE_DIR}) # godonnie depends on GoDonnieParser. This makes sure that the parser is built before the GoDonnie interpreter add_dependencies(GoDonnie GoDonnieParser) diff --git a/client/godonnie/Compiler.cpp b/client/godonnie/Compiler.cpp index 1814d84..521655f 100644 --- a/client/godonnie/Compiler.cpp +++ b/client/godonnie/Compiler.cpp @@ -7,7 +7,7 @@ #include "Historic.h" // this parser uses antlr 3.4, with support to C code generation -// manual is available at +// manual is available at //https://theantlrguy.atlassian.net/wiki/display/ANTLR3/ANTLR+v3+printable+documentation //http://www.antlr3.org/api/C/index.html // this is the source code of -lantlr3 library. run doxygen to generate the docs @@ -38,13 +38,13 @@ using std::endl; #define POSITION_YAW_CAP "A" /// definition of the color tokens in Portuguese -#define COLOR_BLUE "azul" -#define COLOR_RED "vermelho" -#define COLOR_GREEN "verde" +//#define COLOR_BLUE "azul" +//#define COLOR_RED "vermelho" +//#define COLOR_GREEN "verde" /// definition of the on/off tokens in Portuguese -#define SOUND_ON "ligado" -#define SOUND_OFF "desligado" +//#define TOKEN_ON "ligado" +//#define TOKEN_OFF "desligado" /// definition of variable return tokens #define IDLE 4 @@ -54,6 +54,8 @@ using std::endl; #define NEXIST 0 #define EXIST -1 +#define ARRAY_SIZE(array) (sizeof((array))/sizeof((array[0]))) //retorna o tamanho do array + DonnieMemory *DonnieMemory::singleton = 0; extern "C" char messageError[2000]; //global variable for error messages generated by antlr (see GoDonnie.g) @@ -69,13 +71,14 @@ ExprTreeEvaluator::ExprTreeEvaluator() for_itFlag = IDLE; done = 0; log = NULL; + enable_log = false; } ExprTreeEvaluator::~ExprTreeEvaluator() { DonnieClient::ResetInstance(); Donnie = NULL; - + Historic::ResetInstance(); History = NULL; } @@ -85,22 +88,43 @@ void ExprTreeEvaluator::logFile(FILE *file) log = file; } -int ExprTreeEvaluator::parseGD(char* textIn, bool enable_log) + +void ExprTreeEvaluator::setLog(bool log) +{ + enable_log = log; +} + + +bool ExprTreeEvaluator::getLog() +{ + return enable_log; +} + + +int ExprTreeEvaluator::parseGD(char* textIn) { + // Set up language environment + generator gen; + gen.add_messages_path(string(getenv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("Compiler"); + locale loc = gen(string(getenv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + cout.imbue(loc); + // remove accented characters string code = cleanAccents(string(textIn)); - uint8_t* bufferData = (uint8_t*)code.c_str(); + uint8_t* bufferData = (uint8_t*)code.c_str(); uint32_t bufferSize = strlen(code.c_str()); //uint8_t* bufferData = (uint8_t*)textIn; //uint32_t bufferSize = strlen(textIn); pANTLR3_UINT8 bufferName = (pANTLR3_UINT8)"INPUT text"; pANTLR3_INPUT_STREAM input = antlr3NewAsciiStringInPlaceStream( bufferData, bufferSize, bufferName); if (input == NULL) { - cout << "Out of memory trying to allocate ANTLR input stream\n"; + cout << translate("Out of memory trying to allocate ANTLR input stream\n"); exit(ANTLR3_ERR_NOMEM); } - //TODO: amory. com esta funcao eu acredito que eh possivel tornar a linguagem case insentive, + //TODO: amory. com esta funcao eu acredito que eh possivel tornar a linguagem case insentive, // simplificando o arquivo .g //https://github.com/antlr/antlr3/blob/master/runtime/C/include/antlr3input.h#L152 //https://track.hpccsystems.com/browse/WSSQL-118 @@ -109,23 +133,23 @@ int ExprTreeEvaluator::parseGD(char* textIn, bool enable_log) pGoDonnieLexer lex = GoDonnieLexerNew(input); if (lex == NULL) { - cout << "Unable to create the lexer due to malloc() failure\n"; + cout << translate("Unable to create the lexer due to malloc() failure\n"); exit(ANTLR3_ERR_NOMEM); - - } + + } pANTLR3_COMMON_TOKEN_STREAM tokens = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(lex)); if (tokens == NULL) { - cout << "Out of memory trying to allocate token stream\n"; - exit(ANTLR3_ERR_NOMEM); + cout << translate("Out of memory trying to allocate token stream\n"); + exit(ANTLR3_ERR_NOMEM); } // Finally, now that we have our lexer constructed, we can create the parser pGoDonnieParser parser = GoDonnieParserNew(tokens); if (parser == NULL) { - cout << "Out of memory trying to allocate parser\n"; + cout << translate("Out of memory trying to allocate parser\n"); exit(ANTLR3_ERR_NOMEM); } @@ -137,12 +161,12 @@ int ExprTreeEvaluator::parseGD(char* textIn, bool enable_log) r = parser->start_rule(parser); if (r.tree == NULL) { - cout << "Parse error" << endl; + cout << translate("Parse error") << endl; exit(ANTLR3_ERR_NOMEM); - } + } // print the parse tree #ifndef NDEBUG - cout << "Tree : " << r.tree->toStringTree(r.tree)->chars << endl; + cout << translate("Tree : ") << r.tree->toStringTree(r.tree)->chars << endl; #endif } catch(exception& e) @@ -150,7 +174,7 @@ int ExprTreeEvaluator::parseGD(char* textIn, bool enable_log) cout << e.what(); return -1; } - + // If the parser ran correctly, we will have a tree to parse. In general I recommend // keeping your own flags as part of the error trapping, but here is how you can // work out if there were errors if you are using the generic error messages @@ -160,23 +184,26 @@ int ExprTreeEvaluator::parseGD(char* textIn, bool enable_log) if (errors > 0) { cout << messageError << endl; //messageError is a global variable from GoDonnieParser.c. It contains the errors messages generated by antlr in GoDonnie.g - Donnie->speak(messageError); + + Donnie->speak(messageError); flagMsgError = 1; //flag to clean the 'messageError' string in grammar file (GoDonnie.g) after it is printed here - } - + } + else{ + //cout << translate("Tree : ") << r.tree->toStringTree(r.tree)->chars << endl; + // if text is parsed without error and logging is enabled, then save log // log is enabled only in terminal mode and not in the script mode - if (enable_log){ + if (getLog()){ if(log != NULL) { - if(fprintf(log, "%s", textIn) == EOF) - cout << "Erro ao salvar comando no log" << endl; + if(fprintf(log, "%s\n", textIn) == EOF) + cout << translate("Erro ao salvar comando no log") << endl; else fflush(log); } - } - + } + //if all tests passed, try to run the GoDonnie code try{ this->run(r.tree); @@ -186,19 +213,33 @@ int ExprTreeEvaluator::parseGD(char* textIn, bool enable_log) Donnie->speak(e.what()); } } - + parser->free(parser); tokens->free(tokens); lex->free(lex); input->close(input); - + return done; } + + int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) { - std::ostringstream sayStr; + // Set up language environment + generator gen; + gen.add_messages_path(string(getenv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("Compiler"); + locale loc = gen(string(getenv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + cout.imbue(loc); + + string crash_str = translate("bateu"); + string ncrash_str = translate("não bateu"); + + std::ostringstream sayStr; pANTLR3_COMMON_TOKEN tok = tree->getToken(tree); + printf("%d", tok->type); if(tok) { switch(tok->type) { @@ -210,9 +251,9 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) case ID: { return DonnieMemory::getInstance()->getVar(getText(tree)); - break; + break; } - + case STRINGE: { break; @@ -243,22 +284,26 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) { return run(getChild(tree,0)) / run(getChild(tree,1)); } - + case FW: { // forward + //printf("TESTE"); #ifndef NDEBUG - cout << "PF: " << run(getChild(tree,0)) << endl; + cout << translate("PF: ") << run(getChild(tree,0)) << endl; #endif // run the command int distance = (int)run(getChild(tree,0)); int steps_taken = Donnie->moveForward(distance); // if less steps were taken, then report a bump std::ostringstream distanceStr; - distanceStr << "andou " << steps_taken; + + distanceStr.imbue(loc); + + distanceStr << translate("andou ") << steps_taken; if ((steps_taken < distance) || Donnie->bumped()){ - distanceStr << ", bateu"; + distanceStr << translate(", bateu"); }else{ - distanceStr << ", não bateu"; + distanceStr << translate(", não bateu"); } // save into history string command = string(getText(tree)) + " " + to_string(int(distance)); @@ -269,18 +314,21 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) case BW: { // backward #ifndef NDEBUG - cout << "PT: " << run(getChild(tree,0)) << endl; + cout << translate("PT: ") << run(getChild(tree,0)) << endl; #endif // run the command int distance = (int)run(getChild(tree,0)); int steps_taken = Donnie->moveBackward(distance); // if less steps were taken, then report a bump std::ostringstream distanceStr; - distanceStr << "andou " << steps_taken; + + distanceStr.imbue(loc); + + distanceStr << translate("andou ") << steps_taken; if ((steps_taken < distance) || Donnie->bumped()){ - distanceStr << ", bateu"; + distanceStr << translate(", bateu"); }else{ - distanceStr << ", não bateu"; + distanceStr << translate(", não bateu"); } // save into history string command = string(getText(tree)) + " " + to_string(int(distance)); @@ -292,7 +340,7 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) { // right turn int exp = run(getChild(tree,0)); #ifndef NDEBUG - cout << "PD: " << exp << endl; + cout << translate("PD: ") << exp << endl; #endif // run the command float distance = (float)exp; @@ -301,7 +349,7 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) // TODO: o comando pode ser interrompido por uma colizao. // assim, está errado assumir que a distancia pedida será a distancia percorrida string command = string(getText(tree)) + " " + to_string(int(distance)); - History->addCommand(command,(Donnie->bumped() ? "bateu" : "não bateu")); + History->addCommand(command,(Donnie->bumped() ? crash_str : ncrash_str)); break; } @@ -309,7 +357,7 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) { // left turn int exp = run(getChild(tree,0)); #ifndef NDEBUG - cout << "PE: " << exp << endl; + cout << translate("PE: ") << exp << endl; #endif // run the command float distance = (float)exp; @@ -318,13 +366,14 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) // TODO: o comando pode ser interrompido por uma colizao. // assim, está errado assumir que a distancia pedida será a distancia percorrida string command = string(getText(tree)) + " " + to_string(int(distance)); - History->addCommand(command,(Donnie->bumped() ? "bateu" : "não bateu")); + History->addCommand(command,(Donnie->bumped() ? crash_str : ncrash_str)); break; } case SCAN: { + // get 7 sonar and blob readings by moving the head from 0o to 180o // every 30 degrees Donnie->Scan(); @@ -338,7 +387,7 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) vector tokens; split((char*)getText(tree),' ',tokens); //if (tokens.size() != 2) - //throw sintaxeException("Sintaxe não conhecida para comando '"+tokens[0]+"'\n"); + //throw sintaxeException("Sintaxe não conhecida ild(trepara comando '"+tokens[0]+"'\n"); // get the ranger id if (tokens[1] == RANGER_N) @@ -355,8 +404,8 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) arg = 5; //else if (tokens[1] == RANGER_HEAD) // arg = 6; - //else - //throw sintaxeException("Sintaxe não conhecida para comando '"+tokens[0]+"'\n"); + //else + //throw sintaxeException("Sintaxe não conhecida para comando '"+tokens[0]+"'\n"); range = Donnie->GetRange(arg); #ifndef NDEBUG @@ -372,9 +421,9 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) char* tokens; //tokens = strtok((char*)getText(tree)," "); tokens = strpbrk((char*)getText(tree), "xyaXYA"); //verifica qual é o argumento de POS: x, y, a ou NULL - + //if (tokens.size() != 2) - //throw sintaxeException("Sintaxe não conhecida para comando '"+tokens[0]+"'\n"); + //throw sintaxeException("Sintaxe não conhecida para comando '"+tokens[0]+"'\n"); // get the ranger id if (tokens != NULL){ @@ -386,12 +435,12 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) arg = 2; } else - arg = 3; - - //else - //throw sintaxeException("Sintaxe não conhecida para comando '"+tokens[0]+"'\n"); + arg = 3; - pos = Donnie->GetPos("body",arg); + //else + //throw sintaxeException("Sintaxe não conhecida para comando '"+tokens[0]+"'\n"); + + pos = Donnie->GetPos("body",arg); #ifndef NDEBUG cout << "POS: " << arg << " " << (int)pos << endl; #endif @@ -400,51 +449,80 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) case COLOR: { + int arg; // get 7 sonar and blob readings by moving the head from 0o to 180o // every 30 degrees. report only the blobs with requested color (r,g, or b) - + vector tokens; split((char*)getText(tree),' ',tokens); //if (tokens.size() != 2) - //throw sintaxeException("Sintaxe não conhecida para comando '"+tokens[0]+"'\n"); + //throw sintaxeException("Sintaxe não conhecida para comando '"+tokens[0]+"'\n"); arg = Donnie->color_to_value(tokens[1]); if(arg == 0xFFFFFFFF) - throw sintaxeException("Sintaxe não conhecida para comando '"+tokens[0]+"'\n"); + throw sintaxeException(string(translate("Sintaxe não conhecida para comando '"))+tokens[0]+"'\n"); // only report when there are blobs with the selected color return Donnie->Color(arg); break; } - + case SOUND: { + vector tokens; split((char*)getText(tree),' ',tokens); //if (tokens.size() != 2) - //throw sintaxeException("Sintaxe não conhecida para comando '"+tokens[0]+"'\n"); + //throw sintaxeException("Sintaxe não conhecida para comando '"+tokens[0]+"'\n"); // sound on or off - if (tokens[1] == SOUND_ON){ - Donnie->speak("O som foi ligado com sucesso"); + if ((tokens[1] == "ligado") || (tokens[1] == "on")){ + Donnie->speak(translate("O som foi ligado com sucesso")); Donnie->muteTTS(false); } - else if (tokens[1] == SOUND_OFF){ - Donnie->speak("O som foi desligado com sucesso"); + else if ((tokens[1] == "desligado") || (tokens[1] == "off")){ + Donnie->speak(translate("O som foi desligado com sucesso")); Donnie->muteTTS(true); } - //else - //throw sintaxeException("Sintaxe não conhecida para comando '"+tokens[0]+"'\n"); + // error treatmet is performed at the parser level. it is not necessary to test for error here + //else { + //throw sintaxeException("Sintaxe não conhecida para comando '"+tokens[0]+"'\n"); + //Donnie->speak(translate("Sintaxe não conhecida para comando 'som'")); + //} return 0; break; } - + + case BELT: + { + vector tokens; + split((char*)getText(tree),' ',tokens); + //if (tokens.size() != 2) + //throw sintaxeException("Sintaxe não conhecida para comando '"+tokens[0]+"'\n"); + + // sound on or off + if ((tokens[1] == "ligado") || (tokens[1] == "on")){ + Donnie->speak(translate("O cinto foi ligado com sucesso")); + } + else if ((tokens[1] == "desligado") || (tokens[1] == "off")){ + Donnie->speak(translate("O cinto foi desligado com sucesso")); + } + // error treatmet is performed at the parser level. it is not necessary to test for error here + //else{ + //throw sintaxeException("Sintaxe não conhecida para comando '"+tokens[0]+"'\n"); + //Donnie->speak(translate("Sintaxe não conhecida para comando 'cinto'")); + //} + + return 0; + break; + } + case COMENT: { #ifndef NDEBUG - cout << "COMMENT: " << getText(tree) << endl; + cout << translate("COMMENT: ") << getText(tree) << endl; #endif break; } @@ -466,7 +544,7 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) arg << run(getChild(tree,0)); } #ifndef NDEBUG - cout << "SPEAK: " << arg.str() << endl; + cout << translate("SPEAK: ") << arg.str() << endl; #endif Donnie->speak(arg.str()); break; @@ -477,10 +555,10 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) if(tree->getToken(getChild(tree,0))->type != STRINGE){ int wait = run(getChild(tree,0)); #ifndef NDEBUG - cout << "WAIT: " << wait << endl; - #endif + cout << translate("WAIT: ") << wait << endl; + #endif sleep(wait); - Donnie->speak("esperando " + to_string (wait) + " segundos."); + Donnie->speak(string(translate("esperando ")) + to_string (wait) + string(translate(" segundos."))); } break; } @@ -502,8 +580,8 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) bool ok = compare(a,b,c); // Compara variaveis - while (ok == true) - { + while (ok == true) + { run(getChild(tree,5)); //Executa bloco run(getChild(tree,4)); //Executa operação de incremento ok = compare(run(getChild(tree,1)),run(getChild(tree,3)),c); //Realiza comparação novamente @@ -519,7 +597,7 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) case WHILEE: { #ifndef NDEBUG - cout << "while" << endl; + cout << translate("while") << endl; #endif int a = run(getChild(tree,0)); // Retorna o valor das variáveis na condição int b = run(getChild(tree,2)); // # @@ -527,8 +605,8 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) bool ok = compare(a,b,c); // Compara variaveis - while (ok == true) - { + while (ok == true) + { run(getChild(tree,3)); //Executa bloco ok = compare(run(getChild(tree,0)),run(getChild(tree,2)),c); //Realiza comparação novamente } @@ -585,18 +663,18 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) } break; } - + case MAKE: { - - char* var = (char*)getText(getChild(tree,0)); + + char* var = (char*)getText(getChild(tree,0)); int val; if (tree->getChildCount(tree) < 2) { - val = 0; // Se não for atribuido valor, variável começa com zero + val = 0; // Se não for atribuido valor, variável começa com zero } - else + else val = run(getChild(tree,1)); if(for_itFlag == WAITING) @@ -619,17 +697,17 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) for (int f = 1; f <= procedure.argNum ; f++) local.memory[procedure.args[f-1]] = run(getChild(tree,f)); // Atribui as variaveis de argumento no dicionário - DonnieMemory::getInstance()->stackMemory(local); // Empilha dicionário + DonnieMemory::getInstance()->stackMemory(local); // Empilha dicionário - run(procedure.node); // Executa procedimento + run(procedure.node); // Executa procedimento DonnieMemory::getInstance()->unstackMemory(); // Desempilha dicionário } else { - sayStr << "Número de argumentos invalido."; + sayStr << translate("Número de argumentos invalido."); Donnie->speak(sayStr.str()); - cout << sayStr << endl; + cout << sayStr.str() << endl; } @@ -639,11 +717,11 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) case PROCDEC: { char* name = (char*)getText(getChild(tree,0)); - + int childNum = tree->getChildCount(tree); procDec procedure; - + if(childNum < 3) { procedure.argNum = 0; // Caso procedimento não apresente parametros salva bloco do procedimento @@ -652,8 +730,8 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) else { for(int f = 1; f < childNum - 1; f++) - procedure.args.push_back(getText(getChild(tree,f))); // Caso tenha parametros salva numa lista - + procedure.args.push_back(getText(getChild(tree,f))); // Caso tenha parametros salva numa lista + procedure.argNum = childNum - 2; procedure.node = getChild(tree,childNum - 1); // Salva bloco do procedimento } @@ -661,7 +739,7 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) DonnieMemory::getInstance()->addProc(name, procedure); break; } - + case HIST: { //TODO (amory): implementar um clear para o historico @@ -673,24 +751,27 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) case STATE: { std::ostringstream output; - + + output.imbue(loc); + if (History->size()>0){ output << History->getLast(); }else{ - output << "Nenhum comando executado, posição [" + output << translate("Nenhum comando executado, posição [") << Donnie->GetPos("body",0) << //POSITION_X in steps "," << Donnie->GetPos("body",1) << //POSITION_Y in steps - "," << Donnie->GetPos("body",2) << "]"; //POSITION_YAW in degrees + "," << Donnie->GetPos("body",2) << "]"; //POSITION_YAW in degrees // dont add newline here ! } - cout << output.str() << endl; + + //cout << output.str() << endl; Donnie->speak(output.str()); break; } case SEMICOLON: { - + //int fi = tree->getChildCount(tree); //cout << "COMMENT: " << fi << std::endl; break; @@ -698,7 +779,7 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) case WS: { - + //int fi = tree->getChildCount(tree); //cout << "WS: " << fi << std::endl; break; @@ -706,7 +787,7 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) case COMP: { - + //return getText(tree); break; } @@ -714,7 +795,7 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) case QUIT: { #ifndef NDEBUG - cout << "EXIT" << endl; + cout << translate("EXIT") << endl; #endif //fclose(log); done = 1; @@ -723,17 +804,17 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) case EQ: { - + char* var = (char*)getText(getChild(tree,0)); int val = run(getChild(tree,1)); DonnieMemory::getInstance()->assignVar(var,val); - break; + break; } - + default: //cout << "Unhandled token: #" << tok->type << '\n'; - throw sintaxeException("Sintaxe não conhecida\n"); + throw sintaxeException(translate("Sintaxe não conhecida\n")); break; } } @@ -747,22 +828,22 @@ int ExprTreeEvaluator::run(pANTLR3_BASE_TREE tree) } } -void ExprTreeEvaluator::speak(string text) -{ +void ExprTreeEvaluator::speak(string text) +{ Donnie->speak(text); } -void ExprTreeEvaluator::muteTTS(bool m) +void ExprTreeEvaluator::muteTTS(bool m) { Donnie->muteTTS(m); } pANTLR3_BASE_TREE getChild(pANTLR3_BASE_TREE tree, unsigned i) { - + //assert(i < tree->getChildCount(tree)); //if(!(i < tree->getChildCount(tree))) throw sintaxeException(); - + return (pANTLR3_BASE_TREE) tree->getChild(tree, i); } @@ -799,22 +880,22 @@ bool compare (int a, int b, string comp) } else { - cout << "null comp" << endl; + cout << translate("null comp") << endl; //TODO: (amory) nao era p gerar uma excecao ? return false; - } + } } void split(const std::string &s, char delim, std::vector &elems) { std::stringstream ss; - + std::string item, aux = s; // remove extra spaces aux.erase(std::unique(aux.begin(), aux.end(), - [](char a, char b) { return a == ' ' && b == ' '; } ), aux.end() ); + [](char a, char b) { return a == ' ' && b == ' '; } ), aux.end() ); // tolower - transform(aux.begin(), aux.end(), aux.begin(), ::tolower); + transform(aux.begin(), aux.end(), aux.begin(), ::tolower); ss.str(aux); while (std::getline(ss, item, delim)) { elems.push_back(item); @@ -823,20 +904,20 @@ void split(const std::string &s, char delim, std::vector &elems) { string cleanAccents(string code){ - + //this function does not replace character if it is within double quotes, like in the Speak command // note that acented character uses 2 bytes, thus, extra space is required for each accented character - size_t index = 0, index_aux1 = 0, index_aux2 = 0; + size_t index = 0, index_aux1 = 0, index_aux2 = 0; string aux = code; - - //remove all sentences between double quotes from aux string + + //remove all sentences between double quotes from aux string while ((index_aux1 = aux.find('"', index_aux2)) != string::npos){ if ((index_aux2 = aux.find('"', index_aux1+1)) != string::npos){ - aux.replace(index_aux1, (index_aux2-index_aux1+1), (index_aux2-index_aux1+1), '-'); + aux.replace(index_aux1, (index_aux2-index_aux1+1), (index_aux2-index_aux1+1), '-'); index_aux2++; } } - + int i=0, count_replaces=0; //search in the aux string for the commands with accented characters and replace them for not accented characters in the code string while((index = aux.find_first_of("âãáçóÂÃÁÇÓ", index)) != string::npos){ @@ -857,6 +938,6 @@ string cleanAccents(string code){ index+=2; //accented characters have 2 bytes count_replaces++; } - + return code; } diff --git a/client/godonnie/Compiler.h b/client/godonnie/Compiler.h index 38121fd..3e67dba 100644 --- a/client/godonnie/Compiler.h +++ b/client/godonnie/Compiler.h @@ -41,6 +41,12 @@ using std::string; using std::cout; using std::endl; +// Localization libraries +#include +using namespace boost::locale; +using boost::locale::translate; +using boost::locale::format; + typedef struct { char *name; /* User printable name of the function. */ char *doc; /* Documentation for this function. */ @@ -56,6 +62,9 @@ class ExprTreeEvaluator /// this file pointer is used to log into file the commands executed in terminal mode FILE *log; + + /// when enabled, it generated a Log directory in the current path + bool enable_log; DonnieClient *Donnie; /// pointer to Donnie middleware class Historic *History; /// pointer to History class @@ -76,12 +85,18 @@ class ExprTreeEvaluator /// mute the TTS and just print the sentence on the stdout void muteTTS(bool m); + /// Enable logging when true + void setLog(bool m); + + /// Get the logging status + bool getLog(); + /// parse input stream in GoDonnie syntax /*! build the ANTLR objects (lexer and parser), * build the parse tree and run if no parse errors were found. * In Terminal mode, this also saves input stream into the log file */ - int parseGD(char* textIn, bool enable_log); + int parseGD(char* textIn); }; diff --git a/client/godonnie/DonnieClient.cpp b/client/godonnie/DonnieClient.cpp index 979b058..480b689 100644 --- a/client/godonnie/DonnieClient.cpp +++ b/client/godonnie/DonnieClient.cpp @@ -13,8 +13,7 @@ const double SIDE_RANGER = 0.05; const double FRONT_RANGER = 0.06; const double BACK_RANGER = 0.05; - -#ifndef LANG +#ifndef LANG #define LANG "pt-br" #endif @@ -30,8 +29,8 @@ DonnieClient *DonnieClient::getInstance() void DonnieClient::ResetInstance() { - delete singleton; - singleton = NULL; + delete singleton; + singleton = NULL; } DonnieClient::DonnieClient() @@ -42,22 +41,31 @@ DonnieClient::DonnieClient() if(port==0) port = 6665; muted = false; + // Set up language environment + generator gen; + gen.add_messages_path(string(GetEnv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("DonnieClient"); + locale loc = gen(string(GetEnv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + cout.imbue(loc); + cerr.imbue(loc); + try{ robot = new PlayerClient(host,port); } catch (PlayerError e){ #ifndef NDEBUG cerr << e << endl; #endif - cerr << "Não foi possivel conectar no robô com IP " << host << " porta " << port << endl; - cerr << "Possivelmente o Player não foi executado ou as variaveis DONNIE_IP e DONNIE_PORT estão erradas" << endl; + cerr << translate("Não foi possivel conectar no robô com IP ") << host << translate(" porta ") + << port << endl; + cerr << translate("Possivelmente o Player não foi executado ou as variaveis DONNIE_IP e DONNIE_PORT estão erradas") + << endl; exit(1); } - - try{ - //head = new PlayerClient("localhost",6666); + + try{ p2dProxy = new Position2dProxy(robot,0); p2d_headProxy = new Position2dProxy(robot,1); - //actuator = new ActArrayProxy(robot,0); bpProxy = new BumperProxy(robot,0); bfinderProxy = new BlobfinderProxy(robot,0); sonarProxy = new RangerProxy(robot,0); @@ -67,11 +75,11 @@ DonnieClient::DonnieClient() #ifndef NDEBUG cerr << e << endl; #endif - cerr << "Não foi possível conectar no robô " << endl; - cerr << "Possivelmente o arquivo cfg está incorreto." << endl; + cerr << translate("Não foi possível conectar no robô ") << endl; + cerr << translate("Possivelmente o arquivo cfg está incorreto.") << endl; exit(1); } - + robot->StartThread(); } @@ -80,7 +88,7 @@ DonnieClient::~DonnieClient() { } - + int DonnieClient::FrontBumper() { robot->ReadIfWaiting(); @@ -123,9 +131,9 @@ string DonnieClient::value_to_color(int color_value) string donnie_path = GetEnv("DONNIE_PATH"); // read the color file according to the language - if(LANG == "pt-br") + if(strcmp(getenv("DONNIE_LANG"),"pt_BR") == 0) donnie_path = donnie_path + "/resources/color_files/rgb-pt-br.txt"; - else if (LANG == "eng") + else if (strcmp(getenv("DONNIE_LANG"),"en_US") == 0) donnie_path = donnie_path + "/resources/color_files/rgb-en.txt"; else donnie_path = donnie_path + "/resources/color_files/rgb-pt-br.txt"; @@ -142,16 +150,16 @@ string DonnieClient::value_to_color(int color_value) { stringstream str_buff; - str_buff << std::hex << color; //get hex value and convert to string.. - str_buff >> file_value; //then put on an unsigned int + str_buff << std::hex << color; //get hex value and convert to string.. + str_buff >> file_value; //then put on an unsigned int getline(file,color, '\n'); - - if(file_value == color_value || file_value == 0xFFFFFFFF) + + if(file_value == color_value || file_value == 0xFFFFFFFF) { return color; } //smaller = color_value - file_value; - //if(smaller_buff < smaller) + //if(smaller_buff < smaller) //{ // return color_buff; //} @@ -161,10 +169,10 @@ string DonnieClient::value_to_color(int color_value) file.close(); } else{ - cout << "Erro: arquivo de cores " << donnie_path << " não encontrado" << endl; + cout << translate("Erro: arquivo de cores ") << donnie_path << translate(" não encontrado") << endl; exit(1); } - + return color; } @@ -175,6 +183,15 @@ int DonnieClient::color_to_value(string input_color) ostringstream oss; unsigned int file_value; + // Set up language environment + generator gen; + gen.add_messages_path(string(GetEnv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("DonnieClient"); + locale loc = gen(string(GetEnv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + cout.imbue(loc); + cerr.imbue(loc); + string donnie_path = GetEnv("DONNIE_PATH"); // read the color file according to the language @@ -193,7 +210,7 @@ int DonnieClient::color_to_value(string input_color) { stringstream str_buff; - str_buff << std::hex << color; //convert + str_buff << std::hex << color; //convert str_buff >> file_value; getline(file,color, '\n'); @@ -204,13 +221,13 @@ int DonnieClient::color_to_value(string input_color) file.close(); } else{ - cout << "Erro: arquivo de cores " << donnie_path << " não encontrado" << endl; + cout << translate("Erro: arquivo de cores ") << donnie_path << translate(" não encontrado") << endl; exit(1); } // return unknown color return 0xFFFFFFFF; - + } @@ -226,7 +243,7 @@ float DonnieClient::GetRange(int arg) case 1: //tras - S return sonarProxy->GetRange(4)/STEP_LENGHT; - case 2: //frente-esquerda - NW + case 2: //frente-esquerda - NW return sonarProxy->GetRange(2)/STEP_LENGHT; case 3: //frente-direita - NE @@ -241,7 +258,7 @@ float DonnieClient::GetRange(int arg) case 6: //cabeca - head //return sonarProxy->GetRange(6)/STEP_LENGHT; return headSonarProxy->GetRange(0)/STEP_LENGHT; -*/ +*/ default: // invalid ostringstream buf; buf << "Range id "<< arg << "invalid" << endl; @@ -268,6 +285,14 @@ float DonnieClient::GetPos(Position2dProxy *p2d, int arg) robot->ReadIfWaiting(); std::ostringstream sayStr; + // Set up language environment + generator gen; + gen.add_messages_path(string(GetEnv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("DonnieClient"); + locale loc = gen(string(GetEnv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + sayStr.imbue(loc); + switch(arg) { case 0: @@ -277,7 +302,7 @@ float DonnieClient::GetPos(Position2dProxy *p2d, int arg) case 2: return radTOdeg(p2d->GetYaw()); case 3: - sayStr << "Estou no x " << (int)(p2d->GetXPos()/STEP_LENGHT) << ", no y " << (int)(p2d->GetYPos()/STEP_LENGHT) << " e virado para " << (int)(radTOdeg(p2d->GetYaw())) << " graus."; + sayStr << string(translate("Estou no x ")) << (int)(p2d->GetXPos()/STEP_LENGHT) << string(translate(", no y ")) << (int)(p2d->GetYPos()/STEP_LENGHT) << string(translate(" e virado para ")) << (int)(radTOdeg(p2d->GetYaw())) << string(translate(" graus.")); speak(sayStr.str()); return 0; default: @@ -310,6 +335,13 @@ int DonnieClient::moveForward(int arg) double targetHypot = STEP_LENGHT*Npassos; + // Set up language environment + generator gen; + gen.add_messages_path(string(GetEnv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("DonnieClient"); + locale loc = gen(string(GetEnv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + //validate step number if(Npassos != 0){ //initial collision prevent - check if not are nearby obstacle to start movement @@ -361,18 +393,20 @@ int DonnieClient::moveForward(int arg) // say command std::ostringstream sayStr; - sayStr << "Andei " << ((collision||obstacle)?"somente ":"") << int(passos) << " passos para frente."; + sayStr.imbue(loc); + string aux1 = string(translate("somente ")); + sayStr << string(translate("Andei ")) << ((collision||obstacle)?aux1:"") << int(passos) << string(translate(" passos para frente.")); if (collision) - sayStr << "Houve colisão;"; //colisao frontal + sayStr << string(translate("Houve colisão;")); //colisao frontal if (obstacle) - sayStr << "Encontrei obstáculo."; + sayStr << string(translate("Encontrei obstáculo.")); speak(sayStr.str()); - cout << sayStr.str() << endl; + //cout << sayStr.str() << endl; /*#ifndef NDEBUG cout << "obstaculo: " << obstacle << endl; #endif*/ - + // number of steps actually taken return passos; } @@ -392,6 +426,13 @@ int DonnieClient::moveBackward(int arg) double targetHypot = STEP_LENGHT*Npassos; + // Set up language environment + generator gen; + gen.add_messages_path(string(GetEnv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("DonnieClient"); + locale loc = gen(string(GetEnv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + //validate step number if(Npassos != 0){ //initial collision prevent - check if not are nearby obstacle to start movement @@ -400,7 +441,7 @@ int DonnieClient::moveBackward(int arg) p2dProxy->SetSpeed(-0.05,0); else obstacle = true; - // hypotf(p2dProxy->GetXPos() - posxi, p2dProxy->GetYPos() - posyi) <= targetHypot + // hypotf(p2dProxy->GetXPos() - posxi, p2dProxy->GetYPos() - posyi) <= targetHypot while(passos < Npassos && collision==false && obstacle==false) { //#ifndef NDEBUG @@ -443,18 +484,20 @@ int DonnieClient::moveBackward(int arg) // say command std::ostringstream sayStr; - sayStr << "Andei " << ((collision||obstacle)?"somente ":"") << int(passos) << " passos para trás."; + sayStr.imbue(loc); + string aux1 = string(translate("somente ")); + sayStr << string(translate("Andei ")) << ((collision||obstacle)?aux1:"") << int(passos) << string(translate(" passos para trás.")); if (collision) - sayStr << "Houve colisão;"; //colisao frontal + sayStr << string(translate("Houve colisão;")); //colisao frontal if (obstacle) - sayStr << "Encontrei obstáculo."; + sayStr << string(translate("Encontrei obstáculo.")); speak(sayStr.str()); - cout << sayStr.str() << endl; + //cout << sayStr.str() << endl; /*#ifndef NDEBUG cout << "obstaculo: " << obstacle << endl; #endif*/ - + // number of steps actually taken return passos; } @@ -464,36 +507,53 @@ int DonnieClient::GotoTTS(float pa){ // call recursive Goto and return the actual move //float actual_move = Goto(pa); Goto(pa); - + //make sure that robot are stopped while speech + p2dProxy->SetSpeed(0,0); + + // Set up language environment + generator gen; + gen.add_messages_path(string(GetEnv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("DonnieClient"); + locale loc = gen(string(GetEnv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + string direction; if (pa < 0){ - direction = "direita"; + direction = string(translate("direita")); pa = -pa; }else - direction = "esquerda"; + direction = string(translate("esquerda")); // say command // TODO: o comando pode ser interrompido por uma colizao. // assim, está errado assumir que a distancia pedida será a distancia percorrida std::ostringstream sayStr; - sayStr << "Girei " << int(pa) << " graus para " << direction << "."; + sayStr.imbue(loc); + sayStr << string(translate("Girei ")) << int(pa) << string(translate(" graus para ")) << direction << "."; if (bumped()) - sayStr << " Houve colisão."; + sayStr << string(translate(" Houve colisão.")); speak(sayStr.str()); - return 0; + return 0; } int DonnieClient::Goto(float pa){ //faz com que o goto funcione girando para o lado correto - DEBUG_MSG("ROTACAO:" << pa); + + generator gen; + gen.add_messages_path(string(GetEnv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("DonnieClient"); + locale loc = gen(string(GetEnv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + + DEBUG_MSG(string(translate("ROTACAO:")) << pa); if(pa>0 && pa>170){ - DEBUG_MSG("PARCIAL"); + DEBUG_MSG(string(translate("PARCIAL"))); if(Goto(170)) return 1; //se qualquer batida ou erro acontecer retorna imediatamente if(Goto(pa-170)) return 1; //se qualquer batida ou erro acontecer retorna imediatamente return 0; } - if(pa<0 && pa<-170){ - DEBUG_MSG("PARCIAL"); + if(pa<0 && pa<-170){ + DEBUG_MSG(string(translate("PARCIAL"))); if(Goto(-170)) return 1; //se qualquer batida ou erro acontecer retorna imediatamente if(Goto(pa+170)) return 1; //se qualquer batida ou erro acontecer retorna imediatamente return 0; @@ -508,8 +568,8 @@ int DonnieClient::Goto(float pa){ p2dProxy->GoTo(p2dProxy->GetXPos(),p2dProxy->GetYPos(),paTarget); //soma o angulo desejado com o angulo inicial do robo //DEBUG_MSG(" "<< "TH POS:" << p2dProxy->GetYaw()); //DEBUG_MSG(" "<< "TARGET:" << (paTarget)<GetYaw()<=(paTarget)-errorOffset || - p2dProxy->GetYaw()>=(paTarget)+errorOffset); + }while (p2dProxy->GetYaw()<=(paTarget)-errorOffset || + p2dProxy->GetYaw()>=(paTarget)+errorOffset); p2dProxy->SetSpeed(0,0); return 0; } @@ -524,27 +584,32 @@ int DonnieClient::headGoto(float pa){ p2d_headProxy->GoTo(p2dProxy->GetXPos(),p2dProxy->GetYPos(), paTarget+p2dProxy->GetYaw()); //soma a posicao desejada da cabeca em relacao a base //DEBUG_MSG(" "<< "TH POS:" << p2d_headProxy->GetYaw()); //DEBUG_MSG(" "<< "TARGET:" << (paTarget+p2dProxy->GetYaw())-errorOffsetYaw<GetYaw()<=(paTarget+p2dProxy->GetYaw())-errorOffsetYaw || + }while (p2d_headProxy->GetYaw()<=(paTarget+p2dProxy->GetYaw())-errorOffsetYaw || p2d_headProxy->GetYaw()>=(paTarget+p2dProxy->GetYaw())+errorOffsetYaw); //0.5 is the parameter to validate the speed more fast p2d_headProxy->SetSpeed(0,0); return 0; } void DonnieClient::Scan(void){ + float head_yawi = -90; //in degree. +90 due the servo default pos is 90 degre //GOTO -90 to 90 in 30 by 30 steps float sonar_readings[7]; int blobs_found[7]; int yaw_cnt=0; - int blobs_counter_buffer; + int blobs_counter_buffer; std::ostringstream scanText; string color_str; - - + // Set up language environment + generator gen; + gen.add_messages_path(string(GetEnv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("DonnieClient"); + locale loc = gen(string(GetEnv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); bool blob_flag = false; - int camera_width = bfinderProxy->GetWidth() - 1; + int camera_width = bfinderProxy->GetWidth() - 1; int nro_blobs = 0; int nro_blobs_buffer = 0; @@ -562,21 +627,21 @@ void DonnieClient::Scan(void){ //playerc_blobfinder_blob_t teste; - speak("Espiando"); + speak(string(translate("Espiando"))); do{ // move headd headGoto(head_yawi); robot->ReadIfWaiting(); sleep(1); - // read sonar - headSonarProxy->GetRange(0)/100; ///STEP_LENGHT; // read head sonar - sonar_readings[yaw_cnt] = headSonarProxy->GetRange(0)/STEP_LENGHT; // read head sonar + headSonarProxy->GetRange(0)/100; ///STEP_LENGHT; // read head sonar + + sonar_readings[yaw_cnt] = headSonarProxy->GetRange(0)/STEP_LENGHT; // read head sonar blobs_found[yaw_cnt] = bfinderProxy->GetCount(); // get the number of blobs found blobs_counter_buffer = blobs_found[yaw_cnt]; - + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -590,26 +655,20 @@ void DonnieClient::Scan(void){ total_blobs_found[total_counter] = blob_buffer; total_yaws[total_counter] = yaw_buffer; total_counter++; - //nro_blobs++; + //nro_blobs++; blob_flag = false; - //cout<GetBlob(b).color; - //cout<<"numero de blobs "<GetBlob(b).right != (camera_width) && bfinderProxy->GetBlob(b).left==0) /// inacabado na ESQUERDA. + if(bfinderProxy->GetBlob(b).right != (camera_width) && bfinderProxy->GetBlob(b).left==0) /// inacabado na ESQUERDA. { - if (blob_flag ==true) + if (blob_flag ==true) { if(blob_buffer.color !=buffer_color) // blobs with same colors! Para evitar que pegue a mesma blob 2x. Pode ocorrer outros erros. { @@ -617,29 +676,16 @@ void DonnieClient::Scan(void){ total_blobs_found[total_counter] = blob_buffer; total_yaws[total_counter] = yaw_buffer; total_counter++; - //cout<GetBlob(b); - - //mod aqui yaw_buffer = head_yawi; - //yaw_buffer = graus; } - + } else { - //blob_buffer = bfinderProxy->GetBlob(b); - //modificado aqui - //yaw_buffer = graus; //cout<<"blob adicionado! 2x (right e cor diferente)"<GetBlob(b).right == (camera_width) && bfinderProxy->GetBlob(b).left !=0) //inacabado na DIREITA. { if (blob_flag ==true) @@ -648,13 +694,9 @@ void DonnieClient::Scan(void){ { total_blobs_found[total_counter] = blob_buffer; //mod aqui - //total_yaws[total_counter] = (graus+yaw_buffer)/2; total_yaws[total_counter] = (head_yawi+yaw_buffer)/2; total_counter++; blob_flag = false; - //cout<GetBlob(b); - } else // blobs with different colors! { @@ -669,8 +711,6 @@ void DonnieClient::Scan(void){ total_yaws[total_counter] = head_yawi;//graus; total_counter++; blob_flag = false; - // cout<GetBlob(b); } } else @@ -680,23 +720,18 @@ void DonnieClient::Scan(void){ total_blobs_found[total_counter] = bfinderProxy->GetBlob(b); //mod aqui total_yaws[total_counter] = head_yawi;//graus; - //cout<<"do buffer! "<GetBlob(b); } } } - else if(bfinderProxy->GetBlob(b).right == (camera_width) && bfinderProxy->GetBlob(b).left==0) // inacabado nas DUAS pontas. + else if(bfinderProxy->GetBlob(b).right == (camera_width) && bfinderProxy->GetBlob(b).left==0) // inacabado nas DUAS pontas. { if (blob_flag ==true) { if(blob_buffer.color == bfinderProxy->GetBlob(b).color) { blob_buffer = bfinderProxy->GetBlob(b); - //cout<<"ueahieauhea"<GetBlob(b); //mod aqui - yaw_buffer = head_yawi;//graus; + yaw_buffer = head_yawi;//graus; } } else { - - //blob_buffer = bfinderProxy->GetBlob(b); - //mod aqui yaw_buffer = head_yawi;//graus; - // nro_blobs--; - blob_flag = true; - + blob_flag = true; } } else // ok, tudo certo :} { - if (blob_flag ==true) + if (blob_flag ==true) { if(blob_buffer.color == buffer_color) @@ -737,9 +763,6 @@ void DonnieClient::Scan(void){ total_yaws[total_counter] = head_yawi;//graus; total_counter++; blob_flag = false; - //cout<GetBlob(b); - } else { @@ -747,19 +770,14 @@ void DonnieClient::Scan(void){ total_blobs_found[total_counter] = blob_buffer; total_yaws[total_counter] = yaw_buffer; total_counter++; - //nro_blobs++; blob_flag = false; - - //cout<GetBlob(b); - //then buffers the current blob. total_blobs_found[total_counter] = blob_buffer; //mod aqui total_yaws[total_counter] = head_yawi;//graus; total_counter++; } - + } else { @@ -767,15 +785,10 @@ void DonnieClient::Scan(void){ //mod aqui total_yaws[total_counter] = head_yawi;// graus; total_counter++; - //cout<GetBlob(b); } } - //cout<<"!!!!!!!!!!!!!!blob buffered:" << bfinderProxy->GetBlob(b).color<GetBlob(b); - //teste = blob_buffer; - //cout<<"!!!!!!!!!!!!!!blob buffered:" << blob_buffer.color<ReadIfWaiting(); - + robot->ReadIfWaiting(); + scanText.imbue(loc); for(int i=0; iGetWidth() - 1; + int camera_width = bfinderProxy->GetWidth() - 1; int nro_blobs = 0; int nro_blobs_buffer = 0; @@ -920,10 +895,8 @@ int DonnieClient::Color(int color_code){ int total_counter=0; int graus = 0; - //playerc_blobfinder_blob_t teste; - - speak("Espiando"); + speak(string(translate("Espiando"))); do{ // move headd headGoto(head_yawi); @@ -931,72 +904,46 @@ int DonnieClient::Color(int color_code){ sleep(1); // read sonar - headSonarProxy->GetRange(0)/100; ///STEP_LENGHT; // read head sonar - sonar_readings[yaw_cnt] = headSonarProxy->GetRange(0)/STEP_LENGHT; // read head sonar - //blobs_found[yaw_cnt] = bfinderProxy->GetCount(); // get the number of blobs found - //blobs_counter_buffer = blobs_found[yaw_cnt]; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + headSonarProxy->GetRange(0)/100; ///STEP_LENGHT; // read head sonar + sonar_readings[yaw_cnt] = headSonarProxy->GetRange(0)/STEP_LENGHT; // read head sonar nro_blobs_buffer = bfinderProxy->GetCount(); if(nro_blobs_buffer == 0 ) // caso nao tenha blobs, ainda tem que analisar pra ver se tem algum incompleto. { if (blob_flag ==true) { - if(color_str ==value_to_color(blob_buffer.color)) - { total_blobs_found[total_counter] = blob_buffer; total_yaws[total_counter] = yaw_buffer; total_counter++; - nro_blobs++; blob_flag = false; - //cout<GetBlob(b).color; - //cout<<"numero de blobs "<GetBlob(b).right != (camera_width) && bfinderProxy->GetBlob(b).left==0) /// inacabado na ESQUERDA. + + if(bfinderProxy->GetBlob(b).right != (camera_width) && bfinderProxy->GetBlob(b).left==0) /// inacabado na ESQUERDA. { - if (blob_flag ==true) + if (blob_flag ==true) { if(blob_buffer.color !=buffer_color) // blobs with same colors! Para evitar que pegue a mesma blob 2x. Pode ocorrer outros erros. { - //add the buffered blob. total_blobs_found[total_counter] = blob_buffer; total_yaws[total_counter] = yaw_buffer; total_counter++; - //cout<GetBlob(b); yaw_buffer = graus; } - + } else { - //blob_buffer = bfinderProxy->GetBlob(b); - yaw_buffer = graus; //cout<<"blob adicionado! 2x (right e cor diferente)"<GetBlob(b).right == (camera_width) && bfinderProxy->GetBlob(b).left !=0) //inacabado na DIREITA. { if (blob_flag ==true) @@ -1007,9 +954,6 @@ int DonnieClient::Color(int color_code){ total_yaws[total_counter] = (graus+yaw_buffer)/2; total_counter++; blob_flag = false; - //cout<GetBlob(b); - } else // blobs with different colors! { @@ -1023,8 +967,6 @@ int DonnieClient::Color(int color_code){ total_yaws[total_counter] = graus; total_counter++; blob_flag = false; - // cout<GetBlob(b); } } else @@ -1033,23 +975,17 @@ int DonnieClient::Color(int color_code){ { total_blobs_found[total_counter] = bfinderProxy->GetBlob(b); total_yaws[total_counter] = graus; - //cout<<"do buffer! "<GetBlob(b); } - } } - else if(bfinderProxy->GetBlob(b).right == (camera_width) && bfinderProxy->GetBlob(b).left==0) // inacabado nas DUAS pontas. + else if(bfinderProxy->GetBlob(b).right == (camera_width) && bfinderProxy->GetBlob(b).left==0) // inacabado nas DUAS pontas. { if (blob_flag ==true) { if(blob_buffer.color == bfinderProxy->GetBlob(b).color) { blob_buffer = bfinderProxy->GetBlob(b); - //cout<<"ueahieauhea"<GetBlob(b); - yaw_buffer = graus; + yaw_buffer = graus; } } else { - - //blob_buffer = bfinderProxy->GetBlob(b); yaw_buffer = graus; - // nro_blobs--; - blob_flag = true; - + blob_flag = true; } } else // ok, tudo certo :} { - if (blob_flag ==true) + if (blob_flag ==true) { if(blob_buffer.color == buffer_color) @@ -1087,9 +1015,6 @@ int DonnieClient::Color(int color_code){ total_yaws[total_counter] = graus; total_counter++; blob_flag = false; - //cout<GetBlob(b); - } else { @@ -1097,55 +1022,40 @@ int DonnieClient::Color(int color_code){ total_blobs_found[total_counter] = blob_buffer; total_yaws[total_counter] = yaw_buffer; total_counter++; - //nro_blobs++; - blob_flag = false; - - //cout<GetBlob(b); - //then buffers the current blob. + blob_flag = false; total_blobs_found[total_counter] = blob_buffer; total_yaws[total_counter] = graus; total_counter++; } - + } else { total_blobs_found[total_counter] = bfinderProxy->GetBlob(b); total_yaws[total_counter] = graus; total_counter++; - //cout<GetBlob(b); } } - } - - - //cout<<"!!!!!!!!!!!!!!blob buffered:" << bfinderProxy->GetBlob(b).color<GetBlob(b); - //teste = blob_buffer; - //cout<<"!!!!!!!!!!!!!!blob buffered:" << blob_buffer.color<ReadIfWaiting(); - + robot->ReadIfWaiting(); + scanText.imbue(loc); if (nro_blobs == 0) { - scanText << "nenhum objeto encontrado com a cor " << color_str; + scanText << string(translate("nenhum objeto encontrado com a cor ")) << color_str; }else if (nro_blobs == 1) { - scanText << "1 objeto encontrado com a cor " << color_str; - }else + scanText << string(translate("1 objeto encontrado com a cor ")) << color_str; + }else { - scanText << nro_blobs << " objetos encontrados com a cor " << color_str; + scanText << nro_blobs << string(translate(" objetos encontrados com a cor ")) << color_str; } speak(scanText.str()); @@ -1180,7 +1090,7 @@ int DonnieClient::Color(int color_code){ scanText.clear(); - + return nro_blobs; } @@ -1200,7 +1110,7 @@ void DonnieClient::speak(string text) speechProxy->Say(text.c_str()); //wait to complete speech (9 chars/seg) sleep(text.length()/9.0); - } + } } void DonnieClient::muteTTS(bool m) diff --git a/client/godonnie/DonnieClient.h b/client/godonnie/DonnieClient.h index 0eb39e7..d67c32d 100644 --- a/client/godonnie/DonnieClient.h +++ b/client/godonnie/DonnieClient.h @@ -27,6 +27,12 @@ using namespace std; //namespace for use with the player library using namespace PlayerCc; +// Localization libraries +#include +using namespace boost::locale; +using boost::locale::translate; +using boost::locale::format; + struct PathNodes { double posx, posy; diff --git a/client/godonnie/DonnieMemory.cpp b/client/godonnie/DonnieMemory.cpp index 2bbd5f4..5533da1 100644 --- a/client/godonnie/DonnieMemory.cpp +++ b/client/godonnie/DonnieMemory.cpp @@ -1,6 +1,7 @@ #include "DonnieMemory.h" #include "utils.h" #include +#include using namespace std; @@ -41,10 +42,19 @@ int DonnieMemory::addVar(string name, int value) { std::ostringstream sayStr; string var = toLowerCase(name); + + generator gen; + gen.add_messages_path(string(getenv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("DonnieMemory"); + locale loc = gen(string(getenv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + cout.imbue(loc); + sayStr.imbue(loc); + //cout << "variavel " << var << endl; if(Memory.top().memory.find(var) != Memory.top().memory.end()) { - sayStr << "Variável \"" << name << "\" já existe."; + sayStr << translate("Variável \"") << name << translate("\" já existe."); Donnie->speak(sayStr.str()); cout << sayStr.str() << endl; return EXIST; @@ -68,6 +78,15 @@ int DonnieMemory::assignVar(string name, int value) { std::ostringstream sayStr; string var = toLowerCase(name); + + generator gen; + gen.add_messages_path(string(getenv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("DonnieMemory"); + locale loc = gen(string(getenv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + cout.imbue(loc); + sayStr.imbue(loc); + //cout << "variavel " << var << endl; if(Memory.top().memory.find(var) != Memory.top().memory.end()) { @@ -76,7 +95,7 @@ int DonnieMemory::assignVar(string name, int value) } else { - sayStr << "Variável \"" << name << "\" não existe."; + sayStr << translate("Variável \"") << name << translate("\" não existe."); Donnie->speak(sayStr.str()); cout << sayStr.str() << endl; } @@ -87,6 +106,15 @@ int DonnieMemory::getVar(string name) { std::ostringstream sayStr; string var = toLowerCase(name); + + generator gen; + gen.add_messages_path(string(getenv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("DonnieMemory"); + locale loc = gen(string(getenv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + cout.imbue(loc); + sayStr.imbue(loc); + //cout << "variavel " << var << endl; if(Memory.top().memory.find(var) != Memory.top().memory.end()) { @@ -94,7 +122,7 @@ int DonnieMemory::getVar(string name) } else { - sayStr << "Variável \"" << name << "\" não existe."; + sayStr << translate("Variável \"") << name << translate("\" não existe."); Donnie->speak(sayStr.str()); cout << sayStr.str() << endl; } @@ -115,10 +143,19 @@ int DonnieMemory::addForVar(string name, int value) { std::ostringstream sayStr; string var = toLowerCase(name); + + generator gen; + gen.add_messages_path(string(getenv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("DonnieMemory"); + locale loc = gen(string(getenv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + cout.imbue(loc); + sayStr.imbue(loc); + //cout << "variavel " << var << endl; if(Memory.top().memory.find(var) != Memory.top().memory.end()) { - sayStr << "Variável PARA \"" << name << "\" já existe."; + sayStr << translate("Variável PARA \"") << name << translate("\" já existe."); Donnie->speak(sayStr.str()); cout << sayStr.str() << endl; } @@ -143,9 +180,18 @@ void DonnieMemory::addProc(string name, procDec procedure) { std::ostringstream sayStr; string var = toLowerCase(name); + + generator gen; + gen.add_messages_path(string(getenv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("DonnieMemory"); + locale loc = gen(string(getenv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + cout.imbue(loc); + sayStr.imbue(loc); + if(proc.find(var) != proc.end()) { - sayStr << "Procedimento \"" << name << "\" já foi declarado."; + sayStr << translate("Procedimento \"") << name << translate("\" já foi declarado."); Donnie->speak(sayStr.str()); cout << sayStr.str() << endl; } @@ -157,13 +203,22 @@ procDec DonnieMemory::getProc(string name) { std::ostringstream sayStr; string var = toLowerCase(name); + + generator gen; + gen.add_messages_path(string(getenv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("DonnieMemory"); + locale loc = gen(string(getenv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + cout.imbue(loc); + sayStr.imbue(loc); + if(proc.find(var) != proc.end()) { return proc[var]; } else { - sayStr << "Procedimento \"" << name << "\" não existe."; + sayStr << translate("Procedimento \"") << name << translate("\" não existe."); Donnie->speak(sayStr.str()); cout << sayStr.str() << endl; } diff --git a/client/godonnie/Exception.cpp b/client/godonnie/Exception.cpp index 3963169..2605b7a 100644 --- a/client/godonnie/Exception.cpp +++ b/client/godonnie/Exception.cpp @@ -1,3 +1,4 @@ +#include #include #include #include "Exception.h" @@ -10,7 +11,12 @@ parametroException::parametroException(string error) } parametroException::parametroException() { - this->m_msg = "Parametro inválido\n"; + generator gen; + gen.add_messages_path(string(getenv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("Exception"); + locale loc = gen(string(getenv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + this->m_msg = translate("Parametro inválido\n"); } const char* parametroException::what() const throw() { @@ -24,7 +30,12 @@ sintaxeException::sintaxeException(string error) } sintaxeException::sintaxeException() { - this->m_msg = "Erro de Sintaxe\n"; + generator gen; + gen.add_messages_path(string(getenv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("Exception"); + locale loc = gen(string(getenv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + this->m_msg = translate("Erro de Sintaxe\n"); } const char* sintaxeException::what() const throw() { @@ -38,7 +49,12 @@ variavelException::variavelException(string error) } variavelException::variavelException() { - this->m_msg = "Erro Variável Inexistente\n"; + generator gen; + gen.add_messages_path(string(getenv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("Exception"); + locale loc = gen(string(getenv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + this->m_msg = translate("Erro Variável Inexistente\n"); } const char* variavelException::what() const throw() { @@ -51,7 +67,12 @@ invalidValueException::invalidValueException(string error) } invalidValueException::invalidValueException() { - this->m_msg = "Valor Invalido para o Parametro\n"; + generator gen; + gen.add_messages_path(string(getenv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("Exception"); + locale loc = gen(string(getenv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + this->m_msg = translate("Valor Invalido para o Parametro\n"); } const char* invalidValueException::what() const throw() { diff --git a/client/godonnie/Exception.h b/client/godonnie/Exception.h index d767b60..f1edd50 100644 --- a/client/godonnie/Exception.h +++ b/client/godonnie/Exception.h @@ -19,6 +19,12 @@ using namespace std; +// Localization libraries +#include +using namespace boost::locale; +using boost::locale::translate; +using boost::locale::format; + //TODO (amory). mudar nome das classes para ingles class parametroException: public exception { diff --git a/client/godonnie/GoDonnie.cpp b/client/godonnie/GoDonnie.cpp index 21ea48e..42b454c 100644 --- a/client/godonnie/GoDonnie.cpp +++ b/client/godonnie/GoDonnie.cpp @@ -16,13 +16,20 @@ #include "Compiler.h" +// Localization libraries +#include +using namespace boost::locale; +using boost::locale::translate; +using boost::locale::format; + //extern HIST_ENTRY **history_list (); using namespace std; #define LANG "pt-br" -COMMAND commands[] = { +// Comandos em pt_BR +COMMAND comandos[] = { { (char*)"pf ", (char*)"Movimenta para frente" }, { (char*)"pt ", (char*)"Movimenta para trás" }, { (char*)"gd ", (char*)"Gira para direita" }, @@ -42,21 +49,69 @@ COMMAND commands[] = { { (char*)"sair", (char*)"Fechar interpretador" }, { (char*)"som", (char*)"Liga ou desliga o som" }, { (char*)"histórico", (char*)"Histórico de comandos de movimento" }, + { (char*)"cinto", (char*)"Liga ou desliga o cinto" }, + { (char *)NULL, (char *)NULL } +}; + +// Comandos em en_US +COMMAND commands[] = { + { (char*)"fw ", (char*)"Forward movement" }, + { (char*)"bw ", (char*)"Backward movement" }, + { (char*)"tr ", (char*)"Turn right" }, + { (char*)"tl ", (char*)"Turn left" }, + { (char*)"distance", (char*)"Distance sensor" }, + { (char*)"scan", (char*)"Scan for objects" }, + { (char*)"color", (char*)"Searches for a color" }, + { (char*)"position ", (char*)"Robot position" }, + { (char*)"state", (char*)"Current state of the robot" }, + { (char*)"var ", (char*)"Create variable" }, + { (char*)"for ", (char*)"For loop" }, + { (char*)"repeat ", (char*)"Repeat loop" }, + { (char*)"while ", (char*)"While laço" }, + { (char*)"if ", (char*)"Conditional" }, + { (char*)"procedure ", (char*)"Create procedure" }, + { (char*)"speak ", (char*)"Speak" }, + { (char*)"quit", (char*)"Close the interpreter" }, + { (char*)"sound", (char*)"Turns the sound on and off" }, + { (char*)"history", (char*)"Movement command history" }, + { (char*)"belt", (char*)"Turns the belt on and off" }, { (char *)NULL, (char *)NULL } }; string code = ""; bool done = 0; -ExprTreeEvaluator Client; +ExprTreeEvaluator Compiler; +FILE *logFile=NULL; // file handle for the log file void initialize_readline (); char ** fileman_completion (const char *text, int start, int end); char * command_generator (const char *text, int state); void usage(char *exec); int evalCode(int count, int key); +void setupLog(); int main(int argc, char* argv[]) { + string donnie_path = GetEnv("DONNIE_PATH"); + string donnie_lang = GetEnv("DONNIE_LANG"); + + if (donnie_path=="") { + cerr << translate("variable DONNIE_PATH not defined. Please execute 'export DONNIE_PATH='") << endl; + exit(1); + } + if (donnie_lang=="") { + cerr << translate("variable DONNIE_LANG not defined. Please execute 'export DONNIE_LANG=$LANGUAGE'") << endl; + exit(1); + } + + // Set up language environment + generator gen; + gen.add_messages_path(donnie_path + "/resources/loc"); + gen.add_messages_domain("GoDonnie"); + locale loc = gen(donnie_lang + ".UTF-8"); + locale::global(loc); + cout.imbue(loc); + cerr.imbue(loc); bool termMode = 0, scriptMode=0; string filename ; @@ -65,68 +120,91 @@ int main(int argc, char* argv[]) extern int optind; if ( argc <= 1 ) { // there is NO input... - //Client.speak("No argument provided!"); - Client.speak("Comando sem argumentos!"); + //Compiler.speak("No argument provided!"); + Compiler.speak(string(translate("Comando sem argumentos!"))); usage(argv[0]); return 1; } - while ((c = getopt (argc, argv, "mthf:")) != -1){ + // the arguments are case insensitive + while ((c = getopt (argc, argv, "mMlLtThHfF:")) != -1){ switch (c){ + case 'T': case 't': // terminal mode termMode = 1; + /* if ( argc !=2 ) { // check extra useless argumets in terminal mode - //cerr << "Terminal mode requires only one argument" << endl; - Client.speak("Modo terminal requer somente um argumento."); + Compiler.speak(string(translate("Modo terminal requer somente um argumento."))); usage(argv[0]); return 1; } + */ break; + case 'F': case 'f': // script file mode filename = optarg; scriptMode=1; + /* if ( argc !=3 ) { // check extra useless argumets in script mode - //cerr << "Script mode requires only two arguments" << endl; - Client.speak("Modo script requer somente dois argumentos."); + Compiler.speak(string(translate("Modo script requer somente dois argumentos."))); usage(argv[0]); return 1; } + */ // test if file exists if( access( optarg, F_OK ) == -1 ) { - //cerr << "File " << filename << " not found!" << endl; - Client.speak("Arquivo " + string(filename) + " não encontrado."); + Compiler.speak(string(translate("Arquivo ")) + string(filename) + string(translate(" não encontrado."))); return 1; } break; + case 'M': case 'm': // mute //if mute ('m') is on, do it first, before any other command if (argcnt == 0){ - Client.muteTTS(true); + Compiler.muteTTS(true); + break; + }else{ + Compiler.speak(string(translate("Parâmetro m deve vir primeiro."))); + return 1; + } + break; + case 'L': + case 'l': // log + //log is disabled by default + Compiler.setLog(true); + /* + if (argcnt == 0){ + Compiler.setLog(true); break; }else{ - Client.speak("Parâmetro m deve vir primeiro."); + Compiler.speak(string(translate("Parâmetro l deve vir primeiro."))); return 1; } + */ break; + case 'H': case 'h': // help usage(argv[0]); return 0; case '?': // error if (optopt == 'f'){ - //fprintf (stderr, "Option -%c requires a filename with GoDonnie code.\n", optopt); - Client.speak("Parâmetro -f requer um nome de arquivo com código GoDonnie."); + Compiler.speak(string(translate("Parâmetro -f requer um nome de arquivo com código GoDonnie."))); }else if (isprint (optopt)){ //fprintf (stderr, "Unknown option `-%c'.\n", optopt); char buffer[50]; - sprintf (buffer, "Parâmetro `-%c' desconhecido.", optopt); - Client.speak(string(buffer)); + string aux1 = translate("Parâmetro"); + string aux2 = translate("desconhecido"); + sprintf (buffer, "%s `-%c' %s.", aux1.c_str(), optopt, aux2.c_str()); + Compiler.speak(string(buffer)); }else{ //fprintf (stderr, // "Unknown option character `\\x%x'.\n", // optopt); char buffer[50]; - sprintf (buffer, "Parâmetro `\\x%x' desconhecido.", optopt); - Client.speak(string(buffer)); + string aux1 = translate("Parâmetro"); + string aux2 = translate("desconhecido"); + sprintf (buffer, "%s `\\x%x' %s.", aux1.c_str(), optopt, aux2.c_str()); + Compiler.speak(string(buffer)); } usage(argv[0]); return 1; @@ -139,13 +217,13 @@ int main(int argc, char* argv[]) if(!termMode && !scriptMode){ //cerr << "No mode selected" << endl; - Client.speak("Nenhum modo selecionado."); + Compiler.speak(string(translate("Nenhum modo selecionado."))); usage(argv[0]); return 1; } if(termMode && scriptMode){ //cerr << "Cannot have both modes selected at the same time" << endl; - Client.speak("Não pode ter dois modos selecionados ao mesmo tempo."); + Compiler.speak(string(translate("Não pode ter dois modos selecionados ao mesmo tempo."))); usage(argv[0]); return 1; } @@ -154,43 +232,18 @@ int main(int argc, char* argv[]) static char *temp = (char *)NULL; string preCode; + // bind the ESC key to the evalCode function + //rl_attempted_completion_function = fileman_completion; + rl_bind_key (27, evalCode); /* "27" ascii code for ESC */ + //rl_unbind_key('\t'); + //rl_bind_key('a',rl_complete); + + // create log file if it was enabled in command line + setupLog(); + // terminal mode if(termMode) { - FILE* log; - //rl_attempted_completion_function = fileman_completion; - rl_bind_key (27, evalCode); /* "27" ascii code for ESC */ - //rl_unbind_key('\t'); - //rl_bind_key('a',rl_complete); - - // find the appropriate file number to the log file. it follows sequential order - int fileno=0; - bool success = true; - char fileName[40] = ""; - - struct stat info; - - if( stat( "Log", &info ) != 0 ) - mkdir("Log", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); //Log directory does not exist. Creating log directory. - - ifstream ifs; - while(success &&fileno < 999) { - sprintf(fileName, "Log/log_%03d.txt", fileno); - ifs.open(fileName, std::ifstream::in);// attempt read file to check if it exists - success = ifs.good(); - ifs.close(); - fileno++;//increase by one to get a new file name - } - - sprintf(fileName, "Log/log_%03d.txt", fileno-1); - log = fopen(fileName, "w"); - - if (log == NULL) - { - Client.speak("Não foi possivel criar o arquivo de log"); - } - else - Client.logFile(log); while(!done) { @@ -217,9 +270,6 @@ int main(int argc, char* argv[]) rl_on_new_line (); }; - // save remaining buffered data on disk and close the log file - fflush(log); - fclose(log); }else if(scriptMode){ // script mode // read the entire file std::ifstream t(filename.c_str()); @@ -228,21 +278,29 @@ int main(int argc, char* argv[]) if(t.is_open()) { // read the entire file buffer << t.rdbuf(); - Client.parseGD((char *)buffer.str().c_str(),false); + Compiler.parseGD((char *)buffer.str().c_str()); }else{ - Client.speak("Erro ao abrir arquivo " + string(filename)); + Compiler.speak(string(translate("Erro ao abrir arquivo ")) + string(filename)); } t.close(); } + + if (Compiler.getLog()){ + // save remaining buffered data on disk and close the log file + fflush(logFile); + fclose(logFile); + } + + } void usage(char *exec){ sleep(0.5); - Client.speak("Uso: " + string(exec) + " argumentos. \nArgumentos: \n\t-t: Executa em modo terminal; \n\t-f nome do arquivo: Executa em modo script; \n\t-m: Quando habilitado, imprime mensagens na tela; \n\t-h: Ajuda"); + Compiler.speak(string(translate("Uso: ")) + string(exec) + string(translate(" argumentos. \nArgumentos: \n\t-t: Executa em modo terminal; \n\t-f nome do arquivo: Executa em modo script; \n\t-m: Quando habilitado, imprime mensagens na tela; \n\t-l: Quando habilitado, salva log dos comandos; \n\t-h: Ajuda"))); /* POR ALGUM MOTIVO O TTS NAO FUNCIONA C STRING NESTE FORMATO - Client.speak( + Compiler.speak( string( "Uso " + string(exec) + " \ Argumentos:\ @@ -266,18 +324,26 @@ int evalCode(int count, int key) if (!code.empty()) { cout << code << endl; - done = Client.parseGD((char *)code.c_str(),true); + done = Compiler.parseGD((char *)code.c_str()); code.clear(); code = ""; rl_on_new_line (); return 1; } - else + else{ rl_on_new_line (); - code.clear(); - Client.speak("\nNão há código para ser executado."); - return 0; - + code.clear(); + + generator gen; + gen.add_messages_path(string(getenv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("GoDonnie"); + locale loc = gen(string(getenv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + + string str_speak = translate("\nNão há código para ser executado."); + Compiler.speak(str_speak); + return 0; + } } @@ -320,15 +386,68 @@ char * command_generator(const char *text, int state) } /* Return the next name which partially matches from the command list. */ - while (name = commands[list_index].name) + /* In pt_BR */ + char *lang = getenv("DONNIE_LANG"); + if (strcmp(lang,"pt_BR") == 0) + { + while (name = comandos[list_index].name) { list_index++; if (strncmp (name, text, len) == 0) return (strdup(name)); } + } + /* In en_US */ + else if (strcmp(lang,"en_US") == 0) + { + while (name = commands[list_index].name) + { + list_index++; + + if (strncmp (name, text, len) == 0) + return (strdup(name)); + } + } /* If no names matched, then return NULL. */ return ((char *)NULL); } +/// When the log is enabled, it creates the log file +void setupLog() +{ + + // if log is enabled, then create the log file + if (Compiler.getLog()){ + // find the appropriate file number to the log file. it follows sequential order + int fileno=0; + bool success = true; + char fileName[40] = ""; + struct stat info; + + if( stat( "Log", &info ) != 0 ) + mkdir("Log", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); //Log directory does not exist. Creating log directory. + + ifstream ifs; + while(success &&fileno < 999) { + sprintf(fileName, "Log/log_%03d.txt", fileno); + ifs.open(fileName, std::ifstream::in);// attempt read file to check if it exists + success = ifs.good(); + ifs.close(); + fileno++;//increase by one to get a new file name + } + + sprintf(fileName, "Log/log_%03d.txt", fileno-1); + logFile = fopen(fileName, "w"); + + if (logFile == NULL) + { + Compiler.speak(string(translate("Não foi possivel criar o arquivo de log"))); + } + else + Compiler.logFile(logFile); + } + +} + diff --git a/client/godonnie/GoDonnie.g b/client/godonnie/GoDonnie.g index 7d73ea3..d2cc17e 100644 --- a/client/godonnie/GoDonnie.g +++ b/client/godonnie/GoDonnie.g @@ -11,9 +11,11 @@ options -// Header +// Header @parser::header{ #include +#include +#include #ifndef def_displayRecognitionErrorNew #define def_displayRecognitionErrorNew @@ -27,7 +29,7 @@ static void *getMissingSymbolNew(pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_INT //declaration of global variables in GoDonnieParser.c @parser::postinclude{ char messageError[2000]; //global variable for error messages generated by antlr - //It is printed in Compiler.cpp + //It is printed in Compiler.cpp char flagMsgError = 0; //flag to clean the 'messageError' string after it is printed by compiler } @@ -42,18 +44,18 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri @parser::members{ - + static void displayRecognitionErrorNew(pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_UINT8 * tokenNames) { + char* lang = getenv("DONNIE_LANG"); char messageAux[100]; if(flagMsgError == 1){ memset(messageError, 0, strlen(messageError)); - printf("(clear message error)\n"); flagMsgError = 0; } - + //ANTLR3_FPRINTF(stderr, "TESTE DE ERRO"); - + pANTLR3_PARSER parser; pANTLR3_TREE_PARSER tparser; pANTLR3_INT_STREAM is; @@ -90,8 +92,11 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri // Next comes the line number // - - sprintf(messageAux, "Erro na linha \%d ", recognizer->state->exception->line); + if (strcmp(lang,"pt_BR") == 0){ + sprintf(messageAux, "Erro na linha \%d ", recognizer->state->exception->line); + } else if (strcmp(lang,"en_US") == 0){ + sprintf(messageAux, "Error in line \%d ", recognizer->state->exception->line); + } strcat(messageError, messageAux); //ANTLR3_FPRINTF(stderr, "Erro na linha \%d ", recognizer->state->exception->line); //ANTLR3_FPRINTF(stderr, " : error \%d : \%s", recognizer->state->exception->type, (pANTLR3_UINT8)(recognizer->state->exception->message)); @@ -114,7 +119,11 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri //ANTLR3_FPRINTF(stderr, ", at offset \%d", recognizer->state->exception->charPositionInLine); //ANTLR3_FPRINTF(stderr, "e na coluna \%d. ", (recognizer->state->exception->charPositionInLine+1)); - sprintf(messageAux, "e na coluna \%d. ", recognizer->state->exception->charPositionInLine+1); + if (strcmp(lang,"pt_BR") == 0){ + sprintf(messageAux, "e na coluna \%d. ", recognizer->state->exception->charPositionInLine+1); + } else if (strcmp(lang,"en_US") == 0){ + sprintf(messageAux, ", in column \%d. ", recognizer->state->exception->charPositionInLine+1); + } strcat(messageError, messageAux); if (theToken != NULL) { @@ -122,7 +131,11 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri { //ANTLR3_FPRINTF(stderr, ", at "); //ANTLR3_FPRINTF(stderr, " no fim do arquivo."); - sprintf(messageAux, "no fim do arquivo."); + if (strcmp(lang,"pt_BR") == 0){ + sprintf(messageAux, "no fim do arquivo."); + } else if (strcmp(lang,"en_US") == 0){ + sprintf(messageAux, "at end of file."); + } strcat(messageError, messageAux); } else @@ -130,13 +143,21 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri // Guard against null text in a token // //ANTLR3_FPRINTF(stderr, "\n near \%s\n ", ttext == NULL ? (pANTLR3_UINT8)"" : ttext->chars); - pANTLR3_UINT8 temp = (pANTLR3_UINT8)"Sem token identificado"; - + if (strcmp(lang,"pt_BR") == 0){ + pANTLR3_UINT8 temp = (pANTLR3_UINT8)"Sem token identificado"; + } else if (strcmp(lang,"en_US") == 0){ + pANTLR3_UINT8 temp = (pANTLR3_UINT8)"No identified token"; + } + pANTLR3_STRING ttext2 = theToken->getText(theToken); - + //ANTLR3_FPRINTF(stderr, "\n\n \%s \n\n", ttext->chars); //ANTLR3_FPRINTF(stderr, "Verificar comando \%s", ttext == NULL ? (pANTLR3_UINT8)"" : ttext2->chars); - sprintf(messageAux, "Verificar comando \%s", ttext == NULL ? (pANTLR3_UINT8)"" : ttext2->chars); + if (strcmp(lang,"pt_BR") == 0){ + sprintf(messageAux, "Verificar comando \%s", ttext == NULL ? (pANTLR3_UINT8)"" : ttext2->chars); + } else if (strcmp(lang,"en_US") == 0){ + sprintf(messageAux, "Verify command \%s", ttext == NULL ? (pANTLR3_UINT8)"" : ttext2->chars); + } strcat(messageError, messageAux); } } @@ -159,11 +180,19 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri theToken = (pANTLR3_COMMON_TOKEN) theBaseTree->getToken(theBaseTree); } //ANTLR3_FPRINTF(stderr, ", na coluna \%d", (theBaseTree->getCharPositionInLine(theBaseTree)+1)); - sprintf(messageAux, ", na coluna \%d", (theBaseTree->getCharPositionInLine(theBaseTree)+1)); + if (strcmp(lang,"pt_BR") == 0){ + sprintf(messageAux, ", na coluna \%d", (theBaseTree->getCharPositionInLine(theBaseTree)+1)); + } else if (strcmp(lang,"en_US") == 0){ + sprintf(messageAux, ", in column \%d", (theBaseTree->getCharPositionInLine(theBaseTree)+1)); + } strcat(messageError, messageAux); - + //ANTLR3_FPRINTF(stderr, ", na palavra \%s", ttext->chars); - sprintf(messageAux, ", na palavra \%s", ttext->chars); + if (strcmp(lang,"pt_BR") == 0){ + sprintf(messageAux, ", na palavra \%s", ttext->chars); + } else if (strcmp(lang,"en_US") == 0){ + sprintf(messageAux, ", in word \%s", ttext->chars); + } strcat(messageError, messageAux); } break; @@ -201,9 +230,13 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri { //ANTLR3_FPRINTF(stderr, " : Extraneous input..."); //ANTLR3_FPRINTF(stderr, " : Entrada desconhecida..."); - sprintf(messageAux, " : Entrada desconhecida..."); + if (strcmp(lang,"pt_BR") == 0){ + sprintf(messageAux, " : Entrada desconhecida..."); + } else if (strcmp(lang,"en_US") == 0){ + sprintf(messageAux, " : Entry unknown..."); + } strcat(messageError, messageAux); - + } else { @@ -211,14 +244,22 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri { //ANTLR3_FPRINTF(stderr, " : Extraneous input - expected \n"); //ANTLR3_FPRINTF(stderr, " : Entrada desconhecida - Esperava o fim do arquivo\n"); - sprintf(messageAux, " : Entrada desconhecida - Esperava o fim do arquivo\n"); + if (strcmp(lang,"pt_BR") == 0){ + sprintf(messageAux, " : Entrada desconhecida - Esperava o fim do arquivo\n"); + } else if (strcmp(lang,"en_US") == 0){ + sprintf(messageAux, " : Entry unknown - End of file expected\n"); + } strcat(messageError, messageAux); } else { //ANTLR3_FPRINTF(stderr, " : Extraneous input - expected \%s ...\n", tokenNames[ex->expecting]); //ANTLR3_FPRINTF(stderr, " : Entrada desconhecida - esperando \%s ...\n", tokenNames[ex->expecting]); - sprintf(messageAux, " : Entrada desconhecida - esperando \%s ...\n", tokenNames[ex->expecting]); + if (strcmp(lang,"pt_BR") == 0){ + sprintf(messageAux, " : Entrada desconhecida - esperando \%s ...\n", tokenNames[ex->expecting]); + } else if (strcmp(lang,"en_US") == 0){ + sprintf(messageAux, " : Entry unknown - \%s expected ...\n", tokenNames[ex->expecting]); + } strcat(messageError, messageAux); } } @@ -227,7 +268,7 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri case ANTLR3_MISSING_TOKEN_EXCEPTION: // Indicates that the recognizer detected that the token we just - // hit would be valid syntactically if preceeded by a particular + // hit would be valid syntactically if preceeded by a particular // token. Perhaps a missing ';' at line end or a missing ',' in an // expression list, and such like. // @@ -235,7 +276,11 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri { //ANTLR3_FPRINTF(stderr, " : Missing token (\%d)...\n", ex->expecting); //ANTLR3_FPRINTF(stderr, " : token faltando (\%d)...\n", ex->expecting); - sprintf(messageAux, " : token faltando (\%d)...\n", ex->expecting); + if (strcmp(lang,"pt_BR") == 0){ + sprintf(messageAux, " : token faltando (\%d)...\n", ex->expecting); + } else if (strcmp(lang,"en_US") == 0){ + sprintf(messageAux, " : missing token (\%d)...\n", ex->expecting); + } strcat(messageError, messageAux); } else @@ -244,7 +289,11 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri { //ANTLR3_FPRINTF(stderr, " : Missing \n"); //ANTLR3_FPRINTF(stderr, " : Faltando fim do aquivo\n"); - sprintf(messageAux, " : Faltando fim do aquivo\n"); + if (strcmp(lang,"pt_BR") == 0){ + sprintf(messageAux, " : Faltando fim do arquivo\n"); + } else if (strcmp(lang,"en_US") == 0){ + sprintf(messageAux, " : End of file missing\n"); + } strcat(messageError, messageAux); } else @@ -261,14 +310,18 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri case ANTLR3_RECOGNITION_EXCEPTION: // Indicates that the recognizer received a token - // in the input that was not predicted. This is the basic exception type + // in the input that was not predicted. This is the basic exception type // from which all others are derived. So we assume it was a syntax error. // You may get this if there are not more tokens and more are needed // to complete a parse for instance. // - //ANTLR3_FPRINTF(stderr, " : syntax error...\n"); - //ANTLR3_FPRINTF(stderr, " : Erro de sintaxe...\n"); - sprintf(messageAux, " : Erro de sintaxe...\n"); + //ANTLR3_FPRINTF(stderr, " : syntax error...\n"); + //ANTLR3_FPRINTF(stderr, " : Erro de sintaxe...\n"); + if (strcmp(lang,"pt_BR") == 0){ + sprintf(messageAux, " : Erro de sintaxe...\n"); + } else if (strcmp(lang,"en_US") == 0){ + sprintf(messageAux, " : Syntax error...\n"); + } strcat(messageError, messageAux); break; @@ -287,7 +340,11 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri { //ANTLR3_FPRINTF(stderr, " : syntax error...\n"); //ANTLR3_FPRINTF(stderr, " : Erro de sintaxe...\n"); - sprintf(messageAux, " : Erro de sintaxe...\n"); + if (strcmp(lang,"pt_BR") == 0){ + sprintf(messageAux, " : Erro de sintaxe...\n"); + } else if (strcmp(lang,"en_US") == 0){ + sprintf(messageAux, " : Syntax error...\n"); + } strcat(messageError, messageAux); } else @@ -296,14 +353,22 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri { //ANTLR3_FPRINTF(stderr, " : expected \n"); //ANTLR3_FPRINTF(stderr, " : esperando fim do arquivo\n"); - sprintf(messageAux, " : esperando fim do arquivo\n"); + if (strcmp(lang,"pt_BR") == 0){ + sprintf(messageAux, " : esperando fim do arquivo\n"); + } else if (strcmp(lang,"en_US") == 0){ + sprintf(messageAux, " : end of file expected\n"); + } strcat(messageError, messageAux); } else { //ANTLR3_FPRINTF(stderr, " : expected \%s ...\n", tokenNames[ex->expecting]); //ANTLR3_FPRINTF(stderr, " : esperando \%s ...\n", tokenNames[ex->expecting]); - sprintf(messageAux, " : esperando \%s ...\n", tokenNames[ex->expecting]); + if (strcmp(lang,"pt_BR") == 0){ + sprintf(messageAux, " : esperando \%s ...\n", tokenNames[ex->expecting]); + } else if (strcmp(lang,"en_US") == 0){ + sprintf(messageAux, " : \%s expected ...\n", tokenNames[ex->expecting]); + } strcat(messageError, messageAux); } } @@ -320,7 +385,7 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri //ANTLR3_FPRINTF(stderr, "\n"); sprintf(messageAux, "\n"); strcat(messageError, messageAux); - + break; case ANTLR3_MISMATCHED_SET_EXCEPTION: @@ -360,7 +425,7 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri // if (tokenNames[bit]) { - //ANTLR3_FPRINTF(stderr, "\%s\%s", count > 0 ? ", " : "", tokenNames[bit]); + //ANTLR3_FPRINTF(stderr, "\%s\%s", count > 0 ? ", " : "", tokenNames[bit]); count++; } } @@ -382,7 +447,11 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri // //ANTLR3_FPRINTF(stderr, " : missing elements...\n"); //ANTLR3_FPRINTF(stderr, " : faltando elementos...\n"); - sprintf(messageAux, " : faltando elementos...\n"); + if (strcmp(lang,"pt_BR") == 0){ + sprintf(messageAux, " : faltando elementos...\n"); + } else if (strcmp(lang,"en_US") == 0){ + sprintf(messageAux, " : missing elements...\n"); + } strcat(messageError, messageAux); break; @@ -395,7 +464,11 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri // //ANTLR3_FPRINTF(stderr, " : syntax not recognized...\n"); //ANTLR3_FPRINTF(stderr, " : sintaxe não reconhecida...\n"); - sprintf(messageAux, " : sintaxe não reconhecida...\n"); + if (strcmp(lang,"pt_BR") == 0){ + sprintf(messageAux, " : sintaxe não reconhecida...\n"); + } else if (strcmp(lang,"en_US") == 0){ + sprintf(messageAux, " : syntax not recognized...\n"); + } strcat(messageError, messageAux); break; } @@ -412,9 +485,9 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri // } - - - + + + static void *getMissingSymbolNew(pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_INT_STREAM istream, pANTLR3_EXCEPTION e, ANTLR3_UINT32 expectedTokenType, pANTLR3_BITSET_LIST follow) { pANTLR3_TOKEN_STREAM ts; @@ -427,7 +500,7 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri // ts = (pANTLR3_TOKEN_STREAM)istream->super; cts = (pANTLR3_COMMON_TOKEN_STREAM)ts->super; - + // Work out what to use as the current symbol to make a line and offset etc // If we are at EOF, we use the token before EOF // @@ -436,13 +509,13 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri { current = ts->_LT(ts, -1); } - + // Finally return the pointer to our new token // return current; } - - + + } @parser::apifuncs { @@ -457,11 +530,12 @@ char flagMsgError = 0; //flag to clean the 'messageError' string after it is pri start_rule : prog; prog : line+; - + line : (cmd SEMICOLON!?) ; + cmd : arg |narg |make @@ -474,18 +548,19 @@ cmd : arg |commente |procedec |proceinv + |belte ; - - + + //block : cmd ( SEMICOLON!? cmd)* SEMICOLON!?; - + arg : (FW^| BW^| RTURN^| LTURN^| WAIT^) expression; narg : (SCAN | POS | RANGER | QUIT | COLOR | SOUND | HIST | STATE); - - + + signEXP : (PLUS^ | MINUS^)? atom; @@ -527,9 +602,17 @@ whilee : WHILEE^ comparison whileblock ; repeat : REPEAT^ expression reptblock; - +/* make : MAKE^ ID (EQ! expression)?; +*/ +/* +Here are defined the reserved Words. So only words defined here are acceptable as commands +*/ +make : MAKE^ ~(QUIT| PROCDEC| PROCINV| FORE| DOIT| ENDFOR| WHILEE| ENDWHILE| SPEAKE| + HIST| STATE| FW| BW| RTURN| LTURN| SCAN| RANGER| POS| COLOR| SOUND| BELT| + THEN| IFE| ENDIF| ELSEE| REPTB| REPEAT| ENDREPT| WAIT| MAKE| ID| STRINGE| + COMENT| MINUS| MULT| DIV| PLUS| EQ| COMP| SEMICOLON| INT| EOL| WS) (EQ! expression)?; assign : ID EQ^ expression; @@ -545,7 +628,10 @@ procedec : PROCDEC^ ID (':'! (ID) (','! (ID))*)? procblock; proceinv : ID PROCINV^ (expression (','! expression)*)? ']'!; - + +belte : BELT ; + + atom : POS |RANGER |COLOR @@ -558,140 +644,183 @@ atom : POS -PROCINV : '['; +PROCINV : '['; PROCDEC : (('A'|'a')('P'|'p')('R'|'r')('E'|'e')('N'|'n')('D'|'d')('E'|'e')('R'|'r')) + |(('P'|'p')('R'|'r')('O'|'o')('C'|'c')('E'|'e')('D'|'d')('U'|'u')('R'|'r')('E'|'e')) ; - - + + ENDPROC : (('F'|'f')('I'|'i')('M'|'m')(' ')+('A'|'a')('P'|'p')('R'|'r')('E'|'e')('N'|'n')('D'|'d')('E'|'e')('R'|'r')) + |(('E'|'e')('N'|'n')('D'|'d')(' ')+('P'|'p')('R'|'r')('O'|'o')('C'|'c')('E'|'e')('D'|'d')('U'|'u')('R'|'r')('E'|'e')) ; FORE : (('P'|'p')('A'|'a')('R'|'r')('A'|'a')(' ')?) + |(('F'|'f')('O'|'o')('R'|'r')(' ')?) ; - + DOIT : (('F'|'f')('A'|'a')('Ç'|'ç'|'C'|'c')('A'|'a')) + |(('D'|'d')('O'|'o')) ; ENDFOR : (('F'|'f')('I'|'i')('M'|'m')(' ')+('P'|'p')('A'|'a')('R'|'r')('A'|'a')) + |(('E'|'e')('N'|'n')('D'|'d')(' ')+('F'|'f')('O'|'o')('R'|'r')) ; - + WHILEE : (('E'|'e')('N'|'n')('Q'|'q')('U'|'u')('A'|'a')('N'|'n')('T'|'t')('O'|'o')) + |(('W'|'w')('H'|'h')('I'|'i')('L'|'l')('E'|'e')) ; - + ENDWHILE : (('F'|'f')('I'|'i')('M'|'m')(' ')+('E'|'e')('N'|'n')('Q'|'q')('U'|'u')('A'|'a')('N'|'n')('T'|'t')('O'|'o')) + |(('E'|'e')('N'|'n')('D'|'d')(' ')+('W'|'w')('H'|'h')('I'|'i')('L'|'l')('E'|'e')) ; - + SPEAKE : (('F'|'f')('A'|'a')('L'|'l')('A'|'a')('R'|'r')) + |(('S'|'s')('P'|'p')('E'|'e')('A'|'a')('K'|'k')) ; - - + + HIST : (('H'|'h')('I'|'i')('S'|'s')('T'|'t')('Ó'|'ó'|'O'|'o')('R'|'r')('I'|'i')('C'|'c')('O'|'o')) + |(('H'|'h')('I'|'i')('S'|'s')('T'|'t')('O'|'o')('R'|'r')('Y'|'y')) ; STATE : (('E'|'e')('S'|'s')('T'|'t')('A'|'a')('D'|'d')('O'|'o')) + |(('S'|'s')('T'|'t')('A'|'a')('T'|'t')('E'|'e')) ; - + QUIT : (('S'|'s')('A'|'a')('I'|'i')('R'|'r')) + |(('Q'|'q')('U'|'u')('I'|'i')('T'|'t')) + |(('E'|'e')('X'|'x')('I'|'i')('T'|'t')) ; -/*forward*/ +/*forward*/ FW : (('P'|'p')('F'|'f')) |(('P'|'p')('A'|'a')('R'|'r')('A'|'a') (' ')+ ('F'|'f')('R'|'r')('E'|'e')('N'|'n')('T'|'t')('E'|'e')) + |(('F'|'f')('W'|'w')) + |(('F'|'f')('O'|'o')('R'|'r')('W'|'w')('A'|'a')('R'|'r')('D'|'d')) ; /*backward*/ BW : (('P'|'p')('T'|'t')) |(('P'|'p')('A'|'a')('R'|'r')('A'|'a') (' ')+ ('T'|'t')('R'|'r')('A'|'a'|'Á'|'á')('S'|'s')) + |(('B'|'b')('W'|'w')) + |(('B'|'b')('A'|'a')('C'|'c')('W'|'w')('A'|'a')('R'|'r')('D'|'d')) ; /*right turn*/ RTURN : (('G'|'g')('D'|'d')) - |(('G'|'g')('I'|'i')('R'|'r')('A'|'a')('R'|'r') (' ')+ ('D'|'d')('I'|'i')('R'|'r')('E'|'e')('I'|'i')('T'|'t')('A'|'a')) + |(('G'|'g')('I'|'i')('R'|'r')('A'|'a')('R'|'r') (' ')+ ('D'|'d')('I'|'i')('R'|'r')('E'|'e')('I'|'i')('T'|'t')('A'|'a')) + |(('T'|'t')('R'|'r')) + |(('R'|'r')('I'|'i')('G'|'g')('H'|'h')('T'|'t') (' ')+ ('T'|'t')('U'|'u')('R'|'r')('N'|'n')) ; -/*left turn*/ +/*left turn*/ LTURN : (('G'|'g')('E'|'e')) - |(('G'|'g')('I'|'i')('R'|'r')('A'|'a')('R'|'r') (' ')+ ('E'|'e')('S'|'s')('Q'|'q')('U'|'u')('E'|'e')('R'|'r')('D'|'d')('A'|'a')) + |(('G'|'g')('I'|'i')('R'|'r')('A'|'a')('R'|'r') (' ')+ ('E'|'e')('S'|'s')('Q'|'q')('U'|'u')('E'|'e')('R'|'r')('D'|'d')('A'|'a')) + |(('T'|'t')('L'|'l')) + |(('L'|'l')('E'|'e')('F'|'f')('T'|'t') (' ')+ ('T'|'t')('U'|'u')('R'|'r')('N'|'n')) + ; + +SCAN : (('E'|'e')('S'|'s')('P'|'p')('I'|'i')('A'|'a')('R'|'r')) + |(('S'|'s')('C'|'c')('A'|'a')('N'|'n')) ; - -SCAN : (('E'|'e')('S'|'s')('P'|'p')('I'|'i')('A'|'a')('R'|'r')); -RANGER +RANGER : (('D'|'d')('I'|'i')('S'|'s')('T'|'t')('â'|'Â'|'A'|'a')('N'|'n')('C'|'c')('I'|'i')('A'|'a')) (' ')+ (('F'|'f')|('FE'|'fe'|'Fe'|'fE')|('FD'|'fd'|'Fd'|'fD')|('T'|'t')|('TE'|'te'|'Te'|'tE')|('TD'|'td'|'Td'|'tD')) + |(('D'|'d')('I'|'i')('S'|'s')('T'|'t')('A'|'a')('N'|'n')('C'|'c')('E'|'e')) + (' ')+ (('F'|'f')|('FL'|'fl'|'Fl'|'fL')|('FR'|'fr'|'Fr'|'fR')|('B'|'b')|('BL'|'bl'|'Bl'|'bL')|('BR'|'br'|'Br'|'bR')) ; - -POS : (('P'|'p')('O'|'o')('S'|'s')(('I'|'i')('Ç'|'ç'|'C'|'c')('Ã'|'ã'|'A'|'a')('O'|'o'))?) ((' ')+ (('X'|'x') | ('Y'|'y') | ('A'|'a')))? + +POS : (('P'|'p')('O'|'o')('S'|'s') + |('P'|'p')('O'|'o')('S'|'s')('I'|'i')('T'|'t')('I'|'i')('O'|'o')('N'|'n') + |('P'|'p')('O'|'o')('S'|'s')('I'|'i')('Ç'|'ç'|'C'|'c')('Ã'|'ã'|'A'|'a')('O'|'o')?) ((' ')+ (('X'|'x') | ('Y'|'y') | ('A'|'a')))? + //|((('P'|'p')('O'|'o')('S'|'s')('I'|'i')('T'|'t')('I'|'i')('O'|'o')('N'|'n'))?) ((' ')+ (('X'|'x') | ('Y'|'y') | ('A'|'a')))? + //|((('P'|'p')('O'|'o')('S'|'s')('I'|'i')('Ç'|'ç'|'C'|'c')('Ã'|'ã'|'A'|'a')('O'|'o'))?) ((' ')+ (('X'|'x') | ('Y'|'y') | ('A'|'a')))? ; COLOR : (('C'|'c')('O'|'o')('R'|'r')) (' ')+ ((('A'|'a')('Z'|'z')('U'|'u')('L'|'l')) | (('V'|'v')('E'|'e')('R'|'r')('D'|'d')('E'|'e')) | (('V'|'v')('E'|'e')('R'|'r')('M'|'m')('E'|'e')('L'|'l')('H'|'h')('O'|'o'))) + |(('C'|'c')('O'|'o')('L'|'l')('O'|'o')('R'|'r')) (' ')+ ((('B'|'b')('L'|'l')('U'|'u')('E'|'e')) | (('G'|'g')('R'|'r')('E'|'e')('N'|'n')) | (('R'|'r')('E'|'e')('D'|'d'))) ; SOUND : (('S'|'s')('O'|'o')('M'|'m')) (' ')+ ((('L'|'l')('I'|'i')('G'|'g')('A'|'a')('D'|'d')('O'|'o')) | (('D'|'d')('E'|'e')('S'|'s')('L'|'l')('I'|'i')('G'|'g')('A'|'a')('D'|'d')('O'|'o'))) + |(('S'|'s')('O'|'o')('U'|'u')('N'|'n')('D'|'d')) (' ')+ ((('O'|'o')('N'|'n')) | (('O'|'o')('F'|'f')('F'|'f'))) ; - - + +BELT : (('C'|'c')('I'|'i')('N'|'n')('T'|'t')('O'|'o')) (' ')+ ((('L'|'l')('I'|'i')('G'|'g')('A'|'a')('D'|'d')('O'|'o')) | (('D'|'d')('E'|'e')('S'|'s')('L'|'l')('I'|'i')('G'|'g')('A'|'a')('D'|'d')('O'|'o'))) + |(('B'|'b')('E'|'e')('L'|'l')('T'|'t')) (' ')+ ((('O'|'o')('N'|'n')) | (('O'|'o')('F'|'f')('F'|'f'))) + ; + THEN : (('E'|'e')('N'|'n')('T'|'t')('Ã'|'ã'|'A'|'a')('O'|'o')) + |(('T'|'t')('H'|'h')('E'|'e')('N'|'n')) ; - -IFE : (('S'|'s')('E'|'e')) + +IFE : (('S'|'s')('E'|'e')) + |(('I'|'i')('F'|'f')) ; - + ENDIF : (('F'|'f')('I'|'i')('M'|'m')(' ')+('S'|'s')('E'|'e')) + |(('E'|'e')('N'|'n')('D'|'d')(' ')+('I'|'i')('F'|'f')) ; - + ELSEE : (('S'|'s')('E'|'e')('N'|'n')('Ã'|'ã'|'A'|'a')('O'|'o')) + |(('E'|'e')('L'|'l')('S'|'s')('E'|'e')) ; - + REPEAT : (('R'|'r')('E'|'e')('P'|'p')('I'|'i')('T'|'t')('A'|'a')) + |(('R'|'r')('E'|'e')('P'|'p')('E'|'e')('A'|'a')('T'|'t')) ; REPTB : (('V'|'v')('E'|'e')('Z'|'z')('E'|'e')('S'|'s')) + |(('T'|'t')('I'|'i')('M'|'m')('E'|'e')('S'|'s')) ; - + ENDREPT : (('F'|'f')('I'|'i')('M'|'m')(' ')+('R'|'r')('E'|'e')('P'|'p')('I'|'i')('T'|'t')('A'|'a')) + |(('E'|'e')('N'|'n')('D'|'d')(' ')+('R'|'r')('E'|'e')('P'|'p')('E'|'e')('A'|'a')('T'|'t')) ; WAIT : (('E'|'e')('S'|'s')('P'|'p')('E'|'e')('R'|'r')('A'|'a')('R'|'r')) + |(('W'|'w')('A'|'a')('I'|'i')('T'|'t')) ; MAKE : (('C'|'c')('R'|'r')('I'|'i')('A'|'a')('R'|'r')) + |(('V'|'v')('A'|'a')('R'|'r')) ; - + /* fragment Latin1_Supplement : '\u00A0' .. '\u00FF' ; - + ID : ('A'..'Z'|'a'..'z'|Latin1_Supplement)('a'..'z'|'A'..'Z'|Latin1_Supplement|'0'..'9'|'_')*; -*/ +*/ -ID : ('A'..'Z'|'a'..'z')('a'..'z'|'A'..'Z'|'0'..'9'|'_')*; + +ID : ('A'..'Z'|'a'..'z')('a'..'z'|'A'..'Z'|'0'..'9'|'_')*; STRINGE : '"' (~('"'))+ '"'; COMENT : '--' (~('\r'|'\n'))* ('\r\n'|'\r'|'\n'|EOF); - - + + MINUS : '-'; MULT : '*'; -DIV : '/'; - +DIV : '/'; + PLUS : '+'; EQ : '='; - + COMP : '<' | '>' | '==' | '>='| '<=' | '<>'; - + SEMICOLON : ';'; INT : '0'..'9'+; @@ -701,6 +830,3 @@ EOL : ('\r' /*WS : ( ' ' | '\t')+;*/ WS : ( ' ' | '\t')+ {$channel=HIDDEN;}; - - - diff --git a/client/godonnie/Historic.cpp b/client/godonnie/Historic.cpp index bd7b89a..d501e31 100644 --- a/client/godonnie/Historic.cpp +++ b/client/godonnie/Historic.cpp @@ -54,10 +54,17 @@ string Historic::show() list::iterator iterator; int cmdNum=0; - history << "Histórico possui " << commandsList.size() << " comandos" << endl; + generator gen; + gen.add_messages_path(string(getenv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("Historic"); + locale loc = gen(string(getenv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + history.imbue(loc); + + history << translate("Histórico possui ") << commandsList.size() << translate(" comandos") << endl; for (iterator = this->commandsList.begin(); iterator != this->commandsList.end(); ++iterator) { - history << "Comando " << cmdNum << " foi " << (*iterator).name << ", " << (*iterator).feedback << - ", posição [" << (*iterator).posx << ", " << (*iterator).posy << + history << translate("Comando ") << cmdNum << translate(" foi ") << (*iterator).name << ", " << (*iterator).feedback << + translate(", posição [") << (*iterator).posx << ", " << (*iterator).posy << ", " << (*iterator).degree << "]" << endl ; cmdNum++; } @@ -70,10 +77,18 @@ string Historic::getLast() stringstream history; Command last; + generator gen; + gen.add_messages_path(string(getenv("DONNIE_PATH")) + "/resources/loc"); + gen.add_messages_domain("Historic"); + locale loc = gen(string(getenv("DONNIE_LANG")) + ".UTF-8"); + locale::global(loc); + cout.imbue(loc); + history.imbue(loc); + if (commandsList.size() > 0){ last = commandsList.back(); - history << "Comando " << commandsList.size()-1 << " foi " << last.name << ", " << last.feedback << - ", posição [" << last.posx << ", " << last.posy << + history << translate("Comando ") << commandsList.size()-1 << translate(" foi ") << last.name << ", " << last.feedback << + translate(", posição [") << last.posx << ", " << last.posy << ", " << last.degree << "]"; // dont add newline here ! } diff --git a/client/godonnie/Makefile b/client/godonnie/Makefile index a336cb7..d9a40f9 100644 --- a/client/godonnie/Makefile +++ b/client/godonnie/Makefile @@ -9,7 +9,7 @@ all:clean grammar GoDonnie clean: rm -f GoDonnieLexer* GoDonnieParser* GoDonnie GoDonnie.tokens -grammar: GoDonnie.g +grammar: GoDonnie_en_US.g java -jar Antlr/antlr-3.2.jar GoDonnie.g diff --git a/client/godonnie/lexerExtra.h b/client/godonnie/lexerExtra.h index a621462..9458637 100644 --- a/client/godonnie/lexerExtra.h +++ b/client/godonnie/lexerExtra.h @@ -1,6 +1,8 @@ #include #include #include +#include +#include #ifndef def_displayRecognitionErrorNewLexer #define def_displayRecognitionErrorNewLexer @@ -26,10 +28,18 @@ //ftext = ex->streamName->to8(ex->streamName); //ANTLR3_FPRINTF(stderr, "\%s(", ftext->chars); } + + if (strcmp("pt_BR",getenv("DONNIE_LANG")) == 0){ + ANTLR3_FPRINTF(stderr, "Erro na linha %d ", recognizer->state->exception->line); + ANTLR3_FPRINTF(stderr, "e na coluna %d. ", (recognizer->state->exception->charPositionInLine)); + ANTLR3_FPRINTF(stderr, " Palavra invalida \n"); + } - ANTLR3_FPRINTF(stderr, "Erro na linha %d ", recognizer->state->exception->line); - ANTLR3_FPRINTF(stderr, "e na coluna %d. ", (recognizer->state->exception->charPositionInLine)); - ANTLR3_FPRINTF(stderr, " Palavra invalida \n"); + if (strcmp("en_US",getenv("DONNIE_LANG")) == 0){ + ANTLR3_FPRINTF(stderr, "Error in line %d ", recognizer->state->exception->line); + ANTLR3_FPRINTF(stderr, ", column %d. ", (recognizer->state->exception->charPositionInLine)); + ANTLR3_FPRINTF(stderr, " Invalid word \n"); + } //ANTLR3_FPRINTF(stderr, "Verificar comando %s \n", ttext == NULL ? (pANTLR3_UINT8)"" : ttext2->chars); if(ex->c == (char)ANTLR3_TOKEN_EOF) diff --git a/client/godonnie/test/square.gd b/client/godonnie/test/square.gd index 1315ab3..bac057a 100644 --- a/client/godonnie/test/square.gd +++ b/client/godonnie/test/square.gd @@ -1,15 +1,15 @@ criar a = 4 aprender quadradO: a,b,c -faa +faça para criar d = 0; d < c; d = d + 1 - faa + faça pf a ge b fim para fim aprender -se a > 3 ento falar "oi" fim se +se a > 3 então falar "oi" fim se quadrAdO[1,90,2] diff --git a/client/test/CMakeLists.txt b/client/test/CMakeLists.txt index a805b00..b480405 100644 --- a/client/test/CMakeLists.txt +++ b/client/test/CMakeLists.txt @@ -26,7 +26,7 @@ INSTALL(FILES donnie.cfg donnie_sim.cfg Makefile DESTINATION ${DONNIE_PATH}/test IF ( BUILD_EXAMPLES ) # Include this CMake module to get most of the settings needed to build - SET (CMAKE_MODULE_PATH "/usr/local/share/cmake/Modules") + #SET (CMAKE_MODULE_PATH "/usr/local/share/cmake/Modules") INCLUDE (UsePlayerC++) # add EACH executable and sources here diff --git a/client/vib_belt/CMakeLists.txt b/client/vib_belt/CMakeLists.txt new file mode 100644 index 0000000..539baec --- /dev/null +++ b/client/vib_belt/CMakeLists.txt @@ -0,0 +1,21 @@ +CMAKE_MINIMUM_REQUIRED (VERSION 2.8 FATAL_ERROR) +SET (CLIENTNAME "vib_belt") +PROJECT (${CLIENTNAME}) + +message(STATUS "Configuring '${CLIENTNAME}'") + +# Include this CMake module to get most of the settings needed to build +SET (CMAKE_MODULE_PATH "/usr/local/share/cmake/Modules") + +INCLUDE (UsePlayerC++) + +PLAYER_ADD_PLAYERCPP_CLIENT (${CLIENTNAME} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/vib_belt.cpp ${CMAKE_CURRENT_SOURCE_DIR}/vib_belt.cc + INCLUDEDIRS ${CMAKE_CURRENT_SOURCE_DIR} ) + +TARGET_LINK_LIBRARIES (${CLIENTNAME}) +INCLUDE_DIRECTORIES (${CMAKE_CURRENT_SOURCE_DIR}) + +# Install executables with -x permission +INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${CLIENTNAME} DESTINATION ${DONNIE_PATH}/bin) +#INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/test/* DESTINATION ${DONNIE_PATH}/test/${CLIENTNAME}) diff --git a/client/vib_belt/compile.sh b/client/vib_belt/compile.sh new file mode 100755 index 0000000..e54ee53 --- /dev/null +++ b/client/vib_belt/compile.sh @@ -0,0 +1,4 @@ +mkdir -p build # no error if existing +cd build/ +cmake ../ +make diff --git a/client/vib_belt/vib_belt.cc b/client/vib_belt/vib_belt.cc new file mode 100644 index 0000000..ab58942 --- /dev/null +++ b/client/vib_belt/vib_belt.cc @@ -0,0 +1,62 @@ +#include + +using namespace std; + +int main(int argc, char** argv) { + vib_belt* belt = NULL; + + // treatment for the arguments + if (argc > 1) + if (argv[1][0] == '-') + switch (argv[1][1]) { + case 'p': + belt = new vib_belt(argv[2]); + break; + case 'e': + belt = new vib_belt(argv[2], argv[3], atoi(argv[4])); + break; + default: +unknow_command: + cout << "The list of know parameters are: " << endl; + cout << "To run the belt on the default port : ./vib_belt" << endl; + cout << "To run the belt on a user defined serial port: ./vib_belt -p " << endl; + cout << "To run the belt on a user defined serial port, host and port: ./vib_belt -e " << endl; + return 0; + } + else + // jumps to the unknow_command label + goto unknow_command; + else + // default vib_belt constructor + belt = new vib_belt(); + + if (belt == NULL) + cout << "Mega bug !!! " << endl; + + // connect to the serial and check for errors in the connection + if (!belt->connect()) { + perror("Failed to connect."); + return -1; + + } + + cout << "done connected" << endl; + //cout << "Rangers: " << belt->myranger->GetRangeCount() << endl; + //cout << "Ranger[0]: " << belt->myranger->GetRange(0) << endl; + //cout << "done reading 1" << endl; + //belt->robot->Read(); + //cout << "Rangers: " << belt->myranger->GetRangeCount() << endl; + //cout << "Ranger[0]: " << belt->myranger->GetRange(0) << endl; + //cout << "done reading 2" << endl; + //cout << "?" << endl; + // main loop for the belt + while (1){ + usleep(100); //little delay + cout << "Rangers - main: " << belt->myranger->GetRangeCount() << endl; + belt->loop(); + } + // close the serial communication + belt->exit(); + + return 0; +} diff --git a/client/vib_belt/vib_belt.cpp b/client/vib_belt/vib_belt.cpp new file mode 100644 index 0000000..1839d5d --- /dev/null +++ b/client/vib_belt/vib_belt.cpp @@ -0,0 +1,155 @@ + +#include +#include "vib_belt.h" +///////////////////// + +using namespace PlayerCc; +using namespace std; + +vib_belt::vib_belt(const char* device, const char* hostname, int port) { + // initialize P array + this->P[0] = 'Z'; + for (int i = 1; i < 36; i++) + this->P[i] = 'P'; + ///////////////////// + cout << "done setting P array\n"; + + // set device name + if (device != NULL) + strcpy(this->devicename, device); + else + strcpy(this->devicename, "/dev/ttyACM0"); + + cout << "done setting devicename\n"; + + // set port and hostname + if (port != 0) { + cout << "setting port to " << port << endl; + this->port = port; + } + else { + cout << "setting port to 6665" << endl; + this->port = 6665; + } + + if (hostname != NULL) { + cout << "setting hostname to " << hostname << endl; + this->host = string(hostname); + } + else { + cout << "setting hostname to \"localhost\"" << endl; + this->host = string("localhost"); + } + + cout << "done setting port & host" << endl; + + cout << this->host << endl << this->port << endl; + + try{ + this->robot = new PlayerClient(this->host, this->port); + this->myranger = new RangerProxy(this->robot, 0); + } catch (PlayerError e){ + #ifndef NDEBUG + cerr << e << endl; + #endif + cerr << "Não foi possível conectar no robô " << endl; + cerr << "Possivelmente o arquivo cfg está incorreto." << endl; + this->exit(); + } + + robot->StartThread(); + // set robot and rangers + //this->robot(this->host, this->port); + //this->myranger(&this->robot, 0); +} + +bool vib_belt :: connect() { + this->fd = open(devicename, O_RDWR | O_NOCTTY | O_NONBLOCK); + + if (this->fd < 0) + return false; + + int res, i; + //struct terminos newtio; + struct termios newtio; + //struct sigaction saio; + struct sigaction saio; + char buf[255]; + + // Install the serial handler before making the device + saio.sa_handler = NULL; // signal_handler_IO; + sigemptyset(&saio.sa_mask); // saio.sa_mask = 0; + saio.sa_flags = 0; + saio.sa_restorer = NULL; + sigaction(SIGIO, &saio, NULL); + // Allow the process to receive SIGIO + fcntl(this-> + fd, F_SETOWN, getpid()); + // Make the fil descriptor asynchronous + fcntl(this->fd, F_SETFL, FASYNC); + // Set new port settings for canonical input processing + newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD; + newtio.c_iflag = IGNPAR; + newtio.c_oflag = 0; + newtio.c_lflag = 0; + newtio.c_cc[VMIN] = 1; + newtio.c_cc[VTIME] = 0; + + tcflush(this->fd, TCIFLUSH); + tcsetattr(this->fd,TCSANOW,&newtio); + + return true; +} + +char* vib_belt::getP() { + return this->P; +} + +bool vib_belt :: loop() { + // all writing operations are checked to see if they are working properly, in the case in which they aren't, the function will return false. + cout << "writing ... " << endl; + write(this->fd, (void*)this->getP(), 36); + cout << "reading1 ... " << endl; + //robot->Read(); //update proxies + + cout << "Rangers: " << this->myranger->GetRangeCount() << endl; + cout << "reading2 ... " << endl; + cout << "Rangers: " << this->myranger->GetRangeCount() << endl; + cout << "reading3 ... " << endl; + + for(int i = 0; i < this->myranger->GetRangeCount(); i++) { //print all lasers receiveds + cout << "entrei no for do loop" << endl; + if((int(this->myranger->GetRange(i) / 10)) == 0) + //cout << " " << this->myranger[i] << " "; //unidade + cout << " " << this->myranger->GetRange(i) << " "; //unidade + else if ((int(this->myranger->GetRange(i) / 100)) == 0) + cout << " " << this->myranger->GetRange(i) << " "; //dezena + else + cout << this->myranger->GetRange(i) << " "; //centena + + // if(SensorValue < Distance of Max. Vibration value)...elseif(SensorValue < Distance of moderate Vibration)... + if (this->myranger->GetRange(i) < 1.) + this->P[i+8] = 'A'; + else if(this->myranger->GetRange(i) < 1.5) + this->P[i+8] = 'B'; + else + this->P[i+8] = 'P'; + + if (this->myranger->GetRange(i) < 1.) + this->P[i+22] = 'A'; + else if (this->myranger->GetRange(i) < 1.5) + this->P[i+22] = 'B'; + else + this->P[i+22] = 'P'; + } + + //cout << "Qnt:" << this->myranger->GetRangeCount() << endl; + + //cout << "outra coisa" << endl; + cout << "entrei o loop" << endl; + return true; +} + +void vib_belt :: exit() { + close(this->fd); +} diff --git a/client/vib_belt/vib_belt.h b/client/vib_belt/vib_belt.h new file mode 100644 index 0000000..64315c6 --- /dev/null +++ b/client/vib_belt/vib_belt.h @@ -0,0 +1,46 @@ +#ifndef VIB_BELT_H +#define VIB_BELT_H + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#define BAUDRATE B9600 + +using namespace std; +using namespace PlayerCc; + +class vib_belt { +//private: +public: + char devicename[80], ch; + int fd; + int status; + string host; + int port; + PlayerClient *robot; + RangerProxy *myranger; + char P[36]; + // The arduino protocol for controlling the motors is 'z' to indicate de start + // of the information, 'A' for maximum vibration, 'B' for moderate and 'C' for low +public: + void signal_handler_IO(int); + + vib_belt(const char* = NULL, const char* = NULL, int = 0); + + char* getP(); + + bool connect(); + bool loop(); + void exit(); +}; + +#endif diff --git a/docs/Makefile b/docs/Makefile index 36bc533..e076afa 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,26 +1,177 @@ -##################################################### -# A small LaTeX Makefile -##################################################### +# Makefile for Sphinx documentation +# -CHAPTERS=doxygen manual/hardware_manual manual/software_manual manual/user_manual reports/2016 +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build -all: subdirs +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif -##################################################### +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . -.PHONY: subdirs +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext -subdirs: - @for i in $(CHAPTERS); do \ - (cd $$i; $(MAKE)); done - -##################################################### -##################################################### +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: - @for i in $(CHAPTERS); do \ - (cd $$i; $(MAKE) clean); done + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/tutos.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/tutos.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/tutos" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/tutos" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." -install: - @for i in $(CHAPTERS); do \ - (cd $$i; $(MAKE) install); done +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/docs/Makefile-latex b/docs/Makefile-latex new file mode 100644 index 0000000..36bc533 --- /dev/null +++ b/docs/Makefile-latex @@ -0,0 +1,26 @@ +##################################################### +# A small LaTeX Makefile +##################################################### + +CHAPTERS=doxygen manual/hardware_manual manual/software_manual manual/user_manual reports/2016 + +all: subdirs + +##################################################### + +.PHONY: subdirs + +subdirs: + @for i in $(CHAPTERS); do \ + (cd $$i; $(MAKE)); done + +##################################################### +##################################################### + +clean: + @for i in $(CHAPTERS); do \ + (cd $$i; $(MAKE) clean); done + +install: + @for i in $(CHAPTERS); do \ + (cd $$i; $(MAKE) install); done diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..95c7dde --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,260 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# tutos documentation build configuration file, created by +# sphinx-quickstart on Sat Jul 5 13:23:59 2014. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = 'Donnie Developer Manual' +copyright = '2018, Alexandre Amory' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0.0' +# The full version, including alpha/beta/rc tags. +release = '0.1' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['doxygen' 'papers' 'wiki' 'manual' 'reports'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +#html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'tutosdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ('index', 'donnie.tex', 'Donnie Developer Documentation', + 'Alexandre Amory', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'donnie.tex', 'Donnie Developer Documentation', + ['Alexandre Amory'], 1), + +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'tutos', 'tutos Documentation', + 'kotrfa', 'tutos', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..51d6a15 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,127 @@ + +========================== +Donnie Assistive Robot: Developer Manual +========================== + + +About Donnie +----------------- + +.. image:: ./source/getting_started/images/donnie-robot.png + :align: center + :alt: sempre use alt para descreve a imagem p um deficiente visual + +.. image:: ./source/getting_started/images/donnie-sim.png + :align: center + :alt: sempre use alt para descreve a imagem p um deficiente visual + +.. WARNING:: + + This document is for developers only. If you want to use and test Donnie, please refer to the `Donnie Assistive Robot: User Manual `_ + +Donnie is an assistive technology project, whose objective is to use robotics to facilitate programming teaching to visually impaired students. +It is divided in two main parts: + +- The construction and fine-tuning of the titular mobile robot, Donnie; +- The project's software stack, including an intuitive parser/interpreter and a robot simulation environment; + + + +The project is in its second version, developed in the Laboratório de Sistemas Autônomos (LSA_) of the Pontific Catholic University of Rio Grande do Sul (PUCRS), Brazil. + +.. _LSA: http://lsa-pucrs.github.io + +.. talk about LSA, link to the webpage + +.. toctree:: + :maxdepth: 2 + + source/getting_started/index + +Software Description +----------------- + +.. toctree:: + :maxdepth: 3 + + source/godonnie/index + source/player/index + source/stage/index + +Hardware Description +------------------------ + +.. toctree:: + :maxdepth: 3 + + source/building/index + source/rpi/index + source/arduino/index + +Additional Resources +--------------------- + +.. toctree:: + :maxdepth: 3 + + source/contributors/index + + +Papers +---------- + +If you are using Donnie and/or its software on your research projects, please cite our papers: + +.. code-block:: none + + @inproceedings{oliveira2017teaching, + title={Teaching Robot Programming Activities for Visually Impaired Students: A Systematic Review}, + author={Oliveira, Juliana Damasio and de Borba Campos, M{\'a}rcia and de Morais Amory, Alexandre and Manssour, Isabel Harb}, + booktitle={International Conference on Universal Access in Human-Computer Interaction}, + pages={155--167}, + year={2017}, + organization={Springer} + } + +.. code-block:: none + + @inproceedings{guilherme2017donnie, + title={Donnie Robot: Towards an Accessible And Educational Robot for Visually Impaired People}, + author={Guilherme H. M. Marques, Daniel C. Einloft, Augusto C. P. Bergamin, Joice A. Marek, Renan G. Maidana Marcia B. Campos, Isabel H. Manssour, Alexandre M. Amory}, + booktitle={Latin American Robotics Symposium (LARS)}, + year={2017} + } + + +Disclaimer +---------- + +Donnie and its software are protected under the MIT_ License: + +.. _MIT: http://opensource.org/licences/MIT + +.. code-block:: none + + Copyright 2018, Laboratório de Sistemas Autônomos + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in the + Software without restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, subject to the + following conditions: + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Feedback +-------- + +Don't hesitate to ask about additional info or the next guides, and also if you find some mistakes, please let us know. +Issues and push requests can be done on github_. + +.. _github: http://github.com/lsa-pucrs/donnie-assistive-robot-sw + diff --git a/docs/manual/hardware_manual/Tutorial-Configurando_imagem_Raspbian_na_Raspberry.docx b/docs/manual/hardware_manual/Tutorial-Configurando_imagem_Raspbian_na_Raspberry.docx new file mode 100644 index 0000000..4f6fe72 Binary files /dev/null and b/docs/manual/hardware_manual/Tutorial-Configurando_imagem_Raspbian_na_Raspberry.docx differ diff --git a/docs/manual/hardware_manual/Tutorial-Configurando_imagem_Raspbian_na_Raspberry.pdf b/docs/manual/hardware_manual/Tutorial-Configurando_imagem_Raspbian_na_Raspberry.pdf new file mode 100644 index 0000000..2647ba9 Binary files /dev/null and b/docs/manual/hardware_manual/Tutorial-Configurando_imagem_Raspbian_na_Raspberry.pdf differ diff --git a/docs/manual/software_manual/Makefile b/docs/manual/software_manual/eng/Makefile similarity index 100% rename from docs/manual/software_manual/Makefile rename to docs/manual/software_manual/eng/Makefile diff --git a/docs/manual/software_manual/godonnie.tex b/docs/manual/software_manual/eng/godonnie.tex similarity index 100% rename from docs/manual/software_manual/godonnie.tex rename to docs/manual/software_manual/eng/godonnie.tex diff --git a/docs/manual/software_manual/intro.tex b/docs/manual/software_manual/eng/intro.tex similarity index 100% rename from docs/manual/software_manual/intro.tex rename to docs/manual/software_manual/eng/intro.tex diff --git a/docs/manual/software_manual/main.tex b/docs/manual/software_manual/eng/main.tex similarity index 100% rename from docs/manual/software_manual/main.tex rename to docs/manual/software_manual/eng/main.tex diff --git a/docs/manual/software_manual/player.tex b/docs/manual/software_manual/eng/player.tex similarity index 100% rename from docs/manual/software_manual/player.tex rename to docs/manual/software_manual/eng/player.tex diff --git a/docs/manual/software_manual/ros.tex b/docs/manual/software_manual/eng/ros.tex similarity index 100% rename from docs/manual/software_manual/ros.tex rename to docs/manual/software_manual/eng/ros.tex diff --git a/docs/manual/software_manual/sample.bib b/docs/manual/software_manual/eng/sample.bib similarity index 100% rename from docs/manual/software_manual/sample.bib rename to docs/manual/software_manual/eng/sample.bib diff --git a/docs/manual/software_manual/pt-br/tutorial_pacotes_deb.docx b/docs/manual/software_manual/pt-br/tutorial_pacotes_deb.docx new file mode 100644 index 0000000..e675e0e Binary files /dev/null and b/docs/manual/software_manual/pt-br/tutorial_pacotes_deb.docx differ diff --git a/docs/source/arduino/index.rst b/docs/source/arduino/index.rst new file mode 100644 index 0000000..8c035ca --- /dev/null +++ b/docs/source/arduino/index.rst @@ -0,0 +1,24 @@ +.. _arduino: + +=============== +Arduino +=============== + +Introduction +------------- + +.. image:: ./images/arduino-shield.png + :align: center + :alt: sempre use alt para descreve a imagem p um deficiente visual + +explica o shield, e como conecta ele no arduino. colocar diagrama e descreve as pinagens. +como carregar o firmware + +Assembly the Arduino Part +------------- + +Arduino Firmware +------------- + +explicar brevemente a organizacao do firmware + diff --git a/docs/source/building/ArduinoShield.pdf b/docs/source/building/ArduinoShield.pdf new file mode 100644 index 0000000..31d0409 Binary files /dev/null and b/docs/source/building/ArduinoShield.pdf differ diff --git a/docs/source/building/RaspShield.pdf b/docs/source/building/RaspShield.pdf new file mode 100644 index 0000000..01396a7 Binary files /dev/null and b/docs/source/building/RaspShield.pdf differ diff --git a/docs/source/building/donnie-elet3.png b/docs/source/building/donnie-elet3.png new file mode 100644 index 0000000..5794857 Binary files /dev/null and b/docs/source/building/donnie-elet3.png differ diff --git a/docs/source/building/index.rst b/docs/source/building/index.rst new file mode 100644 index 0000000..a8ca67e --- /dev/null +++ b/docs/source/building/index.rst @@ -0,0 +1,109 @@ +.. _arduino: + +=============== +Building Your Donnie Robot +=============== + +Introduction +------------- + +This manual has all files required to understand how to build the Donnie's body with a 3D printer. + +Required Material +----------------- + +Donnie requires about 500g of PLA. We use PLA because its low retraction +factor in large pieces. + +Production Phase +---------------- + +1. The 3D printer requires the stl files, in the stl\_files folder. +2. We use `Slicer (1.2.9) `__ to slice and 3d + printing the robot. We use the following configs on slicer: + +- Infill: 20%; +- Layer height: 0.3mm; +- Without support (parts that need support have it in the model). + +Modifying Donnie's Body +----------------------- + +We used the Solidworks 2014 to model the robot. All the source files are +in the solidworks directory. + +Visualization +------------- + +You can visualize the 3D PDF files with `Adobe Reader +9 `__ or above. You just need to click in "Enable +3D View" when open the 3D PDF. + +.. figure:: screenshot.png + :alt: Meet Donnie !!! + + Meet Donnie !!! + +explica o shield, e como conecta ele no arduino. colocar diagrama e descreve as pinagens. +como carregar o firmware + +Assembly the Arduino Part +------------- +Donnie's PCB +============ + +This repository has all files related to Donnie's hardware (PCB design, +schematics, eletrical diagrams, gerber files, BOM files). Donnie has two +daugther boards (or 'shields'). One for the Arduino Mega (see ard-shield +dir) and the other for the Raspberry Pi (see rasp-shield dir). + +| The following image shows Donnie's brain and its electronics. +| |Meet Donnie Brain!!!| + +Manufacturing the boards +------------------------ + +Send the Gerber for manufacturing +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you just want to manufacture these boards as they are, we recommend +the following steps: + +1. Send the Gerber ZIP files + (`ard-shield `__ + and + `rasp-shield `__) + to manufacture to Seeedstudio. You should use the following tutorial + `Fusion PCB Order Submission + Guidelines `__ + +Assembly +~~~~~~~~ + +After you receive the PCBs, then follow these steps to assemble the +boards: + +1. First of all, separe and buy the components indicated in BOM file + (`ard-shield `__ and + `rasp-shield `__); +2. Print the PDF schemmatic and BOM file; +3. Place and weld the componnects in the PCB with the BOM's indicated + PART. + +Change the PCB Design +--------------------- + +If you want to change the PCB design, we recommend to use Eagle version +XYZ. + +.. |Meet Donnie Brain!!!| image:: donnie-elet3.png + +.. image:: ArduinoShield.pdf +.. image:: RaspShield.pdf + + +Arduino Firmware +------------- + +explicar brevemente a organizacao do firmware + diff --git a/docs/source/building/screenshot.png b/docs/source/building/screenshot.png new file mode 100644 index 0000000..757a91c Binary files /dev/null and b/docs/source/building/screenshot.png differ diff --git a/docs/source/contributors/index.rst b/docs/source/contributors/index.rst new file mode 100644 index 0000000..cfb1e2b --- /dev/null +++ b/docs/source/contributors/index.rst @@ -0,0 +1,19 @@ + +======================== +Donnie Contributors +======================== + +The list of contributors to this document. + + * `@Alexandre Amory `_ + + * @Roger + + * @Renan + + * @Marcelo + + * @Davi + + * `@Beltrano com webpage `_ + diff --git a/docs/source/getting_started/about.rst b/docs/source/getting_started/about.rst new file mode 100644 index 0000000..ec9de35 --- /dev/null +++ b/docs/source/getting_started/about.rst @@ -0,0 +1,22 @@ +.. _getting-started: + +============================== +About Donnie +============================== + +Robotics has been used to teach young students the basics of programming. However, most of the programming environments for kids are high visual, based on grab and drag blocks. Blind students or students with some visual disability cannot use these teaching resources. + +The Donnie project proposes an inclusive robotic programming environment which all students (with or without visual disabilities) can use. + +Donnie comes with two usage options: with the simulated and with the physical robots. It is recommend to start with simulation since it does not require building the robot. Moreover, the physical robot is functional, but still under test. + +Features +----------------- + +- Robot programming environment for young students with or without visual impairment; +- Assistive programming language called GoDonnie. GoDonnie is TTS and screen reader friendly; +- Integration with a Arduino-based robot with Player robotic middleware; +- Extension of Stage simulator to generate sound clues while the robot is moving; +- Software developed for the simulated robot is compatible with the real Donnie robot; + +The simulation is recommended if you want to known about Donnie but don't have the required resources to build your own Donnie robot. \ No newline at end of file diff --git a/docs/source/getting_started/build.rst b/docs/source/getting_started/build.rst new file mode 100644 index 0000000..8c10b2e --- /dev/null +++ b/docs/source/getting_started/build.rst @@ -0,0 +1,50 @@ +.. gaitech documentation master file, created by + sphinx-quickstart on Sun May 8 09:56:52 2016. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +.. _getting-started: + +================================== +How to Build Your Own Donnie Robot +================================== + +To build your own Donnie robot, please refer to the following repositories (github login and read access required): + +- `Donnie electronics `_ +- `Donnie 3D printing `_ + + +Install Donnie's Software on an Embedded Computer (Raspberry Pi) +---------------------------------------------------------------------- + +Once the eletronics and 3D printing are done, the operating system and Donnie's software must be installed in the robot's Raspberry Pi. + +Loading the Donnie Image into the Pi's SD Card +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The easiest way to setup the embedded computer is to use the pre-built image (comming soon!). +Please follow these steps to burn the SD card: + +.. code-block:: none + + wget xxxxxxxx.img + continue ... + + +Compile, Configure the OS, and Install the Donnie Image into the SD Card +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This option is for programmers experient with Raspberry Pi. + +Raspbian 8.0 (`Jessie `_) is the recommended OS distribution for the robot. +Log onto Donnie's embedded computer, open a terminal, and run the following to download and execute the software installation script: + +.. code-block:: none + + mkdir ~/donnie; cd ~/donnie + wget https://github.com/lsa-pucrs/donnie-assistive-robot-sw/raw/devel/install-rpi.sh + chmod +x ./install-rpi.sh + ./install-rpi.sh + +Experienced programmers can configure the same paramerters presented `here `_, for the Raspberry Pi. \ No newline at end of file diff --git a/docs/source/getting_started/index.rst b/docs/source/getting_started/index.rst new file mode 100644 index 0000000..821e5a9 --- /dev/null +++ b/docs/source/getting_started/index.rst @@ -0,0 +1,15 @@ + +=============== +Getting Started +=============== + +Before going into the tutorials, follow the instructions below to prepare your environment. + + +.. toctree:: + :maxdepth: 2 + + About Donnie + How to Install Donnie's Software + How to Build Your Own Donnie Robot + diff --git a/docs/source/getting_started/install.rst b/docs/source/getting_started/install.rst new file mode 100644 index 0000000..be70377 --- /dev/null +++ b/docs/source/getting_started/install.rst @@ -0,0 +1,101 @@ +.. _getting-started: + +================================== +How to Install Donnie's Software +================================== + +There are several ways to install Donnie's software environment: + +- `Run Donnie's Software from a Virtual Machine (VM)`_ +- `Install Donnie's Software with the Debian Package`_ +- `Build and Install Donnie's Software`_ + + +_`Run Donnie's Software from a Virtual Machine (VM)` +-------------------------------------------------- + +Download this VM file (comming soon!), with all the software pre-installed and ready to run. +The VM file can be run with a Virtualization tool such as `VirtualBox `_. + + +_`Install Donnie's Software with the Debian Package` +----------------------------------------------------- + +Ubuntu 14.04 (`Trusty Tahr `_) is the recommended OS distribution. For older computers or VMs, `Lubuntu `_ 14.04 or `Ubuntu Mate `_ 14.04 are recommended. + +Download the package (comming soon!) and execute the following steps in the terminal: + +- It is recommended to update your packages before the instalation: + +.. code-block:: bash + + sudo apt-get install update + +- To install, you can double-click the ".deb" package or run: + +.. code-block:: bash + + sudo dpkg -i donnie_1.0.0_amd64.deb + +- In case of missing dependencies, try: + +.. code-block:: bash + + sudo apt-get install -f + +- To uninstall: + +.. code-block:: bash + + sudo dpkg -r donnie + + +_`Build and Install Donnie's Software` +------------------------------------- + +Ubuntu 14.04 (`Trusty Tahr `_) is the recommended OS distribution. For older computers or VMs, `Lubuntu `_ 14.04 or `Ubuntu Mate `_ 14.04 are recommended. + +Open a terminal, download the installation script and execute it: + +.. code-block:: bash + + mkdir ~/donnie; cd ~/donnie + wget https://github.com/lsa-pucrs/donnie-assistive-robot-sw/raw/devel/install.sh + chmod +x ./install.sh + ./install.sh + +Configuring Donnie +^^^^^^^^^^^^^^^^^^^^^^^ + +The installation script composes a standard instalation that we believe is the most appropriate for the average user. +However, advanced parameters can be set if the user has experience with the appropriate tools. + +The build system is based on cmake, so experience with Linux, `make `_, and `cmake `_ is required. All the individual parts of Donnie's Software Stack are also based on CMake. These are the software parts that can be customized, each with its own set of parameters: + +- raspicam driver +- Player +- Stage +- Donnie Software + +Developers interested in customization might want to read the following files: + +- `install.sh `_: For desktop setup procedure; +- `setup.sh.in `_ +- `install-rpi.sh `_: For embedded computer (e.g. Raspberry Pi) setup procedure; +- `setup-rpi.sh.in `_ +- and all the *CMakeLists.txt* files + +Parameters for Donnie's Software +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following list explains Donnie's main compilation parameters: + +.. code-block:: none + + BUILD_DOCS OFF Generate Donnie's documents. + BUILD_DOXYGEN ON This is the default document in HTML, meant only for developers. + BUILD_DOXYGEN_PDF OFF The same document before, but in PDF. + BUILD_EXAMPLES OFF Build the examples for each part of Donnie. + BUILD_MANUAL OFF Build the manuals: software manual, hardware manual, user manual. + CMAKE_BUILD_TYPE Release | Debug Debug mode is for developers only ! + DOC_LANGUAGE en | pt-br | es The language used to build documents and the GoDonnie interpreter. Future work ! \ No newline at end of file diff --git a/docs/source/godonnie/index.rst b/docs/source/godonnie/index.rst new file mode 100644 index 0000000..49cf655 --- /dev/null +++ b/docs/source/godonnie/index.rst @@ -0,0 +1,24 @@ +.. _godonnie: + +=============== +Donnie Programming Environment +=============== + +Introduction +------------- + +.. image:: ./images/donnie.png + :align: center + :alt: sempre use alt para descreve a imagem p um deficiente visual + +explica brevemente, cita o artigo, mostra algum exemplo pronto. + +GoDonnie Programming Language +------------- + +manual da linguagem e eexemplos de uso + +GoDonnie Interpreter +------------- + +modos de operacao, exemplos de uso diff --git a/docs/source/player/index.rst b/docs/source/player/index.rst new file mode 100644 index 0000000..0771357 --- /dev/null +++ b/docs/source/player/index.rst @@ -0,0 +1,26 @@ +.. _player: + +=============== +Player Robotic Middleware +=============== + +Introduction +------------- + +explica brevemente, cita o artigo, mostra algum exemplo pronto. + +Software Organization +------------- + +o que um driver, interface, client, etc + +Explain the Cfg File +------------- + +fazer tipo um tutorial usando os Cfg do Donnie como exemplo + +Build a Cfg for Multiple Robots +------------- + +fazer tipo um tutorial passo a passo + diff --git a/docs/source/rpi/RPi.rst b/docs/source/rpi/RPi.rst new file mode 100644 index 0000000..9a32fe6 --- /dev/null +++ b/docs/source/rpi/RPi.rst @@ -0,0 +1,769 @@ +Making Raspberry Pi usable +========================== + +Introduction +---------------- + +After 8 months of using RPi, I decided to make second version of this tutorial for same +people as I'm - who looks for easy, understandable way to make RPi as +awesome as possible. Several things have changed since last realease of this tutorial, so I decided to rewrite some parts and also to delete some parts which are not necessary today. + +In this tutorial I will walk you through whole process of making from +Raspberry Pi secure, reliable, efficient, fast and easy to maintain +server for variable purposes as is FTP, web hosting, sharing... All +that thanks to Arch Linux ARM operating system. The device will be +"headless" - it means, there will be no fancy windows etc., just command +line. Don't be scared, I will walk you through and you'll thank me then +:) . You don't need some special knowledge about computers and linux +systems. + +What you get +------------ + +From "bare" RPi you'll get: + +- Safely to connect to your RPi from anywhere +- Possibility of hosting web pages, files, etc. +- Readable and reliable system (it will do what you want and nothing + more) + +What you will need +------------------ + +- Raspberry Pi (doesn't matter which model) with power supply +- SD Card as a main hardisk for RPi +- SD Card reader on computer with internet access +- Ethernet LAN cable or USB Wi-Fi bundle +- Other computer (preferably with linux, but nevermind if you use + Windows or Mac) +- Possibility to physically get to your router and know credentials to + login to it (or have contact to your network administrator :) ) +- Few hours of work + +What you don't need +------------------- + +- Monitor or ability to connect RPi to some monitor +- Keyboard or mouse connected to your RPi + +Start +----- + +So you have just bare RPi, SD card, power supply, ethernet cable +(RJ-45). So let's start! There are houndreds of guides, but I haven't +found them satisfaing. + +Installing Arch Linux ARM to SD card +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Go `here `__, choose installation and +make first 3 steps. That's it! You have done it. You have you Arch Linux +ARM SD card :) + +Little networking +~~~~~~~~~~~~~~~~~ + +I guess you probably have some of "home router" ("box with internet") +and when you want to connect e.g by Wi-Fi with your laptop or mobile +phone, it just connects (after inserting password). You need to test +first what happens, when you try to connect by ethernet cable, for +example with your laptop. Turn off Wi-Fi and check it. Did your computer +connects to the network (or even internet) as usuall? + +If yes, it is great! You can procced. It is what we need - we need RPi, +when it boots up, to automatically connect to the network. Then we will +able to connect to it. You will need one more thing to find out - which +IP address does router assign to you when you connect by cable - it is very +probable that RPi will get very similiar. Don't be afraid - it +is easy to get `IP address `_. On modern systems, +one command :) . + +Ok, now you have to insert SD card to RPi and connect it to your router +with ethernet cable and then turn RPi on by inserting power supply. The +diods start flashing. Now back to your computer and we will try to +connect it using **SSH**. SSH is just "magic power" which enables to +connect to another computer. + +RPi is already ready and waits for SSH connection. How to use SSH is supereasy - you will +find a tons of tutorials on the internet (keywords: how to use ssh). IP +address is the probably the one you assigned before. It will be +something like this: ``192.168.0.x``, ``10.0.0.14x`` or similar. Next +thing you need is username. It's just "root" (and password also). + +If your RPi haven't got this address (ssh is not working), than there +are two options. + +1. You will login to your router settings and find out list of all + connected devices with IP addresses and try them. +2. Use + `nmap `__ + to find active devices in your network. + +**Example** You have this address assigned: ``192.168.0.201``. Then you +have to type (in linux): ``ssh root@192.168.0.201``. + +You should now end up in RPi console. + +Enough of networking for now. We'll set a proper network configuration later in this guide, but first some *musthaves*. + + +First setup +----------- + +This is covered over the internet, so I will just redirect you. +`elinux `__ - from this guide +finish these parts (in RPi console): + +- Change root password +- Modify system files +- Mount extra partitions (if you don't know what it is, nevermind) +- Update system +- Install sudo +- Create regular user account + +My usuall procedure (which is strongly related to my needs!):: + + passwd # change root password to something important + rm -rf /etc/localtime # dont care about this + ln -s /usr/share/zoneinfo/Europe/Prague /etc/localtime # set appropriate timezone + echo "my_raspberry" > /etc/hostname # set name of your RPi + + useradd -m -aG wheel -s /usr/bin/bash common_user # + groupadd webdata # for sharing + useradd -M -aG webdata -s /usr/bin/false nginx + usermod -aG webdata common_user + + visudo # uncomment this line: %wheel ALL=(ALL) ALL + + pacman -Syu + +That's enough for now. Logout from ssh (type ``exit``) and connect +again, but as user who was created. Similiar to previous: +``ssh common_user@ip.address``. From now, you'll need to type "sudo" in +front of every command, which is possibly danger. I will warn you in +next chapter. + +We must be sure that after reboot RPi will reconnect. + + +Now try if you are connected to the internet. Type ``ping 8.8.8.8``. If +you don't see ``ping: unknown host 8.8.8.8`` it's good! If you do, your +internet connection is not working. Try to find out why - unfortunately +it is not possible to solve it here. + +**Warning** Try also ``ping google.com``. It may not work even pinging +8.8.8.8 worked. The reason is bad DNS servers (doesn't matter what it +is). To solve this you have to find "DNS servers of your IPS". Try to +google it. If you find them, add them to ``resolv.conf``. + +Reboot you rpi using ``systemctl reboot``. You must be able to connect +to it again after one minute. If not, somthing is wrong... In that case, +you need to find out why connection stoped working - if you have +keyboard and monitor, you can repair it. If not, you can try to edit +mistake on other computer by inserting SD card. Otherwise, reinstall... + +Installing some sugar candy +--------------------------- + +For our purpouses we will install usefull things, which will help as +maintaing the system. So, run this: +``pacman -S vim zsh wget ranger htop lynx`` + +Do you see: + +:: + + error: you cannot perform this operation unless you are root. + +Then you need to type ``sudo pacman -S ...``. I will not write it in +future and it is not in other guides. So sometimes you might be confused +whel you'll read some tutorials and autor implicitly use sudo without +mentioning it. + +We will also need these in next chapters: +``pacman -S nginx sshguard vsftpd`` + +You can notice that is really few packages! And thats true! Isn't it +great? No needs of tons of crap in your device. + +What are these? Just short summary - you can find more about it in +manual pages (``man ``) or find something usefull on +the internet. \* **vim** - powerfull text editor (that's what you will +do 99% of time). First few *days* are horrible, but keep using it :) . +\* **zsh** - doesn't matter. Just install it and install +`this `__ \* **wget** - just +for downloading things without browser \* **ranger** - file manager (you +can browse files, folders...) \* **htop** - task manager - you can see +what tasks are running, how much CPU/MEM is used, kill processes and so +on \* **lynx** - browser - no kidding :) + +Some configurations +------------------- + +I assume you installed ``zsh`` with ``oh-my-zsh`` (changed your shell) +and also vim. You are connected as created user (from now, I will name +him **bob**). You are in Bob's home directory - check it with typing +``pwd``. It will print ``/home/bob``. + +Make vim usable +~~~~~~~~~~~~~~~ + +Edit .vimrc file: ``vim .vimrc`` and insert this: + +:: + + syntax on + set number + set ruler + set nocompatible + set ignorecase + set backspace=eol,start,indent + set whichwrap+=<,>,h,l + set smartcase + set hlsearch + set incsearch + set magic + set showmatch + set mat=2 + set expandtab + set smarttab + set shiftwidth=4 + set tabstop=4 + set lbr + set tw=500 + set ai + set si + set wrap + set paste + set background=dark + vnoremap * :call VisualSelection('f') + vnoremap # :call VisualSelection('b') + +it will customize vim a bit, so it will be easier to edit files in it. + +Journaling +~~~~~~~~~~ + +Journaling is one of the most important things you need to have. It just +record everything systemd does. It is part of ``systemd`` quite +customizable. We will save journals in memory, because of limited wear +of SD cards. We will also compress them and then limit size for them on +40 MB. + +Open file ``/etc/system/journal.conf`` and uncomment these lines: + +:: + + [Journal] + Storage=volatile + Compress=yes + ... + RuntimeMaxUse=40M + +Network configuration +--------------------- + +For reasons I will mention in future, we need to set RPi to connect with +**static ip**. This will assure that the IP address of RPi will be still +the same and you can connect it. Right now is probably getting +automatically assigned IP address from router (it's called **dhcp**). + +We will use ``systemd-networkd``. + +Type ``ip addr``. It should shows something like this: + +:: + + 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default + link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 + inet 127.0.0.1/8 scope host lo + valid_lft forever preferred_lft forever + 2: ifb0: mtu 1500 qdisc noop state DOWN group default qlen 32 + link/ether 22:2b:20:5b:8e:b0 brd ff:ff:ff:ff:ff:ff + 3: ifb1: mtu 1500 qdisc noop state DOWN group default qlen 32 + link/ether 6a:68:fb:64:2f:c3 brd ff:ff:ff:ff:ff:ff + 4: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 + link/ether b8:27:eb:2d:25:18 brd ff:ff:ff:ff:ff:ff + inet 192.168.0.201/24 brd 192.168.0.255 scope global eth0 + valid_lft forever preferred_lft forever + +you are interested just in name **eth0**. If it is there, it is ok. In +future versions of system it can change to something other, for example +*enp0s1*. Don't be afraid of it and just use that instead in next +chapters. + +In this part you'll need to get address of your router. `How to obtain +it `__? + +And how to choose static address? As you know your +router is assigning IP address automatically (it is called DHCP). But +not randomly in full range. It has some range of IP addresses which it +can assign. Standard is this: router has standard IP adress +``192.168.0.1`` and assign addresses from ``192.168.0.2`` to +``192.168.0.254``. Second standard is ``10.0.0.138`` for router and it +assignes addresses from ``10.0.0.139`` to ``10.0.0.254``. But it *can* +be anything else. + +Interesting - and what the hell should you do that? I suggest to set one +the address on the end from this range. You can notice, that my "eth0" +has IP address ``192.168.0.201``. + +Open this file ``/etc/systemd/network/ethernet_static.network`` (how? +just use ``vim`` as in the previous - but don't forgot to use ``sudo`` +in front of ``vim``, or you'll not be able to save it!) and paste this: + +:: + + [Match] + Name=eth0 + + [Network] + Address=the.static.address.rpi/24 + Gateway=your.router.ip.address + +my example: + +:: + + [Match] + Name=eth0 + + [Network] + Address=192.168.0.111/24 + Gateway=192.168.0.1 + +Now you need to remove old non-static default profile ``/etc/systemd/network/eth0.network``. Move it to your home folder just to be safe if something didn't work. + +Try to restart RPi and try to SSH again. If you just can't connect, try to find out if RPi hadn't connected at all or it just doesn't use IP specified IP address (try to ssh to old IP, look into your router DHCP table, nmap...). If you want to get it back, just turn off RPi (plug off the power cable), take out SD card, plug in to your PC, move ``eth0.network`` from home directory to ``/etc/systemd/network/``, turn RPi back and try it again. + +If you successfuly connected, check how is ``systemd-networkd`` doing. To find out, type: ``systemctl status systemd-networkd``. Does it +shows "active (running)" and something like ``gained carrier``? + +:: + + â systemd-networkd.service - Network Service + Loaded: loaded (/usr/lib/systemd/system/systemd-networkd.service; enabled) + Active: active (running) since Wed 2014-06-11 18:42:13 CEST; 2 weeks 1 days ago + Docs: man:systemd-networkd.service(8) + Main PID: 213 (systemd-network) + Status: "Processing requests..." + CGroup: /system.slice/systemd-networkd.service + ââ213 /usr/lib/systemd/systemd-networkd + + Jun 17 17:52:01 smecpi systemd-networkd[213]: eth0: lost carrier + Jun 17 17:52:02 smecpi systemd-networkd[213]: eth0: gained carrier + + +Timesynchronization +------------------- + +You've maybe noticed that time is quite weird on your RPi. It is beacuse +it does not have real hardware clock. Every time RPi is waken up, it +thinks that is June 1970. You don't have to care about it, but after +boot it would be fine that time is correctly set. You can do it by using +really great part of ``systemd``. Go ahead and check service that +takes care about that: ``systemctl status systemd-timesyncd``. + +Configuring SSH +------------------- + +We will open RPi to world and in that case we need to secure it a bit. +Service, which takes care about SSH is called ``sshd``. "Where" it is? +It is runned by systemd, so ``systemctl status sshd`` will show you some +info :). We will configure it a bit. This is not necessary, but highly +recommended! Brutal force attacks are really common (hundreds every day +on my little unimportant server). + +Open file ``/etc/ssh/sshd_config`` and edit or add these lines as +follows: + +:: + + Port 1234 + PermitRootLogin no + PubkeyAuthentication yes + +that't enough. Restart sshd ``systemctl restart sshd``. + +Since now, you cannot login as a root by ssh and thats good. Also - we +changed the port of ssh. Think about "port" as a tunnel, which is used +for ssh. There are about 60 thousands of them and you can choose +whatever you want. As default there is port **22** used for ssh. We now +changed that to (example) 1234. It is because on port 22 there is to big +chance that someone will try to brutal force your credentials. + +Since now, only ``ssh bob@ipadress`` is not enough. You will have to add +port which should be used (in default is assumed port 22). +``ssh -p 1234 bob@ip.address`` will do it for you :) . + +If you want to be really safe, the next thing you want to do is set up ``sshguard``. More about it +`here `__. You don't need +more :) . Just remember to use your port (in my case 1234) for settings. Personally I stopped to use it, since just changing port what SSH use was enough to reduce uninvited connections. + +It is anoying still typing same username and password when we want to +connect to RPi. And now, we have to add "-p 1234" also. We will make it +automatic. `Here `__ is quite +good guide how to do it. On PC from which you are connecting (no RPi), +edit ``~/.ssh/config`` to this: + +:: + + Host my_superpc + HostName ipaddressofRPi + IdentityFile /home/yourusername/.ssh/name_of_identityfile + User bob + port 1234 + +since now, when you wan't to connect to RPi you can just type +``ssh my_superpc`` and it will take care about rest. + +**Screen** + +You can live without that, but you shouldn't! It makes you +more productive and you don't need to be afraid of some mishmash caused +by accidently closing terminal during update or lossing connection. +Learn more about what the screen is +(`here `__, +`here `__ and +`here `__), +install it (``pacman -S screen``), use it and love it. + +It can be handy to automatically ssh into screen sesion. For that I use +this command (from PC I want to connect to RPi): + +``ssh my_superpc -t screen -dRS "mainScreen"``. You can make some alias +to something shorter (for example adding this to +``alias ssh_connect_RPI="ssh my_superpc -t screen -dRUS mainScreen"`` +in .zshrc). Now all you need to do is type ``ssh_connect_RPI`` - it here +is now screen created, it will create new one. If it is, it will attach +it. + +Speeding RPi up +---------------- + +Arch Linux ARM for RPi is prepared to be tweaked. And now it is possible +to speed RPi up by overclocking it's processor without avoiding your +waranty. How to do it? Just edit file ``/boot/config.txt`` and find this +part: + +:: + + ##None + arm_freq=700 + core_freq=250 + sdram_freq=400 + over_voltage=0 + +now comment it out. That means to add "**#**\ " in front of every line. +From now, it will be treated as text and not command. It will look like +this: + +:: + + ##None + #arm_freq=700 + #core_freq=250 + #sdram_freq=400 + #over_voltage=0 + +and now uncoment this: + +:: + + ##Turbo + arm_freq=1000 + core_freq=500 + sdram_freq=500 + over_voltage=6 + +After next boot your RPi will be able to get even to the 1000 MHz. That +means it is faster. + +Other tweaks of /boot/config.txt +-------------------------------- + +Since you don't need any of gpu memory - which cares about shiny things +like windows etc., you can disable it in favor of the rest of memory +which we use. Don't do this if you want to use monitor. + +:: + + gpu_mem=16 + #gpu_mem_512=316 + #gpu_mem_256=128 + #cma_lwm=16 + #cma_hwm=32 + #cma_offline_start=16 + +Making RPi visible from outside +-------------------------------- + +Now we need to configure access from outside. You will need to configure +you router. You have to make a "port forwarding". Remember port from +ssh? I told you to think about them as a tunnels. These tunnels are also +handy when you need to find out what is on there end. + +What we will do here is this: We want to be able from anywhere on the +internet connect to our RPi server. + +Example? ``ssh -p 1234 bob@what.the.hell.is.here``. You know? There is +definetely not your local address (the one with 192.168...). There must +be your "public" IP address (more about this in **Domains** - take a +look there). But this public address points to your router (if you are +lucky). Where does it go next? + +With every request there is also a port. With command ``ssh smt``, you +are sending username, port (standard 22, if not otherwise stated) and IP +address. Ip address redirect it to router. Now router takes **port** and +looks to it's internal database. In this database are pairs: **port** - +**internal\_ipaddress**. For some port there is IP address, which it +redirects to. In another worlds: if router gets some request from +specific port (say, 1234) and it has in it's database IP address + +to which it has to redirect, it redirects this request there. In our +case, we need to redirect these ports we want (for example 1234 for ssh) +to RPi. So find a port forwarding settings for your router +(`this `__ might be helpful) and set there port +forward from port you setted for ssh to RPi. You can check if your port +is open (it means it accepts requests +`here `__. + +Since now, you can ssh from anywhere. + +Webserver +---------- +Setting up nginx +~~~~~~~~~~~~~~~~ + +Similiar to ``ssh`` handling *sshish* requests, Nginx is handling almost +everything else and even... **WebServers**! Install nginx with +``pacman -S nginx``. For security reasons create special user for it, +for example using: ``useradd -m -G wheel -s /usr/bin/zsh nginx`` and +also group ``groupadd webdata``. Now create some folder for it. It can +be ``mkdir /var/www/`` and now make them owners +``chown nginx:webdata /var/www``. Of course, enable and start nginx. + +``systemctl enable nginx``. It will start after boot. + +Now port forward port number 80 to RPi on your router. + +Open ``/etc/nginx/nginx.conf``, it can looks like this: + +:: + + user nginx; + worker_processes 1; + + error_log /var/log/nginx/error.log warn; + + events { + worker_connections 1024; + } + + http { + include mime.types; + default_type application/octet-stream; + server_names_hash_bucket_size 64; + + sendfile on; + + keepalive_timeout 15; + + server{ + listen 80; + server_name ~^xxx.xxx.xxx.xxx(.*)$; + + location / { + root /var/www/$1; + index index.html index.htm; + } + } + + } + +next, create ``/var/www/test/index.html``: + +:: + + + + Sample "Hello, World" Application + + + + + + + +
+

Sample "Hello, World" Application

+
+ +

This is the home page for the HelloWorld Web application.

+

To prove that they work, you can execute either of the following links: +

+ + + + +where xxx.xxx.xxx.xxx should be your public address. This will do this: +when you type in your browser "youripaddress/test:80", you should see +index Hello world example. Try that without ``:80`` - it will do the +same! Default port for webpages is **80** (similiar to 22 for SSH). So +it can be omited. + +FTP +^^^ + +This will cover the most easy solution for FTP. Don't use this +configuration in real, just for test purpouses. If you didn't download +``vsftp``, do it now by ``pacman -S vsftp``. Now we will create some +directory where all files and users will end up after connecting. Let it +be in ``/var/www/test``. Now edit ``/etc/vsftpd.conf`` and add on the +top this line: + +:: + + anon_root=/var/www/test + +and make sure that this line is uncommented: + +:: + + anonymous_enable=YES + +and just start it: ``systemctl start vsftpd``. + +Now we'll tell nginx about that. Add this to servers confs in +``/etc/nginx/nginx.conf``. + +:: + + server{ + listen 80; + server_name ~^123.123.32.13(.*)$; + location / { + ssi on; + root /var/www/$1; + index index.html index.htm; + } + } + +where you need to replace IP address in ``server_name`` directive to +your public IP. + +What this little configuration does? It's simple. Every time you type to +your brower your IP address and somthing behind it, it will transfer you +to this "something" in /var/www/. + +**Example** I created index.html here ``/var/www/example/index.html``. I +now type ``123.123.32.13/test`` to my browser and voila! + +This nginx configuration isn't neccessary in our ftp example (it could +be simpler), but I just like it... + +You can now connect to ftp by typing this in your browser: +``ftp://your_ip_address`` or use your favorite FTP client (e.g. +``filezilla``). + +**CAUTION** - again, don't use this settings as default. There are great +guides on the internet how to grant access only some users, password +protected etc. + + + +System analyzing and cleaning +----------------------------- + +Use your friend ``systemd-analyze``. It will show you which units +load really long time. Also ``systemctl status`` is great for finding failed +units. + +Disable things that you dont need +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +I guess you don't use ipv6 (if you don't know what it is, you don't need +it :D). ``systemctl disable ip6tables``. In case you use sshguard, you +need also edit file ``/cat /usr/lib/systemd/system/sshguard.service`` +and from **Wants** delete ``ip6tables.service``. + +Usefull utilites +---------------- + +Simple to use, just install them and run: + +- nmon - for internet usage +- htop - for disk usage + +Torrents +~~~~~~~~ + +Your RPi is maybe running 24/7, so why not to use it for torrents? But +how, when there is no GUI? It's pretty simple. We will use transmission +- popular torrent client. Install it by ``pacman -S transmission-cli`` +Installation should create a new user and group, called transmission. To +check that, you can take a look to ``/etc/passwd`` and ``/etc/group``. +``transmission`` will be runned by ``systemd``. Let's see it it's +service file is configured properly. Check +``/usr/lib/systemd/system/transmission.service``: + +:: + + [Unit] + Description=Transmission BitTorrent Daemon + After=network.target + + [Service] + User=transmission + Type=notify + ExecStart=/usr/bin/transmission-daemon -f --log-error + ExecReload=/bin/kill -s HUP $MAINPID + + [Install] + WantedBy=multi-user.target + +``User=transmission`` is important here (for security reasons). Next +thing we need to do is check, if transmission has place where it will +live. By default it is in ``/var/lib/transmission(-daemon)``. In this +dir should be also config file ``settings.json``. There lays +configuration for it.Edit it ass you wish. It is covered +`here `__ and +`here `__. Maybe +you'll need to forward ports as we did in previous chapters, you should +make that again without problems :) . No we can run ``transmission`` +daemon by ``systemctl start transmission``. Now you can give it commands +using transmission-remote . The most usefull (and that's all I need to +know and use :) ) are these: + +- ``transmission-remote -a "magnetlink/url"`` - adds torrent and + starts download it +- ``transmission-remote -l`` - list all torrents that are + currently running + +files should be stored in ``/var/lib/transmission/Downloads``. It can be +configured in config file :) . + +Backups +------- + +For backups I choosed ``rdiff-backup``. It's so stupid but works +(almost) as expected. More about it's usage you can find in it's manual +pages. For my example I'll redirect you to dir with configs in this +repo. These are inserted to ``cron`` (you have it by default installed) +to do SSH backup every day in 4AM. If I'm on local network I also do +backup to my disc on other PC. + +Final +----- + +That's all for now! I will see if this is used by someone and than I +will see if I will continue. + +Troubleshooting +----------------- + +- RPi don't boot - unplug everything from USB ports (there may be not + enough of power to boot up and supply USB) diff --git a/docs/source/rpi/donnie.rst b/docs/source/rpi/donnie.rst new file mode 100644 index 0000000..27aa3ac --- /dev/null +++ b/docs/source/rpi/donnie.rst @@ -0,0 +1,27 @@ + + + +============================================= +Installing Donnie +============================================= + + +How to install the driver and its depedencies +----------------------------- + +- where/how to download +- how to configure it +- how to install its depedencies +- how to install software depedencies and additional required nodes +- provide a script to install it all at once + +Known limitations +----------------------------- + +describe here any known limitation of the software so that the next student is aware of it. + +How to test it +----------------------------- + +- basic testing to see if the is procedure working on the RPi + diff --git a/docs/source/rpi/index.rst b/docs/source/rpi/index.rst new file mode 100644 index 0000000..b35cfce --- /dev/null +++ b/docs/source/rpi/index.rst @@ -0,0 +1,15 @@ +.. _rpi: + +=============== +Setting Up the Raspberry Pi +=============== + + +.. toctree:: + + Installing the OS + Setting Up the OS + Installing Donnie + Hooking Up Peripherals to the Rpi board + Setup Video streamming