motion_planning_interface_tutorial.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *
00003 * Software License Agreement (BSD License)
00004 *
00005 *  Copyright (c) 2012, Willow Garage, Inc.
00006 *  All rights reserved.
00007 *
00008 *  Redistribution and use in source and binary forms, with or without
00009 *  modification, are permitted provided that the following conditions
00010 *  are met:
00011 *
00012 *   * Redistributions of source code must retain the above copyright
00013 *     notice, this list of conditions and the following disclaimer.
00014 *   * Redistributions in binary form must reproduce the above
00015 *     copyright notice, this list of conditions and the following
00016 *     disclaimer in the documentation and/or other materials provided
00017 *     with the distribution.
00018 *   * Neither the name of Willow Garage, Inc. nor the names of its
00019 *     contributors may be used to endorse or promote products derived
00020 *     from this software without specific prior written permission.
00021 *
00022 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033 *  POSSIBILITY OF SUCH DAMAGE.
00034 *
00035 * Author: Sachin Chitta
00036 *********************************************************************/
00037 
00038 #include <pluginlib/class_loader.h>
00039 #include <ros/ros.h>
00040 
00041 // MoveIt!
00042 #include <moveit/robot_model_loader/robot_model_loader.h>
00043 #include <moveit/planning_interface/planning_interface.h>
00044 #include <moveit/kinematic_constraints/utils.h>
00045 #include <moveit_msgs/DisplayTrajectory.h>
00046 #include <moveit_msgs/PlanningScene.h>
00047 
00048 int main(int argc, char **argv)
00049 {
00050   ros::init (argc, argv, "move_group_tutorial");
00051   ros::AsyncSpinner spinner(1);
00052   spinner.start();
00053   ros::NodeHandle node_handle("~");
00054 
00055   /* SETUP A PLANNING SCENE*/
00056   /* Load the robot model */
00057   robot_model_loader::RobotModelLoader robot_model_loader("robot_description");
00058 
00059   /* Get a shared pointer to the model */
00060   robot_model::RobotModelPtr robot_model = robot_model_loader.getModel();
00061 
00062   /* Construct a planning scene - NOTE: this is for illustration purposes only.
00063      The recommended way to construct a planning scene is to use the planning_scene_monitor
00064      to construct it for you.*/
00065   planning_scene::PlanningScenePtr planning_scene(new planning_scene::PlanningScene(robot_model));
00066 
00067   /* SETUP THE PLANNER*/
00068   boost::scoped_ptr<pluginlib::ClassLoader<planning_interface::PlannerManager> > planner_plugin_loader;
00069   planning_interface::PlannerManagerPtr planner_instance;
00070   std::string planner_plugin_name;
00071 
00072   /* Get the name of the planner we want to use */
00073   if (!node_handle.getParam("planning_plugin", planner_plugin_name))
00074     ROS_FATAL_STREAM("Could not find planner plugin name");
00075 
00076   /* Make sure to catch all exceptions */
00077   try
00078   {
00079     planner_plugin_loader.reset(new pluginlib::ClassLoader<planning_interface::PlannerManager>("moveit_core", "planning_interface::PlannerManager"));
00080   }
00081   catch(pluginlib::PluginlibException& ex)
00082   {
00083     ROS_FATAL_STREAM("Exception while creating planning plugin loader " << ex.what());
00084   }
00085   try
00086   {
00087     planner_instance.reset(planner_plugin_loader->createUnmanagedInstance(planner_plugin_name));
00088     if (!planner_instance->initialize(robot_model, node_handle.getNamespace()))
00089       ROS_FATAL_STREAM("Could not initialize planner instance");
00090     ROS_INFO_STREAM("Using planning interface '" << planner_instance->getDescription() << "'");
00091   }
00092   catch(pluginlib::PluginlibException& ex)
00093   {
00094     const std::vector<std::string> &classes = planner_plugin_loader->getDeclaredClasses();
00095     std::stringstream ss;
00096     for (std::size_t i = 0 ; i < classes.size() ; ++i)
00097       ss << classes[i] << " ";
00098     ROS_ERROR_STREAM("Exception while loading planner '" << planner_plugin_name << "': " << ex.what() << std::endl
00099                      << "Available plugins: " << ss.str());
00100   }
00101 
00102   /* Sleep a little to allow time to startup rviz, etc. */
00103   ros::WallDuration sleep_time(8.0);
00104   sleep_time.sleep();
00105 
00106   /* CREATE A MOTION PLAN REQUEST FOR THE RIGHT ARM OF THE PR2 */
00107   /* We will ask the end-effector of the PR2 to go to a desired location */
00108   planning_interface::MotionPlanRequest req;
00109   planning_interface::MotionPlanResponse res;
00110 
00111   /* A desired pose */
00112   geometry_msgs::PoseStamped pose;
00113   pose.header.frame_id = "torso_lift_link";
00114   pose.pose.position.x = 0.75;
00115   pose.pose.position.y = 0.0;
00116   pose.pose.position.z = 0.0;
00117   pose.pose.orientation.w = 1.0;
00118 
00119   /* A desired tolerance */
00120   std::vector<double> tolerance_pose(3, 0.01);
00121   std::vector<double> tolerance_angle(3, 0.01);
00122 
00123   /*Create the request */
00124   req.group_name = "right_arm";
00125   moveit_msgs::Constraints pose_goal = kinematic_constraints::constructGoalConstraints("r_wrist_roll_link", pose, tolerance_pose, tolerance_angle);
00126   req.goal_constraints.push_back(pose_goal);
00127 
00128   /* Construct the planning context */
00129   planning_interface::PlanningContextPtr context = planner_instance->getPlanningContext(planning_scene, req, res.error_code_);
00130 
00131   /* CALL THE PLANNER */
00132   context->solve(res);
00133 
00134   /* Check that the planning was successful */
00135   if(res.error_code_.val != res.error_code_.SUCCESS)
00136   {
00137     ROS_ERROR("Could not compute plan successfully");
00138     return 0;
00139   }
00140 
00141   /* Visualize the generated plan */
00142   /* Publisher for display */
00143   ros::Publisher display_publisher = node_handle.advertise<moveit_msgs::DisplayTrajectory>("/move_group/display_planned_path", 1, true);
00144   moveit_msgs::DisplayTrajectory display_trajectory;
00145 
00146   /* Visualize the trajectory */
00147   ROS_INFO("Visualizing the trajectory");
00148   moveit_msgs::MotionPlanResponse response;
00149   res.getMessage(response);
00150 
00151   display_trajectory.trajectory_start = response.trajectory_start;
00152   display_trajectory.trajectory.push_back(response.trajectory);
00153   display_publisher.publish(display_trajectory);
00154 
00155   sleep_time.sleep();
00156 
00157   /* NOW TRY A JOINT SPACE GOAL */
00158   /* First, set the state in the planning scene to the final state of the last plan */
00159   robot_state::RobotState& robot_state = planning_scene->getCurrentStateNonConst();
00160   planning_scene->setCurrentState(response.trajectory_start);
00161   robot_state::JointStateGroup* joint_state_group = robot_state.getJointStateGroup("right_arm");
00162   joint_state_group->setVariableValues(response.trajectory.joint_trajectory.points.back().positions);
00163 
00164   /* Now, setup a joint space goal*/
00165   robot_state::RobotState goal_state(robot_model);
00166   robot_state::JointStateGroup* goal_group = goal_state.getJointStateGroup("right_arm");
00167   std::vector<double> joint_values(7, 0.0);
00168   joint_values[0] = -2.0;
00169   joint_values[3] = -0.2;
00170   joint_values[5] = -0.15;
00171   goal_group->setVariableValues(joint_values);
00172   moveit_msgs::Constraints joint_goal = kinematic_constraints::constructGoalConstraints(goal_group);
00173 
00174   req.goal_constraints.clear();
00175   req.goal_constraints.push_back(joint_goal);
00176 
00177   /* Construct the planning context */
00178   context = planner_instance->getPlanningContext(planning_scene, req, res.error_code_);
00179 
00180   /* Call the Planner */
00181   context->solve(res);
00182 
00183   /* Check that the planning was successful */
00184   if(res.error_code_.val != res.error_code_.SUCCESS)
00185   {
00186     ROS_ERROR("Could not compute plan successfully");
00187     return 0;
00188   }
00189 
00190   /* Visualize the trajectory */
00191   ROS_INFO("Visualizing the trajectory");
00192   res.getMessage(response);
00193 
00194   display_trajectory.trajectory_start = response.trajectory_start;
00195   display_trajectory.trajectory.push_back(response.trajectory);
00196   //Now you should see two planned trajectories in series
00197   display_publisher.publish(display_trajectory);
00198 
00199   /* Now, let's try to go back to the first goal*/
00200   /* First, set the state in the planning scene to the final state of the last plan */
00201   joint_state_group->setVariableValues(response.trajectory.joint_trajectory.points.back().positions);
00202 
00203   /* Now, we go back to the first goal*/
00204   req.goal_constraints.clear();
00205   req.goal_constraints.push_back(pose_goal);
00206   context = planner_instance->getPlanningContext(planning_scene, req, res.error_code_);
00207   context->solve(res);
00208   res.getMessage(response);
00209   display_trajectory.trajectory.push_back(response.trajectory);
00210   display_publisher.publish(display_trajectory);
00211 
00212   /* Let's create a new pose goal */
00213   pose.pose.position.x = 0.65;
00214   pose.pose.position.y = -0.2;
00215   pose.pose.position.z = -0.1;
00216   moveit_msgs::Constraints pose_goal_2 = kinematic_constraints::constructGoalConstraints("r_wrist_roll_link", pose, tolerance_pose, tolerance_angle);
00217 
00218   /* First, set the state in the planning scene to the final state of the last plan */
00219   joint_state_group->setVariableValues(response.trajectory.joint_trajectory.points.back().positions);
00220 
00221   /* Now, let's try to move to this new pose goal*/
00222   req.goal_constraints.clear();
00223   req.goal_constraints.push_back(pose_goal_2);
00224 
00225   /* But, let's impose a path constraint on the motion.
00226      Here, we are asking for the end-effector to stay level*/
00227   geometry_msgs::QuaternionStamped quaternion;
00228   quaternion.header.frame_id = "torso_lift_link";
00229   quaternion.quaternion.w = 1.0;
00230 
00231   req.path_constraints = kinematic_constraints::constructGoalConstraints("r_wrist_roll_link", quaternion);
00232 
00233   // imposing path constraints requires the planner to reason in the space of possible positions of the end-effector
00234   // (the workspace of the robot)
00235   // because of this, we need to specify a bound for the allowed planning volume as well;
00236   // Note: a default bound is automatically filled by the WorkspaceBounds request adapter (part of the OMPL pipeline,
00237   // but that is not being used in this example).
00238   // We use a bound that definitely includes the reachable space for the arm. This is fine because sampling is not done in this volume
00239   // when planning for the arm; the bounds are only used to determine if the sampled configurations are valid.
00240   req.workspace_parameters.min_corner.x = req.workspace_parameters.min_corner.y = req.workspace_parameters.min_corner.z = -2.0;
00241   req.workspace_parameters.max_corner.x = req.workspace_parameters.max_corner.y = req.workspace_parameters.max_corner.z =  2.0;
00242 
00243 
00244   context = planner_instance->getPlanningContext(planning_scene, req, res.error_code_);
00245   context->solve(res);
00246   res.getMessage(response);
00247   display_trajectory.trajectory.push_back(response.trajectory);
00248   //Now you should see four planned trajectories in series
00249   display_publisher.publish(display_trajectory);
00250 
00251   sleep_time.sleep();
00252   ROS_INFO("Done");
00253   planner_instance.reset();
00254 
00255   return 0;
00256 }


pr2_moveit_tutorials
Author(s): Sachin Chitta
autogenerated on Mon Oct 6 2014 11:15:31