Skip to content

Commit f495289

Browse files
Merge pull request #253 from floweisshardt/feature/emulator_move_base_melodic
melodic/noetic: add optional move_base interface to base emulator
2 parents bf556b2 + e4e2d81 commit f495289

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

cob_hardware_emulation/package.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
<depend>rosgraph_msgs</depend>
1616

1717
<exec_depend>actionlib</exec_depend>
18+
<exec_depend>actionlib_msgs</exec_depend>
1819
<exec_depend>control_msgs</exec_depend>
20+
<exec_depend>move_base_msgs</exec_depend>
1921
<exec_depend>nav_msgs</exec_depend>
2022
<exec_depend>rospy</exec_depend>
2123
<exec_depend>sensor_msgs</exec_depend>

cob_hardware_emulation/scripts/emulation_base.py

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
import copy
44
import math
55

6+
import actionlib
67
import rospy
78
import tf
89
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
1012
from geometry_msgs.msg import Pose, PoseWithCovarianceStamped, Quaternion
13+
from move_base_msgs.msg import MoveBaseAction, MoveBaseGoal, MoveBaseResult
1114
from nav_msgs.msg import Odometry
1215
from std_srvs.srv import Trigger, TriggerRequest, TriggerResponse
1316

@@ -22,11 +25,14 @@ def __init__(self):
2225
# - publishers:
2326
# - /base/odometry_controller/odometry [nav_msgs/Odometry]
2427
# - tf (odom_combined --> base_footprint, map --> odom_combined)
28+
# - actions:
29+
# - move_base [move_base_msgs/MoveBaseAction] (optional)
2530

2631

2732
# TODO
2833
# - add service reset odometry (/base/odometry_controller/reset_odometry [std_srvs::Trigger])
2934
# - speed factor
35+
# - handle cancel on move_base action
3036

3137
rospy.Subscriber("/base/twist_controller/command", Twist, self.twist_callback, queue_size=1)
3238
rospy.Subscriber("/initialpose", PoseWithCovarianceStamped, self.initalpose_callback, queue_size=1)
@@ -68,6 +74,19 @@ def __init__(self):
6874

6975
rospy.loginfo("Emulation for base running")
7076

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+
7190
def initalpose_callback(self, msg):
7291
self.initial_pose.translation.x = msg.pose.pose.position.x
7392
self.initial_pose.translation.y = msg.pose.pose.position.y
@@ -158,6 +177,49 @@ def timer_cb(self, event):
158177

159178
self.br.sendTransform(transforms)
160179

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+
161223
if __name__ == '__main__':
162224
rospy.init_node('emulation_base')
163225
EmulationBase()

0 commit comments

Comments
 (0)