如何使用ROS-SMACH FSM正确传递(可变)对象

时间:2018-01-05 21:13:48

标签: python multithreading serialization ros mutable

我一直在努力解决这个问题。我的问题非常具体,所以请不要使用" 发布ROS教程页面的链接!注意: "段落显示如何传递可变对象(除非你告诉我一些我错过的东西)。我想知道是否有人能够在SMACH状态中来回正确传递可变对象,而不会遇到任何错误。

我写了一个特别简单而无用的程序来解释我试图做的事情。我可以发布这个例子的代码(不幸的是,对于那些以前使用过SMACH的人来说,这并不奇怪,这是一段很长的代码)。所以现在我将尽力解释它,并在我的例子的图像中加入[link]。我创建了两个python脚本。每个脚本包含该类的单个类和对象(使用一些基本方法)。我在每个脚本中创建一个发布者和订阅者,其中一个脚本发送消息(会话),而另一个脚本侦听(听到)消息。最后,讲话者将两个FSM标记为关闭。如果有人想要完整的代码示例,请告诉我......

下面的代码片段显示了smach状态和转换:

# begin sm
with sm:
    smach.StateMachine.add('LOAD', loadFSM(), 
                           transitions={'LOADED':'SENDMSG'})
    smach.StateMachine.add('SENDMSG', startMSG(),
                           transitions={'SENT':'SENDMSG',
                                        'ENDING':'END'})
    smach.StateMachine.add('END', stopFSM(),
                           transitions={'DONE':'complete',
                                        'ERRED':'incomplete'})

下面的代码片段显示了一个smach状态(loadFSM):

class loadFSM(smach.State):
    def __init__(self):
        smach.State.__init__(self, outcomes=['LOADED'],
                            output_keys=['talker_obj'],
                            input_keys=['talker_obj'])
        # Initialise our talker object
        self.talker = Talk()
    def execute(self, userdata):
        rospy.loginfo("talker state: Loading fsm")
        self.talker.init_publish()
        self.talker.init_subscribe()
        userdata.talker_obj = self.talker
        return 'LOADED' 

我收到的错误(使用Ubuntu 14.04,ROS indigo和python 2.7,不太确定,但我相信同样的错误也发生在动力学中)只发生在状态转换期间,当然内省服务器不起作用(不显示状态转换)。错误是;

1。 "线程中的异常sm_introViewer:status_publisher:"

2。 "无法执行转换回调:Traceback(最近一次调用     最后):文件
        " /opt/ros/indigo/lib/python2.7/dist-packages/smach/container.py" ;,
        第175行,在call_transition_cbs cb中(self.userdata,         self.get_active_states(),* args)"

我还需要补充一点,我的简单有限状态机示例实际上已成功运行并完成,即使我的项目的2个较大的FSM也完成了。但是,当FSM在我的项目中有许多状态时,有时我的模拟会失败。如果他们认为这些错误是原因,或者他们知道我没有在状态之间正确传递对象这一事实,那么我想知道任何广泛使用SMACH的人。

先谢谢,

Tiz

1 个答案:

答案 0 :(得分:1)

过去我遇到过类似的问题。如果我没记错的话,userdata只能处理基本类型(int,string,list,dict,...),而不能处理任意对象。 我通过将对象传递给状态类的构造函数而不是使用userdata来解决它,例如:

class myState(smach.State):
    def __init__(self, obj):
        smach.State.__init__(self, outcomes=['foo'], ...)
        self.obj = obj
    ...

然后初始化如下:

obj = SomeClass()
with sm:
    smach.StateMachine.add('MY_STATE', myState(obj), 
                           transitions={'foo':'bar'})

它不是很好,因为它绕过了userdata概念,但它可以工作。