找回密码
 立即注册
首页 业界区 业界 ROS2核心概念之参数

ROS2核心概念之参数

亢安芙 昨天 22:50
在前面的文章,我们已经介绍了话题题、服务、动作三种通信机制,接下来呢我们再来介绍一种ROS系统中常用的数据传输方式——参数。
类似C++编程中的全局变量,可以便于在多个程序中共享某些数据,参数是ROS机器人系统中的全局字典,可以运行多个节点中共享数据。
一、通信模型

在机器视觉识别的时候,有很多参数都会影响视觉识别的效果;
1.png
在Node A相机驱动节点中,就需要考虑很多问题,相机连接到哪个USB端口,使用的图像分辨率是多少,曝光度和编码格式分别是什么,这些都可以通过参数设置,我们可以通过配置文件或者程序进行设置。
Node B节点中也是一样,图像识别使用的阈值是多少,整个图像面积很大,那个部分是我们关注的核心区域,识别过程是否需要美颜等等,就像我们使用美颜相机一样,我们可以通过滑动条或者输入框设置很多参数,不同参数设置后,都会改变执行功能的一些效果。
这就是参数的作用。
1.1 全局字典

在ROS系统中,参数是以全局字典的形态存在的,什么叫字典?
就像真实的字典一样,由名称和数值组成,也叫做键和值,合成键值。或者我们也可以理解为,就像编程中的参数一样,有一个参数名 ,然后跟一个等号,后边就是参数值了,在使用的时候,访问这个参数名即可。
1.2 可动态监控

在ROS2中,参数的特性非常丰富,比如某一个节点共享了一个参数,其它节点都可以访问,如果某一个节点对参数进行了修改,其它节点也有办法立刻知道,从而获取最新的数值。这在参数的高级编程中,我们都可能会用到。
二、参数案例

2.1 小海龟的参数

在小海龟的例程中,仿真器也提供了不少参数,我们一起来通过这个例程,熟悉下参数的含义和命令行的使用方法。
进入桌面系统,启动第一个终端,运行小海龟仿真器;
  1. pi@NanoPC-T6:~/dev_ws$ ros2 run turtlesim turtlesim_node
复制代码
该指令将启动一个蓝色背景的海龟仿真器;
启动第二个终端,运行如下指令:
  1. pi@NanoPC-T6:~/dev_ws$ ros2 run turtlesim turtle_teleop_key
复制代码
该指令将启动一个键盘控制节点,在该终端中点击键盘上的“上下左右”按键,就可以控制小海龟运动啦。
2.1.1 查看参数列表

当前系统中有哪些参数呢?我们可以启动一个终端,并使用如下命令查询:
  1. pi@NanoPC-T6:~/dev_ws$ ros2 param list
  2. /teleop_turtle:
  3.   qos_overrides./parameter_events.publisher.depth
  4.   qos_overrides./parameter_events.publisher.durability
  5.   qos_overrides./parameter_events.publisher.history
  6.   qos_overrides./parameter_events.publisher.reliability
  7.   scale_angular
  8.   scale_linear
  9.   use_sim_time
  10. /turtlesim:
  11.   background_b
  12.   background_g
  13.   background_r
  14.   qos_overrides./parameter_events.publisher.depth
  15.   qos_overrides./parameter_events.publisher.durability
  16.   qos_overrides./parameter_events.publisher.history
  17.   qos_overrides./parameter_events.publisher.reliability
  18.   use_sim_time
复制代码
可以看到系统中有两个正在运行的节点:

  • /teleop_turtle:键盘控制节点;

    • scale_linear:控制线性速度缩放比例;
    • scale_angular:控制角速度缩放比例;
    • use_sim_time:是否使用仿真时间;

  • /turtlesim: 海龟仿真节点;

    • background_b:背景颜色的蓝色分量 (0-255);
    • background_g:背景颜色的绿色分量 (0-255);
    • background_r:背景颜色的红色分量 (0-255);
    • use_sim_time:是否使用仿真时间。
    两个节点都有针对参数事件发布器的QoS覆盖参数:

    • qos_overrides./parameter_events.publisher.depth;
    • qos_overrides./parameter_events.publisher.durability;
    • qos_overrides./parameter_events.publisher.history;
    • qos_overrides./parameter_events.publisher.reliability。

