Rosanswers logo


I'm using ROS Kinetic. I'd like to have multiple instances of a dynamic_reconfigure server in a node, and I'm wondering how to achieve that. I have different robots that I define in YAML files with a specific number of motors for each robot. I have a dynamic_reconfigure config file in my package that allows me to set min, max, offset and enable parameters for a motor.

But I need to be able to tune those parameters for each motor defined in the YAML file, and that is unknown at compile time. I can't dynamically allocate some array of server because at runtime I don't have the callbacks created.

A way, which I don't really like, could be to add a string or int field to the parameters, and type the motor name or index to apply the values to that specific motor in the code. There could be a bool parameter also to apply the new values in the client node when set to true.

Another way could be to create a nodelet class of a motor with its own dynamic reconfigure server and callback, and have a vector of them in the main node, and push back as many as needed.

The other way could be to use services instead, but then I couldn't use the rqt_reconfigure gui.

Is there a good practice for doing this kind of thing ?


Originally posted by Cyril Jourdan on ROS Answers with karma: 157 on 2018-04-18

Post score: 0

Original comments

Comment by lucasw on 2018-04-18:
Passing extra arguments to callbacks: #q63991 (also a complete non-class example #q289061)

Comment by Cyril Jourdan on 2018-04-19:
Thanks! I see that working for topics, but will it work for dynamic_reconfigure, will rqt_reconfigure show me a list of motors with their parameters using that design ? I'll give it a try.

Comment by Cyril Jourdan on 2018-04-19:
Thanks for your hint lucasw, I've published an answer in my question.

Comment by mgruhler on 2018-04-19:
@Cyril_J great you got it working. You can post your solution as an answer and accept that as correct. This will help other users stumbling upon the same problem...


1 Answer 1


Rosanswers logo

I tried something pointed out by @lucasw and it works! I found that a dynamic_reconfigure server is linked to a NodeHandle and there can only be one instance otherwise you get the error: "tried to advertise a service that is already advertised in this node". So I created a vector of NodeHandle that I link to each server. Also I had to make sure to call ros::init(...) before creating any instance of my class that has the CallbackType as a member otherwise I got the error: Couldn't find an AF_INET address...

My class is for filtering motor commands, here are a few lines of code that focus on solving this problem: In my header file :

class CommandFilter
    /* some functions */

    void motorDynConfigCallback(osa_control::MotorDynConfig &config, uint32_t level, const int idx);

    std::vector<dynamic_reconfigure::Server<osa_control::MotorDynConfig>*> motor_dyn_config_server_list_;
    osa_control::MotorDynConfig motor_param_;
    /* other class members */

In my implementation file:

bool CommandFilter::init()
/* some init code */

for(int i=0; i<ptr_robot_description_->getRobotDof(); i++)
        const std::string dof_name = ptr_robot_description_->getControllerList().at(i)->getName();

        ros::NodeHandle node_handle(dof_name.c_str());

        dynamic_reconfigure::Server<osa_control::MotorDynConfig> *s = new dynamic_reconfigure::Server<osa_control::MotorDynConfig>(node_handle);
        dynamic_reconfigure::Server<osa_control::MotorDynConfig>::CallbackType f;
        f = boost::bind(&CommandFilter::motorDynConfigCallback, this, _1, _2, i);

/* some init code */

void CommandFilter::motorDynConfigCallback(osa_control::MotorDynConfig &config, uint32_t level, const int idx)
    ROS_INFO("Dynamic Reconfigure Request for dof%d [%s]: %s %d %d %d", idx+1, ptr_robot_description_->getControllerList().at(idx)->getName().c_str(), config.enable?"True":"False", config.min_pos, config.max_pos, config.offset_pos);

    motor_param_ = config;

Note that it's a first cut solution and the code can be improved, but it works and give me exactly what I needed.

Originally posted by Cyril Jourdan with karma: 157 on 2018-04-19

This answer was ACCEPTED on the original site

Post score: 1

Original comments

Comment by gvdhoorn on 2018-04-19:
ROS1 has a limitation of 1 node per process. Multiple nodehandles will not create more nodes, but could introduce additional namespaces. Afaik the only thing required for multiple dyn_recfg servers is exactly that: multiple namespaces so topics don't clash.

Comment by gvdhoorn on 2018-04-19:\

ros::NodeHandle *node_handle = new ros::NodeHandle(dof_name.c_str());

This line created an additional namespace.

Comment by Cyril Jourdan on 2018-04-19:
Yes exactly. @gvdhoorn Is there a way to create just the namespace ?

Comment by gvdhoorn on 2018-04-19:
You can just directly pass in a NodeHandle instance. No need to keep them around yourself. The dynamic_reconfigure::Server instance owns them.

But you do need the NodeHandle instance.

Comment by Cyril Jourdan on 2018-04-19:
Thanks for your advice @gvdhoorn, I've simplified the code and updated my answer. I works just as well.

Comment by lucasw on 2018-05-04:
It's worth pointing out: https://github.com/ros/dynamic_reconfigure/blob/master/include/dynamic_reconfigure/server.h#L75 the constructor to the server can be given a mutex and a nodehandle

 new dynamic_reconfigure::Server<foo::Bar>(reconfig_mutex, node_handle)

Comment by Loy on 2018-09-17:
You must construct the dynamic_reconfigure Server via the new operator. It doesn't work when you just use config_server(nh). Using the latter syntax, it will get destroyed when it goes out of scope.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.