2 import clearpath_navigation_msgs.msg
6 """A single goal (part of a mission).
8 Contains a goalpoint, optional viapoints, optional tasks to run
9 at the goalpoint, and various other optional parameters related
10 to the specifics at the goal point.
12 A series of goals can be run in sequence to build a larger mission.
16 def createGoal(name, datum_latlon, goalpoint_latlon, viapoints_latlon=[], tasks=[],
17 enable_final_heading=False, goalpoint_heading=0,
18 enable_goal_tolerance=False, position_tolerance=0.1, yaw_tolerance=0.2):
19 """Creates a Goal object from the given parameters.
24 The name or ID of the goal, used for tracking/reporting
26 datum_latlon : CoordinateLatLon
27 The latitude/longitude position of the datum
29 goalpoint_latlon : CoordinateLatLon
30 The latitude/longitude position of the goalpoint
32 viapoints_latlon : CoordinateLatLon[], optional
33 A list of latitude/longitude positions of the viapoints,
34 starting from the beginning of the path and finishing
35 toward the goalpoint (default is no viapoints)
37 tasks : clearpath_navigation_msgs.msg.Task[], optional
38 A list of tasks to run at the goalpoint (default is no tasks)
40 enable_final_heading : bool, optional
41 Whether or not to apply a heading at the goalpoint (default is False)
43 goalpoint_heading : float64, optional
44 The heading, in degrees, to apply at the goalpoint (default is 0);
45 only gets applied when enable_final_heading is True
47 enable_goal_tolerance : bool, optional
48 Whether or not to enforce a tolerance at the goalpoint (default is False)
50 position_tolerance : float64, optional
51 The pose (x,y) tolerance, in meters, to apply at the goalpoint (default is 0.1);
52 only gets applied when enable_goal_tolerance is True
54 yaw_tolerance : float64, optional
55 The yaw tolerance, in radians, to apply at the goalpoint (default is 0.2);
56 only gets applied when enable_goal_tolerance is True
64 goalpoint_xy = goalpoint_latlon.toXY(datum_latlon)
65 goal_msg = clearpath_navigation_msgs.msg.MissionGoal()
66 goal_msg.mission.enable_final_heading = enable_final_heading
67 goal_msg.mission.goalpoint_heading = goalpoint_heading
68 goal_msg.mission.enable_goal_tolerance = enable_goal_tolerance
69 goal_msg.mission.position_tolerance = position_tolerance
70 goal_msg.mission.yaw_tolerance = yaw_tolerance
71 goal_msg.mission.goalpoint.x = goalpoint_xy.getX()
72 goal_msg.mission.goalpoint.y = goalpoint_xy.getY()
75 goal_msg.mission.viapoints = []
76 goal_msg.mission.tasks = tasks
77 for viapoint_latlon
in reversed(viapoints_latlon):
78 viapoint_xy = viapoint_latlon.toXY(datum_latlon)
79 viapoint = clearpath_navigation_msgs.msg.Waypoint()
80 viapoint.x = viapoint_xy.getX()
81 viapoint.y = viapoint_xy.getY()
82 goal_msg.mission.viapoints.append(viapoint)
84 return Goal(name, goal_msg)
94 goal_msg : clearpath_navigation_msgs.msg.MissionGoal
95 The goal message to be sent to the action server
102 """Gets the name of the goal.
113 """Gets the goal message.
117 clearpath_navigation_msgs.msg.MissionGoal
123 def sendGoal(self, actionlib_client, progress_callback=None, done_callback=None):
124 """Sends to goal to be executed.
126 This function returns immediately once the goal has been sent to
127 the navigation engine; it does not wait for the goal to complete.
131 actionlib_client : actionlib.SimpleActionClient reference
132 Reference to an instance of actionlib.SimpleActionClient use to make calls to
133 the appropriate actionlib server
135 progress_callback : fn(feedback_str), optional
136 A callback function that is called at regular intervals while the goal
137 is being executed to provide progress updates. The function should take
138 the "feedback_str" string parameter. If set to None, no feedback will be provided
139 and the goal will execute to completion.
141 done_callback : fn(enum, bool), optional
142 A callback function that is called when the goal is complete. The function should take
143 two parameters: the terminal state (as an integer from actionlib_msgs/GoalStatus) and
149 True on successful goal dispatch, else False
155 if not actionlib_client.wait_for_server(timeout=rospy.Duration()):
156 rospy.logerr(
"Failed to connect to server")
158 actionlib_client.send_goal(self.
_goal_msg,
159 feedback_cb=progress_callback,
160 done_cb=done_callback)
161 except rospy.ROSInterruptException:
162 rospy.logerr(
"mission server is not available; exception detected")
167 """Waits for goal to be executed.
169 This function blocks until the goal has been executed fully.
173 actionlib_client : actionlib.SimpleActionClient reference
174 Reference to an instance of actionlib.SimpleActionClient use to make calls to
175 the appropriate actionlib server
177 timeout : rospy.Duration, optional
178 Amount of time to wait for the goal to complete (default is to wait forever)
183 True on successful goal completion, else False
189 if not actionlib_client.wait_for_server(timeout=rospy.Duration()):
193 actionlib_client.wait_for_result(timeout)
196 return actionlib_client.get_result()
197 except rospy.ROSInterruptException:
198 rospy.logerr(
"mission server is not available; exception detected")
202 """Sends the goal to be executed and waits until completed.
204 This function blocks until the goal has been executed fully.
208 actionlib_client : actionlib.SimpleActionClient reference
209 Reference to an instance of actionlib.SimpleActionClient use to make calls to
210 the appropriate actionlib server
215 True on successful goal completion, else False
218 if not self.
sendGoal(actionlib_client):
224 """Cancels the goal that we are currently executing
228 actionlib_client : actionlib.SimpleActionClient reference
229 Reference to an instance of actionlib.SimpleActionClient use to make calls to
230 the appropriate actionlib server
233 actionlib_client.cancel_goal()
236 """Converts the goal to YAML format, for writing to disk.
241 A YAML-compatible dictionary representation of the object.
247 for viapoint
in goal_msg.mission.viapoints:
248 viapoints_yaml.append({
249 'x': float(viapoint.x),
250 'y': float(viapoint.y)
253 for task
in goal_msg.mission.tasks:
255 'task_name': task.task_name,
256 'action_server_name': task.action_server_name,
257 'version': task.version,
258 'floats': task.floats,
259 'strings': task.strings
263 'x': float(goal_msg.mission.goalpoint.x),
264 'y': float(goal_msg.mission.goalpoint.y)
266 'enable_final_heading': goal_msg.mission.enable_final_heading,
267 'goalpoint_heading': goal_msg.mission.goalpoint_heading,
268 'enable_goal_tolerance': goal_msg.mission.enable_goal_tolerance,
269 'position_tolerance': goal_msg.mission.position_tolerance,
270 'yaw_tolerance': goal_msg.mission.yaw_tolerance,
271 'viapoints': viapoints_yaml,
282 """Creates a Goal object from a YAML-compatible dictionary representation.
287 The YAML-compatible dictionary representation of a Goal object
291 name = goal_yaml[
'name']
292 goal_msg_yaml = goal_yaml[
'msg']
293 goal_msg = clearpath_navigation_msgs.msg.MissionGoal()
295 goal_msg.mission.goalpoint.x = goal_msg_yaml[
'goalpoint'][
'x']
296 goal_msg.mission.goalpoint.y = goal_msg_yaml[
'goalpoint'][
'y']
298 goal_msg.mission.enable_final_heading = goal_msg_yaml[
'enable_final_heading']
299 goal_msg.mission.goalpoint_heading = goal_msg_yaml[
'goalpoint_heading']
300 goal_msg.mission.enable_goal_tolerance = goal_msg_yaml[
'enable_goal_tolerance']
301 goal_msg.mission.position_tolerance = goal_msg_yaml[
'position_tolerance']
302 goal_msg.mission.yaw_tolerance = goal_msg_yaml[
'yaw_tolerance']
304 viapoints_yaml = goal_msg_yaml[
'viapoints']
305 goal_msg.mission.viapoints = []
306 for viapoint_yaml
in viapoints_yaml:
307 viapoint = clearpath_navigation_msgs.msg.Waypoint()
308 viapoint.x = viapoint_yaml[
'x']
309 viapoint.y = viapoint_yaml[
'y']
310 goal_msg.mission.viapoints.append(viapoint)
312 tasks_yaml = goal_msg_yaml[
'tasks']
313 goal_msg.mission.tasks = []
314 for task_yaml
in tasks_yaml:
315 task = clearpath_navigation_msgs.msg.Task()
316 task.task_name = task_yaml[
'task_name']
317 task.action_server_name = task_yaml[
'action_server_name']
318 task.version = task_yaml[
'version']
319 task.floats = task_yaml[
'floats']
320 task.strings = task_yaml[
'strings']
321 goal_msg.mission.tasks.append(task)
323 goal =
Goal(name, goal_msg)
325 except KeyError
as e:
326 rospy.logerr(
'Unable to parse yaml for goal: %s' % e)