vrijdag 25 maart 2016

Controling dynamic reconfiguration from C++ in ROS (roscpp)

ROS has a cool mechanism called Dynamic Reconfigure where parameters of nodes can be set at runtime. The concept is explained here. Sometimes you want to change these parameters from your code. There is a supported python API to do this but there is no API for C/C++ yet.

GUI for dynamic reconfigure which can be launched via rosrun rqt_reconfigure rqt_reconfigure

After some research I found a good thread on the ROS forum here explaining how it is possible use dynamic reconfigure from C++ code in ROS.

Based on that thread I got the dynamic reconfigure working. I wrote this blogpost to take you through the steps needed. Hope this helps you.

In my case, the reason I needed this was that our project is using ar_track_alvar to scan for AR tags. However, this uses a tremendous amount of CPU so I want to be able to switch if off when it's not needed. Alternatively, and arguably better, I could have also modified the ar_track_alvar package when nobody is subscribed to any of the topics. Maybe I'll look into that sometime. But for now, let's dive in.

Nodes that support dynamic reconfigure have a ros service that allows one to set it. Via the command rosservice list you can get a list of those services. In my case it revealed the service that I needed:

/ar_track_alver/set_parameters

We will be invoking this service via C++.

If we run the command rosservice info /ar_track_alvar/set_parameters we can see information about this service:

Node: /ar_track_alvar
URI: rosrpc://ubuntu:42524
Type: dynamic_reconfigure/Reconfigure
Args: config

The argument that we can pass to this service is called 'config'. This is parameter of type dynamic_reconfigure::Config and contains all the parameters that the node allows to be set. To find out more about its internal structure we can look at some of the topics published. Via rostopic list we can quickly find out that there are 2 interesting topics that we can look at:

/ar_track_alvar/parameter_descriptions
/ar_track_alvar/parameter_updates


The first is of type dynamic_reconfigure/ConfigDescription and the latter is of type dynamic_reconfigure/Config.

To find out the parameters that you can set, you can simply look at the content of the topic /ar_track_alvar/parameter_updates via the command rostopic echo /ar_track_alvar/parameter_updates. For this node, the output will look like:

bools:
  -
    name: enabled
    value: True
ints: []
strs: []
doubles:
  -
    name: max_frequency
    value: 10.0
  -
    name: marker_size
    value: 5.5
  -
    name: max_new_marker_error
    value: 0.05
  -
    name: max_track_error
    value: 0.05
groups:
  -
    name: Default
    state: True
    id: 0
    parent: 0
 


Here we can see the boolean parameter 'enabled' that we need to set. Now we have all the information needed to write the code. This is actually pretty straightforward. As we need to set a boolean parameter we use the include file BoolParameter.h. There are corresponding include files for the other elementary data types (IntParameter.h, DoubleParameter.h, etc).

#include <dynamic_reconfigure/BoolParameter.h>
#include <dynamic_reconfigure/Reconfigure.h>
#include <dynamic_reconfigure/Config.h>

.

.
.

void ApproachMarker::EnableArTrackAlvar(bool enable) {
  dynamic_reconfigure::ReconfigureRequest srv_req;
  dynamic_reconfigure::ReconfigureResponse srv_resp;
  dynamic_reconfigure::BoolParameter enable_param;
  dynamic_reconfigure::Config conf;

  enable_param.name = "enabled";
  enable_param.value = enable;
  conf.bools.push_back(enable_param);

  srv_req.config = conf;

  if (ros::service::call("/ar_track_alvar/set_parameters", srv_req, srv_resp)) {
    ROS_INFO("call to set ar_track_alvar parameters succeeded");
  } else {
    ROS_INFO("call to set ar_track_alvar parameters failed");
  }

}


Alright, that's it folks. Hope this was of use!

3 opmerkingen: