planning_scene_monitor.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2011, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Willow Garage nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 
00035 /* Author: Ioan Sucan */
00036 
00037 #include <moveit/planning_scene_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   // make sure we do not advertise the same service multiple times, in case we use multiple PlanningSceneMonitor instances in a process
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,    // not a oneshot timer
00230                                             false);   // do not start the timer yet
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           // remove the '+' added by .diff() at the end of the scene name
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   // publish the full planning scene
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_); // we don't want the transform cache to update while we are potentially changing attached bodies
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(); // in case updates have happened to the attached bodies, put them in
00343             excludeWorldObjectsFromOctree(); // in case updates have happened to the attached bodies, put them in
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   // do not modify update functions while we are calling them
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   // use global namespace for service
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   // Make sure client is connected to server
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_); // we don't want the transform cache to update while we are potentially changing attached bodies
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       // if we just reset the scene completely but we were maintaining diffs, we need to fix that
00483       if (!scene.is_diff && parent_scene_)
00484       {
00485         // the scene is now decoupled from the parent, since we just reset it
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(); // in case updates have happened to the attached bodies, put them in
00497         excludeWorldObjectsFromOctree(); // in case updates have happened to the attached bodies, put them in
00498       }
00499     }
00500 
00501     // if we have a diff, try to more accuratelly determine the update type
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   // if we just want to remove objects, the frame does not matter
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(); // copy shared ptrs on purpuse
00598     for (std::size_t j = 0 ; j < shapes.size() ; ++j)
00599     {
00600       // merge mesh vertices up to 0.1 mm apart
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   // clear information about any attached body, without refering to the AttachedBody* ptr (could be invalid)
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   // add attached objects again
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   // clear information about any attached object
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   // listen for planning scene updates; these messages include transforms, so no need for filters
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   // listen for world geometry updates using message filters
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   // Ocotomap monitor is optional
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       // using regular message filter as there's no header
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   // stop must be called with state_pending_mutex_ unlocked to avoid deadlock
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 & /* joint_state */ )
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   // run the state update with state_pending_mutex_ unlocked
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       // lock for access to dt_state_update_ and state_update_pending_
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     // run the state update with state_pending_mutex_ unlocked
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(); // unlock and rethrow
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     // stop must be called with state_pending_mutex_ unlocked to avoid deadlock
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(); // compute all transforms 
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   // read overriding values from the param server
01216 
01217   // first we do default collision operations
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 }


planning
Author(s): Ioan Sucan , Sachin Chitta
autogenerated on Wed Aug 26 2015 12:43:30