00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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 {
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
00163 const std::vector<std::string>& collision_links = kmodel_->getLinkModelNamesWithCollisionGeometry();
00164 acm_->setEntry(collision_links, collision_links, false);
00165
00166
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
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
00197
00198 world_.reset(new collision_detection::World(*parent_->world_));
00199 world_const_ = world_;
00200
00201
00202 world_diff_.reset(new collision_detection::WorldDiff(world_));
00203
00204
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
00219
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)
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
00303
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
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
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
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
00541 getCollisionWorld()->checkRobotCollision(req, res, *getCollisionRobot(), kstate, getAllowedCollisionMatrix());
00542
00543 if (!res.collision || (req.contacts && res.contacts.size() < req.max_contacts))
00544 {
00545
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
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
00563 getCollisionWorld()->checkRobotCollision(req, res, *getCollisionRobot(), kstate, acm);
00564
00565
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
00589 getCollisionWorld()->checkRobotCollision(req, res, *getCollisionRobotUnpadded(), kstate, acm);
00590
00591
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
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
00916 getPlanningSceneMsgCollisionObjects(scene_msg);
00917
00918
00919 getPlanningSceneMsgOctomap(scene_msg);
00920
00921
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
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
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
01082 kstate_->clearAttachedBodies();
01083 robot_state::robotStateMsgToRobotState(getTransforms(), state, *kstate_);
01084 }
01085 else
01086 {
01087
01088 kstate_->clearAttachedBodies();
01089 robot_state::robotStateMsgToRobotState(*ftf_, state, *kstate_);
01090 }
01091
01092
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
01185
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
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
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
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
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
01230 if (!scene_msg.world.octomap.octomap.data.empty())
01231 processOctomapMsg(scene_msg.world.octomap);
01232
01233
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
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
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
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
01359 const shapes::OcTree *o = static_cast<const shapes::OcTree*>(map->shapes_[0].get());
01360 if (o->octree == octree)
01361 {
01362
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();
01375 world_->moveShapeInObject(OCTOMAP_NS, shape, t);
01376 }
01377 return;
01378 }
01379 }
01380 }
01381
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_)
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
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
01451 shapes = obj->shapes_;
01452 poses = obj->shape_poses_;
01453
01454 world_->removeObject(object.object.id);
01455
01456
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
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
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
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())
01568 {
01569 ls->getAttachedBodies(attached_bodies);
01570 }
01571 else
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
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
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 }