2.1.2 参数查询与修改

2.1.2.1 获取参数值

如果想要查询或者修改某个参数的值,可以在param命令后边跟get或者set子命令。
获取键盘控制的速度参数:
  1. pi@NanoPC-T6:~/dev_ws$ ros2 param get /teleop_turtle scale_linear
  2. Double value is: 2.0
  3. pi@NanoPC-T6:~/dev_ws$ ros2 param get /teleop_turtle scale_angular
  4. Double value is: 2.0
复制代码
获取小海龟仿真的背景颜色:
  1. pi@NanoPC-T6:~/dev_ws$ ros2 param get /turtlesim background_r
  2. Integer value is: 69
复制代码
2.1.2.2 查看参数描述信息

查看某个参数的描述信息:
  1. pi@NanoPC-T6:~/dev_ws$ ros2 param describe /turtlesim background_b
  2. Parameter name: background_b
  3.   Type: integer
  4.   Description: Blue channel of the background color
  5.   Constraints:
  6.     Min value: 0
  7.     Max value: 255
  8.     Step: 1
复制代码
2.1.2.3 设置参数值

让小海龟移动更快:
  1. pi@NanoPC-T6:~/dev_ws$ ros2 param set /teleop_turtle scale_linear 3.0
  2. Set parameter successful
  3. pi@NanoPC-T6:~/dev_ws$ ros2 param set /teleop_turtle scale_angular 3.0
  4. Set parameter successful
复制代码
改变小海龟仿真背景颜色:
  1. pi@NanoPC-T6:~/dev_ws$ ros2 param set /turtlesim background_r 100
  2. Set parameter successful
  3. pi@NanoPC-T6:~/dev_ws$ ros2 param set /turtlesim background_g 50
  4. Set parameter successful
  5. pi@NanoPC-T6:~/dev_ws$ ros2 param set /turtlesim background_b 150
  6. Set parameter successful
复制代码
2.1.3 参数文件保存与加载

一个一个查询/修改参数太麻烦了,不如试一试参数文件,ROS中的参数文件使用yaml格式,可以在param命令后边跟dump子命令,将某个节点的参数都保存到文件中,或者通过load命令一次性加载某个参数文件中的所有内容。
将某个节点的参数保存到参数文件中:
  1. pi@NanoPC-T6:~/dev_ws$ ros2 param dump /turtlesim >> turtlesim.yaml
  2. pi@NanoPC-T6:~/dev_ws$ cat turtlesim.yaml
  3. /turtlesim:
  4.   ros__parameters:
  5.     background_b: 150
  6.     background_g: 50
  7.     background_r: 100
  8.     qos_overrides:
  9.       /parameter_events:
  10.         publisher:
  11.           depth: 1000
  12.           durability: volatile
  13.           history: keep_last
  14.           reliability: reliable
  15.     use_sim_time: false
复制代码
一次性加载某一个文件中的所有参数:
  1. pi@NanoPC-T6:~/dev_ws$ ros2 param load /turtlesim turtlesim.yaml
复制代码
2.2 简单参数示例

接下来就要开始写程序了,在程序中设置参数和读取参数都比较简单,一两句函数就可以实现,我们先来体验一下这几个函数的使用方法。
我们首先创建my_learning_parameter的Python版本的功能包;
  1. pi@NanoPC-T6:~/dev_ws$ cd src
  2. pi@NanoPC-T6:~/dev_ws/src$ ros2 pkg create --build-type ament_python my_learning_parameter
复制代码
2.2.1 代码实现

