James Bryant

【转载】actionlib的身世之谜

0
阅读(1299)

一、服务端描述

1)goal是在ActionClient端启动的(client会发送sendgoal嘛),一旦ActionServer接收到goal请求,它就会为这个goal创建一个状态机来追踪goal的状态转换,重复三遍,状态机是跟踪goal的不是跟踪ActionServer的:

zou是这个状态转换图,下面来细说这些个状态:

2)服务端状态

  • 这些状态的转换大多是服务的实施者触发的(这么生硬的翻译,其实就是服务的程序下同),用小一串命令:
    • setAccepted- 检查到有goal之后,决定开始处理它

    • setRejected- 检察到goal后,决定不去处理它,因为它是个无效请求(溢出,资源不可用,无效等)

    • setSucceeded- 告知goal被正确执行

    • setAborted- 告知goal在处理时遇到了问题不得不被终止了

    • setCanceled- 告知因cancle请求,goal不再被执行了

    action client也能异步触发状态转换:
    • CancelRequest: 客户端通知action server它想要server停止处理这个goal服务端状态

服务端状态
中间状态

(前面说了,simple的状态有三个,就是等待执行挂起)

  • Pending- goal还没有被ActionServer处理

  • Active- goal正在被AS处理

  • Recalling- goal没有被处理并且从客户端已发送取消它的命令,但AS还不确定goal已经被取消了(时差导致的?)

  • Preempting- goal正被处理呢,从AC端收到了取消请求,但AS还不确定goal已经被取消了

终点状态
  • Rejected- AC没有发cancle请求,goal被AS不处理直接拒绝了The goal was rejected by the action server without being processed and without a request from the action client to cancel

  • Succeeded- goal被AS成功实现 was achieved successfully by the action server

  • Aborted- goal被AS终止没有AC的cancle请求

  • Recalled- 在AS开始执行之前这个goal被另一个goal或者cancle请求取消了

  • Preempted- 处理中的goal被另一个goal或者AC的取消请求给取消了

并发问题

setAccepted-CancelRequestvsCancelRequest-setAccepted:

直接的说就是AS能在收到CR之后仍然能把goal给SA。这是因为执行CR的异步竞争机制,那是,因为除了server之外的其他代码触发了状态转换,server不能确定现在到底是在[PENDING]还是[RECALLING]状态。


二、客户端描述

1)客户端状态机

actionlib中,认为server的状态机是主机,client的状态机是从机/耦合机,它在追随主机的状态。

2)客户端转换

服务端触发转换

  • Reported [State]: 因为client在追随主机状态,很多状态的转换都是通知自己状态转换后触发client的状态转换

  • Receive Result Message: 这种状态,server给client发送result message。接收到result就意味着追踪这个goal 结束了

客户端触发转换

  • Cancel Goal: 请求server停止处理这个goal

"略过" 状态

  • 鉴于ROS是基于传输层协议,非常有可能client并不能收到所有server状态的更新。因此,我们允许客户端状态机“略过”server的触发状态
    • Example: 客户端在[WAITING FOR GOAL ACK]状态,收到[PREEMPTED]server的更新状态, 客户端状态可以跳过[ACTIVE]状态,直接转移到[WAITING FOR RESULT]状态

  • 因为多AC可以连接单一AS,因此允许一个client取消另一个client的goal。因此当收到server的[RECALLING]状态时允许client从[PENDING]转移到[RECALLING]状态


三、Action接口和传输协议

Action客户端和服务端通过预定义的action协议交流。这个action协议依赖ROS topics在一个ROS规定的命名空间中传递消息

  • ROS Messages
    • goal- 用于给目标发送新的服务

    • cancel- 用来给服务发送取消命令

    • status- 用来通知当前状态下系统中所有goal的状态

    • feedback- 用来给客户端定期定期发送辅助信息

    • result- 用来在goal完成后给发送客户端一次信息

1)数据组合和goal ID

  goal ID是字符串类型字段

------明天写*^_^*


四、协议

1)Simple Action Client

一般,高层的应用和可执行文件并不关心goal是否被处理或是否完整。他们才不关心中间状态呢。Simple Action Client的原始客户端状态机只有三个状态:Pending, Active, & Done

1.1)客户端状态模糊

  单独客户端状态是不够确定SimpleClient状态的,但这很容易通过观察客户端状态转移来解决.如果客户端状态转移并未使SC状态转移.SC状态就不更新.

  栗子:如果客户端从RECALLING转移到WAITING FOR RESULT,SC的状态仍然在PENDING.

1.2)多goal协议

  Simple Action Client一次只追踪一个goal。当用户使用simple client发送一个goal时, 它会取消前一个goal的所有回调并使停止追踪它的状态,注意它并不是取消前一个goal!

1.3)线程模式(C++)

  基于简单的action客户端结构,用户决定是否要自旋另一个线程

  • 不要额外线程(推荐)

    • 客户端所有用户都注册到全局回调队列
    • 用户的action回调是从ros::spin中回调的,因此,阻断用户的动作回调会组织全局回调队列被服务端处理
  • 自旋一个线程

    • action client的所有订阅者都会注册到一个回调队列。这个队列与全局回调队列分离,这个队列服务于自旋线程
    • 用户的action回调队列被称为spun up线程,虽然堵在action回调不会阻止其他ROS消息被服务,但仍不推荐这样用,因为这个action的status feedback和反馈都不能被服务
    • 一个(可能是唯一一个)自旋一个额外线程的有点是用户可以不用在app中调用ros::spin()

2)Simple Action Server

  很多action server遵循同样的模式,就是在同一时间只能有一个标签是活跃的,并且新的goal可以抢占先前的goal。设计action server包装的simple action server是为了强制这个简单协议去处理goal

  当从action client接收到一个新goal时,simple action server将这个goal移到等待槽。如果这个goal已经占据了等待槽,sipmle action server 将这个目标设置为cancle,并用线上到来的其他目标取代它。

Baidu
map