小鱼 ROS 2 新书上线!点击链接查看, 新书配套视频点击链接查看。
提问前必看的发帖注意事项—— 提问前必看!不符合要求的问题拒绝回答!!
社区使用指南—如何添加标签修改密码
ROS2驱动开发中的参数处理技巧
-
ROS2驱动开发中的参数处理技巧
上周末在忙着给FishBot的配套摄像头写ROS2驱动,外加上周加班导致身体不舒服就没发文,今天分享下小鱼在写配套驱动中,关于参数处理的一些心得和技巧。
首介绍下这个无线摄像头。它基于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
消息,其中包含了所有参数的设置结果。 -
@小鱼 小鱼你好,可以出个C++版本的吗