planning_scene.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2011, 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/planning_scene/planning_scene.h>
00038 #include <moveit/collision_detection_fcl/collision_detector_allocator_fcl.h>
00039 #include <geometric_shapes/shape_operations.h>
00040 #include <moveit/collision_detection/collision_tools.h>
00041 #include <moveit/trajectory_processing/trajectory_tools.h>
00042 #include <moveit/robot_state/conversions.h>
00043 #include <moveit/exceptions/exceptions.h>
00044 #include <octomap_msgs/conversions.h>
00045 #include <eigen_conversions/eigen_msg.h>
00046 #include <set>
00047 
00048 namespace planning_scene
00049 {
00050 const std::string PlanningScene::COLLISION_MAP_NS = "<collision_map>";
00051 const std::string PlanningScene::OCTOMAP_NS = "<octomap>";
00052 const std::string PlanningScene::DEFAULT_SCENE_NAME = "(noname)";
00053 
00054 class SceneTransforms : public robot_state::Transforms
00055 {
00056 public:
00057   SceneTransforms(const PlanningScene *scene) :
00058     Transforms(scene->getRobotModel()->getModelFrame()),
00059     scene_(scene)
00060   {
00061   }
00062 
00063   virtual bool canTransform(const std::string &from_frame) const
00064   {
00065     return scene_->knowsFrameTransform(from_frame);
00066   }
00067 
00068   virtual bool isFixedFrame(const std::string &frame) const
00069   {
00070     if (frame.empty())
00071       return false;
00072     if (Transforms::isFixedFrame(frame))
00073       return true;
00074     if (frame[0] == '/')
00075       return knowsObject(frame.substr(1));
00076     else
00077       return knowsObject(frame);
00078   }
00079 
00080   virtual const Eigen::Affine3d& getTransform(const std::string &from_frame) const
00081   {  // the call below also calls Transforms::getTransform() too
00082     return scene_->getFrameTransform(from_frame);
00083   }
00084 
00085 private:
00086 
00087   bool knowsObject(const std::string &id) const
00088   {
00089     if (scene_->getWorld()->hasObject(id))
00090     {
00091       collision_detection::World::ObjectConstPtr obj = scene_->getWorld()->getObject(id);
00092       return obj->shape_poses_.size() == 1;
00093     }
00094     return false;
00095   }
00096 
00097   const PlanningScene *scene_;
00098 };
00099 
00100 }
00101 
00102 bool planning_scene::PlanningScene::isEmpty(const moveit_msgs::PlanningScene &msg)
00103 {
00104   return msg.name.empty() && msg.fixed_frame_transforms.empty() && msg.allowed_collision_matrix.entry_names.empty() &&
00105     msg.link_padding.empty() && msg.link_scale.empty() && isEmpty(msg.robot_state) && isEmpty(msg.world);
00106 }
00107 
00108 bool planning_scene::PlanningScene::isEmpty(const moveit_msgs::RobotState &msg)
00109 {
00110   return msg.multi_dof_joint_state.joint_names.empty() && msg.joint_state.name.empty() && msg.attached_collision_objects.empty();
00111 }
00112 
00113 bool planning_scene::PlanningScene::isEmpty(const moveit_msgs::PlanningSceneWorld &msg)
00114 {
00115   return msg.collision_objects.empty() && msg.octomap.octomap.data.empty() && msg.collision_map.boxes.empty();
00116 }
00117 
00118 planning_scene::PlanningScene::PlanningScene(const robot_model::RobotModelPtr &robot_model,
00119                                              collision_detection::WorldPtr world) :
00120   kmodel_(robot_model),
00121   world_(world),
00122   world_const_(world)
00123 {
00124   initialize();
00125 }
00126 
00127 planning_scene::PlanningScene::PlanningScene(const boost::shared_ptr<const urdf::ModelInterface> &urdf_model,
00128                                              const boost::shared_ptr<const srdf::Model> &srdf_model,
00129                                              collision_detection::WorldPtr world) :
00130   world_(world),
00131   world_const_(world)
00132 {
00133   if (!urdf_model)
00134     throw moveit::ConstructException("The URDF model cannot be NULL");
00135 
00136   if (!srdf_model)
00137     throw moveit::ConstructException("The SRDF model cannot be NULL");
00138 
00139   kmodel_ = createRobotModel(urdf_model, srdf_model);
00140   if (!kmodel_)
00141     throw moveit::ConstructException("Could not create RobotModel");
00142 
00143   initialize();
00144 }
00145 
00146 planning_scene::PlanningScene::~PlanningScene()
00147 {
00148   if (current_world_object_update_callback_)
00149     world_->removeObserver(current_world_object_update_observer_handle_);
00150 }
00151 
00152 void planning_scene::PlanningScene::initialize()
00153 {
00154   name_ = DEFAULT_SCENE_NAME;
00155 
00156   ftf_.reset(new SceneTransforms(this));
00157 
00158   kstate_.reset(new robot_state::RobotState(kmodel_));
00159   kstate_->setToDefaultValues();
00160 
00161   acm_.reset(new collision_detection::AllowedCollisionMatrix());
00162   // Use default collision operations in the SRDF to setup the acm
00163   const std::vector<std::string>& collision_links = kmodel_->getLinkModelNamesWithCollisionGeometry();
00164   acm_->setEntry(collision_links, collision_links, false);
00165 
00166   // allow collisions for pairs that have been disabled
00167   const std::vector<srdf::Model::DisabledCollision> &dc = getRobotModel()->getSRDF()->getDisabledCollisionPairs();
00168   for (std::vector<srdf::Model::DisabledCollision>::const_iterator it = dc.begin(); it != dc.end(); ++it)
00169     acm_->setEntry(it->link1_, it->link2_, true);
00170 
00171   setActiveCollisionDetector(collision_detection::CollisionDetectorAllocatorFCL::create());
00172 }
00173 
00174 /* return NULL on failure */
00175 robot_model::RobotModelPtr planning_scene::PlanningScene::createRobotModel(const boost::shared_ptr<const urdf::ModelInterface> &urdf_model,
00176                                                                            const boost::shared_ptr<const srdf::Model> &srdf_model)
00177 {
00178   robot_model::RobotModelPtr robot_model(new robot_model::RobotModel(urdf_model, srdf_model));
00179   if (!robot_model || !robot_model->getRoot())
00180     return robot_model::RobotModelPtr();
00181 
00182   return robot_model;
00183 }
00184 
00185 planning_scene::PlanningScene::PlanningScene(const PlanningSceneConstPtr &parent) :
00186   parent_(parent)
00187 {
00188   if (!parent_)
00189     throw moveit::ConstructException("NULL parent pointer for planning scene");
00190 
00191   if (!parent_->getName().empty())
00192     name_ = parent_->getName() + "+";
00193 
00194   kmodel_ = parent_->kmodel_;
00195 
00196   // maintain a separate world.  Copy on write ensures that most of the object
00197   // info is shared until it is modified.
00198   world_.reset(new collision_detection::World(*parent_->world_));
00199   world_const_ = world_;
00200 
00201   // record changes to the world
00202   world_diff_.reset(new collision_detection::WorldDiff(world_));
00203 
00204   // Set up the same collision detectors as the parent
00205   for (CollisionDetectorConstIterator it = parent_->collision_.begin() ;
00206        it != parent_->collision_.end() ;
00207        ++it)
00208   {
00209     const CollisionDetectorPtr& parent_detector = it->second;
00210     CollisionDetectorPtr& detector = collision_[it->first];
00211     detector.reset(new CollisionDetector());
00212     detector->alloc_ = parent_detector->alloc_;
00213     detector->parent_ = parent_detector;
00214 
00215     detector->cworld_ = detector->alloc_->allocateWorld(parent_detector->cworld_, world_);
00216     detector->cworld_const_ = detector->cworld_;
00217 
00218     // leave these empty and use parent collision_robot_ unless/until a non-const one
00219     // is requested (e.g. to modify link padding or scale)
00220     detector->crobot_.reset();
00221     detector->crobot_const_.reset();
00222     detector->crobot_unpadded_.reset();
00223     detector->crobot_unpadded_const_.reset();
00224   }
00225   setActiveCollisionDetector(parent_->getActiveCollisionDetectorName());
00226 }
00227 
00228 planning_scene::PlanningScenePtr planning_scene::PlanningScene::clone(const planning_scene::PlanningSceneConstPtr &scene)
00229 {
00230   PlanningScenePtr result = scene->diff();
00231   result->decoupleParent();
00232   result->setName(scene->getName());
00233   return result;
00234 }
00235 
00236 planning_scene::PlanningScenePtr planning_scene::PlanningScene::diff() const
00237 {
00238   return PlanningScenePtr(new PlanningScene(shared_from_this()));
00239 }
00240 
00241 planning_scene::PlanningScenePtr planning_scene::PlanningScene::diff(const moveit_msgs::PlanningScene &msg) const
00242 {
00243   planning_scene::PlanningScenePtr result = diff();
00244   result->setPlanningSceneDiffMsg(msg);
00245   return result;
00246 }
00247 
00248 void planning_scene::PlanningScene::CollisionDetector::copyPadding(const planning_scene::PlanningScene::CollisionDetector& src)
00249 {
00250   if (!crobot_)
00251   {
00252     alloc_->allocateRobot(parent_->getCollisionRobot());
00253     crobot_const_ = crobot_;
00254   }
00255 
00256   crobot_->setLinkPadding(src.getCollisionRobot()->getLinkPadding());
00257   crobot_->setLinkScale(src.getCollisionRobot()->getLinkScale());
00258 }
00259 
00260 void planning_scene::PlanningScene::propogateRobotPadding()
00261 {
00262   if (!active_collision_->crobot_)
00263     return;
00264 
00265   for (CollisionDetectorIterator it = collision_.begin() ; it != collision_.end() ; ++it)
00266   {
00267     if (it->second != active_collision_)
00268       it->second->copyPadding(*active_collision_);
00269   }
00270 }
00271 
00272 void planning_scene::PlanningScene::CollisionDetector::findParent(const PlanningScene& scene)
00273 {
00274   if (parent_ || !scene.parent_)
00275     return;
00276 
00277   CollisionDetectorConstIterator it = scene.parent_->collision_.find(alloc_->getName());
00278   if (it != scene.parent_->collision_.end())
00279     parent_ = it->second->parent_;
00280 }
00281 
00282 void planning_scene::PlanningScene::addCollisionDetector(const collision_detection::CollisionDetectorAllocatorPtr& allocator)
00283 {
00284   const std::string& name = allocator->getName();
00285   CollisionDetectorPtr& detector = collision_[name];
00286 
00287   if (detector)  // already added this one
00288     return;
00289 
00290   detector.reset(new CollisionDetector());
00291 
00292   detector->alloc_ = allocator;
00293 
00294   if (!active_collision_)
00295     active_collision_ = detector;
00296 
00297   detector->findParent(*this);
00298 
00299   detector->cworld_ = detector->alloc_->allocateWorld(world_);
00300   detector->cworld_const_ = detector->cworld_;
00301 
00302   // Allocate CollisionRobot unless we can use the parent's crobot_.
00303   // If active_collision_->crobot_ is non-NULL there is local padding and we cannot use the parent's crobot_.
00304   if (!detector->parent_ || active_collision_->crobot_)
00305   {
00306     detector->crobot_ = detector->alloc_->allocateRobot(getRobotModel());
00307     detector->crobot_const_ = detector->crobot_;
00308 
00309     if (detector != active_collision_)
00310       detector->copyPadding(*active_collision_);
00311   }
00312 
00313   // Allocate CollisionRobot unless we can use the parent's crobot_unpadded_.
00314   if (!detector->parent_)
00315   {
00316     detector->crobot_unpadded_ = detector->alloc_->allocateRobot(getRobotModel());
00317     detector->crobot_unpadded_const_ = detector->crobot_unpadded_;
00318   }
00319 }
00320 
00321 void planning_scene::PlanningScene::setActiveCollisionDetector(const collision_detection::CollisionDetectorAllocatorPtr& allocator,
00322                                                                bool exclusive)
00323 {
00324   if (exclusive)
00325   {
00326     CollisionDetectorPtr p;
00327     CollisionDetectorIterator it = collision_.find(allocator->getName());
00328     if (it != collision_.end())
00329       p = it->second;
00330 
00331     collision_.clear();
00332     active_collision_.reset();
00333 
00334     if (p)
00335     {
00336       collision_[allocator->getName()] = p;
00337       active_collision_ = p;
00338       return;
00339     }
00340   }
00341 
00342   addCollisionDetector(allocator);
00343   setActiveCollisionDetector(allocator->getName());
00344 }
00345 
00346 
00347 bool planning_scene::PlanningScene::setActiveCollisionDetector(const std::string& collision_detector_name)
00348 {
00349   CollisionDetectorIterator it = collision_.find(collision_detector_name);
00350   if (it != collision_.end())
00351   {
00352     active_collision_ = it->second;
00353     return true;
00354   }
00355   else
00356   {
00357     logError("Cannot setActiveCollisionDetector to '%s' -- it has been added to PlanningScene.  Keeping existing active collision detector '%s'",
00358       collision_detector_name.c_str(),
00359       active_collision_->alloc_->getName().c_str());
00360     return false;
00361   }
00362 }
00363 
00364 void planning_scene::PlanningScene::getCollisionDetectorNames(std::vector<std::string>& names) const
00365 {
00366   names.clear();
00367   names.reserve(collision_.size());
00368   for (CollisionDetectorConstIterator it = collision_.begin() ; it != collision_.end() ; ++it)
00369     names.push_back(it->first);
00370 }
00371 
00372 const collision_detection::CollisionWorldConstPtr& planning_scene::PlanningScene::getCollisionWorld(
00373       const std::string& collision_detector_name) const
00374 {
00375   CollisionDetectorConstIterator it = collision_.find(collision_detector_name);
00376   if (it == collision_.end())
00377   {
00378     logError("Could not get CollisionWorld named '%s'.  Returning active CollisionWorld '%s' instead",
00379       collision_detector_name.c_str(),
00380       active_collision_->alloc_->getName().c_str());
00381     return active_collision_->cworld_const_;
00382   }
00383 
00384   return it->second->cworld_const_;
00385 }
00386 
00387 const collision_detection::CollisionRobotConstPtr& planning_scene::PlanningScene::getCollisionRobot(
00388       const std::string& collision_detector_name) const
00389 {
00390   CollisionDetectorConstIterator it = collision_.find(collision_detector_name);
00391   if (it == collision_.end())
00392   {
00393     logError("Could not get CollisionRobot named '%s'.  Returning active CollisionRobot '%s' instead",
00394       collision_detector_name.c_str(),
00395       active_collision_->alloc_->getName().c_str());
00396     return active_collision_->getCollisionRobot();
00397   }
00398 
00399   return it->second->getCollisionRobot();
00400 }
00401 
00402 const collision_detection::CollisionRobotConstPtr& planning_scene::PlanningScene::getCollisionRobotUnpadded(
00403       const std::string& collision_detector_name) const
00404 {
00405   CollisionDetectorConstIterator it = collision_.find(collision_detector_name);
00406   if (it == collision_.end())
00407   {
00408     logError("Could not get CollisionRobotUnpadded named '%s'.  Returning active CollisionRobotUnpadded '%s' instead",
00409       collision_detector_name.c_str(),
00410       active_collision_->alloc_->getName().c_str());
00411     return active_collision_->getCollisionRobotUnpadded();
00412   }
00413 
00414   return it->second->getCollisionRobotUnpadded();
00415 }
00416 
00417 
00418 void planning_scene::PlanningScene::clearDiffs()
00419 {
00420   if (!parent_)
00421     return;
00422 
00423   // clear everything, reset the world, record diffs
00424   world_.reset(new collision_detection::World(*parent_->world_));
00425   world_const_ = world_;
00426   world_diff_.reset(new collision_detection::WorldDiff(world_));
00427   if (current_world_object_update_callback_)
00428     current_world_object_update_observer_handle_ = world_->addObserver(current_world_object_update_callback_);
00429 
00430   // use parent crobot_ if it exists.  Otherwise copy padding from parent.
00431   for (CollisionDetectorIterator it = collision_.begin() ; it != collision_.end() ; ++it)
00432   {
00433     if (!it->second->parent_)
00434       it->second->findParent(*this);
00435 
00436     if (it->second->parent_)
00437     {
00438       it->second->crobot_.reset();
00439       it->second->crobot_const_.reset();
00440       it->second->crobot_unpadded_.reset();
00441       it->second->crobot_unpadded_const_.reset();
00442 
00443       it->second->cworld_ = it->second->alloc_->allocateWorld(it->second->parent_->cworld_, world_);
00444       it->second->cworld_const_ = it->second->cworld_;
00445     }
00446     else
00447     {
00448       it->second->copyPadding(*parent_->active_collision_);
00449 
00450       it->second->cworld_ = it->second->alloc_->allocateWorld(world_);
00451       it->second->cworld_const_ = it->second->cworld_;
00452     }
00453   }
00454 
00455   ftf_.reset();
00456   kstate_.reset();
00457   acm_.reset();
00458   object_colors_.reset();
00459   object_types_.reset();
00460 }
00461 
00462 void planning_scene::PlanningScene::pushDiffs(const PlanningScenePtr &scene)
00463 {
00464   if (!parent_)
00465     return;
00466 
00467   if (ftf_)
00468     scene->getTransformsNonConst().setAllTransforms(ftf_->getAllTransforms());
00469 
00470   if (kstate_)
00471     scene->getCurrentStateNonConst() = *kstate_;
00472 
00473   if (acm_)
00474     scene->getAllowedCollisionMatrixNonConst() = *acm_;
00475 
00476   if (active_collision_->crobot_)
00477   {
00478     collision_detection::CollisionRobotPtr active_crobot = scene->getCollisionRobotNonConst();
00479     active_crobot->setLinkPadding(active_collision_->crobot_->getLinkPadding());
00480     active_crobot->setLinkScale(active_collision_->crobot_->getLinkScale());
00481     scene->propogateRobotPadding();
00482   }
00483 
00484   if (world_diff_)
00485   {
00486     for (collision_detection::WorldDiff::const_iterator it = world_diff_->begin() ; it != world_diff_->end() ; ++it)
00487     {
00488       if (it->second == collision_detection::World::DESTROY)
00489       {
00490         scene->world_->removeObject(it->first);
00491         scene->removeObjectColor(it->first);
00492       }
00493       else
00494       {
00495         const collision_detection::World::Object& obj = *world_->getObject(it->first);
00496         scene->world_->removeObject(obj.id_);
00497         scene->world_->addToObject(obj.id_, obj.shapes_, obj.shape_poses_);
00498         if (hasObjectColor(it->first))
00499           scene->setObjectColor(it->first, getObjectColor(it->first));
00500         if (hasObjectType(it->first))
00501           scene->setObjectType(it->first, getObjectType(it->first));
00502       }
00503     }
00504   }
00505 }
00506 
00507 double planning_scene::PlanningScene::distanceToCollisionUnpadded(const robot_state::RobotState &kstate) const
00508 {
00509   return getCollisionWorld()->distanceRobot(*getCollisionRobotUnpadded(), kstate);
00510 }
00511 
00512 double planning_scene::PlanningScene::distanceToCollisionUnpadded(const robot_state::RobotState &kstate, const collision_detection::AllowedCollisionMatrix& acm) const
00513 {
00514   return getCollisionWorld()->distanceRobot(*getCollisionRobotUnpadded(), kstate, acm);
00515 }
00516 
00517 double planning_scene::PlanningScene::distanceToCollision(const robot_state::RobotState &kstate) const
00518 {
00519   return getCollisionWorld()->distanceRobot(*getCollisionRobot(), kstate);
00520 }
00521 
00522 double planning_scene::PlanningScene::distanceToCollision(const robot_state::RobotState &kstate, const collision_detection::AllowedCollisionMatrix& acm) const
00523 {
00524   return getCollisionWorld()->distanceRobot(*getCollisionRobot(), kstate, acm);
00525 }
00526 
00527 void planning_scene::PlanningScene::checkCollision(const collision_detection::CollisionRequest& req, collision_detection::CollisionResult &res) const
00528 {
00529   checkCollision(req, res, getCurrentState());
00530 }
00531 
00532 void planning_scene::PlanningScene::checkSelfCollision(const collision_detection::CollisionRequest& req, collision_detection::CollisionResult &res) const
00533 {
00534   checkSelfCollision(req, res, getCurrentState());
00535 }
00536 
00537 void planning_scene::PlanningScene::checkCollision(const collision_detection::CollisionRequest& req, collision_detection::CollisionResult &res,
00538                                                    const robot_state::RobotState &kstate) const
00539 {
00540   // check collision with the world using the padded version
00541   getCollisionWorld()->checkRobotCollision(req, res, *getCollisionRobot(), kstate, getAllowedCollisionMatrix());
00542 
00543   if (!res.collision || (req.contacts && res.contacts.size() < req.max_contacts))
00544   {
00545     // do self-collision checking with the unpadded version of the robot
00546     getCollisionRobotUnpadded()->checkSelfCollision(req, res, kstate, getAllowedCollisionMatrix());
00547   }
00548 }
00549 
00550 void planning_scene::PlanningScene::checkSelfCollision(const collision_detection::CollisionRequest& req, collision_detection::CollisionResult &res,
00551                                                        const robot_state::RobotState &kstate) const
00552 {
00553   // do self-collision checking with the unpadded version of the robot
00554   getCollisionRobotUnpadded()->checkSelfCollision(req, res, kstate, getAllowedCollisionMatrix());
00555 }
00556 
00557 void planning_scene::PlanningScene::checkCollision(const collision_detection::CollisionRequest& req,
00558                                                    collision_detection::CollisionResult &res,
00559                                                    const robot_state::RobotState &kstate,
00560                                                    const collision_detection::AllowedCollisionMatrix& acm) const
00561 {
00562   // check collision with the world using the padded version
00563   getCollisionWorld()->checkRobotCollision(req, res, *getCollisionRobot(), kstate, acm);
00564 
00565   // do self-collision checking with the unpadded version of the robot
00566   if (!res.collision || (req.contacts && res.contacts.size() < req.max_contacts))
00567     getCollisionRobotUnpadded()->checkSelfCollision(req, res, kstate, acm);
00568 }
00569 
00570 void planning_scene::PlanningScene::checkCollisionUnpadded(const collision_detection::CollisionRequest& req,
00571                                                            collision_detection::CollisionResult &res) const
00572 {
00573   return checkCollisionUnpadded(req, res, getCurrentState(), getAllowedCollisionMatrix());
00574 }
00575 
00576 void planning_scene::PlanningScene::checkCollisionUnpadded(const collision_detection::CollisionRequest& req,
00577                                                            collision_detection::CollisionResult &res,
00578                                                            const robot_state::RobotState &kstate) const
00579 {
00580   return checkCollisionUnpadded(req, res, kstate, getAllowedCollisionMatrix());
00581 }
00582 
00583 void planning_scene::PlanningScene::checkCollisionUnpadded(const collision_detection::CollisionRequest& req,
00584                                                            collision_detection::CollisionResult &res,
00585                                                            const robot_state::RobotState &kstate,
00586                                                            const collision_detection::AllowedCollisionMatrix& acm) const
00587 {
00588   // check collision with the world using the padded version
00589   getCollisionWorld()->checkRobotCollision(req, res, *getCollisionRobotUnpadded(), kstate, acm);
00590 
00591   // do self-collision checking with the unpadded version of the robot
00592   if (!res.collision || (req.contacts && res.contacts.size() < req.max_contacts))
00593   {
00594     getCollisionRobotUnpadded()->checkSelfCollision(req, res, kstate, acm);
00595   }
00596 }
00597 
00598 void planning_scene::PlanningScene::checkSelfCollision(const collision_detection::CollisionRequest& req,
00599                                                        collision_detection::CollisionResult &res,
00600                                                        const robot_state::RobotState &kstate,
00601                                                        const collision_detection::AllowedCollisionMatrix& acm) const
00602 {
00603   // do self-collision checking with the unpadded version of the robot
00604   getCollisionRobotUnpadded()->checkSelfCollision(req, res, kstate, acm);
00605 }
00606 
00607 void planning_scene::PlanningScene::getCollidingLinks(std::vector<std::string> &links) const
00608 {
00609   getCollidingLinks(links, getCurrentState());
00610 }
00611 
00612 
00613 void planning_scene::PlanningScene::getCollidingLinks(std::vector<std::string> &links,
00614                                                       const robot_state::RobotState &kstate) const
00615 {
00616   getCollidingLinks(links, kstate, getAllowedCollisionMatrix());
00617 }
00618 
00619 
00620 void planning_scene::PlanningScene::getCollidingLinks(std::vector<std::string> &links,
00621                                                       const robot_state::RobotState &kstate,
00622                                                       const collision_detection::AllowedCollisionMatrix& acm) const
00623 {
00624   collision_detection::CollisionRequest req;
00625   req.contacts = true;
00626   req.max_contacts = getRobotModel()->getLinkModelsWithCollisionGeometry().size() + 1;
00627   req.max_contacts_per_pair = 1;
00628   collision_detection::CollisionResult res;
00629   checkCollision(req, res, kstate, acm);
00630   links.clear();
00631   for (collision_detection::CollisionResult::ContactMap::const_iterator it = res.contacts.begin() ; it != res.contacts.end() ; ++it)
00632     for (std::size_t j = 0 ; j < it->second.size() ; ++j)
00633     {
00634       if (it->second[j].body_type_1 == collision_detection::BodyTypes::ROBOT_LINK)
00635         links.push_back(it->second[j].body_name_1);
00636       if (it->second[j].body_type_2 == collision_detection::BodyTypes::ROBOT_LINK)
00637         links.push_back(it->second[j].body_name_2);
00638     }
00639 }
00640 
00641 const collision_detection::CollisionRobotPtr& planning_scene::PlanningScene::getCollisionRobotNonConst()
00642 {
00643   if (!active_collision_->crobot_)
00644   {
00645     active_collision_->crobot_ = active_collision_->alloc_->allocateRobot(active_collision_->parent_->getCollisionRobot());
00646     active_collision_->crobot_const_ = active_collision_->crobot_;
00647   }
00648   return active_collision_->crobot_;
00649 }
00650 
00651 robot_state::RobotState& planning_scene::PlanningScene::getCurrentStateNonConst()
00652 {
00653   if (!kstate_)
00654   {
00655     kstate_.reset(new robot_state::RobotState(parent_->getCurrentState()));
00656     kstate_->setAttachedBodyUpdateCallback(current_state_attached_body_callback_);
00657   }
00658   return *kstate_;
00659 }
00660 
00661 robot_state::RobotStatePtr planning_scene::PlanningScene::getCurrentStateUpdated(const moveit_msgs::RobotState &update) const
00662 {
00663   robot_state::RobotStatePtr state(new robot_state::RobotState(getCurrentState()));
00664   robot_state::robotStateMsgToRobotState(getTransforms(), update, *state);
00665   return state;
00666 }
00667 
00668 void planning_scene::PlanningScene::setAttachedBodyUpdateCallback(const robot_state::AttachedBodyCallback &callback)
00669 {
00670   current_state_attached_body_callback_ = callback;
00671   if (kstate_)
00672     kstate_->setAttachedBodyUpdateCallback(callback);
00673 }
00674 
00675 void planning_scene::PlanningScene::setCollisionObjectUpdateCallback(const collision_detection::World::ObserverCallbackFn &callback)
00676 {
00677   if (current_world_object_update_callback_)
00678     world_->removeObserver(current_world_object_update_observer_handle_);
00679   if (callback)
00680     current_world_object_update_observer_handle_ = world_->addObserver(callback);
00681   current_world_object_update_callback_ = callback;
00682 }
00683 
00684 collision_detection::AllowedCollisionMatrix& planning_scene::PlanningScene::getAllowedCollisionMatrixNonConst()
00685 {
00686   if (!acm_)
00687     acm_.reset(new collision_detection::AllowedCollisionMatrix(parent_->getAllowedCollisionMatrix()));
00688   return *acm_;
00689 }
00690 
00691 robot_state::Transforms& planning_scene::PlanningScene::getTransformsNonConst()
00692 {
00693   if (!ftf_)
00694   {
00695     ftf_.reset(new SceneTransforms(this));
00696     ftf_->setAllTransforms(parent_->getTransforms().getAllTransforms());
00697   }
00698   return *ftf_;
00699 }
00700 
00701 void planning_scene::PlanningScene::getPlanningSceneDiffMsg(moveit_msgs::PlanningScene &scene_msg) const
00702 {
00703   scene_msg.name = name_;
00704   scene_msg.robot_model_name = getRobotModel()->getName();
00705   scene_msg.is_diff = true;
00706 
00707   if (ftf_)
00708     ftf_->copyTransforms(scene_msg.fixed_frame_transforms);
00709   else
00710     scene_msg.fixed_frame_transforms.clear();
00711 
00712   if (kstate_)
00713     robot_state::robotStateToRobotStateMsg(*kstate_, scene_msg.robot_state);
00714   else
00715     scene_msg.robot_state = moveit_msgs::RobotState();
00716 
00717   if (acm_)
00718     acm_->getMessage(scene_msg.allowed_collision_matrix);
00719   else
00720     scene_msg.allowed_collision_matrix = moveit_msgs::AllowedCollisionMatrix();
00721 
00722   if (active_collision_->crobot_)
00723   {
00724     active_collision_->crobot_->getPadding(scene_msg.link_padding);
00725     active_collision_->crobot_->getScale(scene_msg.link_scale);
00726   }
00727   else
00728   {
00729     scene_msg.link_padding.clear();
00730     scene_msg.link_scale.clear();
00731   }
00732 
00733   scene_msg.object_colors.clear();
00734   if (object_colors_)
00735   {
00736     unsigned int i = 0;
00737     scene_msg.object_colors.resize(object_colors_->size());
00738     for (ObjectColorMap::const_iterator it = object_colors_->begin() ; it != object_colors_->end() ; ++it, ++i)
00739     {
00740       scene_msg.object_colors[i].id = it->first;
00741       scene_msg.object_colors[i].color = it->second;
00742     }
00743   }
00744 
00745   scene_msg.world.collision_objects.clear();
00746   scene_msg.world.collision_map = moveit_msgs::CollisionMap();
00747   scene_msg.world.octomap = octomap_msgs::OctomapWithPose();
00748 
00749   if (world_diff_)
00750   {
00751     bool do_cmap = false;
00752     bool do_omap = false;
00753     for (collision_detection::WorldDiff::const_iterator it = world_diff_->begin() ; it != world_diff_->end() ; ++it)
00754     {
00755       if (it->first == COLLISION_MAP_NS)
00756         do_cmap = true;
00757       else if (it->first == OCTOMAP_NS)
00758         do_omap = true;
00759       else if (it->second == collision_detection::World::DESTROY)
00760       {
00761         moveit_msgs::CollisionObject co;
00762         co.header.frame_id = getPlanningFrame();
00763         co.id = it->first;
00764         co.operation = moveit_msgs::CollisionObject::REMOVE;
00765         scene_msg.world.collision_objects.push_back(co);
00766       }
00767       else
00768         getPlanningSceneMsgCollisionObject(scene_msg, it->first);
00769     }
00770     if (do_cmap)
00771       getPlanningSceneMsgCollisionMap(scene_msg);
00772     if (do_omap)
00773       getPlanningSceneMsgOctomap(scene_msg);
00774   }
00775 }
00776 
00777 namespace planning_scene
00778 {
00779 namespace
00780 {
00781 class ShapeVisitorAddToCollisionObject : public boost::static_visitor<void>
00782 {
00783 public:
00784 
00785   ShapeVisitorAddToCollisionObject(moveit_msgs::CollisionObject *obj) :
00786     boost::static_visitor<void>(), obj_(obj)
00787   {
00788   }
00789 
00790   void setPoseMessage(const geometry_msgs::Pose *pose)
00791   {
00792     pose_ = pose;
00793   }
00794 
00795   void operator()(const shape_msgs::Plane &shape_msg) const
00796   {
00797     obj_->planes.push_back(shape_msg);
00798     obj_->plane_poses.push_back(*pose_);
00799   }
00800 
00801   void operator()(const shape_msgs::Mesh &shape_msg) const
00802   {
00803     obj_->meshes.push_back(shape_msg);
00804     obj_->mesh_poses.push_back(*pose_);
00805   }
00806 
00807   void operator()(const shape_msgs::SolidPrimitive &shape_msg) const
00808   {
00809     obj_->primitives.push_back(shape_msg);
00810     obj_->primitive_poses.push_back(*pose_);
00811   }
00812 
00813 private:
00814 
00815   moveit_msgs::CollisionObject *obj_;
00816   const geometry_msgs::Pose *pose_;
00817 };
00818 }
00819 }
00820 
00821 void planning_scene::PlanningScene::getPlanningSceneMsgCollisionObject(moveit_msgs::PlanningScene &scene_msg, const std::string &ns) const
00822 {
00823   moveit_msgs::CollisionObject co;
00824   co.header.frame_id = getPlanningFrame();
00825   co.id = ns;
00826   co.operation = moveit_msgs::CollisionObject::ADD;
00827   collision_detection::CollisionWorld::ObjectConstPtr obj = world_->getObject(ns);
00828   if (!obj)
00829     return;
00830   ShapeVisitorAddToCollisionObject sv(&co);
00831   for (std::size_t j = 0 ; j < obj->shapes_.size() ; ++j)
00832   {
00833     shapes::ShapeMsg sm;
00834     if (constructMsgFromShape(obj->shapes_[j].get(), sm))
00835     {
00836       geometry_msgs::Pose p;
00837       tf::poseEigenToMsg(obj->shape_poses_[j], p);
00838       sv.setPoseMessage(&p);
00839       boost::apply_visitor(sv, sm);
00840     }
00841   }
00842   if (!co.primitives.empty() || !co.meshes.empty() || !co.planes.empty())
00843   {
00844     if (hasObjectType(co.id))
00845       co.type = getObjectType(co.id);
00846     scene_msg.world.collision_objects.push_back(co);
00847   }
00848 }
00849 
00850 void planning_scene::PlanningScene::getPlanningSceneMsgCollisionObjects(moveit_msgs::PlanningScene &scene_msg) const
00851 {
00852   scene_msg.world.collision_objects.clear();
00853   const std::vector<std::string> &ns = world_->getObjectIds();
00854   for (std::size_t i = 0 ; i < ns.size() ; ++i)
00855     if (ns[i] != COLLISION_MAP_NS && ns[i] != OCTOMAP_NS)
00856       getPlanningSceneMsgCollisionObject(scene_msg, ns[i]);
00857 }
00858 
00859 void planning_scene::PlanningScene::getPlanningSceneMsgCollisionMap(moveit_msgs::PlanningScene &scene_msg) const
00860 {
00861   scene_msg.world.collision_map.header.frame_id = getPlanningFrame();
00862   scene_msg.world.collision_map.boxes.clear();
00863   collision_detection::CollisionWorld::ObjectConstPtr map = world_->getObject(COLLISION_MAP_NS);
00864   if (map)
00865   {
00866     for (std::size_t i = 0 ; i < map->shapes_.size() ; ++i)
00867     {
00868       if (map->shapes_[i]->type != shapes::BOX)
00869       {
00870         logError("Shape that is not a box was found in '%s' object. Skipping shape.", COLLISION_MAP_NS.c_str());
00871         continue;
00872       }
00873       const shapes::Box *b = static_cast<const shapes::Box*>(map->shapes_[i].get());
00874       moveit_msgs::OrientedBoundingBox obb;
00875       obb.extents.x = b->size[0]; obb.extents.y = b->size[1]; obb.extents.z = b->size[2];
00876       tf::poseEigenToMsg(map->shape_poses_[i], obb.pose);
00877       scene_msg.world.collision_map.boxes.push_back(obb);
00878     }
00879   }
00880 }
00881 
00882 void planning_scene::PlanningScene::getPlanningSceneMsgOctomap(moveit_msgs::PlanningScene &scene_msg) const
00883 {
00884   scene_msg.world.octomap.header.frame_id = getPlanningFrame();
00885   scene_msg.world.octomap.octomap = octomap_msgs::Octomap();
00886 
00887   collision_detection::CollisionWorld::ObjectConstPtr map = world_->getObject(OCTOMAP_NS);
00888   if (map)
00889   {
00890     if (map->shapes_.size() == 1)
00891     {
00892       const shapes::OcTree *o = static_cast<const shapes::OcTree*>(map->shapes_[0].get());
00893       octomap_msgs::fullMapToMsg(*o->octree, scene_msg.world.octomap.octomap);
00894       tf::poseEigenToMsg(map->shape_poses_[0], scene_msg.world.octomap.origin);
00895     }
00896     else
00897       logError("Unexpected number of shapes in octomap collision object. Not including '%s' object", OCTOMAP_NS.c_str());
00898   }
00899 }
00900 
00901 void planning_scene::PlanningScene::getPlanningSceneMsg(moveit_msgs::PlanningScene &scene_msg) const
00902 {
00903   scene_msg.name = name_;
00904   scene_msg.is_diff = false;
00905   scene_msg.robot_model_name = getRobotModel()->getName();
00906   getTransforms().copyTransforms(scene_msg.fixed_frame_transforms);
00907 
00908   robot_state::robotStateToRobotStateMsg(getCurrentState(), scene_msg.robot_state);
00909   getAllowedCollisionMatrix().getMessage(scene_msg.allowed_collision_matrix);
00910   getCollisionRobot()->getPadding(scene_msg.link_padding);
00911   getCollisionRobot()->getScale(scene_msg.link_scale);
00912 
00913   getPlanningSceneMsgObjectColors(scene_msg);
00914 
00915   // add collision objects
00916   getPlanningSceneMsgCollisionObjects(scene_msg);
00917 
00918   // get the octomap
00919   getPlanningSceneMsgOctomap(scene_msg);
00920 
00921   // get the collision map
00922   getPlanningSceneMsgCollisionMap(scene_msg);
00923 }
00924 
00925 void planning_scene::PlanningScene::getPlanningSceneMsgObjectColors(moveit_msgs::PlanningScene &scene_msg) const
00926 {
00927   scene_msg.object_colors.clear();
00928 
00929   unsigned int i = 0;
00930   ObjectColorMap cmap;
00931   getKnownObjectColors(cmap);
00932   scene_msg.object_colors.resize(cmap.size());
00933   for (ObjectColorMap::const_iterator it = cmap.begin() ; it != cmap.end() ; ++it, ++i)
00934   {
00935     scene_msg.object_colors[i].id = it->first;
00936     scene_msg.object_colors[i].color = it->second;
00937   }
00938 }
00939 
00940 void planning_scene::PlanningScene::getPlanningSceneMsg(moveit_msgs::PlanningScene &scene_msg, const moveit_msgs::PlanningSceneComponents &comp) const
00941 {
00942   scene_msg.is_diff = false;
00943   if (comp.components & moveit_msgs::PlanningSceneComponents::SCENE_SETTINGS)
00944   {
00945     scene_msg.name = name_;
00946     scene_msg.robot_model_name = getRobotModel()->getName();
00947   }
00948 
00949   if (comp.components & moveit_msgs::PlanningSceneComponents::TRANSFORMS)
00950     getTransforms().copyTransforms(scene_msg.fixed_frame_transforms);
00951 
00952   if (comp.components & moveit_msgs::PlanningSceneComponents::ROBOT_STATE_ATTACHED_OBJECTS)
00953     robot_state::robotStateToRobotStateMsg(getCurrentState(), scene_msg.robot_state, true);
00954   else
00955     if (comp.components & moveit_msgs::PlanningSceneComponents::ROBOT_STATE)
00956       robot_state::robotStateToRobotStateMsg(getCurrentState(), scene_msg.robot_state, false);
00957 
00958   if (comp.components & moveit_msgs::PlanningSceneComponents::ALLOWED_COLLISION_MATRIX)
00959     getAllowedCollisionMatrix().getMessage(scene_msg.allowed_collision_matrix);
00960 
00961   if (comp.components & moveit_msgs::PlanningSceneComponents::LINK_PADDING_AND_SCALING)
00962   {
00963     getCollisionRobot()->getPadding(scene_msg.link_padding);
00964     getCollisionRobot()->getScale(scene_msg.link_scale);
00965   }
00966 
00967   if (comp.components & moveit_msgs::PlanningSceneComponents::OBJECT_COLORS)
00968     getPlanningSceneMsgObjectColors(scene_msg);
00969 
00970   // add collision objects
00971   if (comp.components & moveit_msgs::PlanningSceneComponents::WORLD_OBJECT_GEOMETRY)
00972     getPlanningSceneMsgCollisionObjects(scene_msg);
00973   else
00974     if (comp.components & moveit_msgs::PlanningSceneComponents::WORLD_OBJECT_NAMES)
00975     {
00976       const std::vector<std::string> &ns = world_->getObjectIds();
00977       scene_msg.world.collision_objects.clear();
00978       scene_msg.world.collision_objects.reserve(ns.size());
00979       for (std::size_t i = 0 ; i < ns.size() ; ++i)
00980         if (ns[i] != COLLISION_MAP_NS && ns[i] != OCTOMAP_NS)
00981         {
00982           moveit_msgs::CollisionObject co;
00983           co.id = ns[i];
00984       if (hasObjectType(co.id))
00985         co.type = getObjectType(co.id);
00986           scene_msg.world.collision_objects.push_back(co);
00987         }
00988     }
00989 
00990   // get the octomap
00991   if (comp.components & moveit_msgs::PlanningSceneComponents::OCTOMAP)
00992     getPlanningSceneMsgOctomap(scene_msg);
00993 }
00994 
00995 void planning_scene::PlanningScene::saveGeometryToStream(std::ostream &out) const
00996 {
00997   out << name_ << std::endl;
00998   const std::vector<std::string> &ns = world_->getObjectIds();
00999   for (std::size_t i = 0 ; i < ns.size() ; ++i)
01000     if (ns[i] != COLLISION_MAP_NS && ns[i] != OCTOMAP_NS)
01001     {
01002       collision_detection::CollisionWorld::ObjectConstPtr obj = world_->getObject(ns[i]);
01003       if (obj)
01004       {
01005         out << "* " << ns[i] << std::endl;
01006         out << obj->shapes_.size() << std::endl;
01007         for (std::size_t j = 0 ; j < obj->shapes_.size() ; ++j)
01008         {
01009           shapes::saveAsText(obj->shapes_[j].get(), out);
01010           out << obj->shape_poses_[j].translation().x() << " " << obj->shape_poses_[j].translation().y() << " " << obj->shape_poses_[j].translation().z() << std::endl;
01011           Eigen::Quaterniond r(obj->shape_poses_[j].rotation());
01012           out << r.x() << " " << r.y() << " " << r.z() << " " << r.w() << std::endl;
01013           if (hasObjectColor(ns[i]))
01014           {
01015             const std_msgs::ColorRGBA &c = getObjectColor(ns[i]);
01016             out << c.r << " " << c.g << " " << c.b << " " << c.a << std::endl;
01017           }
01018           else
01019             out << "0 0 0 0" << std::endl;
01020         }
01021       }
01022     }
01023   out << "." << std::endl;
01024 }
01025 
01026 void planning_scene::PlanningScene::loadGeometryFromStream(std::istream &in)
01027 {
01028   if (!in.good() || in.eof())
01029     return;
01030   std::getline(in, name_);
01031   do
01032   {
01033     std::string marker;
01034     in >> marker;
01035     if (!in.good() || in.eof())
01036       return;
01037     if (marker == "*")
01038     {
01039       std::string ns;
01040       std::getline(in, ns);
01041       if (!in.good() || in.eof())
01042         return;
01043       unsigned int shape_count;
01044       in >> shape_count;
01045       for (std::size_t i = 0 ; i < shape_count && in.good() && !in.eof() ; ++i)
01046       {
01047         shapes::Shape *s = shapes::constructShapeFromText(in);
01048         double x, y, z, rx, ry, rz, rw;
01049         in >> x >> y >> z;
01050         in >> rx >> ry >> rz >> rw;
01051         float r, g, b, a;
01052         in >> r >> g >> b >> a;
01053         if (s)
01054         {
01055           Eigen::Affine3d pose = Eigen::Translation3d(x, y, z) * Eigen::Quaterniond(rw, rx, ry, rz);
01056           world_->addToObject(ns, shapes::ShapePtr(s), pose);
01057           if (r > 0.0f || g > 0.0f || b > 0.0f || a > 0.0f)
01058           {
01059             std_msgs::ColorRGBA color;
01060             color.r = r; color.g = g; color.b = b; color.a = a;
01061             setObjectColor(ns, color);
01062           }
01063         }
01064       }
01065     }
01066     else
01067       break;
01068   } while (true);
01069 }
01070 
01071 void planning_scene::PlanningScene::setCurrentState(const moveit_msgs::RobotState &state)
01072 {
01073   if (parent_)
01074   {
01075     if (!kstate_)
01076     {
01077       kstate_.reset(new robot_state::RobotState(parent_->getCurrentState()));
01078       kstate_->setAttachedBodyUpdateCallback(current_state_attached_body_callback_);
01079     }
01080     else
01081       // attached bodies are sent fully, so we need to clear old ones, if any
01082       kstate_->clearAttachedBodies();
01083     robot_state::robotStateMsgToRobotState(getTransforms(), state, *kstate_);
01084   }
01085   else
01086   {
01087     // attached bodies are sent fully, so we need to clear old ones, if any
01088     kstate_->clearAttachedBodies();
01089     robot_state::robotStateMsgToRobotState(*ftf_, state, *kstate_);
01090   }
01091 
01092   // we add object types to the planning scene, if any are specified
01093   for (std::size_t i = 0 ; i < state.attached_collision_objects.size() ; ++i)
01094   {
01095     const moveit_msgs::CollisionObject &o = state.attached_collision_objects[i].object;
01096     if (!o.id.empty() && (!o.type.db.empty() || !o.type.key.empty()))
01097       setObjectType(o.id, o.type);
01098   }
01099 }
01100 
01101 void planning_scene::PlanningScene::setCurrentState(const robot_state::RobotState &state)
01102 {
01103   getCurrentStateNonConst() = state;
01104 }
01105 
01106 void planning_scene::PlanningScene::decoupleParent()
01107 {
01108   if (!parent_)
01109     return;
01110 
01111   if (!ftf_)
01112   {
01113     ftf_.reset(new SceneTransforms(this));
01114     ftf_->setAllTransforms(parent_->getTransforms().getAllTransforms());
01115   }
01116 
01117   if (!kstate_)
01118   {
01119     kstate_.reset(new robot_state::RobotState(parent_->getCurrentState()));
01120     kstate_->setAttachedBodyUpdateCallback(current_state_attached_body_callback_);
01121   }
01122 
01123   if (!acm_)
01124     acm_.reset(new collision_detection::AllowedCollisionMatrix(parent_->getAllowedCollisionMatrix()));
01125 
01126   for (CollisionDetectorIterator it = collision_.begin() ; it != collision_.end() ; ++it)
01127   {
01128     if (!it->second->crobot_)
01129     {
01130       it->second->crobot_ = it->second->alloc_->allocateRobot(it->second->parent_->getCollisionRobot());
01131       it->second->crobot_const_ = it->second->crobot_;
01132     }
01133     if (!it->second->crobot_unpadded_)
01134     {
01135       it->second->crobot_unpadded_ = it->second->alloc_->allocateRobot(it->second->parent_->getCollisionRobotUnpadded());
01136       it->second->crobot_unpadded_const_ = it->second->crobot_unpadded_;
01137     }
01138     it->second->parent_.reset();
01139   }
01140   world_diff_.reset();
01141 
01142   if (!object_colors_)
01143   {
01144     ObjectColorMap kc;
01145     parent_->getKnownObjectColors(kc);
01146     object_colors_.reset(new ObjectColorMap(kc));
01147   }
01148   else
01149   {
01150     ObjectColorMap kc;
01151     parent_->getKnownObjectColors(kc);
01152     for (ObjectColorMap::const_iterator it = kc.begin() ; it != kc.end() ; ++it)
01153       if (object_colors_->find(it->first) == object_colors_->end())
01154         (*object_colors_)[it->first] = it->second;
01155   }
01156 
01157   if (!object_types_)
01158   {
01159     ObjectTypeMap kc;
01160     parent_->getKnownObjectTypes(kc);
01161     object_types_.reset(new ObjectTypeMap(kc));
01162   }
01163   else
01164   {
01165     ObjectTypeMap kc;
01166     parent_->getKnownObjectTypes(kc);
01167     for (ObjectTypeMap::const_iterator it = kc.begin() ; it != kc.end() ; ++it)
01168       if (object_types_->find(it->first) == object_types_->end())
01169         (*object_types_)[it->first] = it->second;
01170   }
01171 
01172   parent_.reset();
01173 }
01174 
01175 void planning_scene::PlanningScene::setPlanningSceneDiffMsg(const moveit_msgs::PlanningScene &scene_msg)
01176 {
01177   logDebug("Adding planning scene diff");
01178   if (!scene_msg.name.empty())
01179     name_ = scene_msg.name;
01180 
01181   if (!scene_msg.robot_model_name.empty() && scene_msg.robot_model_name != getRobotModel()->getName())
01182     logWarn("Setting the scene for model '%s' but model '%s' is loaded.", scene_msg.robot_model_name.c_str(), getRobotModel()->getName().c_str());
01183 
01184   // there is at least one transform in the list of fixed transform: from model frame to itself;
01185   // if the list is empty, then nothing has been set
01186   if (!scene_msg.fixed_frame_transforms.empty())
01187   {
01188     if (!ftf_)
01189       ftf_.reset(new SceneTransforms(this));
01190     ftf_->setTransforms(scene_msg.fixed_frame_transforms);
01191   }
01192 
01193   // if at least some joints have been specified, we set them
01194   if (!scene_msg.robot_state.multi_dof_joint_state.joint_names.empty() ||
01195       !scene_msg.robot_state.joint_state.name.empty() ||
01196       !scene_msg.robot_state.attached_collision_objects.empty())
01197     setCurrentState(scene_msg.robot_state);
01198 
01199   // if at least some links are mentioned in the allowed collision matrix, then we have an update
01200   if (!scene_msg.allowed_collision_matrix.entry_names.empty())
01201     acm_.reset(new collision_detection::AllowedCollisionMatrix(scene_msg.allowed_collision_matrix));
01202 
01203   if (!scene_msg.link_padding.empty() || !scene_msg.link_scale.empty())
01204   {
01205     for (CollisionDetectorIterator it = collision_.begin() ; it != collision_.end() ; ++it)
01206     {
01207       if (!it->second->crobot_)
01208       {
01209         it->second->crobot_ = it->second->alloc_->allocateRobot(it->second->parent_->getCollisionRobot());
01210         it->second->crobot_const_ = it->second->crobot_;
01211       }
01212       it->second->crobot_->setPadding(scene_msg.link_padding);
01213       it->second->crobot_->setScale(scene_msg.link_scale);
01214     }
01215   }
01216 
01217   // if any colors have been specified, replace the ones we have with the specified ones
01218   if (!scene_msg.object_colors.empty())
01219   {
01220     object_colors_.reset();
01221     for (std::size_t i = 0 ; i < scene_msg.object_colors.size() ; ++i)
01222       setObjectColor(scene_msg.object_colors[i].id, scene_msg.object_colors[i].color);
01223   }
01224 
01225   // process collision object updates
01226   for (std::size_t i = 0 ; i < scene_msg.world.collision_objects.size() ; ++i)
01227     processCollisionObjectMsg(scene_msg.world.collision_objects[i]);
01228 
01229   // if an octomap was specified, replace the one we have with that one
01230   if (!scene_msg.world.octomap.octomap.data.empty())
01231     processOctomapMsg(scene_msg.world.octomap);
01232 
01233   // if a collision map was specified, replace the one we have with that one
01234   if (!scene_msg.world.collision_map.boxes.empty())
01235     processCollisionMapMsg(scene_msg.world.collision_map);
01236 }
01237 
01238 void planning_scene::PlanningScene::setPlanningSceneMsg(const moveit_msgs::PlanningScene &scene_msg)
01239 {
01240   logDebug("Setting new planning scene: '%s'", scene_msg.name.c_str());
01241   name_ = scene_msg.name;
01242 
01243   if (!scene_msg.robot_model_name.empty() && scene_msg.robot_model_name != getRobotModel()->getName())
01244     logWarn("Setting the scene for model '%s' but model '%s' is loaded.", scene_msg.robot_model_name.c_str(), getRobotModel()->getName().c_str());
01245 
01246   if (parent_)
01247     decoupleParent();
01248 
01249   object_types_.reset();
01250   ftf_->setTransforms(scene_msg.fixed_frame_transforms);
01251   setCurrentState(scene_msg.robot_state);
01252   acm_.reset(new collision_detection::AllowedCollisionMatrix(scene_msg.allowed_collision_matrix));
01253   for (CollisionDetectorIterator it = collision_.begin() ; it != collision_.end() ; ++it)
01254   {
01255     if (!it->second->crobot_)
01256     {
01257       it->second->crobot_ = it->second->alloc_->allocateRobot(it->second->parent_->getCollisionRobot());
01258       it->second->crobot_const_ = it->second->crobot_;
01259     }
01260     it->second->crobot_->setPadding(scene_msg.link_padding);
01261     it->second->crobot_->setScale(scene_msg.link_scale);
01262   }
01263   object_colors_.reset(new ObjectColorMap());
01264   for (std::size_t i = 0 ; i < scene_msg.object_colors.size() ; ++i)
01265     setObjectColor(scene_msg.object_colors[i].id, scene_msg.object_colors[i].color);
01266   world_->clearObjects();
01267   processPlanningSceneWorldMsg(scene_msg.world);
01268 }
01269 
01270 void planning_scene::PlanningScene::processPlanningSceneWorldMsg(const moveit_msgs::PlanningSceneWorld &world)
01271 {
01272   for (std::size_t i = 0 ; i < world.collision_objects.size() ; ++i)
01273     processCollisionObjectMsg(world.collision_objects[i]);
01274   processOctomapMsg(world.octomap);
01275   processCollisionMapMsg(world.collision_map);
01276 }
01277 
01278 void planning_scene::PlanningScene::usePlanningSceneMsg(const moveit_msgs::PlanningScene &scene_msg)
01279 {
01280   if (scene_msg.is_diff)
01281     setPlanningSceneDiffMsg(scene_msg);
01282   else
01283     setPlanningSceneMsg(scene_msg);
01284 }
01285 
01286 void planning_scene::PlanningScene::processCollisionMapMsg(const moveit_msgs::CollisionMap &map)
01287 {
01288   // each collision map replaces any previous one
01289   world_->removeObject(COLLISION_MAP_NS);
01290 
01291   if (map.boxes.empty())
01292     return;
01293   const Eigen::Affine3d &t = getTransforms().getTransform(map.header.frame_id);
01294   for (std::size_t i = 0 ; i < map.boxes.size() ; ++i)
01295   {
01296     Eigen::Affine3d p;
01297     tf::poseMsgToEigen(map.boxes[i].pose, p);
01298     shapes::Shape *s = new shapes::Box(map.boxes[i].extents.x, map.boxes[i].extents.y, map.boxes[i].extents.z);
01299     world_->addToObject(COLLISION_MAP_NS, shapes::ShapeConstPtr(s), t * p);
01300   }
01301 }
01302 
01303 void planning_scene::PlanningScene::processOctomapMsg(const octomap_msgs::Octomap &map)
01304 {
01305   // each octomap replaces any previous one
01306   world_->removeObject(OCTOMAP_NS);
01307 
01308   if (map.data.empty())
01309     return;
01310 
01311   if (map.id != "OcTree")
01312   {
01313     logError("Received ocomap is of type '%s' but type 'OcTree' is expected.", map.id.c_str());
01314     return;
01315   }
01316 
01317   boost::shared_ptr<octomap::OcTree> om(static_cast<octomap::OcTree*>(octomap_msgs::msgToMap(map)));
01318   if (!map.header.frame_id.empty())
01319   {
01320     const Eigen::Affine3d &t = getTransforms().getTransform(map.header.frame_id);
01321     world_->addToObject(OCTOMAP_NS, shapes::ShapeConstPtr(new shapes::OcTree(om)), t);
01322   }
01323   else
01324   {
01325     world_->addToObject(OCTOMAP_NS, shapes::ShapeConstPtr(new shapes::OcTree(om)), Eigen::Affine3d::Identity());
01326   }
01327 }
01328 
01329 void planning_scene::PlanningScene::processOctomapMsg(const octomap_msgs::OctomapWithPose &map)
01330 {
01331   // each octomap replaces any previous one
01332   world_->removeObject(OCTOMAP_NS);
01333 
01334   if (map.octomap.data.empty())
01335     return;
01336 
01337   if (map.octomap.id != "OcTree")
01338   {
01339     logError("Received ocomap is of type '%s' but type 'OcTree' is expected.", map.octomap.id.c_str());
01340     return;
01341   }
01342 
01343   boost::shared_ptr<octomap::OcTree> om(static_cast<octomap::OcTree*>(octomap_msgs::msgToMap(map.octomap)));
01344   const Eigen::Affine3d &t = getTransforms().getTransform(map.header.frame_id);
01345   Eigen::Affine3d p;
01346   tf::poseMsgToEigen(map.origin, p);
01347   p = t * p;
01348   world_->addToObject(OCTOMAP_NS, shapes::ShapeConstPtr(new shapes::OcTree(om)), p);
01349 }
01350 
01351 void planning_scene::PlanningScene::processOctomapPtr(const boost::shared_ptr<const octomap::OcTree> &octree, const Eigen::Affine3d &t)
01352 {
01353   collision_detection::CollisionWorld::ObjectConstPtr map = world_->getObject(OCTOMAP_NS);
01354   if (map)
01355   {
01356     if (map->shapes_.size() == 1)
01357     {
01358       // check to see if we have the same octree pointer & pose.
01359       const shapes::OcTree *o = static_cast<const shapes::OcTree*>(map->shapes_[0].get());
01360       if (o->octree == octree)
01361       {
01362         // if the pose changed, we update it
01363         if (map->shape_poses_[0].isApprox(t, std::numeric_limits<double>::epsilon() * 100.0))
01364         {
01365           if (world_diff_)
01366             world_diff_->set(OCTOMAP_NS,
01367                              collision_detection::World::DESTROY |
01368                              collision_detection::World::CREATE |
01369                              collision_detection::World::ADD_SHAPE);
01370         }
01371         else
01372         {
01373           shapes::ShapeConstPtr shape = map->shapes_[0];
01374           map.reset(); // reset this pointer first so that caching optimizations can be used in CollisionWorld
01375           world_->moveShapeInObject(OCTOMAP_NS, shape, t);
01376         }
01377         return;
01378       }
01379     }
01380   }
01381   // if the octree pointer changed, update the structure
01382   world_->removeObject(OCTOMAP_NS);
01383   world_->addToObject(OCTOMAP_NS, shapes::ShapeConstPtr(new shapes::OcTree(octree)), t);
01384 }
01385 
01386 bool planning_scene::PlanningScene::processAttachedCollisionObjectMsg(const moveit_msgs::AttachedCollisionObject &object)
01387 {
01388   if (!getRobotModel()->hasLinkModel(object.link_name))
01389   {
01390     if (object.object.operation == moveit_msgs::CollisionObject::ADD)
01391       logError("Unable to attach a body to link '%s' (link not found)", object.link_name.c_str());
01392     else
01393       logError("Unable to detach body from link '%s' (link not found)", object.link_name.c_str());
01394     return false;
01395   }
01396 
01397   if (object.object.id == COLLISION_MAP_NS)
01398   {
01399     logError("The ID '%s' cannot be used for collision objects (name reserved)", COLLISION_MAP_NS.c_str());
01400     return false;
01401   }
01402 
01403   if (object.object.id == OCTOMAP_NS)
01404   {
01405     logError("The ID '%s' cannot be used for collision objects (name reserved)", OCTOMAP_NS.c_str());
01406     return false;
01407   }
01408 
01409   if (!kstate_) // there must be a parent in this case
01410   {
01411     kstate_.reset(new robot_state::RobotState(parent_->getCurrentState()));
01412     kstate_->setAttachedBodyUpdateCallback(current_state_attached_body_callback_);
01413   }
01414 
01415   if (object.object.operation == moveit_msgs::CollisionObject::ADD || object.object.operation == moveit_msgs::CollisionObject::APPEND)
01416   {
01417     if (object.object.primitives.size() != object.object.primitive_poses.size())
01418     {
01419       logError("Number of primitive shapes does not match number of poses in attached collision object message");
01420       return false;
01421     }
01422 
01423     if (object.object.meshes.size() != object.object.mesh_poses.size())
01424     {
01425       logError("Number of meshes does not match number of poses in attached collision object message");
01426       return false;
01427     }
01428 
01429     if (object.object.planes.size() != object.object.plane_poses.size())
01430     {
01431       logError("Number of planes does not match number of poses in attached collision object message");
01432       return false;
01433     }
01434 
01435     robot_state::LinkState *ls = kstate_->getLinkState(object.link_name);
01436     if (ls)
01437     {
01438       std::vector<shapes::ShapeConstPtr> shapes;
01439       EigenSTL::vector_Affine3d poses;
01440 
01441       // we need to add some shapes; if the message is empty, maybe the object is already in the world
01442       if (object.object.operation == moveit_msgs::CollisionObject::ADD &&
01443           object.object.primitives.empty() && object.object.meshes.empty() && object.object.planes.empty())
01444       {
01445         collision_detection::CollisionWorld::ObjectConstPtr obj = world_->getObject(object.object.id);
01446         if (obj)
01447         {
01448           logInform("Attaching world object '%s' to link '%s'", object.object.id.c_str(), object.link_name.c_str());
01449 
01450           // extract the shapes from the world
01451           shapes = obj->shapes_;
01452           poses = obj->shape_poses_;
01453           // remove the pointer to the objects from the collision world
01454           world_->removeObject(object.object.id);
01455 
01456           // need to transform poses to the link frame
01457           const Eigen::Affine3d &i_t = ls->getGlobalLinkTransform().inverse();
01458           for (std::size_t i = 0 ; i < poses.size() ; ++i)
01459             poses[i] = i_t * poses[i];
01460         }
01461         else
01462         {
01463           logError("Attempting to attach object '%s' to link '%s' but no geometry specified and such an object does not exist in the collision world",
01464                    object.object.id.c_str(), object.link_name.c_str());
01465           return false;
01466         }
01467       }
01468       else
01469       {
01470         // we clear the world objects with the same name, since we got an update on their geometry
01471         if (world_->removeObject(object.object.id))
01472         {
01473           if (object.object.operation == moveit_msgs::CollisionObject::ADD)
01474             logInform("Removing world object with the same name as newly attached object: '%s'", object.object.id.c_str());
01475           else
01476             logWarn("You tried to append geometry to an attached object that is actually a world object ('%s'). World geometry is ignored.", object.object.id.c_str());
01477         }
01478 
01479         for (std::size_t i = 0 ; i < object.object.primitives.size() ; ++i)
01480         {
01481           shapes::Shape *s = shapes::constructShapeFromMsg(object.object.primitives[i]);
01482           if (s)
01483           {
01484             Eigen::Affine3d p;
01485             tf::poseMsgToEigen(object.object.primitive_poses[i], p);
01486             shapes.push_back(shapes::ShapeConstPtr(s));
01487             poses.push_back(p);
01488           }
01489         }
01490         for (std::size_t i = 0 ; i < object.object.meshes.size() ; ++i)
01491         {
01492           shapes::Shape *s = shapes::constructShapeFromMsg(object.object.meshes[i]);
01493           if (s)
01494           {
01495             Eigen::Affine3d p;
01496             tf::poseMsgToEigen(object.object.mesh_poses[i], p);
01497             shapes.push_back(shapes::ShapeConstPtr(s));
01498             poses.push_back(p);
01499           }
01500         }
01501         for (std::size_t i = 0 ; i < object.object.planes.size() ; ++i)
01502         {
01503           shapes::Shape *s = shapes::constructShapeFromMsg(object.object.planes[i]);
01504           if (s)
01505           {
01506             Eigen::Affine3d p;
01507             tf::poseMsgToEigen(object.object.plane_poses[i], p);
01508             shapes.push_back(shapes::ShapeConstPtr(s));
01509             poses.push_back(p);
01510           }
01511         }
01512 
01513         // transform poses to link frame
01514         if (object.object.header.frame_id != object.link_name)
01515         {
01516           const Eigen::Affine3d &t = ls->getGlobalLinkTransform().inverse() * getTransforms().getTransform(object.object.header.frame_id);
01517           for (std::size_t i = 0 ; i < poses.size() ; ++i)
01518             poses[i] = t * poses[i];
01519         }
01520       }
01521 
01522       if (shapes.empty())
01523       {
01524         logError("There is no geometry to attach to link '%s' as part of attached body '%s'", object.link_name.c_str(), object.object.id.c_str());
01525         return false;
01526       }
01527 
01528       if (!object.object.type.db.empty() || !object.object.type.key.empty())
01529         setObjectType(object.object.id, object.object.type);
01530 
01531       if (object.object.operation == moveit_msgs::CollisionObject::ADD || !kstate_->hasAttachedBody(object.object.id))
01532       {
01533         // there should not exist an attached object with this name
01534         if (kstate_->clearAttachedBody(object.object.id))
01535           logInform("The robot state already had an object named '%s' attached to link '%s'. The object was replaced.",
01536                     object.object.id.c_str(), object.link_name.c_str());
01537         kstate_->attachBody(object.object.id, shapes, poses, object.touch_links, object.link_name, object.detach_posture);
01538         logInform("Attached object '%s' to link '%s'", object.object.id.c_str(), object.link_name.c_str());
01539       }
01540       else
01541       {
01542         const robot_state::AttachedBody *ab = kstate_->getAttachedBody(object.object.id);
01543         shapes.insert(shapes.end(), ab->getShapes().begin(), ab->getShapes().end());
01544         poses.insert(poses.end(), ab->getFixedTransforms().begin(), ab->getFixedTransforms().end());
01545         sensor_msgs::JointState detach_posture = object.detach_posture.name.empty() ? ab->getDetachPosture() : object.detach_posture;
01546         std::set<std::string> ab_touch_links = ab->getTouchLinks();
01547         kstate_->clearAttachedBody(object.object.id);
01548         if (object.touch_links.empty())
01549           kstate_->attachBody(object.object.id, shapes, poses, ab_touch_links, object.link_name, detach_posture);
01550         else
01551           kstate_->attachBody(object.object.id, shapes, poses, object.touch_links, object.link_name, detach_posture);
01552         logInform("Added shapes to object '%s' attached to link '%s'", object.object.id.c_str(), object.link_name.c_str());
01553       }
01554 
01555       return true;
01556     }
01557     else
01558       logError("Robot state is not compatible with robot model. This could be fatal.");
01559   }
01560   else if (object.object.operation == moveit_msgs::CollisionObject::REMOVE)
01561   {
01562     robot_state::LinkState *ls = kstate_->getLinkState(object.link_name);
01563     if (ls)
01564     {
01565       std::vector<const robot_state::AttachedBody*> attached_bodies;
01566 
01567       if (object.object.id.empty()) // if no specific object id is given, then we remove all objects attached to the link_name
01568       {
01569         ls->getAttachedBodies(attached_bodies);
01570       }
01571       else // a specific object id will be removed
01572       {
01573         const robot_state::AttachedBody *ab = ls->getAttachedBody(object.object.id);
01574         if (ab)
01575           attached_bodies.push_back(ab);
01576       }
01577 
01578       for (std::size_t i = 0; i < attached_bodies.size(); ++i)
01579       {
01580         std::vector<shapes::ShapeConstPtr> shapes = attached_bodies[i]->getShapes();
01581         EigenSTL::vector_Affine3d poses = attached_bodies[i]->getGlobalCollisionBodyTransforms();
01582         std::string name = attached_bodies[i]->getName();
01583 
01584         kstate_->clearAttachedBody(name);
01585 
01586         if (world_->hasObject(name))
01587           logWarn("The collision world already has an object with the same name as the body about to be detached. NOT adding the detached body '%s' to the collision world.", object.object.id.c_str());
01588         else
01589         {
01590           world_->addToObject(name, shapes, poses);
01591           logInform("Detached object '%s' from link '%s' and added it back in the collision world", name.c_str(), object.link_name.c_str());
01592         }
01593       }
01594       if (!attached_bodies.empty() || object.object.id.empty())
01595         return true;
01596     }
01597     else
01598       logError("Robot state is not compatible with robot model. This could be fatal.");
01599   }
01600   else if (object.object.operation == moveit_msgs::CollisionObject::MOVE)
01601   {
01602     logError("Move for attached objects not yet implemented");
01603   }
01604   else
01605   {
01606     logError("Unknown collision object operation: %d", object.object.operation);
01607   }
01608 
01609   return false;
01610 }
01611 
01612 bool planning_scene::PlanningScene::processCollisionObjectMsg(const moveit_msgs::CollisionObject &object)
01613 {
01614   if (object.id == COLLISION_MAP_NS)
01615   {
01616     logError("The ID '%s' cannot be used for collision objects (name reserved)", COLLISION_MAP_NS.c_str());
01617     return false;
01618   }
01619   if (object.id == OCTOMAP_NS)
01620   {
01621     logError("The ID '%s' cannot be used for collision objects (name reserved)", OCTOMAP_NS.c_str());
01622     return false;
01623   }
01624 
01625   if (object.operation == moveit_msgs::CollisionObject::ADD || object.operation == moveit_msgs::CollisionObject::APPEND)
01626   {
01627     if (object.primitives.empty() && object.meshes.empty() && object.planes.empty())
01628     {
01629       logError("There are no shapes specified in the collision object message");
01630       return false;
01631     }
01632 
01633     if (object.primitives.size() != object.primitive_poses.size())
01634     {
01635       logError("Number of primitive shapes does not match number of poses in collision object message");
01636       return false;
01637     }
01638 
01639     if (object.meshes.size() != object.mesh_poses.size())
01640     {
01641       logError("Number of meshes does not match number of poses in collision object message");
01642       return false;
01643     }
01644 
01645     if (object.planes.size() != object.plane_poses.size())
01646     {
01647       logError("Number of planes does not match number of poses in collision object message");
01648       return false;
01649     }
01650 
01651     // replace the object if ADD is specified instead of APPEND
01652     if (object.operation == moveit_msgs::CollisionObject::ADD && world_->hasObject(object.id))
01653       world_->removeObject(object.id);
01654 
01655     const Eigen::Affine3d &t = getTransforms().getTransform(object.header.frame_id);
01656     for (std::size_t i = 0 ; i < object.primitives.size() ; ++i)
01657     {
01658       shapes::Shape *s = shapes::constructShapeFromMsg(object.primitives[i]);
01659       if (s)
01660       {
01661         Eigen::Affine3d p;
01662         tf::poseMsgToEigen(object.primitive_poses[i], p);
01663         world_->addToObject(object.id, shapes::ShapeConstPtr(s), t * p);
01664       }
01665     }
01666     for (std::size_t i = 0 ; i < object.meshes.size() ; ++i)
01667     {
01668       shapes::Shape *s = shapes::constructShapeFromMsg(object.meshes[i]);
01669       if (s)
01670       {
01671         Eigen::Affine3d p;
01672         tf::poseMsgToEigen(object.mesh_poses[i], p);
01673         world_->addToObject(object.id, shapes::ShapeConstPtr(s), t * p);
01674       }
01675     }
01676     for (std::size_t i = 0 ; i < object.planes.size() ; ++i)
01677     {
01678       shapes::Shape *s = shapes::constructShapeFromMsg(object.planes[i]);
01679       if (s)
01680       {
01681         Eigen::Affine3d p;
01682         tf::poseMsgToEigen(object.plane_poses[i], p);
01683         world_->addToObject(object.id, shapes::ShapeConstPtr(s), t * p);
01684       }
01685     }
01686     if (!object.type.key.empty() || !object.type.db.empty())
01687       setObjectType(object.id, object.type);
01688     return true;
01689   }
01690   else if (object.operation == moveit_msgs::CollisionObject::REMOVE)
01691   {
01692     if (object.id.empty())
01693     {
01694       const std::vector<std::string> &object_ids = world_->getObjectIds();
01695       for (std::size_t i = 0; i < object_ids.size(); ++i)
01696         if (object_ids[i] != OCTOMAP_NS)
01697           world_->removeObject(object_ids[i]);
01698     }
01699     else
01700       world_->removeObject(object.id);
01701     return true;
01702   }
01703   else if (object.operation == moveit_msgs::CollisionObject::MOVE)
01704   {
01705     if (world_->hasObject(object.id))
01706     {
01707       if (!object.primitives.empty() || !object.meshes.empty() || !object.planes.empty())
01708         logWarn("Move operation for object '%s' ignores the geometry specified in the message.");
01709 
01710       const Eigen::Affine3d &t = getTransforms().getTransform(object.header.frame_id);
01711       EigenSTL::vector_Affine3d new_poses;
01712       for (std::size_t i = 0 ; i < object.primitive_poses.size() ; ++i)
01713       {
01714         Eigen::Affine3d p;
01715         tf::poseMsgToEigen(object.primitive_poses[i], p);
01716         new_poses.push_back(t * p);
01717       }
01718       for (std::size_t i = 0 ; i < object.mesh_poses.size() ; ++i)
01719       {
01720         Eigen::Affine3d p;
01721         tf::poseMsgToEigen(object.mesh_poses[i], p);
01722         new_poses.push_back(t * p);
01723       }
01724       for (std::size_t i = 0 ; i < object.plane_poses.size() ; ++i)
01725       {
01726         Eigen::Affine3d p;
01727         tf::poseMsgToEigen(object.plane_poses[i], p);
01728         new_poses.push_back(t * p);
01729       }
01730 
01731       collision_detection::World::ObjectConstPtr obj = world_->getObject(object.id);
01732       if (obj->shapes_.size() == new_poses.size())
01733       {
01734         std::vector<shapes::ShapeConstPtr> shapes = obj->shapes_;
01735         obj.reset();
01736         world_->removeObject(object.id);
01737         world_->addToObject(object.id, shapes, new_poses);
01738       }
01739       else
01740       {
01741         logError("Number of supplied poses (%u) for object '%s' does not match number of shapes (%u). Not moving.",
01742                  (unsigned int)new_poses.size(), object.id.c_str(), (unsigned int)obj->shapes_.size());
01743         return false;
01744       }
01745       return true;
01746     }
01747     else
01748       logError("World object '%s' does not exist. Cannot move.", object.id.c_str());
01749   }
01750   else
01751     logError("Unknown collision object operation: %d", object.operation);
01752   return false;
01753 }
01754 
01755 const Eigen::Affine3d& planning_scene::PlanningScene::getFrameTransform(const std::string &id) const
01756 {
01757   return getFrameTransform(getCurrentState(), id);
01758 }
01759 
01760 const Eigen::Affine3d& planning_scene::PlanningScene::getFrameTransform(const robot_state::RobotState &state, const std::string &id) const
01761 {
01762   if (!id.empty() && id[0] == '/')
01763     return getFrameTransform(id.substr(1));
01764   if (state.knowsFrameTransform(id))
01765     return state.getFrameTransform(id);
01766   if (getWorld()->hasObject(id))
01767   {
01768     collision_detection::World::ObjectConstPtr obj = getWorld()->getObject(id);
01769     if (obj->shape_poses_.size() > 1)
01770     {
01771       logWarn("More than one shapes in object '%s'. Using first one to decide transform");
01772       return obj->shape_poses_[0];
01773     }
01774     else
01775       if (obj->shape_poses_.size() == 1)
01776         return obj->shape_poses_[0];
01777   }
01778   return getTransforms().Transforms::getTransform(id);
01779 }
01780 
01781 bool planning_scene::PlanningScene::knowsFrameTransform(const std::string &id) const
01782 {
01783   return knowsFrameTransform(getCurrentState(), id);
01784 }
01785 
01786 bool planning_scene::PlanningScene::knowsFrameTransform(const robot_state::RobotState &state, const std::string &id) const
01787 {
01788   if (!id.empty() && id[0] == '/')
01789     return knowsFrameTransform(id.substr(1));
01790   if (state.knowsFrameTransform(id))
01791     return true;
01792   if (getWorld()->hasObject(id))
01793   {
01794     collision_detection::World::ObjectConstPtr obj = getWorld()->getObject(id);
01795     return obj->shape_poses_.size() == 1;
01796   }
01797   return getTransforms().Transforms::canTransform(id);
01798 }
01799 
01800 bool planning_scene::PlanningScene::hasObjectType(const std::string &id) const
01801 {
01802   if (object_types_)
01803     if (object_types_->find(id) != object_types_->end())
01804       return true;
01805   if (parent_)
01806     return parent_->hasObjectType(id);
01807   return false;
01808 }
01809 
01810 const object_recognition_msgs::ObjectType& planning_scene::PlanningScene::getObjectType(const std::string &id) const
01811 {
01812   if (object_types_)
01813   {
01814     ObjectTypeMap::const_iterator it = object_types_->find(id);
01815     if (it != object_types_->end())
01816       return it->second;
01817   }
01818   if (parent_)
01819     return parent_->getObjectType(id);
01820   static const object_recognition_msgs::ObjectType empty;
01821   return empty;
01822 
01823 }
01824 
01825 void planning_scene::PlanningScene::setObjectType(const std::string &id, const object_recognition_msgs::ObjectType &type)
01826 {
01827   if (!object_types_)
01828     object_types_.reset(new ObjectTypeMap());
01829   (*object_types_)[id] = type;
01830 }
01831 
01832 void planning_scene::PlanningScene::removeObjectType(const std::string &id)
01833 {
01834   if (object_types_)
01835     object_types_->erase(id);
01836 }
01837 
01838 void planning_scene::PlanningScene::getKnownObjectTypes(ObjectTypeMap &kc) const
01839 {
01840   kc.clear();
01841   if (parent_)
01842     parent_->getKnownObjectTypes(kc);
01843   if (object_types_)
01844     for (ObjectTypeMap::const_iterator it = object_types_->begin() ; it != object_types_->end() ; ++it)
01845       kc[it->first] = it->second;
01846 }
01847 
01848 bool planning_scene::PlanningScene::hasObjectColor(const std::string &id) const
01849 {
01850   if (object_colors_)
01851     if (object_colors_->find(id) != object_colors_->end())
01852       return true;
01853   if (parent_)
01854     return parent_->hasObjectColor(id);
01855   return false;
01856 }
01857 
01858 const std_msgs::ColorRGBA& planning_scene::PlanningScene::getObjectColor(const std::string &id) const
01859 {
01860   if (object_colors_)
01861   {
01862     ObjectColorMap::const_iterator it = object_colors_->find(id);
01863     if (it != object_colors_->end())
01864       return it->second;
01865   }
01866   if (parent_)
01867     return parent_->getObjectColor(id);
01868   static const std_msgs::ColorRGBA empty;
01869   return empty;
01870 }
01871 
01872 void planning_scene::PlanningScene::getKnownObjectColors(ObjectColorMap &kc) const
01873 {
01874   kc.clear();
01875   if (parent_)
01876     parent_->getKnownObjectColors(kc);
01877   if (object_colors_)
01878     for (ObjectColorMap::const_iterator it = object_colors_->begin() ; it != object_colors_->end() ; ++it)
01879       kc[it->first] = it->second;
01880 }
01881 
01882 void planning_scene::PlanningScene::setObjectColor(const std::string &id, const std_msgs::ColorRGBA &color)
01883 {
01884   if (!object_colors_)
01885     object_colors_.reset(new ObjectColorMap());
01886   (*object_colors_)[id] = color;
01887 }
01888 
01889 void planning_scene::PlanningScene::removeObjectColor(const std::string &id)
01890 {
01891   if (object_colors_)
01892     object_colors_->erase(id);
01893 }
01894 
01895 bool planning_scene::PlanningScene::isStateColliding(const moveit_msgs::RobotState &state, const std::string &group, bool verbose) const
01896 {
01897   robot_state::RobotState s(getCurrentState());
01898   robot_state::robotStateMsgToRobotState(getTransforms(), state, s);
01899   return isStateColliding(s, group, verbose);
01900 }
01901 
01902 bool planning_scene::PlanningScene::isStateColliding(const std::string &group, bool verbose) const
01903 {
01904   return isStateColliding(getCurrentState(), group, verbose);
01905 }
01906 
01907 bool planning_scene::PlanningScene::isStateColliding(const robot_state::RobotState &state, const std::string &group, bool verbose) const
01908 {
01909   collision_detection::CollisionRequest req;
01910   req.verbose = verbose;
01911   req.group_name = group;
01912   collision_detection::CollisionResult  res;
01913   checkCollision(req, res, state);
01914   return res.collision;
01915 }
01916 
01917 bool planning_scene::PlanningScene::isStateFeasible(const moveit_msgs::RobotState &state, bool verbose) const
01918 {
01919   if (state_feasibility_)
01920   {
01921     robot_state::RobotState s(getCurrentState());
01922     robot_state::robotStateMsgToRobotState(getTransforms(), state, s);
01923     return state_feasibility_(s, verbose);
01924   }
01925   return true;
01926 }
01927 
01928 bool planning_scene::PlanningScene::isStateFeasible(const robot_state::RobotState &state, bool verbose) const
01929 {
01930   if (state_feasibility_)
01931     return state_feasibility_(state, verbose);
01932   return true;
01933 }
01934 
01935 bool planning_scene::PlanningScene::isStateConstrained(const moveit_msgs::RobotState &state, const moveit_msgs::Constraints &constr, bool verbose) const
01936 {
01937   robot_state::RobotState s(getCurrentState());
01938   robot_state::robotStateMsgToRobotState(getTransforms(), state, s);
01939   return isStateConstrained(s, constr, verbose);
01940 }
01941 
01942 
01943 bool planning_scene::PlanningScene::isStateConstrained(const robot_state::RobotState &state, const moveit_msgs::Constraints &constr, bool verbose) const
01944 {
01945   kinematic_constraints::KinematicConstraintSetPtr ks(new kinematic_constraints::KinematicConstraintSet(getRobotModel()));
01946   ks->add(constr, getTransforms());
01947   if (ks->empty())
01948     return true;
01949   else
01950     return isStateConstrained(state, *ks, verbose);
01951 }
01952 
01953 bool planning_scene::PlanningScene::isStateConstrained(const moveit_msgs::RobotState &state, const kinematic_constraints::KinematicConstraintSet &constr, bool verbose) const
01954 {
01955   robot_state::RobotState s(getCurrentState());
01956   robot_state::robotStateMsgToRobotState(getTransforms(), state, s);
01957   return isStateConstrained(s, constr, verbose);
01958 }
01959 
01960 bool planning_scene::PlanningScene::isStateConstrained(const robot_state::RobotState &state,  const kinematic_constraints::KinematicConstraintSet &constr, bool verbose) const
01961 {
01962   return constr.decide(state, verbose).satisfied;
01963 }
01964 
01965 bool planning_scene::PlanningScene::isStateValid(const robot_state::RobotState &state, const std::string &group, bool verbose) const
01966 {
01967   static const moveit_msgs::Constraints emp_constraints;
01968   return isStateValid(state, emp_constraints, group, verbose);
01969 }
01970 
01971 bool planning_scene::PlanningScene::isStateValid(const moveit_msgs::RobotState &state, const std::string &group, bool verbose) const
01972 {
01973   static const moveit_msgs::Constraints emp_constraints;
01974   return isStateValid(state, emp_constraints, group, verbose);
01975 }
01976 
01977 bool planning_scene::PlanningScene::isStateValid(const moveit_msgs::RobotState &state, const moveit_msgs::Constraints &constr, const std::string &group, bool verbose) const
01978 {
01979   robot_state::RobotState s(getCurrentState());
01980   robot_state::robotStateMsgToRobotState(getTransforms(), state, s);
01981   return isStateValid(s, constr, group, verbose);
01982 }
01983 
01984 bool planning_scene::PlanningScene::isStateValid(const robot_state::RobotState &state, const moveit_msgs::Constraints &constr, const std::string &group, bool verbose) const
01985 {
01986   if (isStateColliding(state, group, verbose))
01987     return false;
01988   if (!isStateFeasible(state, verbose))
01989     return false;
01990   return isStateConstrained(state, constr, verbose);
01991 }
01992 
01993 bool planning_scene::PlanningScene::isStateValid(const robot_state::RobotState &state, const kinematic_constraints::KinematicConstraintSet &constr, const std::string &group, bool verbose) const
01994 {
01995   if (isStateColliding(state, group, verbose))
01996     return false;
01997   if (!isStateFeasible(state, verbose))
01998     return false;
01999   return isStateConstrained(state, constr, verbose);
02000 }
02001 
02002 bool planning_scene::PlanningScene::isPathValid(const moveit_msgs::RobotState &start_state,
02003                                                 const moveit_msgs::RobotTrajectory &trajectory,
02004                                                 const std::string &group, bool verbose,
02005                                                 std::vector<std::size_t> *invalid_index) const
02006 {
02007   static const moveit_msgs::Constraints emp_constraints;
02008   static const std::vector<moveit_msgs::Constraints> emp_constraints_vector;
02009   return isPathValid(start_state, trajectory, emp_constraints, emp_constraints_vector, group, verbose, invalid_index);
02010 }
02011 
02012 bool planning_scene::PlanningScene::isPathValid(const moveit_msgs::RobotState &start_state,
02013                                                 const moveit_msgs::RobotTrajectory &trajectory,
02014                                                 const moveit_msgs::Constraints& path_constraints,
02015                                                 const std::string &group, bool verbose,
02016                                                 std::vector<std::size_t> *invalid_index) const
02017 {
02018   static const std::vector<moveit_msgs::Constraints> emp_constraints_vector;
02019   return isPathValid(start_state, trajectory, path_constraints, emp_constraints_vector, group, verbose, invalid_index);
02020 }
02021 
02022 bool planning_scene::PlanningScene::isPathValid(const moveit_msgs::RobotState &start_state,
02023                                                 const moveit_msgs::RobotTrajectory &trajectory,
02024                                                 const moveit_msgs::Constraints& path_constraints,
02025                                                 const moveit_msgs::Constraints& goal_constraints,
02026                                                 const std::string &group, bool verbose,
02027                                                 std::vector<std::size_t> *invalid_index) const
02028 {
02029   std::vector<moveit_msgs::Constraints> goal_constraints_vector(1, goal_constraints);
02030   return isPathValid(start_state, trajectory, path_constraints, goal_constraints_vector, group, verbose, invalid_index);
02031 }
02032 
02033 bool planning_scene::PlanningScene::isPathValid(const moveit_msgs::RobotState &start_state,
02034                                                 const moveit_msgs::RobotTrajectory &trajectory,
02035                                                 const moveit_msgs::Constraints& path_constraints,
02036                                                 const std::vector<moveit_msgs::Constraints>& goal_constraints,
02037                                                 const std::string &group, bool verbose,
02038                                                 std::vector<std::size_t> *invalid_index) const
02039 {
02040   robot_trajectory::RobotTrajectory t(getRobotModel(), group);
02041   robot_state::RobotState start(getCurrentState());
02042   robot_state::robotStateMsgToRobotState(getTransforms(), start_state, start);
02043   t.setRobotTrajectoryMsg(start, trajectory);
02044   return isPathValid(t, path_constraints, goal_constraints, group, verbose, invalid_index);
02045 }
02046 
02047 bool planning_scene::PlanningScene::isPathValid(const robot_trajectory::RobotTrajectory &trajectory,
02048                                                 const moveit_msgs::Constraints& path_constraints,
02049                                                 const std::vector<moveit_msgs::Constraints>& goal_constraints,
02050                                                 const std::string &group, bool verbose, std::vector<std::size_t> *invalid_index) const
02051 {
02052   bool result = true;
02053   if (invalid_index)
02054     invalid_index->clear();
02055   kinematic_constraints::KinematicConstraintSet ks_p(getRobotModel());
02056   ks_p.add(path_constraints, getTransforms());
02057   std::size_t n_wp = trajectory.getWayPointCount();
02058   for (std::size_t i = 0 ; i < n_wp ; ++i)
02059   {
02060     const robot_state::RobotState &st = trajectory.getWayPoint(i);
02061 
02062     bool this_state_valid = true;
02063     if (isStateColliding(st, group, verbose))
02064       this_state_valid = false;
02065     if (!isStateFeasible(st, verbose))
02066       this_state_valid = false;
02067     if (!ks_p.empty() && !ks_p.decide(st, verbose).satisfied)
02068       this_state_valid = false;
02069 
02070     if (!this_state_valid)
02071     {
02072       if (invalid_index)
02073         invalid_index->push_back(i);
02074       else
02075         return false;
02076       result = false;
02077     }
02078 
02079     // check goal for last state
02080     if (i + 1 == n_wp && !goal_constraints.empty())
02081     {
02082       bool found = false;
02083       for (std::size_t k = 0 ; k < goal_constraints.size() ; ++k)
02084       {
02085         if (isStateConstrained(st, goal_constraints[k]))
02086         {
02087           found = true;
02088           break;
02089         }
02090       }
02091       if (!found)
02092       {
02093         if (verbose)
02094           logInform("Goal not satisfied");
02095         if (invalid_index)
02096           invalid_index->push_back(i);
02097         result = false;
02098       }
02099     }
02100   }
02101   return result;
02102 }
02103 
02104 
02105 bool planning_scene::PlanningScene::isPathValid(const robot_trajectory::RobotTrajectory &trajectory,
02106                                                 const moveit_msgs::Constraints& path_constraints,
02107                                                 const moveit_msgs::Constraints& goal_constraints,
02108                                                 const std::string &group, bool verbose, std::vector<std::size_t> *invalid_index) const
02109 {
02110   std::vector<moveit_msgs::Constraints> goal_constraints_vector(1, goal_constraints);
02111   return isPathValid(trajectory, path_constraints, goal_constraints_vector, group, verbose, invalid_index);
02112 }
02113 
02114 bool planning_scene::PlanningScene::isPathValid(const robot_trajectory::RobotTrajectory &trajectory,
02115                                                 const moveit_msgs::Constraints& path_constraints,
02116                                                 const std::string &group, bool verbose, std::vector<std::size_t> *invalid_index) const
02117 {
02118   static const std::vector<moveit_msgs::Constraints> emp_constraints_vector;
02119   return isPathValid(trajectory, path_constraints, emp_constraints_vector, group, verbose, invalid_index);
02120 }
02121 
02122 bool planning_scene::PlanningScene::isPathValid(const robot_trajectory::RobotTrajectory &trajectory,
02123                                                 const std::string &group, bool verbose, std::vector<std::size_t> *invalid_index) const
02124 {
02125   static const moveit_msgs::Constraints emp_constraints;
02126   static const std::vector<moveit_msgs::Constraints> emp_constraints_vector;
02127   return isPathValid(trajectory, emp_constraints, emp_constraints_vector, group, verbose, invalid_index);
02128 }
02129 
02130 void planning_scene::PlanningScene::getCostSources(const robot_trajectory::RobotTrajectory &trajectory, std::size_t max_costs,
02131                                                    std::set<collision_detection::CostSource> &costs, double overlap_fraction) const
02132 {
02133   getCostSources(trajectory, max_costs, std::string(), costs, overlap_fraction);
02134 }
02135 
02136 
02137 void planning_scene::PlanningScene::getCostSources(const robot_trajectory::RobotTrajectory &trajectory, std::size_t max_costs,
02138                                                    const std::string &group_name, std::set<collision_detection::CostSource> &costs,
02139                                                    double overlap_fraction) const
02140 {
02141   collision_detection::CollisionRequest creq;
02142   creq.max_cost_sources = max_costs;
02143   creq.group_name = group_name;
02144   creq.cost = true;
02145   std::set<collision_detection::CostSource> cs;
02146   std::set<collision_detection::CostSource> cs_start;
02147   std::size_t n_wp = trajectory.getWayPointCount();
02148   for (std::size_t i = 0 ; i < n_wp ; ++i)
02149   {
02150     collision_detection::CollisionResult cres;
02151     checkCollision(creq, cres, trajectory.getWayPoint(i));
02152     cs.insert(cres.cost_sources.begin(), cres.cost_sources.end());
02153     if (i == 0)
02154       cs_start.swap(cres.cost_sources);
02155   }
02156 
02157   if (cs.size() <= max_costs)
02158     costs.swap(cs);
02159   else
02160   {
02161     costs.clear();
02162     std::size_t i = 0;
02163     for (std::set<collision_detection::CostSource>::iterator it = cs.begin() ; i < max_costs ; ++it, ++i)
02164       costs.insert(*it);
02165   }
02166 
02167   collision_detection::removeCostSources(costs, cs_start, overlap_fraction);
02168   collision_detection::removeOverlapping(costs, overlap_fraction);
02169 }
02170 
02171 void planning_scene::PlanningScene::getCostSources(const robot_state::RobotState &state, std::size_t max_costs,
02172                                                    std::set<collision_detection::CostSource> &costs) const
02173 {
02174   getCostSources(state, max_costs, std::string(), costs);
02175 }
02176 
02177 void planning_scene::PlanningScene::getCostSources(const robot_state::RobotState &state, std::size_t max_costs,
02178                                                    const std::string &group_name, std::set<collision_detection::CostSource> &costs) const
02179 {
02180   collision_detection::CollisionRequest creq;
02181   creq.max_cost_sources = max_costs;
02182   creq.group_name = group_name;
02183   creq.cost = true;
02184   collision_detection::CollisionResult cres;
02185   checkCollision(creq, cres, state);
02186   cres.cost_sources.swap(costs);
02187 }
02188 
02189 void planning_scene::PlanningScene::printKnownObjects(std::ostream& out) const
02190 {
02191   const std::vector<std::string>& objects = getWorld()->getObjectIds();
02192 
02193   out << "Collision World Objects:\n\t ";
02194   std::copy(objects.begin(), objects.end(), std::ostream_iterator<std::string>(out, "\n\t "));
02195 
02196   std::vector<const robot_state::AttachedBody*> attached_bodies;
02197   getCurrentState().getAttachedBodies(attached_bodies);
02198 
02199   out << "\nAttached Bodies:\n";
02200   for(std::size_t i = 0; i < attached_bodies.size(); ++i)
02201   {
02202     out << "\t " << attached_bodies[i]->getName() << "\n";
02203   }
02204 }


moveit_core
Author(s): Ioan Sucan , Sachin Chitta , Acorn Pooley
autogenerated on Mon Oct 6 2014 02:24:47