关于《ROS 2机器人开发》中修改参数的求助
-
《ROS 2机器人开发》书中114页通过节点修改参数,书里面讲述的例子是修改的模型这个参数,如果想修改检测次数upsample_times这个参数应该怎么做,我模仿书中修改模型model参数的例子写了但是不行,请教一下应该怎么办?
是不是SetParameters里面的integer_value不是检测次数
new_model_value.integer_value=int(detect_times)这一行应该是有问题,请教应该怎么修改。import rclpy from rclpy.node import Node from chapt4_interfaces.srv import FaceDetector from sensor_msgs.msg import Image import cv2 from cv_bridge import CvBridge from rcl_interfaces.srv import SetParameters from rcl_interfaces.msg import Parameter,ParameterValue,ParameterType import time class FaceDetectorClient(Node): def __init__(self,node_name,image_path): super().__init__(node_name) self.client =self.create_client(FaceDetector,'face_detect') self.bridge=CvBridge() self.image_path=image_path self.image =cv2.imread(self.image_path) def send_request(self): while self.client.wait_for_service(timeout_sec=1) is False: self.get_logger().info('服务端未上线...') request=FaceDetector.Request() request.image=self.bridge.cv2_to_imgmsg(self.image) future=self.client.call_async(request) rclpy.spin_until_future_complete(self,future) response=future.result() self.get_logger().info(f'收到响应:图像共有:{response.number}张脸,耗时{response.use_time}') # self.show_face_location(response) def show_face_location(self,response): for i in range(response.number): top =response.top[i] right=response.right[i] bottom=response.bottom[i] left=response.left[i] cv2.rectangle(self.image,(left,top),(right,bottom),(0,0,255),2) cv2.imshow('人脸检测结果',self.image) cv2.waitKey(0) def call_set_parameter(self,parameters): update_param_client=self.create_client(SetParameters,'/face_detect_node/set_parameters') while update_param_client.wait_for_service(timeout_sec=1) is False: self.get_logger().info('等待参数更新服务端上线...') time.sleep(1.0) request=SetParameters.Request() request.parameters=parameters future=update_param_client.call_async(request) rclpy.spin_until_future_complete(self,future) response=future.result() return response def update_detect_model(self,model_name): param=Parameter() param.name='set_model' new_model_value=ParameterValue() new_model_value.type=ParameterType.PARAMETER_STRING new_model_value.string_value=model_name param.value=new_model_value response=self.call_set_parameter([param]) for result in response.results: if result.successful: self.get_logger().info(f'参数{param.name}设置为{model_name}') else: self.get_logger().info(f'参数设置失败,原因为{result.reason}') def update_detect_times(self,detect_times): param=Parameter() param.name='upsample_times' new_model_value=ParameterValue() new_model_value.type=ParameterType.PARAMETER_STRING new_model_value.integer_value=int(detect_times) param.value=new_model_value response=self.call_set_parameter([param]) for result in response.results: if result.successful: self.get_logger().info(f'参数{param.name}设置为{detect_times}') else: self.get_logger().info(f'参数设置失败,原因为{result.reason}') def main(args=None): rclpy.init(args=args) node=FaceDetectorClient('face_detect_client',image_path='/home/bonoit/Desktop/1.jpg') node.update_detect_model('cnn') node.send_request() node.update_detect_model('hog') node.send_request() detect_times=2 node.update_detect_times(detect_times) node.send_request() rclpy.spin(node) node.destroy_node() rclpy.shutdown()
-
@565712988 您在设置整型参数时存在类型定义错误的问题。根据ROS2参数接口定义,整型参数需要使用PARAMETER_INTEGER类型标识,并通过integer_value字段赋值。请按以下修改:
def update_detect_times(self, detect_times): param = Parameter() param.name = 'upsample_times' new_model_value = ParameterValue() # 修改此处类型定义和赋值方式 new_model_value.type = ParameterType.PARAMETER_INTEGER new_model_value.integer_value = int(detect_times) # 直接赋值整数值 param.value = new_model_value response = self.call_set_parameter([param]) for result in response.results: if result.successful: self.get_logger().info(f'参数{param.name}设置为{detect_times}') else: self.get_logger().info(f'参数设置失败,原因为{result.reason}')
需要特别注意的三个关键点:
-
类型匹配:ROS2参数类型必须严格匹配,PARAMETER_INTEGER对应integer_value字段,PARAMETER_STRING对应string_value字段
-
参数声明:确保服务端节点已正确声明该参数(类似以下声明代码):
self.declare_parameter('upsample_times', 1) # 默认值
- 参数验证:建议在服务端添加参数验证回调函数,方便调试参数设置:
def parameter_callback(parameters): for param in parameters: if param.name == 'upsample_times': if param.type_ != Parameter.Type.INTEGER: raise ValueError('upsample_times must be an integer') return SetParametersResult(successful=True)
修改完成后,启动节点时添加参数调试信息:
ros2 run your_package face_detector --ros-args --log-level debug
当您看到类似以下成功日志时,表示参数设置成功:
[INFO] [参数upsample_times设置为2]
如果仍然失败,请检查:
- 参数服务是否正常运行:
ros2 service list | grep set_parameters
- 参数名称是否匹配:
ros2 param list /face_detect_node
- 参数类型是否正确:
ros2 param get /face_detect_node upsample_times
-