place.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 * Software License Agreement (BSD License)
00003 *
00004 *  Copyright (c) 2012, Willow Garage, Inc.
00005 *  All rights reserved.
00006 *
00007 *  Redistribution and use in source and binary forms, with or without
00008 *  modification, are permitted provided that the following conditions
00009 *  are met:
00010 *
00011 *   * Redistributions of source code must retain the above copyright
00012 *     notice, this list of conditions and the following disclaimer.
00013 *   * Redistributions in binary form must reproduce the above
00014 *     copyright notice, this list of conditions and the following
00015 *     disclaimer in the documentation and/or other materials provided
00016 *     with the distribution.
00017 *   * Neither the name of the Willow Garage nor the names of its
00018 *     contributors may be used to endorse or promote products derived
00019 *     from this software without specific prior written permission.
00020 *
00021 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 *  POSSIBILITY OF SUCH DAMAGE.
00033 *********************************************************************/
00034 
00035 /* Author: Ioan Sucan */
00036 
00037 #include <moveit/pick_place/pick_place.h>
00038 #include <moveit/pick_place/reachable_valid_pose_filter.h>
00039 #include <moveit/pick_place/approach_and_translate_stage.h>
00040 #include <moveit/pick_place/plan_stage.h>
00041 #include <moveit/robot_state/conversions.h>
00042 #include <eigen_conversions/eigen_msg.h>
00043 #include <ros/console.h>
00044 
00045 namespace pick_place
00046 {
00047 
00048 PlacePlan::PlacePlan(const PickPlaceConstPtr &pick_place) : PickPlacePlanBase(pick_place, "place")
00049 {
00050 }
00051 
00052 bool PlacePlan::transformToEndEffectorGoal(const geometry_msgs::PoseStamped &goal_pose,
00053                        const robot_state::AttachedBody* attached_body,
00054                        geometry_msgs::PoseStamped &place_pose) const
00055 {
00056   const EigenSTL::vector_Affine3d& fixed_transforms = attached_body->getFixedTransforms();
00057   if (fixed_transforms.empty())
00058     return false;
00059   Eigen::Affine3d end_effector_transform;
00060   tf::poseMsgToEigen(goal_pose.pose, end_effector_transform);
00061   end_effector_transform = end_effector_transform * fixed_transforms[0].inverse();
00062   place_pose.header = goal_pose.header;
00063   tf::poseEigenToMsg(end_effector_transform, place_pose.pose);
00064   return true;
00065 }
00066 
00067 bool PlacePlan::plan(const planning_scene::PlanningSceneConstPtr &planning_scene, const moveit_msgs::PlaceGoal &goal)
00068 {
00069   double timeout = goal.allowed_planning_time;
00070   ros::WallTime endtime = ros::WallTime::now() + ros::WallDuration(timeout);
00071   std::string attached_object_name = goal.attached_object_name;
00072   const robot_model::JointModelGroup *jmg = NULL;
00073   const robot_model::JointModelGroup *eef = NULL;
00074 
00075   if (planning_scene->getRobotModel()->hasEndEffector(goal.group_name))
00076   {
00077     eef = planning_scene->getRobotModel()->getEndEffector(goal.group_name);
00078     if (eef)
00079     {
00080       const std::string &eef_parent = eef->getEndEffectorParentGroup().first;
00081       jmg = planning_scene->getRobotModel()->getJointModelGroup(eef_parent);
00082     }
00083   }
00084   else
00085   {
00086     jmg = planning_scene->getRobotModel()->getJointModelGroup(goal.group_name);
00087     if (jmg)
00088     {
00089       const std::vector<std::string> &eef_names = jmg->getAttachedEndEffectorNames();
00090       if (eef_names.size() == 1)
00091       {
00092         eef = planning_scene->getRobotModel()->getEndEffector(eef_names[0]);
00093       }
00094     }
00095   }
00096 
00097   if (!jmg)
00098   {
00099     error_code_.val = moveit_msgs::MoveItErrorCodes::INVALID_GROUP_NAME;
00100     return false;
00101   }
00102 
00103   // try to infer attached body name if possible
00104   int loop_count = 0;
00105   while (attached_object_name.empty() && loop_count < 2)
00106   {
00107     // in the first try, look for objects attached to the eef, if the eef is known;
00108     // otherwise, look for attached bodies in the planning group itself
00109     const std::vector<std::string> &links = loop_count == 0 ?
00110       (eef ? eef->getLinkModelNames() : jmg->getLinkModelNames()) : jmg->getLinkModelNames();
00111     // if we had no eef, there is no more looping to do, so we bump the loop count
00112     if (loop_count == 0 && !eef)
00113       loop_count++;
00114     loop_count++;
00115     for (std::size_t i = 0 ; i < links.size() ; ++i)
00116     {
00117       const robot_state::LinkState *ls = planning_scene->getCurrentState().getLinkState(links[i]);
00118       if (ls)
00119       {
00120         std::vector<const robot_state::AttachedBody*> attached_bodies;
00121         ls->getAttachedBodies(attached_bodies);
00122         if (attached_bodies.empty())
00123           continue;
00124         if (attached_bodies.size() > 1 || !attached_object_name.empty())
00125         {
00126           ROS_ERROR("Multiple attached bodies for group '%s' but no explicit attached object to place was specified", goal.group_name.c_str());
00127           error_code_.val = moveit_msgs::MoveItErrorCodes::INVALID_OBJECT_NAME;
00128           return false;
00129         }
00130         else
00131           attached_object_name = attached_bodies[0]->getName();
00132       }
00133     }
00134   }
00135 
00136   const robot_state::AttachedBody *attached_body = planning_scene->getCurrentState().getAttachedBody(attached_object_name);
00137   if (!attached_body)
00138   {
00139     ROS_ERROR("There is no object to detach");
00140     error_code_.val = moveit_msgs::MoveItErrorCodes::INVALID_OBJECT_NAME;
00141     return false;
00142   }
00143 
00144   ros::WallTime start_time = ros::WallTime::now();
00145 
00146   // construct common data for possible manipulation plans
00147   ManipulationPlanSharedDataPtr plan_data(new ManipulationPlanSharedData());
00148   ManipulationPlanSharedDataConstPtr const_plan_data = plan_data;
00149   plan_data->planning_group_ = jmg->getName();
00150   plan_data->end_effector_group_ = eef ? eef->getName() : "";
00151   plan_data->ik_link_name_ = eef ? eef->getEndEffectorParentGroup().second : "";
00152   plan_data->timeout_ = endtime;
00153   plan_data->path_constraints_ = goal.path_constraints;
00154   plan_data->planner_id_ = goal.planner_id;
00155   plan_data->minimize_object_distance_ = false;
00156   plan_data->max_goal_sampling_attempts_ = std::max(2u, jmg->getDefaultIKAttempts());
00157   moveit_msgs::AttachedCollisionObject &detach_object_msg = plan_data->diff_attached_object_;
00158 
00159   // construct the attached object message that will change the world to what it would become after a placement
00160   detach_object_msg.link_name = attached_body->getAttachedLinkName();
00161   detach_object_msg.object.id = attached_object_name;
00162   detach_object_msg.object.operation = moveit_msgs::CollisionObject::REMOVE;
00163 
00164   collision_detection::AllowedCollisionMatrixPtr approach_place_acm(new collision_detection::AllowedCollisionMatrix(planning_scene->getAllowedCollisionMatrix()));
00165 
00166   // we are allowed to touch certain other objects with the gripper
00167   approach_place_acm->setEntry(eef->getLinkModelNames(), goal.allowed_touch_objects, true);
00168 
00169   // we are allowed to touch the target object slightly while retreating the end effector
00170   std::vector<std::string> touch_links(attached_body->getTouchLinks().begin(), attached_body->getTouchLinks().end());
00171   approach_place_acm->setEntry(attached_object_name, touch_links, true);
00172 
00173   if (!goal.support_surface_name.empty())
00174   {
00175     // we are allowed to have contact between the target object and the support surface before the place
00176     approach_place_acm->setEntry(goal.support_surface_name, attached_object_name, true);
00177 
00178     // optionally, it may be allowed to touch the support surface with the gripper
00179     if (goal.allow_gripper_support_collision && eef)
00180       approach_place_acm->setEntry(goal.support_surface_name, eef->getLinkModelNames(), true);
00181   }
00182 
00183 
00184   // configure the manipulation pipeline
00185   pipeline_.reset();
00186 
00187   ManipulationStagePtr stage1(new ReachableAndValidPoseFilter(planning_scene, approach_place_acm, pick_place_->getConstraintsSamplerManager()));
00188   ManipulationStagePtr stage2(new ApproachAndTranslateStage(planning_scene, approach_place_acm));
00189   ManipulationStagePtr stage3(new PlanStage(planning_scene, pick_place_->getPlanningPipeline()));
00190   pipeline_.addStage(stage1).addStage(stage2).addStage(stage3);
00191 
00192   initialize();
00193 
00194   pipeline_.start();
00195 
00196   // add possible place locations
00197   for (std::size_t i = 0 ; i < goal.place_locations.size() ; ++i)
00198   {
00199     ManipulationPlanPtr p(new ManipulationPlan(const_plan_data));
00200     const manipulation_msgs::PlaceLocation &pl = goal.place_locations[i];
00201     // The goals are specified for the attached body
00202     // but we want to transform them into goals for the end-effector instead
00203     transformToEndEffectorGoal(pl.place_pose, attached_body, p->goal_pose_);
00204     p->approach_ = pl.approach;
00205     p->retreat_ = pl.retreat;
00206     p->retreat_posture_ = pl.post_place_posture;
00207     if (p->retreat_posture_.name.empty())
00208       p->retreat_posture_ = attached_body->getDetachPosture();
00209     pipeline_.push(p);
00210   }
00211   ROS_INFO("Added %d place locations", (int) goal.place_locations.size());
00212 
00213   // wait till we're done
00214   waitForPipeline(endtime);
00215 
00216   pipeline_.stop();
00217 
00218   last_plan_time_ = (ros::WallTime::now() - start_time).toSec();
00219 
00220   if (!getSuccessfulManipulationPlans().empty())
00221     error_code_.val = moveit_msgs::MoveItErrorCodes::SUCCESS;
00222   else
00223   {
00224     if (last_plan_time_ > timeout)
00225       error_code_.val = moveit_msgs::MoveItErrorCodes::TIMED_OUT;
00226     else
00227     {
00228       error_code_.val = moveit_msgs::MoveItErrorCodes::PLANNING_FAILED;
00229       if (goal.place_locations.size() > 0)
00230       {
00231         ROS_WARN("All supplied place locations failed. Retrying last location in verbose mode.");
00232         // everything failed. we now start the pipeline again in verbose mode for one grasp
00233         initialize();
00234         pipeline_.setVerbose(true);
00235         pipeline_.start();
00236         pipeline_.reprocessLastFailure();
00237         waitForPipeline(ros::WallTime::now() + ros::WallDuration(1.0));
00238         pipeline_.stop();
00239         pipeline_.setVerbose(false);
00240       }
00241     }
00242   }
00243   ROS_INFO("Place completed after %lf seconds", last_plan_time_);
00244 
00245   return error_code_.val == moveit_msgs::MoveItErrorCodes::SUCCESS;
00246 }
00247 
00248 PlacePlanPtr PickPlace::planPlace(const planning_scene::PlanningSceneConstPtr &planning_scene, const moveit_msgs::PlaceGoal &goal) const
00249 {
00250   PlacePlanPtr p(new PlacePlan(shared_from_this()));
00251   if (planning_scene::PlanningScene::isEmpty(goal.planning_options.planning_scene_diff))
00252     p->plan(planning_scene, goal);
00253   else
00254     p->plan(planning_scene->diff(goal.planning_options.planning_scene_diff), goal);
00255 
00256   if (display_computed_motion_plans_)
00257   {
00258     const std::vector<pick_place::ManipulationPlanPtr> &success = p->getSuccessfulManipulationPlans();
00259     if (!success.empty())
00260       visualizePlan(success.back());
00261   }
00262 
00263   if (display_grasps_)
00264   {
00265     const std::vector<pick_place::ManipulationPlanPtr> &success = p->getSuccessfulManipulationPlans();
00266     visualizeGrasps(success);
00267     const std::vector<pick_place::ManipulationPlanPtr> &failed = p->getFailedManipulationPlans();
00268     visualizeGrasps(failed);
00269   }
00270 
00271   return p;
00272 }
00273 
00274 }


manipulation
Author(s): Ioan Sucan , Sachin Chitta
autogenerated on Mon Oct 6 2014 02:33:06