鱼香ROS社区
    • 版块
    • 最新
    • 未解决
    • 已解决
    • 群组
    • 注册
    • 登录
    紧急通知:禁止一切关于政治&VPN翻墙等话题,发现相关帖子会立马删除封号
    提问前必看的发帖注意事项: 社区问答规则(小鱼个人)更新 | 高质量帖子发布指南

    ROS2驱动开发中的参数处理技巧

    已定时 已固定 已锁定 已移动
    文档资料
    ros2 摄像头 驱动 yolo
    3
    3
    1.0k
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • 小鱼小
      小鱼 技术大佬
      最后由 小鱼 编辑

      ROS2驱动开发中的参数处理技巧

      上周末在忙着给FishBot的配套摄像头写ROS2驱动,外加上周加班导致身体不舒服就没发文,今天分享下小鱼在写配套驱动中,关于参数处理的一些心得和技巧。

      34c2e2d6-d6f5-4ca5-897d-0d428a13610e-image.png

      首介绍下这个无线摄像头。它基于ESP32系列的无线模块,小鱼重新设计了一块底板,并编写了新的固件。这样就可以利用配置助手来轻松完成固件的烧录和配置。当然,仅仅有硬件是不够的,为了能够在ROS2中获取图像,并结合小鱼之前开发的yolov5_ros2开源库进行目标检测等任务,小鱼还为这个摄像头编写了一个配套的ROS2驱动。

      这个摄像头拥有众多可调整的参数,如画面大小、前照灯亮度、上下反转和左右镜像等。在ROS2中,我选择了通过节点参数来进行这些参数的封装。但这里存在一个问题:每个参数都有其特定的取值范围。例如,亮度的范围是0-255,图像质量的范围是4-63,而上下反转这个参数则只能是0或1。因此,在代码中,我不能仅仅声明这些参数,还需要对它们的取值范围进行限制。

      为了解决这个问题,我编写了一个函数declare_param_with_range,用于声明带有取值范围的参数。下面是这个函数的完整代码:

      from rcl_interfaces.msg import ParameterDescriptor, IntegerRange
      
      class CameraDriverNode:
          # ... 其他类成员和方法 ...
      
          def declare_param_with_range(self, name, value, start, end):
              pd = ParameterDescriptor()
              pd_range = IntegerRange()
              pd_range.from_value = start
              pd_range.to_value = end
              pd_range.step = 1
              pd.integer_range = [pd_range]  # 注意这里需要使用列表
              self.declare_parameter(name, value, pd)
      
          # ... 其他类成员和方法 ...
      

      使用这个函数,我可以为每个参数指定一个合适的范围,并确保用户在设置参数时不会超出这个范围。

      然而,仅仅声明参数并限制其取值范围还不够。当参数的值发生改变时,我们需要能够动态地感知到这个变化,并将这个变化同步到摄像头设备上。为了实现这一功能,我利用了ROS2的参数更新回调机制。

      在ROS2中,我们可以通过add_on_set_parameters_callback方法为节点添加一个参数更新回调函数。当参数的值发生改变时,ROS2会自动调用这个回调函数,并将改变后的参数作为参数传入。下面是参数更新回调的完整代码实现:

      from rcl_interfaces.msg import SetParametersResult, SetParameterResult
      
      class CameraDriverNode:
          # ... 其他类成员和方法 ...
      
          def __init__(self):
              # ... 初始化其他部分 ...
              self.add_on_set_parameters_callback(self.parameter_callback)
      
          def parameter_callback(self, parameters):
              results = []
              for parameter in parameters:
                  try:
                      # 获取参数的新值,并进行相应的处理
                      new_value = parameter.value
                      self.get_logger().info(f'参数 {parameter.name} 设置为:{new_value}')
                      self.sync_param(parameter.name, new_value)
                      # 构造参数设置结果
                      result = SetParameterResult(successful=True)
                  except Exception as e:
                      self.get_logger().error(f'设置参数 {parameter.name} 失败:{e}')
                      result = SetParameterResult(successful=False, reason=str(e))
                  results.append(result)
              # 返回所有参数的设置结果
              return SetParametersResult(successful=True, results=results)
      
          def sync_param(self, param_name, param_value):
              # 这里应该实现将参数值同步到摄像头设备的逻辑
              # 例如,发送命令到摄像头以设置相应的参数值
              pass  # 这里留空,需要根据具体硬件接口实现
      
          # ... 其他类成员和方法 ...
      

      在这个回调函数中,首先遍历了所有改变的参数,获取了它们的新值,并执行了相应的处理逻辑(例如,调用sync_param函数将新值同步到摄像头设备上)。然后为每个参数构造了一个SetParameterResult消息,表示该参数的设置是否成功,并将这些结果添加到results列表中。最后返回了一个SetParametersResult消息,其中包含了所有参数的设置结果。

      新书配套视频:https://www.bilibili.com/video/BV1GW42197Ck/

      2 1 2 条回复 最后回复 回复 引用 0
      • 2
        ICE @小鱼
        最后由 编辑

        @小鱼 小鱼你好,可以出个C++版本的吗

        1 条回复 最后回复 回复 引用 0
        • 1
          风月 @小鱼
          最后由 编辑

          @小鱼 你好,小鱼,我想通过这个做一个类似于ros1中动态修改bool值的参数修改,但在ParameterDescriptor()没有填写bool值的属性,是需要通过别的方法去做吗?

          1 条回复 最后回复 回复 引用 0
          • 第一个帖子
            最后一个帖子
          皖ICP备16016415号-7
          Powered by NodeBB | 鱼香ROS