SMACH中,状态(State)是状态机器组成的重要部分,理解State的原理和实现,对使用SMACH很有帮助,特别是理解
__init__(),execute(),preempt是尤为关键。
__init__():初始化函数,状态初始化时,进行参数的初始化
execute():状态运行时执行的函数
preempt:暂停状态
详细的说明请参考例子:The principle of Passing User Data between States
下面对State类进行解释注释,代码如下:
1 import threading 2 import traceback 3 4 import smach 5 6 __all__ = ['State','CBState'] 7 8 class State(object): 9 """SMACH的状态基类 10 11 SMACH状态和SMACH容器交互的方式有两种。第一种是它的输出标识符outcome。 12 第二种是运行(execute)时,用来读入和输出打用户数据(userdata)。在execute() 13 调用前,需要在构造函数(__init__())中声明outcome和userdata并做相应的校验。 14 """ 15 def __init__(self, outcomes=[], input_keys=[], output_keys=[], io_keys=[]): 16 """状态构造函数 17 @type outcomes:字符串数组 18 @param outcomes: 为此状态定义输出(outcomes). 19 20 @type input_keys: 字符串数组 21 @param input_keys: 在运行时,从外部输入的用户数据keys. 22 23 @type output_keys: 字符串数组 24 @param output_keys: 在运行时,从外部输出的用户数据keys. 25 26 @type io_keys: 字符串数组 27 @param io_keys: 在运行时,从外部输入/输出的用户数据keys. 28 """ 29 # 存储输出结果(outcomes) 30 self._outcomes = set(outcomes) 31 32 # 存储用户数据接口的描述 33 self._input_keys = set(input_keys + io_keys) 34 self._output_keys = set(output_keys + io_keys) 35 36 # 声明暂停的标识符 37 self._preempt_requested = False 38 39 ### Meat 40 def execute(self, ud): 41 """Called when executing a state.当执行状态时调用 42 在基类中该函数会抛出异常NotImplementedError. 43 44 @type ud: 用户数据结构体 45 @param ud: 状态在执行时,传递的用户数据 46 """ 47 raise NotImplementedError() 48 49 ### SMACH 接口 API 50 def register_outcomes(self, new_outcomes): 51 """向结果集中添加结果标签.""" 52 self._outcomes = self._outcomes.union(new_outcomes) 53 54 def get_registered_outcomes(self): 55 """获取已经注册打结果集. 56 @rtype: 字符串数组 57 @return: 已经注册打结果字符串的数组. 58 """ 59 return tuple(self._outcomes) 60 61 ### 用户数据API 62 def register_io_keys(self, keys): 63 """向io_keys集合中添加keys. 64 @type keys: 字符串数组 65 @param keys: 输入输出的keys. 66 """ 67 self._input_keys = self._input_keys.union(keys) 68 self._output_keys = self._output_keys.union(keys) 69 70 def register_input_keys(self, keys): 71 """向input_keys集合中添加keys. 72 @type keys: 字符串列表 73 @param keys: 输入的keys. 74 """ 75 self._input_keys = self._input_keys.union(keys) 76 77 def get_registered_input_keys(self): 78 """获得已经注册的input_keys数组.""" 79 return tuple(self._input_keys) 80 81 def register_output_keys(self, keys): 82 """向output_keys集合中添加keys. 83 @type keys: 字符串列表 84 @param keys: 输出的keys. 85 """ 86 self._output_keys = self._output_keys.union(keys) 87 88 def get_registered_output_keys(self): 89 """获得已经注册打output keys的数组.""" 90 return tuple(self._output_keys) 91 92 ### 暂停的接口 93 def request_preempt(self): 94 """设置暂停请求preempt_requested为True,状态机暂停的时候,就需要设置该状态为False,运行时 95 需要设置为True才行,否则运行到该状态就会停止了。 96 """ 97 self._preempt_requested = True 98 99 def service_preempt(self): 100 """设置暂停请求preempt_requested为False""" 101 self._preempt_requested = False 102 103 def recall_preempt(self): 104 """设置暂停请求preempt_requested为False""" 105 self._preempt_requested = False 106 107 def preempt_requested(self): 108 """如果暂停则返回True.""" 109 return self._preempt_requested 110 111 class CBState(State): 112 def __init__(self, cb, cb_args=[], cb_kwargs={}, outcomes=[], input_keys=[], output_keys=[], io_keys=[]): 113 """从一个函数中创建一个状态. 114 115 @type outcomes: 字符串数组 116 @param outcomes: 为该状态定义的outcomes. 117 118 @type input_keys: 字符串数组 119 @param input_keys: 在运行时,从外部输入的用户数据keys. 120 121 @type output_keys: 字符串数组 122 @param output_keys: 在运行时,从外部输出的用户数据keys. 123 124 @type io_keys: 字符串数组 125 @param io_keys: 在运行时,从外部输入/输出的用户数据keys. 126 """ 127 State.__init__(self, outcomes, input_keys, output_keys, io_keys) 128 self._cb = cb 129 self._cb_args = cb_args 130 self._cb_kwargs = cb_kwargs 131 132 if smach.util.has_smach_interface(cb): 133 self._cb_input_keys = cb.get_registered_input_keys() 134 self._cb_output_keys = cb.get_registered_output_keys() 135 self._cb_outcomes = cb.get_registered_outcomes() 136 137 self.register_input_keys(self._cb_input_keys) 138 self.register_output_keys(self._cb_output_keys) 139 self.register_outcomes(self._cb_outcomes) 140 141 def execute(self, ud): 142 return self._cb(ud, *self._cb_args, **self._cb_kwargs)