程序项目代做,有需求私信(小程序、网站、爬虫、电路板设计、驱动、应用程序开发、毕设疑难问题处理等)

ROS2核心概念之参数

在前面的文章,我们已经介绍了话题题、服务、动作三种通信机制,接下来呢我们再来介绍一种ROS系统中常用的数据传输方式——参数。

类似C++编程中的全局变量,可以便于在多个程序中共享某些数据,参数是ROS机器人系统中的全局字典,可以运行多个节点中共享数据。

一、通信模型

在机器视觉识别的时候,有很多参数都会影响视觉识别的效果;

Node A相机驱动节点中,就需要考虑很多问题,相机连接到哪个USB端口,使用的图像分辨率是多少,曝光度和编码格式分别是什么,这些都可以通过参数设置,我们可以通过配置文件或者程序进行设置。

Node B节点中也是一样,图像识别使用的阈值是多少,整个图像面积很大,那个部分是我们关注的核心区域,识别过程是否需要美颜等等,就像我们使用美颜相机一样,我们可以通过滑动条或者输入框设置很多参数,不同参数设置后,都会改变执行功能的一些效果。

这就是参数的作用。

1.1 全局字典

ROS系统中,参数是以全局字典的形态存在的,什么叫字典?

就像真实的字典一样,由名称和数值组成,也叫做键和值,合成键值。或者我们也可以理解为,就像编程中的参数一样,有一个参数名 ,然后跟一个等号,后边就是参数值了,在使用的时候,访问这个参数名即可。

1.2 可动态监控

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

二、参数案例

2.1 小海龟的参数

在小海龟的例程中,仿真器也提供了不少参数,我们一起来通过这个例程,熟悉下参数的含义和命令行的使用方法。

进入桌面系统,启动第一个终端,运行小海龟仿真器;

pi@NanoPC-T6:~/dev_ws$ ros2 run turtlesim turtlesim_node

该指令将启动一个蓝色背景的海龟仿真器;

启动第二个终端,运行如下指令:

pi@NanoPC-T6:~/dev_ws$ ros2 run turtlesim turtle_teleop_key

该指令将启动一个键盘控制节点,在该终端中点击键盘上的“上下左右”按键,就可以控制小海龟运动啦。

2.1.1 查看参数列表

当前系统中有哪些参数呢?我们可以启动一个终端,并使用如下命令查询:

pi@NanoPC-T6:~/dev_ws$ ros2 param list
/teleop_turtle:
  qos_overrides./parameter_events.publisher.depth
  qos_overrides./parameter_events.publisher.durability
  qos_overrides./parameter_events.publisher.history
  qos_overrides./parameter_events.publisher.reliability
  scale_angular
  scale_linear
  use_sim_time
/turtlesim:
  background_b
  background_g
  background_r
  qos_overrides./parameter_events.publisher.depth
  qos_overrides./parameter_events.publisher.durability
  qos_overrides./parameter_events.publisher.history
  qos_overrides./parameter_events.publisher.reliability
  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子命令。

获取键盘控制的速度参数:

pi@NanoPC-T6:~/dev_ws$ ros2 param get /teleop_turtle scale_linear
Double value is: 2.0
pi@NanoPC-T6:~/dev_ws$ ros2 param get /teleop_turtle scale_angular
Double value is: 2.0

获取小海龟仿真的背景颜色:

pi@NanoPC-T6:~/dev_ws$ ros2 param get /turtlesim background_r
Integer value is: 69
2.1.2.2 查看参数描述信息

查看某个参数的描述信息:

pi@NanoPC-T6:~/dev_ws$ ros2 param describe /turtlesim background_b
Parameter name: background_b
  Type: integer
  Description: Blue channel of the background color
  Constraints:
    Min value: 0
    Max value: 255
    Step: 1
2.1.2.3 设置参数值

让小海龟移动更快:

pi@NanoPC-T6:~/dev_ws$ ros2 param set /teleop_turtle scale_linear 3.0
Set parameter successful
pi@NanoPC-T6:~/dev_ws$ ros2 param set /teleop_turtle scale_angular 3.0
Set parameter successful

改变小海龟仿真背景颜色:

