diff --git a/README.md b/README.md index f84604a5a63e51a1988a2ff987e9e5d4d683065b..ec36fcde161ddddc9e58610168202f6c2de758b3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Description -This ROS package contains several tools that may be helpfull to develop new ROS nodes. They have been mainly developed for large scale ROS control nodes that need to handle several ROS interfaces (action, services and topics) to carry out a given task, using state machines or behabior trees, but they can be also used in other scenarios. +This ROS package contains several tools that may be helpful to develop new ROS nodes. They have been mainly developed for large scale ROS control nodes that need to handle several ROS interfaces (action, services and topics) to carry out a given task, using state machines or behavior trees, but they can be also used in other scenarios. These tools are describes in the following sections. @@ -8,7 +8,7 @@ These tools are describes in the following sections. ROS actions are designed to handle tasks that may take a long time to finish. Some times these actions may take too long to finish, so it may be interesting to limit their maximum duration (for example in robot navigation). -The timeout class can be used to limit the execution time of any given action and therefore prevent the control loop from getting stucked waiting for it to finish. The timeout should be started at the same time as the action, and in normal operation the action will finish before the timeout gets active. However, if something goes wrong, the timeout will get active, allowing the user to decide what to do (cancel the action, wait more time, etc). +The timeout class can be used to limit the execution time of any given action and therefore prevent the control loop from getting stuck waiting for it to finish. The timeout should be started at the same time as the action, and in normal operation the action will finish before the timeout gets active. However, if something goes wrong, the timeout will get active, allowing the user to decide what to do (cancel the action, wait more time, etc). This class does not provide any means of asynchronous notifications when the desired time has elapsed, instead the timeout has to be polled. The class is thread safe and can be used from different thread contexts. @@ -22,46 +22,86 @@ The class is thread safe and can be used from different thread contexts. ## Action client wrapper -ROS action client interface requires several callback functions (active, done and feedback) as well as several variables and lines of code to handle it. When a single ROS node has to handle several actions clients, the complexity of developing and maintainging the code increases. +ROS action client interface requires several callback functions (active, done and feedback) as well as several variables and lines of code to handle it. When a single ROS node has to handle several actions clients, the complexity of developing and maintaining the code increases. The action client wrapper class is a template of any action message, and it is intended to simplify the use of the ROS action client. This class handles the execution of the action and all the associated callback functions and variables internally, and provides a simple API interface. The class is thread safe and can be used from different thread contexts. This class provides the following features: -* **Configurable maximum number of retries**: this class will not report an error until the action has been tried to start for a given ammount of times. Instead it will return a pending condition. +* **Configurable maximum number of retries**: this class will not report an error until the action has been tried to start for a given amount of times. Instead it will return a pending condition. -* **Configurable watchdog**: is uses the watchdog class presented before to monitor the reception of the feedback topic. This is specially useful for low quality wireless connections were data can be lost. +* **Configurable watchdog**: it uses the [watchdog](#Watchdog) class presented before to monitor the reception of the feedback topic. This is specially useful for low quality wireless connections were data can be lost. -* **Configurable timeout**: it uses the timeout class presented before to control the maximum ammount of time the action can be active before succeeding or aborting. This is specially useful for low quality wireless connections were data can be lost. +* **Configurable timeout**: it uses the [timeout](#Timeout) class presented before to control the maximum amount of time the action can be active before succeeding or aborting. This is specially useful for low quality wireless connections were data can be lost. -* **Internal ROS node handle**: The parent ROS node namespace and the desired action name are provided at construction time to generate the namespace used to create the action topics. +* **Internal ROS node handle**: The parent ROS node name-space and the desired action name are provided at construction time to generate the name-space used to create the action topics. -* **Can be disabled**: the operation of the action client can be disabled to avoid the actual execution of the action. In this case, the class will report the action has completed successfully immediatelly after being started. This is specially useful to skip certain part of large scale ROS control nodes. +* **Can be disabled**: the operation of the action client can be disabled to avoid the actual execution of the action. In this case, the class will report the action has completed successfully immediately after being started. This is specially useful to skip certain part of large scale ROS control nodes. ## Service client wrapper -Eventhough the ROS service client interface is not as complex as the ROS action client interface, handling several of them may also inclrease the complexity of developing and maintainging the code. +Even though the ROS service client interface is not as complex as the ROS action client interface, handling several of them may also increase the complexity of developing and maintaining the code. This class is a template of any service message, and it is intended to simplify the use of the ROS service client. This class handles the call of the service and all the associated variables and functions, and provides a simple API interface. The class is thread safe and can be used from different thread contexts. This class provides the following features: -* **Configurable maximum number of retries**: this class will not report an error until the service has been tried to call for a given ammount of times. Instead it will return a pending condition. +* **Configurable maximum number of retries**: this class will not report an error until the service has been tried to call for a given amount of times. Instead it will return a pending condition. -* **Service answer evaluation callback**: this class can use a user defined function to evaluate the answer returned by the service server to check wheter it is correct or not. The default function always returns success. +* **Service answer evaluation callback**: this class can use a user defined function to evaluate the answer returned by the service server to check whether it is correct or not. The default function always returns success. -* **Internal ROS node handle**: The parent ROS node namespace and the desired service name are provided at construction time to generate the namespace used to create the service. +* **Internal ROS node handle**: The parent ROS node name-space and the desired service name are provided at construction time to generate the name-space used to create the service. -* **Can be disabled**: the operation of the service client can be disabled to avoid the actual call. In this case, the class will report the service has completed successfully immediatelly. This is specially useful for large scale ROS control nodes. +* **Can be disabled**: the operation of the service client can be disabled to avoid the actual call. In this case, the class will report the service has completed successfully immediately. This is specially useful for large scale ROS control nodes. -An inherited class of the templated service client wrapper is provided for the dynamic_reconfigure/Reconfigure.srv service, used by the dynamic reconfigure ROS tool. With this class it is possible to access the parameters defined by the dynamic reconfigure server of any ROS node through code. It provides functions to get and set any of the four data types supported by the service (int, double, bool and string). +An inherited class of the templated service client wrapper is also provided for the dynamic_reconfigure/Reconfigure.srv service, used by the dynamic reconfigure ROS tool. With this class it is possible to access the parameters defined by the dynamic reconfigure server of any ROS node through code. It provides functions to get and set any of the four data types supported by the service (int, double, bool and string). -## ROS modules. +## IRI ROS modules. + +Each robot has a set of basic features, some of them common to other robots (such as navigation, object or person detection based on available sensors, etc), and some other specific to them (such as controlling pan & tilt units, grippers and other devices). Each of these features is normally controlled by a ROS node with one or more action and/or service servers, as well as a number of topics. + +Additionally, more advanced features can be developed on top of the basic ones (and also other advanced ones) to provide more complex behaviors to the robot, such as guiding or following persons, grasping objects, etc. Again, each of these features is controlled by a ROS node with one or more action and/or service servers, as well as a number of topics. ROS nodes for advanced features can also provide some action and/or service servers to access and control their functionalities. + +The ROS node which implements the top level control loop for large scale scenarios needs several basic and advanced features to carry out the desired task, and therefore it has to deal with several action and/or service clients and topics. Taking into account only the amount of lines of code, variables and callback functions required to handle each of the ROS interfaces, the complexity of the development and maintenance may increase quite a lot. Furthermore, different top level control ROS nodes may re-implement the same code (or similar) to handle each of the features, which negates the possibility of code re-usability. + +On possible solution to simplify this problem is to create what we call a **IRI ROS module** for each of the basic and advances features. Such module is implemented as a shared library that can be included in any ROS node and it implements a simple control loop with all the required client side ROS interfaces, providing a simple API to the user. The main idea is sketched in the next Figure. + +<img src="doc/images/module.png" alt="Basic structure of the IRI ROS module" width="838" height="595"> + +The IRI ROS module is implemented as a base class that provides the main features, from which the user should inherit a new class for each of the desired features, and add the required ROS interfaces. + +The main features of the IRI ROS modules are listed and described next: + +* ** ROS interfaces**: Although the ROS interfaces are not directly handled by the IRI ROS module base class itself, it is recommended to use the [action client wrapper](#Action-client-wrapper) and the [service client wrapper](#Service-client-wrapper) presented in the previous sections. This way, the module code is more easily developed and maintained. + +* **Internal thread**: The control code to handle the IRI ROS module (implemented as a state machine, behavior tree, ...) is executed in a parallel thread. This make it possible to assign a different execution rate to each module, and also simplifies the the user interface. A mutex object is provided to ensure unique access to the module attributes. The inherited class has to start the execution of the thread with the *start_operation* functions, and implement the control code in the *state_machine* function. + +* **User interface through an API**: All the features of a ROS node can be accessed through a set of functions, and all the ROS message handling is performed internally in the IRI ROS module. With the API approach, some complex features that would require one or more ROS interfaces and some logic, can be started and handled using simple function calls with the required parameters. This also contributes to the code re-usability. + +* **Dynamic reconfigure**: The module provides a dynamic reconfigure server to be able to set, at start-up, and change, during operation, the values of some internal parameters. It is also recommended to include a dynamic reconfigure client to be able to modify the parameters of the associated ROS node through code. # Dependencies +All the ROS tools included in this project depend on the following IRI dependencies: + +* [iriutils](https://gitlab.iri.upc.edu/labrobotica/algorithms/iriutils): set of basic tools developed at IRI. + # How to use it +To use any of the tools provided in this ROS package, add the iri_ros_tools dependency to the package.xml and CMakeLists.txt files as any other ROS dependency. + +Also add the following lines to the CMakeLists.txt to include the [iriutils](https://gitlab.iri.upc.edu/labrobotica/algorithms/iriutils) dependency: + +``` +CMakeLists.txt +include_directories(${iriutils_INCLUDE_DIR}) +target_link_libraries(${PROJECT_NAME} ${iriutils_LIBRARY}) +``` + +The [Timeout](#Timeout) and [watchdog](#Watchdog) tools can be directly instantiated in any ROS node. + +To use the [action client wrapper](#Action-client-wrapper), the [service client wrapper](#Service-client-wrapper) and the [IRI ROS module](#IRI-ROS-module), a new class, inherited from the base classes provided in this package has to be defined. See the [iri_ana_nav_module](https://gitlab.iri.upc.edu/labrobotica/ros/robots/ana/iri_ana_nav_module) project for an example on how to do it. + ## Disclaimer Copyright (C) Institut de Robòtica i Informà tica Industrial, CSIC-UPC. diff --git a/doc/images/module.png b/doc/images/module.png new file mode 100644 index 0000000000000000000000000000000000000000..fdd27164dc677149d860414dc30f60462fa4394c Binary files /dev/null and b/doc/images/module.png differ diff --git a/doc/modules.odp b/doc/modules.odp new file mode 100644 index 0000000000000000000000000000000000000000..858173b2f92b371bf89758b643a2868f46930a37 Binary files /dev/null and b/doc/modules.odp differ