打开my_learning_parameter功能包,在my_learning_parameter文件夹下创建param_declare.py;
  1. """
  2. ROS2参数示例-创建、读取、修改参数
  3. @author: zy
  4. @since : 2025/12/15
  5. """
  6. import rclpy                                     # ROS2 Python接口库
  7. from rclpy.node import Node                      # ROS2 节点类
  8. class ParameterNode(Node):
  9.     def __init__(self, name):
  10.         super().__init__(name)                                    # ROS2节点父类初始化
  11.         self.timer = self.create_timer(2, self.timer_callback)    # 创建一个定时器(单位为秒的周期,定时执行的回调函数)
  12.         self.declare_parameter('robot_name', 'mbot')              # 创建一个参数,并设置参数的默认值
  13.     def timer_callback(self):                                      # 创建定时器周期执行的回调函数
  14.         robot_name_param = self.get_parameter('robot_name').get_parameter_value().string_value   # 从ROS2系统中读取参数的值
  15.         self.get_logger().info('Hello %s!' % robot_name_param)     # 输出日志信息,打印读取到的参数值
  16.         new_name_param = rclpy.parameter.Parameter(                # 创建一个新的 Parameter 对象
  17.             'robot_name',                                          # 参数名称
  18.             rclpy.Parameter.Type.STRING,                           # 参数类型(字符串类型)
  19.             'mbot'                                                 # 参数值
  20.         )
  21.         all_new_parameters = [new_name_param]
  22.         self.set_parameters(all_new_parameters)                    # 将重新创建的参数列表发送给ROS2系统
  23. def main(args=None):                                 # ROS2节点主入口main函数
  24.     rclpy.init(args=args)                            # ROS2 Python接口初始化
  25.     node = ParameterNode("param_declare")            # 创建ROS2节点对象并进行初始化
  26.     rclpy.spin(node)                                 # 循环等待ROS2退出
  27.     node.destroy_node()                              # 销毁节点对象
  28.     rclpy.shutdown()                                 # 关闭ROS2 Python接口
复制代码
完成代码的编写后需要设置功能包的编译选项,让系统知道Python程序的入口,打开功能包的setup.py文件,加入如下入口点的配置:
  1.     entry_points={
  2.         'console_scripts': [
  3.             'param_declare          = my_learning_parameter.param_declare:main',
  4.         ],
  5.     },
复制代码
2.2.2 编译运行

编译程序:
  1. pi@NanoPC-T6:~/dev_ws$ colcon build --paths src/my_learning_parameter
复制代码
启动第一个终端,运行节点;
  1. pi@NanoPC-T6:~/dev_ws$ ros2 run my_learning_parameter param_declare
  2. [INFO] [1765804528.869092474] [param_declare]: Hello mbot!
  3. [INFO] [1765804530.840071999] [param_declare]: Hello mbot!
  4. [INFO] [1765804532.840587253] [param_declare]: Hello mbot!
  5. ......
  6. INFO] [1765804620.837805446] [param_declare]: Hello mbot!
  7. [INFO] [1765804622.839387783] [param_declare]: Hello turtle!
  8. .....
复制代码
再启动一个中断修改参数robot_name的值;
  1. pi@NanoPC-T6:~/dev_ws$ ros2 param set param_declare robot_name turtle
  2. Set parameter successful
复制代码
2.2.3 流程分析

总结一下,想要实现一个参数设置,代码的实现流程是这样做;

  • 编程接口初始化;
  • 创建节点并初始化;
  • 声明参数,并在定时器读取、设置自己的参数;
  • 销毁节点并关闭接口。
2.3 机器视觉应用

我们已经初步学会了参数的使用,如何在机器人中应用呢?
继续优化机器视觉的示例,物体识别对光线比较敏感,不同的环境大家使用的阈值也是不同的,每次在代码中修改阈值还挺麻烦,不如我们就把阈值提炼成参数,运行过程中就可以动态设置,不是大大提高了程序的易用性么?
说干就干,我们先来看下效果如何,这里我们使用两个节点;

  • 机驱动节点:将驱动相机并发布图像话题,此时的话题数据使用的是ROS中标准定义的Image图像消息;
  • 视觉识别节点:订阅图像数据,并运行视觉识别功能,识别目标的位置;
2.3.1 代码实现

