diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..212386fe9c39a5fa8804e8ba83d7b6af144d7f80
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,84 @@
+# 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)
+
+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_200.cmake b/Findsegway_rmp_200.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..8c47911d9d22969376aeb4a573e6b2e264289802
--- /dev/null
+++ b/Findsegway_rmp_200.cmake
@@ -0,0 +1,20 @@
+FIND_PATH(segway_rmp_200_INCLUDE_DIR segway_rmp200.h segway_rmp200_exceptions.h /usr/include/iridrivers /usr/local/include/iridrivers)
+
+FIND_LIBRARY(segway_rmp_200_LIBRARY
+    NAMES segway_rmp_200
+    PATHS /usr/lib /usr/local/lib /usr/local/lib/iridrivers) 
+
+IF (segway_rmp_200_INCLUDE_DIR AND segway_rmp_200_LIBRARY)
+   SET(segway_rmp_200_FOUND TRUE)
+ENDIF (segway_rmp_200_INCLUDE_DIR AND segway_rmp_200_LIBRARY)
+
+IF (segway_rmp_200_FOUND)
+   IF (NOT segway_rmp_200_FIND_QUIETLY)
+      MESSAGE(STATUS "Found Segway RMP200 driver: ${segway_rmp_200_LIBRARY}")
+   ENDIF (NOT segway_rmp_200_FIND_QUIETLY)
+ELSE (segway_rmp_200_FOUND)
+   IF (segway_rmp_200_FIND_REQUIRED)
+      MESSAGE(FATAL_ERROR "Could not find segway RMP200 driver")
+   ENDIF (segway_rmp_200_FIND_REQUIRED)
+ENDIF (segway_rmp_200_FOUND)
+
diff --git a/ReadMe.txt b/ReadMe.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6f90a5cfa1bcb547b7003fb3303bfaafee9a0731
--- /dev/null
+++ b/ReadMe.txt
@@ -0,0 +1,31 @@
+Copyright (C) 2009-2010 Institut de Robòtica i Informàtica Industrial, CSIC-UPC.
+Author shernand (shernand@iri.upc.edu)
+All rights reserved.
+
+This file is part of segway RMP 200 driver library
+segway RMP 200 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..37b18d4c01c606682a80fd74c0ab435cf79d9387
--- /dev/null
+++ b/doc/doxygen_project_name.conf
@@ -0,0 +1 @@
+PROJECT_NAME = "segway RMP 200 driver"
diff --git a/doc/images/threads_diagram.pdf b/doc/images/threads_diagram.pdf
new file mode 100755
index 0000000000000000000000000000000000000000..0a67e87eb4f2573fab3f533bcfe8f16bdbf2b5df
Binary files /dev/null and b/doc/images/threads_diagram.pdf differ
diff --git a/doc/main.dox b/doc/main.dox
new file mode 100644
index 0000000000000000000000000000000000000000..4e59c249fe279e468cc3b89be82d516514f7a228
--- /dev/null
+++ b/doc/main.dox
@@ -0,0 +1,172 @@
+/*! \mainpage segway RMP200 driver
+ 
+ \section Introduction
+ 
+  This driver is in charge to operate motion of a SegwayRMP200 and as well as monitoring
+
+  The main class is SegwayRMP200,
+
+  - The class has an FTDI driver object to ensure USB communication with the segway
+  - It also launches two threads for reading data and sending commands to the segway
+  - Uses a mutex variable, to ensure that only one thread is accessing ftdi object at a time.
+  .
+	
+  Segway parameters such as position and velocities paramaters are internal variables of the class, 
+  and updated every 10 ms approx, by the read thread.
+	
+  The read thread waits for a reception event coming from FTDI device. Once received it reads data stored into
+  receiving buffer of FTDI device. A reference of reception event of FTDI device is retrieved at constructor so 
+  as to wait upon it.
+	
+
+  Comanding the segway on the ohter hand is done at 50 Hz approx by the command thread, i.e one new command each
+  20 ms.Actually, segway must receive a command at least every 0.4 seconds (2.5 Hz) in order to keep it moving.
+  Otherwise it will automatically set motors to zero. 
+
+
+ \section Installation
+
+  \subsection Pre-Requisites
+
+  This driver 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.
+	 - <a href="http://www.libusb.org">libusb</a> for libftd2xx.
+	 - <a href="http://www.ftdichip.com">libftd2xx</a> for FTDI chip
+	 - <a href="http://wikiri.upc.es/index.php/Utilities_library">libiriutils</a> for threads and events from IRI repository.
+	 - <a href="http://wikiri.upc.es/index.php/Communications_library">communications library</a> for the FTDI driver.
+         .
+
+  Under linux all of these utilities are available in ready-to-use packages.
+
+  \subsection Compilation
+
+  
+  \par Install iriutils
+
+  For information on how to download, compile and install this library, please 
+  visit the following web page: http://wikiri.upc.es/index.php/Utilities_library
+
+  (FTDI,...)
+
+  \par Install this library
+  To build (placed in ./bin) the library just type in FTDI directory:
+
+  \code 
+  cmake .
+  make
+  \endcode
+
+  To create the documentation (placed in ./doc) type:
+  \code 
+  make doc
+  \endcode
+
+  To install the library into system folders
+  \code
+  sudo make install
+  \endcode
+
+  Just download this package, uncompress it, and execute cmake in build folder,
+  this step will generate the makefile and put all cmake files this folder.
+
+  \code 
+  cd build
+  cmake ..
+  \endcode
+  
+  To obtain the executables execute in build folder:
+  
+  \code
+  make
+  \endcode
+
+  To install the library SegwayRMP200 into system folders, in build folder:
+  \code
+  sudo make install
+  \endcode
+  
+  To generate the documentation, in build folder:
+  \code
+  make doc
+  \endcode
+
+  <em>Cmake</em> only needs to be executed once (make will automatically call
+  <em>cmake</em> if you modify one of the <em>CMakeList.txt</em> files).
+
+  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 Contents
+
+  This project is composed by the following source files
+	- SegwayRMP200Driver.cpp  (Segway driver)
+	- SegwayRMP200Driver.h	
+	- SegwayRMP200_main.cpp (example program)
+	.
+
+  \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.
+
+  \section License
+
+  This package is licensed under a 
+  <a href="http://creativecommons.org/licenses/by/3.0/">
+    Creative Commons Attribution 3.0 Unported License</a>.
+
+  \section Disclaimer
+
+  <i>This package is distributed in the hope that it will be useful, but without any warranty. 
+  it is provided "as is" without warranty of any kind, either expressed or implied, including, 
+  but not limited to, the implied warranties of merchantability and fitness for a particular 
+  purpose. The entire risk as to the quality and performance of the program is with you. 
+  should the program prove defective, the GMR group does not assume the cost of any necessary 
+  servicing, repair  or correction.
+
+  In no event unless required by applicable law the author will be liable to you for damages, 
+  including any general, special, incidental or consequential damages arising out of the use or 
+  inability to use the program (including but not limited to loss of data or data being rendered 
+  inaccurate or losses sustained by you or third parties or a failure of the program to operate 
+  with any other programs), even if the author has been advised of the possibility of such damages.</i>
+
+  \author Ismael Haddad
+  \version 0.1
+  \date september 2009
+
+*/
+
+
+
+/*! \todo - afegir variables internes : velocity command (as received) i turn command (as received). Correspond al packet de dades 0x407, veure pag. 10 del Segway RMP Interface guide
+  - mutex per vT i vR ?. fer un mutex.enter() i mutex.exit() a la funcio setComands()
+  - mirar quins son els rangs de valors corrents per velocitat translacio i rotació i implementar algun mecanisme per no sobrepasar els rangs.
+  - Amb Processador UI ences (boto verd) i motors apagats, es pot llegir missatges. Son els heartbeats, missatges sense informacio que envia el UI processor als CPU dels motors
+  - Per llegir informacio util del segway, els motors han d'estar encesos
+  - Si s'utilitza amb un segway 200 (amb balanceig), anar amb compte amb la configuració.
+  De fet, es pot configurar el mode de traccio en el que s'ha de posar el segway (tractor, balance) aixi com bloquejar el balanceig (sendConfig() o config())
+  - sembla que la carga de les batteries dels UI variin lleugerament (augmenten?) quan s'utilitzen els motors. Potser hi ha algun mecanisme de carrega de les bateries amb alternador (verificar)
+  .
+*/
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100755
index 0000000000000000000000000000000000000000..60b7e99959d65aa60334dcb9698248546e7ea2bb
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,31 @@
+# edit the following line to add all the source code files of the library
+SET(sources segway_rmp200.cpp segway_rmp200_exceptions.cpp)
+# edit the following line to add all the header files of the library
+SET(headers segway_rmp200.h segway_rmp200_exceptions.h)
+
+# edit the following line to find the necessary packages
+FIND_PACKAGE(iriutils REQUIRED)
+FIND_PACKAGE(comm REQUIRED)
+
+# edit the following line to add the necessary include directories
+INCLUDE_DIRECTORIES(.)
+INCLUDE_DIRECTORIES(${iriutils_INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${comm_INCLUDE_DIR})
+
+ADD_LIBRARY(segway_rmp_200 SHARED ${sources})
+
+#edit the following line to add the necessary system libraries (if any)
+TARGET_LINK_LIBRARIES(segway_rmp_200 ${iriutils_LIBRARY})
+TARGET_LINK_LIBRARIES(segway_rmp_200 ${comm_LIBRARY})
+
+INSTALL(TARGETS segway_rmp_200
+  RUNTIME DESTINATION bin
+  LIBRARY DESTINATION lib/iridrivers
+  ARCHIVE DESTINATION lib/iridrivers
+)
+
+INSTALL(FILES ${headers} DESTINATION include/iridrivers)
+
+INSTALL(FILES ../Findsegway_rmp_200.cmake DESTINATION ${CMAKE_ROOT}/Modules/)
+	
+ADD_SUBDIRECTORY(examples)
diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6d03ddab41eb690bac833170fcad02f0b1acd7df
--- /dev/null
+++ b/src/examples/CMakeLists.txt
@@ -0,0 +1,9 @@
+# edit the following line to add the source code for the example and the name of the executable
+ADD_EXECUTABLE(test_segway_rmp_200 test_segwayRMP200.cpp)
+ADD_EXECUTABLE(motionModelData motionModelData.cpp)
+
+# edit the following line to add the necessary libraries
+TARGET_LINK_LIBRARIES(test_segway_rmp_200 segway_rmp_200 ${comm_LIBRARY}) 
+TARGET_LINK_LIBRARIES(motionModelData segway_rmp_200 ${comm_LIBRARY}) 
+
+
diff --git a/src/examples/motionModelData.cpp b/src/examples/motionModelData.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4df786ea5d9c578eb4c6536d8c96e7708e95b247
--- /dev/null
+++ b/src/examples/motionModelData.cpp
@@ -0,0 +1,217 @@
+#include "segway_rmp200.h"
+#include "ftdiexceptions.h"
+#include "ftdiserver.h"
+#include "ftdimodule.h"
+#include <iostream>
+#include <fstream>
+#include <time.h>
+#include <sys/time.h>
+#include <math.h>
+
+
+/** \example motionModelData.cpp
+ *
+ * This example executes a series of commands to record platform data of interest to build a kinematic/dynammic model of the platform
+ *
+ * Before running this example it is important to follow the next steps:
+ *
+ * 	- check that E-Stop lanyard is plugged. (the red cordon). Motors won't
+ * 	  start unless it is plugged
+ *	- connect segway to USB slot of Pc host
+ *	- start Segway UI processor (green button)
+ *	- start Motors (yellow button)
+ *
+ * This example first creates an FTDI server to detect any possible segway
+ * platform connected to the computer. It uses the add_custom_PID() function
+ * to add the PID and VID combination used by Segway. It then opens the 
+ * first device found, if any, using the serial number. At this point it is 
+ * important that no other FTDI device is connected to the computer because 
+ * the program does not check which kind of device it is.
+ *
+ * Once the FTDI device is opened and configured, a new CSegwayRMP200 object
+ * is created an associated to the FTDI device. Then the robotic platform is
+ * configured and commanded to move forward.
+ *
+ * While moving, every 1 second, the whole information of the platform is 
+ * 50displayed on screen. Since the odometry of the robot uses inertial sensors,
+ * if the platform is not actually moving, the displayed information will 
+ * have no real meaning.
+ *
+ * It is important to note that it is not possible to execute any function 
+ * of the public API of the CSegwayRMP200 class until a valid FTDI object 
+ * has been associated to the segway object.
+ *
+ * If the motor are not enabled (yellow button turned off), the segway only
+ * sends heartbeat commands, but it is not possible to send motion commands
+ * or receive feedback data. In this case, the program will not fail, but
+ * nothing will happen.
+ */
+
+using namespace std;
+
+string segway_name="segway"; 
+unsigned int iterationPeriod = 50; //msec
+
+int main(int argc, char *argv[])
+{
+	//operational variables
+	CSegwayRMP200 *segway;
+	CFTDIServer *ftdi_server=CFTDIServer::instance();
+	string serial_number;
+	unsigned int ii=0;
+	unsigned int jj=0;
+	unsigned int kk=0;
+	int opt;
+	ofstream dataFile; //data file
+	float vt, vr; //[m/s], [rad/s]
+	string fileName = "/home/andreu/Desktop/dataFile.txt";
+	timeval tvTimeStamp;
+	double timeStamp;
+	streamsize nn;
+	
+	//user variables 
+	float duration; //duration of all the experiment
+	float vTstepDuration; //duration of a step
+	float vRstepDuration; //duration of a step
+	float vT0; //initial translational velocity
+	float vR0; //initial rotational velocity	
+	float vTstepIncrement; //velocity increment at each step
+	float vRstepIncrement; //velocity increment at each step
+	
+	//user derived variables
+	unsigned int totalIterations;
+	unsigned int jjMax;
+	unsigned int kkMax;
+
+	while ((opt = getopt(argc, argv, "f:h?"))!= -1)
+	{
+		switch (opt)
+		{
+			case 'f': // file name
+				fileName = optarg;
+				break;
+			case '?': // help
+			case 'h':
+			default:
+				cout << "  USAGE" << endl
+				<< "  " << argv[0] << " [options]" << endl
+				<< "  OPTIONS" << endl
+				<< "   -f FILE_NAME (default: " << fileName << ")" << endl;
+				return 1;
+		}
+	}
+	
+	//user dialog
+	cout << endl << "Duration [s]: "; cin >> duration;
+	cout << endl << "vTstepDuration [s]: "; cin >> vTstepDuration;
+	cout << endl << "vRstepDuration [s]: "; cin >> vRstepDuration;
+	cout << endl << "vT0 [m/s]: "; cin >> vT0;
+	cout << endl << "vR0 [rad/s]: "; cin >> vR0;	
+	cout << endl << "vTstepIncrement [m/s]: "; cin >> vTstepIncrement;
+	cout << endl << "vRstepIncrement [rad/s]: "; cin >> vRstepIncrement;
+	cout << endl;
+			
+	//set user derived variables
+	totalIterations = (unsigned int)(duration/(iterationPeriod/1000.0));
+	jjMax = (unsigned int)(vTstepDuration/(iterationPeriod/1000.0));
+	kkMax = (unsigned int)(vRstepDuration/(iterationPeriod/1000.0));
+	
+	//prints experiment config
+	cout << "*******************************************************************" << endl;
+	cout << "Duration: " << duration << endl;
+	cout << "vTstepDuration: " << vTstepDuration << endl;
+	cout << "vRstepDuration: " << vRstepDuration << endl;
+	cout << "vTstepIncrement: " << vTstepIncrement << endl;
+	cout << "vRstepIncrement: " << vRstepIncrement << endl;
+	cout << "vT0: " << vT0 << endl;
+	cout << "vR0: " << vR0 << endl;
+	cout << "totalIterations: " << totalIterations << endl;
+	cout << "jjMax: " << jjMax << endl;
+	cout << "kkMax: " << kkMax << endl;
+	cout << "*******************************************************************" << endl;
+	cout << "Do you want to continue ? (y/n)" << endl;
+	char resp;
+	cin >> resp;
+	if (resp == 'n')
+	{
+		cout << "Execution aborted" << endl;
+		return 1;
+	}
+	
+	//open data file and prints a header
+	dataFile.open(fileName.c_str(), ofstream::out);
+	dataFile 	<< "tS[s] vTcmnd[m/s] vRcmnd[rad/s] vT[m/s] vR[rad/s] pitch[rad] roll[rad] pitchRate[rad/s] rollRate[rad/s] "
+			<< "leftTorque[Nm] rightTorque[Nm] uiBattery[V] motorBattery[V]" << endl;
+
+	
+	//execution
+	try{
+		segway=new CSegwayRMP200(segway_name);
+		segway->connect();
+		usleep(10000);
+		segway->unlock_balance();
+		segway->reset_right_wheel_integrator();
+		segway->reset_left_wheel_integrator();
+		segway->reset_yaw_integrator();
+		segway->reset_forward_integrator();
+		segway->set_velocity_scale_factor(1.0);
+		segway->set_acceleration_scale_factor(1.0);
+		segway->set_turnrate_scale_factor(1.0);
+		//segway->set_operation_mode(balance);
+
+		vt = vT0;
+		vr = vR0;
+		for (ii=0; ii<totalIterations; ii++)
+		{
+			jj++; kk++; 
+			if ( jj == jjMax )
+			{
+				jj=0;
+				vt = vt + vTstepIncrement;
+			}
+			if ( kk == kkMax )
+			{
+				kk=0;
+				vr = vr + vRstepIncrement;
+			}
+
+			//send commands to platform
+			segway->move( vt , vr/(2*M_PI) ); //rotational speed required in revolutions per second
+			
+			//timeStamp
+			gettimeofday(&tvTimeStamp, NULL); 
+			timeStamp = (double)(tvTimeStamp.tv_sec + tvTimeStamp.tv_usec/1e6);	
+	
+			//logging data
+			//cout << (*segway) << endl;
+			nn=dataFile.precision(15);
+			dataFile << timeStamp << " ";
+			dataFile.precision(6);
+			dataFile 	<< vt << "\t" << vr << "\t"
+					<< (segway->get_left_wheel_velocity()+segway->get_right_wheel_velocity())/2.0 << "\t" << segway->get_yaw_rate()*M_PI/180.0 << "\t"
+					<< segway->get_pitch_angle()*M_PI/180.0 << "\t" << segway->get_roll_angle()*M_PI/180.0 << "\t"
+					<< segway->get_pitch_rate()*M_PI/180.0 << "\t" << segway->get_roll_rate()*M_PI/180.0 << "\t"
+					<< segway->get_left_motor_torque() << "\t" << segway->get_right_motor_torque() << "\t"
+					<< segway->get_ui_battery_voltage() << "\t" << segway->get_powerbase_battery_voltage() << endl;					
+					
+			//sleep up to next iteration
+			usleep(iterationPeriod*1000);//sending commands @20Hz approx
+		}
+		
+		dataFile.close();
+		
+/*		segway->reset_right_wheel_integrator();
+		segway->reset_left_wheel_integrator();
+		segway->reset_yaw_integrator();
+		segway->reset_forward_integrator();
+		sleep(5);
+		cout << (*segway) << endl;*/
+		
+		segway->stop();
+		segway->close();
+		delete segway;
+		
+	}catch(CException &e){
+		std::cout << e.what() << std::endl;
+	}
+}
diff --git a/src/examples/test_segwayRMP200.cpp b/src/examples/test_segwayRMP200.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..7acc1bb37697133a387351c54daebd772de5f85a
--- /dev/null
+++ b/src/examples/test_segwayRMP200.cpp
@@ -0,0 +1,147 @@
+#include "segway_rmp200.h"
+#include "ftdiexceptions.h"
+#include "eventserver.h"
+#include "ftdiserver.h"
+#include "ftdimodule.h"
+#include <iostream>
+
+/** \example test_segwayRMP200.cpp
+ *
+ * This example shows the basic operation of a Segway RMP200 platform.
+ *
+ * Before running this example it is important to follow the next steps:
+ *
+ * 	- check that E-Stop lanyard is plugged. (the red cordon). Motors won't
+ * 	  start unless it is plugged
+ *	- connect segway to USB slot of Pc host
+ *	- start Segway UI processor (green button)
+ *	- start Motors (yellow button)
+ *
+ * This example first creates an FTDI server to detect any possible segway
+ * platform connected to the computer. It uses the add_custom_PID() function
+ * to add the PID and VID combination used by Segway. It then opens the 
+ * first device found, if any, using the serial number. At this point it is 
+ * important that no other FTDI device is connected to the computer because 
+ * the program does not check which kind of device it is.
+ *
+ * Once the FTDI device is opened and configured, a new CSegwayRMP200 object
+ * is created an associated to the FTDI device. Then the robotic platform is
+ * configured and commanded to move forward.
+ *
+ * While moving, every 1 second, the whole information of the platform is 
+ * displayed on screen. Since the odometry of the robot uses inertial sensors,
+ * if the platform is not actually moving, the displayed information will 
+ * have no real meaning.
+ *
+ * It is important to note that it is not possible to execute any function 
+ * of the public API of the CSegwayRMP200 class until a valid FTDI object 
+ * has been associated to the segway object.
+ *
+ * If the motor are not enabled (yellow button turned off), the segway only
+ * sends heartbeat commands, but it is not possible to send motion commands
+ * or receive feedback data. In this case, the program will not fail, but
+ * nothing will happen.
+ */
+
+std::string segway_name="segway"; 
+
+int main(int argc, char *argv[])
+{
+  CSegwayRMP200 *segway = NULL;
+  std::list<std::string> events;
+  CFTDIServer *ftdi_server=CFTDIServer::instance();
+  CEventServer *event_server=CEventServer::instance();
+  std::string serial_number,cable_disconnected,power_off;
+  bool connected=false;
+  int i=0,event_id=0;
+
+  try
+  {
+    while(!connected)
+    {
+      try
+      {
+        segway = new CSegwayRMP200();
+        connected = true;
+      }
+      catch(CException &e)
+      {
+        if(segway != NULL)
+          delete segway;
+
+        segway = NULL;
+
+        std::cout << e.what() << std::endl;
+        std::cout << "The segway platfrom is still not ready (is it power on?)" << std::endl << std::endl;
+        sleep(1);
+      }
+    }
+
+    segway->unlock_balance();
+    segway->set_operation_mode(tractor);
+    segway->set_gain_schedule(light);
+    segway->reset_right_wheel_integrator();
+    segway->reset_left_wheel_integrator();
+    segway->reset_yaw_integrator();
+    segway->reset_forward_integrator();
+
+    // keep in mind that the order in of the event son the events list fix their
+    // priority. The first event on the list will be checked first, and if it is 
+    // active, the other will not be checked.
+    events.push_back(segway->get_cable_disconnected_event());    
+    events.push_back(segway->get_power_off_event());    
+    events.push_back(segway->get_no_heartbeat_event());    
+    events.push_back(segway->get_new_status_event());   
+
+    segway->move(0.1,0.0);
+    for(i=0;i<1000000;i++)
+    {
+      event_id=event_server->wait_first(events);
+      if(event_id==3)
+      {
+        if((i%100)==0)
+          std::cout << (*segway) << std::endl;
+      }
+      else if(event_id==2)
+      {
+        std::cout << "No heart beat detected" << std::endl;
+        segway->stop();
+        sleep(1);
+      }
+      else if(event_id==1)
+      {
+        std::cout << "The segway platform power is off" << std::endl;
+        segway->stop();
+        sleep(1);
+      }
+      else
+      {
+        std::cout << "The USB cable has been disconnected" << std::endl;
+        segway->stop();
+        segway->close();
+        connected=false;
+        while(!connected)
+        {
+          try
+          {
+            segway->connect();
+            connected=true;
+            segway->move(0.1,0.0);
+          }
+          catch(CException &e)
+          {
+            std::cout << "The segway platfrom is still not ready" << std::endl;
+            sleep(1);
+          }
+        }
+      }
+    }
+    segway->stop();
+    segway->close();
+    delete segway;
+  }
+  catch(CException &e)
+  {
+     std::cout << e.what() << std::endl;
+  }
+}
diff --git a/src/segway_rmp200.cpp b/src/segway_rmp200.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..bef3fb563ff55a09d6589ee698a551146e4ebb53
--- /dev/null
+++ b/src/segway_rmp200.cpp
@@ -0,0 +1,953 @@
+#include "segway_rmp200.h"
+#include "segway_rmp200_exceptions.h"
+#include "eventexceptions.h"
+#include "ftdiexceptions.h"
+#include <iostream>
+#include <string>
+
+const std::string CSegwayRMP200::description = "Robotic Mobile Platform";
+const short int CSegwayRMP200::pid = 0xE729;
+
+CSegwayRMP200::CSegwayRMP200(const std::string& desc_serial)
+{
+  std::string serial_number=desc_serial;
+  std::vector<int> ftdi_devs;
+
+  this->event_server  = CEventServer::instance(); 
+  this->thread_server = CThreadServer::instance();
+
+  this->init_attributes();
+  this->init_ftdi();
+
+  if(desc_serial.compare("") == 0)
+  {
+    ftdi_devs = this->ftdi_server->get_ids_by_description(CSegwayRMP200::description);
+    
+    //check how many segway devices are connected
+    //launch exception if there are no segways or there is more than one
+    if(ftdi_devs.size() != 1)
+    {
+      if(ftdi_devs.size() == 0)
+        throw CSegwayRMP200Exception(_HERE_, "No segways available", this->id);
+      else
+      {
+        throw CSegwayRMP200Exception(_HERE_, "More than one segway available", this->id);
+      }
+    }
+    serial_number= this->ftdi_server->get_serial_number(ftdi_devs.at(0));
+  }
+  this->id = "segway_" + serial_number;
+  this->init_threads();
+  this->init_events();
+
+  this->connect(desc_serial);
+}
+
+void CSegwayRMP200::init_attributes(void)
+{
+  // initialize internal variables
+  this->left_wheel_velocity=0.0;
+  this->right_wheel_velocity=0.0;
+  this->pitch_angle=0.0;
+  this->pitch_rate=0.0;
+  this->roll_angle=0.0;
+  this->roll_rate=0.0;
+  this->yaw_rate=0.0;
+  this->servo_frames=0.0;
+  this->left_wheel_displ=0.0;
+  this->right_wheel_displ=0.0;
+  this->forward_displ=0.0;
+  this->yaw_displ=0.0;
+  this->left_torque=0.0;
+  this->right_torque=0.0;
+  this->mode=(op_mode)-1;
+  this->hardware_mode=(op_mode)-1;
+  this->gain_schedule=(gain)-1;
+  this->ui_battery=0.0;
+  this->powerbase_battery=0.0;
+  // command variables
+  this->vT=0; 
+  this->vR=0;
+}
+
+void CSegwayRMP200::init_ftdi(void)
+{
+    this->comm_dev=NULL;
+    this->ftdi_server = CFTDIServer::instance();
+    this->ftdi_server->add_custom_PID(this->pid);
+}
+
+void CSegwayRMP200::init_threads(void)
+{
+
+  // create the feedback and command threads
+  this->read_thread_id = this->id;
+  this->read_thread_id += "_read_thread";
+  this->thread_server->create_thread(this->read_thread_id);
+  this->thread_server->attach_thread(this->read_thread_id,this->start_read_thread,this);
+  this->command_thread_id = this->id;
+  this->command_thread_id += "_command_thread";
+  this->thread_server->create_thread(this->command_thread_id);
+  this->thread_server->attach_thread(this->command_thread_id,this->start_command_thread,this);
+  //create the heartbeat thread
+  this->heartbeat_thread_id = this->id;
+  this->heartbeat_thread_id += "_heartbeat_thread";
+  this->thread_server->create_thread(this->heartbeat_thread_id);
+  this->thread_server->attach_thread(this->heartbeat_thread_id,this->heartbeat_thread,this);
+}
+
+void CSegwayRMP200::init_events(void)
+{
+  // create the finish events
+  this->read_finish_event = this->id;
+  this->read_finish_event += "_finish_read_thread";
+  this->event_server->create_event(this->read_finish_event);
+  this->command_finish_event = this->id;
+  this->command_finish_event += "_finish_command_thread";
+  this->event_server->create_event(this->command_finish_event);
+  // create the error events
+  this->cable_disconnected_event = this->id;
+  this->cable_disconnected_event += "_cable_disconnected";
+  this->event_server->create_event(this->cable_disconnected_event);
+  this->power_off_event = this->id;
+  this->power_off_event += "_power_off_event";
+  this->event_server->create_event(this->power_off_event);
+  this->no_heartbeat_event = this->id;
+  this->no_heartbeat_event += "_no_heartbeat";
+  this->event_server->create_event(this->no_heartbeat_event);
+  // create the heartbeat event
+  this->heartbeat_event = this->id;
+  this->heartbeat_event += "_heartbeat";
+  this->event_server->create_event(this->heartbeat_event);
+  // create the new status event
+  this->new_status_event = this->id;
+  this->new_status_event += "_new_status";
+  this->event_server->create_event(this->new_status_event);
+
+}
+
+std::string CSegwayRMP200::get_id(void)
+{
+  return this->id;
+}
+
+std::string CSegwayRMP200::get_cable_disconnected_event(void)
+{
+  return this->cable_disconnected_event;
+}
+
+std::string CSegwayRMP200::get_power_off_event(void)
+{
+  return this->power_off_event;
+}
+
+std::string CSegwayRMP200::get_no_heartbeat_event(void)
+{
+  return this->no_heartbeat_event;
+}
+
+std::string CSegwayRMP200::get_new_status_event(void)
+{
+  return this->new_status_event;
+}
+
+unsigned char CSegwayRMP200::compute_checksum(segway_packet *packet)
+{
+  int i;
+
+  unsigned short int checksum=0;
+  unsigned short int checksum_high=0;
+
+  for(i=0;i<17;i++)
+    checksum += (short)packet->data[i];
+  checksum_high = (unsigned short)(checksum >> 8);
+  checksum &= 0xFF;
+  checksum +=checksum_high;
+  checksum_high = (unsigned short)(checksum >> 8);
+  checksum &= 0xFF;
+  checksum +=checksum_high;
+  checksum = (~checksum + 1) & 0xFF;
+ 
+  return (unsigned char)checksum;
+}
+
+bool CSegwayRMP200::read_packet(segway_packet *packet,int *packet_len)
+{
+  int read_data=0,len=0,pos=0;
+  unsigned char *data=NULL;
+
+  if(packet==NULL)
+  {
+    /* handle exceptions */
+    throw CSegwayRMP200Exception(_HERE_,"Invalid packet structure",this->id);
+  } 
+  else
+  {
+    len=this->comm_dev->get_num_data();
+    data=new unsigned char[len];
+    try{
+      read_data=this->comm_dev->read(data,len);
+    }catch(CException &e){
+      /* handle exception */
+      throw;
+    }
+    if(read_data!=len)
+    {
+      /* handle exceptions */
+      throw CSegwayRMP200Exception(_HERE_,"Unexpected error while reading the USB device",this->id);
+    }
+    while(pos<len)
+    {
+      if((*packet_len)==0)
+      {
+        if(data[pos]==0xF0)
+        {
+          packet->data[(*packet_len)]=data[pos];
+          (*packet_len)++;
+        }
+      }
+      else
+      { 
+        if((*packet_len)==1)
+        {
+          if(data[pos]==0x55)
+          {
+            packet->data[(*packet_len)]=data[pos];
+            (*packet_len)++;
+          }
+          else
+            (*packet_len)=0;
+        }
+        else
+        {
+          if((*packet_len)==2)
+          {
+            if(data[pos]==0xAA || data[pos]==0xBB)
+            {
+              packet->data[(*packet_len)]=data[pos];
+              (*packet_len)++;
+            }
+            else
+              (*packet_len)=0;
+          }
+          else
+          {
+            packet->data[(*packet_len)]=data[pos];
+            (*packet_len)++;
+            if((*packet_len)==18)
+            {
+              (*packet_len)=0;
+              if(data!=NULL)
+                delete[] data;
+              return true;
+            }
+          }
+        }
+      }
+      pos++;
+    }
+  }
+
+  if(data!=NULL)
+    delete[] data;
+  return false;
+}
+
+void CSegwayRMP200::parse_packet(segway_packet *packet)
+{
+  short int command;
+  int i=0;
+
+  if(this->compute_checksum(packet)!=packet->data[17])
+  {
+    /* handle exceptions */
+    throw CSegwayRMP200Exception(_HERE_,"Invalid packet checksum, a transmission error ocurred",this->id);
+  }
+  if(packet->data[2]==0xaa)
+  {
+    this->access_status.enter();
+    command=(packet->data[4]*256+packet->data[5])/32;
+    switch(command)
+    {
+      case 0x0400: break;
+      case 0x0401: this->pitch_angle=((float)((short int)(((int)packet->data[9]<<8)+(int)packet->data[10])))/7.8;
+                   this->pitch_rate=((float)((short int)(((int)packet->data[11]<<8)+(int)packet->data[12])))/7.8;
+                   this->roll_angle=((float)((short int)(((int)packet->data[13]<<8)+(int)packet->data[14])))/7.8;
+                   this->roll_rate=((float)((short int)(((int)packet->data[15]<<8)+(int)packet->data[16])))/7.8;
+                   break;
+      case 0x0402: this->left_wheel_velocity=((float)((short int)(((int)packet->data[9]<<8)+(int)packet->data[10])))/332.0;
+                   this->right_wheel_velocity=((float)((short int)(((int)packet->data[11]<<8)+(int)packet->data[12])))/332.0;
+                   this->yaw_rate=((float)((short int)(((int)packet->data[13]<<8)+(int)packet->data[14])))/7.8;
+                   this->servo_frames=((float)((unsigned short int)(((int)packet->data[15]<<8)+(int)packet->data[16])))*0.01;
+                   break; 
+      case 0x0403: this->left_wheel_displ=((float)((int)(((int)packet->data[11]<<24)+((int)packet->data[12]<<16)+((int)packet->data[9]<<8)+(int)packet->data[10])))/33215.0; 
+                   this->right_wheel_displ=((float)((int)(((int)packet->data[15]<<24)+((int)packet->data[16]<<16)+((int)packet->data[13]<<8)+(int)packet->data[14])))/33215.0;
+                   break;
+      case 0x0404: this->forward_displ=((float)((int)(((int)packet->data[11]<<24)+((int)packet->data[12]<<16)+((int)packet->data[9]<<8)+(int)packet->data[10])))/33215.0;;
+                   this->yaw_displ=((float)((int)(((int)packet->data[15]<<24)+((int)packet->data[16]<<16)+((int)packet->data[13]<<8)+(int)packet->data[14])))/112644.0;
+                   break;
+      case 0x0405: this->left_torque=((float)((short int)(((int)packet->data[9]<<8)+(int)packet->data[10])))/1094.0;
+                   this->right_torque=((float)((short int)(((int)packet->data[11]<<8)+(int)packet->data[12])))/1094.0;
+                   break;
+      case 0x0406: this->mode=(op_mode)(packet->data[9]*256+packet->data[10]);
+                   this->gain_schedule=(gain)(((int)packet->data[11]<<8)+(int)packet->data[12]);
+                   this->ui_battery=1.4+(float)(((int)packet->data[13]<<8)+(int)packet->data[14])*0.0125;
+                   this->powerbase_battery=(float)(((int)packet->data[15]<<8)+(int)packet->data[16])/4.0;
+                   if(!this->event_server->event_is_set(this->new_status_event))
+                     this->event_server->set_event(this->new_status_event);
+                   break;
+      case 0x0407: break;
+      case 0x0680: this->hardware_mode=(op_mode)(packet->data[10]&0x03);
+                   if(!this->event_server->event_is_set(this->heartbeat_event))
+                     this->event_server->set_event(this->heartbeat_event);
+                   break;
+      case 0x0688: break;
+      default: /* handle exceptions */
+               break;
+    }
+    this->access_status.exit();
+  }
+}
+
+void *CSegwayRMP200::start_read_thread(void *param)
+{
+  CSegwayRMP200 *segway = (CSegwayRMP200 *) param;
+
+  segway->read_thread();
+}
+
+void CSegwayRMP200::read_thread(void)
+{
+  std::list<std::string> event_list;
+  int packet_len=0,event_id;
+  segway_packet packet;
+  bool end=false;
+
+  event_list.push_back(this->comm_rx_event);
+  event_list.push_back(this->read_finish_event);
+  while(!end)
+  {
+    event_id=this->event_server->wait_first(event_list);
+    if(event_id==0)
+    {
+      try{
+        if(this->read_packet(&packet,&packet_len))
+          this->parse_packet(&packet);
+      }catch(CException &e){
+        std::cout << e.what() << std::endl;
+        throw;
+      }
+    }
+    else
+    {
+      end=true; 
+    }
+  }
+
+  pthread_exit(NULL);
+}
+
+void *CSegwayRMP200::start_command_thread(void *param)
+{
+  CSegwayRMP200 *segway = (CSegwayRMP200 *) param;
+
+  segway->command_thread();
+}
+ 
+void CSegwayRMP200::command_thread(void)
+{
+  segway_packet packet={0xF0,0x55,0x00,0x00,0x00,0x00,0x04,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+  std::vector<unsigned char> command;
+  int exception_count=0;
+  bool end=false;
+  short int vT,vR;
+
+  while(!end)
+  {
+    usleep(100000);
+    this->access_command.enter();
+    vT=this->vT;
+    vR=this->vR;
+    this->access_command.exit();
+    packet.data[9]=((unsigned char *)&vT)[1];
+    packet.data[10]=((unsigned char *)&vT)[0];
+    packet.data[11]=((unsigned char *)&vR)[1];
+    packet.data[12]=((unsigned char *)&vR)[0];
+    this->access_command.enter();
+    if(this->command_queue.size()>0)
+    {
+      command=this->command_queue.front();
+      this->command_queue.pop();
+      packet.data[13]=command[0];
+      packet.data[14]=command[1];
+      packet.data[15]=command[2];
+      packet.data[16]=command[3];
+    }
+    this->access_command.exit();
+    packet.data[17]=this->compute_checksum(&packet);
+    try{
+      this->comm_dev->write(packet.data,18);
+      if(this->event_server->event_is_set(this->cable_disconnected_event))
+        this->event_server->reset_event(this->cable_disconnected_event);
+      if(this->event_server->event_is_set(this->power_off_event))
+        this->event_server->reset_event(this->power_off_event);
+    }catch(CFTDIException &e){// cable disconnected
+      exception_count=0;
+      if(!this->event_server->event_is_set(this->cable_disconnected_event))
+        this->event_server->set_event(this->cable_disconnected_event);
+    }catch(CCommException &e){// power off and also cable disconnected
+      exception_count++;
+      if(exception_count==2)
+      {
+        exception_count=0;
+        if(!this->event_server->event_is_set(this->power_off_event))
+          this->event_server->set_event(this->power_off_event);
+      }
+    }catch(CException &e){// something else
+      std::cout << e.what() << std::endl;
+      throw;
+    }
+    if(this->event_server->event_is_set(this->command_finish_event))
+    {
+      this->event_server->reset_event(this->command_finish_event);
+      end=true;
+    }
+  }
+
+  pthread_exit(NULL);
+}
+
+void *CSegwayRMP200::heartbeat_thread(void *param)
+{
+  CSegwayRMP200 *segway = (CSegwayRMP200 *) param;
+  std::list<std::string> events;
+
+  events.push_back(segway->heartbeat_event);
+  while(1)
+  {
+    try{
+      segway->event_server->wait_all(events,200);
+    }catch(CEventTimeoutException &e){
+      if(!segway->event_server->event_is_set(segway->no_heartbeat_event))
+        segway->event_server->set_event(segway->no_heartbeat_event);
+    }
+  }
+  
+  pthread_exit(NULL); 
+}
+
+// configuration functions
+void CSegwayRMP200::set_velocity_scale_factor(float factor)
+{
+  std::vector<unsigned char> command;
+  short int value;
+
+  if(factor < 0.0 || factor > 1.0)
+  {
+    /* handle exceptions */
+    throw CSegwayRMP200Exception(_HERE_,"Invalid scale factor for velocity",this->id);
+  }
+  else
+  {
+    command.resize(4);
+    value=(short int)(factor*16);
+    command[0]=0;
+    command[1]=10;
+    command[2]=((unsigned char *)&value)[1];
+    command[3]=((unsigned char *)&value)[0];
+    this->access_command.enter();
+    this->command_queue.push(command);
+    this->access_command.exit();
+  }
+}
+
+void CSegwayRMP200::set_acceleration_scale_factor(float factor)
+{
+  std::vector<unsigned char> command;
+  short int value;
+
+  if(factor < 0.0 || factor > 1.0)
+  {
+    /* handle exceptions */
+    throw CSegwayRMP200Exception(_HERE_,"Invalid scale factor for acceleration",this->id);
+  }
+  else
+  {
+    command.resize(4);
+    value=(short int)(factor*16);
+    command[0]=0;
+    command[1]=11;
+    command[2]=((unsigned char *)&value)[1];
+    command[3]=((unsigned char *)&value)[0];
+    this->access_command.enter();
+    this->command_queue.push(command);
+    this->access_command.exit();
+  }
+}
+
+void CSegwayRMP200::set_turnrate_scale_factor(float factor)
+{
+  std::vector<unsigned char> command;
+  short int value;
+
+  if(factor < 0.0 || factor > 1.0)
+  {
+    /* handle exceptions */
+    throw CSegwayRMP200Exception(_HERE_,"Invalid scale factor for turn rate",this->id);
+  }
+  else
+  {
+    command.resize(4);
+    value=(short int)(factor*16);
+    command[0]=0;
+    command[1]=12;
+    command[2]=((unsigned char *)&value)[1];
+    command[3]=((unsigned char *)&value)[0];
+    this->access_command.enter();
+    this->command_queue.push(command);
+    this->access_command.exit();
+  }
+}
+
+void CSegwayRMP200::set_gain_schedule(gain value)
+{
+  std::vector<unsigned char> command;
+
+  command.resize(4);
+  command[0]=0;
+  command[1]=13;
+  command[2]=((unsigned char *)&value)[1];
+  command[3]=((unsigned char *)&value)[0];
+  this->access_command.enter();
+  this->command_queue.push(command);
+  this->access_command.exit();
+}
+
+void CSegwayRMP200::set_currentlimit_scale_factor(float factor)
+{
+  std::vector<unsigned char> command;
+  short int value;
+
+  if(factor < 0.0 || factor > 1.0)
+  {
+    /* handle exceptions */
+    throw CSegwayRMP200Exception(_HERE_,"Invalid scale factor for current limit",this->id);
+  }
+  else
+  {
+    command.resize(4);
+    value=(short int)(factor*256);
+    command[0]=0;
+    command[1]=14;
+    command[2]=((unsigned char *)&value)[1];
+    command[3]=((unsigned char *)&value)[0];
+    this->access_command.enter();
+    this->command_queue.push(command);
+    this->access_command.exit();
+  }
+}
+
+void CSegwayRMP200::lock_balance(void)
+{
+  std::vector<unsigned char> command;
+
+  command.resize(4);
+  command[0]=0;
+  command[1]=15;
+  command[2]=0;
+  command[3]=1;
+  this->access_command.enter();
+  this->command_queue.push(command);
+  this->access_command.exit();
+}
+
+void CSegwayRMP200::unlock_balance(void)
+{
+  std::vector<unsigned char> command;
+
+  command.resize(4);
+  command[0]=0;
+  command[1]=15;
+  command[2]=0;
+  command[3]=0;
+  this->access_command.enter();
+  this->command_queue.push(command);
+  this->access_command.exit();
+}
+
+void CSegwayRMP200::set_operation_mode(op_mode mode)
+{
+  std::vector<unsigned char> command;
+std::cout << "set_operation_mode::hardware_mode=" << hardware_mode << " vs. mode=" << mode << std::endl;
+  if(this->hardware_mode==mode)
+  {
+    command.resize(4);
+    command[0]=0;
+    command[1]=16;
+    command[2]=((unsigned char *)&mode)[1];
+    command[3]=((unsigned char *)&mode)[0];
+    this->access_command.enter();
+    this->command_queue.push(command);
+    this->access_command.exit();
+  }
+  else
+  {
+    /* handle exceptions */
+    throw CSegwayRMP200Exception(_HERE_,"The platform current operation mode does not coincide with the desiered mode",this->id);
+  }
+}
+
+void CSegwayRMP200::reset_right_wheel_integrator(void)
+{
+  std::vector<unsigned char> command;
+
+  command.resize(4);
+  command[0]=0;
+  command[1]=50;
+  command[2]=0;
+  command[3]=1;
+  this->access_command.enter();
+  this->command_queue.push(command);
+  this->access_command.exit();
+}
+
+void CSegwayRMP200::reset_left_wheel_integrator(void)
+{
+  std::vector<unsigned char> command;
+
+  command.resize(4);
+  command[0]=0;
+  command[1]=50;
+  command[2]=0;
+  command[3]=2;
+  this->access_command.enter();
+  this->command_queue.push(command);
+  this->access_command.exit();
+}
+
+void CSegwayRMP200::reset_yaw_integrator(void)
+{
+  std::vector<unsigned char> command;
+
+  command.resize(4);
+  command[0]=0;
+  command[1]=50;
+  command[2]=0;
+  command[3]=4;
+  this->access_command.enter();
+  this->command_queue.push(command);
+  this->access_command.exit();
+}
+
+void CSegwayRMP200::reset_forward_integrator(void)
+{
+  std::vector<unsigned char> command;
+
+  command.resize(4);
+  command[0]=0;
+  command[1]=50;
+  command[2]=0;
+  command[3]=8;
+  this->access_command.enter();
+  this->command_queue.push(command);
+  this->access_command.exit();
+} 
+
+// status functions
+float CSegwayRMP200::get_pitch_angle(void)
+{
+  return this->pitch_angle;
+}
+
+float CSegwayRMP200::get_pitch_rate(void)
+{
+  return this->pitch_rate;
+}
+
+float CSegwayRMP200::get_roll_angle(void)
+{
+  return this->roll_angle;
+}
+
+float CSegwayRMP200::get_roll_rate(void)
+{
+  return this->roll_rate;
+}
+
+float CSegwayRMP200::get_left_wheel_velocity(void)
+{
+  return this->left_wheel_velocity;
+}
+
+float CSegwayRMP200::get_right_wheel_velocity(void)
+{
+  return this->right_wheel_velocity;
+}
+
+float CSegwayRMP200::get_yaw_rate(void)
+{
+  return this->yaw_rate;
+}
+
+float CSegwayRMP200::get_servo_frames(void)
+{
+  return this->servo_frames;
+}
+
+float CSegwayRMP200::get_left_wheel_displacement(void)
+{
+  return this->left_wheel_displ;
+}
+
+float CSegwayRMP200::get_right_wheel_displacement(void)
+{
+  return this->right_wheel_displ;
+}
+
+float CSegwayRMP200::get_forward_displacement(void)
+{
+  return this->forward_displ;
+}
+
+float CSegwayRMP200::get_yaw_displacement(void)
+{
+  return this->yaw_displ;
+}
+
+float CSegwayRMP200::get_left_motor_torque(void)
+{
+  return this->left_torque;
+}
+
+float CSegwayRMP200::get_right_motor_torque(void)
+{
+  return this->right_torque;
+}
+
+op_mode CSegwayRMP200::get_operation_mode(void)
+{
+  return this->mode;
+}
+
+op_mode CSegwayRMP200::get_hardware_operation_mode(void)
+{
+  return this->hardware_mode;
+}
+
+gain CSegwayRMP200::get_gain_schedule(void)
+{
+  return this->gain_schedule;
+}
+
+float CSegwayRMP200::get_ui_battery_voltage(void)
+{
+  return this->ui_battery;
+}
+
+float CSegwayRMP200::get_powerbase_battery_voltage(void)
+{
+  return this->powerbase_battery;
+}
+
+void CSegwayRMP200::connect(const std::string& desc_serial)
+{
+  std::string serial_number = desc_serial;
+  std::list<std::string> events;
+
+  // rescan the bus to update the local information
+  this->ftdi_server->scan_bus();
+
+  //if no serial number is provided
+  if(desc_serial.compare("") == 0)
+  {
+    std::vector<int> ftdi_devs;
+    ftdi_devs = this->ftdi_server->get_ids_by_description(CSegwayRMP200::description);
+    
+    //check how many segway devices are connected
+    //launch exception if there are no segways or there is more than one
+    if(ftdi_devs.size() != 1)
+    {
+      if(ftdi_devs.size() == 0)
+        throw CSegwayRMP200Exception(_HERE_, "No segways available", this->id);
+      else
+      {
+        throw CSegwayRMP200Exception(_HERE_, "More than one segway available", this->id);
+      }
+    }
+    serial_number = this->ftdi_server->get_serial_number(ftdi_devs.at(0));
+  }
+
+  TFTDIconfig ftdi_config;
+
+  if(this->comm_dev!=NULL)
+    this->close();
+
+  this->comm_dev=this->ftdi_server->get_device(serial_number);
+
+  ftdi_config.baud_rate     = 460800;
+  ftdi_config.word_length   = -1;
+  ftdi_config.stop_bits     = -1;
+  ftdi_config.parity        = -1;
+  ftdi_config.read_timeout  = 1000;
+  ftdi_config.write_timeout = 1000;
+  ftdi_config.latency_timer = 1;
+
+  this->comm_dev->config(&ftdi_config);
+  this->comm_rx_event=this->comm_dev->get_rx_event_id();
+  this->thread_server->start_thread(this->read_thread_id);
+  this->thread_server->start_thread(this->command_thread_id);
+  
+
+  // wait until the state has been updated for the first time
+  events.push_back(this->new_status_event);
+  events.push_back(this->heartbeat_event);
+  try
+  {
+    this->event_server->wait_all(events, 2000);
+    this->event_server->wait_all(events, 2000);
+  }
+  catch(CEventTimeoutException e)
+  {
+    this->close();
+    throw CSegwayRMP200Exception(_HERE_,"Segway connection not ready",this->id);
+  }
+
+  this->thread_server->start_thread(this->heartbeat_thread_id);
+}
+
+void CSegwayRMP200::reset(void)
+{
+  segway_packet packet={0xF0,0x55,0x00,0x00,0x00,0x00,0x04,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+
+  if(this->comm_dev==NULL)
+  {
+    /* handle exceptions */
+    throw CSegwayRMP200Exception(_HERE_,"Communciation device not set",this->id);
+  }
+  else
+  {
+    packet.data[17]=this->compute_checksum(&packet);
+    this->comm_dev->write(packet.data,18);
+  }
+
+}
+	
+void CSegwayRMP200::move(float vT,float vR)
+{
+std::cout << "move::hardware_mode=" << hardware_mode << " vs. mode=" << mode << std::endl;
+  if(this->mode!=this->hardware_mode)
+  {
+    /* handle exceptions */
+    throw CSegwayRMP200Exception(_HERE_,"The desired operation mode does not coincide with the one set in the platform.",this->id);
+  }
+  else
+  {
+    this->access_command.enter();
+    this->vT = (short int)(vT*3.6*147.0/1.609344);
+    this->vR = (short int)(vR*1024.0);
+    this->access_command.exit();
+  }
+}
+
+void CSegwayRMP200::stop(void)
+{
+  this->access_command.enter();
+  this->vT = 0;
+  this->vR = 0;
+  this->access_command.exit();
+}
+
+void CSegwayRMP200::close()
+{
+  //kill threads
+  if(this->comm_dev!=NULL)
+  {
+    // finish the threads
+    this->event_server->set_event(this->read_finish_event);
+    this->event_server->set_event(this->command_finish_event);
+    this->thread_server->end_thread(this->read_thread_id);
+    this->thread_server->end_thread(this->command_thread_id);
+    this->thread_server->kill_thread(this->heartbeat_thread_id);
+    /* reset the events if necessary */
+    this->event_server->reset_event(this->read_finish_event);
+    this->event_server->reset_event(this->command_finish_event);
+    if(this->event_server->event_is_set(this->no_heartbeat_event))
+      this->event_server->reset_event(this->no_heartbeat_event);
+    if(this->event_server->event_is_set(this->power_off_event))
+      this->event_server->reset_event(this->power_off_event);
+    if(this->event_server->event_is_set(this->cable_disconnected_event))
+      this->event_server->reset_event(this->cable_disconnected_event);
+    this->comm_dev->close();
+    delete this->comm_dev;
+    this->comm_dev=NULL;
+  }
+}
+
+CSegwayRMP200::~CSegwayRMP200()
+{
+  this->close();
+  /* destroy the events */
+  this->event_server->delete_event(this->read_finish_event);
+  this->read_finish_event="";
+  this->event_server->delete_event(this->command_finish_event);
+  this->command_finish_event="";
+  this->event_server->delete_event(this->cable_disconnected_event);
+  this->cable_disconnected_event="";
+  this->event_server->delete_event(this->power_off_event);
+  this->power_off_event="";
+  this->event_server->delete_event(this->no_heartbeat_event);
+  this->no_heartbeat_event="";
+  this->event_server->delete_event(this->heartbeat_event);
+  this->heartbeat_event="";
+  this->event_server->delete_event(this->new_status_event);
+  this->new_status_event="";
+  // destroy the threads
+  this->thread_server->delete_thread(this->read_thread_id);
+  this->read_thread_id="";
+  this->thread_server->delete_thread(this->command_thread_id);
+  this->command_thread_id="";
+  this->thread_server->delete_thread(this->heartbeat_thread_id);
+  this->heartbeat_thread_id="";
+}
+
+std::ostream& operator<< (std::ostream& out, CSegwayRMP200& segway)
+{
+  segway.access_status.enter();
+  out << "Pitch angle: " << segway.pitch_angle << " degrees" << std::endl;
+  out << "Pitch rate " << segway.pitch_rate << " degrees/s" << std::endl;
+  out << "Roll angle: " << segway.roll_angle << " degrees" << std::endl;
+  out << "Roll rate: " << segway.roll_rate << " degrees/s" << std::endl;
+  out << "Left wheel velocity: " << segway.left_wheel_velocity << " m/s" << std::endl;
+  out << "Right wheel velocity: " << segway.right_wheel_velocity << " m/s" << std::endl;
+  out << "Yaw rate: " << segway.yaw_rate << " degrees/s" << std::endl;
+  out << "Servo frames: " << segway.servo_frames << " frames/s" << std::endl;
+  out << "Left wheel displacement: " << segway.left_wheel_displ << " m" << std::endl;
+  out << "Right wheel displacement: " << segway.right_wheel_displ << " m" << std::endl;
+  out << "Forward displacement: " << segway.forward_displ << " m" << std::endl;
+  out << "Yaw displacement: " << segway.yaw_displ << " rev" << std::endl;
+  out << "Left motor torque: " << segway.left_torque << " Nm" << std::endl;
+  out << "Right motor torque: " << segway.right_torque << " Nm" << std::endl;
+  if(segway.mode==tractor)
+    out << "Operation mode: tractor" << std::endl;
+  else if(segway.mode==balance)
+    out << "Operation mode: balance" << std::endl;
+  else 
+    out << "Operation mode: power down" << std::endl;
+  if(segway.hardware_mode==tractor)
+    out << "Hardware operation mode: tractor" << std::endl;
+  else if(segway.hardware_mode==balance)
+    out << "Hardware operation mode: balance" << std::endl;
+  else 
+    out << "Hardware operation mode: power down" << std::endl;
+  if(segway.gain_schedule==light)
+    out << "Gain schedule: light" << std::endl;
+  else if(segway.gain_schedule==tall)
+    out << "Gain schedule: tall" << std::endl;
+  else 
+    out << "Gain schedule: heavy" << std::endl;
+  out << "UI battery voltage: " << segway.ui_battery << " V" << std::endl;
+  out << "Powerbase battery voltage: " << segway.powerbase_battery << " V" << std::endl;
+  segway.access_status.exit();
+
+  return out;
+}
diff --git a/src/segway_rmp200.h b/src/segway_rmp200.h
new file mode 100755
index 0000000000000000000000000000000000000000..e83f0369f8a670a1e3dbc0c3e35cd363b4c1c4e5
--- /dev/null
+++ b/src/segway_rmp200.h
@@ -0,0 +1,1421 @@
+#ifndef _SEGWAYRMP200_DRIVER_H
+#define _SEGWAYRMP200_DRIVER_H
+
+#include "ftdimodule.h"
+#include "ftdiserver.h"
+#include "mutex.h"
+#include <string>
+#include <vector>
+#include <queue>
+
+/**
+ * \brief structure of a USB packet 
+ *
+ * This new data type has all the information of a data packet send to or received
+ * from the USB communication device. This data type is only 18 unsigned char values 
+ * arranged as a vector.
+ *
+ */
+typedef struct 
+{
+  /**
+   * \brief packet data
+   *
+   * This vector has all the data of a packet that has been received or that is going
+   * to be sent. The format of this packet is as follows:
+   *
+   */  
+  unsigned char data[18];
+}segway_packet;
+
+/**
+ * \brief Valid gain schedules for the segway
+ *
+ * This new data type enumerates all the possible gain schedules of a segway platform.
+ * This data type is only used on the balancing mode and ignored in the tractor mode.
+ * The possible gain schedule values are:
+ *
+ * - light: for relativelly small weights (20 kg) placed near the platform.
+ * - tall: for relativelly small weights (20 kg) distributed along the vertical axis
+ *         of the robot.
+ * - heavy: for heavy weights (40 kg) placed near the platform.
+ *
+ */
+typedef enum {light,tall,heavy} gain;
+
+/**
+ * \brief Valid operation modes of the segway
+ *
+ * This new data type enumerates all the possible operation modes of a segway platform.
+ * The possible operation modes are:
+ *
+ * - tractor: in this mode the balancing feature is disabled and the platform needs an
+ *            additional support point (castor wheel). In this mode it is possible to
+ *            command the robot to move forward/reverse and also turn.
+ * - balance: in this mode the segway balances itself, trying to keep the given position.
+ *            In this mode it is possible to move the robot without a castor wheel.
+ * - power down: the platform is shut down and no power is provided to the motors. It is 
+ *               possible to enter this mode from either the tractor and balance modes.
+ *
+ */
+typedef enum {tractor=1,balance=2,power_down=3} op_mode;
+
+/**
+ * \brief Segway RMP 200 driver
+ *
+ * This class implements the basic interface to communcate with an RMP200 segway platform,
+ * configure it and also send motion commands. By default the communication with the 
+ * hardware platform is achieved through USB.
+ *
+ * At construction time the object tries to connect to a platform. If only one platform is
+ * connected to the computer, the default constructor can be used, but if there exist 
+ * multiple segway platforms, it is necessary to pass the serial number to the constructor
+ * In order to connect to the desired one and avoid errors.
+ * 
+ * When the object is properly contructed, the two main threads of the class start. These 
+ * threads are:
+ *
+ * - The command thread: which is responsible of sending the mnotion command to the platform
+ *                       at regular intervals. Currently the update rate for the motion 
+ *                       command is fixed to 50 times per second. 
+ *
+ *                       When the user gives a motion command using the move() or stop() 
+ *                       functions, the new command is not immediatelly send to the robot,
+ *                       but stored into internal parameters of the class. It is this thread
+ *                       that sends the new commands to the robot at regular intervals. The
+ *                       same happens with all the configuration parameters, when the 
+ *                       corresponding function is called, the command is internally stored
+ *                       and send in the next command packet to the platform.
+ *
+ *                       At the moment it is not possible to change the update rate of the 
+ *                       motion commands.
+ *
+ * - The feedback thread: this thread is responsible of reding all the data sent by the 
+ *                        robot platform and store it in the internal parameters of the 
+ *                        class as fast as they are sent.
+ *
+ *                        When the user tries to read the value of one of the parameters 
+ *                        of the platform, the returned value is the one stored inside 
+ *                        the class, which are updated by this thread.
+ *
+ *                        At the moment only data messages from 2 to 7 are handled, as well
+ *                        as the heart beat. The other messages are received but ignored.
+ *
+ * The public interface of this class alows to completelly configure all the parameters of
+ * the segway platform as well as monitor each of the available feedback parameters. Also
+ * there exist an operator << to show all feedback information already formated.
+ *
+ * This class also has support for unexpected hardware events such as diconnection of the
+ * USB cable, turning the platform power off or no reception of the heartbeat message for
+ * a long period. Primary, this actions are reported by dedicated events that are created 
+ * internally at construction time. These events are:
+ *
+ * - cable_disconnected_event: when activated, it notifies that the USB cable has been
+ *                             disconnected from the platform. When this happens, the normal
+ *                             operation of the class is interrupted, but it does not crash.
+ *                             After this event is received, it will be necessary to call the
+ *                             close() function and the connect() function again to restore
+ *                             normal operation.
+ *
+ *                             When the connection is restored, this event is automatically
+ *                             cleared.
+ *
+ * - power_off_event : when activated, it notifies that the platform is not powerd on. This
+ *                     normally happens at start up when the green button on the platform is
+ *                     not lid or when an error ocurrs. When this event is active, the normal
+ *                     operation of the class is interrupted, but it is not necessary to
+ *                     close and reconnect the object. When the problem is solved, the class
+ *                     automatically returns to the normal operation mode.
+ * 
+ *                     When the connection is restored, this event is automatically cleared.
+ * 
+ * - no_heartbeat_event : when activated, it notifies that the platform is turned on, but no
+ *                        data is received from it. The class has an internal thread that
+ *                        works as a watchdog: when a heartbeat message is received, the 
+ *                        watchdog counter is reset, but if this message is not received for
+ *                        a long time, the watchdog times out and generates an event.
+ * 
+ *                        When this event is active, the normal operation of the class is 
+ *                        interrupted, but it is not necessary to close and reconnect the
+ *                        object. When the problem is solved, the class automatically returns
+ *                        to the normal operation. When the connection is restored, this event 
+ *                        is automatically cleared.
+ *
+ * Finally, in addition to the previously defined events, the class also provide an event to
+ * notify when a new complete status data is available. This event can be used to avoid
+ * reading the same data several times. 
+ */
+class CSegwayRMP200
+{
+  public:
+    /**
+     * \brief segway PID
+     *
+     * This constant holds the PID number used by the segway platforms. It is defined
+     * as static so it can be used even if no instance of this class exists. 
+     */
+    static const short int pid;
+    /**
+     * \brief Segway platform description
+     *
+     * This constant holds the description string of the segway platforms. It is
+     * defined as static so it can be used even if no instance of this class
+     * exists. 
+     *
+     * This description can be used in the FTDI server to identify the segway platforms
+     * from any other FTDI device connected to the computer.
+     */
+    static const std::string description;
+  private:
+    /**
+     * \brief unique identifier of the segway platform
+     *
+     * This string has the unique identifier of the segway platform. This string is
+     * initialized at construction time and can not be modified afterwards. The 
+     * get_segway_id() function can be used to get this string. 
+     *
+     * This string is also used to create unique identifier for all the threads and
+     * events used inside the class. This identifier is build from the serial number
+     * of the segway platform to which it is connected.
+     *
+     */
+    std::string id;
+    /**
+     * \brief mutex for the status data
+     *
+     * This mutex is used to control the access to the status variables (shared memory)
+     * of the class. These variables are periodically updated by the feedback thread 
+     * and they can be read by the user at any time using the get functions. 
+     *
+     * This mutex is used by the feedback thread and all the get status function to 
+     * avoid data corruption while simultaneously reading and writing to the status 
+     * variable of the segway platform. There exist a different mutex for the command 
+     * data.
+     *
+     */
+    CMutex access_status;
+    /**
+     * \brief mutex for the command data
+     *
+     * This mutex is used to control the access to the command variables (shared memory)
+     * of the class. These variables are changed by the user at any time using the mov()
+     * or stop() functions, and the new command is actually send to the segway platform
+     * periodically by the command thread. 
+     *
+     * This mutex is used by the command thread and all the motion function to avoid data
+     * corruption while simultaneously reading and writing to the command variable of the
+     * segway platform. There exist a different mutex for the status data.
+     */
+    CMutex access_command;
+    /**
+     * \brief a reference to the FTDI USB device
+     *
+     * This attribute points to the communication device used to send and receive data 
+     * to and from the segway platform. The communication device is cretaed inside the 
+     * object at initialization time using the CFTDIServer and the description or serial
+     * number of the desired platform via the connect() function.
+     *
+     * It is not possible to send or receive data to or from the platform until the 
+     * driver is not connected to the hardware platform. Any attempt to do so will 
+     * result in an exception being thrown.
+     *
+     */
+    CFTDI *comm_dev;
+    /**
+     * \brief reference to the unique ftdi_server
+     *
+     * This reference to the unique ftdi server is initialized when an object of
+     * this class is first created. It is used to create and handle all the
+     * FTDI device drivers used to access the segway platform. The object pointed 
+     * by this reference is shared by all objects in any application.
+     *
+     */
+    CFTDIServer *ftdi_server; 
+    /**
+     * \brief Reference to the unique event handler
+     *
+     * This reference to the unique event handler is initialized when an object of
+     * this class is first created. It is used to create and handle all the
+     * segway platform events. The object pointed by this reference is shared by all
+     * objects in any application.
+     */
+    CEventServer *event_server;
+    /**
+     * \brief Reference to the unique thread handler
+     *
+     * This reference to the unique thread handler is initialized when an object of
+     * this class is first created. It is used to create and handle all the
+     * segway platform threads. The object pointed by this reference is shared by all
+     * objects in any application.
+     */
+    CThreadServer *thread_server;
+    /**
+     * \brief identifier of the feedback thread
+     *
+     * This string has the identifier of the thread used to read status information from
+     * the segway platform. This string is initialized at contruction time by appending
+     * the unique identifier of the segway object and the string "_read_thread". This
+     * thread is only used internally to the class, so it is not possible to get its
+     * identifier out.
+     */
+    std::string read_thread_id;
+    /**
+     * \brief identifer of the command thread
+     *
+     * This string has the identifier of the thread used to send motion commands to 
+     * the segway platform. This string is initialized at contruction time by appending
+     * the unique identifier of the segway object and the string "_command_thread". This
+     * thread is only used internally to the class, so it is not possible to get its
+     * identifier out.
+     */
+    std::string command_thread_id;
+    /**
+     * \brief segway heartbeat thread
+     *
+     * This string has the idetifier of the thread used to check the periodic reception
+     * of the heartbeat signal send by the segway platform. This string is initialized 
+     * at contruction time by appending the unique identifier of the segway object and 
+     * the string "_heartbeat_thread". This thread is only used internally to the class, 
+     * so it is not possible to get its identifier out.
+     */
+    std::string heartbeat_thread_id;
+    /**
+     * \brief identifier of the reception event of the communication device
+     * 
+     * This string has the identifier of the event generated by the communcation device 
+     * to signal de reception of new data. This event is not created by this class, but
+     * retrieved from the communication device when it is attached to this class. This
+     * event is used by the read thread to awake when new data is received. 
+     */
+    std::string comm_rx_event;
+    /**
+     * \brief identifier of the event to finish the feedback thread
+     *
+     * This string has the identifier of the event used to signal the feedback thread
+     * to end its execution. This string is initialized at contruction time by appending
+     * the unique identifier of the segway object and the string "_finish_read_thread".
+     * This event is only used inside the class, so it is not possible to get its
+     * identifier out.
+     */
+    std::string read_finish_event;
+    /**
+     * \brief identifier of the event to finish the command thread
+     *
+     * This string has the identifier of the event used to signal the command thread
+     * to end its execution. This string is initialized at contruction time by appending
+     * the unique identifier of the segway object and the string "_finish_command_thread".
+     * This event is only used inside the class, so it is not possible to get its
+     * identifier out.
+     */
+    std::string command_finish_event;
+    /**
+     * \brief identifier of the event to signal that the platform is powered off
+     *
+     * This string has the identifier of the event used to signal that the platform is
+     * powered off. This string is initialized at contruction time by appending
+     * the unique identifier of the segway object and the string "_power_off_event".
+     * Use the get_power_off_event() function to get the event identifier from
+     * outside the class.
+     */
+    std::string power_off_event;
+    /**
+     * \brief identifier of the event to signal that the cable is disconnected
+     *
+     * This string has the identifier of the event used to signal that the USB 
+     * cable is disconnected. This string is initialized at contruction time by 
+     * appending the unique identifier of the segway object and the string 
+     * "_cable_disconnected_event". Use the get_cable_disconnected_event() 
+     * function to get the event identifier from outside the class.
+     */
+    std::string cable_disconnected_event;
+    /**
+     * \brief identifier of the event to signal the availability of new status data
+     *
+     * This string has the identifier of the event used to signal the availability
+     * of new status data. This string is initialized at contruction time by 
+     * appending the unique identifier of the segway object and the string 
+     * "_new_status_event". Use the get_new_status_event() function to 
+     * get the event identifier from outside the class.
+     */
+    std::string new_status_event;
+    /**
+     * \brief identifeir of the event to signal the absence of the heartbeat signal
+     *
+     * This string has the identifier of the event used to signal that no heartbeat
+     * has been received for a while. This string is initialized at contruction time 
+     * by appending the unique identifier of the segway object and the string 
+     * "_no_heartbeat_event". Use the get_no_heartbeat_event() function to 
+     * get the event identifier from outside the class.
+     */
+    std::string no_heartbeat_event;
+    /**
+     * \brief identifeir of the internal heartbeat event
+     *
+     * This string has the identifier of the heartbeat event .This string is 
+     * initialized at contruction time by appending the unique identifier of 
+     * the segway object and the string "_heartbeat_event". This event is only 
+     * used inside the class, so it is not possible to get its identifier out.
+     */
+    std::string heartbeat_event;
+    /**
+     * \brief class attributes initialization
+     *
+     * This method initalizes all the internal class variables at construction time.
+     */
+    void init_attributes(void);
+    /**
+     * \brief ftdi server initialization
+     *
+     * This method initializes the ftdi_server to handle all the FTDI devices  
+     * and also adds the specific PID of the segway platforms in order to be able
+     * to detect and list them.
+     */
+    void init_ftdi(void);
+    /**
+     * \brief function to initialize the class threads
+     *
+     * This method initializes all the internal threads of the class. This includes
+     * the read and command threads and also the heartbeat thread. 
+     * 
+     * All the threads are created and assigned their corresponding execution function
+     * but they are not started until the connection to the platform is done, either
+     * at construction time or when the connect function is called.
+     */
+    void init_threads(void);
+    /**
+     * \brief function to initialize the class events
+     * 
+     * This function initializes all the internal and external events of the class.
+     * 
+     */
+    void init_events(void);
+  protected:
+    // status variables
+    /**
+     * \brief left wheel velocity
+     *
+     * This value has the velocity of the left wheel in meters per second. This value is
+     * periodically updated by the read thread and it is not possible to modify it 
+     * otherwise. To get its value use the get_left_wheel_velocity() function or the
+     * overloaded operator <<.
+     */
+    float left_wheel_velocity;
+    /**
+     * \brief right wheel velovity
+     *
+     * This value has the velocity of the right wheel in meters per second. This value is
+     * periodically updated by the read thread and it is not possible to modify it 
+     * otherwise. To get its value use the get_right_wheel_velocity() function or the
+     * overloaded operator <<.
+     */
+    float right_wheel_velocity;
+    /**
+     * \brief pitch angle
+     *
+     * This value has the pitch angle of the platform in degrees. This value is
+     * periodically updated by the read thread and it is not possible to modify it 
+     * otherwise. To get its value use the get_pitch_angle() function or the
+     * overloaded operator <<.
+     */
+    float pitch_angle;
+    /**
+     * \brief pitch rate
+     *
+     * This value has the pitch rate of the platform in degrees per second. This value is
+     * periodically updated by the read thread and it is not possible to modify it 
+     * otherwise. To get its value use the get_pitch_rate() function or the
+     * overloaded operator <<.
+     */
+    float pitch_rate;
+    /**
+     * \brief roll angle
+     *
+     * This value has the roll angle of the platform in degrees. This value is
+     * periodically updated by the read thread and it is not possible to modify it 
+     * otherwise. To get its value use the get_roll_angle() function or the
+     * overloaded operator <<.
+     */
+    float roll_angle;
+    /**
+     * \brief roll rate
+     *
+     * This value has the roll rate of the platform in degrees per second. This value is
+     * periodically updated by the read thread and it is not possible to modify it 
+     * otherwise. To get its value use the get_roll_rate() function or the
+     * overloaded operator <<.
+     */
+    float roll_rate;
+    /**
+     * \brief yaw rate
+     *
+     * This value has the yaw rate of the platform in degrees per second. This value is
+     * periodically updated by the read thread and it is not possible to modify it 
+     * otherwise. To get its value use the get_yaw_rate() function or the
+     * overloaded operator <<.
+     */
+    float yaw_rate;
+    /**
+     * \brief number of frames per second
+     *
+     * This value has the number of servo frames in fames per second. This value is
+     * periodically updated by the read thread and it is not possible to modify it 
+     * otherwise. To get its value use the get_servo_frames() function or the
+     * overloaded operator <<.
+     */
+    float servo_frames; 
+    /**
+     * \brief left wheel displacement
+     *
+     * This value has the displacement of the left wheel in meters. This value is
+     * periodically updated by the read thread and it is not possible to modify it 
+     * otherwise. To get its value use the get_left_wheel_displacement() function 
+     * or the overloaded operator <<.
+     */
+    float left_wheel_displ;
+    /**
+     * \brief right wheel displacement
+     *
+     * This value has the displacement of the right wheel in meters. This value is
+     * periodically updated by the read thread and it is not possible to modify it 
+     * otherwise. To get its value use the get_right_wheel_displacement() function 
+     * or the overloaded operator <<.
+     */
+    float right_wheel_displ;
+    /**
+     * \brief forward displacement
+     *
+     * This value has the displacement of the whole platform in meters. This value is
+     * periodically updated by the read thread and it is not possible to modify it 
+     * otherwise. To get its value use the get_forward_displacement() function 
+     * or the overloaded operator <<.
+     */
+    float forward_displ;
+    /**
+     * \brief yaw displacement
+     *
+     * This value has the rotation of the whole platform in revolutions. This value is
+     * periodically updated by the read thread and it is not possible to modify it 
+     * otherwise. To get its value use the get_yaw_displacement() function 
+     * or the overloaded operator <<.
+     */
+    float yaw_displ;
+    /**
+     * \brief left motor torque
+     *
+     * This value has the torque of the left motor in Newtorn per meter. This value is
+     * periodically updated by the read thread and it is not possible to modify it 
+     * otherwise. To get its value use the get_left_motor_torque() function 
+     * or the overloaded operator <<.
+     */
+    float left_torque;
+    /**
+     * \brief right motor torque
+     *
+     * This value has the torque of the right motor in Newtorn per meter. This value is
+     * periodically updated by the read thread and it is not possible to modify it 
+     * otherwise. To get its value use the get_right_motor_torque() function 
+     * or the overloaded operator <<.
+     */
+    float right_torque;
+    /**
+     * \brief operation mode
+     *
+     * This value has the current operation mode of the platform. This value is
+     * periodically updated by the read thread and it is not possible to modify it 
+     * otherwise. To get its value use the get_operation_mode() function 
+     * or the overloaded operator <<. The possible operation modes are:
+     *
+     * - tractor
+     * - balance
+     * - power down
+     *
+     * See the documentation of the op_mode data type for more information on the
+     * possible operation modes.
+     */
+    op_mode mode;
+    /**
+     * \brief hardware operation mode
+     *
+     * This value has the current hardware operation mode of the platform. This 
+     * value is periodically updated by the read thread and it is not possible to 
+     * modify it otherwise. To get its value use the get_hardware_operation_mode() 
+     * function or the overloaded operator <<. The possible operation modes are:
+     *
+     * - tractor
+     * - balance
+     * - power down
+     *
+     * See the documentation of the op_mode data type for more information on the
+     * possible operation modes.
+     *
+     * This operation mode coincides with the platfrom settings (which of the two
+     * blue buttons are on). This operation mode must coincide with the operation 
+     * mode set by the user.
+     */
+    op_mode hardware_mode;
+    /**
+     * \brief gain schedule
+     *
+     * This value has the current gain schedule of the platform. This value is
+     * periodically updated by the read thread and it is not possible to modify it 
+     * otherwise. To get its value use the get_gain_schedule() function 
+     * or the overloaded operator <<. The possible gain schedules are:
+     *
+     * - light
+     * - tall
+     * - heavy.
+     *
+     * See the documentation of the gain data type for more information on the 
+     * possible gain schedule.
+     */
+    gain gain_schedule;
+    /**
+     * \brief user battery
+     *
+     * This value has the voltage of the UI battery in Volts. This value is
+     * periodically updated by the read thread and it is not possible to modify it 
+     * otherwise. To get its value use the get_ui_battery_voltage() function 
+     * or the overloaded operator <<.
+     */
+    float ui_battery;
+    /**
+     * \brief power base battery
+     *
+     * This value has the voltage of the power base battery in Volts. This value is
+     * periodically updated by the read thread and it is not possible to modify it 
+     * otherwise. To get its value use the get_powerbase_battery_voltage() function 
+     * or the overloaded operator <<.
+     */
+    float powerbase_battery;
+    // command variables
+    /**
+     * \brief translation velocity
+     * 
+     * This value has the desired translational velocity in meters per second. This 
+     * values is updated each time the move() or stop() functions are called. Then
+     * this value is sent periodically to the segway platform by the command thread.
+     */
+    short int vT; 
+    /**
+     * \brief rotation velocity
+     *
+     * This value has the desired rotational velocity in revolutions per second. This 
+     * values is updated each time the move() or stop() functions are called. Then
+     * this value is sent periodically to the segway platform by the command thread.
+     */
+    short int vR; 
+    /**
+     * \brief internal command queus
+     *
+     * This queue is used to store configuration commands to be send to the platform.
+     * Initially, this queue is empty, and its length increases each time a set() or
+     * reset() function is called. The command thread checks this queue every time it
+     * is about to send a new command to include any configuration data if needed.
+     */
+    std::queue< std::vector<unsigned char> > command_queue;
+    // methods
+    /**
+     * \brief function to compute checksum of USB packets 
+     *
+     * This function computes the checksum of a given USB packet either received from
+     * the platform or to be send to it. When a new packet is received this function 
+     * is used to check that the packet has no errors. Since the packet is sent with
+     * a checksum, the return value of this function should be 0.
+     *
+     * When a packet is about to be sent, this function is used to compute the 
+     * checksum value for the packet. The returned value then is used to complete
+     * the data packet (18th bytes) before it is sent to the segway platform.
+     *
+     * This function is only used internally by the feedback and command threads,
+     * but it can not be used elsewhere.
+     *
+     * \param packet a reference to the packet on which to compute the chcksum. If
+     *               the packet has been received it should already has a checksum
+     *               value at the 18th position, and otherwise this position should
+     *               be set to 0 to correctly compute the checksum.
+     *
+     * \return the value of the checksum. If the packet has been received, this value 
+     *         should be 0 for a valid packet and any other value otherwise. If the 
+     *         packet is to be sent, this value is the checksum to be used to complete
+     *         the packet.
+     */		
+    unsigned char compute_checksum(segway_packet *packet);
+    /**
+     * \brief function to read a whole packet from the segway platform
+     *
+     * This functions is used to read full packets from the segway platform. It first 
+     * syncronizes the incomming data to detect the packet header, and then stores all
+     * the data of the packet in the given packet strcuture. 
+     *
+     * This function reads all available data and returns immediatelly even if the 
+     * whole packet has not been received. If several packets have been received, this
+     * function returns after reading the first one, and the function has to be recalled
+     * until no more data is available. This function is only used internally by the 
+     * feedback thread.
+     *
+     * \param packet a reference to a packet structure in which to store the received 
+     *               packet. The necessary memory for this structure has to be allocated
+     *               before calling this function. This contents of this structure are
+     *               only valid when the return value of this function is true, otherwise
+     *               its contents should be ignored, but not modified since it has 
+     *               partial packet information.
+     * \param packet_len an integer with the size of the read packet. If the packet is 
+     *                   completely received in a single call, this value is always 18 
+     *                   (the dafault length). In case the packet is not completelly 
+     *                   received in a single call, this parameter is used to hold the 
+     *                   actual number of bytes read, and the same variable must be used 
+     *                   in the next call to this function to guarantee a correct reception 
+     *                   of all data packets.
+     *
+     * \return a flag that indicated if a whole packet has been read (true) or not (false).
+     *         only when the return value is true, the contents of the packet parameter
+     *         can be used.
+     */
+    bool read_packet(segway_packet *packet,int *packet_len);
+    /**
+     * \brief function to parse whole packets read from the segway platform
+     *
+     * This function is used to extract the data contained into the data packets received.
+     * The checksum is first checked and if there is any error, an exception is thrown.
+     * Otherwise, the data from the packet is stored into the corresponding internal 
+     * attributes of the class.
+     *
+     * This function blocks the status mutex to avoid errors while updating the internal
+     * attributes. This way all functions to get the current status will get blocked until
+     * the update is complete.
+     *
+     * \param packet a reference to a packet structure which stores the data of a new 
+     *               received packet. The packet passed to this function should be the
+     *               one returned by the read_packet() function. 
+     *
+     */
+    void parse_packet(segway_packet *packet);
+    /**
+     * \brief Thread function that reads data from segway
+     *
+     * This functions waits for any data to be received from the segway platform. When a whole
+     * packet is read from the robot, it is parsed and then the internal information of the class
+     * updated.
+     *
+     * This thread is created at construction time but it is not started until the communication
+     * device is attached to avoid errors. This thread is always active until the finish event is
+     * activated, which happens when the close() function is called.
+     * 
+     * \return in this case, the function always return NULL, so no data is returned to the 
+     *         main thread.
+     */
+    void read_thread(void);
+    /**
+     * \brief start read thread
+     *
+     * This function starts the read thread.
+     *
+     * \param param a pointer to the object itself. since this function is statis, there exist no
+     *              this pointer, so this parameter is used to access the internal attributes of
+     *              the class.
+     */
+    static void *start_read_thread(void *param); 
+    /**
+     * \brief Thread function that sends commands to the segway
+     *
+     * This function is used to send motion commands to the segway platform periodically. This 
+     * functions gets the internal motion commands (translational and rotational velocities) from
+     * the class and sends it to the robot every 20ms. At this moment it is not possible to
+     * change the update drate of the motion commandsi.
+     * 
+     * This thread also checks the internal command queue to check if there is any configuration
+     * data avaialble. If so, it reads the contents of the first commans and includes it into the
+     * packet data to be send. If no new configuration data is available, this thread only sends 
+     * motion commands.
+     *
+     * This thread is created at construction time but it is not started until the communication
+     * device is attached to avoid errors. This thread is always active until the finish event is
+     * activated, which happens when the close() function is called. If this thread ends unexpectly
+     * the robot will stop after a few moments, since it requires constant commands from the host
+     * computer to continued operation.
+     *
+     * To change the current motion command, use the move() function. The stop() function should
+     * be used to immediatelly stop the motors. These functions will modify the internal attributes
+     * of the class, and this thread will be the one responsible of sending the new commands to
+     * the robot.
+     * 
+     * \return in this case, the function always return NULL, so no data is returned to the 
+     *         main thread.
+     *
+     */
+    void command_thread(void);
+    /**
+     * \brief start command thread
+     *
+     * This function starts the command thread.
+     *
+     * \param param a pointer to the object itself. since this function is statis, there exist no
+     *              this pointer, so this parameter is used to access the internal attributes of
+     *              the class.
+     */
+    static void *start_command_thread(void *param);
+    /**
+     * \brief heartbeat thread function
+     * 
+     * This threads waits for the heartbeat event generated by the reception of a specific 
+     * data packet from the segway platform for a given ammount of time.
+     *
+     * While this data packet is received the thread does nothing. When the communications
+     * are interrupted or the power is turned off, the allowed ammount of time elapses 
+     * and the external no_heartbeat_event is set to notify the error to the user. The
+     * operation of this thread is equivalent to a watchdog.
+     *
+     * If the problem is solved, the event is reset and the normal operation of the 
+     * driver continues.
+     */
+    static void *heartbeat_thread(void *param);
+  public:
+    /**
+     * \brief constructor
+     *
+     * This constructor creates and initializes all the threads and events nedded by the class.
+     * However, the threads are not started until the connect() function is called. This 
+     * constructor accepts a string with the serial number of the segway platform, which is used to 
+     * create the unique identifiers of both events and threads.
+     * 
+     * If no serial number is provided, the class tries to automatically connect to the 
+     * platfrom. In this case is more or less than one platforms are connected to the
+     * computer, the constructor throws an exception.
+     *
+     * \param desc_serial a null terminated string with the description or the serial
+     *                    number of the segway platform to associate to the driver.
+     *                    This string can be obtanied through the CFTDIServer or else
+     *                    hardcoded if known.
+     */
+    CSegwayRMP200(const std::string& desc_serial="");
+    /**
+     * \brief function to get the identifeir of the segway
+     *
+     * This function is used to get the unique identifier of the segway platform associated
+     * to the driver.
+     *
+     * \return a null terminated string with the identifier of the segway.
+     */
+    std::string get_id(void);
+    /**
+     * \brief function to get the identifier of the cable disconnected event
+     *
+     * This function returns the identifier of the cable disconnected event. This
+     * event can be used by an external application to monitor the state of the
+     * segway platform.
+     */
+    std::string get_cable_disconnected_event(void);
+    /**
+     * \brief function to get the identifier of the power off event
+     *
+     * This function returns the identifier of the power off event. This
+     * event can be used by an external application to monitor the state of the
+     * segway platform.
+     */
+    std::string get_power_off_event(void);
+    /**
+     * \brief function to get the no heartbeat event
+     *
+     * This function returns the identifier of the cable no heartbeat event. This
+     * event can be used by an external applciation to monitor the state of the
+     * segway platform.
+     */
+    std::string get_no_heartbeat_event(void);
+    /**
+     * \brief function to get the new status data available event
+     *
+     * This function returns the identifier of the new status data available event. 
+     * This event can be used by an external application to know when there exist
+     * new data, and avoid polling the driver too fast or too slowly.
+     */
+    std::string get_new_status_event(void);
+    // configuration functions
+    /**
+     * \brief function to set the velocity scale factor
+     *
+     * This function is used to set the desired scale factor for the velocity. This scale factor 
+     * is used to change the maximum velocity allowed. The given motion commands are multiplied
+     * by this scale factor, thus limiting the maximum possible speed. 
+     *
+     * This configuration information is processed but it is not immediatelly send to the platform.
+     * Instead, it is stored internally and send by the command thread the next time a new motion
+     * command has to be send. Therefore, there may exist a small delay between this call and the
+     * actual change in the configuration. 
+     *
+     * This function can be called at any time, but it is recomended to use it only once at the
+     * configuration stage of the robot, before sending motion commands to it.  
+     *
+     * \param factor the desired scale factor for the velocity. The possible values for this 
+     *               parameter must be limited between 0.0 and 1.0. Any other value is not 
+     *               allowed and will throw an exception.
+     */
+    void set_velocity_scale_factor(float factor);
+    /**
+     * \brief function to set the acceleration scale factor
+     *
+     * This function is used to set the desired scale factor for the acceleration. This scale factor 
+     * is used to change the maximum acceleration allowed. The given motion commands are multiplied
+     * by this scale factor, thus limiting the maximum possible acceleration. 
+     *
+     * This configuration information is processed but it is not immediatelly send to the platform.
+     * Instead, it is stored internally and send by the command thread the next time a new motion
+     * command has to be send. Therefore, there may exist a small delay between this call and the
+     * actual change in the configuration. 
+     *
+     * This function can be called at any time, but it is recomended to use it only once at the
+     * configuration stage of the robot, before sending motion commands to it.  
+     *
+     * \param factor the desired scale factor for the acceleration. The possible values for this 
+     *               parameter must be limited between 0.0 and 1.0. Any other value is not 
+     *               allowed and will throw an exception.
+     */
+    void set_acceleration_scale_factor(float factor);
+    /**
+     * \brief function to set the turnrate scale factor
+     *
+     * This function is used to set the desired scale factor for the turn rate. This scale factor 
+     * is used to change the maximum turn rate allowed. The given motion commands are multiplied
+     * by this scale factor, thus limiting the maximum possible turn speed. 
+     *
+     * This configuration information is processed but it is not immediatelly send to the platform.
+     * Instead, it is stored internally and send by the command thread the next time a new motion
+     * command has to be send. Therefore, there may exist a small delay between this call and the
+     * actual change in the configuration. 
+     *
+     * This function can be called at any time, but it is recomended to use it only once at the
+     * configuration stage of the robot, before sending motion commands to it. 
+     *
+     * \param factor the desired scale factor for the turn rate. The possible values for this 
+     *               parameter must be limited between 0.0 and 1.0. Any other value is not 
+     *               allowed and will throw an exception
+     */
+    void set_turnrate_scale_factor(float factor);
+    /**
+     * \brief function to set the gain schedule
+     *
+     * This function is used to change the current gain schedule of the segway platform. The gain
+     * schedule is used to improve the balance capabilities of the platform. Depending on the 
+     * weight of the payload and on its distribution, this parameter must be changed. 
+     *
+     * This configuration information is processed but it is not immediatelly send to the platform.
+     * Instead, it is stored internally and send by the command thread the next time a new motion
+     * command has to be send. Therefore, there may exist a small delay between this call and the
+     * actual change in the configuration. 
+     *
+     * This function can be called at any time, but it is recomended to use it only once at the
+     * configuration stage of the robot, before sending motion commands to it.  
+     *
+     * \param value the desired value for the gain schedule. This parameter should be one of the
+     *              following values:
+     *
+     *              - light
+     *              - tall
+     *              - heavy
+     *
+     *              See the documentation on the gain data type for more information on the 
+     *              different meaning of the gain schedules.
+     */
+    void set_gain_schedule(gain value);
+    /**
+     * \brief function to set the current limit scale factor
+     *
+     * This function is used to set the desired scale factor for the current limit. This scale 
+     * factor is used to change the maximum motor current allowed. 
+     *
+     * This configuration information is processed but it is not immediatelly send to the platform.
+     * Instead, it is stored internally and send by the command thread the next time a new motion
+     * command has to be send. Therefore, there may exist a small delay between this call and the
+     * actual change in the configuration. 
+     * 
+     * This function can be called at any time, but it is recomended to use it only once at the
+     * configuration stage of the robot, before sending motion commands to it.  
+     *
+     * \param factor the desired scale factor for the current limit. The possible values for this 
+     *               parameter must be limited between 0.0 and 1.0. Any other value is not 
+     *               allowed and will throw an exception
+     */
+    void set_currentlimit_scale_factor(float factor);
+    /**
+     * \brief function to lock the balance function
+     *
+     * This function is used to block the balance mode. 
+     *
+     * This configuration information is processed but it is not immediatelly send to the platform.
+     * Instead, it is stored internally and send by the command thread the next time a new motion
+     * command has to be send. Therefore, there may exist a small delay between this call and the
+     * actual change in the configuration. 
+     */
+    void lock_balance(void);
+    /**
+     * \brief function to unlock the balance function
+     *
+     * This function is used to unblock the balance mode. 
+     *
+     * This configuration information is processed but it is not immediatelly send to the platform.
+     * Instead, it is stored internally and send by the command thread the next time a new motion
+     * command has to be send. Therefore, there may exist a small delay between this call and the
+     * actual change in the configuration. 
+     */
+    void unlock_balance(void);
+    /**
+     * \brief function to set the operation mode
+     *
+     * This function is used to change the current operation mode of the segway platform. The 
+     * operation mode is used to change the working mode of the segway platform. 
+     *
+     * This configuration information is processed but it is not immediatelly send to the platform.
+     * Instead, it is stored internally and send by the command thread the next time a new motion
+     * command has to be send. Therefore, there may exist a small delay between this call and the
+     * actual change in the configuration. 
+     *
+     * This function can be called at any time, but it is recomended to use it only once at the
+     * configuration stage of the robot, before sending motion commands to it.  
+     *
+     * \param mode the desired value for the operation mode. This parameter should be one of the
+     *             following values:
+     *
+     *             - tractor
+     *             - balance
+     *             - power down
+     *
+     *             See the documentation on the op_mode data type for more information on the 
+     *             different meaning of the operation modes.
+     */
+    void set_operation_mode(op_mode mode);
+    /**
+     * \brief function to reset the right wheel integrator
+     *
+     * This function is used to reeet the right wheel integrator of the segway platform. This 
+     * integrator holds the total distance traveled by the right wheel. 
+     *
+     * This configuration information is processed but it is not immediatelly send to the platform.
+     * Instead, it is stored internally and send by the command thread the next time a new motion
+     * command has to be send. Therefore, there may exist a small delay between this call and the
+     * actual change in the configuration. 
+     * 
+     * This function can be called at any time, but it is recomended to use it only once at the
+     * configuration stage of the robot, before sending motion commands to it.  
+     *     
+     */
+    void reset_right_wheel_integrator(void);
+    /**
+     * \brief function to reset the left wheel integrator
+     *
+     * This function is used to reset the left wheel integrator of the segway platform. This 
+     * integrator holds the total distance traveled by the left wheel. 
+     *
+     * This configuration information is processed but it is not immediatelly send to the platform.
+     * Instead, it is stored internally and send by the command thread the next time a new motion
+     * command has to be send. Therefore, there may exist a small delay between this call and the
+     * actual change in the configuration. 
+     * 
+     * This function can be called at any time, but it is recomended to use it only once at the
+     * configuration stage of the robot, before sending motion commands to it.  
+     */
+    void reset_left_wheel_integrator(void);
+    /**
+     * \brief function to reset the yaw integrator
+     *
+     * This function is used to reset the yaw integrator of the segway platform. This 
+     * integrator holds the total rotation performed by the robot. 
+     *
+     * This configuration information is processed but it is not immediatelly send to the platform.
+     * Instead, it is stored internally and send by the command thread the next time a new motion
+     * command has to be send. Therefore, there may exist a small delay between this call and the
+     * actual change in the configuration. 
+     * 
+     * This function can be called at any time, but it is recomended to use it only once at the
+     * configuration stage of the robot, before sending motion commands to it.  
+     */
+    void reset_yaw_integrator(void);
+    /**
+     * \brief function to reset the forward integrator
+     *
+     * This function is used to reset the forward integrator of the segway platform. This 
+     * integrator holds the total forward displacement of the robot.
+     *
+     * This configuration information is processed but it is not immediatelly send to the platform.
+     * Instead, it is stored internally and send by the command thread the next time a new motion
+     * command has to be send. Therefore, there may exist a small delay between this call and the
+     * actual change in the configuration. 
+     * 
+     * This function can be called at any time, but it is recomended to use it only once at the
+     * configuration stage of the robot, before sending motion commands to it.  
+     * 
+     */
+    void reset_forward_integrator(void);
+    /**
+     * \brief function to connect to the hardware platform
+     *
+     * This function is used to connect the driver with the hardware platform. The
+     * communication device is only created and initialized when this function is 
+     * called, so it is not possible to send or receive data to or from the platform
+     * until then. When this function is called, both the command and feedback threads 
+     * are started. Otherwise, the communication is not possible.
+     *
+     * At contruction time this function is automatically called so the segway is 
+     * ready right after it is created. Howerver, it is possible to call this function
+     * again in case the object msu be closed due to an error or because the target
+     * platform changed.
+     *
+     * If a serial number is provided to this function, it tries to connect to the 
+     * platform which has the same serial number. If no serial number is provided, it
+     * tries to automatically connect to any platform it may find. If more or less than 
+     * one segway platforms are connected to the computer, this function will throw
+     * an exception.
+     *
+     * If the cable is disconnected, it throws a CSegwayCableDisconnectedException class and 
+     * also activates the cable_diconnected_event event. If the power is turner off, it 
+     * throws a CSegwayPowerOffException class and also activates the power_off_event event. 
+     * Any other exception id rethrown without being processed.
+     * This function throws a CSegwayRMP200Exception exception to report any error.
+     *
+     * \param desc_serial a null terminated string with the description or the serial
+     *                    number of the segway platform to associate to the driver.
+     *                    This string can be obtanied through the CFTDIServer or else
+     *                    hardcoded if known.
+     *
+     */
+    void connect(const std::string& desc_serial="");
+    // status functions
+    /**
+     * \brief function to return the pitch angle
+     *
+     * This function returns the current pitch angle in degrees. 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.
+     *
+     * \return the current pitch angle in degrees.
+     */
+    float get_pitch_angle(void);
+    /**
+     * \brief function to return the pitch rate
+     *
+     * This function returns the current pitch rate in degrees 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.
+     *
+     * \return the current pitch rate in degrees per second.
+     */
+    float get_pitch_rate(void);
+    /**
+     * \brief function to return the roll angle
+     *
+     * This function returns the current roll angle in degrees. 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.
+     *
+     * \return the current roll angle in degrees.
+     */
+    float get_roll_angle(void);
+    /**
+     * \brief function to return the roll rate
+     *
+     * This function returns the current roll rate in degrees 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.
+     *
+     * \return the current roll rate in degrees per second.
+     */
+    float get_roll_rate(void);
+    /**
+     * \brief function to return the left wheel velocity
+     *
+     * This function returns the current left wheel velocity in meters 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.
+     *
+     * \return the current left wheel in meters per second.
+     */
+    float get_left_wheel_velocity(void);
+    /**
+     * \brief function to return the right wheel velocity
+     *
+     * This function returns the current right wheel velocity in meters 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.
+     *
+     * \return the current right wheel in meters per second.
+     */
+    float get_right_wheel_velocity(void);
+    /**
+     * \brief function to return the yaw rate
+     *
+     * This function returns the current yaw rate in degrees 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.
+     *
+     * \return the current yaw rate in revolutions per second.
+     *
+     */
+    float get_yaw_rate(void);
+    /**
+     * \brief function to return the number of servo frames per second
+     *
+     * This function returns the current number of servo frames 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.
+     *
+     * \return the current number of servo frames per second.
+     */
+    float get_servo_frames(void);
+    /**
+     * \brief function to return the left wheel displacement
+     *
+     * This function returns the current left wheel 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.
+     *
+     * \return the current left wheel displacement in meters.
+     */
+    float get_left_wheel_displacement(void);
+    /**
+     * \brief function to return the right wheel displacement
+     *
+     * This function returns the current right wheel 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.
+     *
+     * \return the current right wheel displacement in meters.
+     */
+    float get_right_wheel_displacement(void);
+    /**
+     * \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.
+     *
+     * \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. 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.
+     *
+     * \return the current yaw displacement in revolutions per second.
+     *
+     */
+    float get_yaw_displacement(void);
+    /**
+     * \brief function to return the current left motot torque
+     *
+     * This function returns the current left motor torque in Nm. 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.
+     *
+     * \return the current left motor torque in Nm.
+     */
+    float get_left_motor_torque(void);
+    /**
+     * \brief function to return the current right motor torque
+     *
+     * This function returns the current right motor torque in Nm. 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.
+     *
+     * \return the current right motor torque in Nm.
+     *
+     */
+    float get_right_motor_torque(void);
+    /**
+     * \brief function to return the current operation mode
+     *
+     * This function returns the current operation mode of the segway platform. 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.
+     *
+     * \return the current operation mode being used. The possible values are:
+     *
+     * - tractor
+     * - balance
+     * - power down
+     *
+     */
+    op_mode get_operation_mode(void);
+    /**
+     * \brief function to return the current hardware operation mode
+     *
+     * This function returns the current hardware operation mode of the segway 
+     * platform. 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.
+     * 
+     * The value of this attribute is fixed by the state of the two blue buttons
+     * on the platform. 
+     *
+     * \return the current operation mode being used. The possible values are:
+     *
+     * - tractor
+     * - balance
+     * - power down
+     *
+     */
+    op_mode get_hardware_operation_mode(void);
+    /**
+     * \brief function to get the current gain schedule
+     *
+     * This function returns the current gain schedule of the segway platform. 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.
+     *
+     * \return the current gain schedule being used. The possible values are:
+     *
+     * - light
+     * - tall
+     * - heavy
+     *
+     */
+    gain get_gain_schedule(void);
+    /**
+     * \brief function to return the value of the user battery voltage
+     *
+     * This function returns the current voltage of the user battery. 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.
+     *
+     * \return the value in volts of the user battery.
+     */
+    float get_ui_battery_voltage(void);
+    /**
+     * \brief function to get the current value of the powerbase battery voltage
+     *
+     * This function returns the current voltage of the powerbase battery. 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.
+     *
+     * \return the value in volts of the powerbase battery.
+     *
+     */
+    float get_powerbase_battery_voltage(void);
+    /**
+     * \brief function to reset the segway platform
+     *
+     * This function is used to reset the segway platform to its default state. When
+     * this function is called al configuration paramerets previoulsy set return to
+     * its default value. Contrary to what happens with the motion commands, this 
+     * function immediatelly sends a data packet to the segway platform.
+     *
+     * This function throws a CSegwayRMP200Exception exception to report any error.
+     *
+     */
+    void reset(void);
+    /**
+     * \brief function to set new translational and rotational velocities
+     *
+     * This function is used to set a new motion command on the segway. This function 
+     * sets the internal translational and rotational velocities to the desired values,
+     * and it is the command thread which actually sends the new comamnd to the robot.
+     *
+     * This function can be called at any time to set up a new motion command to the 
+     * robot. The command thread sends the current motion command to the robot every 
+     * 20ms, so if this function is called more often, some of the commands will not
+     * be executed. This function throws a CSegwayRMP200Exception to report errors.
+     *
+     * If the desired operation mode set by the user with the set_operation_mode()
+     * function does not coincide with the hardware operation mode defined by the
+     * state of the two blue buttons on the platform, this function throws an exception.
+     * 
+     * \param vT desired translational velocity in meters per second. This parameter
+     *           is limited to 12 kilometers per hour in both directions (both signs).
+     *           However, the given value is affected by the velocity scale factor set
+     *           by the set_velocity_scale_factor() function, so the actual maximum 
+     *           speed can be lower.
+     *
+     * \param vR desired rotational velocity in revolutions per second. This parameter
+     *           is limited to 0.6 revolutions per second in both directions (both
+     *           signs). However, the given value is affectd by the turnrate scale 
+     *           factor set by the set_turnrate_scale_factor() function, so the actual
+     *           maximum turnrate can be lower.
+     */
+    void move(float vT,float vR);
+    /**
+     * \brief function to stop all motion
+     *
+     * This function is used to stop all motion on the segway. This function sets the
+     * internal translational and rotational velocities to 0.0, and it is the command 
+     * thread which actually sends the new comamnd to the robot.
+     *
+     * This function can be called at any time to stop the current motion of the robot.
+     * This function throws a CSegwayRMP200Exception to report errors.
+     *
+     */
+    void stop(void);
+    /**
+     * \brief function to close the segway driver
+     *
+     * This function stops all internal threads by activating the the associated finish 
+     * events, but it does not destroy them, since it is possible to reconnect the object
+     * to a new platform, in which case the thread will be restarted.
+     *
+     * This function also closes the communication device and frees all the associated
+     * resources.
+     *
+     */
+    void close(void);
+    // operators
+    /**
+     * \brief display operator overloading
+     *
+     * This operator is used to show the current state of an object of this class
+     * onto the standard ouput, file or any output stream. The information shown
+     * is already formated as shown below:
+     *
+     * \verbatim
+     * Pitch angle: <pitch_angle> degrees
+     * Pitch rate: <pitch_rate> degrees/s
+     * Roll angle: <roll_angle> degrees
+     * Roll rate: <roll_rate> degrees/s
+     * Left wheel velocity: <left_wheel_velocity> m/s
+     * Right wheel velocity: <right_wheel_velocity> m/s
+     * Yaw rate: <yaw_rate> degrees/s
+     * Servo frames: <servo_frames> frames/s
+     * Left wheel displacement: <left_wheel_displ> m
+     * Right wheel displacement: <right_wheel_displ> m
+     * Forward displacement: <forward_displ> m
+     * Yaw displacement: <yaw_displ> rev
+     * Left motor torque: <left_torque> Nm
+     * Right motor torque: <right_torque> Nm
+     * Operation mode: <op_mode>
+     * Hardware operation mode : <hardware_op_mode>
+     * Gain schedule: <gain_schedule>
+     * UI battery voltage: <ui_battery> V
+     * Powerbase battery voltage: <powerbase_battery> V
+     * \endverbatim
+     */
+    friend std::ostream& operator<< (std::ostream& out, CSegwayRMP200& segway);
+    /**
+     * \brief destructor
+     *
+     * This destructor is called when the object is about to be destroyed. It calls
+     * the close() function to safely stop all the internal threads, and then deletes
+     * all the internal threads and events.
+     *
+     */
+    ~CSegwayRMP200(); 
+};
+
+#endif
+
diff --git a/src/segway_rmp200_exceptions.cpp b/src/segway_rmp200_exceptions.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..59d3e8c7c1a183302c5ba20d0c6ec0a2cbdee349
--- /dev/null
+++ b/src/segway_rmp200_exceptions.cpp
@@ -0,0 +1,12 @@
+#include "segway_rmp200_exceptions.h"
+#include <string.h>
+#include <stdio.h>
+
+const std::string segway_rmp200_exception_msg="[CSegwayRMP200 class] - ";
+
+CSegwayRMP200Exception::CSegwayRMP200Exception(const std::string& where,const std::string& error_msg,const std::string& segway_id):CException(where,segway_rmp200_exception_msg)
+{
+  this->error_msg+=error_msg;
+  this->error_msg+=" - ";
+  this->error_msg+=segway_id;
+}
diff --git a/src/segway_rmp200_exceptions.h b/src/segway_rmp200_exceptions.h
new file mode 100644
index 0000000000000000000000000000000000000000..99fc2ac89e97ab29a4c5e1eb2a1a5ff929ddcef2
--- /dev/null
+++ b/src/segway_rmp200_exceptions.h
@@ -0,0 +1,58 @@
+#ifndef _SEGWAY_RMP200_EXCEPTIONS
+#define _SEGWAY_RMP200_EXCEPTIONS
+
+#include "exceptions.h"
+
+/**
+ * \brief Generic segway RMP 200 exception class
+ *
+ * This class implements the exceptions for the CSegwayRMP200 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 ("[CSegwayRMP200 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 CSegwayRMP200Exception : 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 
+     * "[CSegwayRMP200 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>
+     * [CSegwayRMP200 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.
+     *
+     */
+    CSegwayRMP200Exception(const std::string& where,const std::string& error_msg,const std::string& segway_id);
+};
+
+#endif