Ask Your Question
0

[ROS2][rclpy] how to set parameter hosted by another Node via service [closed]

asked 2020-02-05 01:09:44 -0600

lin404 gravatar image

updated 2020-02-05 18:15:42 -0600

I am looking for a solution to set the Parameter which is host by another node using rclpy.

I found there is a relavent post, but in rclcpp.

While, I tried below. But the error occurred. Any idea how I can fix it? Thank you very much!

import time

import rclpy
from rclpy.node import Node
import rclpy.qos as qos

from rclpy.parameter import Parameter
# from rcl_interfaces.msg import Parameter
from rcl_interfaces.msg import ParameterValue
from rcl_interfaces.srv import SetParameters, GetParameters, ListParameters
from rcl_interfaces.msg import ParameterDescriptor, ParameterValue


class MinimalClientAsync(Node):

    def __init__(self):
        super().__init__('my_node')

        self.cli = self.create_client(SetParameters, '/another_node/set_parameters')
        while not self.cli.wait_for_service(timeout_sec=1.0):
            self.get_logger().info('service not available, waiting again...')
        self.req = SetParameters.Request()

    def send_request(self):
        self.req.parameters = [Parameter(name='parameter_1', value=13)]
        self.future = self.cli.call_async(self.req)


def main(args=None):
    rclpy.init(args=args)

    minimal_client = MinimalClientAsync()
    minimal_client.send_request()

    while rclpy.ok():
        rclpy.spin_once(minimal_client)
        if minimal_client.future.done():
            try:
                response = minimal_client.future.result()
            except Exception as e:
                minimal_client.get_logger().info(
                    'Service call failed %r' % (e,))
            break

    minimal_client.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()

The error is:

  File "/opt/ros/dashing/lib/python3.6/site-packages/rcl_interfaces/srv/_set_parameters.py", line 138, in parameters
    "The 'parameters' field must be a set or sequence and each value of type 'Parameter'"
AssertionError: The 'parameters' field must be a set or sequence and each value of type 'Parameter'

I also tried to use rcl_interfaces.msg.Parameter instead of rclpy.parameter.Parameter so it won't failed at rcl_interfaces/srv/_set_parameters.py. However it failed at rcl_interfaces/msg/_parameter.py this time:

  File "/opt/ros/dashing/lib/python3.6/site-packages/rcl_interfaces/msg/_parameter.py", line 80, in __init__
    self.value = kwargs.get('value', ParameterValue())
  File "/opt/ros/dashing/lib/python3.6/site-packages/rcl_interfaces/msg/_parameter.py", line 149, in value
    "The 'value' field must be a sub message of type 'ParameterValue'"
AssertionError: The 'value' field must be a sub message of type 'ParameterValue'

Then I kept trying, used ParameterValue, like this:

Parameter(name='parameter_1', value=ParameterValue(integer_value=3))

It did not cause any error, but when I check the param, it shows Parameter not set.. I am confused. The parameter parameter_1 seems to be undeclared.

edit retag flag offensive reopen merge delete

Closed for the following reason duplicate question by lin404
close date 2020-02-05 18:18:44.228658

1 Answer

Sort by ยป oldest newest most voted
1

answered 2020-02-05 03:22:14 -0600

marguedas gravatar image

You're very close. As there is currently no helper in rclpy, the "easier" might be to use only rcl_interfaces type for now to avoid confusion

The 'parameters' field must be a set or sequence and each value of type 'Parameter'

This means that you need to pass a rcl_interfaces.msg.Parameter to this function.

Then I kept trying, used ParameterValue, like this:

That's the way to go. On top of defining the value, the type of the parameter needs to be set, as it is not detected automatically

Parameter(name='parameter_1', value=ParameterValue(integer_value=3, type=ParameterType.PARAMETER_INTEGER))

The send_request function will look like this:

def send_request(self):
    new_param_value = ParameterValue(type=ParameterType.PARAMETER_INTEGER, integer_value=13)
    self.req.parameters = [Parameter(name='parameter_1', value=new_param_value)]
    self.future = self.cli.call_async(self.req)

Note that you'll need to import ParameterType from rcl_interfaces.msg at the top of your file.

edit flag offensive delete link more

Comments

@marguedas Thank you very much! I have confirmed it, it works perfect!

lin404 gravatar imagelin404 ( 2020-02-05 18:16:32 -0600 )edit

Question Tools

2 followers

Stats

Asked: 2020-02-05 01:09:44 -0600

Seen: 23 times

Last updated: Feb 05