How to pass mutable input and output keys in SMACH
Hello,
I am currently using the melodic distro. Here are my ROS env vars:
ROS_ETC_DIR=/opt/ros/melodic/etc/ros
ROS_ROOT=/opt/ros/melodic/share/ros
ROS_MASTER_URI=http://localhost:11311
ROS_VERSION=1
ROS_PYTHON_VERSION=2
ROS_PACKAGE_PATH=/opt/ros/melodic/share
ROSLISP_PACKAGE_DIRECTORIES=
ROS_DISTRO=melodic
My question is more conceptual than, "I need help fixing this error," so my environment information may not be completely relevant.
I am having a hard time finding any documentation on passing mutable user data between different state machines. In fact, the only real documentation I can find for SMACH is (understandably) the ros wiki page. I have linked the only page I can find on user data. On this topic, it says
If you require a mutable input object, you must specify the same key in both input_keys and output_keys
Okay, but what if each state machine accepts and outputs a defined object that I defined that is not a string, int, etc (immutable objects)? What if, say, state machine FOO expects some Foo() object, and send a Bar() object to state machine BAR? Is there any documentation (examples preferred) on how to do that?
So, instead of something like this:
class Foo(smach.State):
def __init__(self):
smach.State.__init__(self,
outcomes=['outcome1','outcome2'],
input_keys=['foo_counter_in'],
output_keys=['foo_counter_out'])
def execute(self, userdata):
rospy.loginfo('Executing state FOO')
if userdata.foo_counter_in < 3:
userdata.foo_counter_out = userdata.foo_counter_in + 1
return 'outcome1'
else:
return 'outcome2'
# define state Bar
class Bar(smach.State):
def __init__(self):
smach.State.__init__(self,
outcomes=['outcome1'],
input_keys=['bar_counter_in'])
def execute(self, userdata):
rospy.loginfo('Executing state BAR')
rospy.loginfo('Counter = %f'%userdata.bar_counter_in)
return 'outcome1'
def main():
rospy.init_node('smach_example_state_machine')
# Create a SMACH state machine
sm = smach.StateMachine(outcomes=['outcome4'])
sm.userdata.sm_counter = 0
# Open the container
with sm:
# Add states to the container
smach.StateMachine.add('FOO', Foo(),
transitions={'outcome1':'BAR',
'outcome2':'outcome4'},
remapping={'foo_counter_in':'sm_counter',
'foo_counter_out':'sm_counter'})
smach.StateMachine.add('BAR', Bar(),
transitions={'outcome1':'FOO'},
remapping={'bar_counter_in':'sm_counter'})
# Execute SMACH plan
outcome = sm.execute()
if __name__ == '__main__':
main()
I would like to have something like this (but apparently it won't work):
class Foo(smach.State):
def __init__(self):
smach.State.__init__(self,
outcomes=['outcome1','outcome2'],
input_keys=['foo_in'],
output_keys=['foo_out'])
def execute(self, userdata):
rospy.loginfo('Executing state FOO')
userdata.foo_out = BarObj()
return 'outcome1'
# define state Bar
class Bar(smach.State):
def __init__(self):
smach.State.__init__(self,
outcomes=['outcome1'],
input_keys=['bar_in'],
output_keys=['bar_out'])
def execute(self, userdata):
userdata.bar_out = SomethingElse()
return 'outcome1'
def main():
rospy.init_node('smach_example_state_machine')
# Create a SMACH state machine
sm = smach.StateMachine(outcomes=['outcome4'])
sm.userdata.sm_input = FooObj()
# Open the container
with sm:
# Add states to the container
smach.StateMachine.add('FOO', Foo(),
transitions={'outcome1':'BAR',
'outcome2':'outcome4'},
remapping={'foo_in':'sm_input',
'foo_out':'foo_output'})
smach.StateMachine.add('BAR', Bar(),
transitions={'outcome1':'FOO'},
remapping={'bar_in':'foo_output'
'bar_out' : 'sm_out'})
# Execute SMACH plan
outcome = sm.execute()
if __name__ == '__main__':
main()
What I want to happen here is that the StateMachine SM
that has two state machines, Foo
and Bar
, should have input keys ...
mutable or immutable?
apparently, or are you getting errors? If so, please share them.
Sorry, mutably*