Skip to content

Commit 4afdda3

Browse files
author
Emiliano Borghi
committed
Add smach scripts for ca_move_base_flex
1 parent f2134f2 commit 4afdda3

File tree

2 files changed

+134
-0
lines changed

2 files changed

+134
-0
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/usr/bin/env python
2+
import roslib
3+
import rospy
4+
import smach
5+
import smach_ros
6+
from mbf_msgs.msg import MoveBaseAction
7+
from mbf_msgs.msg import MoveBaseResult
8+
from geometry_msgs.msg import PoseStamped
9+
from nav_msgs.msg import Path
10+
from wait_for_goal import WaitForGoal
11+
12+
13+
@smach.cb_interface(
14+
input_keys=['target_pose', 'controller', 'planner', 'recovery_behaviors'])
15+
def move_base_goal_cb(userdata, goal):
16+
goal.target_pose = userdata.target_pose
17+
goal.controller = userdata.controller
18+
goal.planner = userdata.planner
19+
goal.recovery_behaviors = userdata.recovery_behaviors
20+
21+
22+
@smach.cb_interface(
23+
outcomes=['success', 'general_failure', 'plan_failure', 'ctrl_failure', 'undefined_failure'],
24+
output_keys=['mb_outcome', 'mb_message', 'mb_dist_to_goal', 'mb_angle_to_goal'])
25+
def move_base_result_cb(userdata, status, result):
26+
userdata.mb_outcome = result.outcome
27+
userdata.mb_message = result.message
28+
userdata.mb_dist_to_goal = result.dist_to_goal
29+
userdata.mb_angle_to_goal = result.angle_to_goal
30+
31+
if result.outcome is MoveBaseResult.SUCCESS:
32+
return 'success'
33+
elif 10 <= result.outcome < 50:
34+
return 'general_failure'
35+
elif 50 <= result.outcome < 100:
36+
return 'plan_failure'
37+
elif 100 <= result.outcome < 150:
38+
return 'ctrl_failure'
39+
else:
40+
return 'undefined_failure'
41+
42+
43+
def main():
44+
rospy.init_node('mbf_state_machine')
45+
46+
mbf_sm = smach.StateMachine(outcomes=['aborted', 'succeeded', 'preempted'])
47+
mbf_sm.userdata.path = Path()
48+
mbf_sm.userdata.previous_state = None
49+
mbf_sm.userdata.act_pos = None
50+
mbf_sm.userdata.error = None
51+
mbf_sm.userdata.error_status = None
52+
mbf_sm.userdata.goal_position = None
53+
mbf_sm.userdata.recovery_behavior = None
54+
mbf_sm.userdata.clear_costmap_flag = False
55+
mbf_sm.userdata.controller = 'controller'
56+
mbf_sm.userdata.planner = 'planner'
57+
mbf_sm.userdata.recovery_behaviors = ['clear_costmap', 'rotate_recovery']
58+
59+
with mbf_sm:
60+
# TODO: The states RECALLED and REJECTED are not implemented in the SimpleActionServer!
61+
# TODO: Trying to getState() when no goal is running. You are incorrectly using SimpleActionClient
62+
# TODO: smach viewer: http://wiki.ros.org/smach/Tutorials/Smach%20Viewer
63+
# TODO: navigation scripts: https://github.com/uos/ceres_robot/tree/master/ceres_navigation/scripts
64+
smach.StateMachine.add('WAIT_FOR_GOAL',
65+
WaitForGoal(),
66+
transitions={'received_goal': 'MOVE_BASE',
67+
'preempted': 'preempted'})
68+
69+
smach.StateMachine.add('MOVE_BASE',
70+
smach_ros.SimpleActionState(
71+
'move_base_flex/move_base',
72+
MoveBaseAction,
73+
goal_cb=move_base_goal_cb,
74+
result_cb=move_base_result_cb
75+
),
76+
transitions={
77+
'success': 'WAIT_FOR_GOAL',
78+
'general_failure': 'WAIT_FOR_GOAL',
79+
'plan_failure': 'WAIT_FOR_GOAL',
80+
'ctrl_failure': 'WAIT_FOR_GOAL',
81+
'undefined_failure': 'aborted'}
82+
)
83+
84+
sis = smach_ros.IntrospectionServer('mbf_move_base_server', mbf_sm, '/SM_ROOT')
85+
sis.start()
86+
outcome = mbf_sm.execute()
87+
rospy.spin()
88+
sis.stop()
89+
90+
91+
if __name__ == "__main__":
92+
while not rospy.is_shutdown():
93+
main()
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import rospy
2+
import smach
3+
import threading
4+
from geometry_msgs.msg import PoseStamped
5+
6+
7+
class WaitForGoal(smach.State):
8+
9+
def __init__(self):
10+
smach.State.__init__(self, outcomes=['received_goal', 'preempted'], input_keys=[], output_keys=['target_pose'])
11+
self.target_pose = PoseStamped()
12+
self.signal = threading.Event()
13+
self.subscriber = None
14+
15+
def execute(self, user_data):
16+
17+
rospy.loginfo("Waiting for a goal...")
18+
self.signal.clear()
19+
self.subscriber = rospy.Subscriber('/move_base_simple/goal', PoseStamped, self.goal_callback)
20+
while not rospy.is_shutdown() and not self.signal.is_set() and not self.preempt_requested():
21+
rospy.logdebug("Waiting for a goal...")
22+
self.signal.wait(1)
23+
24+
if self.preempt_requested() or rospy.is_shutdown():
25+
self.service_preempt()
26+
return 'preempted'
27+
28+
user_data.target_pose = self.target_pose
29+
pos = self.target_pose.pose.position
30+
rospy.loginfo("Received goal pose: (%s, %s, %s)", pos.x, pos.y, pos.z)
31+
32+
return 'received_goal'
33+
34+
def goal_callback(self, msg):
35+
rospy.logdebug("Received goal pose: %s", str(msg))
36+
self.target_pose = msg
37+
self.signal.set()
38+
39+
def request_preempt(self):
40+
smach.State.request_preempt(self)
41+
self.signal.set()

0 commit comments

Comments
 (0)