Ros2中goal_handle状态SUCCEED及ACCEPTED及CANCLED在rclpy中的死循环(彻底解决版本)

承接上文,遇到了在动作通信开发中,使用rclpy编写代码进行feedback等操作,但所有逻辑均编写完后,却无法将goal_handle提交为succeed状态,之前的解决方案是更改自己重写的execute()函数名为my_execute()并且在提交SUCCEED前使用一次,将goal_handle的状态更改为EXECUTING状态,具体文章参考下述。

https://blog.csdn.net/m0_56210953/article/details/140221097

但这并非万全之策,眨眼一看确实没啥问题。但是首先,在我的任务进行中,执行结束日志打印之后还会再打印一次任务开始,我认为应该是最后调用execute后重新打开了一个线程,导致任务重新走了一遍,但是又不满足条件,于是仅仅打印了日志,这无伤大雅,但在逻辑上是不对的。

其次项目的业务逻辑是包括了中间取消的情况的,也就是强制ctrl+c取消任务,当我使用ctrl+c取消了客,户端的请求时,服务端依旧在为乌龟导航,且服务端也没有提示任务取消,经过代码检查之后发现并非是我代码的问题,熟悉的,当我使用了源码实现的函数来进行状态变更为CANCLED的时候,也出现了以下的两个错误

[exer04_action_server-2] rclpy._rclpy_pybind11.RCLError: Failed to update goal state: goal_handle attempted invalid transition from state ABORTED with event SUCCEED, at ./src/rcl_action/goal_handle.c:95

[exer04_action_server-2] rclpy._rclpy_pybind11.RCLError: Failed to update goal state: goal_handle attempted invalid transition from state ACCEPTEDwith event CANCLED, at ./src/rcl_action/goal_handle.c:95

还是状态变更的错误,但是Python并没有ACCEPT_AND_EXECUTE状态,本来一行代码能实现的问题扯了这么远,于是我尝试在子线程中变更我的回调函数为源码回调函数的参数,但是均失败了

# 原来的
Thread(target=self.my_execute, args=(goal_handle,)).start()
# 变更后的1(出错)
Thread(target=goal.execute, args=(self.my_execute,)).start()
# 变更后的2(出错)
Thread(target=goal.execute(self.goal_handle)).start()

看来不实现源码的功能是不行了,于是我掉头细细读了一下源码,发现其实是可以实现的,具体做法就是将状态转换的部分源码粘贴到自己的代码中,但是要注意的是不能粘贴到执行部分,一定是状态转换的部分源码

from rclpy.impl.implementation_singleton import rclpy_implementation as _rclpy

    def my_execute(self, goal_handle):
        # 在自己的执行函数中粘贴状态转换语句
        goal_handle._update_state((_rclpy.GoalEvent.EXECUTE))

这样其实之前更改的最后的goal_handle.execute()也可以删掉了,毕竟已经把状态在之前就进行了变更。这样问题就解决了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值