pi@NanoPC-T6:~/dev_ws$ ros2 param set /turtlesim background_r 100
Set parameter successful
pi@NanoPC-T6:~/dev_ws$ ros2 param set /turtlesim background_g 50
Set parameter successful
pi@NanoPC-T6:~/dev_ws$ ros2 param set /turtlesim background_b 150
Set parameter successful
2.1.3 参数文件保存与加载

一个一个查询/修改参数太麻烦了,不如试一试参数文件,ROS中的参数文件使用yaml格式,可以在param命令后边跟dump子命令,将某个节点的参数都保存到文件中,或者通过load命令一次性加载某个参数文件中的所有内容。

将某个节点的参数保存到参数文件中:

pi@NanoPC-T6:~/dev_ws$ ros2 param dump /turtlesim >> turtlesim.yaml
pi@NanoPC-T6:~/dev_ws$ cat turtlesim.yaml
/turtlesim:
  ros__parameters:
    background_b: 150
    background_g: 50
    background_r: 100
    qos_overrides:
      /parameter_events:
        publisher:
          depth: 1000
          durability: volatile
          history: keep_last
          reliability: reliable
    use_sim_time: false

一次性加载某一个文件中的所有参数:

pi@NanoPC-T6:~/dev_ws$ ros2 param load /turtlesim turtlesim.yaml 

2.2 简单参数示例

接下来就要开始写程序了,在程序中设置参数和读取参数都比较简单,一两句函数就可以实现,我们先来体验一下这几个函数的使用方法。

我们首先创建my_learning_parameterPython版本的功能包;

pi@NanoPC-T6:~/dev_ws$ cd src
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

"""
ROS2参数示例-创建、读取、修改参数

@author: zy
@since : 2025/12/15
"""

import rclpy                                     # ROS2 Python接口库
from rclpy.node import Node                      # ROS2 节点类

class ParameterNode(Node):
    def __init__(self, name):
        super().__init__(name)                                    # ROS2节点父类初始化
        self.timer = self.create_timer(2, self.timer_callback)    # 创建一个定时器(单位为秒的周期,定时执行的回调函数)
        self.declare_parameter('robot_name', 'mbot')              # 创建一个参数,并设置参数的默认值

    def timer_callback(self):                                      # 创建定时器周期执行的回调函数
        robot_name_param = self.get_parameter('robot_name').get_parameter_value().string_value   # 从ROS2系统中读取参数的值

        self.get_logger().info('Hello %s!' % robot_name_param)     # 输出日志信息,打印读取到的参数值

        new_name_param = rclpy.parameter.Parameter(                # 创建一个新的 Parameter 对象
            'robot_name',                                          # 参数名称
            rclpy.Parameter.Type.STRING,                           # 参数类型(字符串类型)
            'mbot'                                                 # 参数值
        )
        all_new_parameters = [new_name_param]
        self.set_parameters(all_new_parameters)                    # 将重新创建的参数列表发送给ROS2系统

def main(args=None):                                 # ROS2节点主入口main函数
    rclpy.init(args=args)                            # ROS2 Python接口初始化
    node = ParameterNode("param_declare")            # 创建ROS2节点对象并进行初始化
    rclpy.spin(node)                                 # 循环等待ROS2退出
    node.destroy_node()                              # 销毁节点对象
    rclpy.shutdown()                                 # 关闭ROS2 Python接口

完成代码的编写后需要设置功能包的编译选项,让系统知道Python程序的入口,打开功能包的setup.py文件,加入如下入口点的配置:

    entry_points={
        'console_scripts': [
            'param_declare          = my_learning_parameter.param_declare:main',
        ],
    },
2.2.2 编译运行

编译程序:

pi@NanoPC-T6:~/dev_ws$ colcon build --paths src/my_learning_parameter

启动第一个终端,运行节点;

pi@NanoPC-T6:~/dev_ws$ ros2 run my_learning_parameter param_declare
[INFO] [1765804528.869092474] [param_declare]: Hello mbot!
[INFO] [1765804530.840071999] [param_declare]: Hello mbot!
[INFO] [1765804532.840587253] [param_declare]: Hello mbot!
......
INFO] [1765804620.837805446] [param_declare]: Hello mbot!
[INFO] [1765804622.839387783] [param_declare]: Hello turtle!
.....

