Commit fe67a0e8 authored by Sergi Hernandez's avatar Sergi Hernandez
Browse files

Merge branch 'kinetic_migration'

parents ac3846b5 96798d7e
......@@ -4,12 +4,11 @@ project(iri_ros_tools)
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED)
find_package(catkin REQUIRED COMPONENTS roscpp)
## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)
## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
......@@ -87,17 +86,32 @@ catkin_package(
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(include)
# include_directories(include)
include_directories(
include
${catkin_INCLUDE_DIRS}
)
## Declare a cpp library
# add_library(iri_ros_tool
# src/${PROJECT_NAME}/iri_ros_tool.cpp
# )
add_library(${PROJECT_NAME} src/timeout.cpp src/watchdog.cpp)
add_library(modules include/${PROJECT_NAME}/module_common.h include/${PROJECT_NAME}/module.h include/${PROJECT_NAME}/module_service.h include/${PROJECT_NAME}/module_action.h include/${PROJECT_NAME}/module_exceptions.h include/${PROJECT_NAME}/module_dyn_reconf.h)
target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES})
add_library(modules
include/${PROJECT_NAME}/module_common.h
include/${PROJECT_NAME}/module.h
include/${PROJECT_NAME}/module_service.h
include/${PROJECT_NAME}/module_action.h
include/${PROJECT_NAME}/module_exceptions.h
include/${PROJECT_NAME}/module_dyn_reconf.h
)
set_target_properties(modules PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(modules ${PROJECT_NAME})
target_link_libraries(modules
${PROJECT_NAME}
${catkin_LIBRARIES}
)
## Declare a cpp executable
......
# Description
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.
## Timeout
ROS actions are designed to handle tasks that may take a long time to finish. Sometimes 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 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.
## Watchdog
Many ROS nodes depend on the periodic or continuous publication of data through topics, for example sensor data or the action feedback.
The watchdog class can be used to detect the possible failures of the ROS nodes publishing the desired data by limiting the time maximum between two consecutive topic receptions. In normal operation, the watchdog is reset whenever new data is received before it gets active (in the topic subscriber function), but if the topic stops receiving data, the watchdog will eventually activate to indicate something may be wrong with the publishing ROS nodes.
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 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 amount of times. Instead it will return a pending condition.
* **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](#Timeout) class presented before to control the maximum amount of time the action can be active before succeeding or aborting.
* **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 immediately after being started. This is specially useful to skip certain part of large scale ROS control nodes.
## Service client wrapper
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 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 whether it is correct or not. The default function always returns success.
* **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 immediately. This is specially useful for large scale ROS control nodes.
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).
## 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.
One 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 makes it possible to assign a different execution rate to each module, and also simplifies 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:
```
find_package(iriutils REQUIRED)
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.
Mantainer IRI labrobotics (labrobotica@iri.upc.edu)
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.
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/>
File added
......@@ -238,6 +238,7 @@ class CModuleAction
this->status=ACTION_SUCCESS;
}
this->action_result_msg=*result;
this->action_feedback_msg=Feedback();
this->action_access.exit();
}
/**
......
<?xml version="1.0"?>
<package>
<package format="2">
<name>iri_ros_tools</name>
<version>0.0.0</version>
<version>1.0.0</version>
<description>The iri_ros_tools package</description>
<!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: -->
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
<maintainer email="labrobotica@iri.upc.edu">labrobotica</maintainer>
<!-- One license tag required, multiple allowed, one license per tag -->
<!-- Commonly used license strings: -->
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
<license>LGPL</license>
<url type="website">http://wiki.ros.org/iri_ros_tool</url>
<!-- Url tags are optional, but mutiple are allowed, one per tag -->
<!-- Optional attribute type can be: website, bugtracker, or repository -->
<!-- Example: -->
<!-- <url type="website">http://wiki.ros.org/iri_ros_tool</url> -->
<author email="shernand@iri.upc.edu">Sergi Hernandez</author>
<!-- Author tags are optional, mutiple are allowed, one per tag -->
<!-- Authors do not have to be maintianers, but could be -->
<!-- Example: -->
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
<author email="shernand@iri.upc.edu">shernand</author>
<!-- The *_depend tags are used to specify dependencies -->
<!-- Dependencies can be catkin packages or system dependencies -->
<!-- Examples: -->
<!-- Use build_depend for packages you need at compile time: -->
<!-- <build_depend>message_generation</build_depend> -->
<build_depend>roscpp</build_depend>
<!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use run_depend for packages you need at runtime: -->
<!-- <run_depend>message_runtime</run_depend> -->
<run_depend>roscpp</run_depend>
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->
<buildtool_depend>catkin</buildtool_depend>
<depend>roscpp</depend>
<!-- The export tag contains other, unspecified, tags -->
<export>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment