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
00038 #include "collider/collider.h"
00039 #include <planning_environment/monitors/monitor_utils.h>
00040 #include <octomap_msgs/conversions.h>
00041
00042 Collider::Collider(): root_handle_(""), pruning_counter_(0), transparent_freespace_(false) {
00043
00044 ros::NodeHandle priv("~");
00045
00046 cm_ = new planning_environment::CollisionModels("robot_description");
00047 fixed_frame_ = cm_->getWorldFrameId();
00048
00049 attached_color_.a = 0.5;
00050 attached_color_.r = 0.6;
00051 attached_color_.g = 0.4;
00052 attached_color_.b = 0.3;
00053
00054 priv.param<double>("resolution", resolution_, 0.1);
00055 priv.param<double>("max_range", max_range_, -1.0);
00056 priv.param<int>("pruning_period", pruning_period_, 5);
00057
00058 priv.param<bool>("publish_static_over_dynamic_map", publish_over_dynamic_map_, false);
00059
00060
00061 priv.param<double>("dimension_x", workspace_box_.dimensionX, 0.0);
00062 priv.param<double>("dimension_y", workspace_box_.dimensionY, 0.0);
00063 priv.param<double>("dimension_z", workspace_box_.dimensionZ, 0.0);
00064
00065
00066 priv.param<double>("origin_x", workspace_box_.originX, 0.0);
00067 priv.param<double>("origin_y", workspace_box_.originY, 0.0);
00068 priv.param<double>("origin_z", workspace_box_.originZ, 0.0);
00069
00070
00071 workspace_box_.real_minX = -workspace_box_.dimensionX + workspace_box_.originX;
00072 workspace_box_.real_maxX = workspace_box_.dimensionX + workspace_box_.originX;
00073 workspace_box_.real_minY = -workspace_box_.dimensionY + workspace_box_.originY;
00074 workspace_box_.real_maxY = workspace_box_.dimensionY + workspace_box_.originY;
00075 workspace_box_.real_minZ = -workspace_box_.dimensionZ + workspace_box_.originZ;
00076 workspace_box_.real_maxZ = workspace_box_.dimensionZ + workspace_box_.originZ;
00077
00078
00079 priv.param<int>("camera_stereo_offset_left", camera_stereo_offset_left_, 128);
00080 priv.param<int>("camera_stereo_offset_right", camera_stereo_offset_right_, 0);
00081
00082
00083 collision_octree_ = new OcTreeType(resolution_);
00084 double probHit = 0.7;
00085 double probMiss = 0.4;
00086 double thresMin = 0.12;
00087 double thresMax = 0.97;
00088 priv.param("sensor_model_hit", probHit, probHit);
00089 priv.param("sensor_model_miss", probMiss, probMiss);
00090 priv.param("sensor_model_min", thresMin, thresMin);
00091 priv.param("sensor_model_max", thresMax, thresMax);
00092 collision_octree_->setProbHit(probHit);
00093 collision_octree_->setProbMiss(probMiss);
00094 collision_octree_->setClampingThresMin(thresMin);
00095 collision_octree_->setClampingThresMax(thresMax);
00096
00097 marker_pub_ = root_handle_.advertise<visualization_msgs::Marker>("visualization_marker", 10);
00098 octomap_visualization_pub_ = root_handle_.advertise<visualization_msgs::Marker>("occupied_cells", 10);
00099 octomap_visualization_free_pub_ = root_handle_.advertise<visualization_msgs::Marker>("free_cells", 10);
00100 octomap_visualization_attached_pub_ = root_handle_.advertise<visualization_msgs::Marker>("attached_objects", 10);
00101 octomap_visualization_attached_array_pub_ = root_handle_.advertise<visualization_msgs::MarkerArray>("attached_objects_array", 10);
00102 cmap_publisher_ = root_handle_.advertise<arm_navigation_msgs::CollisionMap>("collision_map_out", 1, true);
00103 static_map_publisher_ = root_handle_.advertise<arm_navigation_msgs::CollisionMap>("collision_map_occ_static", 1);
00104 pointcloud_publisher_ = root_handle_.advertise<sensor_msgs::PointCloud2>("point_cloud_out", 1, true);
00105
00106 color_occupied_.r = 0;
00107 color_occupied_.g = 0;
00108 color_occupied_.b = 1.0;
00109 color_occupied_.a = 0.5;
00110
00111 color_free_.r = 0;
00112 color_free_.g = 1.0;
00113 color_free_.b = 0.0;
00114 color_free_.a = 0.5;
00115
00116
00117 double default_padding, default_scale;
00118 priv.param<double> ("self_see_default_padding", default_padding, .01);
00119 priv.param<double> ("self_see_default_scale", default_scale, 1.0);
00120 priv.param<double> ("min_sensor_dist", self_filter_min_dist_, 0.05);
00121
00122 std::vector<robot_self_filter::LinkInfo> links;
00123 if (!priv.hasParam ("self_see_links"))
00124 {
00125 ROS_WARN ("No links specified for self filtering.");
00126 }
00127 else
00128 {
00129 XmlRpc::XmlRpcValue ssl_vals;;
00130
00131 priv.getParam ("self_see_links", ssl_vals);
00132 if (ssl_vals.getType () != XmlRpc::XmlRpcValue::TypeArray)
00133 {
00134 ROS_WARN ("Self see links need to be an array");
00135 }
00136 else
00137 {
00138 if (ssl_vals.size () == 0)
00139 {
00140 ROS_WARN ("No values in self see links array");
00141 }
00142 else
00143 {
00144 for (int i = 0; i < ssl_vals.size (); ++i)
00145 {
00146 robot_self_filter::LinkInfo li;
00147
00148 if (ssl_vals[i].getType() != XmlRpc::XmlRpcValue::TypeStruct)
00149 {
00150 ROS_WARN ("Self see links entry %d is not a structure. Stopping processing of self see links", i);
00151 break;
00152 }
00153 if (!ssl_vals[i].hasMember ("name"))
00154 {
00155 ROS_WARN ("Self see links entry %d has no name. Stopping processing of self see links", i);
00156 break;
00157 }
00158 li.name = std::string (ssl_vals[i]["name"]);
00159 if (!ssl_vals[i].hasMember ("padding"))
00160 {
00161 ROS_DEBUG ("Self see links entry %d has no padding. Assuming default padding of %g", i, default_padding);
00162 li.padding = default_padding;
00163 }
00164 else
00165 {
00166 li.padding = ssl_vals[i]["padding"];
00167 }
00168 if (!ssl_vals[i].hasMember ("scale"))
00169 {
00170 ROS_DEBUG ("Self see links entry %d has no scale. Assuming default scale of %g", i, default_scale);
00171 li.scale = default_scale;
00172 }
00173 else
00174 {
00175 li.scale = ssl_vals[i]["scale"];
00176 }
00177 links.push_back (li);
00178 }
00179 }
00180 }
00181 }
00182
00183
00184 robot_mask_right_ = new robot_self_filter::SelfMask(tf_, links);
00185 robot_mask_left_ = new robot_self_filter::SelfMask(tf_, links);
00186 ROS_INFO_STREAM("Robot self mask initialized with " << links.size() << " links");
00187
00188
00189
00190 cam_model_initialized_ = false;
00191 camera_info_subscriber_ = new ros::Subscriber;
00192 std::string camera_info_topic;
00193 priv.getParam("camera_info_topic", camera_info_topic);
00194 (*camera_info_subscriber_) = root_handle_.subscribe( camera_info_topic , 10,
00195 &Collider::cameraInfoCallback, this);
00196
00197
00198
00199 if(!priv.hasParam("cloud_sources")) {
00200
00201
00202 }
00203 else
00204 {
00205 XmlRpc::XmlRpcValue cloud_sources;
00206 priv.getParam("cloud_sources", cloud_sources);
00207
00208 if(cloud_sources.getType() != XmlRpc::XmlRpcValue::TypeArray) {
00209 ROS_WARN("Cloud sources needs to be an array");
00210 }
00211 else
00212 {
00213 for(int i = 0; i < cloud_sources.size(); ++i)
00214 {
00215 CloudInfo cinfo;
00216 if(cloud_sources[i].getType() != XmlRpc::XmlRpcValue::TypeStruct)
00217 {
00218 ROS_WARN("Cloud source entry %d is not a structure. Stopping processing of cloud sources",i);
00219 break;
00220 }
00221
00222 if(!cloud_sources[i].hasMember("name"))
00223 {
00224 ROS_WARN("Cloud sources entry %d has no name. Stopping processing of cloud sources",i);
00225 break;
00226 }
00227
00228 if(cloud_sources[i].hasMember("raw_name"))
00229 {
00230 cinfo.raw_cloud_name_ = std::string(cloud_sources[i]["raw_name"]);
00231
00232 if (!cloud_sources[i].hasMember("sensor_stereo_other_frame")){
00233 ROS_WARN("Cloud sources entry %d has a raw_name but no sensor_stereo_other_frame. Stopping processing of cloud sources",i);
00234 break;
00235 } else{
00236 cinfo.sensor_stereo_other_frame_ = std::string(cloud_sources[i]["sensor_stereo_other_frame"]);
00237 }
00238
00239 }
00240
00241 if(!cloud_sources[i].hasMember("sensor_frame"))
00242 {
00243 ROS_WARN("Cloud sources entry %d has no sensor_frame. Stopping processing of cloud sources",i);
00244 break;
00245 }
00246
00247 cinfo.cloud_name_ = std::string(cloud_sources[i]["name"]);
00248 cinfo.sensor_frame_ = std::string(cloud_sources[i]["sensor_frame"]);
00249
00250 if(!cloud_sources[i].hasMember("frame_subsample"))
00251 {
00252 ROS_DEBUG("Cloud sources entry %d has no frame subsample. Assuming default subsample of %g",i,1.0);
00253 cinfo.frame_subsample_ = 1.0;;
00254 }
00255 else
00256 {
00257 cinfo.frame_subsample_ = cloud_sources[i]["frame_subsample"];
00258 }
00259
00260 if(!cloud_sources[i].hasMember("point_subsample"))
00261 {
00262 ROS_DEBUG("Cloud sources entry %d has no point subsample. Assuming default subsample of %g",i,1.0);
00263 cinfo.point_subsample_ = 1.0;;
00264 }
00265 else
00266 {
00267 cinfo.point_subsample_ = cloud_sources[i]["point_subsample"];
00268 }
00269
00270 if(cloud_sources[i].hasMember("dynamic_buffer_size"))
00271 cinfo.dynamic_buffer_size_ = static_cast<unsigned int>(int(cloud_sources[i]["dynamic_buffer_size"]));
00272
00273 if(cloud_sources[i].hasMember("static_buffer_size"))
00274 cinfo.static_buffer_size_ = static_cast<unsigned int>(int(cloud_sources[i]["static_buffer_size"]));
00275
00276 if(cloud_sources[i].hasMember("dynamic_buffer_duration"))
00277 cinfo.dynamic_buffer_duration_ = ros::Duration(int(cloud_sources[i]["dynamic_buffer_duration"]));
00278
00279 if(cloud_sources[i].hasMember("static_buffer_duration"))
00280 cinfo.static_buffer_duration_ = ros::Duration(int(cloud_sources[i]["static_buffer_duration"]));
00281
00282 if(cloud_sources[i].hasMember("dynamic_publish"))
00283 cinfo.dynamic_publish_ = cloud_sources[i]["dynamic_publish"];
00284
00285 if(cloud_sources[i].hasMember("static_publish"))
00286 cinfo.static_publish_ = cloud_sources[i]["static_publish"];
00287
00288 if(cloud_sources[i].hasMember("dynamic_until_static_publish")) {
00289 cinfo.dynamic_until_static_publish_ = cloud_sources[i]["dynamic_until_static_publish"];
00290 }
00291
00292 if(cloud_sources_.find(cinfo.cloud_name_) != cloud_sources_.end())
00293 {
00294 ROS_WARN_STREAM("Already have a cloud defined with name " << cinfo.cloud_name_ << ", using prior values");
00295 }
00296 else
00297 {
00298 message_filters::Subscriber<sensor_msgs::PointCloud2>* sub = new message_filters::Subscriber<sensor_msgs::PointCloud2>();
00299 sub->subscribe(root_handle_, cinfo.cloud_name_, 3);
00300 sub_filtered_clouds_.push_back(sub);
00301 if(cinfo.raw_cloud_name_ != "") {
00302 message_filters::Subscriber<sensor_msgs::PointCloud2>* sub_raw = new message_filters::Subscriber<sensor_msgs::PointCloud2>();
00303 sub_raw->subscribe(root_handle_,cinfo.raw_cloud_name_, 3);
00304 message_filters::Synchronizer<message_filters::sync_policies::ApproximateTime<sensor_msgs::PointCloud2, sensor_msgs::PointCloud2> >* sync =
00305 new message_filters::Synchronizer<message_filters::sync_policies::ApproximateTime<sensor_msgs::PointCloud2, sensor_msgs::PointCloud2> >(3);
00306 sub_raw_clouds_.push_back(sub_raw);
00307 sync->connectInput (*sub, *sub_raw);
00308 sync->registerCallback(bind (&Collider::cloudCombinedCallback, this, _1, _2, cinfo.cloud_name_));
00309 sync_vector_.push_back(sync);
00310 ROS_INFO_STREAM("Adding synced callback for cloud " << cinfo.cloud_name_ << " raw " << cinfo.raw_cloud_name_);
00311 } else {
00312 sub->registerCallback(boost::bind(&Collider::cloudCallback, this, _1, cinfo.cloud_name_));
00313 ROS_INFO_STREAM("Adding callback for " << cinfo.cloud_name_);
00314 }
00315 cloud_sources_[cinfo.cloud_name_] = cinfo;
00316 }
00317 }
00318 }
00319 }
00320
00321 attached_collision_object_subscriber_ = new message_filters::Subscriber<arm_navigation_msgs::AttachedCollisionObject>(root_handle_, "attached_collision_object", 1024);
00322 attached_collision_object_subscriber_->registerCallback(boost::bind(&Collider::attachedObjectCallback, this, _1));
00323
00324 collision_object_subscriber_ = new message_filters::Subscriber<arm_navigation_msgs::CollisionObject>(root_handle_, "collision_object", 1024);
00325 collision_object_subscriber_->registerCallback(boost::bind(&Collider::objectCallback, this, _1));
00326
00327 reset_service_ = priv.advertiseService("reset", &Collider::reset, this);
00328 dummy_reset_service_ = priv.advertiseService("dummy_reset", &Collider::dummyReset, this);
00329
00330 action_server_.reset( new actionlib::SimpleActionServer<arm_navigation_msgs::MakeStaticCollisionMapAction>(root_handle_, "make_static_collision_map", boost::bind(&Collider::makeStaticCollisionMap, this, _1), false));
00331 action_server_->start();
00332
00333
00334 get_octomap_service_ = root_handle_.advertiseService("octomap_binary", &Collider::octomapSrv, this);
00335 occupancy_point_service_ = root_handle_.advertiseService("occupancy_point", &Collider::occupancyPointSrv, this);
00336 occupancy_bbx_service_ = root_handle_.advertiseService("occupancy_in_bbx", &Collider::occupancyBBXSrv, this);
00337 occupancy_bbx_size_service_ = root_handle_.advertiseService("occupancy_in_bbx_size", &Collider::occupancyBBXSizeSrv, this);
00338
00339 }
00340
00341
00342 Collider::~Collider() {
00343
00344 delete collision_octree_;
00345 delete robot_mask_right_;
00346 delete robot_mask_left_;
00347 delete attached_collision_object_subscriber_;
00348 delete collision_object_subscriber_;
00349
00350 for(unsigned int i = 0; i < sub_filtered_clouds_.size(); ++i){
00351 delete sub_filtered_clouds_[i];
00352 }
00353 for(unsigned int i = 0; i < sub_raw_clouds_.size(); ++i) {
00354 delete sub_raw_clouds_[i];
00355 }
00356 for(unsigned int i = 0; i < sync_vector_.size(); ++i) {
00357 delete sync_vector_[i];
00358 }
00359 }
00360
00361 void Collider::attachedObjectCallback(const arm_navigation_msgs::AttachedCollisionObjectConstPtr& attached_object) {
00362 planning_environment::processAttachedCollisionObjectMsg(attached_object, tf_, cm_);
00363 }
00364
00365 void Collider::objectCallback(const arm_navigation_msgs::CollisionObjectConstPtr& object) {
00366 planning_environment::processCollisionObjectMsg(object, tf_, cm_);
00367 }
00368
00369 void Collider::cameraInfoCallback(const sensor_msgs::CameraInfo::ConstPtr &cam_info){
00370 ROS_DEBUG("Got camera info: %d x %d\n", cam_info->height, cam_info->width);
00371 cam_model_.fromCameraInfo(*cam_info);
00372 cam_size_ = cam_model_.fullResolution();
00373 cam_model_initialized_ = true;
00374 delete camera_info_subscriber_;
00375 }
00376
00377 void Collider::cloudCombinedCallback(const sensor_msgs::PointCloud2::ConstPtr &cloud,
00378 const sensor_msgs::PointCloud2::ConstPtr &cloud_raw,
00379 const std::string topic_name) {
00380
00381 CloudInfo settings = cloud_sources_[topic_name];
00382
00383 ros::WallTime begin_cb = ros::WallTime::now();
00384
00385 if (!cam_model_initialized_) {
00386 ROS_INFO ("ERROR: camera model not initialized.");
00387 return;
00388 }
00389
00390
00391
00392
00393
00394
00395
00396 if (!tf_.waitForTransform(fixed_frame_, cloud_raw->header.frame_id, cloud->header.stamp, ros::Duration(1.0))) {
00397 ROS_WARN_STREAM( "Timed out waiting for transform from " << cloud_raw->header.frame_id
00398 << " to " << fixed_frame_ << ", quitting callback");
00399 return;
00400 }
00401
00402
00403 if (!tf_.waitForTransform(fixed_frame_, cloud->header.frame_id, cloud->header.stamp, ros::Duration(1.0))) {
00404 ROS_WARN_STREAM( "Timed out waiting for transform from " << cloud->header.frame_id
00405 << " to " << fixed_frame_ << ", quitting callback");
00406 return;
00407 }
00408
00409
00410 tf::StampedTransform trans;
00411 tf_.lookupTransform (fixed_frame_, cloud->header.frame_id, cloud->header.stamp, trans);
00412 tf::Transform to_world = trans;
00413
00414 ros::WallTime begin_transform = ros::WallTime::now();
00415 Eigen::Matrix4f eigen_transform;
00416 sensor_msgs::PointCloud2 transformed_cloud;
00417
00418
00419
00420
00421 pcl_ros::transformAsMatrix (to_world, eigen_transform);
00422 pcl_ros::transformPointCloud (eigen_transform, *cloud, transformed_cloud);
00423
00424 pcl::PointCloud<pcl::PointXYZ> pcl_cloud;
00425 pcl::fromROSMsg (transformed_cloud, pcl_cloud);
00426
00427 pcl_cloud.header.frame_id = cm_->getWorldFrameId();
00428 pcl_cloud.header.stamp = cloud->header.stamp;
00429
00430 std::vector<int> inside_mask;
00431
00432 if(planning_environment::computeAttachedObjectPointCloudMask(pcl_cloud,
00433 cm_->getWorldFrameId(),
00434 cm_,
00435 tf_,
00436 inside_mask)) {
00437 pcl::PointCloud<pcl::PointXYZ>::iterator it = pcl_cloud.points.begin();
00438 unsigned int i = 0;
00439 unsigned int count = 0;
00440 while(it != pcl_cloud.points.end()) {
00441 if(inside_mask[i++] == robot_self_filter::INSIDE) {
00442 it = pcl_cloud.points.erase(it);
00443 count++;
00444 } else {
00445 it++;
00446 }
00447 }
00448 ROS_DEBUG_STREAM("Filtering " << count << " points");
00449 }
00450
00451 {
00452 planning_models::KinematicState state(cm_->getKinematicModel());
00453 state.setKinematicStateToDefault();
00454
00455 planning_environment::updateAttachedObjectBodyPoses(cm_,
00456 state,
00457 tf_);
00458
00459 visualization_msgs::MarkerArray arr;
00460 cm_->getAttachedCollisionObjectMarkers(state,
00461 arr,
00462 "filter_attached",
00463 attached_color_,
00464 ros::Duration(.2));
00465
00466 octomap_visualization_attached_array_pub_.publish(arr);
00467 }
00468
00469 std_msgs::Header global_header = cloud->header;
00470 global_header.frame_id = fixed_frame_;
00471
00472
00473
00474
00475
00476
00477 pcl::PointCloud<pcl::PointXYZ> pcl_cloud_raw;
00478 pcl::fromROSMsg (*cloud_raw, pcl_cloud_raw);
00479
00480
00481 octomap::Pointcloud octo_pointcloud;
00482 octomap::pointcloudPCLToOctomap(pcl_cloud, octo_pointcloud);
00483 double elapsed_transform = (ros::WallTime::now() - begin_transform).toSec();
00484
00485
00486 octomap::point3d sensor_origin = getSensorOrigin(cloud->header);
00487 tf::Point sensor_origin_tf = octomap::pointOctomapToTf(sensor_origin);
00488
00489
00490 ros::WallTime begin_insert = ros::WallTime::now();
00491
00492
00493 collision_octree_->insertScan(octo_pointcloud, sensor_origin, max_range_, false, true);
00494 collision_octree_->updateInnerOccupancy();
00495
00496 double elapsed_insert = (ros::WallTime::now() - begin_insert).toSec();
00497
00498
00499
00500 ros::WallTime begin_degrade = ros::WallTime::now();
00501 degradeOutdatedRaw(cloud->header, sensor_origin_tf, settings.sensor_stereo_other_frame_, pcl_cloud_raw);
00502 double elapsed_degrade = (ros::WallTime::now() - begin_degrade).toSec();
00503
00504
00505
00506 octomap::point3d_list node_centers;
00507 ros::WallTime begin_get_occupied = ros::WallTime::now();
00508
00509 std::vector<geometry_msgs::Point> pointlist;
00510 getOccupiedPoints(pointlist);
00511
00512
00513 double elapsed_get_occupied = (ros::WallTime::now() - begin_get_occupied).toSec();
00514
00515
00516
00517 ros::WallTime begin_send = ros::WallTime::now();
00518 if (settings.dynamic_publish_ && cmap_publisher_.getNumSubscribers() > 0) {
00519 publishCollisionMap(pointlist, global_header, cmap_publisher_);
00520 }
00521 if (pointcloud_publisher_.getNumSubscribers() > 0) {
00522 publishPointCloud(pointlist, global_header, pointcloud_publisher_);
00523 }
00524 if (octomap_visualization_pub_.getNumSubscribers() > 0){
00525 publishMarkerArray(pointlist, global_header, color_occupied_, octomap_visualization_pub_);
00526 }
00527 if (octomap_visualization_free_pub_.getNumSubscribers() > 0){
00528 std::vector<geometry_msgs::Point> freelist;
00529 getFreePoints(freelist);
00530 publishMarkerArray(freelist, global_header, color_free_, octomap_visualization_free_pub_);
00531 }
00532 double elapsed_send = (ros::WallTime::now() - begin_send).toSec();
00533
00534 double total_elapsed = (ros::WallTime::now() - begin_cb).toSec();
00535 ROS_DEBUG("Total cloudCombinedCB %d pts: %f (transf: %f, update: %f, clear: %f, get occ: %f, send map: %f)",
00536 int(pcl_cloud.size()), total_elapsed, elapsed_transform, elapsed_insert, elapsed_degrade, elapsed_get_occupied, elapsed_send);
00537
00538 }
00539
00540
00541 void Collider::cloudCallback(const sensor_msgs::PointCloud2::ConstPtr &cloud, const std::string topic_name) {
00542
00543 ros::WallTime begin_cb = ros::WallTime::now();
00544 CloudInfo settings = cloud_sources_[topic_name];
00545
00546
00547 if (!tf_.waitForTransform(fixed_frame_, cloud->header.frame_id, cloud->header.stamp, ros::Duration(1.0))) {
00548 ROS_WARN_STREAM( "Timed out waiting for transform from " << cloud->header.frame_id
00549 << " to " << fixed_frame_ << ", quitting callback");
00550 return;
00551 }
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 tf::StampedTransform trans;
00564 tf_.lookupTransform (fixed_frame_, cloud->header.frame_id, cloud->header.stamp, trans);
00565 tf::Transform to_world = trans;
00566 Eigen::Matrix4f eigen_transform;
00567 sensor_msgs::PointCloud2 transformed_cloud;
00568
00569
00570
00571
00572 pcl_ros::transformAsMatrix (to_world, eigen_transform);
00573 pcl_ros::transformPointCloud (eigen_transform, *cloud, transformed_cloud);
00574
00575 pcl::PointCloud<pcl::PointXYZ> pcl_cloud;
00576 pcl::fromROSMsg (transformed_cloud, pcl_cloud);
00577 transformed_cloud.header.frame_id = fixed_frame_;
00578
00579 std::vector<int> inside_mask;
00580
00581 if(planning_environment::computeAttachedObjectPointCloudMask(pcl_cloud,
00582 cm_->getWorldFrameId(),
00583 cm_,
00584 tf_,
00585 inside_mask)) {
00586 pcl::PointCloud<pcl::PointXYZ>::iterator it = pcl_cloud.points.begin();
00587 unsigned int i = 0;
00588 while(it != pcl_cloud.end()) {
00589 if(inside_mask[i++] == robot_self_filter::INSIDE) {
00590 it = pcl_cloud.points.erase(it);
00591 } else {
00592 it++;
00593 }
00594 }
00595 }
00596
00597 {
00598 planning_models::KinematicState state(cm_->getKinematicModel());
00599 state.setKinematicStateToDefault();
00600
00601 planning_environment::updateAttachedObjectBodyPoses(cm_,
00602 state,
00603 tf_);
00604
00605 visualization_msgs::MarkerArray arr;
00606 cm_->getAttachedCollisionObjectMarkers(state,
00607 arr,
00608 "filter_attached",
00609 attached_color_,
00610 ros::Duration(.2));
00611
00612 octomap_visualization_attached_array_pub_.publish(arr);
00613 }
00614
00615
00616 octomap::Pointcloud octo_pointcloud;
00617 octomap::pointcloudPCLToOctomap(pcl_cloud, octo_pointcloud);
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627 octomap::point3d sensor_origin = getSensorOrigin(cloud->header);
00628 octomap::pose6d sensor_pose(sensor_origin.x(), sensor_origin.y(), sensor_origin.z(), 0, 0, 0);
00629
00630
00631
00632
00633
00634
00635 ros::WallTime begin_insert = ros::WallTime::now();
00636 collision_octree_->insertScan(octo_pointcloud, sensor_origin, max_range_, false);
00637
00638 double elapsed_insert = (ros::WallTime::now() - begin_insert).toSec();
00639
00640
00641 ros::WallTime begin_degrade = ros::WallTime::now();
00642
00643
00644
00645
00646 degradeSingleSpeckles();
00647 double elapsed_degrade = (ros::WallTime::now() - begin_degrade).toSec();
00648
00649
00650
00651 octomap::point3d_list node_centers;
00652 ros::WallTime begin_get_occupied = ros::WallTime::now();
00653 std::vector<geometry_msgs::Point> pointlist;
00654 getOccupiedPoints(pointlist);
00655 double elapsed_get_occupied = (ros::WallTime::now() - begin_get_occupied).toSec();
00656
00657
00658
00659 ros::WallTime begin_send = ros::WallTime::now();
00660 if (settings.dynamic_publish_ && cmap_publisher_.getNumSubscribers() > 0) {
00661 publishCollisionMap(pointlist, transformed_cloud.header, cmap_publisher_);
00662 }
00663 if (pointcloud_publisher_.getNumSubscribers() > 0) {
00664 publishPointCloud(pointlist, transformed_cloud.header, pointcloud_publisher_);
00665 }
00666 if (octomap_visualization_pub_.getNumSubscribers() > 0){
00667 publishMarkerArray(pointlist, transformed_cloud.header, color_occupied_, octomap_visualization_pub_);
00668 }
00669
00670 double elapsed_send = (ros::WallTime::now() - begin_send).toSec();
00671
00672 double total_elapsed = (ros::WallTime::now() - begin_cb).toSec();
00673 ROS_DEBUG("Total cloudCB: %f (Update %d pnts: %f, clearing: %f, get occupied: %f, send map: %f)",
00674 total_elapsed, int(pcl_cloud.size()), elapsed_insert, elapsed_degrade, elapsed_get_occupied, elapsed_send);
00675
00676 }
00677
00678
00679 void Collider::degradeOutdatedRaw(const std_msgs::Header& sensor_header, const tf::Point& sensor_origin,
00680 const std::string& other_stereo_frame, const pcl::PointCloud<pcl::PointXYZ>& pcl_cloud_raw) {
00681
00682 tf::StampedTransform trans;
00683
00684
00685 tf_.lookupTransform (sensor_header.frame_id, fixed_frame_, sensor_header.stamp, trans);
00686 tf::Transform to_sensor = trans;
00687
00688 robot_mask_right_->assumeFrame(fixed_frame_, sensor_header.stamp, sensor_header.frame_id, self_filter_min_dist_);
00689 robot_mask_left_->assumeFrame(fixed_frame_, sensor_header.stamp, other_stereo_frame, self_filter_min_dist_);
00690
00691 tf::Vector3 sensor_pos_right, sensor_pos_left;
00692 planning_models::KinematicState state(cm_->getKinematicModel());
00693 planning_environment::configureForAttachedBodyMask(state,
00694 cm_,
00695 tf_,
00696 sensor_header.frame_id,
00697 sensor_header.stamp,
00698 sensor_pos_right);
00699
00700 planning_environment::configureForAttachedBodyMask(state,
00701 cm_,
00702 tf_,
00703 other_stereo_frame,
00704 sensor_header.stamp,
00705 sensor_pos_left);
00706
00707 octomap::point3d min;
00708 octomap::point3d max;
00709 computeBBX(sensor_header, min, max);
00710 unsigned query_time = time(NULL);
00711 unsigned max_update_time = 3;
00712 for(OcTreeType::leaf_bbx_iterator it = collision_octree_->begin_leafs_bbx(min,max),
00713 end=collision_octree_->end_leafs_bbx(); it!= end; ++it)
00714 {
00715 if (collision_octree_->isNodeOccupied(*it) &&
00716 ((query_time - it->getTimestamp()) > max_update_time))
00717 {
00718 tf::Point pos(it.getX(), it.getY(), it.getZ());
00719 tf::Point posRel = to_sensor(pos);
00720 cv::Point2d uv = cam_model_.project3dToPixel(cv::Point3d(posRel.x(), posRel.y(), posRel.z()));
00721
00722
00723 if (!inSensorCone(uv))
00724 continue;
00725
00726
00727 if (isOccludedRaw(uv, pos.distance(sensor_origin), pcl_cloud_raw))
00728 continue;
00729
00730
00731 if (robot_mask_right_->getMaskIntersection(pos) == robot_self_filter::SHADOW
00732 || robot_mask_left_->getMaskIntersection(pos) == robot_self_filter::SHADOW
00733 || planning_environment::computeAttachedObjectPointMask(cm_, pos, sensor_pos_right) == robot_self_filter::SHADOW
00734 || planning_environment::computeAttachedObjectPointMask(cm_, pos, sensor_pos_left) == robot_self_filter::SHADOW)
00735 {
00736 continue;
00737 }
00738
00739
00740 collision_octree_->integrateMissNoTime(&*it);
00741
00742 }
00743 }
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779 }
00780
00781
00782
00783 void Collider::degradeOutdatedRaycasting(const std_msgs::Header& sensor_header, const octomap::point3d& sensor_origin,
00784 octomap::OcTreeStamped& tree) {
00785 tf::StampedTransform trans;
00786 tf_.lookupTransform (sensor_header.frame_id, fixed_frame_, sensor_header.stamp, trans);
00787 tf::Transform to_sensor = trans;
00788
00789
00790 octomap::point3d min;
00791 octomap::point3d max;
00792 computeBBX(sensor_header, min, max);
00793
00794 unsigned query_time = time(NULL);
00795 unsigned max_update_time = 1;
00796 for(OcTreeType::leaf_bbx_iterator it = collision_octree_->begin_leafs_bbx(min,max),
00797 end=collision_octree_->end_leafs_bbx(); it!= end; ++it)
00798 {
00799 if (collision_octree_->isNodeOccupied(*it) &&
00800 ((query_time - it->getTimestamp()) > max_update_time))
00801 {
00802 tf::Point pos(it.getX(), it.getY(), it.getZ());
00803 tf::Point posRel = to_sensor(pos);
00804 cv::Point2d uv = cam_model_.project3dToPixel(cv::Point3d(posRel.x(), posRel.y(), posRel.z()));
00805
00806
00807 if (!inSensorCone(uv))
00808 continue;
00809
00810
00811 if (isOccludedMap(sensor_origin, it.getCoordinate()))
00812 continue;
00813
00814
00815 collision_octree_->integrateMissNoTime(&*it);
00816
00817 }
00818 }
00819 }
00820
00821 void Collider::degradeSingleSpeckles(){
00822 for(OcTreeType::leaf_iterator it = collision_octree_->begin_leafs(),
00823 end=collision_octree_->end_leafs(); it!= end; ++it)
00824 {
00825 if (collision_octree_->isNodeOccupied(*it)){
00826 octomap::OcTreeKey nKey = it.getKey();
00827 octomap::OcTreeKey key;
00828 bool neighborFound = false;
00829 for (key[2] = nKey[2] - 1; !neighborFound && key[2] <= nKey[2] + 1; ++key[2]){
00830 for (key[1] = nKey[1] - 1; !neighborFound && key[1] <= nKey[1] + 1; ++key[1]){
00831 for (key[0] = nKey[0] - 1; !neighborFound && key[0] <= nKey[0] + 1; ++key[0]){
00832 if (key != nKey){
00833 OcTreeType::NodeType* node = collision_octree_->search(key);
00834 if (node && collision_octree_->isNodeOccupied(node)){
00835
00836 neighborFound = true;
00837 }
00838 }
00839 }
00840 }
00841 }
00842
00843 if (!neighborFound){
00844 ROS_DEBUG("Degrading single speckle at (%f,%f,%f)", it.getX(), it.getY(), it.getZ());
00845 collision_octree_->integrateMissNoTime(&*it);
00846 }
00847
00848 }
00849 }
00850 }
00851
00852
00853 octomap::point3d Collider::getSensorOrigin(const std_msgs::Header& sensor_header) {
00854
00855 geometry_msgs::PointStamped stamped_in;
00856 geometry_msgs::PointStamped stamped_out;
00857 stamped_in.header = sensor_header;
00858
00859
00860 if (sensor_header.frame_id == "base_footprint") {
00861 stamped_in.header.frame_id = "laser_tilt_link";
00862 }
00863
00864 geometry_msgs::Point p;
00865 p.x=p.y=p.z=0;
00866 try {
00867 tf_.transformPoint(fixed_frame_, stamped_in, stamped_out);
00868 } catch(tf::TransformException& ex) {
00869 ros::Time t;
00870 std::string err_string;
00871 ROS_INFO_STREAM("Transforming sensor origin using latest common time because there's a tf problem");
00872 if (tf_.getLatestCommonTime(fixed_frame_, stamped_in.header.frame_id, stamped_in.header.stamp, &err_string) == tf::NO_ERROR) {
00873 try {
00874 tf_.transformPoint(fixed_frame_, stamped_in, stamped_out);
00875 } catch(...) {
00876 ROS_WARN_STREAM("Still can't transform sensor origin between " << fixed_frame_ << " and " << stamped_in.header.frame_id);
00877 }
00878 } else {
00879 ROS_WARN_STREAM("No common time between " << fixed_frame_ << " and " << stamped_in.header.frame_id);
00880 }
00881 }
00882 octomap::point3d retval (stamped_out.point.x, stamped_out.point.y, stamped_out.point.z);
00883
00884 return retval;
00885 }
00886
00887
00888 void Collider::computeBBX(const std_msgs::Header& sensor_header, octomap::point3d& bbx_min, octomap::point3d& bbx_max) {
00889
00890 std::string sensor_frame = sensor_header.frame_id;
00891
00892
00893 geometry_msgs::PointStamped stamped_in;
00894 geometry_msgs::PointStamped stamped_out;
00895 stamped_in.header = sensor_header;
00896 stamped_in.header.frame_id = sensor_frame;
00897
00898
00899 geometry_msgs::Point p[8];
00900
00901
00902 cv::Point2d uv [4];
00903 uv[0].x = camera_stereo_offset_left_;
00904 uv[0].y = 0;
00905 uv[1].x = cam_size_.width + camera_stereo_offset_right_;
00906 uv[1].y = 0;
00907 uv[2].x = cam_size_.width + camera_stereo_offset_right_;
00908 uv[2].y = cam_size_.height;
00909 uv[3].x = camera_stereo_offset_left_;
00910 uv[3].y = cam_size_.height;
00911
00912
00913 cv::Point3d xyz [4];
00914 for (int i=0;i<4;i++) {
00915 xyz[i] = cam_model_.projectPixelTo3dRay(uv[i]);
00916 cv::Point3d xyz_05 = xyz[i] * 0.5;
00917 xyz[i] *= 5.;
00918 p[i].x = xyz[i].x;
00919 p[i].y = xyz[i].y;
00920 p[i].z = xyz[i].z;
00921 p[i+4].x = xyz_05.x;
00922 p[i+4].y = xyz_05.y;
00923 p[i+4].z = xyz_05.z;
00924 }
00925
00926
00927 bbx_min.x() = bbx_min.y() = bbx_min.z() = 1e6;
00928 bbx_max.x() = bbx_max.y() = bbx_max.z() = -1e6;
00929 for (int i=0; i<8; i++) {
00930 stamped_in.point = p[i];
00931 tf_.transformPoint(fixed_frame_, stamped_in, stamped_out);
00932 p[i].x = stamped_out.point.x;
00933 p[i].y = stamped_out.point.y;
00934 p[i].z = stamped_out.point.z;
00935 if (p[i].x < bbx_min.x()) bbx_min.x() = p[i].x;
00936 if (p[i].y < bbx_min.y()) bbx_min.y() = p[i].y;
00937 if (p[i].z < bbx_min.z()) bbx_min.z() = p[i].z;
00938 if (p[i].x > bbx_max.x()) bbx_max.x() = p[i].x;
00939 if (p[i].y > bbx_max.y()) bbx_max.y() = p[i].y;
00940 if (p[i].z > bbx_max.z()) bbx_max.z() = p[i].z;
00941 }
00942
00943
00944
00945 visualization_msgs::Marker bbx;
00946 bbx.header.frame_id = fixed_frame_;
00947 bbx.header.stamp = ros::Time::now();
00948 bbx.ns = "collider";
00949 bbx.id = 1;
00950 bbx.action = visualization_msgs::Marker::ADD;
00951 bbx.type = visualization_msgs::Marker::CUBE;
00952 bbx.pose.orientation.w = 1.0;
00953 bbx.pose.position.x = (bbx_min.x() + bbx_max.x()) / 2.;
00954 bbx.pose.position.y = (bbx_min.y() + bbx_max.y()) / 2.;
00955 bbx.pose.position.z = (bbx_min.z() + bbx_max.z()) / 2.;
00956 bbx.scale.x = bbx_max.x()-bbx_min.x();
00957 bbx.scale.y = bbx_max.y()-bbx_min.y();
00958 bbx.scale.z = bbx_max.z()-bbx_min.z();
00959 bbx.color.g = 1;
00960 bbx.color.a = 0.3;
00961 marker_pub_.publish(bbx);
00962
00963
00964
00965 visualization_msgs::Marker bbx_points;
00966 bbx_points.header.frame_id = fixed_frame_;
00967 bbx_points.header.stamp = ros::Time::now();
00968 bbx_points.ns = "collider";
00969 bbx_points.id = 2;
00970 bbx_points.action = visualization_msgs::Marker::ADD;
00971 bbx_points.type = visualization_msgs::Marker::LINE_STRIP;
00972 bbx_points.pose.orientation.w = 1.0;
00973 bbx_points.scale.x = 0.02;
00974 bbx_points.scale.y = 0.02;
00975 bbx_points.color.g = 1;
00976 bbx_points.color.a = 0.3;
00977 bbx_points.points.push_back(p[0]);
00978 bbx_points.points.push_back(p[1]);
00979 bbx_points.points.push_back(p[2]);
00980 bbx_points.points.push_back(p[3]);
00981 bbx_points.points.push_back(p[0]);
00982 bbx_points.points.push_back(p[4]);
00983 bbx_points.points.push_back(p[5]);
00984 bbx_points.points.push_back(p[6]);
00985 bbx_points.points.push_back(p[7]);
00986 bbx_points.points.push_back(p[4]);
00987 bbx_points.points.push_back(p[7]);
00988 bbx_points.points.push_back(p[3]);
00989 bbx_points.points.push_back(p[2]);
00990 bbx_points.points.push_back(p[6]);
00991 bbx_points.points.push_back(p[5]);
00992 bbx_points.points.push_back(p[1]);
00993 marker_pub_.publish(bbx_points);
00994 }
00995
00996
00997 bool Collider::inSensorCone(const cv::Point2d& uv) const {
00998
00999
01000
01001
01002 return ( (uv.x > camera_stereo_offset_left_+1)
01003 && (uv.x < cam_size_.width + camera_stereo_offset_right_ - 2)
01004 && (uv.y > 1)
01005 && (uv.y < cam_size_.height-2) );
01006 }
01007
01008
01009
01010 bool Collider::isOccludedRaw(const cv::Point2d& uv, double range, const pcl::PointCloud<pcl::PointXYZ>& pcl_cloud_raw) {
01011
01012
01013 if ((uv.x < 0) || (uv.y < 0) || (uv.x > cam_size_.width) || (uv.y > cam_size_.height))
01014 return false;
01015
01016 double sensor_range = pcl_cloud_raw(uv.x, uv.y).z;
01017
01018 return (sensor_range < range);
01019 }
01020
01021
01022 bool Collider::isOccludedMap(const octomap::point3d& sensor_origin, const octomap::point3d& p) const {
01023
01024 octomap::point3d direction (p-sensor_origin);
01025 octomap::point3d obstacle;
01026 double range = direction.norm() - resolution_;
01027
01028 if (collision_octree_->castRay(sensor_origin, direction, obstacle, true, range)) {
01029
01030
01031
01032
01033 return true;
01034 }
01035 return false;
01036 }
01037
01038
01039
01040
01041
01042 void Collider::publishCollisionMap(const std::vector<geometry_msgs::Point>& pointlist,
01043 const std_msgs::Header &header, ros::Publisher &pub) {
01044 if(pointlist.size() <= 1)
01045 return;
01046
01047 arm_navigation_msgs::CollisionMap cmap;
01048 cmap.header = header;
01049
01050 arm_navigation_msgs::OrientedBoundingBox box;
01051 box.extents.x = box.extents.y = box.extents.z = collision_octree_->getResolution();
01052 box.axis.x = box.axis.y = 0.0; box.axis.z = 1.0;
01053 box.angle = 0.0;
01054 cmap.boxes.reserve(pointlist.size());
01055
01056 for (std::vector<geometry_msgs::Point>::const_iterator it = pointlist.begin(); it != pointlist.end(); ++it) {
01057 box.center.x = it->x;
01058 box.center.y = it->y;
01059 box.center.z = it->z;
01060 cmap.boxes.push_back(box);
01061 }
01062 pub.publish(cmap);
01063 }
01064
01065
01066 void Collider::publishPointCloud(const std::vector<geometry_msgs::Point>& pointlist,
01067 const std_msgs::Header &header, ros::Publisher &pub) {
01068
01069 if(pointlist.size() <= 1)
01070 return;
01071
01072 pcl::PointCloud<pcl::PointXYZ> pcl_cloud;
01073 pcl_cloud.points.reserve (pointlist.size ());
01074
01075 for (std::vector<geometry_msgs::Point>::const_iterator it = pointlist.begin(); it != pointlist.end(); ++it) {
01076 pcl::PointXYZ point;
01077 point.x = it->x;
01078 point.y = it->y;
01079 point.z = it->z;
01080 pcl_cloud.points.push_back (point);
01081 }
01082
01083 sensor_msgs::PointCloud2 cloud;
01084 pcl::toROSMsg (pcl_cloud, cloud);
01085 cloud.header = header;
01086 pub.publish (cloud);
01087
01088 }
01089
01090 void Collider::publishMarkerArray(const std::vector<geometry_msgs::Point>& pointlist,
01091 const std_msgs::Header &header, const std_msgs::ColorRGBA& color,
01092 ros::Publisher &pub) {
01093
01094 if(pointlist.size() <= 1)
01095 return;
01096
01097 visualization_msgs::Marker occupiedCellsVis;
01098 occupiedCellsVis.header = header;
01099 occupiedCellsVis.ns = "map";
01100 occupiedCellsVis.id = 0;
01101 occupiedCellsVis.type = visualization_msgs::Marker::CUBE_LIST;
01102 occupiedCellsVis.scale.x = collision_octree_->getResolution();
01103 occupiedCellsVis.scale.y = collision_octree_->getResolution();
01104 occupiedCellsVis.scale.z = collision_octree_->getResolution();
01105 occupiedCellsVis.color = color;
01106
01107
01108 occupiedCellsVis.points = pointlist;
01109
01110 pub.publish (occupiedCellsVis);
01111
01112 }
01113
01114
01115
01116
01117
01118 bool Collider::reset(std_srvs::Empty::Request &req, std_srvs::Empty::Response &res) {
01119 delete collision_octree_;
01120 collision_octree_ = new OcTreeType(resolution_);
01121 return true;
01122 }
01123
01124
01125 bool Collider::dummyReset(std_srvs::Empty::Request &req, std_srvs::Empty::Response &res) {
01126
01127
01128
01129 return true;
01130 }
01131
01132
01133 void Collider::makeStaticCollisionMap(const arm_navigation_msgs::MakeStaticCollisionMapGoalConstPtr& goal) {
01134
01135 std_msgs::Header head;
01136 head.stamp = ros::Time::now();
01137 head.frame_id = fixed_frame_;
01138
01139 ROS_INFO("Making static collision map");
01140
01141
01142 std::vector<geometry_msgs::Point> pointlist;
01143 getOccupiedPoints(pointlist);
01144 if (pointcloud_publisher_.getNumSubscribers() > 0) {
01145 publishPointCloud(pointlist, head, pointcloud_publisher_);
01146 }
01147
01148 if(publish_over_dynamic_map_)
01149 {
01150 if (cmap_publisher_.getNumSubscribers() > 0) {
01151 publishCollisionMap(pointlist, head, cmap_publisher_);
01152 }
01153
01154 for(std::map<std::string,CloudInfo>::iterator it = cloud_sources_.begin();
01155 it != cloud_sources_.end();
01156 it++)
01157 {
01158 it->second.dynamic_publish_ = false;
01159 }
01160 ROS_INFO("Should stop publishing dynamic map");
01161 } else {
01162 publishCollisionMap(pointlist, head, static_map_publisher_);
01163 }
01164 action_server_->setSucceeded();
01165 }
01166
01167 bool Collider::octomapSrv(octomap_msgs::GetOctomap::Request &req, octomap_msgs::GetOctomap::Response &res){
01168 ROS_DEBUG("Sending map data on service request");
01169
01170 res.map.header.frame_id = fixed_frame_;
01171 res.map.header.stamp = ros::Time::now();
01172 octomap::octomapMapToMsg(*collision_octree_, res.map);
01173
01174 return true;
01175 }
01176
01177 bool Collider::occupancyPointSrv(collider::OccupancyPointQuery::Request &req,
01178 collider::OccupancyPointQuery::Response &res){
01179
01180 octomap::OcTreeNodeStamped* node = collision_octree_->search(req.point.x, req.point.y, req.point.z);
01181 if (node){
01182 if (collision_octree_->isNodeOccupied(node))
01183 res.occupancy=collider::OccupancyPointQueryResponse::OCCUPIED;
01184 else
01185 res.occupancy=collider::OccupancyPointQueryResponse::FREE;
01186 } else{
01187 res.occupancy = collider::OccupancyPointQueryResponse::UNKNOWN;
01188 }
01189
01190 return true;
01191 }
01192
01193 bool Collider::occupancyBBXSrv(collider::OccupancyBBXQuery::Request &req,
01194 collider::OccupancyBBXQuery::Response &res){
01195
01196 OcTreeType::leaf_bbx_iterator it = collision_octree_->begin_leafs_bbx(octomap::pointMsgToOctomap(req.min),
01197 octomap::pointMsgToOctomap(req.max));
01198 OcTreeType::leaf_bbx_iterator end = collision_octree_->end_leafs_bbx();
01199
01200 geometry_msgs::Point pt;
01201 for(; it!= end; ++it){
01202 pt.x = it.getX();
01203 pt.y = it.getY();
01204 pt.z = it.getZ();
01205
01206 if (collision_octree_->isNodeOccupied(*it)){
01207 res.occupied.push_back(pt);
01208 } else {
01209 res.free.push_back(pt);
01210 }
01211 }
01212 res.resolution = collision_octree_->getResolution();
01213
01214 return true;
01215 }
01216
01217 bool Collider::occupancyBBXSizeSrv(collider::OccupancyBBXSizeQuery::Request &req,
01218 collider::OccupancyBBXSizeQuery::Response &res){
01219
01220 octomap::point3d center = octomap::pointMsgToOctomap(req.center);
01221 octomap::point3d size = octomap::pointMsgToOctomap(req.size);
01222 OcTreeType::leaf_bbx_iterator it = collision_octree_->begin_leafs_bbx(center - (size*0.5), center + (size*0.5));
01223 OcTreeType::leaf_bbx_iterator end = collision_octree_->end_leafs_bbx();
01224
01225 geometry_msgs::Point pt;
01226 for(; it!= end; ++it){
01227 pt.x = it.getX();
01228 pt.y = it.getY();
01229 pt.z = it.getZ();
01230
01231 if (collision_octree_->isNodeOccupied(*it)){
01232 res.occupied.push_back(pt);
01233 } else {
01234 res.free.push_back(pt);
01235 }
01236 }
01237 res.resolution = collision_octree_->getResolution();
01238
01239 return true;
01240 }
01241