再启动一个中断修改参数robot_name的值;

pi@NanoPC-T6:~/dev_ws$ ros2 param set param_declare robot_name turtle
Set parameter successful
2.2.3 流程分析

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

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

2.3 机器视觉应用

我们已经初步学会了参数的使用,如何在机器人中应用呢?

继续优化机器视觉的示例,物体识别对光线比较敏感,不同的环境大家使用的阈值也是不同的,每次在代码中修改阈值还挺麻烦,不如我们就把阈值提炼成参数,运行过程中就可以动态设置,不是大大提高了程序的易用性么?

说干就干,我们先来看下效果如何,这里我们使用两个节点;

  • 机驱动节点:将驱动相机并发布图像话题,此时的话题数据使用的是ROS中标准定义的Image图像消息;

  • 视觉识别节点:订阅图像数据,并运行视觉识别功能,识别目标的位置;

2.3.1 代码实现

my_learning_parameter文件夹下创建param_object_detect.py

"""
ROS2参数示例-设置目标识别的颜色阈值参数

@author: zy
@since : 2025/12/15
"""

import rclpy                      # ROS2 Python接口库
from rclpy.node import Node       # ROS2 节点类
from sensor_msgs.msg import Image # 图像消息类型
from cv_bridge import CvBridge    # ROS与OpenCV图像转换类
import cv2                        # Opencv图像处理库
import numpy as np                # Python数值计算库

lower_red = np.array([0, 90, 128])     # 红色的HSV阈值下限
upper_red = np.array([180, 255, 255])  # 红色的HSV阈值上限

"""
创建一个订阅者节点
"""
class ImageSubscriber(Node):
  def __init__(self, name):
    super().__init__(name)                                  # ROS2节点父类初始化    
    self.sub = self.create_subscription(Image,              # 创建订阅者对象(消息类型、话题名、订阅者回调函数、队列长度)     
                  'image_raw', self.listener_callback, 10) 
    self.cv_bridge = CvBridge()                             # 创建一个图像转换对象,用于OpenCV图像与ROS的图像消息的互相转换

    self.declare_parameter('red_h_upper', 0)                # 创建一个参数,表示阈值上限
    self.declare_parameter('red_h_lower', 0)                # 创建一个参数,表示阈值下限

  def object_detect(self, image):
    upper_red[0] = self.get_parameter('red_h_upper').get_parameter_value().integer_value    # 读取阈值上限的参数值
    lower_red[0] = self.get_parameter('red_h_lower').get_parameter_value().integer_value    # 读取阈值下限的参数值
    self.get_logger().info('Get Red H Upper: %d, Lower: %d' % (upper_red[0], lower_red[0])) # 通过日志打印读取到的参数值

    hsv_img = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)                                        # 图像从BGR颜色模型转换为HSV模型
    mask_red = cv2.inRange(hsv_img, lower_red, upper_red)                                   # 图像二值化
    contours, hierarchy = cv2.findContours(mask_red, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)  # 图像中轮廓检测
    for cnt in contours:                                                                    # 去除一些轮廓面积太小的噪声
        if cnt.shape[0] < 150:
            continue

        (x, y, w, h) = cv2.boundingRect(cnt)                            # 得到苹果所在轮廓的左上角xy像素坐标及轮廓范围的宽和高
        cv2.drawContours(image, [cnt], -1, (0, 255, 0), 2)              # 将苹果的轮廓勾勒出来
        cv2.circle(image, (int(x+w/2), int(y+h/2)), 5, (0, 255, 0), -1) # 将苹果的图像中心点画出来

    cv2.imshow("object", image)                                         # 使用OpenCV显示处理后的图像效果
    cv2.waitKey(50)

  def listener_callback(self, data):
    self.get_logger().info('Receiving video frame')     # 输出日志信息,提示已进入回调函数
    image = self.cv_bridge.imgmsg_to_cv2(data, "bgr8")  # 将ROS的图像消息转化成OpenCV图像
    self.object_detect(image)                            # 苹果检测

