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

    ros2 humble python调用ActionServer自定义goal_callback报错

    已定时 已固定 已锁定 已移动 未解决
    综合问题
    humble actionserver
    3
    4
    247
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • L
      luminuo
      最后由 编辑

      背景:

      ros2 humble python调用ActionServer自定义goal_callback报错

      问题描述:

      自定义ActionServer内goal_callback,报错:AttributeError: 'Nav_Goal' object has no attribute 'request';打印goal_handle发现它的类型是base_interfaces_demo.action._nav.Nav_Goal,而不是rclpy.action.server.ServerGoalHandle

      具体细节和上下文:

      接口Nav.action

      float32 goal_x
      float32 goal_y
      float32 goal_theta
      ---
      float32 turtle_x
      float32 turtle_y
      float32 turtle_theta
      ---
      float32 distance
      

      服务端

      from rclpy.action import ActionServer
      self.server = ActionServer(
                  self,
                  Nav,
                  'nav',
                  self.execute_callback,
                  goal_callback=self.goal_callback,
                  cancel_callback=self.cancel_callback
              )
      
      def goal_callback(self, goal_handle):
              self.get_logger().info("*********%s"%type(goal_handle))
              # 访问目标数据
              goal = goal_handle.request
      
              # 检查目标的合法性
              if (goal.goal_x < 0 or goal.goal_x > 11.08 or
                  goal.goal_y < 0 or goal.goal_y > 11.08):
                  goal_handle.canceled()  # 取消目标
                  return None  # 返回 None 表示没有接受目标
      
              # 目标合法,接受目标
              goal_handle.accept()
              return goal_handle  # 返回 goal_handle 以便进一步处理
      

      报错信息

      [exer03_action_server-2] [INFO] [1723443526.653815246] [exer03_action_server_node_py]: *********<class 'base_interfaces_demo.action._nav.Nav_Goal'>
      [exer03_action_server-2] Traceback (most recent call last):
      [exer03_action_server-2]   File "/home/ws01_plumbing/install/py07_exercise/lib/py07_exercise/exer03_action_server", line 33, in <module>
      [exer03_action_server-2]     sys.exit(load_entry_point('py07-exercise==0.0.0', 'console_scripts', 'exer03_action_server')())
      [exer03_action_server-2]   File "/home/ws01_plumbing/install/py07_exercise/lib/python3.10/site-packages/py07_exercise/exer03_action_server.py", line 94, in main
      [exer03_action_server-2]     rclpy.spin(Exer03ActionServer())
      [exer03_action_server-2]   File "/opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/__init__.py", line 222, in spin
      [exer03_action_server-2]     executor.spin_once()
      [exer03_action_server-2]   File "/opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/executors.py", line 739, in spin_once
      [exer03_action_server-2]     self._spin_once_impl(timeout_sec)
      [exer03_action_server-2]   File "/opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/executors.py", line 736, in _spin_once_impl
      [exer03_action_server-2]     raise handler.exception()
      [exer03_action_server-2]   File "/opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/task.py", line 239, in __call__
      [exer03_action_server-2]     self._handler.send(None)
      [exer03_action_server-2]   File "/opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/executors.py", line 437, in handler
      [exer03_action_server-2]     await call_coroutine(entity, arg)
      [exer03_action_server-2]   File "/opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/executors.py", line 403, in _execute_waitable
      [exer03_action_server-2]     await waitable.execute(data)
      [exer03_action_server-2]   File "/opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/action/server.py", line 492, in execute
      [exer03_action_server-2]     await self._execute_goal_request(taken_data['goal'])
      [exer03_action_server-2]   File "/opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/action/server.py", line 280, in _execute_goal_request
      [exer03_action_server-2]     response = await await_or_execute(self._goal_callback, goal_request.goal)
      [exer03_action_server-2]   File "/opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/executors.py", line 107, in await_or_execute
      [exer03_action_server-2]     return callback(*args)
      [exer03_action_server-2]   File "/home/ws01_plumbing/install/py07_exercise/lib/python3.10/site-packages/py07_exercise/exer03_action_server.py", line 29, in goal_callback
      [exer03_action_server-2]     goal = goal_handle.request
      [exer03_action_server-2] AttributeError: 'Nav_Goal' object has no attribute 'request'
      [ERROR] [exer03_action_server-2]: process has died [pid 16798, exit code 1, cmd '/home/ws01_plumbing/install/py07_exercise/lib/py07_exercise/exer03_action_server --ros-args'].
      
      小鱼小 1 条回复 最后回复 回复 引用 0
      • 小伊小
        机器人小伊
        最后由 编辑

        在 ROS 2 的 rclpy 框架中,当你定义一个 Action Server 的 goal_callback 时,你需要正确地处理传入的参数。在你的代码中,goal_callback 被错误地期望接收一个 ServerGoalHandle 对象,但实际上在 ROS 2 的较新版本中(包括 Humble),goal_callback 直接接收的是 Action 的目标(Goal)对象,而不是 ServerGoalHandle。

        解决方案

        你需要修改 goal_callback 以直接接收 Nav_Goal 类型的对象,而不是 ServerGoalHandle。同时,你需要从 goal_handle 中获取 goal 的方式需要改变,因为你现在直接处理的就是 goal 对象。

        修改后的 goal_callback 应该像这样:

        def goal_callback(self, goal):
            self.get_logger().info("Received goal: x={}, y={}, theta={}".format(goal.goal_x, goal.goal_y, goal.goal_theta))
        
            # 检查目标的合法性
            if (goal.goal_x < 0 or goal.goal_x > 11.08 or
                goal.goal_y < 0 or goal.goal_y > 11.08):
                # 这里你不需要直接调用 goal_handle.canceled(),因为在这个回调中没有 goal_handle
                # 你需要在 execute_callback 中处理取消逻辑
                return rclpy.action.GoalResponse.REJECT
        
            # 目标合法,返回 ACCEPT 表示接受目标
            return rclpy.action.GoalResponse.ACCEPT
        

        注意:

        1. goal_callback 现在直接接收 goal 对象。
        2. goal_callback 需要返回一个 GoalResponse,而不是执行 goal_handle.accept() 或 goal_handle.canceled()。这是因为 goal_callback 是在决定是否接受或拒绝目标时调用的,而实际的处理(如接受或取消)将在 execute_callback 中进行。

        完整的 Action Server 示例

        这里是一个简化的 Action Server 示例,展示如何设置 goal_callback 和 execute_callback:

        from rclpy.action import ActionServer, GoalResponse
        from rclpy.node import Node
        from your_package.action import Nav
        
        class NavActionServer(Node):
            def __init__(self):
                super().__init__('nav_action_server')
                self.server = ActionServer(
                    self,
                    Nav,
                    'nav',
                    self.execute_callback,
                    goal_callback=self.goal_callback,
                    cancel_callback=self.cancel_callback
                )
        
            def goal_callback(self, goal):
                # 检查目标合法性
                if (goal.goal_x < 0 or goal.goal_x > 11.08 or
                    goal.goal_y < 0 or goal.goal_y > 11.08):
                    return GoalResponse.REJECT
                return GoalResponse.ACCEPT
        
            def execute_callback(self, goal_handle):
                self.get_logger().info('Executing goal...')
                # 这里是实际执行目标的地方
                # 假设执行成功
                result = Nav.Result()
                result.distance = 10.0  # 假设的距离
                goal_handle.succeed(result)
        
            def cancel_callback(self, goal_handle):
                self.get_logger().info('Goal canceled')
                goal_handle.canceled()
        
        def main(args=None):
            rclpy.init(args=args)
            nav_server = NavActionServer()
            rclpy.spin(nav_server)
            nav_server.destroy_node()
            rclpy.shutdown()
        
        if __name__ == '__main__':
            main()
        

        注意:你需要根据你的具体包名和命名空间调整代码中的 from your_package.action import Nav。


        以上为生成回答,仅供参考~

        我是小伊,已接入ChatGpt,所有回复,仅供参考~

        1 条回复 最后回复 回复 引用 0
        • 小鱼小
          小鱼 技术大佬 @luminuo
          最后由 编辑

          @luminuo 提供下完整代码,看不太懂

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

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

            @小鱼 按上面那个回复解决了,但是要怎么把未解决改成已解决

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