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

Access parameters set from another node

asked 2018-10-17 19:30:02 -0500

alsora gravatar image

updated 2018-10-17 19:39:47 -0500

Hi,

I'm using ROS2 Bouncy.

I have two nodes. What I would like to do is to allow the first node to set some parameters on the parameters server and then make the second node to retrieve these parameters.

The problem is that I'm able to see the parameters only from the node that has set them.

NODE 1

  rclcpp::init(argc, argv);
  rclcpp::Node::SharedPtr node = rclcpp::Node::make_shared("node_1");

  rclcpp::SyncParametersClient::SharedPtr parameters_client = std::make_shared<rclcpp::SyncParametersClient>(node);

  while (!parameters_client->wait_for_service(1s)){ 
     if (!rclcpp::ok()) { 
         RCLCPP_ERROR(node->get_logger(), "Interrupted while waiting for the service. Exiting.");
         return 0;}
    RCLCPP_INFO(node->get_logger(), "service not available, waiting again..."); }

  std::vector<rcl_interfaces::msg::SetParametersResult> set_parameters_results = parameters_client->set_parameters({rclcpp::Parameter("wheels.radius", 1)});

  rclcpp::spin(node);
  rclcpp::shutdown();

NODE 2

  rclcpp::init(argc, argv);
  rclcpp::Node::SharedPtr node = rclcpp::Node::make_shared("node_2");

  rclcpp::SyncParametersClient::SharedPtr parameters_client = std::make_shared<rclcpp::SyncParametersClient>(node);

  while (!parameters_client->wait_for_service(1s)){ 
     if (!rclcpp::ok()) { 
         RCLCPP_ERROR(node->get_logger(), "Interrupted while waiting for the service. Exiting.");
         return 0;}
    RCLCPP_INFO(node->get_logger(), "service not available, waiting again..."); }

    rclcpp::spin_some(node);

    auto parameters_and_prefixes = parameters_client->list_parameters({ }, 0);
    std::cout<<"READING PARAMS"<<std::endl;
    for (auto & name : parameters_and_prefixes.names) {
        std::cout<<"P: "<< name << std::endl;
    }

The parameters_and_prefixes variable in the second node is an empty vector. On the other hand, if I try to list all parameters from node 1 (where they are actually set), everything works fine.

It looks like I'm setting the parameters for node 1 only... What should I change ? Thanks

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
2

answered 2018-10-17 20:03:28 -0500

William gravatar image

I believe the issue is that in NODE 2 you're not providing a remote node name:

http://docs.ros2.org/bouncy/api/rclcp...

(it's the second argument after the handle to the local node)

Basically that defaults to "" which implicitly means "this node", which I admit isn't very clear.

So yes, in NODE 2 you're listing parameters on yourself rather than NODE 1.

Try this change in NODE 2:

auto parameters_client = std::make_shared<rclcpp::SyncParametersClient>(node, "node_1");
edit flag offensive delete link more

Comments

Thank you for the clarification! Is there a way to have some sort of global parameters? Which can be accessed even without knowing which node has created them? They can still live within one node and have its lifetime, but I really would like to throw away the node name from the method..

alsora gravatar image alsora  ( 2018-10-17 20:38:52 -0500 )edit

For global parameters, from what I see here, I don't think it will be possible: For the sake of validating parameter lifecycle, all parameters will be hosted on a node. Their lifetime will be implicitly tied to the nodes lifetime.

Marc Testier gravatar image Marc Testier  ( 2018-10-17 20:48:18 -0500 )edit

Nm, forget my previous comment, if you read a bit further it says : Backwards compatibility Parameter Server like behavior [...] To this end we propose to write a simple node which emulates the policy of the ROS 1.0 parameter server: it runs in namespace / and simply accepts all changes requested.

Marc Testier gravatar image Marc Testier  ( 2018-10-17 20:55:15 -0500 )edit

It was the proposed approach though, so I don't know what has been implemented yet or if it changed.

Marc Testier gravatar image Marc Testier  ( 2018-10-17 20:56:46 -0500 )edit
1

There's no global parameters right now. We have always talked about having a special node that accepts all parameter changes and maybe some convenience functions in rclcpp for accessing it, but we haven't done that yet.

William gravatar image William  ( 2018-10-17 21:35:22 -0500 )edit

@William is setting the remote node to "" and then setting/getting parameters equivalent to use the methods Node::set_parameters, Node::get_parameters defined here https://github.com/ros2/rclcpp/blob/m... ?

alsora gravatar image alsora  ( 2018-10-25 11:50:45 -0500 )edit

Yup! In fact I've considered removing the ability to use the parameter client on "self", but it's useful for tests.

William gravatar image William  ( 2018-10-25 14:10:43 -0500 )edit

@William Thanks! If I do not create a parameter client on "self" can I still register a rcl_interfaces::msg::ParameterEvent callback for the parameters owned by this node? Despite the name, it looks to me that register_param_change_callback should be used for accepting/rejecting changes only

alsora gravatar image alsora  ( 2018-10-25 18:09:06 -0500 )edit
1

answered 2018-10-17 20:01:59 -0500

Marc Testier gravatar image

updated 2018-10-17 20:10:06 -0500

You can give a remote_node_name when creating a SyncParametersClient:

SyncParametersClient(
    rclcpp::Node::SharedPtr node,
    const std::string & remote_node_name = "",
    const rmw_qos_profile_t & qos_profile = rmw_qos_profile_parameters)

So in NODE 1 you can do :

rclcpp::SyncParametersClient::SharedPtr parameters_client = std::make_shared<rclcpp::SyncParametersClient>(node, "node2");

edit: If you want to catch parameter changes during run time, you might want to play with parameters events. Because from what I tried (very quickly, might be wrong), NODE 1 is going to wait for NODE 2 to be launched at while (!parameters_client->wait_for_service(1s)). So you'll have to launch NODE 2 first but then in NODE 2 you only check parameters once in the main and since NODE 1 hasn't set them yet, you won't receive them.

edit 2: Just in case, you can find examples about this in the demos pkg.

edit flag offensive delete link more

Comments

^ What he said :D

William gravatar image William  ( 2018-10-17 20:03:45 -0500 )edit

Thank you, it works, but I don't think I can use it in more general cases where there is more than one node willing to read the parameters. Moreover I need to hardcode node2 which is something that I could not know while writing the code for node1. Maybe I need a ParameterService ?

alsora gravatar image alsora  ( 2018-10-17 20:10:58 -0500 )edit

Oh yeah, the other option is to set the parameter on NODE 1 for NODE 1, so don't change what you did in NODE 1 but use what @William said

auto parameters_client = std::make_shared<rclcpp::SyncParametersClient>(node, "node_1");

in NODE 2, NODE 3, etc

Marc Testier gravatar image Marc Testier  ( 2018-10-17 20:16:05 -0500 )edit

Haven't tried ParameterService yet so I actually don't know what they are for... might be a solution.

Marc Testier gravatar image Marc Testier  ( 2018-10-17 20:19:21 -0500 )edit

Question Tools

3 followers

Stats

Asked: 2018-10-17 19:30:02 -0500

Seen: 2,437 times

Last updated: Oct 17 '18