From a9393e370a39b38bbc9d0c01df5bc9c201ad1e40 Mon Sep 17 00:00:00 2001
From: "Isaac I.Y. Saito" <130s@2000.jukuin.keio.ac.jp>
Date: Tue, 6 Jun 2017 16:42:23 -0700
Subject: [PATCH 1/5] Move smach_tutorials (from
https://github.com/eacousineau/executive_smach_tutorials.git). Catkinized.
According to the repo that currently hosts `executive_smach_tutorials` mentioned above, which is also referenced in the [tutorial set of SMACH](http://wiki.ros.org/smach/Tutorials), the code was evacuated from https://code.ros.org/svn/ros-pkg/stacks/executive_smach_tutorials/trunk fortunately before the website went unaccessible.
Since `executive_smach` is part of core ROS (hosted under `ros` org https://github.com/ros/executive_smach), I think it makes sense to move this tutorial package to also `ros` org.
The package is also catkinized this time.
---
smach_tutorials/CMakeLists.txt | 9 +
smach_tutorials/action/Test.action | 3 +
smach_tutorials/examples/actionlib2_test.py | 81 +++++++++
smach_tutorials/examples/actionlib_test.py | 82 +++++++++
smach_tutorials/examples/concurrence.py | 75 +++++++++
smach_tutorials/examples/concurrence2.py | 80 +++++++++
smach_tutorials/examples/iterator_tutorial.py | 88 ++++++++++
smach_tutorials/examples/sequence.py | 50 ++++++
smach_tutorials/examples/state_machine.py | 48 ++++++
smach_tutorials/examples/state_machine2.py | 56 +++++++
.../examples/state_machine_nesting.py | 72 ++++++++
.../examples/state_machine_nesting2.py | 80 +++++++++
.../examples/state_machine_simple.py | 56 +++++++
smach_tutorials/examples/user_data.py | 53 ++++++
smach_tutorials/examples/user_data2.py | 66 ++++++++
smach_tutorials/mainpage.dox | 26 +++
smach_tutorials/package.xml | 31 ++++
.../scripts/usecase_01/executive_step_01.py | 42 +++++
.../scripts/usecase_01/executive_step_02.py | 53 ++++++
.../scripts/usecase_01/executive_step_03.py | 59 +++++++
.../scripts/usecase_01/executive_step_04.py | 97 +++++++++++
.../scripts/usecase_01/executive_step_05.py | 107 ++++++++++++
.../scripts/usecase_01/executive_step_06.py | 142 ++++++++++++++++
.../scripts/usecase_01/executive_step_07.py | 156 ++++++++++++++++++
.../scripts/usecase_01/turtle_nodes.launch | 9 +
25 files changed, 1621 insertions(+)
create mode 100644 smach_tutorials/CMakeLists.txt
create mode 100644 smach_tutorials/action/Test.action
create mode 100755 smach_tutorials/examples/actionlib2_test.py
create mode 100755 smach_tutorials/examples/actionlib_test.py
create mode 100755 smach_tutorials/examples/concurrence.py
create mode 100755 smach_tutorials/examples/concurrence2.py
create mode 100755 smach_tutorials/examples/iterator_tutorial.py
create mode 100755 smach_tutorials/examples/sequence.py
create mode 100755 smach_tutorials/examples/state_machine.py
create mode 100755 smach_tutorials/examples/state_machine2.py
create mode 100755 smach_tutorials/examples/state_machine_nesting.py
create mode 100755 smach_tutorials/examples/state_machine_nesting2.py
create mode 100755 smach_tutorials/examples/state_machine_simple.py
create mode 100755 smach_tutorials/examples/user_data.py
create mode 100755 smach_tutorials/examples/user_data2.py
create mode 100644 smach_tutorials/mainpage.dox
create mode 100644 smach_tutorials/package.xml
create mode 100755 smach_tutorials/scripts/usecase_01/executive_step_01.py
create mode 100755 smach_tutorials/scripts/usecase_01/executive_step_02.py
create mode 100755 smach_tutorials/scripts/usecase_01/executive_step_03.py
create mode 100755 smach_tutorials/scripts/usecase_01/executive_step_04.py
create mode 100755 smach_tutorials/scripts/usecase_01/executive_step_05.py
create mode 100755 smach_tutorials/scripts/usecase_01/executive_step_06.py
create mode 100755 smach_tutorials/scripts/usecase_01/executive_step_07.py
create mode 100644 smach_tutorials/scripts/usecase_01/turtle_nodes.launch
diff --git a/smach_tutorials/CMakeLists.txt b/smach_tutorials/CMakeLists.txt
new file mode 100644
index 0000000..2d857e0
--- /dev/null
+++ b/smach_tutorials/CMakeLists.txt
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 2.8.3)
+project(smach_tutorials)
+
+find_package(catkin REQUIRED COMPONENTS actionlib_msgs message_generation)
+
+add_action_files(DIRECTORY action)
+generate_messages(DEPENDENCIES actionlib_msgs)
+
+catkin_package(CATKIN_DEPENDS actionlib_msgs message_runtime)
diff --git a/smach_tutorials/action/Test.action b/smach_tutorials/action/Test.action
new file mode 100644
index 0000000..fb8b0ac
--- /dev/null
+++ b/smach_tutorials/action/Test.action
@@ -0,0 +1,3 @@
+float64 goal
+---
+---
diff --git a/smach_tutorials/examples/actionlib2_test.py b/smach_tutorials/examples/actionlib2_test.py
new file mode 100755
index 0000000..f102bdd
--- /dev/null
+++ b/smach_tutorials/examples/actionlib2_test.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+import smach
+import smach_ros
+
+from smach_tutorials.msg import TestAction, TestGoal
+from actionlib import *
+from actionlib_msgs.msg import *
+
+
+# Create a trivial action server
+class TestServer:
+ def __init__(self,name):
+ self._sas = SimpleActionServer(name,
+ TestAction,
+ execute_cb=self.execute_cb)
+
+ def execute_cb(self, msg):
+ if msg.goal == 0:
+ self._sas.set_succeeded()
+ elif msg.goal == 1:
+ self._sas.set_aborted()
+ elif msg.goal == 2:
+ self._sas.set_preempted()
+
+def main():
+ rospy.init_node('smach_example_actionlib')
+
+ # Start an action server
+ server = TestServer('test_action')
+
+ # Create a SMACH state machine
+ sm0 = smach.StateMachine(outcomes=['succeeded','aborted','preempted'])
+
+ # Open the container
+ with sm0:
+ # Add states to the container
+
+ # Add a simple action state. This will use an empty, default goal
+ # As seen in TestServer above, an empty goal will always return with
+ # GoalStatus.SUCCEEDED, causing this simple action state to return
+ # the outcome 'succeeded'
+ smach.StateMachine.add('GOAL_DEFAULT',
+ smach_ros.SimpleActionState('test_action', TestAction),
+ {'succeeded':'GOAL_STATIC'})
+
+ # Add another simple action state. This will give a goal
+ # that should abort the action state when it is received, so we
+ # map 'aborted' for this state onto 'succeeded' for the state machine.
+ smach.StateMachine.add('GOAL_STATIC',
+ smach_ros.SimpleActionState('test_action', TestAction,
+ goal = TestGoal(goal=1)),
+ {'aborted':'GOAL_CB'})
+
+
+ # Add another simple action state. This will give a goal
+ # that should abort the action state when it is received, so we
+ # map 'aborted' for this state onto 'succeeded' for the state machine.
+ def goal_callback(userdata, default_goal):
+ goal = TestGoal()
+ goal.goal = 2
+ return goal
+
+ smach.StateMachine.add('GOAL_CB',
+ smach_ros.SimpleActionState('test_action', TestAction,
+ goal_cb = goal_callback),
+ {'aborted':'succeeded'})
+
+ # For more examples on how to set goals and process results, see
+ # executive_smach/smach_ros/tests/smach_actionlib.py
+
+ # Execute SMACH plan
+ outcome = sm0.execute()
+
+ rospy.signal_shutdown('All done.')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/examples/actionlib_test.py b/smach_tutorials/examples/actionlib_test.py
new file mode 100755
index 0000000..5378f9b
--- /dev/null
+++ b/smach_tutorials/examples/actionlib_test.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+"""
+Description:
+ Spawn an actionlib action server, then create a state machine that sends
+ some goals to the action server that will automatically succeed or abort.
+ We expect the first goal to succeed, and the second goal to abort, so
+ when the second goal aborts, we map that onto success of the state
+ machine.
+
+Usage:
+ $> ./actionlib.py
+
+Output:
+ [INFO] : State machine starting in initial state 'GOAL_DEFAULT' with userdata:
+ []
+ [WARN] : Still waiting for action server 'test_action' to start... is it running?
+ [INFO] : State machine transitioning 'GOAL_DEFAULT':'succeeded'-->'GOAL_STATIC'
+ [INFO] : State machine terminating 'GOAL_STATIC':'aborted':'succeeded'
+"""
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+import smach
+import smach_ros
+
+from actionlib import *
+from actionlib_msgs.msg import *
+
+# Create a trivial action server
+class TestServer:
+ def __init__(self,name):
+ self._sas = SimpleActionServer(name,
+ TestAction,
+ execute_cb=self.execute_cb)
+
+ def execute_cb(self, msg):
+ if msg.goal == 0:
+ self._sas.set_succeeded()
+ elif msg.goal == 1:
+ self._sas.set_aborted()
+ elif msg.goal == 2:
+ self._sas.set_preempted()
+
+def main():
+ rospy.init_node('smach_example_actionlib')
+
+ # Start an action server
+ server = TestServer('test_action')
+
+ # Create a SMACH state machine
+ sm0 = smach.StateMachine(outcomes=['succeeded','aborted','preempted'])
+
+ # Open the container
+ with sm0:
+ # Add states to the container
+
+ # Add a simple action sttate. This will use an emtpy, default goal
+ # As seen in TestServer above, an empty goal will always return with
+ # GoalStatus.SUCCEEDED, causing this simple action state to return
+ # the outcome 'succeeded'
+ smach.StateMachine.add('GOAL_DEFAULT',
+ smach_ros.SimpleActionState('test_action', TestAction),
+ {'succeeded':'GOAL_STATIC'})
+
+ # Add another simple action state. This will give a goal
+ # that should abort the action state when it is received, so we
+ # map 'aborted' for this state onto 'succeeded' for the state machine.
+ smach.StateMachine.add('GOAL_STATIC',
+ smach_ros.SimpleActionState('test_action', TestAction,
+ goal = TestGoal(goal=1)),
+ {'aborted':'succeeded'})
+
+ # For more examples on how to set goals and process results, see
+ # executive_python/smach/tests/smach_actionlib.py
+
+ # Execute SMACH plan
+ outcome = sm0.execute()
+
+ rospy.signal_shutdown('All done.')
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/examples/concurrence.py b/smach_tutorials/examples/concurrence.py
new file mode 100755
index 0000000..84b0c15
--- /dev/null
+++ b/smach_tutorials/examples/concurrence.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python
+"""
+Description:
+ This creates a concurrence with two states, one state, 'SET', waits three
+ seconds before setting something in userdata, while another state 'GET'
+ blocks while checking for thie userdata key, and only returns once it
+ has been set.
+
+Usage:
+ $> ./concurrence.py
+
+Output:
+ [INFO] 1279226335.169182: Concurrence starting with userdata:
+ []
+ [INFO] : >>> Waiting for data...
+ [INFO] : >>> Waiting for data...
+ [INFO] : >>> Waiting for data...
+ [INFO] : >>> Waiting for data...
+ [INFO] : >>> Waiting for data...
+ [INFO] : >>> Waiting for data...
+ [INFO] : >>> Set data: hello
+ [INFO] : >>> GOT DATA! x = hello
+ [INFO] : Concurrent Outcomes: {'SET': 'set_it', 'GET': 'got_it'}
+"""
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+import smach
+import smach_ros
+
+# Define a state to set some user data
+class Setter(smach.State):
+ def __init__(self, val):
+ smach.State.__init__(self, outcomes = ['set_it'], output_keys = ['x'])
+ self._val = val
+ def execute(self, ud):
+ # Delay a bit to make this clear
+ rospy.sleep(3.0)
+ # Set the data
+ ud.x = self._val
+ rospy.loginfo('>>> Set data: %s' % str(self._val))
+ return 'set_it'
+
+# Define a state to get some user data
+class Getter(smach.State):
+ def __init__(self):
+ smach.State.__init__(self, outcomes = ['got_it'], input_keys = ['x'])
+ def execute(self, ud):
+ # Wait for data to appear
+ while 'x' not in ud:
+ rospy.loginfo('>>> Waiting for data...')
+ rospy.sleep(0.5)
+ rospy.loginfo('>>> GOT DATA! x = '+str(ud.x))
+ return 'got_it'
+
+def main():
+ rospy.init_node('smach_example_concurrence')
+
+ # Create a SMACH state machine
+ cc0 = smach.Concurrence(
+ outcomes=['succeeded', 'aborted'],
+ default_outcome='aborted',
+ outcome_map = {'succeeded':{'SET':'set_it','GET':'got_it'}})
+
+ # Open the container
+ with cc0:
+ # Add states to the container
+ smach.Concurrence.add('SET', Setter(val='hello'))
+ smach.Concurrence.add('GET', Getter())
+
+ # Execute SMACH plan
+ outcome = cc0.execute()
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/examples/concurrence2.py b/smach_tutorials/examples/concurrence2.py
new file mode 100755
index 0000000..d45204e
--- /dev/null
+++ b/smach_tutorials/examples/concurrence2.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+import smach
+import smach_ros
+
+# define state Foo
+class Foo(smach.State):
+ def __init__(self):
+ smach.State.__init__(self, outcomes=['outcome1','outcome2'])
+ self.counter = 0
+
+ def execute(self, userdata):
+ rospy.loginfo('Executing state FOO')
+ if self.counter < 3:
+ self.counter += 1
+ return 'outcome1'
+ else:
+ return 'outcome2'
+
+
+# define state Bar
+class Bar(smach.State):
+ def __init__(self):
+ smach.State.__init__(self, outcomes=['outcome1'])
+
+ def execute(self, userdata):
+ rospy.loginfo('Executing state BAR')
+ return 'outcome1'
+
+
+
+# define state Bas
+class Bas(smach.State):
+ def __init__(self):
+ smach.State.__init__(self, outcomes=['outcome3'])
+
+ def execute(self, userdata):
+ rospy.loginfo('Executing state BAS')
+ return 'outcome3'
+
+
+
+
+def main():
+ rospy.init_node('smach_example_state_machine')
+
+ # Create the top level SMACH state machine
+ sm_top = smach.StateMachine(outcomes=['outcome6'])
+
+ # Open the container
+ with sm_top:
+
+ smach.StateMachine.add('BAS', Bas(),
+ transitions={'outcome3':'CON'})
+
+ # Create the sub SMACH state machine
+ sm_con = smach.Concurrence(outcomes=['outcome4','outcome5'],
+ default_outcome='outcome4',
+ outcome_map={'outcome5':
+ { 'FOO':'outcome2',
+ 'BAR':'outcome1'}})
+
+ # Open the container
+ with sm_con:
+ # Add states to the container
+ smach.Concurrence.add('FOO', Foo())
+ smach.Concurrence.add('BAR', Bar())
+
+ smach.StateMachine.add('CON', sm_con,
+ transitions={'outcome4':'CON',
+ 'outcome5':'outcome6'})
+
+ # Execute SMACH plan
+ outcome = sm_top.execute()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/examples/iterator_tutorial.py b/smach_tutorials/examples/iterator_tutorial.py
new file mode 100755
index 0000000..6b4de06
--- /dev/null
+++ b/smach_tutorials/examples/iterator_tutorial.py
@@ -0,0 +1,88 @@
+#! /usr/bin/env python
+## %Tag(FULLTEXT)%
+
+
+import roslib; roslib.load_manifest('smach')
+roslib.load_manifest('smach_ros')
+import rospy
+
+import smach
+from smach import Iterator, StateMachine, CBState
+from smach_ros import ConditionState, IntrospectionServer
+
+def construct_sm():
+ sm = StateMachine(outcomes = ['succeeded','aborted','preempted'])
+ sm.userdata.nums = range(25, 88, 3)
+ sm.userdata.even_nums = []
+ sm.userdata.odd_nums = []
+ with sm:
+## %Tag(ITERATOR)%
+ tutorial_it = Iterator(outcomes = ['succeeded','preempted','aborted'],
+ input_keys = ['nums', 'even_nums', 'odd_nums'],
+ it = lambda: range(0, len(sm.userdata.nums)),
+ output_keys = ['even_nums', 'odd_nums'],
+ it_label = 'index',
+ exhausted_outcome = 'succeeded')
+## %EndTag(ITERATOR)%
+## %Tag(CONTAINER)%
+ with tutorial_it:
+ container_sm = StateMachine(outcomes = ['succeeded','preempted','aborted','continue'],
+ input_keys = ['nums', 'index', 'even_nums', 'odd_nums'],
+ output_keys = ['even_nums', 'odd_nums'])
+ with container_sm:
+ #test wether even or odd
+ StateMachine.add('EVEN_OR_ODD',
+ ConditionState(cond_cb = lambda ud:ud.nums[ud.index]%2,
+ input_keys=['nums', 'index']),
+ {'true':'ODD',
+ 'false':'EVEN' })
+ #add even state
+ @smach.cb_interface(input_keys=['nums', 'index', 'even_nums'],
+ output_keys=['odd_nums'],
+ outcomes=['succeeded'])
+ def even_cb(ud):
+ ud.even_nums.append(ud.nums[ud.index])
+ return 'succeeded'
+ StateMachine.add('EVEN', CBState(even_cb),
+ {'succeeded':'continue'})
+ #add odd state
+ @smach.cb_interface(input_keys=['nums', 'index', 'odd_nums'],
+ output_keys=['odd_nums'],
+ outcomes=['succeeded'])
+ def odd_cb(ud):
+ ud.odd_nums.append(ud.nums[ud.index])
+ return 'succeeded'
+ StateMachine.add('ODD', CBState(odd_cb),
+ {'succeeded':'continue'})
+## %EndTag(CONTAINER)%
+## %Tag(ADDCONTAINER)%
+ #close container_sm
+ Iterator.set_contained_state('CONTAINER_STATE',
+ container_sm,
+ loop_outcomes=['continue'])
+## %EndTag(ADDCONTAINER)%
+## %Tag(ADDITERATOR)%
+ #close the tutorial_it
+ StateMachine.add('TUTORIAL_IT',tutorial_it,
+ {'succeeded':'succeeded',
+ 'aborted':'aborted'})
+## %EndTag(ADDITERATOR)%
+ return sm
+
+def main():
+ rospy.init_node("iterator_tutorial")
+ sm_iterator = construct_sm()
+
+ # Run state machine introspection server for smach viewer
+ intro_server = IntrospectionServer('iterator_tutorial',sm_iterator,'/ITERATOR_TUTORIAL')
+ intro_server.start()
+
+
+ outcome = sm_iterator.execute()
+
+ rospy.spin()
+ intro_server.stop()
+
+if __name__ == "__main__":
+ main()
+## %EndTag(FULLTEXT)%
diff --git a/smach_tutorials/examples/sequence.py b/smach_tutorials/examples/sequence.py
new file mode 100755
index 0000000..62fc865
--- /dev/null
+++ b/smach_tutorials/examples/sequence.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+"""
+Description:
+ Create a simple 3-state state sequence. A Sequence is a StateMachine
+ that just assumes that states added in some sequence should be
+ executed in the order in which they were added, but only if they
+ return the "connector outcome" given in the Sequence constructor.
+
+Usage:
+ $> ./sequence.py
+
+Output:
+ [INFO] : State machine starting in initial state 'FOO' with userdata:
+ []
+ [INFO] : State machine transitioning 'FOO':'done'-->'BAR'
+ [INFO] : State machine transitioning 'BAR':'done'-->'BAZ'
+ [INFO] : State machine terminating 'BAZ':'done':'succeeded'
+"""
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+import smach
+import smach_ros
+
+class ExampleState(smach.State):
+ def __init__(self):
+ smach.State.__init__(self, outcomes = ['done'])
+ def execute(self, ud):
+ return 'done'
+
+def main():
+ rospy.init_node('smach_example_sequence')
+
+ # Create a SMACH state machine
+ sq = smach.Sequence(
+ outcomes = ['succeeded'],
+ connector_outcome = 'done')
+
+ # Open the container
+ with sq:
+ # Add states to the container
+ smach.Sequence.add('FOO', ExampleState())
+ smach.Sequence.add('BAR', ExampleState())
+ smach.Sequence.add('BAZ', ExampleState(), {'done':'succeeded'})
+
+ # Execute SMACH plan
+ outcome = sq.execute()
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/examples/state_machine.py b/smach_tutorials/examples/state_machine.py
new file mode 100755
index 0000000..81af47b
--- /dev/null
+++ b/smach_tutorials/examples/state_machine.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+"""
+Description:
+ Create a simple 3-state state machine.
+
+Usage:
+ $> ./state_machine.py
+
+Output:
+ [INFO] : State machine starting in initial state 'FOO' with userdata:
+ []
+ [INFO] : State machine transitioning 'FOO':'done'-->'BAR'
+ [INFO] : State machine transitioning 'BAR':'done'-->'BAZ'
+ [INFO] : State machine terminating 'BAZ':'done':'succeeded'
+
+"""
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+import smach
+import smach_ros
+
+class ExampleState(smach.State):
+ def __init__(self):
+ smach.State.__init__(self, outcomes = ['done'])
+ def execute(self, ud):
+ return 'done'
+
+def main():
+ rospy.init_node('smach_example_state_machine')
+
+ # Create a SMACH state machine
+ sm = smach.StateMachine(outcomes=['succeeded','aborted'])
+
+ # Open the container
+ with sm:
+ # Add states to the container
+ smach.StateMachine.add('FOO', ExampleState(), {'done':'BAR'})
+ smach.StateMachine.add('BAR', ExampleState(), {'done':'BAZ'})
+ smach.StateMachine.add('BAZ',
+ ExampleState(),
+ {'done':'succeeded'})
+
+ # Execute SMACH plan
+ outcome = sm.execute()
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/examples/state_machine2.py b/smach_tutorials/examples/state_machine2.py
new file mode 100755
index 0000000..c14d4d7
--- /dev/null
+++ b/smach_tutorials/examples/state_machine2.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+import smach
+import smach_ros
+
+# define state Foo
+class Foo(smach.State):
+ def __init__(self):
+ smach.State.__init__(self, outcomes=['outcome1','outcome2'])
+ self.counter = 0
+
+ def execute(self, userdata):
+ rospy.loginfo('Executing state FOO')
+ if self.counter < 3:
+ self.counter += 1
+ return 'outcome1'
+ else:
+ return 'outcome2'
+
+
+# define state Bar
+class Bar(smach.State):
+ def __init__(self):
+ smach.State.__init__(self, outcomes=['outcome1'])
+
+ def execute(self, userdata):
+ rospy.loginfo('Executing state BAR')
+ return 'outcome1'
+
+
+
+
+
+def main():
+ rospy.init_node('smach_example_state_machine')
+
+ # Create a SMACH state machine
+ sm = smach.StateMachine(outcomes=['outcome4'])
+
+ # Open the container
+ with sm:
+ # Add states to the container
+ smach.StateMachine.add('FOO', Foo(),
+ transitions={'outcome1':'BAR', 'outcome2':'outcome4'})
+ smach.StateMachine.add('BAR', Bar(),
+ transitions={'outcome1':'FOO'})
+
+ # Execute SMACH plan
+ outcome = sm.execute()
+
+
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/examples/state_machine_nesting.py b/smach_tutorials/examples/state_machine_nesting.py
new file mode 100755
index 0000000..6cd92dc
--- /dev/null
+++ b/smach_tutorials/examples/state_machine_nesting.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+"""
+Description:
+ Create one state machine, put a state in it that sets something in the
+ userdata key 'x'. Put another state machine inside of that state machine,
+ tell it to fetch the userdata key 'x'. Put a state that reads 'x' into
+ that nested state machine, and spew some info to rosout.
+
+Usage:
+ $> ./state_machine_nesting.py
+
+Output:
+ [INFO] : State machine starting in initial state 'SET' with userdata:
+ []
+ [INFO] : State machine transitioning 'SET':'set_it'-->'NESTED'
+ [INFO] : State machine starting in initial state 'GET' with userdata:
+ ['x']
+ [INFO] : >>> GOT DATA! x = hello
+ [INFO] : State machine terminating 'GET':'got_it':'done'
+ [INFO] : State machine terminating 'NESTED':'done':'succeeded'
+
+"""
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+import smach
+import smach_ros
+
+# Define a state to set some user data
+class Setter(smach.State):
+ def __init__(self, val):
+ smach.State.__init__(self, outcomes = ['set_it'], output_keys = ['x'])
+ self._val = val
+ def execute(self, ud):
+ # Set the data
+ ud.x = self._val
+ rospy.loginfo('>>> Set data: %s' % str(self._val))
+ return 'set_it'
+
+# Define a state to get some user data
+class Getter(smach.State):
+ def __init__(self):
+ smach.State.__init__(self, outcomes = ['got_it'], input_keys = ['x'])
+ def execute(self, ud):
+ # Wait for data to appear
+ while 'x' not in ud:
+ rospy.loginfo('>>> Waiting for data...')
+ rospy.sleep(0.5)
+ rospy.loginfo('>>> GOT DATA! x = '+str(ud.x))
+ return 'got_it'
+
+def main():
+ rospy.init_node('smach_example_state_machine_nesting')
+
+ # Create a SMACH state machine
+ sm0 = smach.StateMachine(outcomes=['succeeded'])
+
+ # Open the container
+ with sm0:
+ # Add states to the container
+ smach.StateMachine.add('SET', Setter(val='hello'), {'set_it':'NESTED'})
+
+ sm1 = smach.StateMachine(outcomes=['done'], input_keys=['x'])
+ smach.StateMachine.add('NESTED', sm1, {'done':'succeeded'})
+ with sm1:
+ smach.StateMachine.add('GET', Getter(), {'got_it':'done'})
+
+ # Execute SMACH plan
+ outcome = sm0.execute()
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/examples/state_machine_nesting2.py b/smach_tutorials/examples/state_machine_nesting2.py
new file mode 100755
index 0000000..7d64c11
--- /dev/null
+++ b/smach_tutorials/examples/state_machine_nesting2.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+import smach
+import smach_ros
+
+# define state Foo
+class Foo(smach.State):
+ def __init__(self):
+ smach.State.__init__(self, outcomes=['outcome1','outcome2'])
+ self.counter = 0
+
+ def execute(self, userdata):
+ rospy.loginfo('Executing state FOO')
+ if self.counter < 3:
+ self.counter += 1
+ return 'outcome1'
+ else:
+ return 'outcome2'
+
+
+# define state Bar
+class Bar(smach.State):
+ def __init__(self):
+ smach.State.__init__(self, outcomes=['outcome1'])
+
+ def execute(self, userdata):
+ rospy.loginfo('Executing state BAR')
+ return 'outcome1'
+
+
+
+# define state Bas
+class Bas(smach.State):
+ def __init__(self):
+ smach.State.__init__(self, outcomes=['outcome3'])
+
+ def execute(self, userdata):
+ rospy.loginfo('Executing state BAS')
+ return 'outcome3'
+
+
+
+
+def main():
+ rospy.init_node('smach_example_state_machine')
+
+ # Create the top level SMACH state machine
+ sm_top = smach.StateMachine(outcomes=['outcome5'])
+
+ # Open the container
+ with sm_top:
+
+ smach.StateMachine.add('BAS', Bas(),
+ transitions={'outcome3':'SUB'})
+
+ # Create the sub SMACH state machine
+ sm_sub = smach.StateMachine(outcomes=['outcome4'])
+
+ # Open the container
+ with sm_sub:
+
+ # Add states to the container
+ smach.StateMachine.add('FOO', Foo(),
+ transitions={'outcome1':'BAR',
+ 'outcome2':'outcome4'})
+ smach.StateMachine.add('BAR', Bar(),
+ transitions={'outcome1':'FOO'})
+
+ smach.StateMachine.add('SUB', sm_sub,
+ transitions={'outcome4':'outcome5'})
+
+ # Execute SMACH plan
+ outcome = sm_top.execute()
+
+
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/examples/state_machine_simple.py b/smach_tutorials/examples/state_machine_simple.py
new file mode 100755
index 0000000..2d87822
--- /dev/null
+++ b/smach_tutorials/examples/state_machine_simple.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+import smach
+import smach_ros
+
+# define state Foo
+class Foo(smach.State):
+ def __init__(self):
+ smach.State.__init__(self, outcomes=['outcome1','outcome2'])
+ self.counter = 0
+
+ def execute(self, userdata):
+ rospy.loginfo('Executing state FOO')
+ if self.counter < 3:
+ self.counter += 1
+ return 'outcome1'
+ else:
+ return 'outcome2'
+
+
+# define state Bar
+class Bar(smach.State):
+ def __init__(self):
+ smach.State.__init__(self, outcomes=['outcome2'])
+
+ def execute(self, userdata):
+ rospy.loginfo('Executing state BAR')
+ return 'outcome2'
+
+
+
+
+# main
+def main():
+ rospy.init_node('smach_example_state_machine')
+
+ # Create a SMACH state machine
+ sm = smach.StateMachine(outcomes=['outcome4', 'outcome5'])
+
+ # Open the container
+ with sm:
+ # Add states to the container
+ smach.StateMachine.add('FOO', Foo(),
+ transitions={'outcome1':'BAR',
+ 'outcome2':'outcome4'})
+ smach.StateMachine.add('BAR', Bar(),
+ transitions={'outcome2':'FOO'})
+
+ # Execute SMACH plan
+ outcome = sm.execute()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/examples/user_data.py b/smach_tutorials/examples/user_data.py
new file mode 100755
index 0000000..322c29c
--- /dev/null
+++ b/smach_tutorials/examples/user_data.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+"""
+Description:
+ Create a two-state state machine where one state writes to userdata and
+ the other state reads from userdata, and spews a message to rosout.
+
+Usage:
+ $> ./user_data.py
+
+Output:
+ [INFO] : State machine starting in initial state 'SET' with userdata:
+ []
+ [INFO] : State machine transitioning 'SET':'set_it'-->'GET'
+ [INFO] : >>> GOT DATA! x = True
+ [INFO] : State machine terminating 'GET':'got_it':'succeeded'
+"""
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+import smach
+import smach_ros
+
+class Setter(smach.State):
+ def __init__(self):
+ smach.State.__init__(self, outcomes = ['set_it'], output_keys = ['x'])
+ def execute(self, ud):
+ ud.x = True
+ return 'set_it'
+
+class Getter(smach.State):
+ def __init__(self):
+ smach.State.__init__(self, outcomes = ['got_it'], input_keys = ['x'])
+ def execute(self, ud):
+ rospy.loginfo('>>> GOT DATA! x = '+str(ud.x))
+ return 'got_it'
+
+def main():
+ rospy.init_node('smach_example_user_data')
+
+ # Create a SMACH state machine
+ sm = smach.StateMachine(outcomes=['succeeded'])
+
+ # Open the container
+ with sm:
+ # Add states to the container
+ smach.StateMachine.add('SET', Setter(), {'set_it':'GET'})
+ smach.StateMachine.add('GET', Getter(), {'got_it':'succeeded'})
+
+ # Execute SMACH plan
+ outcome = sm.execute()
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/examples/user_data2.py b/smach_tutorials/examples/user_data2.py
new file mode 100755
index 0000000..e61f890
--- /dev/null
+++ b/smach_tutorials/examples/user_data2.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+import smach
+import smach_ros
+
+# define state Foo
+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()
diff --git a/smach_tutorials/mainpage.dox b/smach_tutorials/mainpage.dox
new file mode 100644
index 0000000..4de1a7a
--- /dev/null
+++ b/smach_tutorials/mainpage.dox
@@ -0,0 +1,26 @@
+/**
+\mainpage
+\htmlinclude manifest.html
+
+\b smach_tutorials is ...
+
+
+
+
+\section codeapi Code API
+
+
+
+
+*/
diff --git a/smach_tutorials/package.xml b/smach_tutorials/package.xml
new file mode 100644
index 0000000..3230f5f
--- /dev/null
+++ b/smach_tutorials/package.xml
@@ -0,0 +1,31 @@
+
+ smach_tutorials
+ 0.1.10
+
+ This package contains numerous examples of how to use SMACH.
+ See the examples directory.
+
+ Isaac I. Y. Saito
+ Jonathan Bohren
+ BSD
+
+ http://wiki.ros.org/smach_tutorials
+ https://github.com/ros/common_tutorials
+ https://github.com/ros/common_tutorials/issues
+
+ catkin
+
+ message_generation
+ message_runtime
+ actionlib_msgs
+ actionlib
+ common_msgs
+ message_runtime
+ rospy
+ ros_tutorials
+ smach
+ smach_ros
+ turtlesim
+
+
+
diff --git a/smach_tutorials/scripts/usecase_01/executive_step_01.py b/smach_tutorials/scripts/usecase_01/executive_step_01.py
new file mode 100755
index 0000000..20aaaa6
--- /dev/null
+++ b/smach_tutorials/scripts/usecase_01/executive_step_01.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+"""
+Description:
+
+Usage:
+ $> ./executive_step_01.py
+
+Output:
+ [ERROR] : InvalidTransitionError: State machine failed consistency check:
+ No initial state set.
+
+ Available states: []
+ [ERROR] : Container consistency check failed.
+ [ERROR] : InvalidTransitionError: State machine failed consistency check:
+ No initial state set.
+
+ Available states: []
+ [ERROR] : Container consistency check failed.
+"""
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+import smach
+
+def main():
+ rospy.init_node('smach_usecase_step_01')
+
+ # Create a SMACH state machine
+ sm0 = smach.StateMachine(outcomes=[])
+
+ # Open the container
+ with sm0:
+ pass
+
+ # Execute SMACH tree
+ outcome = sm0.execute()
+
+ # Signal ROS shutdown (kill threads in background)
+ rospy.signal_shutdown('All done.')
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/scripts/usecase_01/executive_step_02.py b/smach_tutorials/scripts/usecase_01/executive_step_02.py
new file mode 100755
index 0000000..c96cab8
--- /dev/null
+++ b/smach_tutorials/scripts/usecase_01/executive_step_02.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+"""
+Description:
+
+Usage:
+ $> roslaunch turtle_nodes.launch
+ $> ./executive_step_02.py
+
+Output:
+ [INFO] : State machine starting in initial state 'RESET' with userdata:
+ []
+ [INFO] : State machine transitioning 'RESET':'succeeded'-->'SPAWN'
+ [INFO] : State machine terminating 'SPAWN':'succeeded':'succeeded'
+
+"""
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+
+import threading
+
+import smach
+from smach import StateMachine, ServiceState, SimpleActionState
+
+import std_srvs.srv
+import turtlesim.srv
+
+def main():
+ rospy.init_node('smach_usecase_step_02')
+
+ # Create a SMACH state machine
+ sm0 = StateMachine(outcomes=['succeeded','aborted','preempted'])
+
+ # Open the container
+ with sm0:
+ # Reset turtlesim
+ StateMachine.add('RESET',
+ ServiceState('reset', std_srvs.srv.Empty),
+ {'succeeded':'SPAWN'})
+
+ # Create a second turtle
+ StateMachine.add('SPAWN',
+ ServiceState('spawn', turtlesim.srv.Spawn,
+ request = turtlesim.srv.SpawnRequest(0.0,0.0,0.0,'turtle2')))
+
+ # Execute SMACH tree
+ outcome = sm0.execute()
+
+ # Signal ROS shutdown (kill threads in background)
+ rospy.signal_shutdown('All done.')
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/scripts/usecase_01/executive_step_03.py b/smach_tutorials/scripts/usecase_01/executive_step_03.py
new file mode 100755
index 0000000..da27185
--- /dev/null
+++ b/smach_tutorials/scripts/usecase_01/executive_step_03.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+"""
+Description:
+
+Usage:
+ $> roslaunch turtle_nodes.launch
+ $> ./executive_step_02.py
+
+Output:
+ [INFO] : State machine starting in initial state 'RESET' with userdata:
+ []
+ [INFO] : State machine transitioning 'RESET':'succeeded'-->'SPAWN'
+ [INFO] : State machine terminating 'SPAWN':'succeeded':'succeeded'
+
+"""
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+
+import threading
+
+import smach
+from smach import StateMachine, ServiceState, SimpleActionState, IntrospectionServer
+
+import std_srvs.srv
+import turtlesim.srv
+
+def main():
+ rospy.init_node('smach_usecase_step_02')
+
+ # Create a SMACH state machine
+ sm0 = StateMachine(outcomes=['succeeded','aborted','preempted'])
+
+ # Open the container
+ with sm0:
+ # Reset turtlesim
+ StateMachine.add('RESET',
+ ServiceState('reset', std_srvs.srv.Empty),
+ {'succeeded':'SPAWN'})
+
+ # Create a second turtle
+ StateMachine.add('SPAWN',
+ ServiceState('spawn', turtlesim.srv.Spawn,
+ request = turtlesim.srv.SpawnRequest(0.0,0.0,0.0,'turtle2')))
+
+ # Attach a SMACH introspection server
+ sis = IntrospectionServer('smach_usecase_01', sm0, '/USE_CASE')
+ sis.start()
+
+ # Execute SMACH tree
+ outcome = sm0.execute()
+
+ # Signal ROS shutdown (kill threads in background)
+ rospy.spin()
+
+ sis.stop()
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/scripts/usecase_01/executive_step_04.py b/smach_tutorials/scripts/usecase_01/executive_step_04.py
new file mode 100755
index 0000000..f6fe6d9
--- /dev/null
+++ b/smach_tutorials/scripts/usecase_01/executive_step_04.py
@@ -0,0 +1,97 @@
+#!/usr/bin/env python
+"""
+Description:
+
+Usage:
+ $> roslaunch turtle_nodes.launch
+ $> ./executive_step_04.py
+
+Output:
+ [INFO] : State machine starting in initial state 'RESET' with userdata:
+ []
+ [INFO] : State machine transitioning 'RESET':'succeeded'-->'SPAWN'
+ [INFO] : State machine transitioning 'SPAWN':'succeeded'-->'TELEPORT1'
+ [INFO] : State machine transitioning 'TELEPORT1':'succeeded'-->'TELEPORT2'
+ [INFO] : State machine transitioning 'TELEPORT2':'succeeded'-->'BIG'
+ [WARN] : Still waiting for action server 'turtle_shape1' to start... is it running?
+ [INFO] : Connected to action server 'turtle_shape1'.
+ [INFO] 1279655938.783058: State machine transitioning 'BIG':'succeeded'-->'SMALL'
+ [INFO] 1279655975.025202: State machine terminating 'SMALL':'succeeded':'succeeded'
+
+"""
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+
+import threading
+
+import smach
+from smach import StateMachine, ServiceState, SimpleActionState, IntrospectionServer
+
+import std_srvs.srv
+import turtlesim.srv
+import turtle_actionlib.msg
+
+
+def main():
+ rospy.init_node('smach_usecase_step_04')
+
+ # Construct static goals
+ polygon_big = turtle_actionlib.msg.ShapeGoal(edges = 11, radius = 4.0)
+ polygon_small = turtle_actionlib.msg.ShapeGoal(edges = 6, radius = 0.5)
+
+ # Create a SMACH state machine
+ sm0 = StateMachine(outcomes=['succeeded','aborted','preempted'])
+
+ # Open the container
+ with sm0:
+ # Reset turtlesim
+ StateMachine.add('RESET',
+ ServiceState('reset', std_srvs.srv.Empty),
+ {'succeeded':'SPAWN'})
+
+ # Create a second turtle
+ StateMachine.add('SPAWN',
+ ServiceState('spawn', turtlesim.srv.Spawn,
+ request = turtlesim.srv.SpawnRequest(0.0,0.0,0.0,'turtle2')),
+ {'succeeded':'TELEPORT1'})
+
+ # Teleport turtle 1
+ StateMachine.add('TELEPORT1',
+ ServiceState('turtle1/teleport_absolute', turtlesim.srv.TeleportAbsolute,
+ request = turtlesim.srv.TeleportAbsoluteRequest(5.0,1.0,0.0)),
+ {'succeeded':'TELEPORT2'})
+
+ # Teleport turtle 2
+ StateMachine.add('TELEPORT2',
+ ServiceState('turtle2/teleport_absolute', turtlesim.srv.TeleportAbsolute,
+ request = turtlesim.srv.TeleportAbsoluteRequest(9.0,5.0,0.0)),
+ {'succeeded':'BIG'})
+
+ # Draw a large polygon with the first turtle
+ StateMachine.add('BIG',
+ SimpleActionState('turtle_shape1',turtle_actionlib.msg.ShapeAction,
+ goal = polygon_big),
+ {'succeeded':'SMALL'})
+
+ # Draw a small polygon with the second turtle
+ StateMachine.add('SMALL',
+ SimpleActionState('turtle_shape2',turtle_actionlib.msg.ShapeAction,
+ goal = polygon_small))
+
+ # Attach a SMACH introspection server
+ sis = IntrospectionServer('smach_usecase_01', sm0, '/USE_CASE')
+ sis.start()
+
+ # Set preempt handler
+ smach.set_preempt_handler(sm0)
+
+ # Execute SMACH tree in a separate thread so that we can ctrl-c the script
+ smach_thread = threading.Thread(target = sm0.execute)
+ smach_thread.start()
+
+ # Signal handler
+ rospy.spin()
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/scripts/usecase_01/executive_step_05.py b/smach_tutorials/scripts/usecase_01/executive_step_05.py
new file mode 100755
index 0000000..97d1ae4
--- /dev/null
+++ b/smach_tutorials/scripts/usecase_01/executive_step_05.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python
+"""
+Description:
+
+Usage:
+ $> roslaunch turtle_nodes.launch
+ $> ./executive_step_06.py
+
+Output:
+ [INFO] : State machine starting in initial state 'RESET' with userdata:
+ []
+ [INFO] : State machine transitioning 'RESET':'succeeded'-->'SPAWN'
+ [INFO] : State machine transitioning 'SPAWN':'succeeded'-->'TELEPORT1'
+ [INFO] : State machine transitioning 'TELEPORT1':'succeeded'-->'TELEPORT2'
+ [INFO] : State machine transitioning 'TELEPORT2':'succeeded'-->'DRAW_SHAPES'
+ [INFO] : Concurrence starting with userdata:
+ []
+ [WARN] : Still waiting for action server 'turtle_shape2' to start... is it running?
+ [WARN] : Still waiting for action server 'turtle_shape1' to start... is it running?
+ [INFO] : Connected to action server 'turtle_shape2'.
+ [INFO] : Connected to action server 'turtle_shape1'.
+ [INFO] : Concurrent Outcomes: {'SMALL': 'succeeded', 'BIG': 'succeeded'}
+ [INFO] : State machine terminating 'DRAW_SHAPES':'succeeded':'succeeded'
+"""
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+
+import threading
+
+import smach
+from smach import StateMachine, ServiceState, SimpleActionState, IntrospectionServer, Concurrence
+
+import std_srvs.srv
+import turtlesim.srv
+import turtle_actionlib.msg
+
+
+def main():
+ rospy.init_node('smach_usecase_step_05')
+
+ # Construct static goals
+ polygon_big = turtle_actionlib.msg.ShapeGoal(edges = 11, radius = 4.0)
+ polygon_small = turtle_actionlib.msg.ShapeGoal(edges = 6, radius = 0.5)
+
+ # Create a SMACH state machine
+ sm0 = StateMachine(outcomes=['succeeded','aborted','preempted'])
+
+ # Open the container
+ with sm0:
+ # Reset turtlesim
+ StateMachine.add('RESET',
+ ServiceState('reset', std_srvs.srv.Empty),
+ {'succeeded':'SPAWN'})
+
+ # Create a second turtle
+ StateMachine.add('SPAWN',
+ ServiceState('spawn', turtlesim.srv.Spawn,
+ request = turtlesim.srv.SpawnRequest(0.0,0.0,0.0,'turtle2')),
+ {'succeeded':'TELEPORT1'})
+
+ # Teleport turtle 1
+ StateMachine.add('TELEPORT1',
+ ServiceState('turtle1/teleport_absolute', turtlesim.srv.TeleportAbsolute,
+ request = turtlesim.srv.TeleportAbsoluteRequest(5.0,1.0,0.0)),
+ {'succeeded':'TELEPORT2'})
+
+ # Teleport turtle 2
+ StateMachine.add('TELEPORT2',
+ ServiceState('turtle2/teleport_absolute', turtlesim.srv.TeleportAbsolute,
+ request = turtlesim.srv.TeleportAbsoluteRequest(9.0,5.0,0.0)),
+ {'succeeded':'DRAW_SHAPES'})
+
+ # Draw some polygons
+ shapes_cc = Concurrence(
+ outcomes=['succeeded','aborted','preempted'],
+ default_outcome='aborted',
+ outcome_map = {'succeeded':{'BIG':'succeeded','SMALL':'succeeded'}})
+ StateMachine.add('DRAW_SHAPES',shapes_cc)
+ with shapes_cc:
+ # Draw a large polygon with the first turtle
+ Concurrence.add('BIG',
+ SimpleActionState('turtle_shape1',turtle_actionlib.msg.ShapeAction,
+ goal = polygon_big))
+
+ # Draw a small polygon with the second turtle
+ Concurrence.add('SMALL',
+ SimpleActionState('turtle_shape2',turtle_actionlib.msg.ShapeAction,
+ goal = polygon_small))
+
+
+ # Attach a SMACH introspection server
+ sis = IntrospectionServer('smach_usecase_01', sm0, '/USE_CASE')
+ sis.start()
+
+ # Set preempt handler
+ smach.set_preempt_handler(sm0)
+
+ # Execute SMACH tree in a separate thread so that we can ctrl-c the script
+ smach_thread = threading.Thread(target = sm0.execute)
+ smach_thread.start()
+
+ # Signal handler
+ rospy.spin()
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/scripts/usecase_01/executive_step_06.py b/smach_tutorials/scripts/usecase_01/executive_step_06.py
new file mode 100755
index 0000000..802f153
--- /dev/null
+++ b/smach_tutorials/scripts/usecase_01/executive_step_06.py
@@ -0,0 +1,142 @@
+#!/usr/bin/env python
+"""
+Description:
+
+Usage:
+ $> roslaunch turtle_nodes.launch
+ $> ./executive_step_06.py
+
+Output:
+ [INFO] : State machine starting in initial state 'RESET' with userdata:
+
+ [INFO] : State machine transitioning 'RESET':'succeeded'-->'SPAWN'
+ [INFO] : State machine transitioning 'SPAWN':'succeeded'-->'TELEPORT1'
+ [INFO] : State machine transitioning 'TELEPORT1':'succeeded'-->'TELEPORT2'
+ [INFO] : State machine transitioning 'TELEPORT2':'succeeded'-->'DRAW_SHAPES'
+ [INFO] : Concurrence starting with userdata:
+ []
+ [INFO] : State machine starting in initial state 'DRAW_WITH_MONITOR' with userdata:
+ []
+ [INFO] : Concurrence starting with userdata:
+ []
+ [WARN] : Still waiting for action server 'turtle_shape1' to start... is it running?
+ [WARN] : Still waiting for action server 'turtle_shape2' to start... is it running?
+ [INFO] : Connected to action server 'turtle_shape2'.
+ [INFO] : Connected to action server 'turtle_shape1'.
+ [INFO] : Preempt requested on action 'turtle_shape2'
+ [INFO] : Preempt on action 'turtle_shape2' cancelling goal:
+ edges: 6
+ radius: 0.5
+ [INFO] : Concurrent Outcomes: {'MONITOR': 'invalid', 'DRAW': 'preempted'}
+ [INFO] : State machine transitioning 'DRAW_WITH_MONITOR':'interrupted'-->'WAIT_FOR_CLEAR'
+ [INFO] : State machine transitioning 'WAIT_FOR_CLEAR':'invalid'-->'DRAW_WITH_MONITOR'
+ [INFO] : Concurrence starting with userdata:
+ []
+ [INFO] : Concurrent Outcomes: {'MONITOR': 'preempted', 'DRAW': 'succeeded'}
+ [INFO] : State machine terminating 'DRAW_WITH_MONITOR':'succeeded':'succeeded'
+ [INFO] : Concurrent Outcomes: {'SMALL': 'succeeded', 'BIG': 'succeeded'}
+ [INFO] : State machine terminating 'DRAW_SHAPES':'succeeded':'succeeded'
+
+"""
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+
+import threading
+from math import sqrt, pow
+
+import smach
+from smach import StateMachine, ServiceState, SimpleActionState, MonitorState, IntrospectionServer, Concurrence
+
+import std_srvs.srv
+import turtlesim.srv
+import turtlesim.msg
+import turtle_actionlib.msg
+
+
+def main():
+ rospy.init_node('smach_usecase_step_06')
+
+ # Construct static goals
+ polygon_big = turtle_actionlib.msg.ShapeGoal(edges = 11, radius = 4.0)
+ polygon_small = turtle_actionlib.msg.ShapeGoal(edges = 6, radius = 0.5)
+
+ # Create a SMACH state machine
+ sm0 = StateMachine(outcomes=['succeeded','aborted','preempted'])
+
+ # Open the container
+ with sm0:
+ # Reset turtlesim
+ StateMachine.add('RESET',
+ ServiceState('reset', std_srvs.srv.Empty),
+ {'succeeded':'SPAWN'})
+
+ # Create a second turtle
+ StateMachine.add('SPAWN',
+ ServiceState('spawn', turtlesim.srv.Spawn,
+ request = turtlesim.srv.SpawnRequest(0.0,0.0,0.0,'turtle2')),
+ {'succeeded':'TELEPORT1'})
+
+ # Teleport turtle 1
+ StateMachine.add('TELEPORT1',
+ ServiceState('turtle1/teleport_absolute', turtlesim.srv.TeleportAbsolute,
+ request = turtlesim.srv.TeleportAbsoluteRequest(5.0,1.0,0.0)),
+ {'succeeded':'TELEPORT2'})
+
+ # Teleport turtle 2
+ StateMachine.add('TELEPORT2',
+ ServiceState('turtle2/teleport_absolute', turtlesim.srv.TeleportAbsolute,
+ request = turtlesim.srv.TeleportAbsoluteRequest(9.0,5.0,0.0)),
+ {'succeeded':'DRAW_SHAPES'})
+
+ # Draw some polygons
+ shapes_cc = Concurrence(
+ outcomes=['succeeded','aborted','preempted'],
+ default_outcome='aborted',
+ outcome_map = {'succeeded':{'BIG':'succeeded','SMALL':'succeeded'}})
+ StateMachine.add('DRAW_SHAPES',shapes_cc)
+ with shapes_cc:
+ # Draw a large polygon with the first turtle
+ Concurrence.add('BIG',
+ SimpleActionState('turtle_shape1',turtle_actionlib.msg.ShapeAction,
+ goal = polygon_big))
+ # Draw a small polygon with the second turtle
+ draw_monitor_cc = Concurrence(
+ ['succeeded','aborted','preempted'],
+ 'aborted',
+ child_termination_cb = lambda so: True,
+ outcome_map = {
+ 'succeeded':{'DRAW':'succeeded'},
+ 'preempted':{'DRAW':'preempted','MONITOR':'preempted'},
+ 'aborted':{'MONITOR':'invalid'}})
+ Concurrence.add('SMALL',draw_monitor_cc)
+ with draw_monitor_cc:
+ Concurrence.add('DRAW',
+ SimpleActionState('turtle_shape2',turtle_actionlib.msg.ShapeAction,
+ goal = polygon_small))
+
+ def turtle_far_away(ud, msg):
+ """Returns True while turtle pose in msg is at least 1 unit away from (9,5)"""
+ if sqrt(pow(msg.x-9.0,2) + pow(msg.y-5.0,2)) > 2.0:
+ return True
+ return False
+ Concurrence.add('MONITOR',
+ MonitorState('/turtle1/pose',turtlesim.msg.Pose,
+ cond_cb = turtle_far_away))
+
+ # Attach a SMACH introspection server
+ sis = IntrospectionServer('smach_usecase_01', sm0, '/USE_CASE')
+ sis.start()
+
+ # Set preempt handler
+ smach.set_preempt_handler(sm0)
+
+ # Execute SMACH tree in a separate thread so that we can ctrl-c the script
+ smach_thread = threading.Thread(target = sm0.execute)
+ smach_thread.start()
+
+ # Signal handler
+ rospy.spin()
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/scripts/usecase_01/executive_step_07.py b/smach_tutorials/scripts/usecase_01/executive_step_07.py
new file mode 100755
index 0000000..2ed6c81
--- /dev/null
+++ b/smach_tutorials/scripts/usecase_01/executive_step_07.py
@@ -0,0 +1,156 @@
+#!/usr/bin/env python
+"""
+Description:
+
+Usage:
+ $> roslaunch turtle_nodes.launch
+ $> ./executive_step_06.py
+
+Output:
+ [INFO] : State machine starting in initial state 'RESET' with userdata:
+
+ [INFO] : State machine transitioning 'RESET':'succeeded'-->'SPAWN'
+ [INFO] : State machine transitioning 'SPAWN':'succeeded'-->'TELEPORT1'
+ [INFO] : State machine transitioning 'TELEPORT1':'succeeded'-->'TELEPORT2'
+ [INFO] : State machine transitioning 'TELEPORT2':'succeeded'-->'DRAW_SHAPES'
+ [INFO] : Concurrence starting with userdata:
+ []
+ [INFO] : State machine starting in initial state 'DRAW_WITH_MONITOR' with userdata:
+ []
+ [INFO] : Concurrence starting with userdata:
+ []
+ [WARN] : Still waiting for action server 'turtle_shape1' to start... is it running?
+ [WARN] : Still waiting for action server 'turtle_shape2' to start... is it running?
+ [INFO] : Connected to action server 'turtle_shape2'.
+ [INFO] : Connected to action server 'turtle_shape1'.
+ [INFO] : Preempt requested on action 'turtle_shape2'
+ [INFO] : Preempt on action 'turtle_shape2' cancelling goal:
+ edges: 6
+ radius: 0.5
+ [INFO] : Concurrent Outcomes: {'MONITOR': 'invalid', 'DRAW': 'preempted'}
+ [INFO] : State machine transitioning 'DRAW_WITH_MONITOR':'interrupted'-->'WAIT_FOR_CLEAR'
+ [INFO] : State machine transitioning 'WAIT_FOR_CLEAR':'invalid'-->'DRAW_WITH_MONITOR'
+ [INFO] : Concurrence starting with userdata:
+ []
+ [INFO] : Concurrent Outcomes: {'MONITOR': 'preempted', 'DRAW': 'succeeded'}
+ [INFO] : State machine terminating 'DRAW_WITH_MONITOR':'succeeded':'succeeded'
+ [INFO] : Concurrent Outcomes: {'SMALL': 'succeeded', 'BIG': 'succeeded'}
+ [INFO] : State machine terminating 'DRAW_SHAPES':'succeeded':'succeeded'
+
+"""
+
+import roslib; roslib.load_manifest('smach_tutorials')
+import rospy
+
+import threading
+from math import sqrt, pow
+
+import smach
+from smach import StateMachine, ServiceState, SimpleActionState, MonitorState, IntrospectionServer, Concurrence
+
+import std_srvs.srv
+import turtlesim.srv
+import turtlesim.msg
+import turtle_actionlib.msg
+
+
+def main():
+ rospy.init_node('smach_usecase_step_06')
+
+ # Construct static goals
+ polygon_big = turtle_actionlib.msg.ShapeGoal(edges = 11, radius = 4.0)
+ polygon_small = turtle_actionlib.msg.ShapeGoal(edges = 6, radius = 0.5)
+
+ # Create a SMACH state machine
+ sm0 = StateMachine(outcomes=['succeeded','aborted','preempted'])
+
+ # Open the container
+ with sm0:
+ # Reset turtlesim
+ StateMachine.add('RESET',
+ ServiceState('reset', std_srvs.srv.Empty),
+ {'succeeded':'SPAWN'})
+
+ # Create a second turtle
+ StateMachine.add('SPAWN',
+ ServiceState('spawn', turtlesim.srv.Spawn,
+ request = turtlesim.srv.SpawnRequest(0.0,0.0,0.0,'turtle2')),
+ {'succeeded':'TELEPORT1'})
+
+ # Teleport turtle 1
+ StateMachine.add('TELEPORT1',
+ ServiceState('turtle1/teleport_absolute', turtlesim.srv.TeleportAbsolute,
+ request = turtlesim.srv.TeleportAbsoluteRequest(5.0,1.0,0.0)),
+ {'succeeded':'DRAW_SHAPES'})
+
+ # Draw some polygons
+ shapes_cc = Concurrence(
+ outcomes=['succeeded','aborted','preempted'],
+ default_outcome='aborted',
+ outcome_map = {'succeeded':{'BIG':'succeeded','SMALL':'succeeded'}})
+ StateMachine.add('DRAW_SHAPES',shapes_cc)
+ with shapes_cc:
+ # Draw a large polygon with the first turtle
+ Concurrence.add('BIG',
+ SimpleActionState('turtle_shape1',turtle_actionlib.msg.ShapeAction,
+ goal = polygon_big))
+
+ # Draw a small polygon with the second turtle
+ small_shape_sm = StateMachine(outcomes=['succeeded','aborted','preempted'])
+ Concurrence.add('SMALL',small_shape_sm)
+ with small_shape_sm:
+ # Teleport turtle 2
+ StateMachine.add('TELEPORT2',
+ ServiceState('turtle2/teleport_absolute', turtlesim.srv.TeleportAbsolute,
+ request = turtlesim.srv.TeleportAbsoluteRequest(9.0,5.0,0.0)),
+ {'succeeded':'DRAW_WITH_MONITOR'})
+
+ # Construct a concurrence for the shape action and the monitor
+ draw_monitor_cc = Concurrence(
+ ['succeeded','aborted','preempted','interrupted'],
+ 'aborted',
+ child_termination_cb = lambda so: True,
+ outcome_map = {
+ 'succeeded':{'DRAW':'succeeded'},
+ 'preempted':{'DRAW':'preempted','MONITOR':'preempted'},
+ 'interrupted':{'MONITOR':'invalid'}})
+
+ StateMachine.add('DRAW_WITH_MONITOR',
+ draw_monitor_cc,
+ {'interrupted':'WAIT_FOR_CLEAR'})
+
+ with draw_monitor_cc:
+ Concurrence.add('DRAW',
+ SimpleActionState('turtle_shape2',turtle_actionlib.msg.ShapeAction,
+ goal = polygon_small))
+ def turtle_far_away(ud, msg):
+ """Returns True while turtle pose in msg is at least 1 unit away from (9,5)"""
+ if sqrt(pow(msg.x-9.0,2) + pow(msg.y-5.0,2)) > 2.0:
+ return True
+ return False
+ Concurrence.add('MONITOR',
+ MonitorState('/turtle1/pose',turtlesim.msg.Pose,
+ cond_cb = turtle_far_away))
+
+ StateMachine.add('WAIT_FOR_CLEAR',
+ MonitorState('/turtle1/pose',turtlesim.msg.Pose,
+ cond_cb = lambda ud,msg: not turtle_far_away(ud,msg)),
+ {'valid':'WAIT_FOR_CLEAR','invalid':'TELEPORT2'})
+
+
+ # Attach a SMACH introspection server
+ sis = IntrospectionServer('smach_usecase_01', sm0, '/USE_CASE')
+ sis.start()
+
+ # Set preempt handler
+ smach.set_preempt_handler(sm0)
+
+ # Execute SMACH tree in a separate thread so that we can ctrl-c the script
+ smach_thread = threading.Thread(target = sm0.execute)
+ smach_thread.start()
+
+ # Signal handler
+ rospy.spin()
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/scripts/usecase_01/turtle_nodes.launch b/smach_tutorials/scripts/usecase_01/turtle_nodes.launch
new file mode 100644
index 0000000..a0ee91d
--- /dev/null
+++ b/smach_tutorials/scripts/usecase_01/turtle_nodes.launch
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
From 2c63a763a87b3d389698280720eb1a12a1ec0171 Mon Sep 17 00:00:00 2001
From: "Isaac I.Y. Saito" <130s@2000.jukuin.keio.ac.jp>
Date: Thu, 8 Jun 2017 12:25:56 -0700
Subject: [PATCH 2/5] Batch picking newer changes from a forked repo
https://github.com/rhaschke/executive_smach_tutorials/commits/indigo-devel.
---
smach_tutorials/CMakeLists.txt | 11 +++-
smach_tutorials/examples/actionlib2_test.py | 1 -
smach_tutorials/examples/actionlib_test.py | 2 +-
smach_tutorials/examples/concurrence.py | 1 -
smach_tutorials/examples/concurrence2.py | 1 -
smach_tutorials/examples/sequence.py | 1 -
smach_tutorials/examples/state_machine.py | 1 -
.../examples/state_machine_nesting.py | 1 -
.../examples/state_machine_nesting2.py | 1 -
.../examples/state_machine_simple.py | 2 -
.../state_machine_simple_introspection.py | 62 +++++++++++++++++++
smach_tutorials/examples/user_data.py | 1 -
smach_tutorials/examples/user_data2.py | 1 -
smach_tutorials/package.xml | 3 +-
.../scripts/usecase_01/executive_step_01.py | 1 -
.../scripts/usecase_01/executive_step_02.py | 1 -
.../scripts/usecase_01/executive_step_03.py | 1 -
.../scripts/usecase_01/executive_step_04.py | 1 -
.../scripts/usecase_01/executive_step_05.py | 1 -
.../scripts/usecase_01/executive_step_06.py | 1 -
.../scripts/usecase_01/executive_step_07.py | 1 -
21 files changed, 75 insertions(+), 21 deletions(-)
create mode 100755 smach_tutorials/examples/state_machine_simple_introspection.py
diff --git a/smach_tutorials/CMakeLists.txt b/smach_tutorials/CMakeLists.txt
index 2d857e0..e1dc6ce 100644
--- a/smach_tutorials/CMakeLists.txt
+++ b/smach_tutorials/CMakeLists.txt
@@ -3,7 +3,16 @@ project(smach_tutorials)
find_package(catkin REQUIRED COMPONENTS actionlib_msgs message_generation)
-add_action_files(DIRECTORY action)
+add_action_files(
+ DIRECTORY action
+ FILES Test.action)
generate_messages(DEPENDENCIES actionlib_msgs)
catkin_package(CATKIN_DEPENDS actionlib_msgs message_runtime)
+
+install(
+ DIRECTORY examples
+ DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
+ USE_SOURCE_PERMISSIONS
+ FILES_MATCHING PATTERN "*.py"
+)
\ No newline at end of file
diff --git a/smach_tutorials/examples/actionlib2_test.py b/smach_tutorials/examples/actionlib2_test.py
index f102bdd..8a70ef6 100755
--- a/smach_tutorials/examples/actionlib2_test.py
+++ b/smach_tutorials/examples/actionlib2_test.py
@@ -1,6 +1,5 @@
#!/usr/bin/env python
-import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import smach
import smach_ros
diff --git a/smach_tutorials/examples/actionlib_test.py b/smach_tutorials/examples/actionlib_test.py
index 5378f9b..d476de1 100755
--- a/smach_tutorials/examples/actionlib_test.py
+++ b/smach_tutorials/examples/actionlib_test.py
@@ -18,11 +18,11 @@
[INFO] : State machine terminating 'GOAL_STATIC':'aborted':'succeeded'
"""
-import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import smach
import smach_ros
+from smach_tutorials.msg import TestAction, TestGoal
from actionlib import *
from actionlib_msgs.msg import *
diff --git a/smach_tutorials/examples/concurrence.py b/smach_tutorials/examples/concurrence.py
index 84b0c15..3462445 100755
--- a/smach_tutorials/examples/concurrence.py
+++ b/smach_tutorials/examples/concurrence.py
@@ -23,7 +23,6 @@
[INFO] : Concurrent Outcomes: {'SET': 'set_it', 'GET': 'got_it'}
"""
-import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import smach
import smach_ros
diff --git a/smach_tutorials/examples/concurrence2.py b/smach_tutorials/examples/concurrence2.py
index d45204e..bcf1243 100755
--- a/smach_tutorials/examples/concurrence2.py
+++ b/smach_tutorials/examples/concurrence2.py
@@ -1,6 +1,5 @@
#!/usr/bin/env python
-import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import smach
import smach_ros
diff --git a/smach_tutorials/examples/sequence.py b/smach_tutorials/examples/sequence.py
index 62fc865..0e73589 100755
--- a/smach_tutorials/examples/sequence.py
+++ b/smach_tutorials/examples/sequence.py
@@ -17,7 +17,6 @@
[INFO] : State machine terminating 'BAZ':'done':'succeeded'
"""
-import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import smach
import smach_ros
diff --git a/smach_tutorials/examples/state_machine.py b/smach_tutorials/examples/state_machine.py
index 81af47b..d5afc95 100755
--- a/smach_tutorials/examples/state_machine.py
+++ b/smach_tutorials/examples/state_machine.py
@@ -15,7 +15,6 @@
"""
-import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import smach
import smach_ros
diff --git a/smach_tutorials/examples/state_machine_nesting.py b/smach_tutorials/examples/state_machine_nesting.py
index 6cd92dc..55d41a0 100755
--- a/smach_tutorials/examples/state_machine_nesting.py
+++ b/smach_tutorials/examples/state_machine_nesting.py
@@ -21,7 +21,6 @@
"""
-import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import smach
import smach_ros
diff --git a/smach_tutorials/examples/state_machine_nesting2.py b/smach_tutorials/examples/state_machine_nesting2.py
index 7d64c11..bac37df 100755
--- a/smach_tutorials/examples/state_machine_nesting2.py
+++ b/smach_tutorials/examples/state_machine_nesting2.py
@@ -1,6 +1,5 @@
#!/usr/bin/env python
-import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import smach
import smach_ros
diff --git a/smach_tutorials/examples/state_machine_simple.py b/smach_tutorials/examples/state_machine_simple.py
index 2d87822..3d40057 100755
--- a/smach_tutorials/examples/state_machine_simple.py
+++ b/smach_tutorials/examples/state_machine_simple.py
@@ -1,9 +1,7 @@
#!/usr/bin/env python
-import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import smach
-import smach_ros
# define state Foo
class Foo(smach.State):
diff --git a/smach_tutorials/examples/state_machine_simple_introspection.py b/smach_tutorials/examples/state_machine_simple_introspection.py
new file mode 100755
index 0000000..2b76526
--- /dev/null
+++ b/smach_tutorials/examples/state_machine_simple_introspection.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+
+import rospy
+import smach
+import smach_ros
+
+# define state Foo
+class Foo(smach.State):
+ def __init__(self):
+ smach.State.__init__(self, outcomes=['outcome1','outcome2'])
+ self.counter = 0
+
+ def execute(self, userdata):
+ rospy.loginfo('Executing state FOO')
+ if self.counter < 3:
+ self.counter += 1
+ return 'outcome1'
+ else:
+ return 'outcome2'
+
+
+# define state Bar
+class Bar(smach.State):
+ def __init__(self):
+ smach.State.__init__(self, outcomes=['outcome2'])
+
+ def execute(self, userdata):
+ rospy.loginfo('Executing state BAR')
+ return 'outcome2'
+
+
+
+
+# main
+def main():
+ rospy.init_node('smach_example_state_machine')
+
+ # Create a SMACH state machine
+ sm = smach.StateMachine(outcomes=['outcome4', 'outcome5'])
+
+ # Open the container
+ with sm:
+ # Add states to the container
+ smach.StateMachine.add('FOO', Foo(),
+ transitions={'outcome1':'BAR',
+ 'outcome2':'outcome4'})
+ smach.StateMachine.add('BAR', Bar(),
+ transitions={'outcome2':'FOO'})
+
+ # Create and start the introspection server
+ sis = smach_ros.IntrospectionServer('my_smach_introspection_server', sm, '/SM_ROOT')
+ sis.start()
+
+ # Execute SMACH plan
+ outcome = sm.execute()
+
+ # Wait for ctrl-c to stop the application
+ rospy.spin()
+ sis.stop()
+
+if __name__ == '__main__':
+ main()
diff --git a/smach_tutorials/examples/user_data.py b/smach_tutorials/examples/user_data.py
index 322c29c..e087982 100755
--- a/smach_tutorials/examples/user_data.py
+++ b/smach_tutorials/examples/user_data.py
@@ -15,7 +15,6 @@
[INFO] : State machine terminating 'GET':'got_it':'succeeded'
"""
-import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import smach
import smach_ros
diff --git a/smach_tutorials/examples/user_data2.py b/smach_tutorials/examples/user_data2.py
index e61f890..056bd6d 100755
--- a/smach_tutorials/examples/user_data2.py
+++ b/smach_tutorials/examples/user_data2.py
@@ -1,6 +1,5 @@
#!/usr/bin/env python
-import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import smach
import smach_ros
diff --git a/smach_tutorials/package.xml b/smach_tutorials/package.xml
index 3230f5f..23447ad 100644
--- a/smach_tutorials/package.xml
+++ b/smach_tutorials/package.xml
@@ -5,8 +5,9 @@
This package contains numerous examples of how to use SMACH.
See the examples directory.
- Isaac I. Y. Saito
Jonathan Bohren
+ Robert Haschke
+ Isaac I. Y. Saito
BSD
http://wiki.ros.org/smach_tutorials
diff --git a/smach_tutorials/scripts/usecase_01/executive_step_01.py b/smach_tutorials/scripts/usecase_01/executive_step_01.py
index 20aaaa6..01c81c2 100755
--- a/smach_tutorials/scripts/usecase_01/executive_step_01.py
+++ b/smach_tutorials/scripts/usecase_01/executive_step_01.py
@@ -18,7 +18,6 @@
[ERROR] : Container consistency check failed.
"""
-import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import smach
diff --git a/smach_tutorials/scripts/usecase_01/executive_step_02.py b/smach_tutorials/scripts/usecase_01/executive_step_02.py
index c96cab8..7e26ff4 100755
--- a/smach_tutorials/scripts/usecase_01/executive_step_02.py
+++ b/smach_tutorials/scripts/usecase_01/executive_step_02.py
@@ -14,7 +14,6 @@
"""
-import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import threading
diff --git a/smach_tutorials/scripts/usecase_01/executive_step_03.py b/smach_tutorials/scripts/usecase_01/executive_step_03.py
index da27185..23c05e3 100755
--- a/smach_tutorials/scripts/usecase_01/executive_step_03.py
+++ b/smach_tutorials/scripts/usecase_01/executive_step_03.py
@@ -14,7 +14,6 @@
"""
-import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import threading
diff --git a/smach_tutorials/scripts/usecase_01/executive_step_04.py b/smach_tutorials/scripts/usecase_01/executive_step_04.py
index f6fe6d9..46bdb0e 100755
--- a/smach_tutorials/scripts/usecase_01/executive_step_04.py
+++ b/smach_tutorials/scripts/usecase_01/executive_step_04.py
@@ -20,7 +20,6 @@
"""
-import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import threading
diff --git a/smach_tutorials/scripts/usecase_01/executive_step_05.py b/smach_tutorials/scripts/usecase_01/executive_step_05.py
index 97d1ae4..3745514 100755
--- a/smach_tutorials/scripts/usecase_01/executive_step_05.py
+++ b/smach_tutorials/scripts/usecase_01/executive_step_05.py
@@ -23,7 +23,6 @@
[INFO] : State machine terminating 'DRAW_SHAPES':'succeeded':'succeeded'
"""
-import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import threading
diff --git a/smach_tutorials/scripts/usecase_01/executive_step_06.py b/smach_tutorials/scripts/usecase_01/executive_step_06.py
index 802f153..91a544a 100755
--- a/smach_tutorials/scripts/usecase_01/executive_step_06.py
+++ b/smach_tutorials/scripts/usecase_01/executive_step_06.py
@@ -39,7 +39,6 @@
"""
-import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import threading
diff --git a/smach_tutorials/scripts/usecase_01/executive_step_07.py b/smach_tutorials/scripts/usecase_01/executive_step_07.py
index 2ed6c81..471fa5b 100755
--- a/smach_tutorials/scripts/usecase_01/executive_step_07.py
+++ b/smach_tutorials/scripts/usecase_01/executive_step_07.py
@@ -39,7 +39,6 @@
"""
-import roslib; roslib.load_manifest('smach_tutorials')
import rospy
import threading
From 673f4464d1eb25001ccdfcb3b0a829d132f69f19 Mon Sep 17 00:00:00 2001
From: "Isaac I.Y. Saito" <130s@2000.jukuin.keio.ac.jp>
Date: Mon, 21 May 2018 09:53:04 -0700
Subject: [PATCH 3/5] [smach_tutorials] Update author, maintainer.
---
smach_tutorials/package.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smach_tutorials/package.xml b/smach_tutorials/package.xml
index 23447ad..3834b4d 100644
--- a/smach_tutorials/package.xml
+++ b/smach_tutorials/package.xml
@@ -6,7 +6,7 @@
See the examples directory.
Jonathan Bohren
- Robert Haschke
+ Robert Haschke
Isaac I. Y. Saito
BSD
From ddfc8bcd56c2d1dea6f2aaf18d8df61f2280abaa Mon Sep 17 00:00:00 2001
From: "Isaac I.Y. Saito" <130s@2000.jukuin.keio.ac.jp>
Date: Mon, 21 May 2018 10:05:03 -0700
Subject: [PATCH 4/5] [smach_tutorials] Install example Python scripts.
---
smach_tutorials/CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smach_tutorials/CMakeLists.txt b/smach_tutorials/CMakeLists.txt
index e1dc6ce..2b9d4cd 100644
--- a/smach_tutorials/CMakeLists.txt
+++ b/smach_tutorials/CMakeLists.txt
@@ -11,7 +11,7 @@ generate_messages(DEPENDENCIES actionlib_msgs)
catkin_package(CATKIN_DEPENDS actionlib_msgs message_runtime)
install(
- DIRECTORY examples
+ DIRECTORY examples scripts
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
USE_SOURCE_PERMISSIONS
FILES_MATCHING PATTERN "*.py"
From f77d02863eefbd491674994e58ed654321e1bd72 Mon Sep 17 00:00:00 2001
From: Daniel Stonier
Date: Thu, 2 Apr 2020 09:29:48 -0400
Subject: [PATCH 5/5] trailing newline
---
smach_tutorials/CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/smach_tutorials/CMakeLists.txt b/smach_tutorials/CMakeLists.txt
index 2b9d4cd..8ffbcfc 100644
--- a/smach_tutorials/CMakeLists.txt
+++ b/smach_tutorials/CMakeLists.txt
@@ -15,4 +15,4 @@ install(
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
USE_SOURCE_PERMISSIONS
FILES_MATCHING PATTERN "*.py"
-)
\ No newline at end of file
+)