UP | HOME

Advanced ROS

Overview

These notes cover some more advanced ROS issues that you may encounter from time to time.

Actions

Actions allow you to

  1. Initiate a request (like a service)
  2. Receive ongoing feedback (like a subscriber)
  3. Cancel the request (like another service)
  4. 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

  1. 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
  2. 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
  3. Result: When the action is completed, the server sends information about the result
    • For example, Server sends ARM FINISHED MOVING to client

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:

  1. Use add_action_files(DIRECTORY action files MyAction.action)
  2. <depend> on actionlib_msgs and actionlib in the package.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 called axclient.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.

  1. 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.
  2. 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 or rosrun rqt_reconfigure rqt_reconfigure which is a Gui version.
  3. Dynamically reconfigured parameters are typically accessed through the Python API
  4. The Dynamic Reconfigure Tutorial provides an example of how to use dynamic reconfigure

Using Dynamic Reconfigure

  1. 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
  2. The config file must be added in CMakeLists.txt to the generate_dynamic_reconfigure_options line
  3. 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

  1. Dynamic reconfigure is very useful for nodes that have parameters that are constant but need to be tuned by the user
  2. 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.
  3. 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 variable ROS_MASTER_URI.
    • Typically, ROS_MASTER_URI=http://<hostname>:11311
  • 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 all hostnames are resolvable on the network then you can specify the ROS_MASTER_URI using the hostname, 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 or ROS_IP simultaneously
  • 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
  • If hostnames cannot be easily resolved you can either
    1. Hardcode IP addresses and set ROS_IP
    2. Use the /etc/hosts file to associate hostnames with static ip addresses

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.

  1. Make sure that your ROS packages properly install and generate the install space
  2. 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
  3. 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
  4. 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 the env.sh from the install space that you just copied over

Author: Matthew Elwin