在进行Ros2学习和进行项目的开发途中,准确来说实在动作通信项目的实战中,我给出了以下示例的ActionServer端初始化,并且使用goal_handle进行下一步操作。
self.server = ActionServer(self,Nav,"nav",execute_callback=self.execute,goal_callback=self.handle_goal,cancel_callback=self.handle_cancel,handle_accepted_callback=self.handle_accepted,)
以下是我的Nav.action,简而言之,是我的动作接口,当我在使用goal_handle的goal_x = goal_handle.request.goal_x方法来获取客户端传来的数据时,竟然报错了,而且错误是Nav_Goal没有request这个方法,但是goal_handle明明是ServerGoalHandle类型,且是有request这个方法的,为什么会这样呢?
float32 goal_x
float32 goal_y
float32 goal_theta
---
float32 turtle_x
float32 turtle_y
float32 turtle_theta
---
float32 distance
在经过我查看源码后我发现,在default_goal_callback()函数中给出的是goal_request,在default_cancel_callback()函数中给出的是cancel_request,只有在执行函数过度的default_handle_accepted_callback()中才给出了goal_handle这一类型的指定,所以并不能直接认为这些函数给出的handle是相同的,换言之,将每个函数中的参数都写成goal_handle是不准确的,也不应该这么做。
def default_goal_callback(goal_request):"""Accept all goals."""return GoalResponse.ACCEPTdef default_cancel_callback(cancel_request):"""No cancellations."""return CancelResponse.REJECTdef default_handle_accepted_callback(goal_handle):"""Execute the goal."""goal_handle.execute()
即以下写法不准确,不应全写成goal_handle
def handle_goal(self, goal_handle):passdef handle_cancel(self, goal_handle):passdef handle_accepted(self, goal_handle):passdef execute(self, goal_handle):pass
经过查询和尝试得知:Nav_Goal是一个数据类,通常包含目标动作的请求数据。包含目标的具体字段 goal_x,goal_y,goal_theta等。在处理目标时,Nav_Goal是接收和发送的实际数据。于是通过查看源码发现handle有一个take_data()方法,试了发现Nav_Goal没有这个方法,于是就直接访问其内部的数据,发现可行。
def handle_goal(self, goal_handle):self.get_logger().info(f"请求坐标: ({goal_handle.goal_x:.2f}, {goal_handle.goal_y:.2f}), 航向: {goal_handle.goal_theta:.2f}")if (goal_handle.goal_x < 0or goal_handle.goal_x > 11.1or goal_handle.goal_y < 0or goal_handle.goal_y > 11.1):return GoalResponse.REJECTreturn GoalResponse.ACCEPT
而下方的执行部分,不出所料地肯定是ServerGoalHandle类型,于是继续是用老方法就行了
goal_x = goal_handle.request.goal_xgoal_y = goal_handle.request.goal_y