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
00036 #include <boost/bind.hpp>
00037 #include <climits>
00038 #include <sstream>
00039
00040 #include <planning_environment/monitors/collision_space_monitor.h>
00041 #include <planning_environment/monitors/monitor_utils.h>
00042
00043 namespace planning_environment
00044 {
00045
00046 static inline double maxCoord(const geometry_msgs::Point32 &point)
00047 {
00048 return std::max(std::max(point.x, point.y), point.z);
00049 }
00050 }
00051
00052 void planning_environment::CollisionSpaceMonitor::setupCSM(void)
00053 {
00054 envMonitorStarted_ = false;
00055
00056 collisionMapFilter_ = NULL;
00057 collisionMapUpdateFilter_ = NULL;
00058 collisionObjectFilter_ = NULL;
00059
00060 collisionMapSubscriber_ = NULL;
00061 collisionMapUpdateSubscriber_ = NULL;
00062 collisionObjectSubscriber_ = NULL;
00063
00064 have_map_ = false;
00065 use_collision_map_ = false;
00066
00067 nh_.param<double>("pointcloud_padd", pointcloud_padd_, 0.00);
00068 }
00069
00070 void planning_environment::CollisionSpaceMonitor::startEnvironmentMonitor(void)
00071 {
00072 if (envMonitorStarted_)
00073 return;
00074
00075 if(use_collision_map_) {
00076 collisionMapSubscriber_ = new message_filters::Subscriber<arm_navigation_msgs::CollisionMap>(root_handle_, "collision_map_occ", 1);
00077 collisionMapFilter_ = new tf::MessageFilter<arm_navigation_msgs::CollisionMap>(*collisionMapSubscriber_, *tf_, cm_->getWorldFrameId(), 1);
00078 collisionMapFilter_->registerCallback(boost::bind(&CollisionSpaceMonitor::collisionMapCallback, this, _1));
00079 ROS_INFO("Listening to collision_map using message notifier with target frame %s", collisionMapFilter_->getTargetFramesString().c_str());
00080
00081 collisionMapUpdateSubscriber_ = new message_filters::Subscriber<arm_navigation_msgs::CollisionMap>(root_handle_, "collision_map_update", 1024);
00082 collisionMapUpdateFilter_ = new tf::MessageFilter<arm_navigation_msgs::CollisionMap>(*collisionMapUpdateSubscriber_, *tf_, cm_->getWorldFrameId(), 1);
00083 collisionMapUpdateFilter_->registerCallback(boost::bind(&CollisionSpaceMonitor::collisionMapUpdateCallback, this, _1));
00084 ROS_DEBUG("Listening to collision_map_update using message notifier with target frame %s", collisionMapUpdateFilter_->getTargetFramesString().c_str());
00085 }
00086
00087 collisionObjectSubscriber_ = new message_filters::Subscriber<arm_navigation_msgs::CollisionObject>(root_handle_, "collision_object", 1024);
00088 collisionObjectFilter_ = new tf::MessageFilter<arm_navigation_msgs::CollisionObject>(*collisionObjectSubscriber_, *tf_, cm_->getWorldFrameId(), 1024);
00089 collisionObjectFilter_->registerCallback(boost::bind(&CollisionSpaceMonitor::collisionObjectCallback, this, _1));
00090 ROS_DEBUG("Listening to object_in_map using message notifier with target frame %s", collisionObjectFilter_->getTargetFramesString().c_str());
00091
00092
00093 attachedCollisionObjectSubscriber_ = new message_filters::Subscriber<arm_navigation_msgs::AttachedCollisionObject>(root_handle_, "attached_collision_object", 1024);
00094 attachedCollisionObjectSubscriber_->registerCallback(boost::bind(&CollisionSpaceMonitor::attachObjectCallback, this, _1));
00095
00096 envMonitorStarted_ = true;
00097 }
00098
00099 void planning_environment::CollisionSpaceMonitor::setUseCollisionMap(bool use_collision_map) {
00100 if(use_collision_map_ == use_collision_map) return;
00101
00102 use_collision_map_ = use_collision_map;
00103
00104 if(!envMonitorStarted_) return;
00105
00106 if(use_collision_map_) {
00107 collisionMapSubscriber_ = new message_filters::Subscriber<arm_navigation_msgs::CollisionMap>(root_handle_, "collision_map", 1);
00108 collisionMapFilter_ = new tf::MessageFilter<arm_navigation_msgs::CollisionMap>(*collisionMapSubscriber_, *tf_, cm_->getWorldFrameId(), 1);
00109 collisionMapFilter_->registerCallback(boost::bind(&CollisionSpaceMonitor::collisionMapCallback, this, _1));
00110 ROS_DEBUG("Listening to collision_map using message notifier with target frame %s", collisionMapFilter_->getTargetFramesString().c_str());
00111
00112 collisionMapUpdateSubscriber_ = new message_filters::Subscriber<arm_navigation_msgs::CollisionMap>(root_handle_, "collision_map_update", 1);
00113 collisionMapUpdateFilter_ = new tf::MessageFilter<arm_navigation_msgs::CollisionMap>(*collisionMapUpdateSubscriber_, *tf_, cm_->getWorldFrameId(), 1);
00114 collisionMapUpdateFilter_->registerCallback(boost::bind(&CollisionSpaceMonitor::collisionMapUpdateCallback, this, _1));
00115 ROS_DEBUG("Listening to collision_map_update using message notifier with target frame %s", collisionMapUpdateFilter_->getTargetFramesString().c_str());
00116 } else {
00117 if(collisionMapUpdateFilter_) {
00118 delete collisionMapUpdateFilter_;
00119 collisionMapUpdateFilter_ = NULL;
00120 }
00121 if(collisionMapUpdateSubscriber_) {
00122 delete collisionMapUpdateSubscriber_;
00123 collisionMapUpdateSubscriber_ = NULL;
00124 }
00125 if(collisionMapFilter_) {
00126 delete collisionMapFilter_;
00127 collisionMapFilter_ = NULL;
00128 }
00129
00130 if(collisionMapSubscriber_) {
00131 delete collisionMapSubscriber_;
00132 collisionMapSubscriber_ = NULL;
00133 }
00134 }
00135 }
00136
00137 void planning_environment::CollisionSpaceMonitor::stopEnvironmentMonitor(void)
00138 {
00139 if (!envMonitorStarted_)
00140 return;
00141
00142 if(collisionMapUpdateFilter_) {
00143 delete collisionMapUpdateFilter_;
00144 collisionMapUpdateFilter_ = NULL;
00145 }
00146 if(collisionMapUpdateSubscriber_) {
00147 delete collisionMapUpdateSubscriber_;
00148 collisionMapUpdateSubscriber_ = NULL;
00149 }
00150 if(collisionMapFilter_) {
00151 delete collisionMapFilter_;
00152 collisionMapFilter_ = NULL;
00153 }
00154
00155 if(collisionMapSubscriber_) {
00156 delete collisionMapSubscriber_;
00157 collisionMapSubscriber_ = NULL;
00158 }
00159
00160 if(collisionObjectFilter_) {
00161 delete collisionObjectFilter_;
00162 collisionObjectFilter_ = NULL;
00163 }
00164
00165 if(collisionObjectSubscriber_) {
00166 delete collisionObjectSubscriber_;
00167 collisionObjectSubscriber_ = NULL;
00168 }
00169
00170 if(attachedCollisionObjectSubscriber_) {
00171 delete attachedCollisionObjectSubscriber_;
00172 attachedCollisionObjectSubscriber_ = NULL;
00173 }
00174
00175 ROS_DEBUG("Environment state is no longer being monitored");
00176
00177 envMonitorStarted_ = false;
00178 }
00179
00180 bool planning_environment::CollisionSpaceMonitor::isMapUpdated(double sec) const
00181 {
00182 if(sec < 1e-5)
00183 {
00184 return false;
00185 }
00186
00187
00188 if(last_map_update_ > ros::TIME_MIN && ros::Time::now() < ros::Time(sec))
00189 {
00190 return true;
00191 }
00192
00193
00194 if (last_map_update_ < ros::Time::now()-ros::Duration(sec))
00195 {
00196 return false;
00197 }
00198
00199 return true;
00200 }
00201
00202 void planning_environment::CollisionSpaceMonitor::waitForMap(void) const
00203 {
00204 if(!use_collision_map_) {
00205 ROS_INFO("Not subscribing to map so not waiting");
00206 return;
00207 }
00208 int s = 0;
00209 while (nh_.ok() && !haveMap())
00210 {
00211 if (s == 0)
00212 ROS_INFO("Waiting for map ...");
00213 s = (s + 1) % 40;
00214 ros::spinOnce();
00215 ros::Duration().fromSec(0.05).sleep();
00216 }
00217 if (haveMap())
00218 ROS_INFO("Map received!");
00219 }
00220
00221 void planning_environment::CollisionSpaceMonitor::collisionMapUpdateCallback(const arm_navigation_msgs::CollisionMapConstPtr &collisionMap)
00222 {
00223 if (collisionMap->boxes.size() > 0)
00224 updateCollisionSpace(collisionMap, false);
00225 }
00226
00227 void planning_environment::CollisionSpaceMonitor::collisionMapCallback(const arm_navigation_msgs::CollisionMapConstPtr &collisionMap)
00228 {
00229 updateCollisionSpace(collisionMap, true);
00230 }
00231
00232 void planning_environment::CollisionSpaceMonitor::collisionMapAsSpheres(const arm_navigation_msgs::CollisionMapConstPtr &collisionMap,
00233 std::vector<shapes::Shape*> &spheres, std::vector<tf::Transform> &poses)
00234 {
00235
00236 bool transform = collisionMap->header.frame_id != cm_->getWorldFrameId();
00237 const int n = collisionMap->boxes.size();
00238
00239 spheres.resize(n);
00240 poses.resize(n);
00241
00242 if (transform)
00243 {
00244 std::string target = cm_->getWorldFrameId();
00245 bool err = false;
00246
00247
00248 for (int i = 0 ; i < n ; ++i)
00249 {
00250 geometry_msgs::PointStamped psi;
00251 psi.header = collisionMap->header;
00252 psi.point.x = collisionMap->boxes[i].center.x;
00253 psi.point.y = collisionMap->boxes[i].center.y;
00254 psi.point.z = collisionMap->boxes[i].center.z;
00255
00256 geometry_msgs::PointStamped pso;
00257 try
00258 {
00259 tf_->transformPoint(target, psi, pso);
00260 }
00261 catch(...)
00262 {
00263 err = true;
00264 pso = psi;
00265 }
00266
00267 poses[i].setIdentity();
00268 poses[i].setOrigin(tf::Vector3(pso.point.x, pso.point.y, pso.point.z));
00269 spheres[i] = new shapes::Sphere(maxCoord(collisionMap->boxes[i].extents) * 0.867 + pointcloud_padd_);
00270 }
00271
00272 if (err)
00273 ROS_ERROR("Some errors encountered in transforming the collision map to frame '%s' from frame '%s'", target.c_str(), collisionMap->header.frame_id.c_str());
00274 }
00275 else
00276 {
00277
00278
00279 for (int i = 0 ; i < n ; ++i)
00280 {
00281 poses[i].setIdentity();
00282 poses[i].setOrigin(tf::Vector3(collisionMap->boxes[i].center.x, collisionMap->boxes[i].center.y, collisionMap->boxes[i].center.z));
00283 spheres[i] = new shapes::Sphere(maxCoord(collisionMap->boxes[i].extents) * 0.867 + pointcloud_padd_);
00284 }
00285 }
00286 }
00287
00288 void planning_environment::CollisionSpaceMonitor::collisionMapAsBoxes(const arm_navigation_msgs::CollisionMapConstPtr &collision_map,
00289 std::vector<shapes::Shape*> &boxes, std::vector<tf::Transform> &poses)
00290 {
00291 collisionMapAsBoxes(*collision_map, boxes, poses);
00292 }
00293
00294 void planning_environment::CollisionSpaceMonitor::collisionMapAsBoxes(const arm_navigation_msgs::CollisionMap& collision_map,
00295 std::vector<shapes::Shape*> &boxes, std::vector<tf::Transform> &poses)
00296 {
00297
00298
00299 bool transform = collision_map.header.frame_id != cm_->getWorldFrameId();
00300 const int n = collision_map.boxes.size();
00301
00302 double pd = 2.0 * pointcloud_padd_;
00303
00304 boxes.resize(n);
00305 poses.resize(n);
00306
00307 if (transform)
00308 {
00309 std::string target = cm_->getWorldFrameId();
00310 bool err = false;
00311
00312
00313 for (int i = 0 ; i < n ; ++i)
00314 {
00315 geometry_msgs::PointStamped psi;
00316 psi.header = collision_map.header;
00317 psi.point.x = collision_map.boxes[i].center.x;
00318 psi.point.y = collision_map.boxes[i].center.y;
00319 psi.point.z = collision_map.boxes[i].center.z;
00320
00321 geometry_msgs::PointStamped pso;
00322 try
00323 {
00324 tf_->transformPoint(target, psi, pso);
00325 }
00326 catch(...)
00327 {
00328 err = true;
00329 pso = psi;
00330 }
00331
00332 poses[i].setRotation(tf::Quaternion(tf::Vector3(collision_map.boxes[i].axis.x, collision_map.boxes[i].axis.y, collision_map.boxes[i].axis.z), collision_map.boxes[i].angle));
00333 poses[i].setOrigin(tf::Vector3(pso.point.x, pso.point.y, pso.point.z));
00334 boxes[i] = new shapes::Box(collision_map.boxes[i].extents.x + pd, collision_map.boxes[i].extents.y + pd, collision_map.boxes[i].extents.z + pd);
00335 }
00336
00337 if (err)
00338 ROS_ERROR("Some errors encountered in transforming the collision map to frame '%s' from frame '%s'", target.c_str(), collision_map.header.frame_id.c_str());
00339 }
00340 else
00341 {
00342
00343
00344 for (int i = 0 ; i < n ; ++i)
00345 {
00346 poses[i].setRotation(tf::Quaternion(tf::Vector3(collision_map.boxes[i].axis.x, collision_map.boxes[i].axis.y, collision_map.boxes[i].axis.z), collision_map.boxes[i].angle));
00347 poses[i].setOrigin(tf::Vector3(collision_map.boxes[i].center.x, collision_map.boxes[i].center.y, collision_map.boxes[i].center.z));
00348 boxes[i] = new shapes::Box(collision_map.boxes[i].extents.x + pd, collision_map.boxes[i].extents.y + pd, collision_map.boxes[i].extents.z + pd);
00349 }
00350 }
00351 }
00352
00353 void planning_environment::CollisionSpaceMonitor::updateCollisionSpace(const arm_navigation_msgs::CollisionMapConstPtr &collision_map, bool clear)
00354 {
00355 std::vector<shapes::Shape*> shapes;
00356 std::vector<tf::Transform> poses;
00357
00358 collisionMapAsBoxes(*collision_map, shapes, poses);
00359
00360 cm_->setCollisionMap(shapes, poses, false);
00361 last_map_update_ = collision_map->header.stamp;
00362 have_map_ = true;
00363 }
00364
00365
00366 void planning_environment::CollisionSpaceMonitor::collisionObjectCallback(const arm_navigation_msgs::CollisionObjectConstPtr &collision_object)
00367 {
00368 processCollisionObjectMsg(collision_object, *tf_, cm_);
00369 }
00370
00371 bool planning_environment::CollisionSpaceMonitor::attachObjectCallback(const arm_navigation_msgs::AttachedCollisionObjectConstPtr &attached_object)
00372 {
00373 return processAttachedCollisionObjectMsg(attached_object, *tf_, cm_);
00374 }
00375
00376