planning_scene_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 <ros/ros.h>
00039 
00040 // MoveIt!
00041 #include <moveit/robot_model_loader/robot_model_loader.h>
00042 #include <moveit/planning_scene/planning_scene.h>
00043 
00044 #include <moveit/kinematic_constraints/utils.h>
00045 #include <eigen_conversions/eigen_msg.h>
00046 
00047 bool userCallback(const robot_state::RobotState &kinematic_state, bool verbose)
00048 {
00049   // get the joint value for the right shoulder pan of the PR2 robot
00050   const std::vector<double>& joint_state_values = kinematic_state.getJointState("r_shoulder_pan_joint")->getVariableValues();
00051   return (joint_state_values.front() > 0.0);
00052 }
00053 
00054 int main(int argc, char **argv)
00055 {
00056   ros::init (argc, argv, "right_arm_kinematics");
00057   ros::AsyncSpinner spinner(1);
00058   spinner.start();
00059 
00060   /* Load the robot model */
00061   robot_model_loader::RobotModelLoader robot_model_loader("robot_description");
00062 
00063   /* Get a shared pointer to the model */
00064   robot_model::RobotModelPtr kinematic_model = robot_model_loader.getModel();
00065 
00066   /* Construct a planning scene - NOTE: this is for illustration purposes only.
00067      The recommended way to construct a planning scene is to use the planning_scene_monitor
00068      to construct it for you.*/
00069   planning_scene::PlanningScene planning_scene(kinematic_model);
00070 
00071   /* The planning scene contains a RobotState *representation of the robot configuration
00072    We can get a reference to it.*/
00073   robot_state::RobotState& current_state = planning_scene.getCurrentStateNonConst();
00074 
00075   /* COLLISION CHECKING */
00076   /* Let's check if the current state is in self-collision. All self-collision checks use an unpadded version of the
00077      robot collision model, i.e. no extra padding is applied to the robot.*/
00078   collision_detection::CollisionRequest collision_request;
00079   collision_detection::CollisionResult collision_result;
00080   planning_scene.checkSelfCollision(collision_request, collision_result);
00081   ROS_INFO_STREAM("Test 1 : Current state is " << (collision_result.collision ? "in" : "not in") << " self collision");
00082 
00083   /* Let's change the current state that the planning scene has and check if that is in self-collision*/
00084   current_state.setToRandomValues();
00085   collision_result.clear();
00086   planning_scene.checkSelfCollision(collision_request, collision_result);
00087   ROS_INFO_STREAM("Test 2 : Current state is " << (collision_result.collision ? "in" : "not in") << " self collision");
00088 
00089   /* Now, we will do collision checking only for the right_arm of the PR2, i.e. we will check whether
00090    there are any collisions between the right arm and other parts of the body of the robot.*/
00091   collision_request.group_name = "right_arm";
00092   current_state.setToRandomValues();
00093   collision_result.clear();
00094   planning_scene.checkSelfCollision(collision_request, collision_result);
00095   ROS_INFO_STREAM("Test 3: Current state is " << (collision_result.collision ? "in" : "not in") << " self collision");
00096 
00097   /* We will first manually set the right arm to a position where we know internal (self) collisions
00098      do happen.*/
00099   std::vector<double> joint_values;
00100   robot_state::JointStateGroup* joint_state_group = current_state.getJointStateGroup("right_arm");
00101   joint_state_group->getVariableValues(joint_values);
00102   joint_values[0] = 1.57; //hard-coded since we know collisions will happen here
00103   joint_state_group->setVariableValues(joint_values);
00104   /* Note that this state is now actually outside the joint limits of the PR2, which we can also check for
00105      directly.*/
00106   ROS_INFO_STREAM("Current state is " << (current_state.satisfiesBounds() ? "valid" : "not valid"));
00107 
00108   /* Now, we will try and get contact information for any collisions that
00109      might have happened at a given configuration of the right arm. */
00110   collision_request.contacts = true;
00111   collision_request.max_contacts = 1000;
00112 
00113   collision_result.clear();
00114   planning_scene.checkSelfCollision(collision_request, collision_result);
00115   ROS_INFO_STREAM("Test 4: Current state is " << (collision_result.collision ? "in" : "not in") << " self collision");
00116   for(collision_detection::CollisionResult::ContactMap::const_iterator it = collision_result.contacts.begin();
00117       it != collision_result.contacts.end();
00118       ++it)
00119   {
00120     ROS_INFO("Contact between: %s and %s", it->first.first.c_str(), it->first.second.c_str());
00121   }
00122 
00123   /* We will pass in a changed collision matrix to allow the particular set of contacts that just happened*/
00124   collision_detection::AllowedCollisionMatrix acm = planning_scene.getAllowedCollisionMatrix();
00125   robot_state::RobotState copied_state = planning_scene.getCurrentState();
00126 
00127   for(collision_detection::CollisionResult::ContactMap::const_iterator it = collision_result.contacts.begin();
00128       it != collision_result.contacts.end();
00129       ++it)
00130   {
00131     acm.setEntry(it->first.first, it->first.second, true);
00132   }
00133   collision_result.clear();
00134   planning_scene.checkSelfCollision(collision_request, collision_result, copied_state, acm);
00135   ROS_INFO_STREAM("Test 5: Current state is " << (collision_result.collision ? "in" : "not in") << " self collision");
00136 
00137   /* While we have been checking for self-collisions, we can use the checkCollision functions instead which will
00138      check for both self-collisions and for collisions with the environment (which is currently empty).
00139      This is the set of collision checking functions that you will use most often in a planner. Note that collision checks
00140      with the environment will use the padded version of the robot. Padding helps in keeping the robot further away from
00141      obstacles in the environment.*/
00142   collision_result.clear();
00143   planning_scene.checkCollision(collision_request, collision_result, copied_state, acm);
00144   ROS_INFO_STREAM("Test 6: Current state is " << (collision_result.collision ? "in" : "not in") << " self collision");
00145 
00146 
00147   /* CONSTRAINT CHECKING*/
00148   /* Let's first create a constraint for the end-effector of the right arm of the PR2 */
00149   const robot_model::JointModelGroup* joint_model_group = kinematic_model->getJointModelGroup("right_arm");
00150   std::string end_effector_name = joint_model_group->getLinkModelNames().back();
00151 
00152   geometry_msgs::PoseStamped desired_pose;
00153   desired_pose.pose.orientation.w = 1.0;
00154   desired_pose.pose.position.x = 0.75;
00155   desired_pose.pose.position.y = -0.185;
00156   desired_pose.pose.position.z = 1.3;
00157   desired_pose.header.frame_id = "base_footprint";
00158 
00159   moveit_msgs::Constraints goal_constraint = kinematic_constraints::constructGoalConstraints(end_effector_name, desired_pose);
00160 
00161   /* Now, we can directly check it for a state using the PlanningScene class*/
00162   copied_state.setToRandomValues();
00163   bool state_constrained = planning_scene.isStateConstrained(copied_state, goal_constraint);
00164   ROS_INFO_STREAM("Test 7: Random state is " << (state_constrained ? "constrained" : "not constrained"));
00165 
00166   /* There's a more efficient way of checking constraints (when you want to check the same constraint over
00167      and over again, e.g. inside a planner). We first construct a KinematicConstraintSet which pre-processes
00168      the ROS Constraints messages and sets it up for quick processing. */
00169   kinematic_constraints::KinematicConstraintSet kinematic_constraint_set(kinematic_model);
00170   kinematic_constraint_set.add(goal_constraint, planning_scene.getTransforms());
00171 
00172   bool state_constrained_2 = planning_scene.isStateConstrained(copied_state, kinematic_constraint_set);
00173   ROS_INFO_STREAM("Test 8: Random state is " << (state_constrained_2 ? "constrained" : "not constrained"));
00174 
00175   /* There's an even more efficient way to do this using the KinematicConstraintSet class directly.*/
00176   kinematic_constraints::ConstraintEvaluationResult constraint_eval_result = kinematic_constraint_set.decide(copied_state);
00177   ROS_INFO_STREAM("Test 9: Random state is " << (constraint_eval_result.satisfied ? "constrained" : "not constrained"));
00178 
00179   /* Now, lets try a user-defined callback. This is done by specifying the callback using the
00180      setStateFeasibilityPredicate function to which you pass the desired callback.
00181      Now, whenever anyone calls isStateFeasible, the callback will be checked.*/
00182   planning_scene.setStateFeasibilityPredicate(userCallback);
00183   bool state_feasible = planning_scene.isStateFeasible(copied_state);
00184   ROS_INFO_STREAM("Test 10: Random state is " << (state_feasible ? "feasible" : "not feasible"));
00185 
00186   /* Whenever anyone calls isStateValid, three checks are conducted: (a) collision checking (b) constraint checking and
00187      (c) feasibility checking using the user-defined callback */
00188   bool state_valid = planning_scene.isStateValid(copied_state, kinematic_constraint_set, "right_arm");
00189   ROS_INFO_STREAM("Test 10: Random state is " << (state_valid ? "valid" : "not valid"));
00190 
00191   ros::shutdown();
00192   return 0;
00193 }


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