Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix is_running behaviour in case of exception in the state #50

Merged
merged 1 commit into from
Jun 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions smach/src/smach/state_machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,16 +353,18 @@ def execute(self, parent_ud = smach.UserData()):
# Initialize container outcome
container_outcome = None

# Step through state machine
while container_outcome is None and self._is_running and not smach.is_shutdown():
# Update the state machine
container_outcome = self._update_once()
try:
# Step through state machine
while container_outcome is None and self._is_running and not smach.is_shutdown():
# Update the state machine
container_outcome = self._update_once()

# Copy output keys
self._copy_output_keys(self.userdata, parent_ud)
# Copy output keys
self._copy_output_keys(self.userdata, parent_ud)

# We're no longer running
self._is_running = False
finally:
# We're no longer running
self._is_running = False

return container_outcome

Expand Down
25 changes: 25 additions & 0 deletions smach_ros/test/sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,31 @@ def test_sequence(self):

assert outcome == 'done'

def test_exception(self):
class DoneState(State):
def __init__(self):
State.__init__(self,outcomes=['done'])
def execute(self,ud=None):
return 'done'

class ErrorState(State):
"""State falls with exception"""
def __init__(self):
State.__init__(self, ['done'])
def execute(self, ud):
raise Exception('Test exception')

sq = Sequence(['done'], connector_outcome='done')
with sq:
Sequence.add('OK', DoneState())
Sequence.add('ERROR', ErrorState())
Sequence.add('IGNORED', Setter())

with self.assertRaises(InvalidUserCodeError):
sq.execute()

assert sq.is_running() == False
assert 'a' not in sq.userdata # test IGNORED state wasn't called

def main():
rospy.init_node('sequence_test',log_level=rospy.DEBUG)
Expand Down
17 changes: 17 additions & 0 deletions smach_ros/test/state_machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,23 @@ def test_alt_api(self):

assert outcome == 'succeeded'

def test_exception(self):
class ErrorState(State):
"""State falls with exception"""
def __init__(self):
State.__init__(self, ['done'])
def execute(self, ud):
raise Exception('Test exception')

sm = StateMachine(['done'])
with sm:
StateMachine.add('ERROR', ErrorState())

with self.assertRaises(InvalidUserCodeError):
sm.execute()

assert sm.is_running() == False # test running flag lowered

def main():
rospy.init_node('state_machine_test',log_level=rospy.DEBUG)
rostest.rosrun('smach', 'state_machine_test', TestStateMachine)
Expand Down