在my_learning_parameter文件夹下创建param_object_detect.py;
  1. """
  2. ROS2参数示例-设置目标识别的颜色阈值参数
  3. @author: zy
  4. @since : 2025/12/15
  5. """
  6. import rclpy                      # ROS2 Python接口库
  7. from rclpy.node import Node       # ROS2 节点类
  8. from sensor_msgs.msg import Image # 图像消息类型
  9. from cv_bridge import CvBridge    # ROS与OpenCV图像转换类
  10. import cv2                        # Opencv图像处理库
  11. import numpy as np                # Python数值计算库
  12. lower_red = np.array([0, 90, 128])     # 红色的HSV阈值下限
  13. upper_red = np.array([180, 255, 255])  # 红色的HSV阈值上限
  14. """
  15. 创建一个订阅者节点
  16. """
  17. class ImageSubscriber(Node):
  18.   def __init__(self, name):
  19.     super().__init__(name)                                  # ROS2节点父类初始化   
  20.     self.sub = self.create_subscription(Image,              # 创建订阅者对象(消息类型、话题名、订阅者回调函数、队列长度)     
  21.                   'image_raw', self.listener_callback, 10)
  22.     self.cv_bridge = CvBridge()                             # 创建一个图像转换对象,用于OpenCV图像与ROS的图像消息的互相转换
  23.     self.declare_parameter('red_h_upper', 0)                # 创建一个参数,表示阈值上限
  24.     self.declare_parameter('red_h_lower', 0)                # 创建一个参数,表示阈值下限
  25.   def object_detect(self, image):
  26.     upper_red[0] = self.get_parameter('red_h_upper').get_parameter_value().integer_value    # 读取阈值上限的参数值
  27.     lower_red[0] = self.get_parameter('red_h_lower').get_parameter_value().integer_value    # 读取阈值下限的参数值
  28.     self.get_logger().info('Get Red H Upper: %d, Lower: %d' % (upper_red[0], lower_red[0])) # 通过日志打印读取到的参数值
  29.     hsv_img = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)                                        # 图像从BGR颜色模型转换为HSV模型
  30.     mask_red = cv2.inRange(hsv_img, lower_red, upper_red)                                   # 图像二值化
  31.     contours, hierarchy = cv2.findContours(mask_red, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)  # 图像中轮廓检测
  32.     for cnt in contours:                                                                    # 去除一些轮廓面积太小的噪声
  33.         if cnt.shape[0] < 150:
  34.             continue
  35.         (x, y, w, h) = cv2.boundingRect(cnt)                            # 得到苹果所在轮廓的左上角xy像素坐标及轮廓范围的宽和高
  36.         cv2.drawContours(image, [cnt], -1, (0, 255, 0), 2)              # 将苹果的轮廓勾勒出来
  37.         cv2.circle(image, (int(x+w/2), int(y+h/2)), 5, (0, 255, 0), -1) # 将苹果的图像中心点画出来
  38.     cv2.imshow("object", image)                                         # 使用OpenCV显示处理后的图像效果
  39.     cv2.waitKey(50)
  40.   def listener_callback(self, data):
  41.     self.get_logger().info('Receiving video frame')     # 输出日志信息,提示已进入回调函数
  42.     image = self.cv_bridge.imgmsg_to_cv2(data, "bgr8")  # 将ROS的图像消息转化成OpenCV图像
  43.     self.object_detect(image)                            # 苹果检测
  44. def main(args=None):                                    # ROS2节点主入口main函数
  45.     rclpy.init(args=args)                               # ROS2 Python接口初始化
  46.     node = ImageSubscriber("param_object_detect")       # 创建ROS2节点对象并进行初始化
  47.     rclpy.spin(node)                                    # 循环等待ROS2退出
  48.     node.destroy_node()                                 # 销毁节点对象
  49.     rclpy.shutdown()                                    # 关闭ROS2 Python接口
复制代码
完成代码的编写后需要设置功能包的编译选项,让系统知道Python程序的入口,打开功能包的setup.py文件,加入如下入口点的配置:
  1.     entry_points={
  2.         'console_scripts': [
  3.             'param_declare          = my_learning_parameter.param_declare:main',
  4.             'param_object_detect    = my_learning_parameter.param_object_detect:main',
  5.         ],
  6.     },
复制代码
2.3.2 编译运行

编译程序:
  1. pi@NanoPC-T6:~/dev_ws$ colcon build --paths src/my_learning_parameter