def main(args=None):                                    # ROS2节点主入口main函数
    rclpy.init(args=args)                               # ROS2 Python接口初始化
    node = ImageSubscriber("param_object_detect")       # 创建ROS2节点对象并进行初始化
    rclpy.spin(node)                                    # 循环等待ROS2退出
    node.destroy_node()                                 # 销毁节点对象
    rclpy.shutdown()                                    # 关闭ROS2 Python接口

完成代码的编写后需要设置功能包的编译选项,让系统知道Python程序的入口,打开功能包的setup.py文件,加入如下入口点的配置:

    entry_points={
        'console_scripts': [
            'param_declare          = my_learning_parameter.param_declare:main',
            'param_object_detect    = my_learning_parameter.param_object_detect:main',
        ],
    },
2.3.2 编译运行

编译程序:

pi@NanoPC-T6:~/dev_ws$ colcon build --paths src/my_learning_parameter

启动第一个终端,第一个节点是相机驱动节点,发布图像数据;

pi@NanoPC-T6:~/dev_ws$ ros2 run usb_cam usb_cam_node_exe --ros-args -p video_device:="/dev/video21"

启动第二个终端,订阅图像数据,并运行视觉识别功能,识别目标的位置;

pi@NanoPC-T6:~/dev_ws$ ros2 run my_learning_parameter param_object_detect

在视觉识别节点中,我们故意将视觉识别中红色阈值的上限设置为0

lower_red = np.array([0, 90, 128])     # 红色的HSV阈值下限
upper_red = np.array([180, 255, 255])  # 红色的HSV阈值上限

......
    self.declare_parameter('red_h_upper', 0)                # 创建一个参数,表示阈值上限
    self.declare_parameter('red_h_lower', 0)                # 创建一个参数,表示阈值下限
......
    upper_red[0] = self.get_parameter('red_h_upper').get_parameter_value().integer_value    # 读取阈值上限的参数值
    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参数,通过命令行修改该参数的值,就可以实现视觉识别啦;

pi@NanoPC-T6:~/dev_ws$ ros2 param set param_object_detect red_h_upper 180

2.4 参数命令行操作

参数相关命令:

pi@NanoPC-T6:~/dev_ws$ ros2 param
usage: ros2 param [-h] Call `ros2 param <command> -h` for more detailed usage. ...

Various param related sub-commands

options:
  -h, --help            show this help message and exit

Commands:
  delete    Delete parameter
  describe  Show descriptive information about declared parameters
  dump      Show all of the parameters of a node in a YAML file format
  get       Get parameter
  list      Output a list of available parameters
  load      Load parameter file for a node
  set       Set parameter

  Call `ros2 param <command> -h` for more detailed usage.
2.4.1 查看参数列表
pi@NanoPC-T6:~/dev_ws$ ros2 param list
/param_object_detect:
  red_h_lower
  red_h_upper
  use_sim_time
/usb_cam:
  auto_white_balance
  autoexposure
  autofocus
  ......

可以看到我们实现的/param_object_detect节点有三个参数,其中:

  • red_h_lower: 红色识别的最小色相阈值 (Hue lower);
  • red_h_upper:红色识别的最大色相阈值 (Hue upper);
  • use_sim_time :是否使用仿真时间。

red_h_lowerred_h_upper我们在代码里有定义,而use_sim_timeROS 2节点的一个内置默认参数,所有节点都会自动拥有这个参数,即使没有在代码中声明它。

2.4.2 获取参数值
pi@NanoPC-T6:~/dev_ws$ ros2 param get /param_object_detect red_h_upper
Integer value is: 180
2.4.3 查询参数信息
pi@NanoPC-T6:~/dev_ws$ ros2 param describe /param_object_detect red_h_lower
Parameter name: red_h_lower
  Type: integer
  Constraints:
pi@NanoPC-T6:~/dev_ws$ ros2 param describe /param_object_detect red_h_upper
Parameter name: red_h_upper
  Type: integer
  Constraints:
2.4.4 设置参数值
pi@NanoPC-T6:~/dev_ws$ ros2 param set param_object_detect red_h_upper 180	

参考文章

[1] 古月居ROS2入门教程学习笔记

posted @ 2025-12-15 21:51  大奥特曼打小怪兽  阅读(85)  评论(0)    收藏  举报
如果有任何技术小问题,欢迎大家交流沟通,共同进步