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 #define BOOST_PARAMETER_MAX_ARITY 7
00037 #include "jsk_pcl_ros/octomap_server_contact.h"
00038 #include <algorithm>
00039
00040 using namespace octomap;
00041 using octomap_msgs::Octomap;
00042
00043 namespace jsk_pcl_ros
00044 {
00045 OctomapServerContact::OctomapServerContact(const ros::NodeHandle &privateNh)
00046 : OctomapServer(privateNh),
00047 DiagnosticNodelet("OctomapServerContact"),
00048 m_octreeContact(NULL),
00049 m_publishUnknownSpace(false),
00050 m_publishFrontierSpace(false),
00051 m_offsetVisualizeUnknown(0),
00052 m_maxRangeProximity(0.05),
00053 m_occupancyMinX(-std::numeric_limits<double>::max()),
00054 m_occupancyMaxX(std::numeric_limits<double>::max()),
00055 m_occupancyMinY(-std::numeric_limits<double>::max()),
00056 m_occupancyMaxY(std::numeric_limits<double>::max()),
00057 m_useContactSurface(true)
00058 {
00059 delete m_octree;
00060 m_octree = NULL;
00061 m_octree = new OcTreeContact(m_res);
00062 m_octreeContact = dynamic_cast<OcTreeContact*>(m_octree);
00063 if (!m_octreeContact) {
00064 ROS_ERROR("Could not convert OcTreeContact from OcTree");
00065 assert(m_octreeContact);
00066 }
00067
00068 m_useHeightMap = false;
00069
00070 privateNh.param("publish_unknown_space", m_publishUnknownSpace, m_publishUnknownSpace);
00071 privateNh.param("offset_vis_unknown", m_offsetVisualizeUnknown, m_offsetVisualizeUnknown);
00072 privateNh.param("sensor_model/max_range_proximity", m_maxRangeProximity, m_maxRangeProximity);
00073 privateNh.param("publish_frontier_space", m_publishFrontierSpace, m_publishFrontierSpace);
00074
00075 privateNh.param("occupancy_min_x", m_occupancyMinX,m_occupancyMinX);
00076 privateNh.param("occupancy_max_x", m_occupancyMaxX,m_occupancyMaxX);
00077 privateNh.param("occupancy_min_y", m_occupancyMinY,m_occupancyMinY);
00078 privateNh.param("occupancy_max_y", m_occupancyMaxY,m_occupancyMaxY);
00079
00080 privateNh.param("use_contact_surface", m_useContactSurface,m_useContactSurface);
00081
00082 double r, g, b, a;
00083 privateNh.param("color_unknown/r", r, 0.5);
00084 privateNh.param("color_unknown/g", g, 0.5);
00085 privateNh.param("color_unknown/b", b, 0.7);
00086 privateNh.param("color_unknown/a", a, 1.0);
00087 m_colorUnknown.r = r;
00088 m_colorUnknown.g = g;
00089 m_colorUnknown.b = b;
00090 m_colorUnknown.a = a;
00091 privateNh.param("color_frontier/r", r, 1.0);
00092 privateNh.param("color_frontier/g", g, 0.0);
00093 privateNh.param("color_frontier/b", b, 0.0);
00094 privateNh.param("color_frontier/a", a, 1.0);
00095 m_colorFrontier.r = r;
00096 m_colorFrontier.g = g;
00097 m_colorFrontier.b = b;
00098 m_colorFrontier.a = a;
00099
00100 m_unknownPointCloudPub = m_nh.advertise<sensor_msgs::PointCloud2>("octomap_unknown_point_cloud_centers", 1, m_latchedTopics);
00101 m_umarkerPub = m_nh.advertise<visualization_msgs::MarkerArray>("unknown_cells_vis_array", 1, m_latchedTopics);
00102
00103 m_pointProximitySub = new message_filters::Subscriber<sensor_msgs::PointCloud2> (m_nh, "proximity_in", 5);
00104 m_tfPointProximitySub = new tf::MessageFilter<sensor_msgs::PointCloud2> (*m_pointProximitySub, m_tfListener, m_worldFrameId, 5);
00105 m_tfPointProximitySub->registerCallback(boost::bind(&OctomapServerContact::insertProximityCallback, this, _1));
00106
00107 m_frontierPointCloudPub = m_nh.advertise<sensor_msgs::PointCloud2>("octomap_frontier_point_cloud_centers", 1, m_latchedTopics);
00108 m_fromarkerPub = m_nh.advertise<visualization_msgs::MarkerArray>("frontier_cells_vis_array", 1, m_latchedTopics);
00109
00110 m_contactSensorSub.subscribe(m_nh, "contact_sensors_in", 2);
00111 m_tfContactSensorSub.reset(new tf::MessageFilter<jsk_recognition_msgs::ContactSensorArray> (
00112 m_contactSensorSub, m_tfListener, m_worldFrameId, 2));
00113 m_tfContactSensorSub->registerCallback(boost::bind(&OctomapServerContact::insertContactSensorCallback, this, _1));
00114
00115 initContactSensor(privateNh);
00116 }
00117
00118 OctomapServerContact::~OctomapServerContact() {
00119 }
00120
00121 void OctomapServerContact::initContactSensor(const ros::NodeHandle &privateNh) {
00122 double defaultPadding, defaultScale;
00123 privateNh.param<double>("self_see_defaultPadding", defaultPadding, .01);
00124 privateNh.param<double>("self_see_defaultScale", defaultScale, 1.0);
00125 std::vector<robot_self_filter::LinkInfo> links;
00126
00127 if (!privateNh.hasParam("self_see_links")) {
00128 ROS_WARN("No links specified for self filtering.");
00129 }
00130 else {
00131 XmlRpc::XmlRpcValue sslVals;;
00132 privateNh.getParam("self_see_links", sslVals);
00133 if (sslVals.getType() != XmlRpc::XmlRpcValue::TypeArray) {
00134 ROS_WARN("Self see links need to be an array");
00135 }
00136 else {
00137 if (sslVals.size() == 0) {
00138 ROS_WARN("No values in self see links array");
00139 }
00140 else {
00141 for (int i = 0; i < sslVals.size(); i++) {
00142 robot_self_filter::LinkInfo li;
00143 if (sslVals[i].getType() != XmlRpc::XmlRpcValue::TypeStruct) {
00144 ROS_WARN("Self see links entry %d is not a structure. Stopping processing of self see links",i);
00145 break;
00146 }
00147 if (!sslVals[i].hasMember("name")) {
00148 ROS_WARN("Self see links entry %d has no name. Stopping processing of self see links",i);
00149 break;
00150 }
00151 li.name = std::string(sslVals[i]["name"]);
00152 if (!sslVals[i].hasMember("padding")) {
00153 ROS_DEBUG("Self see links entry %d has no padding. Assuming default padding of %g",i,defaultPadding);
00154 li.padding = defaultPadding;
00155 }
00156 else {
00157 li.padding = sslVals[i]["padding"];
00158 }
00159 if (!sslVals[i].hasMember("scale")) {
00160 ROS_DEBUG("Self see links entry %d has no scale. Assuming default scale of %g",i,defaultScale);
00161 li.scale = defaultScale;
00162 }
00163 else {
00164 li.scale = sslVals[i]["scale"];
00165 }
00166 links.push_back(li);
00167 }
00168 }
00169 }
00170 }
00171 m_selfMask = boost::shared_ptr<robot_self_filter::SelfMaskNamedLink>(new robot_self_filter::SelfMaskNamedLink(m_tfListener, links));
00172 }
00173
00174 void OctomapServerContact::insertProximityCallback(const sensor_msgs::PointCloud2::ConstPtr& cloud) {
00175
00176
00177 ros::WallTime startTime = ros::WallTime::now();
00178
00179
00180
00181
00182 PCLPointCloud pc;
00183 pcl::fromROSMsg(*cloud, pc);
00184
00185 tf::StampedTransform sensorToWorldTf;
00186 try {
00187 m_tfListener.lookupTransform(m_worldFrameId, cloud->header.frame_id, cloud->header.stamp, sensorToWorldTf);
00188 } catch(tf::TransformException& ex){
00189 ROS_ERROR_STREAM( "Transform error of sensor data: " << ex.what() << ", quitting callback");
00190 return;
00191 }
00192
00193 Eigen::Matrix4f sensorToWorld;
00194 pcl_ros::transformAsMatrix(sensorToWorldTf, sensorToWorld);
00195
00196
00197 pcl::transformPointCloud(pc, pc, sensorToWorld);
00198
00199 pc.header = pc.header;
00200
00201 insertScanProximity(sensorToWorldTf.getOrigin(), pc);
00202
00203 double total_elapsed = (ros::WallTime::now() - startTime).toSec();
00204 ROS_DEBUG("Pointcloud insertion in OctomapServer done (%zu pts, %f sec)", pc.size(), total_elapsed);
00205
00206 publishAll(cloud->header.stamp);
00207 }
00208
00209 void OctomapServerContact::insertScanProximity(const tf::Point& sensorOriginTf, const PCLPointCloud& pc) {
00210 point3d sensorOrigin = pointTfToOctomap(sensorOriginTf);
00211
00212 if (!m_octree->coordToKeyChecked(sensorOrigin, m_updateBBXMin)
00213 || !m_octree->coordToKeyChecked(sensorOrigin, m_updateBBXMax))
00214 {
00215 ROS_ERROR_STREAM("Could not generate Key for origin "<<sensorOrigin);
00216 }
00217
00218 #ifdef COLOR_OCTOMAP_SERVER
00219 unsigned char* colors = new unsigned char[3];
00220 #endif
00221
00222
00223 KeySet free_cells, occupied_cells;
00224
00225
00226 for (PCLPointCloud::const_iterator it = pc.begin(); it != pc.end(); ++it) {
00227 point3d point(it->x, it->y, it->z);
00228
00229 if ((m_maxRangeProximity < 0.0) || ((point - sensorOrigin).norm() <= m_maxRangeProximity) ) {
00230
00231
00232 if (m_octree->computeRayKeys(sensorOrigin, point, m_keyRay)){
00233 free_cells.insert(m_keyRay.begin(), m_keyRay.end());
00234 }
00235
00236 OcTreeKey key;
00237 if (m_octree->coordToKeyChecked(point, key)){
00238 occupied_cells.insert(key);
00239
00240 updateMinKey(key, m_updateBBXMin);
00241 updateMaxKey(key, m_updateBBXMax);
00242
00243 #ifdef COLOR_OCTOMAP_SERVER // NB: Only read and interpret color if it's an occupied node
00244 const int rgb = *reinterpret_cast<const int*>(&(it->rgb));
00245 colors[0] = ((rgb >> 16) & 0xff);
00246 colors[1] = ((rgb >> 8) & 0xff);
00247 colors[2] = (rgb & 0xff);
00248 m_octree->averageNodeColor(it->x, it->y, it->z, colors[0], colors[1], colors[2]);
00249 #endif
00250 }
00251 } else {
00252 point3d new_end = sensorOrigin + (point - sensorOrigin).normalized() * m_maxRangeProximity;
00253 if (m_octree->computeRayKeys(sensorOrigin, new_end, m_keyRay)){
00254 free_cells.insert(m_keyRay.begin(), m_keyRay.end());
00255
00256 octomap::OcTreeKey endKey;
00257 if (m_octree->coordToKeyChecked(new_end, endKey)){
00258 updateMinKey(endKey, m_updateBBXMin);
00259 updateMaxKey(endKey, m_updateBBXMax);
00260 } else{
00261 ROS_ERROR_STREAM("Could not generate Key for endpoint "<<new_end);
00262 }
00263 }
00264 }
00265 }
00266
00267
00268 for(KeySet::iterator it = free_cells.begin(), end=free_cells.end(); it!= end; ++it){
00269 if (occupied_cells.find(*it) == occupied_cells.end()){
00270 m_octree->updateNode(*it, false);
00271 }
00272 }
00273
00274
00275 for (KeySet::iterator it = occupied_cells.begin(), end=occupied_cells.end(); it!= end; it++) {
00276 m_octree->updateNode(*it, true);
00277 }
00278
00279
00280
00281
00282 octomap::point3d minPt, maxPt;
00283 ROS_DEBUG_STREAM("Bounding box keys (before): " << m_updateBBXMin[0] << " " <<m_updateBBXMin[1] << " " << m_updateBBXMin[2] << " / " <<m_updateBBXMax[0] << " "<<m_updateBBXMax[1] << " "<< m_updateBBXMax[2]);
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 minPt = m_octree->keyToCoord(m_updateBBXMin);
00299 maxPt = m_octree->keyToCoord(m_updateBBXMax);
00300 ROS_DEBUG_STREAM("Updated area bounding box: "<< minPt << " - "<<maxPt);
00301 ROS_DEBUG_STREAM("Bounding box keys (after): " << m_updateBBXMin[0] << " " <<m_updateBBXMin[1] << " " << m_updateBBXMin[2] << " / " <<m_updateBBXMax[0] << " "<<m_updateBBXMax[1] << " "<< m_updateBBXMax[2]);
00302
00303 if (m_compressMap)
00304 m_octree->prune();
00305 }
00306
00307 void OctomapServerContact::insertContactSensor(const jsk_recognition_msgs::ContactSensorArray::ConstPtr& msg) {
00308 std::vector<jsk_recognition_msgs::ContactSensor> datas = msg->datas;
00309
00310
00311 {
00312 std_msgs::Header tmpHeader;
00313 tmpHeader.frame_id = m_worldFrameId;
00314 tmpHeader.stamp = msg->header.stamp;
00315 if(!m_selfMask->assumeFrame(tmpHeader)) {
00316 ROS_ERROR_STREAM("failed tf transformation in insertContactSensor");
00317 return;
00318 }
00319 }
00320
00321
00322 point3d pmin_raw( m_occupancyMinX, m_occupancyMinY, m_occupancyMinZ );
00323 point3d pmax_raw( m_occupancyMaxX, m_occupancyMaxY, m_occupancyMaxZ );
00324 point3d pmin = m_octree->keyToCoord(m_octree->coordToKey(pmin_raw));
00325 point3d pmax = m_octree->keyToCoord(m_octree->coordToKey(pmax_raw));
00326 float diff[3];
00327 unsigned int steps[3];
00328 double resolution = m_octreeContact->getResolution();
00329 for (int i = 0; i < 3; ++i) {
00330 diff[i] = pmax(i) - pmin(i);
00331 steps[i] = floor(diff[i] / resolution);
00332
00333 }
00334
00335
00336 if (m_useContactSurface) {
00337 std::vector< std::vector<bool> > containFlag(datas.size(), std::vector<bool>(8));
00338 point3d p = pmin;
00339 for (unsigned int x = 0; x < steps[0]; ++x) {
00340 p.x() += resolution;
00341 for (unsigned int y = 0; y < steps[1]; ++y) {
00342 p.y() += resolution;
00343 for (unsigned int z = 0; z < steps[2]; ++z) {
00344
00345 p.z() += resolution;
00346
00347 point3d vertexOffset(-resolution/2.0, -resolution/2.0, -resolution/2.0);
00348 point3d vertex;
00349 for (int i = 0; i < 2; i++) {
00350 if (i == 1) { vertexOffset.z() += resolution; }
00351 for (int j = 0; j < 2; j++) {
00352 if (j == 1) { vertexOffset.y() += resolution; }
00353 for (int k = 0; k < 2; k++) {
00354 if (k == 1) { vertexOffset.x() += resolution; }
00355 vertex = p + vertexOffset;
00356
00357
00358 for (int l=0; l<datas.size(); l++) {
00359 if (m_selfMask->getMaskContainmentforNamedLink(vertex(0), vertex(1), vertex(2), datas[l].link_name) == robot_self_filter::INSIDE) {
00360
00361 containFlag[l][i+j*2+k*4] = true;
00362 }
00363 else {
00364 containFlag[l][i+j*2+k*4] = false;
00365 }
00366 }
00367 }
00368 vertexOffset.x() -= resolution;
00369 }
00370 vertexOffset.y() -= resolution;
00371 }
00372
00373
00374 std::vector<bool> containFlagLinkSum(8, false);
00375 std::vector<bool> containFlagVerticesSum(datas.size(), false);
00376 std::vector<bool> containFlagVerticesProd(datas.size(), true);
00377 bool insideFlag = false;
00378 bool surfaceFlag = false;
00379 for (int l = 0; l < datas.size(); l++) {
00380 for (int i = 0; i < 8; i++) {
00381 if (containFlag[l][i]) {
00382 containFlagLinkSum[i] = true;
00383 containFlagVerticesSum[l] = true;
00384 }
00385 else {
00386 containFlagVerticesProd[l] = false;
00387 }
00388 }
00389 }
00390 insideFlag = (std::find(containFlagLinkSum.begin(), containFlagLinkSum.end(), false) == containFlagLinkSum.end());
00391 for (int l = 0; l < datas.size(); l++) {
00392 if (containFlagVerticesSum[l] && !(containFlagVerticesProd[l]) ) {
00393 if (datas[l].contact) {
00394 surfaceFlag = true;
00395 }
00396 }
00397 }
00398 if (insideFlag) {
00399 octomap::OcTreeKey pKey;
00400 if (m_octreeContact->coordToKeyChecked(p, pKey)) {
00401 m_octreeContact->updateNode(pKey, m_octreeContact->getProbMissContactSensorLog());
00402
00403 }
00404 }
00405 else if (surfaceFlag) {
00406 octomap::OcTreeKey pKey;
00407 if (m_octreeContact->coordToKeyChecked(p, pKey)) {
00408 m_octreeContact->updateNode(pKey, m_octreeContact->getProbHitContactSensorLog());
00409
00410 }
00411 }
00412 }
00413 p.z() = pmin.z();
00414 }
00415 p.y() = pmin.y();
00416 }
00417 }
00418 else {
00419 point3d vertexOffset(-resolution/2.0, -resolution/2.0, -resolution/2.0);
00420 #pragma omp parallel for
00421 for (unsigned int cnt = 0; cnt < steps[0] * steps[1] * steps[2]; ++cnt) {
00422
00423 point3d p;
00424 {
00425 unsigned int id[3];
00426 id[0] = cnt / (steps[1] * steps[2]);
00427 id[1] = (cnt % (steps[1] * steps[2])) / steps[2];
00428 id[2] = (cnt % (steps[1] * steps[2])) % steps[2];
00429 p.x() = pmin(0) + resolution * id[0];
00430 p.y() = pmin(1) + resolution * id[1];
00431 p.z() = pmin(2) + resolution * id[2];
00432 }
00433 point3d vertex;
00434 vertex = p + vertexOffset;
00435
00436 for (int l=0; l<datas.size(); l++) {
00437 if (m_selfMask->getMaskContainmentforNamedLink(vertex(0), vertex(1), vertex(2), datas[l].link_name) == robot_self_filter::INSIDE) {
00438 octomap::OcTreeKey pKey;
00439 if (m_octreeContact->coordToKeyChecked(p, pKey)) {
00440 #pragma omp critical
00441 m_octreeContact->updateNode(pKey, m_octreeContact->getProbMissContactSensorLog());
00442 }
00443 break;
00444 }
00445 }
00446 }
00447 }
00448 m_octreeContact->updateInnerOccupancy();
00449 }
00450
00451 void OctomapServerContact::insertContactSensorCallback(const jsk_recognition_msgs::ContactSensorArray::ConstPtr& msg) {
00452 NODELET_INFO("insert contact sensor");
00453 insertContactSensor(msg);
00454
00455 publishAll(msg->header.stamp);
00456 }
00457
00458 void OctomapServerContact::publishAll(const ros::Time& rostime) {
00459 ros::WallTime startTime = ros::WallTime::now();
00460 size_t octomapSize = m_octreeContact->size();
00461
00462 if (octomapSize <= 1) {
00463 ROS_WARN("Nothing to publish, octree is empty");
00464 return;
00465 }
00466
00467 bool publishFreeMarkerArray = m_publishFreeSpace && (m_latchedTopics || m_fmarkerPub.getNumSubscribers() > 0);
00468 bool publishUnknownMarkerArray = m_publishUnknownSpace && (m_latchedTopics || m_umarkerPub.getNumSubscribers() > 0);
00469 bool publishFrontierMarkerArray = m_publishFrontierSpace && (m_latchedTopics || m_fromarkerPub.getNumSubscribers() > 0);
00470 bool publishMarkerArray = (m_latchedTopics || m_markerPub.getNumSubscribers() > 0);
00471 bool publishPointCloud = (m_latchedTopics || m_pointCloudPub.getNumSubscribers() > 0);
00472 bool publishBinaryMap = (m_latchedTopics || m_binaryMapPub.getNumSubscribers() > 0);
00473 bool publishFullMap = (m_latchedTopics || m_fullMapPub.getNumSubscribers() > 0);
00474 m_publish2DMap = (m_latchedTopics || m_mapPub.getNumSubscribers() > 0);
00475
00476
00477 visualization_msgs::MarkerArray freeNodesVis;
00478
00479 freeNodesVis.markers.resize(m_treeDepth+1);
00480
00481 geometry_msgs::Pose pose;
00482 pose.orientation = tf::createQuaternionMsgFromYaw(0.0);
00483
00484
00485 visualization_msgs::MarkerArray occupiedNodesVis;
00486
00487 occupiedNodesVis.markers.resize(m_treeDepth+1);
00488
00489
00490 pcl::PointCloud<pcl::PointXYZ> pclCloud;
00491
00492
00493 handlePreNodeTraversal(rostime);
00494
00495
00496 for (OcTree::iterator it = m_octreeContact->begin(m_maxTreeDepth), end = m_octreeContact->end(); it != end; ++it) {
00497 bool inUpdateBBX = isInUpdateBBX(it);
00498
00499
00500 handleNode(it);
00501 if (inUpdateBBX) {
00502 handleNodeInBBX(it);
00503 }
00504
00505 if (m_octreeContact->isNodeOccupied(*it)) {
00506 double x = it.getX();
00507 double y = it.getY();
00508 double z = it.getZ();
00509 if (x > m_occupancyMinX && x < m_occupancyMaxX && y > m_occupancyMinY && y < m_occupancyMaxY && z > m_occupancyMinZ && z < m_occupancyMaxZ) {
00510 double size = it.getSize();
00511 double x = it.getX();
00512 double y = it.getY();
00513
00514
00515 if (m_filterSpeckles && (it.getDepth() == m_treeDepth +1) && isSpeckleNode(it.getKey())) {
00516 ROS_DEBUG("Ignoring single speckle at (%f,%f,%f)", x, y, z);
00517 continue;
00518 }
00519
00520 handleOccupiedNode(it);
00521 if (inUpdateBBX) {
00522 handleOccupiedNodeInBBX(it);
00523 }
00524
00525
00526 if (publishMarkerArray) {
00527 unsigned idx = it.getDepth();
00528 assert(idx < occupiedNodesVis.markers.size());
00529
00530 geometry_msgs::Point cubeCenter;
00531 cubeCenter.x = x;
00532 cubeCenter.y = y;
00533 cubeCenter.z = z;
00534
00535 occupiedNodesVis.markers[idx].points.push_back(cubeCenter);
00536 if (m_useHeightMap) {
00537 double minX, minY, minZ, maxX, maxY, maxZ;
00538 m_octreeContact->getMetricMin(minX, minY, minZ);
00539 m_octreeContact->getMetricMax(maxX, maxY, maxZ);
00540
00541 double h = (1.0 - std::min(std::max((cubeCenter.z-minZ)/ (maxZ - minZ), 0.0), 1.0)) *m_colorFactor;
00542 occupiedNodesVis.markers[idx].colors.push_back(heightMapColor(h));
00543 }
00544 }
00545
00546
00547 if (publishPointCloud) {
00548 pclCloud.push_back(pcl::PointXYZ(x, y, z));
00549 }
00550
00551 }
00552 } else {
00553 double x = it.getX();
00554 double y = it.getY();
00555 double z = it.getZ();
00556 if (x > m_occupancyMinX && x < m_occupancyMaxX && y > m_occupancyMinY && y < m_occupancyMaxY && z > m_occupancyMinZ && z < m_occupancyMaxZ) {
00557 handleFreeNode(it);
00558 if (inUpdateBBX)
00559 handleFreeNodeInBBX(it);
00560
00561 if (m_publishFreeSpace) {
00562 double x = it.getX();
00563 double y = it.getY();
00564
00565
00566 if (publishFreeMarkerArray) {
00567 unsigned idx = it.getDepth();
00568 assert(idx < freeNodesVis.markers.size());
00569
00570 geometry_msgs::Point cubeCenter;
00571 cubeCenter.x = x;
00572 cubeCenter.y = y;
00573 cubeCenter.z = z;
00574
00575 freeNodesVis.markers[idx].points.push_back(cubeCenter);
00576 }
00577 }
00578 }
00579 }
00580 }
00581
00582
00583 handlePostNodeTraversal(rostime);
00584
00585
00586 if (publishMarkerArray) {
00587 for (unsigned i = 0; i < occupiedNodesVis.markers.size(); ++i) {
00588 double size = m_octreeContact->getNodeSize(i);
00589
00590 occupiedNodesVis.markers[i].header.frame_id = m_worldFrameId;
00591 occupiedNodesVis.markers[i].header.stamp = rostime;
00592 occupiedNodesVis.markers[i].ns = m_worldFrameId;
00593 occupiedNodesVis.markers[i].id = i;
00594 occupiedNodesVis.markers[i].type = visualization_msgs::Marker::CUBE_LIST;
00595 occupiedNodesVis.markers[i].scale.x = size;
00596 occupiedNodesVis.markers[i].scale.y = size;
00597 occupiedNodesVis.markers[i].scale.z = size;
00598 occupiedNodesVis.markers[i].color = m_color;
00599
00600
00601 if (occupiedNodesVis.markers[i].points.size() > 0) {
00602 occupiedNodesVis.markers[i].action = visualization_msgs::Marker::ADD;
00603 }
00604 else {
00605 occupiedNodesVis.markers[i].action = visualization_msgs::Marker::DELETE;
00606 }
00607 }
00608
00609 m_markerPub.publish(occupiedNodesVis);
00610 }
00611
00612
00613
00614 if (publishFreeMarkerArray) {
00615 for (unsigned i = 0; i < freeNodesVis.markers.size(); ++i) {
00616 double size = m_octreeContact->getNodeSize(i);
00617
00618 freeNodesVis.markers[i].header.frame_id = m_worldFrameId;
00619 freeNodesVis.markers[i].header.stamp = rostime;
00620 freeNodesVis.markers[i].ns = m_worldFrameId;
00621 freeNodesVis.markers[i].id = i;
00622 freeNodesVis.markers[i].type = visualization_msgs::Marker::CUBE_LIST;
00623 freeNodesVis.markers[i].scale.x = size;
00624 freeNodesVis.markers[i].scale.y = size;
00625 freeNodesVis.markers[i].scale.z = size;
00626 freeNodesVis.markers[i].color = m_colorFree;
00627
00628
00629 if (freeNodesVis.markers[i].points.size() > 0) {
00630 freeNodesVis.markers[i].action = visualization_msgs::Marker::ADD;
00631 }
00632 else {
00633 freeNodesVis.markers[i].action = visualization_msgs::Marker::DELETE;
00634 }
00635 }
00636
00637 m_fmarkerPub.publish(freeNodesVis);
00638 }
00639
00640
00641
00642 if (publishUnknownMarkerArray) {
00643 visualization_msgs::MarkerArray unknownNodesVis;
00644 unknownNodesVis.markers.resize(1);
00645
00646 point3d_list unknownLeaves;
00647 double offset = m_offsetVisualizeUnknown;
00648 point3d pMin(m_occupancyMinX + offset, m_occupancyMinY + offset, m_occupancyMinZ + offset);
00649 point3d pMax(m_occupancyMaxX - offset, m_occupancyMaxY - offset, m_occupancyMaxZ - offset);
00650
00651 m_octreeContact->getUnknownLeafCenters(unknownLeaves, pMin, pMax);
00652 pcl::PointCloud<pcl::PointXYZ> unknownCloud;
00653
00654 for (point3d_list::iterator it = unknownLeaves.begin(); it != unknownLeaves.end(); it++) {
00655 float x = (*it).x();
00656 float y = (*it).y();
00657 float z = (*it).z();
00658 unknownCloud.push_back(pcl::PointXYZ(x, y, z));
00659
00660 geometry_msgs::Point cubeCenter;
00661 cubeCenter.x = x;
00662 cubeCenter.y = y;
00663 cubeCenter.z = z;
00664 if (m_useHeightMap) {
00665 double minX, minY, minZ, maxX, maxY, maxZ;
00666 m_octreeContact->getMetricMin(minX, minY, minZ);
00667 m_octreeContact->getMetricMax(maxX, maxY, maxZ);
00668 double h = (1.0 - std::min(std::max((cubeCenter.z-minZ)/ (maxZ - minZ), 0.0), 1.0)) *m_colorFactor;
00669 unknownNodesVis.markers[0].colors.push_back(heightMapColor(h));
00670 }
00671 unknownNodesVis.markers[0].points.push_back(cubeCenter);
00672 }
00673
00674 double size = m_octreeContact->getNodeSize(m_maxTreeDepth);
00675 unknownNodesVis.markers[0].header.frame_id = m_worldFrameId;
00676 unknownNodesVis.markers[0].header.stamp = rostime;
00677 unknownNodesVis.markers[0].ns = m_worldFrameId;
00678 unknownNodesVis.markers[0].id = 0;
00679 unknownNodesVis.markers[0].type = visualization_msgs::Marker::CUBE_LIST;
00680 unknownNodesVis.markers[0].scale.x = size;
00681 unknownNodesVis.markers[0].scale.y = size;
00682 unknownNodesVis.markers[0].scale.z = size;
00683 unknownNodesVis.markers[0].color = m_colorUnknown;
00684
00685 if (unknownNodesVis.markers[0].points.size() > 0) {
00686 unknownNodesVis.markers[0].action = visualization_msgs::Marker::ADD;
00687 }
00688 else {
00689 unknownNodesVis.markers[0].action = visualization_msgs::Marker::DELETE;
00690 }
00691 m_umarkerPub.publish(unknownNodesVis);
00692
00693
00694 sensor_msgs::PointCloud2 unknownRosCloud;
00695 pcl::toROSMsg (unknownCloud, unknownRosCloud);
00696 unknownRosCloud.header.frame_id = m_worldFrameId;
00697 unknownRosCloud.header.stamp = rostime;
00698 m_unknownPointCloudPub.publish(unknownRosCloud);
00699
00700
00701 if (publishFrontierMarkerArray) {
00702 visualization_msgs::MarkerArray frontierNodesVis;
00703 frontierNodesVis.markers.resize(1);
00704 pcl::PointCloud<pcl::PointXYZ> frontierCloud;
00705 double resolution = m_octreeContact->getResolution();
00706
00707 int x_num = int(((m_occupancyMaxX - m_occupancyMinX) / resolution));
00708 int y_num = int(((m_occupancyMaxY - m_occupancyMinY) / resolution));
00709 int z_num = int(((m_occupancyMaxZ - m_occupancyMinZ) / resolution));
00710 std::vector< std::vector< std::vector<int> > > check_unknown(x_num, std::vector< std::vector<int> >(y_num, std::vector<int>(z_num)));
00711 std::vector< std::vector< std::vector<int> > > check_occupied(x_num, std::vector< std::vector<int> >(y_num, std::vector<int>(z_num)));
00712 std::vector< std::vector< std::vector<int> > > check_frontier(x_num, std::vector< std::vector<int> >(y_num, std::vector<int>(z_num)));
00713
00714 for (int i = 0; i < x_num; i++) {
00715 for (int j = 0; j < y_num; j++) {
00716 for (int k = 0; k < z_num; k++) {
00717 check_unknown[i][j][k] = 0;
00718 check_occupied[i][j][k] = 0;
00719 check_frontier[i][j][k] = 0;
00720 }
00721 }
00722 }
00723
00724
00725 for (point3d_list::iterator it_unknown = unknownLeaves.begin();
00726 it_unknown != unknownLeaves.end();
00727 it_unknown++) {
00728
00729 double x_unknown = it_unknown->x();
00730 double y_unknown = it_unknown->y();
00731 double z_unknown = it_unknown->z();
00732 int x_index = int(std::round((x_unknown - m_occupancyMinX) / resolution - 1));
00733 int y_index = int(std::round((y_unknown - m_occupancyMinY) / resolution - 1));
00734 int z_index = int(std::round((z_unknown - m_occupancyMinZ) / resolution - 1));
00735 check_unknown[x_index][y_index][z_index] = 1;
00736 }
00737
00738
00739 for (int idx = 0; idx < occupiedNodesVis.markers.size(); idx++) {
00740 double size_occupied = occupiedNodesVis.markers[idx].scale.x;
00741 for (int id = 0; id < occupiedNodesVis.markers[idx].points.size(); id++) {
00742 double x_occupied = occupiedNodesVis.markers[idx].points[id].x;
00743 double y_occupied = occupiedNodesVis.markers[idx].points[id].y;
00744 double z_occupied = occupiedNodesVis.markers[idx].points[id].z;
00745 int x_min_index = std::round((x_occupied - (size_occupied / 2.0) - m_occupancyMinX) / resolution);
00746 int y_min_index = std::round((y_occupied - (size_occupied / 2.0) - m_occupancyMinY) / resolution);
00747 int z_min_index = std::round((z_occupied - (size_occupied / 2.0) - m_occupancyMinZ) / resolution);
00748 for (int i = x_min_index; i < x_min_index + int(size_occupied/resolution); i++) {
00749 for (int j = y_min_index; j < y_min_index + int(size_occupied/resolution); j++) {
00750 for (int k = z_min_index; k < z_min_index + int(size_occupied/resolution); k++) {
00751 check_occupied[i][j][k] = 1;
00752 }
00753 }
00754 }
00755 }
00756 }
00757
00758
00759
00760
00761 geometry_msgs::Point cubeCenter;
00762 for (int i = 0; i < x_num; i++) {
00763 for (int j = 0; j < y_num; j++) {
00764 for (int k = 0; k < z_num-1; k++) {
00765 for (int l = -1; l <= 1; l++) {
00766 if ( i+l < 0 || x_num <= i+l ) continue;
00767 for (int m = -1; m <= 1; m++) {
00768 if ( j+m < 0 || y_num <= j+m ) continue;
00769 for (int n = -1; n <= 1; n++) {
00770 if ( k+n < 0 || z_num <= k+n ) continue;
00771 if (l == 0 && m == 0 && n== 0) continue;
00772 if (check_unknown[i+l][j+m][k+n] == 1 && check_unknown[i][j][k] == 0 && check_occupied[i][j][k] == 0 && check_frontier[i][j][k] == 0) {
00773 check_frontier[i][j][k] = 1;
00774 cubeCenter.x = (i+0.5)*resolution + m_occupancyMinX;
00775 cubeCenter.y = (j+0.5)*resolution + m_occupancyMinY;
00776 cubeCenter.z = (k+0.5)*resolution + m_occupancyMinZ;
00777 if (m_useHeightMap) {
00778 double minX, minY, minZ, maxX, maxY, maxZ;
00779 m_octreeContact->getMetricMin(minX, minY, minZ);
00780 m_octreeContact->getMetricMax(maxX, maxY, maxZ);
00781 double h = (1.0 - std::min(std::max((cubeCenter.z-minZ)/ (maxZ - minZ), 0.0), 1.0)) *m_colorFactor;
00782 frontierNodesVis.markers[0].colors.push_back(heightMapColor(h));
00783 }
00784 frontierNodesVis.markers[0].points.push_back(cubeCenter);
00785 }
00786 }
00787 }
00788 }
00789 }
00790 }
00791 }
00792
00793
00794 double size = m_octreeContact->getNodeSize(m_maxTreeDepth);
00795 frontierNodesVis.markers[0].header.frame_id = m_worldFrameId;
00796 frontierNodesVis.markers[0].header.stamp = rostime;
00797 frontierNodesVis.markers[0].ns = m_worldFrameId;
00798 frontierNodesVis.markers[0].id = 0;
00799 frontierNodesVis.markers[0].type = visualization_msgs::Marker::CUBE_LIST;
00800 frontierNodesVis.markers[0].scale.x = size;
00801 frontierNodesVis.markers[0].scale.y = size;
00802 frontierNodesVis.markers[0].scale.z = size;
00803 frontierNodesVis.markers[0].color = m_colorFrontier;
00804
00805 if (frontierNodesVis.markers[0].points.size() > 0) {
00806 frontierNodesVis.markers[0].action = visualization_msgs::Marker::ADD;
00807 }
00808 else {
00809 frontierNodesVis.markers[0].action = visualization_msgs::Marker::DELETE;
00810 }
00811
00812 m_fromarkerPub.publish(frontierNodesVis);
00813
00814
00815 sensor_msgs::PointCloud2 frontierRosCloud;
00816 pcl::toROSMsg (frontierCloud, frontierRosCloud);
00817 frontierRosCloud.header.frame_id = m_worldFrameId;
00818 frontierRosCloud.header.stamp = rostime;
00819 m_frontierPointCloudPub.publish(frontierRosCloud);
00820 }
00821 }
00822
00823
00824 if (publishPointCloud) {
00825 sensor_msgs::PointCloud2 cloud;
00826 pcl::toROSMsg (pclCloud, cloud);
00827 cloud.header.frame_id = m_worldFrameId;
00828 cloud.header.stamp = rostime;
00829 m_pointCloudPub.publish(cloud);
00830 }
00831
00832 if (publishBinaryMap) {
00833 publishBinaryOctoMap(rostime);
00834 }
00835
00836 if (publishFullMap) {
00837 publishFullOctoMap(rostime);
00838 }
00839
00840 double totalElapsed = (ros::WallTime::now() - startTime).toSec();
00841 ROS_DEBUG("Map publishing in OctomapServer took %f sec", totalElapsed);
00842 }
00843
00844 void OctomapServerContact::onInit(void)
00845 {
00846 DiagnosticNodelet::onInit();
00847 onInitPostProcess();
00848 }
00849 }
00850
00851 #include <pluginlib/class_list_macros.h>
00852 PLUGINLIB_EXPORT_CLASS (jsk_pcl_ros::OctomapServerContact, nodelet::Nodelet);