36 from moveit_commander
import (
39 PlanningSceneInterface,
40 MoveItCommanderException,
42 from geometry_msgs.msg
import Pose, PoseStamped
59 Interpreter for simple commands
62 DEFAULT_FILENAME =
"move_group.cfg"
106 MoveGroupInfoLevel.INFO,
108 +
"\n\nNo groups initialized yet. You must call the 'use' or the 'load' command first.\n",
112 if os.path.isfile(
"cmd/" + cmd):
113 cmd =
"load cmd/" + cmd
115 if cmdlow.startswith(
"use"):
119 clist[0] = clist[0].lower()
121 if clist[0] ==
"use":
122 if clist[1] ==
"previous":
124 if len(clist[1]) == 0:
125 return (MoveGroupInfoLevel.DEBUG,
"OK")
126 if clist[1]
in self.
_gdict:
129 return (MoveGroupInfoLevel.DEBUG,
"OK")
133 self.
_gdict[clist[1]] = mg
135 return (MoveGroupInfoLevel.DEBUG,
"OK")
136 except MoveItCommanderException
as e:
138 MoveGroupInfoLevel.FAIL,
139 "Initializing " + clist[1] +
": " + str(e),
143 MoveGroupInfoLevel.FAIL,
144 "Unable to initialize " + clist[1],
146 elif cmdlow.startswith(
"trace"):
147 if cmdlow ==
"trace":
149 MoveGroupInfoLevel.INFO,
150 "trace is on" if self.
_trace else "trace is off",
152 clist = cmdlow.split()
153 if clist[0] ==
"trace" and clist[1] ==
"on":
155 return (MoveGroupInfoLevel.DEBUG,
"OK")
156 if clist[0] ==
"trace" and clist[1] ==
"off":
158 return (MoveGroupInfoLevel.DEBUG,
"OK")
159 elif cmdlow.startswith(
"load"):
163 return (MoveGroupInfoLevel.WARN,
"Unable to parse load command")
166 if not os.path.isfile(filename):
167 filename =
"cmd/" + filename
171 f = open(filename,
"r")
177 print(
"%s:%d: %s" % (filename, line_num, line_content))
178 comment = line.find(
"#")
180 line = line[0:comment].rstrip()
184 return (MoveGroupInfoLevel.DEBUG,
"OK")
185 except MoveItCommanderException
as e:
188 MoveGroupInfoLevel.WARN,
189 "Error at %s:%d: %s\n%s"
190 % (filename, line_num, line_content, str(e)),
194 MoveGroupInfoLevel.WARN,
195 "Processing " + filename +
": " + str(e),
200 MoveGroupInfoLevel.WARN,
201 "Error at %s:%d: %s" % (filename, line_num, line_content),
204 return (MoveGroupInfoLevel.WARN,
"Unable to load " + filename)
205 elif cmdlow.startswith(
"save"):
209 return (MoveGroupInfoLevel.WARN,
"Unable to parse save command")
213 f = open(filename,
"w")
214 for gr
in self.
_gdict.keys():
215 f.write(
"use " + gr +
"\n")
216 known = self.
_gdict[gr].get_remembered_joint_values()
217 for v
in known.keys():
219 v +
" = [" +
" ".join([str(x)
for x
in known[v]]) +
"]\n"
225 return (MoveGroupInfoLevel.DEBUG,
"OK")
227 return (MoveGroupInfoLevel.WARN,
"Unable to save " + filename)
232 cmd = cmdorig.lower()
236 return (MoveGroupInfoLevel.DEBUG,
"OK")
239 return (MoveGroupInfoLevel.INFO, g.get_name())
242 return (MoveGroupInfoLevel.INFO, self.
get_help())
245 known = g.get_remembered_joint_values()
246 return (MoveGroupInfoLevel.INFO,
"[" +
" ".join(known.keys()) +
"]")
249 joints = g.get_joints()
251 MoveGroupInfoLevel.INFO,
253 +
"\n".join([str(i) +
" = " + joints[i]
for i
in range(len(joints))])
263 if cmd ==
"group_state":
268 pose.pose.position.x = 0
269 pose.pose.position.y = 0
271 pose.pose.position.z = -0.0501
272 pose.pose.orientation.x = 0
273 pose.pose.orientation.y = 0
274 pose.pose.orientation.z = 0
275 pose.pose.orientation.w = 1
276 pose.header.stamp = rospy.get_rostime()
277 pose.header.frame_id = self.
_robot.get_root_link()
279 self.
_robot.get_root_link(),
"ground", pose, (3, 3, 0.1)
281 return (MoveGroupInfoLevel.INFO,
"Added ground")
284 if len(g.get_end_effector_link()) > 0:
285 return (MoveGroupInfoLevel.INFO, g.get_end_effector_link())
287 return (MoveGroupInfoLevel.INFO,
"There is no end effector defined")
289 if cmd ==
"database":
291 return (MoveGroupInfoLevel.INFO,
"Not connected to a database")
294 MoveGroupInfoLevel.INFO,
299 return (MoveGroupInfoLevel.INFO, str(self.
_last_plan))
301 return (MoveGroupInfoLevel.INFO,
"No previous plan")
303 if cmd ==
"constrain":
304 g.clear_path_constraints()
305 return (MoveGroupInfoLevel.SUCCESS,
"Cleared path constraints")
307 if cmd ==
"tol" or cmd ==
"tolerance":
309 MoveGroupInfoLevel.INFO,
310 "Joint = %0.6g, Position = %0.6g, Orientation = %0.6g"
311 % g.get_goal_tolerance(),
315 return (MoveGroupInfoLevel.INFO, str(g.get_planning_time()))
320 return (MoveGroupInfoLevel.SUCCESS,
"Plan submitted for execution")
323 MoveGroupInfoLevel.WARN,
324 "Failed to submit plan for execution",
327 return (MoveGroupInfoLevel.WARN,
"No motion plan computed")
330 assign_match = re.match(
r"^(\w+)\s*=\s*(\w+)$", cmd)
332 known = g.get_remembered_joint_values()
333 if assign_match.group(2)
in known:
334 g.remember_joint_values(
335 assign_match.group(1), known[assign_match.group(2)]
338 MoveGroupInfoLevel.SUCCESS,
339 assign_match.group(1)
340 +
" is now the same as "
341 + assign_match.group(2),
344 return (MoveGroupInfoLevel.WARN,
"Unknown command: '" + cmd +
"'")
347 set_match = re.match(
r"^(\w+)\s*=\s*\[([\d\.e\-\+\s]+)\]$", cmd)
350 g.remember_joint_values(
351 set_match.group(1), [float(x)
for x
in set_match.group(2).split()]
354 MoveGroupInfoLevel.SUCCESS,
355 "Remembered joint values ["
357 +
"] under the name "
358 + set_match.group(1),
362 MoveGroupInfoLevel.WARN,
363 "Unable to parse joint value [" + set_match.group(2) +
"]",
367 component_match = re.match(
368 r"^(\w+)\s*\[\s*(\d+)\s*\]\s*=\s*([\d\.e\-\+]+)$", cmd
371 known = g.get_remembered_joint_values()
372 if component_match.group(1)
in known:
374 val = known[component_match.group(1)]
375 val[int(component_match.group(2))] = float(component_match.group(3))
376 g.remember_joint_values(component_match.group(1), val)
378 MoveGroupInfoLevel.SUCCESS,
380 + component_match.group(1)
382 + component_match.group(2)
387 MoveGroupInfoLevel.WARN,
388 "Unable to parse index or value in '" + cmd +
"'",
391 return (MoveGroupInfoLevel.WARN,
"Unknown command: '" + cmd +
"'")
393 clist = cmdorig.split()
394 clist[0] = clist[0].lower()
398 known = g.get_remembered_joint_values()
401 MoveGroupInfoLevel.INFO,
402 "[" +
" ".join([str(x)
for x
in known[cmd]]) +
"]",
405 return (MoveGroupInfoLevel.WARN,
"Unknown command: '" + cmd +
"'")
411 if clist[1] ==
"rand" or clist[1] ==
"random":
412 vals = g.get_random_joint_values()
413 g.set_joint_value_target(vals)
416 MoveGroupInfoLevel.SUCCESS,
417 "Moved to random target ["
418 +
" ".join([str(x)
for x
in vals])
423 MoveGroupInfoLevel.FAIL,
424 "Failed while moving to random target ["
425 +
" ".join([str(x)
for x
in vals])
430 g.set_named_target(clist[1])
432 return (MoveGroupInfoLevel.SUCCESS,
"Moved to " + clist[1])
435 MoveGroupInfoLevel.FAIL,
436 "Failed while moving to " + clist[1],
438 except MoveItCommanderException
as e:
440 MoveGroupInfoLevel.WARN,
441 "Going to " + clist[1] +
": " + str(e),
444 return (MoveGroupInfoLevel.WARN, clist[1] +
" is unknown")
445 if clist[0] ==
"plan":
448 if clist[1] ==
"rand" or clist[1] ==
"random":
449 vals = g.get_random_joint_values()
450 g.set_joint_value_target(vals)
454 g.set_named_target(clist[1])
456 except MoveItCommanderException
as e:
458 MoveGroupInfoLevel.WARN,
459 "Planning to " + clist[1] +
": " + str(e),
462 return (MoveGroupInfoLevel.WARN, clist[1] +
" is unknown")
465 len(self.
_last_plan.joint_trajectory.points) == 0
466 and len(self.
_last_plan.multi_dof_joint_trajectory.points) == 0
471 dest_str =
"[" +
" ".join([str(x)
for x
in vals]) +
"]"
473 return (MoveGroupInfoLevel.SUCCESS,
"Planned to " + dest_str)
476 MoveGroupInfoLevel.FAIL,
477 "Failed while planning to " + dest_str,
479 elif clist[0] ==
"pick":
482 return (MoveGroupInfoLevel.SUCCESS,
"Picked object " + clist[1])
485 MoveGroupInfoLevel.FAIL,
486 "Failed while trying to pick object " + clist[1],
488 elif clist[0] ==
"place":
490 if g.place(clist[1]):
491 return (MoveGroupInfoLevel.SUCCESS,
"Placed object " + clist[1])
494 MoveGroupInfoLevel.FAIL,
495 "Failed while trying to place object " + clist[1],
497 elif clist[0] ==
"planner":
498 g.set_planner_id(clist[1])
499 return (MoveGroupInfoLevel.SUCCESS,
"Planner is now " + clist[1])
500 elif clist[0] ==
"record" or clist[0] ==
"rec":
501 g.remember_joint_values(clist[1])
503 MoveGroupInfoLevel.SUCCESS,
504 "Remembered current joint values under the name " + clist[1],
506 elif clist[0] ==
"rand" or clist[0] ==
"random":
507 g.remember_joint_values(clist[1], g.get_random_joint_values())
509 MoveGroupInfoLevel.SUCCESS,
510 "Remembered random joint values under the name " + clist[1],
512 elif clist[0] ==
"del" or clist[0] ==
"delete":
513 g.forget_joint_values(clist[1])
515 MoveGroupInfoLevel.SUCCESS,
516 "Forgot joint values under the name " + clist[1],
518 elif clist[0] ==
"show":
519 known = g.get_remembered_joint_values()
520 if clist[1]
in known:
522 MoveGroupInfoLevel.INFO,
523 "[" +
" ".join([str(x)
for x
in known[clist[1]]]) +
"]",
527 MoveGroupInfoLevel.WARN,
528 "Joint values for " + clist[1] +
" are not known",
530 elif clist[0] ==
"tol" or clist[0] ==
"tolerance":
532 g.set_goal_tolerance(float(clist[1]))
533 return (MoveGroupInfoLevel.SUCCESS,
"OK")
536 MoveGroupInfoLevel.WARN,
537 "Unable to parse tolerance value '" + clist[1] +
"'",
539 elif clist[0] ==
"time":
541 g.set_planning_time(float(clist[1]))
542 return (MoveGroupInfoLevel.SUCCESS,
"OK")
545 MoveGroupInfoLevel.WARN,
546 "Unable to parse planning duration value '" + clist[1] +
"'",
548 elif clist[0] ==
"constrain":
550 g.set_path_constraints(clist[1])
551 return (MoveGroupInfoLevel.SUCCESS,
"OK")
555 MoveGroupInfoLevel.WARN,
556 "Constraint " + clist[1] +
" is not known.",
559 return (MoveGroupInfoLevel.WARN,
"Not connected to a database.")
560 elif clist[0] ==
"wait":
562 time.sleep(float(clist[1]))
563 return (MoveGroupInfoLevel.SUCCESS, clist[1] +
" seconds passed")
566 MoveGroupInfoLevel.WARN,
567 "Unable to wait '" + clist[1] +
"' seconds",
569 elif clist[0] ==
"database":
571 g.set_constraints_database(clist[1], self.
_db_port)
574 MoveGroupInfoLevel.SUCCESS,
579 MoveGroupInfoLevel.WARN,
580 "Unable to connect to '"
587 return (MoveGroupInfoLevel.WARN,
"Unknown command: '" + cmd +
"'")
590 if clist[0] ==
"go" and clist[1]
in self.
GO_DIRS:
593 offset = float(clist[2])
594 (axis, factor) = self.
GO_DIRS[clist[1]]
596 except MoveItCommanderException
as e:
598 MoveGroupInfoLevel.WARN,
599 "Going " + clist[1] +
": " + str(e),
603 MoveGroupInfoLevel.WARN,
604 "Unable to parse distance '" + clist[2] +
"'",
606 elif clist[0] ==
"allow" and (clist[1] ==
"look" or clist[1] ==
"looking"):
609 or clist[2] ==
"true"
611 or clist[2] ==
"True"
613 g.allow_looking(
True)
615 g.allow_looking(
False)
616 return (MoveGroupInfoLevel.DEBUG,
"OK")
617 elif clist[0] ==
"allow" and (
618 clist[1] ==
"replan" or clist[1] ==
"replanning"
622 or clist[2] ==
"true"
624 or clist[2] ==
"True"
626 g.allow_replanning(
True)
628 g.allow_replanning(
False)
629 return (MoveGroupInfoLevel.DEBUG,
"OK")
630 elif clist[0] ==
"database":
632 g.set_constraints_database(clist[1], int(clist[2]))
636 MoveGroupInfoLevel.SUCCESS,
642 MoveGroupInfoLevel.WARN,
643 "Unable to connect to '" + clist[1] +
":" + clist[2] +
"'",
646 if clist[0] ==
"rotate":
648 g.set_rpy_target([float(x)
for x
in clist[1:]])
650 return (MoveGroupInfoLevel.SUCCESS,
"Rotation complete")
653 MoveGroupInfoLevel.FAIL,
654 "Failed while rotating to " +
" ".join(clist[1:]),
656 except MoveItCommanderException
as e:
657 return (MoveGroupInfoLevel.WARN, str(e))
660 MoveGroupInfoLevel.WARN,
661 "Unable to parse X-Y-Z rotation values '"
662 +
" ".join(clist[1:])
670 if clist[7] ==
"approx" or clist[7] ==
"approximate":
674 p.position.x = float(clist[1])
675 p.position.y = float(clist[2])
676 p.position.z = float(clist[3])
677 q = tf.transformations.quaternion_from_euler(
678 float(clist[4]), float(clist[5]), float(clist[6])
680 p.orientation.x = q[0]
681 p.orientation.y = q[1]
682 p.orientation.z = q[2]
683 p.orientation.w = q[3]
685 g.set_joint_value_target(p,
True)
690 MoveGroupInfoLevel.SUCCESS,
691 "Moved to pose target\n%s\n" % (str(p)),
695 MoveGroupInfoLevel.FAIL,
696 "Failed while moving to pose \n%s\n" % (str(p)),
698 except MoveItCommanderException
as e:
700 MoveGroupInfoLevel.WARN,
701 "Going to pose target: %s" % (str(e)),
705 MoveGroupInfoLevel.WARN,
706 "Unable to parse pose '" +
" ".join(clist[1:]) +
"'",
709 return (MoveGroupInfoLevel.WARN,
"Unknown command: '" + cmd +
"'")
712 known = g.get_remembered_joint_values()
714 for k
in known.keys():
715 res.append(k +
" = [" +
" ".join([str(x)
for x
in known[k]]) +
"]")
716 return (MoveGroupInfoLevel.INFO,
"\n".join(res))
720 ' <group_state name="custom_state" group="{}">\n'.format(g.get_name())
723 ' <joint name="{}" value="{}"/>'.format(j, v)
724 for j, v
in zip(g._g.get_variables(), g.get_current_joint_values())
727 +
"\n </group_state>"
729 return (MoveGroupInfoLevel.INFO, res)
734 +
", ".join([str(x)
for x
in g.get_current_joint_values()])
737 if len(g.get_end_effector_link()) > 0:
741 + g.get_end_effector_link()
743 + str(g.get_current_pose())
749 + g.get_end_effector_link()
751 + str(g.get_current_rpy())
753 return (MoveGroupInfoLevel.INFO, res)
756 if g.has_end_effector_link():
758 g.shift_pose_target(dimension_index, factor * offset)
761 MoveGroupInfoLevel.SUCCESS,
762 "Moved " + direction_name +
" by " + str(offset) +
" m",
766 MoveGroupInfoLevel.FAIL,
767 "Failed while moving " + direction_name,
769 except MoveItCommanderException
as e:
770 return (MoveGroupInfoLevel.WARN, str(e))
772 return (MoveGroupInfoLevel.WARN,
"Unable to process pose update")
775 MoveGroupInfoLevel.WARN,
776 "No known end effector. Cannot move " + direction_name,
780 cmd = cmdorig.lower()
789 res.append(
"Known commands:")
790 res.append(
" help show this screen")
791 res.append(
" allow looking <true|false> enable/disable looking around")
792 res.append(
" allow replanning <true|false> enable/disable replanning")
793 res.append(
" constrain clear path constraints")
795 " constrain <name> use the constraint <name> as a path constraint"
797 res.append(
" current show the current state of the active group")
798 res.append(
" group_state current state to copy&paste to srdf file")
800 " database display the current database connection (if any)"
803 " delete <name> forget the joint values under the name <name>"
806 " eef print the name of the end effector attached to the current group"
808 res.append(
" execute execute a previously computed motion plan")
810 " go <name> plan and execute a motion to the state <name>"
812 res.append(
" go rand plan and execute a motion to a random state")
814 " go <dir> <dx>| plan and execute a motion in direction up|down|left|right|forward|backward for distance <dx>"
816 res.append(
" ground add a ground plane to the planning scene")
818 " id|which display the name of the group that is operated on"
821 " joints display names of the joints in the active group"
824 " load [<file>] load a set of interpreted commands from a file"
826 res.append(
" pick <name> pick up object <name>")
827 res.append(
" place <name> place object <name>")
828 res.append(
" plan <name> plan a motion to the state <name>")
829 res.append(
" plan rand plan a motion to a random state")
830 res.append(
" planner <name> use planner <name> to plan next motion")
832 " record <name> record the current joint values under the name <name>"
835 " rotate <x> <y> <z> plan and execute a motion to a specified orientation (about the X,Y,Z axes)"
838 " save [<file>] save the currently known variables as a set of commands"
841 " show display the names and values of the known states"
843 res.append(
" show <name> display the value of a state")
844 res.append(
" stop stop the active group")
845 res.append(
" time show the configured allowed planning time")
846 res.append(
" time <val> set the allowed planning time")
848 " tolerance show the tolerance for reaching the goal region"
851 " tolerance <val> set the tolerance for reaching the goal region"
853 res.append(
" trace <on|off> enable/disable replanning or looking around")
855 " use <name> switch to using the group named <name> (and load it if necessary)"
857 res.append(
" use|groups show the group names that are already loaded")
858 res.append(
" vars display the names of the known states")
859 res.append(
" wait <dt> sleep for <dt> seconds")
860 res.append(
" x = y assign the value of y to x")
861 res.append(
" x = [v1 v2...] assign a vector of values to x")
862 res.append(
" x[idx] = val assign a value to dimension idx of x")
863 return "\n".join(res)
871 groups = self.
_robot.get_group_names()
873 "go": [
"up",
"down",
"left",
"right",
"backward",
"forward",
"random"]
876 "record": known_vars,
879 "delete": known_vars,
889 "allow": [
"replanning",
"looking"],
890 "constrain": known_constr,