在进行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.ACCEPT
def default_cancel_callback(cancel_request):
"""No cancellations."""
return CancelResponse.REJECT
def default_handle_accepted_callback(goal_handle):
"""Execute the goal."""
goal_handle.execute()
即以下写法不准确,不应全写成goal_handle
def handle_goal(self, goal_handle):
pass
def handle_cancel(self, goal_handle):
pass
def handle_accepted(self, goal_handle):
pass
def 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 < 0
or goal_handle.goal_x > 11.1
or goal_handle.goal_y < 0
or goal_handle.goal_y > 11.1
):
return GoalResponse.REJECT
return GoalResponse.ACCEPT
而下方的执行部分,不出所料地肯定是ServerGoalHandle类型,于是继续是用老方法就行了
goal_x = goal_handle.request.goal_x
goal_y = goal_handle.request.goal_y