3
3
import copy
4
4
import math
5
5
6
+ import actionlib
6
7
import rospy
7
8
import tf
8
9
import tf2_ros
9
- from geometry_msgs .msg import Twist , Transform , TransformStamped
10
+ from actionlib_msgs .msg import GoalStatus
11
+ from geometry_msgs .msg import Twist , Transform , TransformStamped , PoseStamped
10
12
from geometry_msgs .msg import Pose , PoseWithCovarianceStamped , Quaternion
13
+ from move_base_msgs .msg import MoveBaseAction , MoveBaseGoal , MoveBaseResult
11
14
from nav_msgs .msg import Odometry
12
15
from std_srvs .srv import Trigger , TriggerRequest , TriggerResponse
13
16
@@ -22,11 +25,14 @@ def __init__(self):
22
25
# - publishers:
23
26
# - /base/odometry_controller/odometry [nav_msgs/Odometry]
24
27
# - tf (odom_combined --> base_footprint, map --> odom_combined)
28
+ # - actions:
29
+ # - move_base [move_base_msgs/MoveBaseAction] (optional)
25
30
26
31
27
32
# TODO
28
33
# - add service reset odometry (/base/odometry_controller/reset_odometry [std_srvs::Trigger])
29
34
# - speed factor
35
+ # - handle cancel on move_base action
30
36
31
37
rospy .Subscriber ("/base/twist_controller/command" , Twist , self .twist_callback , queue_size = 1 )
32
38
rospy .Subscriber ("/initialpose" , PoseWithCovarianceStamped , self .initalpose_callback , queue_size = 1 )
@@ -68,6 +74,19 @@ def __init__(self):
68
74
69
75
rospy .loginfo ("Emulation for base running" )
70
76
77
+ # Optional move_base action
78
+ self .move_base_mode = rospy .get_param ("~move_base_mode" , None )
79
+ if self .move_base_mode == None :
80
+ rospy .loginfo ("Emulation running without move_base" )
81
+ elif self .move_base_mode == "beam" or self .move_base_mode == "linear_nav" :
82
+ self .move_base_action_name = "/move_base"
83
+ rospy .Subscriber (self .move_base_action_name + "_simple/goal" , PoseStamped , self .move_base_simple_callback , queue_size = 1 )
84
+ self .as_move_base = actionlib .SimpleActionServer (self .move_base_action_name , MoveBaseAction , execute_cb = self .move_base_cb , auto_start = False )
85
+ self .as_move_base .start ()
86
+ rospy .loginfo ("Emulation running for action %s of type MoveBaseAction with mode '%s'" % (self .move_base_action_name , self .move_base_mode ))
87
+ else :
88
+ rospy .logwarn ("Emulation running without move_base due to invalid value for parameter move_base_mode: '%s'" , self .move_base_mode )
89
+
71
90
def initalpose_callback (self , msg ):
72
91
self .initial_pose .translation .x = msg .pose .pose .position .x
73
92
self .initial_pose .translation .y = msg .pose .pose .position .y
@@ -158,6 +177,49 @@ def timer_cb(self, event):
158
177
159
178
self .br .sendTransform (transforms )
160
179
180
+ def move_base_cb (self , goal ):
181
+ pwcs = PoseWithCovarianceStamped ()
182
+ pwcs .header = goal .target_pose .header
183
+ pwcs .pose .pose = goal .target_pose .pose
184
+ if self .move_base_mode == "beam" :
185
+ rospy .loginfo ("move_base: beaming robot to new goal" )
186
+ self .initalpose_callback (pwcs )
187
+ elif self .move_base_mode == "linear_nav" :
188
+ move_base_linear_action_name = "/move_base_linear"
189
+ ac_move_base_linear = actionlib .SimpleActionClient (move_base_linear_action_name , MoveBaseAction )
190
+ rospy .loginfo ("Waiting for ActionServer: %s" , move_base_linear_action_name )
191
+ if not ac_move_base_linear .wait_for_server (rospy .Duration (1 )):
192
+ rospy .logerr ("Emulator move_base failed because move_base_linear action server is not available" )
193
+ self .as_move_base .set_aborted ()
194
+ return
195
+ rospy .loginfo ("send goal to %s" , move_base_linear_action_name )
196
+ ac_move_base_linear .send_goal (goal )
197
+ ac_move_base_linear .wait_for_result ()
198
+ ac_move_base_linear_status = ac_move_base_linear .get_state ()
199
+ ac_move_base_linear_result = ac_move_base_linear .get_result ()
200
+ if ac_move_base_linear_status != GoalStatus .SUCCEEDED :
201
+ rospy .logerr ("Emulator move_base failed because move_base_linear failed" )
202
+ self .as_move_base .set_aborted ()
203
+ return
204
+ else :
205
+ rospy .logerr ("Invalid move_base_action_mode" )
206
+ self .as_move_base .set_aborted ()
207
+ return
208
+ rospy .loginfo ("Emulator move_base succeeded" )
209
+ self .as_move_base .set_succeeded (MoveBaseResult ())
210
+
211
+ def move_base_simple_callback (self , msg ):
212
+ goal = MoveBaseGoal ()
213
+ goal .target_pose = msg
214
+ ac_move_base = actionlib .SimpleActionClient (self .move_base_action_name , MoveBaseAction )
215
+ rospy .loginfo ("Waiting for ActionServer: %s" , self .move_base_action_name )
216
+ if not ac_move_base .wait_for_server (rospy .Duration (1 )):
217
+ rospy .logerr ("Emulator move_base simple failed because move_base action server is not available" )
218
+ return
219
+ rospy .loginfo ("send goal to %s" , self .move_base_action_name )
220
+ ac_move_base .send_goal (goal )
221
+ # ac_move_base.wait_for_result() # no need to wait for the result as this is the topic interface to move_base without feedback
222
+
161
223
if __name__ == '__main__' :
162
224
rospy .init_node ('emulation_base' )
163
225
EmulationBase ()
0 commit comments