diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..9c9ddbc81d445cd3643a06eed8e9293803370495 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,85 @@ +# Pre-requisites about cmake itself +CMAKE_MINIMUM_REQUIRED(VERSION 2.4) + +if(COMMAND cmake_policy) + cmake_policy(SET CMP0005 NEW) + cmake_policy(SET CMP0003 NEW) +endif(COMMAND cmake_policy) + +# The project name and the type of project +PROJECT(comm) + +SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin) +SET(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib) +SET(CMAKE_INSTALL_PREFIX /usr/local) + +IF (NOT CMAKE_BUILD_TYPE) + SET(CMAKE_BUILD_TYPE "DEBUG") +ENDIF (NOT CMAKE_BUILD_TYPE) + +SET(CMAKE_C_FLAGS_DEBUG "-g -Wall") +SET(CMAKE_C_FLAGS_RELEASE "-O3") + +ADD_SUBDIRECTORY(src/) +ADD_SUBDIRECTORY(test/) + +FIND_PACKAGE(Doxygen) + +FIND_PATH(IRI_DOC_DIR doxygen.conf ${CMAKE_SOURCE_DIR}/doc/iri_doc/) +IF (IRI_DOC_DIR) + ADD_CUSTOM_TARGET (doc ${DOXYGEN_EXECUTABLE} ${CMAKE_SOURCE_DIR}/doc/iri_doc/doxygen.conf) +ELSE (IRI_DOC_DIR) + ADD_CUSTOM_TARGET (doc ${DOXYGEN_EXECUTABLE} ${CMAKE_SOURCE_DIR}/doc/doxygen.conf) +ENDIF (IRI_DOC_DIR) + +ADD_CUSTOM_TARGET (distclean @echo cleaning cmake files) + +IF (UNIX) + ADD_CUSTOM_COMMAND( + COMMENT "distribution clean" + COMMAND make ARGS clean + COMMAND rm ARGS -rf ${CMAKE_SOURCE_DIR}/build/* + + TARGET distclean + ) +ELSE(UNIX) + ADD_CUSTOM_COMMAND( + COMMENT "distclean only implemented in unix" + TARGET distclean + ) +ENDIF(UNIX) + +ADD_CUSTOM_TARGET (uninstall @echo uninstall package) + +IF (UNIX) + ADD_CUSTOM_COMMAND( + COMMENT "uninstall package" + COMMAND xargs ARGS rm < install_manifest.txt + + TARGET uninstall + ) +ELSE(UNIX) + ADD_CUSTOM_COMMAND( + COMMENT "uninstall only implemented in unix" + TARGET uninstall + ) +ENDIF(UNIX) + + +IF (UNIX) + SET(CPACK_PACKAGE_FILE_NAME "iri-${PROJECT_NAME}-dev-${CPACK_PACKAGE_VERSION}${DISTRIB}${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}") + SET(CPACK_PACKAGE_NAME "iri-${PROJECT_NAME}-dev") + SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Part of IRI-laboratory libraries. More information at http://wikiri.upc.es/index.php/Robotics_Lab") + SET(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) + SET(CPACK_GENERATOR "DEB") + SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "labrobotica@iri.upc.edu") + SET(CPACK_SET_DESTDIR "ON") # Necessary because of the absolute install paths + + INCLUDE(CPack) +ELSE(UNIX) + ADD_CUSTOM_COMMAND( + COMMENT "packaging only implemented in unix" + TARGET uninstall + ) +ENDIF(UNIX) + diff --git a/Findsegway_rmp_400.cmake b/Findsegway_rmp_400.cmake new file mode 100644 index 0000000000000000000000000000000000000000..767d062b06efe438545b84c0c8998d86c95b9277 --- /dev/null +++ b/Findsegway_rmp_400.cmake @@ -0,0 +1,20 @@ +FIND_PATH(segway_rmp_400_INCLUDE_DIR segway_RMP400.h segway_RMP400_exceptions.h /usr/include/iridrivers /usr/local/include/iridrivers) + +FIND_LIBRARY(segway_rmp_400_LIBRARY + NAMES segway_rmp_400 + PATHS /usr/lib /usr/local/lib /usr/local/lib/iridrivers) + +IF (segway_rmp_400_INCLUDE_DIR AND segway_rmp_400_LIBRARY) + SET(segway_rmp_400_FOUND TRUE) +ENDIF (segway_rmp_400_INCLUDE_DIR AND segway_rmp_400_LIBRARY) + +IF (segway_rmp_400_FOUND) + IF (NOT segway_rmp_400_FIND_QUIETLY) + MESSAGE(STATUS "Found Segway RMP400 driver: ${segway_rmp_400_LIBRARY}") + ENDIF (NOT segway_rmp_400_FIND_QUIETLY) +ELSE (segway_rmp_400_FOUND) + IF (segway_rmp_400_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find segway RMP200 driver") + ENDIF (segway_rmp_400_FIND_REQUIRED) +ENDIF (segway_rmp_400_FOUND) + diff --git a/ReadMe.txt b/ReadMe.txt new file mode 100644 index 0000000000000000000000000000000000000000..d598803afb1927a434e90332e4479694a76c55ec --- /dev/null +++ b/ReadMe.txt @@ -0,0 +1,19 @@ +Copyright (C) 2009-2010 Institut de Robòtica i Informà tica Industrial, CSIC-UPC. +Author cetto (cetto@iri.upc.edu) +All rights reserved. + +This file is part of Segway RMP 400 driver library +Segway RMP400 driver library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see <http://www.gnu.org/licenses/> + + diff --git a/doc/doxygen.conf b/doc/doxygen.conf new file mode 100644 index 0000000000000000000000000000000000000000..347af2ef86bf4786d49b13d48c12146b0d001b01 --- /dev/null +++ b/doc/doxygen.conf @@ -0,0 +1,251 @@ +# Doxyfile 1.5.5 + +@INCLUDE_PATH = ../doc/ +@INCLUDE = doxygen_project_name.conf + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NUMBER = +OUTPUT_DIRECTORY = ../doc +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = NO +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +TYPEDEF_HIDES_STRUCT = NO +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ../src \ + ../doc/main.dox +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.c \ + *.h \ + *.cpp +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = *.tab.c \ + *.tab.h \ + lex* \ + *glr.h \ + *llr.h \ + *glr.c \ + *llr.c \ + *general.h +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = ../src/examples +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = ../doc/images +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +HTML_DYNAMIC_SECTIONS = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4 +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = _USE_MPI=1 +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = NO +INCLUDED_BY_GRAPH = NO +CALL_GRAPH = YES +CALLER_GRAPH = YES +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = NO +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 2 +DOT_TRANSPARENT = YES +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/doc/doxygen_project_name.conf b/doc/doxygen_project_name.conf new file mode 100644 index 0000000000000000000000000000000000000000..c16199478444307494a28c86170d0552fc303278 --- /dev/null +++ b/doc/doxygen_project_name.conf @@ -0,0 +1 @@ +PROJECT_NAME = "Segway RMP400 driver" diff --git a/doc/main.dox b/doc/main.dox new file mode 100644 index 0000000000000000000000000000000000000000..a7afebb8613a1de25b9d1b5d5b027a6a52df3eec --- /dev/null +++ b/doc/main.dox @@ -0,0 +1,107 @@ +/*! \mainpage segway RMP400 driver + + \section Introduction + + \subsection Pre-Requisites + + This package requires of the following libraries and packages + - <A href="http://www.cmake.org">cmake</A>, a cross-platform build system. + - <A href="http://www.doxygen.org">doxygen</a> and + <A href="http://www.graphviz.org">graphviz</a> to generate the documentation. + - stdc++, + . + + Under linux all of these utilities are available in ready-to-use packages. + + Under MacOS most of the packages are available via <a href="http://www.finkproject.org/">fink</a>. <br> + + \subsection Compilation + + Just download this package, uncompress it, and execute + - cd build + - cmake .. + . + to generate the makefile and then + - make + . + to obtain the shared library (in this case called <em>iriutils.so</em>) and + also all the example programs. + + The <em>cmake</em> only need to be executed once (make will automatically call + <em>cmake</em> if you modify one of the <em>CMakeList.txt</em> files). + + To generate this documentation type + - make doc + . + + The files in the <em>build</em> directory are genetated by <em>cmake</em> + and <em>make</em> and can be safely removed. + After doing so you will need to call cmake manually again. + + \subsection Configuration + + The default build mode is DEBUG. That is, objects and executables + include debug information. + + The RELEASE build mode optimizes for speed. To build in this mode + execute + - cmake .. -DCMAKE_BUILD_TYPE=RELEASE + . + The release mode will be kept until next time cmake is executed. + + \subsection Installation + + In order to be able to use the library, it it necessary to copy it into the system. + To do that, execute + + - make install + . + + as root and the shared libraries will be copied to <em>/usr/local/lib/iriutils</em> directory + and the header files will be copied to <em>/usr/local/include/iriutils</em> dierctory. At + this point, the library may be used by any user. + + To remove the library from the system, exceute + - make uninstall + . + as root, and all the associated files will be removed from the system. + + \section Customization + + To build a new application using these library, first it is necessary to locate if the library + has been installed or not using the following command + + - FIND_PACKAGE(library_name REQUIRED) + + In the case that the package is present, it is necessary to add the header files directory to + the include directory path by using + + - INCLUDE_DIRECTORIES(${library_name_INCLUDE_DIR}) + + Finally, it is also nevessary to link with the desired libraries by using the following command + + - TARGET_LINK_LIBRARIES(<executable name> ${library_name_LIBRARY}) + . + + \section License + + This package is licensed under a + <a href="http://www.gnu.org/licenses/lgpl.html"> + LGPL 3.0 License</a>. + + \section Disclaimer + + This is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ffb000b2648c7ce6d50b9b4365536bfdd1817f88 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,32 @@ +# edit the following line to add all the source code files of the library +SET(sources segway_RMP400.cpp segway_RMP400_exception.cpp) +# edit the following line to add all the header files of the library +SET(headers segway_RMP400.h segway_RMP400_exception.h) + +# edit the following line to find the necessary packages +FIND_PACKAGE(iriutils REQUIRED) +FIND_PACKAGE(comm REQUIRED) +FIND_PACKAGE(segway_rmp_200 REQUIRED) + +# edit the following line to add the necessary include directories +INCLUDE_DIRECTORIES(.) +INCLUDE_DIRECTORIES(${iriutils_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${comm_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${segway_rmp_200_INCLUDE_DIR}) + +ADD_LIBRARY(segway_rmp_400 SHARED ${sources}) + +#edit the following line to add the necessary system libraries (if any) +TARGET_LINK_LIBRARIES(segway_rmp_400 ${iriutils_LIBRARY}) +TARGET_LINK_LIBRARIES(segway_rmp_400 ${comm_LIBRARY}) +TARGET_LINK_LIBRARIES(segway_rmp_400 ${segway_rmp_200_LIBRARY}) + +INSTALL(TARGETS segway_rmp_400 + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib/iridrivers + ARCHIVE DESTINATION lib/iridrivers +) + +INSTALL(FILES ${headers} DESTINATION include/iridrivers) + +INSTALL(FILES ../Findsegway_rmp_400.cmake DESTINATION ${CMAKE_ROOT}/Modules/) diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..16a8a78939bf71849c7f161a9eafb39824d43672 --- /dev/null +++ b/src/examples/CMakeLists.txt @@ -0,0 +1,6 @@ +# edit the following line to add the source code for the example and the name of the executable +ADD_EXECUTABLE(test_segwayRMP400 test_segwayRMP400.cpp) +# edit the following line to add the necessary libraries +TARGET_LINK_LIBRARIES(test_segwayRMP400 ${segway_rmp_200_LIBRARY} segway_rmp_200) + + diff --git a/src/examples/test_segwayRMP400.cpp b/src/examples/test_segwayRMP400.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff1826293e98a73a17ebb56fc5ca3d0aac7076eb --- /dev/null +++ b/src/examples/test_segwayRMP400.cpp @@ -0,0 +1,75 @@ +#include "segway_RMP400.h" +#include <iostream> + +void wait() +{ +// std::puts("Press any key to continue..."); +// std::getchar(); + sleep(1); +} + +/*void tensecs(CSegwayRMP400* segway) +{ + int i; + //std::string info; +// std::ostream info; + + for(i=0;i<10;i++) + { + sleep(1); +// segway->get_info(info); + std::cout << (*segway) << std::endl; + } +} +*/ + +int main(int argc, char *argv[]) +{ + CSegwayRMP400 *segway; + + segway=new CSegwayRMP400(); + segway->set_operation_mode(tractor); + segway->reset_integrators(); + + std::cout << "CAUTION!! THIS PROGRAM MOVES THE SEGWAYRMP400" << std::endl; + std::cout << "You need at least 4x4 meter clearance around the robot for these tests!" << std::endl; + std::cout << "No obstacle avoidance is implemented. If there is something in the way the robot will hit it!" << std::endl; + std::cout << "Moving 0.5 meters at 0.05m/sec" << std::endl; + wait(); + segway->move(0.05,0.0); // 5cm per second 10 seconds = half a meter + int i; + for(i=0;i<10;i++) + { + sleep(1); + std::cout << (*segway) << std::endl; + } + segway->stop(); + sleep(2); + + std::cout << "Rotating 360 degrees with center of rotation on the side of the base" << std::endl; + wait(); + segway->move(0.0,0.1); // one 10th rev per second, 10 seconds = 360 degrees turn + // center right on the side of the base (about 54 cm from center of base) +// tensecs(segway); + segway->stop(); + sleep(2); + + std::cout << "Rotating 360 degrees with center of rotation 1m away from the base center" << std::endl; + wait(); + segway->move(0.1,0.1); // one 10th rev per second, 10 seconds = 360 degrees turn + // center of rotation vT/vR = 1meter from the center of the base + // tensecs(segway); + segway->stop(); + sleep(2); + + std::cout << "Rotating backwards 360 degrees with center of rotation 1m away from the base center" << std::endl; + wait(); + segway->move(-0.1,0.1); // one 10th rev per second, 10 seconds = 360 degrees turn BACKWARDS + // center of rotation vT/vR = 1meter from the center of the base + // tensecs(segway); + segway->stop(); + + + delete segway; + return 0; +} diff --git a/src/segway_RMP400.cpp b/src/segway_RMP400.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e33cc09ed9556d121c1b8b94846d2d81ee0a2df1 --- /dev/null +++ b/src/segway_RMP400.cpp @@ -0,0 +1,274 @@ +#include "segway_RMP400.h" +#include "segway_RMP400_exception.h" +#include <iridrivers/segway_rmp200_exceptions.h> +#include <cmath> + +CSegwayRMP400::CSegwayRMP400() : + status_(rmp400_off), + forward_displacement_(0.0), + yaw_displacement_(0.0), + yaw_rate_ (0.0), + wheel_radius_(default_wheel_radius_), + use_correction_wheel_factor_(true) +{ + scan_ftdi_for_segways(); +} + +CSegwayRMP400::CSegwayRMP400(const std::string serial1, const std::string serial2) : + status_(rmp400_off), + forward_displacement_(0.0), + yaw_displacement_(0.0), + yaw_rate_ (0.0), + wheel_radius_(default_wheel_radius_), + use_correction_wheel_factor_(true) +{ + if (serial1 == serial2) + throw RMP400IdemSerialException(_HERE_, serial1); + + scan_ftdi_for_segways(); + + for (int i = 0; i < serial_ftdi_segway_devices_.size(); i++) { + std::string serial = serial_ftdi_segway_devices_[i]; + + if ((serial != serial1) && (serial != serial2)) + throw RMP400NotFoundSerialException(_HERE_, serial); + } +} + +void +CSegwayRMP400::scan_ftdi_for_segways() +{ + CFTDIServer * ftdi_server_ = CFTDIServer::instance(); + ftdi_server_->add_custom_PID(CSegwayRMP200::pid); + + std::vector<int> ftdi_devs = ftdi_server_->get_ids_by_description(CSegwayRMP200::description); + + for (int i = 0;i < ftdi_devs.size();i++) { + serial_ftdi_segway_devices_.push_back( + ftdi_server_->get_serial_number(ftdi_devs.at(i))); + } + + if (serial_ftdi_segway_devices_.size() != NUM_SEGWAY_200) + throw RMP400NotValidNumberRMP200Exception(_HERE_, serial_ftdi_segway_devices_.size()); +} + +void +CSegwayRMP400::start() +{ + for (int i = 0;i < NUM_SEGWAY_200 ;i++) { + + try + { + CSegwayRMP200 * segway = new CSegwayRMP200(serial_ftdi_segway_devices_[i]); + segways_.push_back(segway); + } + catch (CSegwayRMP200Exception & e) + { + // Something failed while starting engines + // clean up previous (if any) started engine + for (int i = 0; i < segways_.size(); i++) { + segways_[i]->stop(); + delete segways_[i]; + } + + status_ = rmp400_off; + throw; + } + } + + status_ = rmp400_connected; +} + +std::ostream & +operator<< (std::ostream& data, CSegwayRMP400 & segway) +{ + for (int i=0; i<segway.segways_.size(); i++) + { + data << "Segway unit: " << i << std::endl; + data << "Pitch angle: " << segway.segways_[i]->get_pitch_angle() << " degrees" << std::endl; + data << "Pitch rate " << segway.segways_[i]->get_pitch_rate() << " degrees/s" << std::endl; + data << "Roll angle: " << segway.segways_[i]->get_roll_angle() << " degrees" << std::endl; + data << "Roll rate: " << segway.segways_[i]->get_roll_rate() << " degrees/s" << std::endl; + data << "Left wheel velocity: " << segway.segways_[i]->get_left_wheel_velocity() << " m/s" << std::endl; + data << "Right wheel velocity: " << segway.segways_[i]->get_right_wheel_velocity() << " m/s" << std::endl; + data << "Yaw rate: " << segway.segways_[i]->get_yaw_rate() << " degrees/s" << std::endl; + data << "Servo frames: " << segway.segways_[i]->get_servo_frames() << " frames/s" << std::endl; + data << "Left wheel displacement: " << segway.segways_[i]->get_left_wheel_displacement() << " m" << std::endl; + data << "Right wheel displacement: " << segway.segways_[i]->get_right_wheel_displacement() << " m" << std::endl; + data << "Forward displacement: " << segway.segways_[i]->get_forward_displacement() << " m" << std::endl; + data << "Yaw displacement: " << segway.segways_[i]->get_yaw_displacement() << " rev" << std::endl; + data << "Left motor torque: " << segway.segways_[i]->get_left_motor_torque() << " Nm" << std::endl; + data << "Right motor torque: " << segway.segways_[i]->get_right_motor_torque() << " Nm" << std::endl; + if(segway.segways_[i]->get_operation_mode()==tractor) + data << "Operation mode: tractor" << std::endl; + else + data << "Operation mode: power down" << std::endl; + if(segway.segways_[i]->get_gain_schedule()==light) + data << "Gain schedule: light" << std::endl; + else if(segway.segways_[i]->get_gain_schedule()==tall) + data << "Gain schedule: tall" << std::endl; + else + data << "Gain schedule: heavy" << std::endl; + data << "UI battery voltage: " << segway.segways_[i]->get_ui_battery_voltage() << " V" << std::endl; + data << "Powerbase battery voltage: " << segway.segways_[i]->get_powerbase_battery_voltage() << " V" << std::endl << std::endl; + } + data << std::endl; +} + +void +CSegwayRMP400::set_operation_mode(op_mode mode) +{ + if (mode == balance) + throw RMP400InvalidBalanceModeOperation(_HERE_); + + for (int i=0;i < segways_.size();i++) + { + segways_[i]->set_operation_mode(mode); + usleep(10000); + } +} + +void +CSegwayRMP400::need_to_be_connected() const +{ + if (! is_connected()) + throw RMP400NoConnected(_HERE_); +} + +void +CSegwayRMP400::disable_corretion_wheel_factor() +{ + use_correction_wheel_factor_ = false; +} + +void +CSegwayRMP400::fix_with_wheel_factor(float & value) +{ + /* corretion factor is the diference between real wheel and supposed + * firmware wheel (probaby segway using the rmp200 value) */ + value = value * (wheel_radius_ / RMP200_DEFAULT_WHEEL_RADIUS); +} + +void +CSegwayRMP400::set_wheel_radius(const float radius) +{ + wheel_radius_ = radius; +} + +float +CSegwayRMP400::get_forward_displacement() +{ + need_to_be_connected(); + + // The get_forward_displacement function in segway RMP 200 doesn't + // return the accumulate value of displacement, wheel_displacement + // function do. Use them instead. + + double fwd_displ_segway0 = (segways_[0]->get_right_wheel_displacement() + + segways_[0]->get_left_wheel_displacement()) / 2; + double fwd_displ_segway1 = (segways_[1]->get_right_wheel_displacement() + + segways_[1]->get_left_wheel_displacement()) / 2; + + forward_displacement_ = (fwd_displ_segway0 + fwd_displ_segway1) / 2; + + if (use_correction_wheel_factor_) + fix_with_wheel_factor(forward_displacement_); + + return forward_displacement_; +} + +float +CSegwayRMP400::get_yaw_displacement() +{ + need_to_be_connected(); + + float yaw_displacement_mts = (segways_[0]->get_yaw_displacement() + + segways_[1]->get_yaw_displacement()) / 2; + + if (use_correction_wheel_factor_) + fix_with_wheel_factor(yaw_displacement_mts); + + yaw_displacement_ = yaw_displacement_mts * 2 * PI; // convert to radians + return yaw_displacement_; +} + +float +CSegwayRMP400::get_yaw_rate() +{ + need_to_be_connected(); + + yaw_rate_ = get_yaw_displacement() * (PI / 180); + return yaw_rate_; +} + +void +CSegwayRMP400::reset_integrators() +{ + need_to_be_connected(); + + do { + for (int i=0; i < segways_.size(); i++) { + segways_[i]->reset_right_wheel_integrator(); + segways_[i]->reset_left_wheel_integrator(); + segways_[i]->reset_yaw_integrator(); + segways_[i]->reset_forward_integrator(); + } + // Need to leave the segwayrmp 200 driver to read need values + sleep(1); + } while (! is_valid_reset_integrators()); +} + +bool +CSegwayRMP400::is_valid_reset_integrators() +{ + float fd = get_forward_displacement(); + float yd = get_yaw_displacement(); + + if (std::fabs(0.0 - fd) > 0.1) { + std::cerr << "[segway] Invalid forward reset value " << fd << std::endl; + return false; + } + + if (std::fabs(0.0 - yd) > 0.1) { + std::cerr << "[segway] Invalid yaw reset value " << yd << std::endl; + return false; + } + + return true; +} + +void +CSegwayRMP400::move(float vT, float vR) +{ + need_to_be_connected(); + + float vRradsec = vR * 2.0 * PI; // revs per sec to rads per sec + + if (fabs(vT) < fabs(RMP400_b * vRradsec / 2)) { + // minimum translational velocity needed to enforce rotation about a ICR outside of the robot base + if(vT>=0.0) + vT = fabs(RMP400_b * vRradsec / 2); + else + vT = -fabs(RMP400_b * vRradsec / 2); + } + + for (int i=0 ;i < segways_.size(); i++) + segways_[i]->move(vT,vR); +} + +void +CSegwayRMP400::stop() +{ + need_to_be_connected(); + + for (int i=0;i < segways_.size();i++) + segways_[i]->stop(); + + status_ = rmp400_off; +} + +CSegwayRMP400::~CSegwayRMP400() +{ + for (int i=0;i < segways_.size(); i++) + delete segways_[i]; +} diff --git a/src/segway_RMP400.h b/src/segway_RMP400.h new file mode 100644 index 0000000000000000000000000000000000000000..595f51b01eed759e39dc6e524ac06683c5f141c6 --- /dev/null +++ b/src/segway_RMP400.h @@ -0,0 +1,230 @@ +#ifndef _SEGWAYRMP400_H +#define _SEGWAYRMP400_H + +#include <segway_rmp200.h> +#include <ftdiserver.h> +#include <math.h> +#include <vector> +#include <string> +#include <iostream> + +#define RMP400_b 0.54 // distance between weels for one rmp unit in meters +#define PI 3.141592 +#define RMP200_DEFAULT_WHEEL_RADIUS 0.24 + +const int NUM_SEGWAY_200 = 2; + +enum SegwayRMP400_status { rmp400_off, rmp400_connected }; + +class CSegwayRMP400 +{ + private: + std::vector<CSegwayRMP200 *> segways_; + /* vector of valid segway serials found in the ftdi bus */ + std::vector<std::string> serial_ftdi_segway_devices_; + + /** + * \brief Segway status + */ + SegwayRMP400_status status_; + + /** + * \brief forward displacement + * + * This value has the displacement of the whole platform in meters + * TODO: should be a thread periodically updating this value + */ + float forward_displacement_; + + /** + * \brief yaw displacement + * + * This value has the rotation of the whole platform in revolutions. + * TODO: should be a thread periodically updating this value + */ + float yaw_displacement_; + + /** + * \brief yaw rate + * + * This value has the yaw rate of the platform in degrees per second. + * TODO: should be a thread periodically updating this value + */ + float yaw_rate_; + + /** + * \brief default rmp400 wheel radius when inflated to 10 psi (in meters) + */ + static const float default_wheel_radius_ = 0.26; + + /** + * \brief wheel radius in meters + * + */ + float wheel_radius_; + + /** + * \brief whether use or not the correction factor to fix wheel size + * (default is true). See fix_with_wheel_factor for more info. + * + */ + bool use_correction_wheel_factor_; + + /** + * \brief apply a corretion factor to the value given + * + * It is suspected that segway is using the RMP200 wheel radius in RMP400 + * firmware which gives a bad measure for displacements. This functions + * calculate the relation between radius and fix the value given using this + * factor. + */ + void fix_with_wheel_factor(float & value); + + /** + * \brief disable use of correction wheel factor for displacements + * + * Check fix_with_wheel_factor for more info. + */ + void disable_corretion_wheel_factor(); + + void scan_ftdi_for_segways(); + + /** + * \brief set a different wheel radius (in meters) + * + * Default, when wheels are inflated to 10psi, is 0.26m. If the segway has + * a different meassure, please use this function before starting to operate + * as normal. + */ + void set_wheel_radius(const float radius); + + /* + * \brief check if the driver is already connected (made a start() call). + * + * It will return an RMP400NoConnected exception if fail + */ + void need_to_be_connected() const; + + /* \brief aux function to check if platform is really doing the reset in + * integrators. + */ + bool is_valid_reset_integrators(); + + protected: + /** + * \brief allowed modes: + * - tractor + * - power_dow + */ + op_mode mode; + + public: + CSegwayRMP400(); + CSegwayRMP400(const std::string serial1, const std::string serial2); + + ~CSegwayRMP400(); + + /** + * \brief function to set the operation mode + * + * Operation modes: tractor or power_down. + * In the RMP400 the balance mode is disabled. + */ + void set_operation_mode(op_mode mode); + + /** + * \brief function to check if segway is already connected + */ + bool is_connected() const; + + /** + * \brief function to return the total forward displacement + * + * This function returns the current forward displacement in meters. This + * function only returns the value of the internal attribute, but it does + * not access the hardware platform. This value is periodically updated by + * the feedback thread. + * + * Both fordward displacement from segways are sum and a mean is calculated + * + * \return the current forward displacement in meters. + * + */ + float get_forward_displacement(void); + + /** + * \brief function to return the total yaw displacement + * + * This function returns the current yaw displacement in revolutions per + * second. This function only returns the value of the internal attribute, + * but it does not access the hardware platform. This value is periodically + * updated by the feedback thread. + * + * Both yaw displacement from segways are sum and a mean is calculated + * + * \return the current yaw displacement in revolutions per second. + * + */ + float get_yaw_displacement(void); + + /** + * \brief function to return the yaw rate + * + * This function returns the current yaw rate in revolutions per second. + * This function only returns the value of the internal attribute, but it + * does not access the hardware platform. This value is periodically updated + * by the feedback thread. + * + * Both yaw rate from segways are sum and a mean is calculated + * + * \return the current yaw rate in revolutions per second. + * + */ + float get_yaw_rate(void); + + /** + * \brief function to reset integrators + * + * This function sets all encoder integrators to zero in both platforms. + * Currently this function seems NOT to be reliable since hardware not + * always is doing the proper work. + */ + void reset_integrators(); + + /** + * \brief function to move the platform + * + * This function sets the rotational and translational velocities to a desired value + * vT is in m/sec, vR is in rev/sec + * + * Rotation about the center of the platform with skid steer is disabled. + * Skid steering is not recommended since it produces significant tire wear and unnecessary battery consumption. + * Odometry readings during skid steering are useless since they depend heavily on soil characteristics. + * A minimum Instantaneous Center of Rotation (ICR) located on the side of the platform is enforced (0.54cm). + */ + void move(float vT, float vR); + + /* \brief function to connect segways RMP200 + * + * This functions start the vehicle + */ + void start(); + + /* \brief function to stop the platform + * + * This function stops the vehicle + */ + void stop(); + friend std::ostream& operator<< (std::ostream& out, CSegwayRMP400& segway); +}; + +inline bool +CSegwayRMP400::is_connected() const +{ + return (status_ == rmp400_connected); +} + + +#endif + + diff --git a/src/segway_RMP400_exception.cpp b/src/segway_RMP400_exception.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4daace416d4161548e29f76e451a38c2abd5076a --- /dev/null +++ b/src/segway_RMP400_exception.cpp @@ -0,0 +1,56 @@ +#include "segway_RMP400_exception.h" +#include <string> +#include <sstream> + +const std::string segway_rmp400_exception_msg = "[CSegwayRMP400 class] - "; + +CSegwayRMP400Exception::CSegwayRMP400Exception(const std::string & where, + const std::string & error_msg, + const std::string & segway_id) throw () : + CException(where, segway_rmp400_exception_msg + error_msg + "-" + segway_id) +{ +} + +CSegwayRMP400Exception::CSegwayRMP400Exception(const std::string & where, + const std::string & error_msg) throw () : + CException(where, segway_rmp400_exception_msg) +{ +} + +RMP400IdemSerialException::RMP400IdemSerialException(const std::string & where, + const std::string & serial) throw () : + CSegwayRMP400Exception(where, segway_rmp400_exception_msg) +{ + error_msg += "Serial ports are the same for two segways: " + serial; +} + +RMP400NotFoundSerialException::RMP400NotFoundSerialException(const std::string & where, + const std::string & serial) throw () : + + CSegwayRMP400Exception(where, segway_rmp400_exception_msg) +{ + error_msg += "Serial port found: " + serial + " not inside valid ports supplied"; +} + + +RMP400NotValidNumberRMP200Exception::RMP400NotValidNumberRMP200Exception(const std::string & where, + const int & number_found) throw () : + CSegwayRMP400Exception(where, segway_rmp400_exception_msg) +{ + std::stringstream s; + s << number_found; + + error_msg += "Found " + s.str() + " RMP200 units which is not valid for this device"; +} + +RMP400InvalidBalanceModeOperation::RMP400InvalidBalanceModeOperation(const std::string & where) throw () : + CSegwayRMP400Exception(where, segway_rmp400_exception_msg) +{ + error_msg += "Balance mode for the segway RMP400 is completly crazy"; +} + +RMP400NoConnected::RMP400NoConnected(const std::string & where) throw () : + CSegwayRMP400Exception(where, segway_rmp400_exception_msg) +{ + error_msg += "Segway RMP 400 has not been connected"; +} diff --git a/src/segway_RMP400_exception.h b/src/segway_RMP400_exception.h new file mode 100644 index 0000000000000000000000000000000000000000..bd8b98751a49e547507e73852772d29664c75cd1 --- /dev/null +++ b/src/segway_RMP400_exception.h @@ -0,0 +1,100 @@ +#ifndef _SEGWAY_RMP400_EXCEPTIONS +#define _SEGWAY_RMP400_EXCEPTIONS + +#include "exceptions.h" + +/** + * \brief Generic segway RMP 400 exception class + * + * This class implements the exceptions for the CSegwayRMP400 class. In addition + * to the basic error message provided by the base class CException, this + * exception class provides also the unique identifier of the segway robot + * that generated the exception. + * + * Also, similarly to other exception classes, it appends a class identifer + * string ("[CSegwayRMP400 class] - ") to the error message in order to identify the + * class that generated the exception. + * + * The base class can be used to catch any exception thrown by the application + * or also, this class can be used in order to catch only exceptions generated + * by CComm objects. + */ +class CSegwayRMP400Exception : public CException +{ + public: + /** + * \brief Constructor + * + * The constructor calls the base class constructor to add the general + * exception identifier and then adds the class identifier string + * "[CSegwayRMP400 class]" and the supplied error message. + * + * It also appends the unique identifier of the segway robot + * that generated the exception. So, the total exception message will + * look like this: + * + * \verbatim + * [Exception caught] - <where> + * [CSegwayRMP400 class] - <error message> - <segway id> + * \endverbatim + * + * \param where a null terminated string with the information about the name + * of the function, the source code filename and the line where + * the exception was generated. This string must be generated + * by the _HERE_ macro. + * + * \param error_msg a null terminated string that contains the error message. + * This string may have any valid character and there is no + * limit on its length. + * + * \param segway_id a null terminated string that contains the segway robot + * unique identifier. This string must be the one used to create + * the communication device. + * + */ + CSegwayRMP400Exception(const std::string& where,const std::string& error_msg,const std::string& segway_id) throw(); + + CSegwayRMP400Exception(const std::string& where,const std::string& error_msg) throw(); +}; + +class RMP400IdemSerialException : + public CSegwayRMP400Exception +{ + public: + /* Constructor */ + RMP400IdemSerialException(const std::string & where, const std::string & serial) throw (); +}; + +class RMP400NotFoundSerialException : + public CSegwayRMP400Exception +{ + public: + /* Constructor */ + RMP400NotFoundSerialException(const std::string & where, const std::string & serial) throw (); +}; + +class RMP400NotValidNumberRMP200Exception : + public CSegwayRMP400Exception +{ + public: + /* Constructor */ + RMP400NotValidNumberRMP200Exception(const std::string & where, const int & number) throw (); +}; + +class RMP400InvalidBalanceModeOperation : + public CSegwayRMP400Exception +{ + public: + /* Constructor */ + RMP400InvalidBalanceModeOperation(const std::string & where) throw (); +}; + +class RMP400NoConnected : + public CSegwayRMP400Exception +{ + public: + /* constructor */ + RMP400NoConnected(const std::string & where) throw (); +}; + +#endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b212e3776b808a04784cc57fc512f20a160de8bd --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,20 @@ +# edit the following line to find the necessary packages +FIND_LIBRARY(GTEST gtest) +FIND_PACKAGE(segway_rmp_200) + +FIND_LIBRARY (GTEST_LIBRARY + NAMES gtest) + +IF (GTEST_LIBRARY) + message (STATUS "Found gtest library: testing suite will be compiled") + # edit the following line to add the necessary include directories + INCLUDE_DIRECTORIES(../src) + INCLUDE_DIRECTORIES(${segway_rmp_200_INCLUDE_DIR}) + + ADD_EXECUTABLE(test_basic basic.cpp) + ADD_EXECUTABLE(test_movement movement.cpp) + TARGET_LINK_LIBRARIES(test_basic segway_rmp_400 ${GTEST_LIBRARY}) + TARGET_LINK_LIBRARIES(test_movement segway_rmp_400 ${GTEST_LIBRARY}) +else () + message (STATUS "Not Found gtest library: testing suite won't be compiled") +endif () diff --git a/test/basic.cpp b/test/basic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a0decba65d4f967476597da5c0c91c6e6ad4fbc4 --- /dev/null +++ b/test/basic.cpp @@ -0,0 +1,62 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#include <gtest/gtest.h> +#include "segway_RMP400.h" +#include "exceptions.h" + +int g_argc; +char** g_argv; + +TEST(Driver, constructor_destructor) +{ + ASSERT_NO_THROW ({ + CSegwayRMP400 * segway = new CSegwayRMP400(); + delete segway; + }); +} + +TEST(Driver, startstop) +{ + CSegwayRMP400 * segway = new CSegwayRMP400(); + ASSERT_NO_THROW(segway->start()); + ASSERT_NO_THROW(segway->stop()); + delete segway; +} + +TEST(Driver, startstoptwice) +{ + CSegwayRMP400 * segway = new CSegwayRMP400(); + ASSERT_NO_THROW(segway->start()); + ASSERT_NO_THROW(segway->stop()); + ASSERT_NO_THROW(segway->start()); + ASSERT_NO_THROW(segway->stop()); + delete segway; +} + +TEST(Driver, connected) +{ + CSegwayRMP400 * segway = new CSegwayRMP400(); + ASSERT_FALSE(segway->is_connected()); + segway->start(); + ASSERT_TRUE(segway->is_connected()); + segway->stop(); + ASSERT_FALSE(segway->is_connected()); + delete segway; +} + +TEST(Driver, reset_integrators) +{ + CSegwayRMP400 * segway = new CSegwayRMP400(); + segway->start(); + ASSERT_NO_THROW(segway->reset_integrators()); + segway->stop(); + delete segway; +} + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + g_argc = argc; + g_argv = argv; + return RUN_ALL_TESTS(); +} diff --git a/test/movement.cpp b/test/movement.cpp new file mode 100644 index 0000000000000000000000000000000000000000..98ff4fa282f3c98e983b7a60e13f7c033391c81b --- /dev/null +++ b/test/movement.cpp @@ -0,0 +1,104 @@ +/* vim: set sw=4 sts=4 et foldmethod=syntax : */ + +#include <gtest/gtest.h> +#include "segway_RMP400.h" +#include "exceptions.h" + +int g_argc; +char** g_argv; + +TEST(Driver, basic_move) +{ + CSegwayRMP400 * segway = new CSegwayRMP400(); + segway->start(); + ASSERT_NO_THROW(segway->move(0.3,0.3)); + sleep(3); + segway->move(0.0,0.0); + segway->stop(); + delete segway; +} + +TEST(Driver, reset_integrators_after_move) +{ + CSegwayRMP400 * segway = new CSegwayRMP400(); + segway->start(); + segway->reset_integrators(); + segway->move(0.2,0.0); + sleep(2); + segway->move(0.0,0.2); + sleep(2); + segway->move(0.0,0.0); + sleep(2); + segway->reset_integrators(); + ASSERT_NEAR(segway->get_forward_displacement(), 0.0, 0.1); + ASSERT_NEAR(segway->get_yaw_displacement(), 0.0, 0.1); + segway->stop(); + delete segway; +} + +TEST(Driver, get_forward_displacement) +{ + CSegwayRMP400 * segway = new CSegwayRMP400(); + segway->start(); + segway->reset_integrators(); + segway->move(0.2,0.0); + sleep(3); + ASSERT_GT(segway->get_forward_displacement(), 0.0); + segway->stop(); + delete segway; +} + +TEST(Driver, get_forward_negative_displacement) +{ + CSegwayRMP400 * segway = new CSegwayRMP400(); + segway->start(); + segway->reset_integrators(); + segway->move(-0.2,0.0); + sleep(3); + ASSERT_LT(segway->get_forward_displacement(), 0.0); + segway->stop(); + delete segway; +} + +TEST(Driver, get_yaw_displacement) +{ + CSegwayRMP400 * segway = new CSegwayRMP400(); + segway->start(); + segway->reset_integrators(); + segway->move(0.0,0.2); + sleep(3); + ASSERT_GT(segway->get_yaw_displacement(), 0.0); + segway->stop(); + delete segway; +} + +TEST(Driver, get_yaw_negative_displacement) +{ + CSegwayRMP400 * segway = new CSegwayRMP400(); + segway->start(); + segway->reset_integrators(); + segway->move(0.0,-0.2); + sleep(3); + ASSERT_LT(segway->get_yaw_displacement(), 0.0); + segway->stop(); + delete segway; +} + +TEST(Driver, get_yaw_rate) +{ + CSegwayRMP400 * segway = new CSegwayRMP400(); + segway->start(); + segway->move(0.0,0.3); + sleep(3); + ASSERT_GT(segway->get_yaw_rate(), 0.0); + segway->stop(); + delete segway; +} + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + g_argc = argc; + g_argv = argv; + return RUN_ALL_TESTS(); +}