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_monitor/planning_scene_monitor.h>
00038 #include <moveit/robot_model_loader/robot_model_loader.h>
00039 #include <moveit/exceptions/exceptions.h>
00040 #include <moveit_msgs/GetPlanningScene.h>
00041
00042 #include <dynamic_reconfigure/server.h>
00043 #include <moveit_ros_planning/PlanningSceneMonitorDynamicReconfigureConfig.h>
00044 #include <tf_conversions/tf_eigen.h>
00045 #include <moveit/profiler/profiler.h>
00046
00047 namespace planning_scene_monitor
00048 {
00049
00050 using namespace moveit_ros_planning;
00051
00052 class PlanningSceneMonitor::DynamicReconfigureImpl
00053 {
00054 public:
00055
00056 DynamicReconfigureImpl(PlanningSceneMonitor *owner) : owner_(owner),
00057 dynamic_reconfigure_server_(ros::NodeHandle(decideNamespace(owner->getName())))
00058 {
00059 dynamic_reconfigure_server_.setCallback(boost::bind(&DynamicReconfigureImpl::dynamicReconfigureCallback, this, _1, _2));
00060 }
00061
00062 private:
00063
00064
00065 static std::string decideNamespace(const std::string &name)
00066 {
00067 std::string ns = "~/" + name;
00068 std::replace(ns.begin(), ns.end(), ' ', '_');
00069 std::transform(ns.begin(), ns.end(), ns.begin(), ::tolower);
00070 if (ros::service::exists(ns + "/set_parameters", false))
00071 {
00072 unsigned int c = 1;
00073 while (ros::service::exists(ns + boost::lexical_cast<std::string>(c) + "/set_parameters", false))
00074 c++;
00075 ns += boost::lexical_cast<std::string>(c);
00076 }
00077 return ns;
00078 }
00079
00080 void dynamicReconfigureCallback(PlanningSceneMonitorDynamicReconfigureConfig &config, uint32_t level)
00081 {
00082 PlanningSceneMonitor::SceneUpdateType event = PlanningSceneMonitor::UPDATE_NONE;
00083 if (config.publish_geometry_updates)
00084 event = (PlanningSceneMonitor::SceneUpdateType) ((int)event | (int)PlanningSceneMonitor::UPDATE_GEOMETRY);
00085 if (config.publish_state_updates)
00086 event = (PlanningSceneMonitor::SceneUpdateType) ((int)event | (int)PlanningSceneMonitor::UPDATE_STATE);
00087 if (config.publish_transforms_updates)
00088 event = (PlanningSceneMonitor::SceneUpdateType) ((int)event | (int)PlanningSceneMonitor::UPDATE_TRANSFORMS);
00089 if (config.publish_planning_scene)
00090 {
00091 owner_->setPlanningScenePublishingFrequency(config.publish_planning_scene_hz);
00092 owner_->startPublishingPlanningScene(event);
00093 }
00094 else
00095 owner_->stopPublishingPlanningScene();
00096 }
00097
00098 PlanningSceneMonitor *owner_;
00099 dynamic_reconfigure::Server<PlanningSceneMonitorDynamicReconfigureConfig> dynamic_reconfigure_server_;
00100 };
00101
00102 }
00103
00104 const std::string planning_scene_monitor::PlanningSceneMonitor::DEFAULT_JOINT_STATES_TOPIC = "joint_states";
00105 const std::string planning_scene_monitor::PlanningSceneMonitor::DEFAULT_ATTACHED_COLLISION_OBJECT_TOPIC = "attached_collision_object";
00106 const std::string planning_scene_monitor::PlanningSceneMonitor::DEFAULT_COLLISION_OBJECT_TOPIC = "collision_object";
00107 const std::string planning_scene_monitor::PlanningSceneMonitor::DEFAULT_PLANNING_SCENE_WORLD_TOPIC = "planning_scene_world";
00108 const std::string planning_scene_monitor::PlanningSceneMonitor::DEFAULT_PLANNING_SCENE_TOPIC = "planning_scene";
00109 const std::string planning_scene_monitor::PlanningSceneMonitor::DEFAULT_PLANNING_SCENE_SERVICE = "get_planning_scene";
00110 const std::string planning_scene_monitor::PlanningSceneMonitor::MONITORED_PLANNING_SCENE_TOPIC = "monitored_planning_scene";
00111
00112 planning_scene_monitor::PlanningSceneMonitor::PlanningSceneMonitor(const std::string &robot_description, const boost::shared_ptr<tf::Transformer> &tf, const std::string &name) :
00113 monitor_name_(name), nh_("~"), tf_(tf)
00114 {
00115 rm_loader_.reset(new robot_model_loader::RobotModelLoader(robot_description));
00116 initialize(planning_scene::PlanningScenePtr());
00117 }
00118
00119 planning_scene_monitor::PlanningSceneMonitor::PlanningSceneMonitor(const planning_scene::PlanningScenePtr &scene, const std::string &robot_description,
00120 const boost::shared_ptr<tf::Transformer> &tf, const std::string &name) :
00121 monitor_name_(name), nh_("~"), tf_(tf)
00122 {
00123 rm_loader_.reset(new robot_model_loader::RobotModelLoader(robot_description));
00124 initialize(scene);
00125 }
00126
00127 planning_scene_monitor::PlanningSceneMonitor::PlanningSceneMonitor(const robot_model_loader::RobotModelLoaderPtr &rm_loader,
00128 const boost::shared_ptr<tf::Transformer> &tf, const std::string &name) :
00129 monitor_name_(name), nh_("~"), tf_(tf), rm_loader_(rm_loader)
00130 {
00131 initialize(planning_scene::PlanningScenePtr());
00132 }
00133
00134 planning_scene_monitor::PlanningSceneMonitor::PlanningSceneMonitor(const planning_scene::PlanningScenePtr &scene, const robot_model_loader::RobotModelLoaderPtr &rm_loader,
00135 const boost::shared_ptr<tf::Transformer> &tf, const std::string &name) :
00136 monitor_name_(name), nh_("~"), tf_(tf), rm_loader_(rm_loader)
00137 {
00138 initialize(scene);
00139 }
00140
00141 planning_scene_monitor::PlanningSceneMonitor::~PlanningSceneMonitor()
00142 {
00143 if (scene_)
00144 {
00145 scene_->setCollisionObjectUpdateCallback(collision_detection::World::ObserverCallbackFn());
00146 scene_->setAttachedBodyUpdateCallback(robot_state::AttachedBodyCallback());
00147 }
00148 stopPublishingPlanningScene();
00149 stopStateMonitor();
00150 stopWorldGeometryMonitor();
00151 stopSceneMonitor();
00152 delete reconfigure_impl_;
00153 current_state_monitor_.reset();
00154 scene_const_.reset();
00155 scene_.reset();
00156 parent_scene_.reset();
00157 robot_model_.reset();
00158 rm_loader_.reset();
00159 }
00160
00161 void planning_scene_monitor::PlanningSceneMonitor::initialize(const planning_scene::PlanningScenePtr &scene)
00162 {
00163 moveit::tools::Profiler::ScopedStart prof_start;
00164 moveit::tools::Profiler::ScopedBlock prof_block("PlanningSceneMonitor::initialize");
00165
00166 if (monitor_name_.empty())
00167 monitor_name_ = "planning_scene_monitor";
00168 robot_description_ = rm_loader_->getRobotDescription();
00169 if (rm_loader_->getModel())
00170 {
00171 robot_model_ = rm_loader_->getModel();
00172 scene_ = scene;
00173 scene_const_ = scene_;
00174 if (!scene_)
00175 {
00176 try
00177 {
00178 scene_.reset(new planning_scene::PlanningScene(rm_loader_->getModel()));
00179 scene_const_ = scene_;
00180 configureCollisionMatrix(scene_);
00181 configureDefaultPadding();
00182
00183 scene_->getCollisionRobotNonConst()->setPadding(default_robot_padd_);
00184 scene_->getCollisionRobotNonConst()->setScale(default_robot_scale_);
00185 for(std::map<std::string, double>::iterator it=default_robot_link_padd_.begin(); it != default_robot_link_padd_.end(); ++it) {
00186 scene_->getCollisionRobotNonConst()->setLinkPadding(it->first, it->second);
00187 }
00188 for(std::map<std::string, double>::iterator it=default_robot_link_scale_.begin(); it != default_robot_link_scale_.end(); ++it) {
00189 scene_->getCollisionRobotNonConst()->setLinkScale(it->first, it->second);
00190 }
00191 scene_->propogateRobotPadding();
00192 }
00193 catch (moveit::ConstructException &e)
00194 {
00195 ROS_ERROR("Configuration of planning scene failed");
00196 scene_.reset();
00197 scene_const_ = scene_;
00198 }
00199 }
00200 if (scene_)
00201 {
00202 scene_->setAttachedBodyUpdateCallback(boost::bind(&PlanningSceneMonitor::currentStateAttachedBodyUpdateCallback, this, _1, _2));
00203 scene_->setCollisionObjectUpdateCallback(boost::bind(&PlanningSceneMonitor::currentWorldObjectUpdateCallback, this, _1, _2));
00204 }
00205 }
00206 else
00207 {
00208 ROS_ERROR("Robot model not loaded");
00209 }
00210
00211 publish_planning_scene_frequency_ = 2.0;
00212 new_scene_update_ = UPDATE_NONE;
00213
00214 last_update_time_ = ros::Time::now();
00215 last_state_update_ = ros::WallTime::now();
00216 dt_state_update_ = ros::WallDuration(0.1);
00217
00218 double temp_wait_time;
00219 nh_.param(
00220 robot_description_ + "_planning/shape_transform_cache_lookup_wait_time",
00221 temp_wait_time,
00222 0.05);
00223 shape_transform_cache_lookup_wait_time_ = ros::Duration(temp_wait_time);
00224
00225 state_update_pending_ = false;
00226 state_update_timer_ = nh_.createWallTimer(dt_state_update_,
00227 &PlanningSceneMonitor::stateUpdateTimerCallback,
00228 this,
00229 false,
00230 false);
00231
00232 reconfigure_impl_ = new DynamicReconfigureImpl(this);
00233 }
00234
00235 void planning_scene_monitor::PlanningSceneMonitor::monitorDiffs(bool flag)
00236 {
00237 if (scene_)
00238 {
00239 if (flag)
00240 {
00241 boost::unique_lock<boost::shared_mutex> ulock(scene_update_mutex_);
00242 if (scene_)
00243 {
00244 scene_->setAttachedBodyUpdateCallback(robot_state::AttachedBodyCallback());
00245 scene_->setCollisionObjectUpdateCallback(collision_detection::World::ObserverCallbackFn());
00246 scene_->decoupleParent();
00247 parent_scene_ = scene_;
00248 scene_ = parent_scene_->diff();
00249 scene_const_ = scene_;
00250 scene_->setAttachedBodyUpdateCallback(boost::bind(&PlanningSceneMonitor::currentStateAttachedBodyUpdateCallback, this, _1, _2));
00251 scene_->setCollisionObjectUpdateCallback(boost::bind(&PlanningSceneMonitor::currentWorldObjectUpdateCallback, this, _1, _2));
00252 }
00253 }
00254 else
00255 {
00256 if (publish_planning_scene_)
00257 {
00258 ROS_WARN("Diff monitoring was stopped while publishing planning scene diffs. Stopping planning scene diff publisher");
00259 stopPublishingPlanningScene();
00260 }
00261 {
00262 boost::unique_lock<boost::shared_mutex> ulock(scene_update_mutex_);
00263 if (scene_)
00264 {
00265 scene_->decoupleParent();
00266 parent_scene_.reset();
00267
00268 if (!scene_->getName().empty())
00269 {
00270 if (scene_->getName()[scene_->getName().length() - 1] == '+')
00271 scene_->setName(scene_->getName().substr(0, scene_->getName().length() - 1));
00272 }
00273 }
00274 }
00275 }
00276 }
00277 }
00278
00279 void planning_scene_monitor::PlanningSceneMonitor::stopPublishingPlanningScene()
00280 {
00281 if (publish_planning_scene_)
00282 {
00283 boost::scoped_ptr<boost::thread> copy;
00284 copy.swap(publish_planning_scene_);
00285 new_scene_update_condition_.notify_all();
00286 copy->join();
00287 monitorDiffs(false);
00288 planning_scene_publisher_.shutdown();
00289 ROS_INFO("Stopped publishing maintained planning scene.");
00290 }
00291 }
00292
00293 void planning_scene_monitor::PlanningSceneMonitor::startPublishingPlanningScene(SceneUpdateType update_type, const std::string &planning_scene_topic)
00294 {
00295 publish_update_types_ = update_type;
00296 if (!publish_planning_scene_ && scene_)
00297 {
00298 planning_scene_publisher_ = nh_.advertise<moveit_msgs::PlanningScene>(planning_scene_topic, 100, false);
00299 ROS_INFO("Publishing maintained planning scene on '%s'", planning_scene_topic.c_str());
00300 monitorDiffs(true);
00301 publish_planning_scene_.reset(new boost::thread(boost::bind(&PlanningSceneMonitor::scenePublishingThread, this)));
00302 }
00303 }
00304
00305 void planning_scene_monitor::PlanningSceneMonitor::scenePublishingThread()
00306 {
00307 ROS_DEBUG("Started scene publishing thread ...");
00308
00309
00310 moveit_msgs::PlanningScene msg;
00311 scene_->getPlanningSceneMsg(msg);
00312 planning_scene_publisher_.publish(msg);
00313 ROS_DEBUG("Published the full planning scene: '%s'", msg.name.c_str());
00314
00315 do
00316 {
00317 bool publish_msg = false;
00318 bool is_full = false;
00319 ros::Rate rate(publish_planning_scene_frequency_);
00320 {
00321 boost::unique_lock<boost::shared_mutex> ulock(scene_update_mutex_);
00322 while (new_scene_update_ == UPDATE_NONE && publish_planning_scene_)
00323 new_scene_update_condition_.wait(ulock);
00324 if (new_scene_update_ != UPDATE_NONE)
00325 {
00326 if ((publish_update_types_ & new_scene_update_) ||
00327 new_scene_update_ == UPDATE_SCENE)
00328 {
00329 if (new_scene_update_ == UPDATE_SCENE)
00330 is_full = true;
00331 else
00332 scene_->getPlanningSceneDiffMsg(msg);
00333 boost::recursive_mutex::scoped_lock prevent_shape_cache_updates(shape_handles_lock_);
00334 scene_->setAttachedBodyUpdateCallback(robot_state::AttachedBodyCallback());
00335 scene_->setCollisionObjectUpdateCallback(collision_detection::World::ObserverCallbackFn());
00336 scene_->pushDiffs(parent_scene_);
00337 scene_->clearDiffs();
00338 scene_->setAttachedBodyUpdateCallback(boost::bind(&PlanningSceneMonitor::currentStateAttachedBodyUpdateCallback, this, _1, _2));
00339 scene_->setCollisionObjectUpdateCallback(boost::bind(&PlanningSceneMonitor::currentWorldObjectUpdateCallback, this, _1, _2));
00340 if (octomap_monitor_)
00341 {
00342 excludeAttachedBodiesFromOctree();
00343 excludeWorldObjectsFromOctree();
00344 }
00345 if (is_full)
00346 scene_->getPlanningSceneMsg(msg);
00347 publish_msg = true;
00348 }
00349 new_scene_update_ = UPDATE_NONE;
00350 }
00351 }
00352 if (publish_msg)
00353 {
00354 rate.reset();
00355 planning_scene_publisher_.publish(msg);
00356 if (is_full)
00357 ROS_DEBUG("Published full planning scene: '%s'", msg.name.c_str());
00358 rate.sleep();
00359 }
00360 }
00361 while (publish_planning_scene_);
00362 }
00363
00364 void planning_scene_monitor::PlanningSceneMonitor::getMonitoredTopics(std::vector<std::string> &topics) const
00365 {
00366 topics.clear();
00367 if (current_state_monitor_)
00368 {
00369 const std::string &t = current_state_monitor_->getMonitoredTopic();
00370 if (!t.empty())
00371 topics.push_back(t);
00372 }
00373 if (planning_scene_subscriber_)
00374 topics.push_back(planning_scene_subscriber_.getTopic());
00375 if (collision_object_subscriber_)
00376 topics.push_back(collision_object_subscriber_->getTopic());
00377 if (planning_scene_world_subscriber_)
00378 topics.push_back(planning_scene_world_subscriber_.getTopic());
00379 }
00380
00381 namespace
00382 {
00383 bool sceneIsParentOf(const planning_scene::PlanningSceneConstPtr &scene, const planning_scene::PlanningScene *possible_parent)
00384 {
00385 if (scene && scene.get() == possible_parent)
00386 return true;
00387 if (scene)
00388 return sceneIsParentOf(scene->getParent(), possible_parent);
00389 return false;
00390 }
00391 }
00392
00393 bool planning_scene_monitor::PlanningSceneMonitor::updatesScene(const planning_scene::PlanningScenePtr &scene) const
00394 {
00395 return sceneIsParentOf(scene_const_, scene.get());
00396 }
00397
00398 bool planning_scene_monitor::PlanningSceneMonitor::updatesScene(const planning_scene::PlanningSceneConstPtr &scene) const
00399 {
00400 return sceneIsParentOf(scene_const_, scene.get());
00401 }
00402
00403 void planning_scene_monitor::PlanningSceneMonitor::triggerSceneUpdateEvent(SceneUpdateType update_type)
00404 {
00405
00406 boost::recursive_mutex::scoped_lock lock(update_lock_);
00407
00408 for (std::size_t i = 0 ; i < update_callbacks_.size() ; ++i)
00409 update_callbacks_[i](update_type);
00410 new_scene_update_ = (SceneUpdateType) ((int)new_scene_update_ | (int)update_type);
00411 new_scene_update_condition_.notify_all();
00412 }
00413
00414 bool planning_scene_monitor::PlanningSceneMonitor::requestPlanningSceneState(const std::string& service_name)
00415 {
00416
00417 ros::ServiceClient client = ros::NodeHandle().serviceClient<moveit_msgs::GetPlanningScene>(service_name);
00418 moveit_msgs::GetPlanningScene srv;
00419 srv.request.components.components =
00420 srv.request.components.SCENE_SETTINGS |
00421 srv.request.components.ROBOT_STATE |
00422 srv.request.components.ROBOT_STATE_ATTACHED_OBJECTS |
00423 srv.request.components.WORLD_OBJECT_NAMES |
00424 srv.request.components.WORLD_OBJECT_GEOMETRY |
00425 srv.request.components.OCTOMAP |
00426 srv.request.components.TRANSFORMS |
00427 srv.request.components.ALLOWED_COLLISION_MATRIX |
00428 srv.request.components.LINK_PADDING_AND_SCALING |
00429 srv.request.components.OBJECT_COLORS;
00430
00431
00432 if (!client.exists())
00433 {
00434 ROS_DEBUG_STREAM("Waiting for service `" << service_name << "` to exist.");
00435 client.waitForExistence(ros::Duration(5.0));
00436 }
00437
00438 if (client.call(srv))
00439 {
00440 newPlanningSceneMessage(srv.response.scene);
00441 }
00442 else
00443 {
00444 ROS_WARN("Failed to call service %s, have you launched move_group? at %s:%d",
00445 service_name.c_str(),
00446 __FILE__,
00447 __LINE__);
00448 return false;
00449 }
00450 return true;
00451 }
00452
00453 void planning_scene_monitor::PlanningSceneMonitor::newPlanningSceneCallback(const moveit_msgs::PlanningSceneConstPtr &scene)
00454 {
00455 newPlanningSceneMessage(*scene);
00456 }
00457
00458 void planning_scene_monitor::PlanningSceneMonitor::newPlanningSceneMessage(const moveit_msgs::PlanningScene& scene)
00459 {
00460 if (scene_)
00461 {
00462 SceneUpdateType upd = UPDATE_SCENE;
00463 std::string old_scene_name;
00464 {
00465 boost::unique_lock<boost::shared_mutex> ulock(scene_update_mutex_);
00466 boost::recursive_mutex::scoped_lock prevent_shape_cache_updates(shape_handles_lock_);
00467
00468 last_update_time_ = ros::Time::now();
00469 old_scene_name = scene_->getName();
00470 scene_->usePlanningSceneMsg(scene);
00471 if (octomap_monitor_)
00472 {
00473 if (!scene.is_diff && scene.world.octomap.octomap.data.empty())
00474 {
00475 octomap_monitor_->getOcTreePtr()->lockWrite();
00476 octomap_monitor_->getOcTreePtr()->clear();
00477 octomap_monitor_->getOcTreePtr()->unlockWrite();
00478 }
00479 }
00480 robot_model_ = scene_->getRobotModel();
00481
00482
00483 if (!scene.is_diff && parent_scene_)
00484 {
00485
00486 scene_->setAttachedBodyUpdateCallback(robot_state::AttachedBodyCallback());
00487 scene_->setCollisionObjectUpdateCallback(collision_detection::World::ObserverCallbackFn());
00488 parent_scene_ = scene_;
00489 scene_ = parent_scene_->diff();
00490 scene_const_ = scene_;
00491 scene_->setAttachedBodyUpdateCallback(boost::bind(&PlanningSceneMonitor::currentStateAttachedBodyUpdateCallback, this, _1, _2));
00492 scene_->setCollisionObjectUpdateCallback(boost::bind(&PlanningSceneMonitor::currentWorldObjectUpdateCallback, this, _1, _2));
00493 }
00494 if (octomap_monitor_)
00495 {
00496 excludeAttachedBodiesFromOctree();
00497 excludeWorldObjectsFromOctree();
00498 }
00499 }
00500
00501
00502 if (scene.is_diff)
00503 {
00504 bool no_other_scene_upd = (scene.name.empty() || scene.name == old_scene_name) &&
00505 scene.allowed_collision_matrix.entry_names.empty() && scene.link_padding.empty() && scene.link_scale.empty();
00506 if (no_other_scene_upd)
00507 {
00508 upd = UPDATE_NONE;
00509 if (!planning_scene::PlanningScene::isEmpty(scene.world))
00510 upd = (SceneUpdateType) ((int)upd | (int)UPDATE_GEOMETRY);
00511
00512 if (!scene.fixed_frame_transforms.empty())
00513 upd = (SceneUpdateType) ((int)upd | (int)UPDATE_TRANSFORMS);
00514
00515 if (!planning_scene::PlanningScene::isEmpty(scene.robot_state))
00516 {
00517 upd = (SceneUpdateType) ((int)upd | (int)UPDATE_STATE);
00518 if (!scene.robot_state.attached_collision_objects.empty() || scene.robot_state.is_diff == false)
00519 upd = (SceneUpdateType) ((int)upd | (int)UPDATE_GEOMETRY);
00520 }
00521 }
00522 }
00523 triggerSceneUpdateEvent(upd);
00524 }
00525 }
00526
00527 void planning_scene_monitor::PlanningSceneMonitor::newPlanningSceneWorldCallback(const moveit_msgs::PlanningSceneWorldConstPtr &world)
00528 {
00529 if (scene_)
00530 {
00531 updateFrameTransforms();
00532 {
00533 boost::unique_lock<boost::shared_mutex> ulock(scene_update_mutex_);
00534 last_update_time_ = ros::Time::now();
00535 scene_->getWorldNonConst()->clearObjects();
00536 scene_->processPlanningSceneWorldMsg(*world);
00537 if (octomap_monitor_)
00538 {
00539 if (world->octomap.octomap.data.empty())
00540 {
00541 octomap_monitor_->getOcTreePtr()->lockWrite();
00542 octomap_monitor_->getOcTreePtr()->clear();
00543 octomap_monitor_->getOcTreePtr()->unlockWrite();
00544 }
00545 }
00546 }
00547 triggerSceneUpdateEvent(UPDATE_SCENE);
00548 }
00549 }
00550
00551 void planning_scene_monitor::PlanningSceneMonitor::collisionObjectFailTFCallback(const moveit_msgs::CollisionObjectConstPtr &obj, tf::filter_failure_reasons::FilterFailureReason reason)
00552 {
00553
00554 if (reason == tf::filter_failure_reasons::EmptyFrameID && obj->operation == moveit_msgs::CollisionObject::REMOVE)
00555 collisionObjectCallback(obj);
00556 }
00557
00558 void planning_scene_monitor::PlanningSceneMonitor::collisionObjectCallback(const moveit_msgs::CollisionObjectConstPtr &obj)
00559 {
00560 if (scene_)
00561 {
00562 updateFrameTransforms();
00563 {
00564 boost::unique_lock<boost::shared_mutex> ulock(scene_update_mutex_);
00565 last_update_time_ = ros::Time::now();
00566 scene_->processCollisionObjectMsg(*obj);
00567 }
00568 triggerSceneUpdateEvent(UPDATE_GEOMETRY);
00569 }
00570 }
00571
00572 void planning_scene_monitor::PlanningSceneMonitor::attachObjectCallback(const moveit_msgs::AttachedCollisionObjectConstPtr &obj)
00573 {
00574 if (scene_)
00575 {
00576 updateFrameTransforms();
00577 {
00578 boost::unique_lock<boost::shared_mutex> ulock(scene_update_mutex_);
00579 last_update_time_ = ros::Time::now();
00580 scene_->processAttachedCollisionObjectMsg(*obj);
00581 }
00582 triggerSceneUpdateEvent(UPDATE_GEOMETRY);
00583 }
00584 }
00585
00586 void planning_scene_monitor::PlanningSceneMonitor::excludeRobotLinksFromOctree()
00587 {
00588 if (!octomap_monitor_)
00589 return;
00590
00591 boost::recursive_mutex::scoped_lock _(shape_handles_lock_);
00592
00593 includeRobotLinksInOctree();
00594 const std::vector<const robot_model::LinkModel*> &links = getRobotModel()->getLinkModelsWithCollisionGeometry();
00595 for (std::size_t i = 0 ; i < links.size() ; ++i)
00596 {
00597 std::vector<shapes::ShapeConstPtr> shapes = links[i]->getShapes();
00598 for (std::size_t j = 0 ; j < shapes.size() ; ++j)
00599 {
00600
00601 if (shapes[j]->type == shapes::MESH)
00602 {
00603 shapes::Mesh *m = static_cast<shapes::Mesh*>(shapes[j]->clone());
00604 m->mergeVertices(1e-4);
00605 shapes[j].reset(m);
00606 }
00607
00608 occupancy_map_monitor::ShapeHandle h = octomap_monitor_->excludeShape(shapes[j]);
00609 if (h)
00610 link_shape_handles_[links[i]].push_back(std::make_pair(h, j));
00611 }
00612 }
00613 }
00614
00615 void planning_scene_monitor::PlanningSceneMonitor::includeRobotLinksInOctree()
00616 {
00617 if (!octomap_monitor_)
00618 return;
00619
00620 boost::recursive_mutex::scoped_lock _(shape_handles_lock_);
00621
00622 for (LinkShapeHandles::iterator it = link_shape_handles_.begin() ; it != link_shape_handles_.end() ; ++it)
00623 for (std::size_t i = 0 ; i < it->second.size() ; ++i)
00624 octomap_monitor_->forgetShape(it->second[i].first);
00625 link_shape_handles_.clear();
00626 }
00627
00628 void planning_scene_monitor::PlanningSceneMonitor::includeAttachedBodiesInOctree()
00629 {
00630 if (!octomap_monitor_)
00631 return;
00632
00633 boost::recursive_mutex::scoped_lock _(shape_handles_lock_);
00634
00635
00636 for (AttachedBodyShapeHandles::iterator it = attached_body_shape_handles_.begin() ; it != attached_body_shape_handles_.end() ; ++it)
00637 for (std::size_t k = 0 ; k < it->second.size() ; ++k)
00638 octomap_monitor_->forgetShape(it->second[k].first);
00639 attached_body_shape_handles_.clear();
00640 }
00641
00642 void planning_scene_monitor::PlanningSceneMonitor::excludeAttachedBodiesFromOctree()
00643 {
00644 boost::recursive_mutex::scoped_lock _(shape_handles_lock_);
00645
00646 includeAttachedBodiesInOctree();
00647
00648 std::vector<const robot_state::AttachedBody*> ab;
00649 scene_->getCurrentState().getAttachedBodies(ab);
00650 for (std::size_t i = 0 ; i < ab.size() ; ++i)
00651 excludeAttachedBodyFromOctree(ab[i]);
00652 }
00653
00654 void planning_scene_monitor::PlanningSceneMonitor::includeWorldObjectsInOctree()
00655 {
00656 if (!octomap_monitor_)
00657 return;
00658
00659 boost::recursive_mutex::scoped_lock _(shape_handles_lock_);
00660
00661
00662 for (CollisionBodyShapeHandles::iterator it = collision_body_shape_handles_.begin() ; it != collision_body_shape_handles_.end() ; ++it)
00663 for (std::size_t k = 0 ; k < it->second.size() ; ++k)
00664 octomap_monitor_->forgetShape(it->second[k].first);
00665 collision_body_shape_handles_.clear();
00666 }
00667
00668 void planning_scene_monitor::PlanningSceneMonitor::excludeWorldObjectsFromOctree()
00669 {
00670 boost::recursive_mutex::scoped_lock _(shape_handles_lock_);
00671
00672 includeWorldObjectsInOctree();
00673 for (collision_detection::World::const_iterator it = scene_->getWorld()->begin(); it != scene_->getWorld()->end() ; ++it)
00674 excludeWorldObjectFromOctree(it->second);
00675 }
00676
00677 void planning_scene_monitor::PlanningSceneMonitor::excludeAttachedBodyFromOctree(const robot_state::AttachedBody *attached_body)
00678 {
00679 if (!octomap_monitor_)
00680 return;
00681
00682 boost::recursive_mutex::scoped_lock _(shape_handles_lock_);
00683 bool found = false;
00684 for (std::size_t i = 0 ; i < attached_body->getShapes().size() ; ++i)
00685 {
00686 if (attached_body->getShapes()[i]->type == shapes::PLANE || attached_body->getShapes()[i]->type == shapes::OCTREE)
00687 continue;
00688 occupancy_map_monitor::ShapeHandle h = octomap_monitor_->excludeShape(attached_body->getShapes()[i]);
00689 if (h)
00690 {
00691 found = true;
00692 attached_body_shape_handles_[attached_body].push_back(std::make_pair(h, i));
00693 }
00694 }
00695 if (found)
00696 ROS_DEBUG("Excluding attached body '%s' from monitored octomap", attached_body->getName().c_str());
00697 }
00698
00699 void planning_scene_monitor::PlanningSceneMonitor::includeAttachedBodyInOctree(const robot_state::AttachedBody *attached_body)
00700 {
00701 if (!octomap_monitor_)
00702 return;
00703
00704 boost::recursive_mutex::scoped_lock _(shape_handles_lock_);
00705
00706 AttachedBodyShapeHandles::iterator it = attached_body_shape_handles_.find(attached_body);
00707 if (it != attached_body_shape_handles_.end())
00708 {
00709 for (std::size_t k = 0 ; k < it->second.size() ; ++k)
00710 octomap_monitor_->forgetShape(it->second[k].first);
00711 ROS_DEBUG("Including attached body '%s' in monitored octomap", attached_body->getName().c_str());
00712 attached_body_shape_handles_.erase(it);
00713 }
00714 }
00715
00716 void planning_scene_monitor::PlanningSceneMonitor::excludeWorldObjectFromOctree(const collision_detection::World::ObjectConstPtr &obj)
00717 {
00718 if (!octomap_monitor_)
00719 return;
00720
00721 boost::recursive_mutex::scoped_lock _(shape_handles_lock_);
00722
00723 bool found = false;
00724 for (std::size_t i = 0 ; i < obj->shapes_.size() ; ++i)
00725 {
00726 if (obj->shapes_[i]->type == shapes::PLANE || obj->shapes_[i]->type == shapes::OCTREE)
00727 continue;
00728 occupancy_map_monitor::ShapeHandle h = octomap_monitor_->excludeShape(obj->shapes_[i]);
00729 if (h)
00730 {
00731 collision_body_shape_handles_[obj->id_].push_back(std::make_pair(h, &obj->shape_poses_[i]));
00732 found = true;
00733 }
00734 }
00735 if (found)
00736 ROS_DEBUG("Excluding collision object '%s' from monitored octomap", obj->id_.c_str());
00737 }
00738
00739 void planning_scene_monitor::PlanningSceneMonitor::includeWorldObjectInOctree(const collision_detection::World::ObjectConstPtr &obj)
00740 {
00741 if (!octomap_monitor_)
00742 return;
00743
00744 boost::recursive_mutex::scoped_lock _(shape_handles_lock_);
00745
00746 CollisionBodyShapeHandles::iterator it = collision_body_shape_handles_.find(obj->id_);
00747 if (it != collision_body_shape_handles_.end())
00748 {
00749 for (std::size_t k = 0 ; k < it->second.size() ; ++k)
00750 octomap_monitor_->forgetShape(it->second[k].first);
00751 ROS_DEBUG("Including collision object '%s' in monitored octomap", obj->id_.c_str());
00752 collision_body_shape_handles_.erase(it);
00753 }
00754 }
00755
00756 void planning_scene_monitor::PlanningSceneMonitor::currentStateAttachedBodyUpdateCallback(robot_state::AttachedBody *attached_body, bool just_attached)
00757 {
00758 if (!octomap_monitor_)
00759 return;
00760
00761 if (just_attached)
00762 excludeAttachedBodyFromOctree(attached_body);
00763 else
00764 includeAttachedBodyInOctree(attached_body);
00765 }
00766
00767 void planning_scene_monitor::PlanningSceneMonitor::currentWorldObjectUpdateCallback(const collision_detection::World::ObjectConstPtr &obj, collision_detection::World::Action action)
00768 {
00769 if (!octomap_monitor_)
00770 return;
00771 if (obj->id_ == planning_scene::PlanningScene::OCTOMAP_NS)
00772 return;
00773
00774 if (action & collision_detection::World::CREATE)
00775 excludeWorldObjectFromOctree(obj);
00776 else
00777 if (action & collision_detection::World::DESTROY)
00778 includeWorldObjectInOctree(obj);
00779 else
00780 {
00781 excludeWorldObjectFromOctree(obj);
00782 includeWorldObjectInOctree(obj);
00783 }
00784 }
00785
00786 void planning_scene_monitor::PlanningSceneMonitor::lockSceneRead()
00787 {
00788 scene_update_mutex_.lock_shared();
00789 if (octomap_monitor_)
00790 octomap_monitor_->getOcTreePtr()->lockRead();
00791 }
00792
00793 void planning_scene_monitor::PlanningSceneMonitor::unlockSceneRead()
00794 {
00795 scene_update_mutex_.unlock_shared();
00796 if (octomap_monitor_)
00797 octomap_monitor_->getOcTreePtr()->unlockRead();
00798 }
00799
00800 void planning_scene_monitor::PlanningSceneMonitor::lockSceneWrite()
00801 {
00802 scene_update_mutex_.lock();
00803 if (octomap_monitor_)
00804 octomap_monitor_->getOcTreePtr()->lockWrite();
00805 }
00806
00807 void planning_scene_monitor::PlanningSceneMonitor::unlockSceneWrite()
00808 {
00809 scene_update_mutex_.unlock();
00810 if (octomap_monitor_)
00811 octomap_monitor_->getOcTreePtr()->unlockWrite();
00812 }
00813
00814 void planning_scene_monitor::PlanningSceneMonitor::startSceneMonitor(const std::string &scene_topic)
00815 {
00816 stopSceneMonitor();
00817
00818 ROS_INFO("Starting scene monitor");
00819
00820 if (!scene_topic.empty())
00821 {
00822 planning_scene_subscriber_ = root_nh_.subscribe(scene_topic, 100, &PlanningSceneMonitor::newPlanningSceneCallback, this);
00823 ROS_INFO("Listening to '%s'", root_nh_.resolveName(scene_topic).c_str());
00824 }
00825 }
00826
00827 void planning_scene_monitor::PlanningSceneMonitor::stopSceneMonitor()
00828 {
00829 if (planning_scene_subscriber_)
00830 {
00831 ROS_INFO("Stopping scene monitor");
00832 planning_scene_subscriber_.shutdown();
00833 }
00834 }
00835
00836 bool planning_scene_monitor::PlanningSceneMonitor::getShapeTransformCache(const std::string &target_frame, const ros::Time &target_time,
00837 occupancy_map_monitor::ShapeTransformCache &cache) const
00838 {
00839 if (!tf_)
00840 return false;
00841 try
00842 {
00843 boost::recursive_mutex::scoped_lock _(shape_handles_lock_);
00844
00845 for (LinkShapeHandles::const_iterator it = link_shape_handles_.begin() ; it != link_shape_handles_.end() ; ++it)
00846 {
00847 tf::StampedTransform tr;
00848 tf_->waitForTransform(target_frame, it->first->getName(), target_time, shape_transform_cache_lookup_wait_time_);
00849 tf_->lookupTransform(target_frame, it->first->getName(), target_time, tr);
00850 Eigen::Affine3d ttr;
00851 tf::transformTFToEigen(tr, ttr);
00852 for (std::size_t j = 0 ; j < it->second.size() ; ++j)
00853 cache[it->second[j].first] = ttr * it->first->getCollisionOriginTransforms()[it->second[j].second];
00854 }
00855 for (AttachedBodyShapeHandles::const_iterator it = attached_body_shape_handles_.begin() ; it != attached_body_shape_handles_.end() ; ++it)
00856 {
00857 tf::StampedTransform tr;
00858 tf_->waitForTransform(target_frame, it->first->getAttachedLinkName(), target_time, shape_transform_cache_lookup_wait_time_);
00859 tf_->lookupTransform(target_frame, it->first->getAttachedLinkName(), target_time, tr);
00860 Eigen::Affine3d transform;
00861 tf::transformTFToEigen(tr, transform);
00862 for (std::size_t k = 0 ; k < it->second.size() ; ++k)
00863 cache[it->second[k].first] = transform * it->first->getFixedTransforms()[it->second[k].second];
00864 }
00865 {
00866 tf::StampedTransform tr;
00867 tf_->waitForTransform(target_frame, scene_->getPlanningFrame(), target_time, shape_transform_cache_lookup_wait_time_);
00868 tf_->lookupTransform(target_frame, scene_->getPlanningFrame(), target_time, tr);
00869 Eigen::Affine3d transform;
00870 tf::transformTFToEigen(tr, transform);
00871 for (CollisionBodyShapeHandles::const_iterator it = collision_body_shape_handles_.begin() ; it != collision_body_shape_handles_.end() ; ++it)
00872 for (std::size_t k = 0 ; k < it->second.size() ; ++k)
00873 cache[it->second[k].first] = transform * (*it->second[k].second);
00874 }
00875 }
00876 catch (tf::TransformException& ex)
00877 {
00878 ROS_ERROR_THROTTLE(1, "Transform error: %s", ex.what());
00879 return false;
00880 }
00881 return true;
00882 }
00883
00884 void planning_scene_monitor::PlanningSceneMonitor::startWorldGeometryMonitor(const std::string &collision_objects_topic,
00885 const std::string &planning_scene_world_topic,
00886 const bool load_octomap_monitor)
00887 {
00888 stopWorldGeometryMonitor();
00889 ROS_INFO("Starting world geometry monitor");
00890
00891
00892 if (!collision_objects_topic.empty())
00893 {
00894 collision_object_subscriber_.reset(new message_filters::Subscriber<moveit_msgs::CollisionObject>(root_nh_, collision_objects_topic, 1024));
00895 if (tf_)
00896 {
00897 collision_object_filter_ .reset(new tf::MessageFilter<moveit_msgs::CollisionObject>(*collision_object_subscriber_, *tf_, scene_->getPlanningFrame(), 1024));
00898 collision_object_filter_->registerCallback(boost::bind(&PlanningSceneMonitor::collisionObjectCallback, this, _1));
00899 collision_object_filter_->registerFailureCallback(boost::bind(&PlanningSceneMonitor::collisionObjectFailTFCallback, this, _1, _2));
00900 ROS_INFO("Listening to '%s' using message notifier with target frame '%s'", root_nh_.resolveName(collision_objects_topic).c_str(), collision_object_filter_->getTargetFramesString().c_str());
00901 }
00902 else
00903 {
00904 collision_object_subscriber_->registerCallback(boost::bind(&PlanningSceneMonitor::collisionObjectCallback, this, _1));
00905 ROS_INFO("Listening to '%s'", root_nh_.resolveName(collision_objects_topic).c_str());
00906 }
00907 }
00908
00909 if (!planning_scene_world_topic.empty())
00910 {
00911 planning_scene_world_subscriber_ = root_nh_.subscribe(planning_scene_world_topic, 1, &PlanningSceneMonitor::newPlanningSceneWorldCallback, this);
00912 ROS_INFO("Listening to '%s' for planning scene world geometry", root_nh_.resolveName(planning_scene_world_topic).c_str());
00913 }
00914
00915
00916 if (load_octomap_monitor)
00917 {
00918 if (!octomap_monitor_)
00919 {
00920 octomap_monitor_.reset(new occupancy_map_monitor::OccupancyMapMonitor(tf_, scene_->getPlanningFrame()));
00921 excludeRobotLinksFromOctree();
00922 excludeAttachedBodiesFromOctree();
00923 excludeWorldObjectsFromOctree();
00924
00925 octomap_monitor_->setTransformCacheCallback(boost::bind(&PlanningSceneMonitor::getShapeTransformCache, this, _1, _2, _3));
00926 octomap_monitor_->setUpdateCallback(boost::bind(&PlanningSceneMonitor::octomapUpdateCallback, this));
00927 }
00928 octomap_monitor_->startMonitor();
00929 }
00930 }
00931
00932 void planning_scene_monitor::PlanningSceneMonitor::stopWorldGeometryMonitor()
00933 {
00934 if (collision_object_subscriber_ || collision_object_filter_)
00935 {
00936 ROS_INFO("Stopping world geometry monitor");
00937 collision_object_filter_.reset();
00938 collision_object_subscriber_.reset();
00939 planning_scene_world_subscriber_.shutdown();
00940 }
00941 else
00942 if (planning_scene_world_subscriber_)
00943 {
00944 ROS_INFO("Stopping world geometry monitor");
00945 planning_scene_world_subscriber_.shutdown();
00946 }
00947 if (octomap_monitor_)
00948 octomap_monitor_->stopMonitor();
00949 }
00950
00951 void planning_scene_monitor::PlanningSceneMonitor::startStateMonitor(const std::string &joint_states_topic, const std::string &attached_objects_topic)
00952 {
00953 stopStateMonitor();
00954 if (scene_)
00955 {
00956 if (!current_state_monitor_)
00957 current_state_monitor_.reset(new CurrentStateMonitor(getRobotModel(), tf_));
00958 current_state_monitor_->addUpdateCallback(boost::bind(&PlanningSceneMonitor::onStateUpdate, this, _1));
00959 current_state_monitor_->startStateMonitor(joint_states_topic);
00960
00961 {
00962 boost::mutex::scoped_lock lock(state_pending_mutex_);
00963 if (!dt_state_update_.isZero())
00964 state_update_timer_.start();
00965 }
00966
00967 if (!attached_objects_topic.empty())
00968 {
00969
00970 attached_collision_object_subscriber_ = root_nh_.subscribe(attached_objects_topic, 1024, &PlanningSceneMonitor::attachObjectCallback, this);
00971 ROS_INFO("Listening to '%s' for attached collision objects", root_nh_.resolveName(attached_objects_topic).c_str());
00972 }
00973 }
00974 else
00975 ROS_ERROR("Cannot monitor robot state because planning scene is not configured");
00976 }
00977
00978 void planning_scene_monitor::PlanningSceneMonitor::stopStateMonitor()
00979 {
00980 if (current_state_monitor_)
00981 current_state_monitor_->stopStateMonitor();
00982 if (attached_collision_object_subscriber_)
00983 attached_collision_object_subscriber_.shutdown();
00984
00985
00986 state_update_timer_.stop();
00987 {
00988 boost::mutex::scoped_lock lock(state_pending_mutex_);
00989 state_update_pending_ = false;
00990 }
00991 }
00992
00993 void planning_scene_monitor::PlanningSceneMonitor::onStateUpdate(const sensor_msgs::JointStateConstPtr & )
00994 {
00995 const ros::WallTime &n = ros::WallTime::now();
00996 ros::WallDuration dt = n - last_state_update_;
00997
00998 bool update = false;
00999 {
01000 boost::mutex::scoped_lock lock(state_pending_mutex_);
01001
01002 if (dt < dt_state_update_)
01003 {
01004 state_update_pending_ = true;
01005 }
01006 else
01007 {
01008 state_update_pending_ = false;
01009 last_state_update_ = n;
01010 update = true;
01011 }
01012 }
01013
01014
01015 if (update)
01016 updateSceneWithCurrentState();
01017 }
01018
01019 void planning_scene_monitor::PlanningSceneMonitor::stateUpdateTimerCallback(const ros::WallTimerEvent& event)
01020 {
01021 if (state_update_pending_)
01022 {
01023 bool update = false;
01024
01025 const ros::WallTime &n = ros::WallTime::now();
01026 ros::WallDuration dt = n - last_state_update_;
01027
01028 {
01029
01030 boost::mutex::scoped_lock lock(state_pending_mutex_);
01031 if (state_update_pending_ && dt >= dt_state_update_)
01032 {
01033 state_update_pending_ = false;
01034 last_state_update_ = ros::WallTime::now();
01035 update = true;
01036 }
01037 }
01038
01039
01040 if (update)
01041 updateSceneWithCurrentState();
01042 }
01043 }
01044
01045 void planning_scene_monitor::PlanningSceneMonitor::octomapUpdateCallback()
01046 {
01047 if (!octomap_monitor_)
01048 return;
01049
01050 updateFrameTransforms();
01051 {
01052 boost::unique_lock<boost::shared_mutex> ulock(scene_update_mutex_);
01053 last_update_time_ = ros::Time::now();
01054 octomap_monitor_->getOcTreePtr()->lockRead();
01055 try
01056 {
01057 scene_->processOctomapPtr(octomap_monitor_->getOcTreePtr(), Eigen::Affine3d::Identity());
01058 octomap_monitor_->getOcTreePtr()->unlockRead();
01059 }
01060 catch(...)
01061 {
01062 octomap_monitor_->getOcTreePtr()->unlockRead();
01063 throw;
01064 }
01065 }
01066 triggerSceneUpdateEvent(UPDATE_GEOMETRY);
01067 }
01068
01069 void planning_scene_monitor::PlanningSceneMonitor::setStateUpdateFrequency(double hz)
01070 {
01071 bool update = false;
01072 if (hz > std::numeric_limits<double>::epsilon())
01073 {
01074 boost::mutex::scoped_lock lock(state_pending_mutex_);
01075 dt_state_update_.fromSec(1.0 / hz);
01076 state_update_timer_.setPeriod(dt_state_update_);
01077 state_update_timer_.start();
01078 }
01079 else
01080 {
01081
01082 state_update_timer_.stop();
01083 boost::mutex::scoped_lock lock(state_pending_mutex_);
01084 dt_state_update_ = ros::WallDuration(0,0);
01085 if (state_update_pending_)
01086 update = true;
01087 }
01088 ROS_INFO("Updating internal planning scene state at most every %lf seconds", dt_state_update_.toSec());
01089
01090 if (update)
01091 updateSceneWithCurrentState();
01092 }
01093
01094 void planning_scene_monitor::PlanningSceneMonitor::updateSceneWithCurrentState()
01095 {
01096 if (current_state_monitor_)
01097 {
01098 std::vector<std::string> missing;
01099 if (!current_state_monitor_->haveCompleteState(missing) && (ros::Time::now() - current_state_monitor_->getMonitorStartTime()).toSec() > 1.0)
01100 {
01101 std::string missing_str = boost::algorithm::join(missing, ", ");
01102 ROS_WARN_THROTTLE(1, "The complete state of the robot is not yet known. Missing %s", missing_str.c_str());
01103 }
01104
01105 {
01106 boost::unique_lock<boost::shared_mutex> ulock(scene_update_mutex_);
01107 current_state_monitor_->setToCurrentState(scene_->getCurrentStateNonConst());
01108 last_update_time_ = ros::Time::now();
01109 scene_->getCurrentStateNonConst().update();
01110 }
01111 triggerSceneUpdateEvent(UPDATE_STATE);
01112 }
01113 else
01114 ROS_ERROR_THROTTLE(1, "State monitor is not active. Unable to set the planning scene state");
01115 }
01116
01117 void planning_scene_monitor::PlanningSceneMonitor::addUpdateCallback(const boost::function<void(SceneUpdateType)> &fn)
01118 {
01119 boost::recursive_mutex::scoped_lock lock(update_lock_);
01120 if (fn)
01121 update_callbacks_.push_back(fn);
01122 }
01123
01124 void planning_scene_monitor::PlanningSceneMonitor::clearUpdateCallbacks()
01125 {
01126 boost::recursive_mutex::scoped_lock lock(update_lock_);
01127 update_callbacks_.clear();
01128 }
01129
01130 void planning_scene_monitor::PlanningSceneMonitor::setPlanningScenePublishingFrequency(double hz)
01131 {
01132 publish_planning_scene_frequency_ = hz;
01133 ROS_DEBUG("Maximum frquency for publishing a planning scene is now %lf Hz", publish_planning_scene_frequency_);
01134 }
01135
01136 void planning_scene_monitor::PlanningSceneMonitor::getUpdatedFrameTransforms(std::vector<geometry_msgs::TransformStamped> &transforms)
01137 {
01138 const std::string &target = getRobotModel()->getModelFrame();
01139
01140 std::vector<std::string> all_frame_names;
01141 tf_->getFrameStrings(all_frame_names);
01142 for (std::size_t i = 0 ; i < all_frame_names.size() ; ++i)
01143 {
01144 const std::string &frame_no_slash = (!all_frame_names[i].empty() && all_frame_names[i][0] == '/') ? all_frame_names[i].substr(1) : all_frame_names[i];
01145 const std::string &frame_with_slash = (!all_frame_names[i].empty() && all_frame_names[i][0] != '/') ? '/' + all_frame_names[i] : all_frame_names[i];
01146
01147 if (frame_with_slash == target || getRobotModel()->hasLinkModel(frame_no_slash))
01148 continue;
01149
01150 ros::Time stamp(0);
01151 std::string err_string;
01152 if (tf_->getLatestCommonTime(target, all_frame_names[i], stamp, &err_string) != tf::NO_ERROR)
01153 {
01154 ROS_WARN_STREAM("No transform available between frame '" << all_frame_names[i] << "' and planning frame '" <<
01155 target << "' (" << err_string << ")");
01156 continue;
01157 }
01158
01159 tf::StampedTransform t;
01160 try
01161 {
01162 tf_->lookupTransform(target, all_frame_names[i], stamp, t);
01163 }
01164 catch (tf::TransformException& ex)
01165 {
01166 ROS_WARN_STREAM("Unable to transform object from frame '" << all_frame_names[i] << "' to planning frame '" <<
01167 target << "' (" << ex.what() << ")");
01168 continue;
01169 }
01170 geometry_msgs::TransformStamped f;
01171 f.header.frame_id = frame_with_slash;
01172 f.child_frame_id = target;
01173 f.transform.translation.x = t.getOrigin().x();
01174 f.transform.translation.y = t.getOrigin().y();
01175 f.transform.translation.z = t.getOrigin().z();
01176 const tf::Quaternion &q = t.getRotation();
01177 f.transform.rotation.x = q.x();
01178 f.transform.rotation.y = q.y();
01179 f.transform.rotation.z = q.z();
01180 f.transform.rotation.w = q.w();
01181 transforms.push_back(f);
01182 }
01183 }
01184
01185 void planning_scene_monitor::PlanningSceneMonitor::updateFrameTransforms()
01186 {
01187 if (!tf_)
01188 return;
01189
01190 if (scene_)
01191 {
01192 std::vector<geometry_msgs::TransformStamped> transforms;
01193 getUpdatedFrameTransforms(transforms);
01194 {
01195 boost::unique_lock<boost::shared_mutex> ulock(scene_update_mutex_);
01196 scene_->getTransformsNonConst().setTransforms(transforms);
01197 last_update_time_ = ros::Time::now();
01198 }
01199 triggerSceneUpdateEvent(UPDATE_TRANSFORMS);
01200 }
01201 }
01202
01203 void planning_scene_monitor::PlanningSceneMonitor::publishDebugInformation(bool flag)
01204 {
01205 if (octomap_monitor_)
01206 octomap_monitor_->publishDebugInformation(flag);
01207 }
01208
01209 void planning_scene_monitor::PlanningSceneMonitor::configureCollisionMatrix(const planning_scene::PlanningScenePtr &scene)
01210 {
01211 if (!scene || robot_description_.empty())
01212 return;
01213 collision_detection::AllowedCollisionMatrix &acm = scene->getAllowedCollisionMatrixNonConst();
01214
01215
01216
01217
01218 if (!nh_.hasParam(robot_description_ + "_planning/default_collision_operations"))
01219 ROS_DEBUG("No additional default collision operations specified");
01220 else
01221 {
01222 ROS_DEBUG("Reading additional default collision operations");
01223
01224 XmlRpc::XmlRpcValue coll_ops;
01225 nh_.getParam(robot_description_ + "_planning/default_collision_operations", coll_ops);
01226
01227 if (coll_ops.getType() != XmlRpc::XmlRpcValue::TypeArray)
01228 {
01229 ROS_WARN("default_collision_operations is not an array");
01230 return;
01231 }
01232
01233 if (coll_ops.size() == 0)
01234 {
01235 ROS_WARN("No collision operations in default collision operations");
01236 return;
01237 }
01238
01239 for (int i = 0 ; i < coll_ops.size() ; ++i)
01240 {
01241 if (!coll_ops[i].hasMember("object1") || !coll_ops[i].hasMember("object2") || !coll_ops[i].hasMember("operation"))
01242 {
01243 ROS_WARN("All collision operations must have two objects and an operation");
01244 continue;
01245 }
01246 acm.setEntry(std::string(coll_ops[i]["object1"]), std::string(coll_ops[i]["object2"]), std::string(coll_ops[i]["operation"]) == "disable");
01247 }
01248 }
01249 }
01250
01251 void planning_scene_monitor::PlanningSceneMonitor::configureDefaultPadding()
01252 {
01253 if (robot_description_.empty())
01254 {
01255 default_robot_padd_ = 0.0;
01256 default_robot_scale_ = 1.0;
01257 default_object_padd_ = 0.0;
01258 default_attached_padd_ = 0.0;
01259 return;
01260 }
01261 nh_.param(robot_description_ + "_planning/default_robot_padding", default_robot_padd_, 0.0);
01262 nh_.param(robot_description_ + "_planning/default_robot_scale", default_robot_scale_, 1.0);
01263 nh_.param(robot_description_ + "_planning/default_object_padding", default_object_padd_, 0.0);
01264 nh_.param(robot_description_ + "_planning/default_attached_padding", default_attached_padd_, 0.0);
01265 nh_.param(robot_description_ + "_planning/default_robot_link_padding", default_robot_link_padd_, std::map<std::string, double>());
01266 nh_.param(robot_description_ + "_planning/default_robot_link_scale", default_robot_link_scale_, std::map<std::string, double>());
01267 }