Motion Planning using C++¶
In this exercise, we’ll explore MoveIt’s C++ interface to programatically move a robot.
Motivation¶
Now that we’ve got a working MoveIt! configuration for your workcell and we’ve played a bit in RViz with the planning tools, let’s perform planning and motion in code. This exercise will introduce you to the basic C++ interface for interacting with the MoveIt! node in your own program. There are lots of ways to use MoveIt!, but for simple applications this is the most straight forward.
Reference Example¶
3. Further Information and Resources¶
Scan-N-Plan Application: Problem Statement¶
In this exercise, your goal is to modify the myworkcell_core
node to:
- Move the robot’s tool frame to the center of the part location as reported by the service call to your vision node.
Scan-N-Plan Application: Guidance¶
Edit your
myworkcell_node.cpp
file.Add
#include <tf/tf.h>
to allow access to the tf library (for frame transforms/utilities).- Remember that we already added a dependency on the
tf
package in a previous exercise.
- Remember that we already added a dependency on the
In the
ScanNPlan
class’sstart
method, use the response from theLocalizePart
service to initialize a newmove_target
variable:geometry_msgs::Pose move_target = srv.response.pose;
- make sure to place this code after the call to the vision_node’s service.
Use the
MoveGroupInterface
to plan/execute a move to themove_target
position:In order to use the
MoveGroupInterface
class it is necessary to add themoveit_ros_planning_interface
package as a dependency of yourmyworkcell_core
package. Add themoveit_ros_planning_interface
dependency by modifying your package’sCMakeLists.txt
(2 lines) andpackage.xml
(1 line) as in previous exercises.Add the appropriate “include” reference to allow use of the
MoveGroupInterface
:#include <moveit/move_group_interface/move_group_interface.h>
Create a
moveit::planning_interface::MoveGroupInterface
object in theScanNPlan
class’sstart()
method. It has a single constructor that takes the name of the planning group you defined when creating the workcell moveit package (“manipulator”).moveit::planning_interface::MoveGroupInterface move_group("manipulator");
Set the desired cartesian target position using the
move_group
object’ssetPoseTarget
function. Call the object’smove()
function to plan and execute a move to the target position.// Plan for robot to move to part move_group.setPoseReferenceFrame(base_frame); move_group.setPoseTarget(move_target); move_group.move();
As described here, the
move_group.move()
command requires use of an “asynchronous” spinner, to allow processing of ROS messages during the blockingmove()
command. Initialize the spinner near the start of themain()
routine afterros::init(argc, argv, "myworkcell_node")
, and replace the existingros::spin()
command withros::waitForShutdown()
, as shown:ros::AsyncSpinner async_spinner(1); async_spinner.start(); ... ros::waitForShutdown();
Test the system!
catkin build roslaunch myworkcell_moveit_config myworkcell_planning_execution.launch roslaunch myworkcell_support workcell.launch
More to explore…
- In RViz, add a “Marker” display of topic “/ar_pose_visual” to confirm that the final robot position matches the position published by
fake_ar_publisher
- Try repeating the motion planning sequence:
- Use the MoveIt rviz interface to move the arm back to the “allZeros” position
- Ctrl+C the
workcell.launch
file, then rerun
- Try updating the
workcell_node
’sstart
method to automatically move back to theallZeros
position after moving to the AR_target position. See here for a list ofmove_group
’s available methods. - Try moving to an “approach position” located a few inches away from the target position, prior to the final move-to-target.
- In RViz, add a “Marker” display of topic “/ar_pose_visual” to confirm that the final robot position matches the position published by