36 from moveit_commander
import RobotCommander, MoveGroupCommander, PlanningSceneInterface, MoveItCommanderException
37 from geometry_msgs.msg
import Pose, PoseStamped
52 Interpreter for simple commands 55 DEFAULT_FILENAME =
"move_group.cfg" 56 GO_DIRS = {
"up" : (2,1),
"down" : (2, -1),
"z" : (2, 1),
57 "left" : (1, 1),
"right" : (1, -1),
"y" : (1, 1),
58 "forward" : (0, 1),
"backward" : (0, -1),
"back" : (0, -1),
"x" : (0, 1) }
78 return self._gdict.keys()
89 return (MoveGroupInfoLevel.INFO, self.
get_help() +
"\n\nNo groups initialized yet. You must call the 'use' or the 'load' command first.\n")
92 if os.path.isfile(
"cmd/" + cmd):
93 cmd =
"load cmd/" + cmd
95 if cmdlow.startswith(
"use"):
99 clist[0] = clist[0].lower()
101 if clist[0] ==
"use":
102 if clist[1] ==
"previous":
104 if len(clist[1]) == 0:
105 return (MoveGroupInfoLevel.DEBUG,
"OK")
106 if self._gdict.has_key(clist[1]):
109 return (MoveGroupInfoLevel.DEBUG,
"OK")
112 mg = MoveGroupCommander(clist[1])
113 self.
_gdict[clist[1]] = mg
115 return (MoveGroupInfoLevel.DEBUG,
"OK")
116 except MoveItCommanderException
as e:
117 return (MoveGroupInfoLevel.FAIL,
"Initializing " + clist[1] +
": " +
str(e))
119 return (MoveGroupInfoLevel.FAIL,
"Unable to initialize " + clist[1])
120 elif cmdlow.startswith(
"trace"):
121 if cmdlow ==
"trace":
122 return (MoveGroupInfoLevel.INFO,
"trace is on" if self.
_trace else "trace is off")
123 clist = cmdlow.split()
124 if clist[0] ==
"trace" and clist[1] ==
"on":
126 return (MoveGroupInfoLevel.DEBUG,
"OK")
127 if clist[0] ==
"trace" and clist[1] ==
"off":
129 return (MoveGroupInfoLevel.DEBUG,
"OK")
130 elif cmdlow.startswith(
"load"):
134 return (MoveGroupInfoLevel.WARN,
"Unable to parse load command")
137 if not os.path.isfile(filename):
138 filename =
"cmd/" + filename
142 f = open(filename,
'r') 148 print (
"%s:%d: %s" % (filename, line_num, line_content))
149 comment = line.find(
"#")
151 line = line[0:comment].rstrip()
155 return (MoveGroupInfoLevel.DEBUG,
"OK")
156 except MoveItCommanderException
as e:
158 return (MoveGroupInfoLevel.WARN,
"Error at %s:%d: %s\n%s" % (filename, line_num, line_content,
str(e)))
160 return (MoveGroupInfoLevel.WARN,
"Processing " + filename +
": " +
str(e))
163 return (MoveGroupInfoLevel.WARN,
"Error at %s:%d: %s" % (filename, line_num, line_content))
165 return (MoveGroupInfoLevel.WARN,
"Unable to load " + filename)
166 elif cmdlow.startswith(
"save"):
170 return (MoveGroupInfoLevel.WARN,
"Unable to parse save command")
174 f = open(filename,
'w')
175 for gr
in self._gdict.keys():
176 f.write(
"use " + gr +
"\n")
177 known = self.
_gdict[gr].get_remembered_joint_values()
178 for v
in known.keys():
179 f.write(v +
" = [" +
" ".join([
str(x)
for x
in known[v]]) +
"]\n")
182 return (MoveGroupInfoLevel.DEBUG,
"OK")
184 return (MoveGroupInfoLevel.WARN,
"Unable to save " + filename)
189 cmd = cmdorig.lower()
193 return (MoveGroupInfoLevel.DEBUG,
"OK")
196 return (MoveGroupInfoLevel.INFO, g.get_name())
199 return (MoveGroupInfoLevel.INFO, self.
get_help())
202 known = g.get_remembered_joint_values()
203 return (MoveGroupInfoLevel.INFO,
"[" +
" ".join(known.keys()) +
"]")
206 joints = g.get_joints()
207 return (MoveGroupInfoLevel.INFO,
"\n" +
"\n".join([
str(i) +
" = " + joints[i]
for i
in range(len(joints))]) +
"\n")
217 pose.pose.position.x = 0
218 pose.pose.position.y = 0
220 pose.pose.position.z = -0.0501
221 pose.pose.orientation.x = 0
222 pose.pose.orientation.y = 0
223 pose.pose.orientation.z = 0
224 pose.pose.orientation.w = 1
225 pose.header.stamp = rospy.get_rostime()
226 pose.header.frame_id = self._robot.get_root_link()
227 self._planning_scene_interface.attach_box(self._robot.get_root_link(),
"ground", pose, (3, 3, 0.1))
228 return (MoveGroupInfoLevel.INFO,
"Added ground")
231 if len(g.get_end_effector_link()) > 0:
232 return (MoveGroupInfoLevel.INFO, g.get_end_effector_link())
234 return (MoveGroupInfoLevel.INFO,
"There is no end effector defined")
236 if cmd ==
"database":
238 return (MoveGroupInfoLevel.INFO,
"Not connected to a database")
240 return (MoveGroupInfoLevel.INFO,
"Connected to " + self.
_db_host +
":" +
str(self.
_db_port))
245 return (MoveGroupInfoLevel.INFO,
"No previous plan")
247 if cmd ==
"constrain":
248 g.clear_path_constraints()
249 return (MoveGroupInfoLevel.SUCCESS,
"Cleared path constraints")
251 if cmd ==
"tol" or cmd ==
"tolerance":
252 return (MoveGroupInfoLevel.INFO,
"Joint = %0.6g, Position = %0.6g, Orientation = %0.6g" % g.get_goal_tolerance())
255 return (MoveGroupInfoLevel.INFO,
str(g.get_planning_time()))
260 return (MoveGroupInfoLevel.SUCCESS,
"Plan submitted for execution")
262 return (MoveGroupInfoLevel.WARN,
"Failed to submit plan for execution")
264 return (MoveGroupInfoLevel.WARN,
"No motion plan computed")
267 assign_match = re.match(
r"^(\w+)\s*=\s*(\w+)$", cmd)
269 known = g.get_remembered_joint_values()
270 if known.has_key(assign_match.group(2)):
271 g.remember_joint_values(assign_match.group(1), known[assign_match.group(2)])
272 return (MoveGroupInfoLevel.SUCCESS, assign_match.group(1) +
" is now the same as " + assign_match.group(2))
274 return (MoveGroupInfoLevel.WARN,
"Unknown command: '" + cmd +
"'")
277 set_match = re.match(
r"^(\w+)\s*=\s*\[([\d\.e\-\+\s]+)\]$", cmd)
280 g.remember_joint_values(set_match.group(1), [float(x)
for x
in set_match.group(2).split()])
281 return (MoveGroupInfoLevel.SUCCESS,
"Remembered joint values [" + set_match.group(2) +
"] under the name " + set_match.group(1))
283 return (MoveGroupInfoLevel.WARN,
"Unable to parse joint value [" + set_match.group(2) +
"]")
286 component_match = re.match(
r"^(\w+)\s*\[\s*(\d+)\s*\]\s*=\s*([\d\.e\-\+]+)$", cmd)
288 known = g.get_remembered_joint_values()
289 if known.has_key(component_match.group(1)):
291 val = known[component_match.group(1)]
292 val[int(component_match.group(2))] = float(component_match.group(3))
293 g.remember_joint_values(component_match.group(1), val)
294 return (MoveGroupInfoLevel.SUCCESS,
"Updated " + component_match.group(1) +
"[" + component_match.group(2) +
"]")
296 return (MoveGroupInfoLevel.WARN,
"Unable to parse index or value in '" + cmd +
"'")
298 return (MoveGroupInfoLevel.WARN,
"Unknown command: '" + cmd +
"'")
300 clist = cmdorig.split()
301 clist[0] = clist[0].lower()
305 known = g.get_remembered_joint_values()
306 if known.has_key(cmd):
307 return (MoveGroupInfoLevel.INFO,
"[" +
" ".join([
str(x)
for x
in known[cmd]]) +
"]")
309 return (MoveGroupInfoLevel.WARN,
"Unknown command: '" + cmd +
"'")
315 if clist[1] ==
"rand" or clist[1] ==
"random":
316 vals = g.get_random_joint_values()
317 g.set_joint_value_target(vals)
319 return (MoveGroupInfoLevel.SUCCESS,
"Moved to random target [" +
" ".join([
str(x)
for x
in vals]) +
"]")
321 return (MoveGroupInfoLevel.FAIL,
"Failed while moving to random target [" +
" ".join([
str(x)
for x
in vals]) +
"]")
324 g.set_named_target(clist[1])
326 return (MoveGroupInfoLevel.SUCCESS,
"Moved to " + clist[1])
328 return (MoveGroupInfoLevel.FAIL,
"Failed while moving to " + clist[1])
329 except MoveItCommanderException
as e:
330 return (MoveGroupInfoLevel.WARN,
"Going to " + clist[1] +
": " +
str(e))
332 return (MoveGroupInfoLevel.WARN, clist[1] +
" is unknown")
333 if clist[0] ==
"plan":
336 if clist[1] ==
"rand" or clist[1] ==
"random":
337 vals = g.get_random_joint_values()
338 g.set_joint_value_target(vals)
342 g.set_named_target(clist[1])
344 except MoveItCommanderException
as e:
345 return (MoveGroupInfoLevel.WARN,
"Planning to " + clist[1] +
": " +
str(e))
347 return (MoveGroupInfoLevel.WARN, clist[1] +
" is unknown")
349 if len(self._last_plan.joint_trajectory.points) == 0
and len(self._last_plan.multi_dof_joint_trajectory.points) == 0:
353 dest_str =
"[" +
" ".join([
str(x)
for x
in vals]) +
"]" 355 return (MoveGroupInfoLevel.SUCCESS,
"Planned to " + dest_str)
357 return (MoveGroupInfoLevel.FAIL,
"Failed while planning to " + dest_str)
358 elif clist[0] ==
"pick":
361 return (MoveGroupInfoLevel.SUCCESS,
"Picked object " + clist[1])
363 return (MoveGroupInfoLevel.FAIL,
"Failed while trying to pick object " + clist[1])
364 elif clist[0] ==
"place":
366 if g.place(clist[1]):
367 return (MoveGroupInfoLevel.SUCCESS,
"Placed object " + clist[1])
369 return (MoveGroupInfoLevel.FAIL,
"Failed while trying to place object " + clist[1])
370 elif clist[0] ==
"planner":
371 g.set_planner_id(clist[1])
372 return (MoveGroupInfoLevel.SUCCESS,
"Planner is now " + clist[1])
373 elif clist[0] ==
"record" or clist[0] ==
"rec":
374 g.remember_joint_values(clist[1])
375 return (MoveGroupInfoLevel.SUCCESS,
"Remembered current joint values under the name " + clist[1])
376 elif clist[0] ==
"rand" or clist[0] ==
"random":
377 g.remember_joint_values(clist[1], g.get_random_joint_values())
378 return (MoveGroupInfoLevel.SUCCESS,
"Remembered random joint values under the name " + clist[1])
379 elif clist[0] ==
"del" or clist[0] ==
"delete":
380 g.forget_joint_values(clist[1])
381 return (MoveGroupInfoLevel.SUCCESS,
"Forgot joint values under the name " + clist[1])
382 elif clist[0] ==
"show":
383 known = g.get_remembered_joint_values()
384 if known.has_key(clist[1]):
385 return (MoveGroupInfoLevel.INFO,
"[" +
" ".join([
str(x)
for x
in known[clist[1]]]) +
"]")
387 return (MoveGroupInfoLevel.WARN,
"Joint values for " + clist[1] +
" are not known")
388 elif clist[0] ==
"tol" or clist[0] ==
"tolerance":
390 g.set_goal_tolerance(float(clist[1]))
391 return (MoveGroupInfoLevel.SUCCESS,
"OK")
393 return (MoveGroupInfoLevel.WARN,
"Unable to parse tolerance value '" + clist[1] +
"'")
394 elif clist[0] ==
"time":
396 g.set_planning_time(float(clist[1]))
397 return (MoveGroupInfoLevel.SUCCESS,
"OK")
399 return (MoveGroupInfoLevel.WARN,
"Unable to parse planning duration value '" + clist[1] +
"'")
400 elif clist[0] ==
"constrain":
402 g.set_path_constraints(clist[1])
403 return (MoveGroupInfoLevel.SUCCESS,
"OK")
406 return (MoveGroupInfoLevel.WARN,
"Constraint " + clist[1] +
" is not known.")
408 return (MoveGroupInfoLevel.WARN,
"Not connected to a database.")
409 elif clist[0] ==
"wait":
411 time.sleep(float(clist[1]))
412 return (MoveGroupInfoLevel.SUCCESS, clist[1] +
" seconds passed")
414 return (MoveGroupInfoLevel.WARN,
"Unable to wait '" + clist[1] +
"' seconds")
415 elif clist[0] ==
"database":
417 g.set_constraints_database(clist[1], self.
_db_port)
419 return (MoveGroupInfoLevel.SUCCESS,
"Connected to " + self.
_db_host +
":" +
str(self.
_db_port))
421 return (MoveGroupInfoLevel.WARN,
"Unable to connect to '" + clist[1] +
":" +
str(self.
_db_port) +
"'")
423 return (MoveGroupInfoLevel.WARN,
"Unknown command: '" + cmd +
"'")
426 if clist[0] ==
"go" and self.GO_DIRS.has_key(clist[1]):
429 offset = float(clist[2])
430 (axis, factor) = self.
GO_DIRS[clist[1]]
432 except MoveItCommanderException
as e:
433 return (MoveGroupInfoLevel.WARN,
"Going " + clist[1] +
": " +
str(e))
435 return (MoveGroupInfoLevel.WARN,
"Unable to parse distance '" + clist[2] +
"'")
436 elif clist[0] ==
"allow" and (clist[1] ==
"look" or clist[1] ==
"looking"):
437 if clist[2] ==
"1" or clist[2] ==
"true" or clist[2] ==
"T" or clist[2] ==
"True":
438 g.allow_looking(
True)
440 g.allow_looking(
False)
441 return (MoveGroupInfoLevel.DEBUG,
"OK")
442 elif clist[0] ==
"allow" and (clist[1] ==
"replan" or clist[1] ==
"replanning"):
443 if clist[2] ==
"1" or clist[2] ==
"true" or clist[2] ==
"T" or clist[2] ==
"True":
444 g.allow_replanning(
True)
446 g.allow_replanning(
False)
447 return (MoveGroupInfoLevel.DEBUG,
"OK")
448 elif clist[0] ==
"database":
450 g.set_constraints_database(clist[1], int(clist[2]))
453 return (MoveGroupInfoLevel.SUCCESS,
"Connected to " + self.
_db_host +
":" +
str(self.
_db_port))
456 return (MoveGroupInfoLevel.WARN,
"Unable to connect to '" + clist[1] +
":" + clist[2] +
"'")
458 if clist[0] ==
"rotate":
460 g.set_rpy_target([float(x)
for x
in clist[1:]])
462 return (MoveGroupInfoLevel.SUCCESS,
"Rotation complete")
464 return (MoveGroupInfoLevel.FAIL,
"Failed while rotating to " +
" ".join(clist[1:]))
465 except MoveItCommanderException
as e:
466 return (MoveGroupInfoLevel.WARN,
str(e))
468 return (MoveGroupInfoLevel.WARN,
"Unable to parse X-Y-Z rotation values '" +
" ".join(clist[1:]) +
"'")
474 if (clist[7] ==
"approx" or clist[7] ==
"approximate"):
478 p.position.x = float(clist[1])
479 p.position.y = float(clist[2])
480 p.position.z = float(clist[3])
481 q = tf.transformations.quaternion_from_euler(float(clist[4]), float(clist[5]), float(clist[6]))
482 p.orientation.x = q[0]
483 p.orientation.y = q[1]
484 p.orientation.z = q[2]
485 p.orientation.w = q[3]
487 g.set_joint_value_target(p,
True)
491 return (MoveGroupInfoLevel.SUCCESS,
"Moved to pose target\n%s\n" % (
str(p)))
493 return (MoveGroupInfoLevel.FAIL,
"Failed while moving to pose \n%s\n" % (
str(p)))
494 except MoveItCommanderException
as e:
495 return (MoveGroupInfoLevel.WARN,
"Going to pose target: %s" % (
str(e)))
497 return (MoveGroupInfoLevel.WARN,
"Unable to parse pose '" +
" ".join(clist[1:]) +
"'")
499 return (MoveGroupInfoLevel.WARN,
"Unknown command: '" + cmd +
"'")
502 known = g.get_remembered_joint_values()
504 for k
in known.keys():
505 res.append(k +
" = [" +
" ".join([
str(x)
for x
in known[k]]) +
"]")
506 return (MoveGroupInfoLevel.INFO,
"\n".join(res))
509 res =
"joints = [" +
" ".join([
str(x)
for x
in g.get_current_joint_values()]) +
"]" 510 if len(g.get_end_effector_link()) > 0:
511 res = res +
"\n" + g.get_end_effector_link() +
" pose = [\n" +
str(g.get_current_pose()) +
" ]" 512 res = res +
"\n" + g.get_end_effector_link() +
" RPY = " +
str(g.get_current_rpy())
513 return (MoveGroupInfoLevel.INFO, res)
516 if g.has_end_effector_link():
518 g.shift_pose_target(dimension_index, factor * offset)
520 return (MoveGroupInfoLevel.SUCCESS,
"Moved " + direction_name +
" by " +
str(offset) +
" m")
522 return (MoveGroupInfoLevel.FAIL,
"Failed while moving " + direction_name)
523 except MoveItCommanderException
as e:
524 return (MoveGroupInfoLevel.WARN,
str(e))
526 return (MoveGroupInfoLevel.WARN,
"Unable to process pose update")
528 return (MoveGroupInfoLevel.WARN,
"No known end effector. Cannot move " + direction_name)
531 cmd = cmdorig.lower()
540 res.append(
"Known commands:")
541 res.append(
" help show this screen")
542 res.append(
" allow looking <true|false> enable/disable looking around")
543 res.append(
" allow replanning <true|false> enable/disable replanning")
544 res.append(
" constrain clear path constraints")
545 res.append(
" constrain <name> use the constraint <name> as a path constraint")
546 res.append(
" current show the current state of the active group")
547 res.append(
" database display the current database connection (if any)")
548 res.append(
" delete <name> forget the joint values under the name <name>")
549 res.append(
" eef print the name of the end effector attached to the current group")
550 res.append(
" execute execute a previously computed motion plan")
551 res.append(
" go <name> plan and execute a motion to the state <name>")
552 res.append(
" go rand plan and execute a motion to a random state")
553 res.append(
" go <dir> <dx>| plan and execute a motion in direction up|down|left|right|forward|backward for distance <dx>")
554 res.append(
" ground add a ground plane to the planning scene")
555 res.append(
" id|which display the name of the group that is operated on")
556 res.append(
" joints display names of the joints in the active group")
557 res.append(
" load [<file>] load a set of interpreted commands from a file")
558 res.append(
" pick <name> pick up object <name>")
559 res.append(
" place <name> place object <name>")
560 res.append(
" plan <name> plan a motion to the state <name>")
561 res.append(
" plan rand plan a motion to a random state")
562 res.append(
" planner <name> use planner <name> to plan next motion")
563 res.append(
" record <name> record the current joint values under the name <name>")
564 res.append(
" rotate <x> <y> <z> plan and execute a motion to a specified orientation (about the X,Y,Z axes)")
565 res.append(
" save [<file>] save the currently known variables as a set of commands")
566 res.append(
" show display the names and values of the known states")
567 res.append(
" show <name> display the value of a state")
568 res.append(
" stop stop the active group")
569 res.append(
" time show the configured allowed planning time")
570 res.append(
" time <val> set the allowed planning time")
571 res.append(
" tolerance show the tolerance for reaching the goal region")
572 res.append(
" tolerance <val> set the tolerance for reaching the goal region")
573 res.append(
" trace <on|off> enable/disable replanning or looking around")
574 res.append(
" use <name> switch to using the group named <name> (and load it if necessary)")
575 res.append(
" use|groups show the group names that are already loaded")
576 res.append(
" vars display the names of the known states")
577 res.append(
" wait <dt> sleep for <dt> seconds")
578 res.append(
" x = y assign the value of y to x")
579 res.append(
" x = [v1 v2...] assign a vector of values to x")
580 res.append(
" x[idx] = val assign a value to dimension idx of x")
581 return "\n".join(res)
589 groups = self._robot.get_group_names()
590 return {
'go':[
'up',
'down',
'left',
'right',
'backward',
'forward',
'random'] + known_vars,
604 'allow':[
'replanning',
'looking'],
605 'constrain':known_constr,
def execute_generic_command(self, cmd)
def command_show(self, g)
def command_current(self, g)
def execute_group_command(self, g, cmdorig)
def get_loaded_groups(self)
def get_active_group(self)
def command_go_offset(self, g, offset, factor, dimension_index, direction_name)
def resolve_command_alias(self, cmdorig)
_planning_scene_interface