复制代码
启动第一个终端,第一个节点是相机驱动节点,发布图像数据;
  1. pi@NanoPC-T6:~/dev_ws$ ros2 run usb_cam usb_cam_node_exe --ros-args -p video_device:="/dev/video21"
复制代码
启动第二个终端,订阅图像数据,并运行视觉识别功能,识别目标的位置;
  1. pi@NanoPC-T6:~/dev_ws$ ros2 run my_learning_parameter param_object_detect
复制代码
在视觉识别节点中,我们故意将视觉识别中红色阈值的上限设置为0;
  1. lower_red = np.array([0, 90, 128])     # 红色的HSV阈值下限
  2. upper_red = np.array([180, 255, 255])  # 红色的HSV阈值上限
  3. ......
  4.     self.declare_parameter('red_h_upper', 0)                # 创建一个参数,表示阈值上限
  5.     self.declare_parameter('red_h_lower', 0)                # 创建一个参数,表示阈值下限
  6. ......
  7.     upper_red[0] = self.get_parameter('red_h_upper').get_parameter_value().integer_value    # 读取阈值上限的参数值
  8.     lower_red[0] = self.get_parameter('red_h_lower').get_parameter_value().integer_value
复制代码
HSV是一种将RGB颜色表示为三个分量的颜色模型:

  • H (Hue):色相/色调 (0-180°);
  • S (Saturation): 饱和度 (0-255);
  • V (Value):明度/亮度 (0-255);
如果不修改参数,将无法实现目标识别。为了便于调整阈值,我们在节点中将红色阈值的限位修改为了ROS参数,通过命令行修改该参数的值,就可以实现视觉识别啦;
  1. pi@NanoPC-T6:~/dev_ws$ ros2 param set param_object_detect red_h_upper 180
复制代码
2.png
2.4 参数命令行操作

参数相关命令:
  1. pi@NanoPC-T6:~/dev_ws$ ros2 param
  2. usage: ros2 param [-h] Call `ros2 param <command> -h` for more detailed usage. ...
  3. Various param related sub-commands
  4. options:
  5.   -h, --help            show this help message and exit
  6. Commands:
  7.   delete    Delete parameter
  8.   describe  Show descriptive information about declared parameters
  9.   dump      Show all of the parameters of a node in a YAML file format
  10.   get       Get parameter
  11.   list      Output a list of available parameters
  12.   load      Load parameter file for a node
  13.   set       Set parameter
  14.   Call `ros2 param <command> -h` for more detailed usage.
复制代码
2.4.1 查看参数列表
  1. pi@NanoPC-T6:~/dev_ws$ ros2 param list
  2. /param_object_detect:
  3.   red_h_lower
  4.   red_h_upper
  5.   use_sim_time
  6. /usb_cam:
  7.   auto_white_balance
  8.   autoexposure
  9.   autofocus
  10.   ......
复制代码
可以看到我们实现的/param_object_detect节点有三个参数,其中:

  • red_h_lower: 红色识别的最小色相阈值 (Hue lower);
  • red_h_upper:红色识别的最大色相阈值 (Hue upper);
  • use_sim_time :是否使用仿真时间。
red_h_lower和red_h_upper我们在代码里有定义,而use_sim_time 是ROS 2节点的一个内置默认参数,所有节点都会自动拥有这个参数,即使没有在代码中声明它。
2.4.2 获取参数值
  1. pi@NanoPC-T6:~/dev_ws$ ros2 param get /param_object_detect red_h_upper
  2. Integer value is: 180
复制代码
2.4.3 查询参数信息
  1. pi@NanoPC-T6:~/dev_ws$ ros2 param describe /param_object_detect red_h_lower
  2. Parameter name: red_h_lower
  3.   Type: integer
  4.   Constraints:
  5. pi@NanoPC-T6:~/dev_ws$ ros2 param describe /param_object_detect red_h_upper
  6. Parameter name: red_h_upper
  7.   Type: integer
  8.   Constraints:
复制代码
2.4.4 设置参数值
  1. pi@NanoPC-T6:~/dev_ws$ ros2 param set param_object_detect red_h_upper 180       
复制代码
参考文章
[1] 古月居ROS2入门教程学习笔记

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册