Advanced ROS
Overview
These notes cover some more advanced ROS issues that you may encounter from time to time.
Actions
Actions allow you to
- Initiate a request (like a service)
- Receive ongoing feedback (like a subscriber)
- Cancel the request (like another service)
- Get a result (like a service)
Like a ROS service, ROS actions have a client that initiates a request and a server that processes that request and provides a response. Just as a ROS service has a client andhas a Request and a Response, an action has the following components
- Goal: An ActionClient sends the goal to initiate the action on the ActionServer
- For example:
Client sends MOVE ROBOT ARM TO (X,Y,Z) to Server
to initiate the arm moving
- For example:
- Feedback: This is data that an action server sends to the client while the server is executing the action
- For example, while the arm is moving
Server sends ROBOT ARM AT (location) to Client
- For example, while the arm is moving
- Result: When the action is completed, the server sends information about the result
- For example,
Server sends ARM FINISHED MOVING to client
- For example,
Defining the Action
Just like messages and services, actions are also defined in a file using the same syntax as messages and services. The
Goal, Feedback, and Result types are separated by ---
.
For example
uint32 the_goal --- uint32 the_result --- uint32 the_feedback
Building the Action
Just like for messages and services, you must edit CMakeLists.txt
and package.xml
to build an action:
- Use
add_action_files(DIRECTORY action files MyAction.action)
<depend>
onactionlib_msgs
andactionlib
in thepackage.xml
Using Actions
- The code API reference is here, and there are examples on the Wiki page
- Use the
action
library to create action clients and servers.
Actions are very flexible, since goals can be preempted and feedback provided. There are many tutorials. Most of the tutorials are in C++ but the API is similar for python.
The Action Server
- Action server creates a callback
- The callback should perform the task and periodically send feedback and check for pre-emption
- See the Tutorial for details
The Action Client
- To start an action, you send it a goal, as per this tutorial
- There are many options when calling an action See API Docs
- For example, you can poll or you can use callbacks to get the results
Under the Hood
- Actions are implemented using ROS messages. So you can set a goal by publishing to a ROS topic
- This is mostly for convenience when interacting from the command line
- The
actionlib_tools
package (not installed by default) contains a tool calledaxclient.py
:rosrun actionlib_tools axclient.py /action/topic/name
will launch a GUI for controlling the action
Dynamic Reconfigure
Dynamic Reconfigure is an extension to ROS parameters that can be updated at runtime.
- Usually, a node will read parameters once at startup. If you subsequently change a parameter it will not take effect until the node is restarted.
- Dynamic reconfigure enables your node to update the parameters when the parameters change. It also provides client programs
such as
dynparam
that allow a user to change these parameters at runtime orrosrun rqt_reconfigure rqt_reconfigure
which is a Gui version. - Dynamically reconfigured parameters are typically accessed through the Python API
- The Dynamic Reconfigure Tutorial provides an example of how to use dynamic reconfigure
Using Dynamic Reconfigure
- You must create a
.cfg
file. This file is actually an executable python file that uses the dynamic reconfigure API to define the parameters that should be dynamically reconfigured. This file - The config file must be added in
CMakeLists.txt
to thegenerate_dynamic_reconfigure_options
line - You then create a Dynamic reconfigure server in your code. This code has a callback that receives parameter values when they are changed
using the
dynamic_reconfigure
client tools.
Uses of Dynamic Reconfigure
- Dynamic reconfigure is very useful for nodes that have parameters that are constant but need to be
tuned
by the user - Sometimes it is easier to just have these values modified by a regular ROS service or subscriber, but using dynamic reconfigure allows you to take advantage of all the client tools (including GUI's) to change these values.
- Examples of items that it may be useful to dynamically reconfigure include control system gains and thresholds for vision processing algorithms
Nodelets
- Nodelets essentially allow you to run multiple ROS nodes within the same process
- When nodes are in the same process, they do not need to copy data when sending/receiving messages.
- These need to be written in C++, but you may encounter nodelets that you use (such as for point cloud processing)
- Think of nodelets as essentially a way of enabling the ROS API abstractions without most of the overhead
Remote Nodes
- ROS nodes can be running on multiple computers
roscore
always runs on a single computer, and nodes connect to it via the environment variableROS_MASTER_URI
.- Typically,
ROS_MASTER_URI=http://<hostname>:11311
- Typically,
- To be fully functional, ROS requires all computers on the network to be able to directly communicate with each other
Basic Networking
- Every network device has an IP address.
- Every computer on the network has a hostname.
- In a properly configured network, the
hostname
will resolve (that is be associated with) the ip address of exactly one computer. - If each host computer in the network has a
hostname
, and allhostnames
are resolvable on the network then you can specify theROS_MASTER_URI
using thehostname
, and every ROS node will just work- If the computer on which you are running a node is not accessible via its hostname you must either
- Set the environment variable
ROS_IP
to the ip address of the computer - Set the environment
ROS_HOSTNAME
to the hostname of the computer - DO NOT SET
ROS_HOSTNAME
orROS_IP
simultaneously
- Set the environment variable
- If the computer on which you are running a node is not accessible via its hostname you must either
- If you cannot easily get hostnames resolved (such as you don't control the router) there are other options
- Avahi (also known as zero conf) is a decentralized method for resolving hostnames. When every computer on a local
network is running avahi, you can resolve hostnames via
hostname.local
- Avahi (also known as zero conf) is a decentralized method for resolving hostnames. When every computer on a local
network is running avahi, you can resolve hostnames via
- If hostnames cannot be easily resolved you can either
- Hardcode IP addresses and set
ROS_IP
- Use the
/etc/hosts
file to associate hostnames with static ip addresses
- Hardcode IP addresses and set
My preferred network setup
- The easiest way to do handle the network is to connect everything to a router running OpenWrt.
- By default
OpenWrt
configures a Domain Name Server (DNS) to resolve all hostnames connected to the router - Upon discovering this, I exclusively by routers that support OpenWrt since most consumer-level devices with the default firmware do not have DNS running
Northwestern Specific Setup
- Northwestern has the Device Northwestern Wireless network for embedded device
- I run a DNS server and also a server that allows devices to register with it
- Devices that want to use my DNS server are configured such that
- They ignore the DNS servers they get from DHCP and instead use my DNS server
- They have a NetworkManager script that registers them with my DNS server whenever their ip address changes
Launchfiles
- The
<machine>
tag lets you define a remote machine a launchfile - You can then refer to the
machine
when you launch a node. - Thus, a single launchfile can launch nodes across multiple machines
- You should be able to
ssh
into the remote machines using a private key in order to launch nodes on that machine. - To run a node on a remote machine, the compiled version of that node (or the python script) must reside on the remote machine
A Trick
You can take advantage of some properties of launch files to make development easier.
- Make sure that your ROS packages properly install and generate the install space
- Write a script that copies your install space to a remote machine
- This script will make sure that the latest nodes that you use are on the remote machine
- Load the output of this script into the parameter server using the
rosparam
tag- This is guaranteed to execute prior to any nodes being launched
- The script has now copied the
install
space to the remote machine. Now the nodes you are developing will be on the remote machine- The
env-loader
script can be theenv.sh
from the install space that you just copied over
- The