## page was copied from smach/Tutorials/Concurrence container ## For instruction on writing tutorials ## http://www.ros.org/wiki/WritingTutorials #################################### ##FILL ME IN #################################### ## for a custom note with links: ## note = ## for the canned note of "This tutorial assumes that you have completed the previous tutorials:" just add the links ## note.0= ## descriptive title for the tutorial ## title = Concurrence container ## multi-line description to be displayed in search ## description = This tutorial teaches you how to use the Concurrence container. ## the next tutorial description (optional) ## next = ## links to next tutorial (optional) ## next.0.link=[[smach/Tutorials/Sequence container|Sequence container]] ## next.1.link= ## what level user is this tutorial for ## level= BeginnerCategory ## keywords = #################################### <<IncludeCSTemplate(TutorialCSHeaderTemplate)>> <<TableOfContents(4)>> {{{#!python from smach import Concurrence }}} == Specify concurrence outcomes == === Concurrence Outcome Map === The outcome map of a SMACH concurrence specifies the policy for determining the outcome of the concurrence based on the outcomes of its children. Specifically, the map is a dictionary where the keys are potential outcomes of the concurrence, and the values are dictionaries mapping child labels onto child outcomes. Once all the states in the concurrence have terminated, if '''one''' of these child-outcome mappings is satisfied, the concurrence will return its associated outcome. If '''none''' of the mappings are satisfied, the concurrence will return its default outcome. {{{ #!python cc = Concurrence(outcomes = ['outcome1', 'outcome2'], default_outcome = 'outcome1', input_keys = ['sm_input'], output_keys = ['sm_output'], outcome_map = {'succeeded':{'FOO':'succeeded', 'BAR':'outcome2'}, 'outcome3':{'FOO':'outcome2'}}) with cc: Concurrence.add('FOO', Foo()) Concurrence.add('BAR', Bar()) }}} The example above specifies the following policy: * When 'FOO' has outcome 'succeeded' and 'BAR' has outcome 'outcome2', the state machine will exit with outcome 'succeeded'. * When 'FOO' has outcome 'outcome2', the state machine will exit with outcome 'outcome3', independent of the outcome of state BAR. === Callbacks === If you want full control over a concurrence state machine, you can use the callbacks it provides, the child_termination_cb and the outcome_cb: {{{ #!python # gets called when ANY child state terminates def child_term_cb(outcome_map): # terminate all running states if FOO finished with outcome 'outcome3' if outcome_map['FOO'] == 'outcome3': return True # terminate all running states if BAR finished if outcome_map['BAR']: return True # in all other case, just keep running, don't terminate anything return False # gets called when ALL child states are terminated def out_cb(outcome_map): if outcome_map['FOO'] == 'succeeded': return 'outcome1' else: return 'outcome2' # creating the concurrence state machine sm = Concurrence(outcomes=['outcome1', 'outcome2'], default_outcome='outcome1', input_keys=['sm_input'], output_keys=['sm_output'], child_termination_cb = child_term_cb, outcome_cb = out_cb) with sm: Concurrence.add('FOO', Foo(), remapping={'foo_in':'input'}) Concurrence.add('BAR', Bar(), remapping={'bar_out':'bar_out'}) }}} * The child_termination_cb is called every time one of the child states terminates. In the callback function you can decide if the state machine should keep running (return False), or if it should preempt all remaining running states (return True). * The outcome_cb is called once when the last child state terminates. This callback returns the outcome of the concurrence state machine. ## AUTOGENERATED DO NOT DELETE ## TutorialCategory ## FILL IN THE STACK TUTORIAL CATEGORY HERE ## SMACHContainerCategory