ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
3

Notification when a parameter in param server is changed

asked 2011-05-02 02:25:41 -0600

Victor Lopez gravatar image

Is there any C++ utility to notice if a parameter in param server has changed instead of storing the value and keep checking it for changes continuously?

edit retag flag offensive close merge delete

Comments

If you expect changes during runtime, maybe you should use dynamic_reconfigure instead of the parameter server.
Felix Endres gravatar image Felix Endres  ( 2011-05-02 04:41:03 -0600 )edit
Yes, but dynamic_reconfigure only works with Python, right?
Martin Günther gravatar image Martin Günther  ( 2011-05-02 22:07:03 -0600 )edit
A colleague of mine used it with python and c++
Felix Endres gravatar image Felix Endres  ( 2011-05-02 23:39:30 -0600 )edit
I'll have a look at it, but it is marked as unstable so I'm not sure it is resilient enough for what I need. I have a workaround, which is a thread that queries the parameter I'm watching and reports if it has been changed.
Victor Lopez gravatar image Victor Lopez  ( 2011-05-03 03:42:45 -0600 )edit
I'll have a look at it, but it is marked as unstable so I'm not sure it is resilient enough for what I need.
Victor Lopez gravatar image Victor Lopez  ( 2011-05-03 03:42:46 -0600 )edit

3 Answers

Sort by » oldest newest most voted
4

answered 2011-05-05 15:40:20 -0600

joq gravatar image

You could periodically call getParamCached(). It caches the value locally and subscribes to the parameter server for notification in the event of updates. So, the polling overhead is minimal.

Or, use dynamic_reconfigure. Even though it's marked unstable, the basic interfaces are widely used and will probably be preserved in future distributions.

edit flag offensive delete link more

Comments

I don't know if I'm going nuts, but when I looked in the param.cpp code (in diamondback), I couldn't find where the cached params were being updated. Instead it looks for all the world like the normal params are being updated and the cached ones are not.
Asomerville gravatar image Asomerville  ( 2011-05-05 16:01:38 -0600 )edit
2

answered 2011-05-04 15:50:50 -0600

updated 2011-05-05 10:37:38 -0600

It doesn't appear to be a conventionally exposed interface for doing so, and it's probably not a recommended route, but if you have a look in stacks/ros_comm/clients/cpp/roscpp/src/libros you'll find param.cpp where ros does it's parameter handling for each node. (edit) You can try to emulate what they did.

In:

   void init(const M_string& remappings)

you'll see that they set up a callback:

   XMLRPCManager::instance()->bind("paramUpdate", paramUpdateCallback);

Which is used to update the local parameter table. You might be able to set up your own callback to do this, but I'm unsure if it would interfere with the node's own parameter updating.

The signature of the callback looks like this btw:

    void callback(XmlRpc::XmlRpcValue& params, XmlRpc::XmlRpcValue& result)

You can look at param.cpp for details on how to use the arguments.

edit flag offensive delete link more

Comments

I was looking for something more standard because changing param.cpp is not an option.
Victor Lopez gravatar image Victor Lopez  ( 2011-05-05 03:31:07 -0600 )edit
You don't need to change param.cpp to use this, simply use the same method it does to attach a callback. I only say not conventionally exposed because I've not ever seen the use of XMLRPCManager discussed in any ros documentation.
Asomerville gravatar image Asomerville  ( 2011-05-05 06:04:44 -0600 )edit
You're right, sorry I misunderstood you. Certainly it might interfere with normal param updating, I think I'll use a less intrusive approach.
Victor Lopez gravatar image Victor Lopez  ( 2011-05-05 19:59:17 -0600 )edit

I tried binding to the same callback, but the program tends to gets stuck after this call, and I never receive a callback. If I first unbind the original callback method and then bind my implementation, it works, but that's too intrusive. Did anyone experience the same problem?

Mate Wolfram gravatar image Mate Wolfram  ( 2013-06-02 20:46:55 -0600 )edit
2

answered 2016-06-30 05:10:10 -0600

phlf gravatar image

updated 2016-06-30 07:50:06 -0600

I was looking for a way to accomplish this without the useful but cumbersome dynamic_reconfigure package as I think we have enough things to deal with, just considering ROS messages/actions/services, launch files (that support YAML syntax in XML...) and catkin specific CMakeLists file without adding another layer of complexity which is often unneeded.

So here is my working but *flawed example (I followed Asormeville's hints):

#include <ros/ros.h>
#include <ros/xmlrpc_manager.h>
#include <std_msgs/String.h>

void callback(XmlRpc::XmlRpcValue& params, XmlRpc::XmlRpcValue& result)
{
    ROS_ERROR("Updated parameters!");
}

int main(int argc, char **argv)
{
    XmlRpc::XmlRpcValue params, result, payload;

    ros::init(argc, argv, "test_node");

    ros::NodeHandle nh;

    ros::XMLRPCManager::instance()->unbind("paramUpdate");
    ros::XMLRPCManager::instance()->bind("paramUpdate", callback);

    ros::param::set("~test_param", true);

    ROS_INFO("Created new parameter through XmlRpc API call.");

    params[0] = ros::this_node::getName();
    params[1] = ros::XMLRPCManager::instance()->getServerURI();
    params[2] = ros::names::resolve(std::string("~test_param"));

    if (ros::master::execute("subscribeParam", params, result, payload, false)) {
        ROS_INFO("Subscribed to parameter.");
    }
    else {
        ROS_ERROR("Failed to subscribe to the parameter.");
    }

    while (ros::ok()) {
        ros::spinOnce();
    }

    return 0;
}

The next steps would be to have a specific callback per parameter. But I don't know if that would be possible and it would begin to look like Publishers/Subscribers mechanisms.

* The ROS node redefining this callback won't be able to use the ros::param::getCached() function anymore.

edit flag offensive delete link more

Comments

At first, thank you for the information sharing. I think this answer is the closest to the goal.

It is possible to use getCached function, you just need to make a hack of declaring ros::param::paramUpdateCallback, and then calling it in your custom callback. I checked it, the cache is filled this way.

Probably it's possible to implement individual subscribers for each parameters by adding sub-callbacks inside the main callback. But I'm already happy with your solution.

_andrei_ gravatar image _andrei_  ( 2022-04-06 05:02:01 -0600 )edit

Happy if my answer may have helped someone six years later ;) I did not follow ROS development closely so there may me a more effective way to do the same kind of things with ROS2 (though I am not sure there is still a concept of a parameter server)

phlf gravatar image phlf  ( 2022-04-06 05:47:17 -0600 )edit

Question Tools

2 followers

Stats

Asked: 2011-05-02 02:25:41 -0600

Seen: 3,633 times

Last updated: Jun 30 '16