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

    关于《ROS 2机器人开发》中修改参数的求助

    已定时 已固定 已锁定 已移动
    ROS2机器人开发:从入门到实践
    修改参数的求助帖 《ros 2机器人开发》
    2
    2
    20
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • 5
      565712988
      最后由 编辑

      《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()
      
      小鱼小 1 条回复 最后回复 回复 引用 0
      • 小鱼小
        小鱼 技术大佬 @565712988
        最后由 编辑

        @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}')
        

        需要特别注意的三个关键点:

        1. 类型匹配:ROS2参数类型必须严格匹配,PARAMETER_INTEGER对应integer_value字段,PARAMETER_STRING对应string_value字段

        2. 参数声明:确保服务端节点已正确声明该参数(类似以下声明代码):

        self.declare_parameter('upsample_times', 1)  # 默认值
        
        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]
        

        如果仍然失败,请检查:

        1. 参数服务是否正常运行:ros2 service list | grep set_parameters
        2. 参数名称是否匹配:ros2 param list /face_detect_node
        3. 参数类型是否正确:ros2 param get /face_detect_node upsample_times

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

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