pcl_to_octree.cpp
Go to the documentation of this file.
00001 /*
00002  * Based on the original code by Kai M. Wurm and Armin Hornung
00003  * (http://octomap.sourceforge.net)
00004  * Author: Hozefa Indorewala
00005  */
00006 
00007 #include <ros/ros.h>
00008 #include <sensor_msgs/PointCloud.h>
00009 #include <sensor_msgs/PointCloud2.h>
00010 #include <sensor_msgs/point_cloud_conversion.h>
00011 #include "octomap/octomap.h"
00012 #include "pcl_to_octree/octree/OcTreeNodePCL.h"
00013 #include "pcl_to_octree/octree/OcTreePCL.h"
00014 #include "pcl_to_octree/octree/OcTreeServerPCL.h"
00015 //#include "octomap_server/octomap_server.h"
00016 #include <pcl/point_types.h>
00017 #include <pcl/io/pcd_io.h>
00018 #include <pcl/ros/conversions.h>
00019 #include <visualization_msgs/MarkerArray.h>
00020 
00021 #include <vector>
00022 #include <iostream>
00023 
00024 class PclToOctree
00025 {
00026 public:
00027   PclToOctree();
00028   ~PclToOctree();
00029         void pclToOctreeCallback(const sensor_msgs::PointCloud2& msg);
00030         void run();
00031 
00032 private:
00033   ros::NodeHandle nh_;
00034   double laser_offset_, octree_res_;
00035   int octree_maxrange_, level_;
00036   std::string point_cloud_topic_, frame_id_;
00037   bool visualize_octree_, visualize_only_occupied_cells_;
00038         // Publishes the octree in MarkerArray format so that it can be visualized in rviz
00039   ros::Publisher octree_marker_array_publisher_;
00040 
00041         /*
00042          * The following publisher, even though not required, is used because otherwise rviz
00043          * cannot visualize the MarkerArray format without advertising the Marker format
00044          */
00045   ros::Publisher octree_marker_publisher_;
00046 
00047         ros::Publisher octree_binary_publisher_;
00048 
00049         // Subscribes to the PointCloud format to acquire point cloud data
00050         ros::Subscriber pointcloud_subscriber_;
00051 
00052         // Marker array to visualize the octree. It displays the occuplied cells of the octree
00053         visualization_msgs::MarkerArray octree_marker_array_msg_;
00054 };
00055 
00056 
00057 
00058 
00059 PclToOctree::PclToOctree() : nh_("~")
00060 {
00061   nh_.param("laser_offset", laser_offset_, 1.5);
00062   nh_.param("octree_resolution", octree_res_, 0.05);
00063   nh_.param("octree_maxrange", octree_maxrange_, -1);
00064   nh_.param("point_cloud_topic", point_cloud_topic_, std::string("/merged_cloud"));
00065   nh_.param("frame_id", frame_id_, std::string("/map"));
00066   nh_.param("level", level_, 0);
00067   nh_.param("visualize_octree", visualize_octree_, false);
00068   nh_.param("visualize_only_occupied_cells", visualize_only_occupied_cells_, true);
00069   ROS_INFO("pcl_to_octree node is up and running.");
00070   run();
00071 }
00072 
00073 
00074 void PclToOctree::run()
00075 {
00076   octree_marker_array_publisher_ = nh_.advertise<visualization_msgs::MarkerArray>("visualization_marker_array", 100);
00077 
00078   octree_marker_publisher_ = nh_.advertise<visualization_msgs::Marker>("visualization_marker", 100);
00079 
00080   octree_binary_publisher_ = nh_.advertise<octomap_ros::OctomapBinary>("octree_binary", 100);
00081 
00082   pointcloud_subscriber_ = nh_.subscribe(point_cloud_topic_, 100, &PclToOctree::pclToOctreeCallback, this);
00083 
00084   ros::spin();
00085 }
00086 
00087 PclToOctree::~PclToOctree()
00088 {
00089   ROS_INFO("Shutting down pcl_to_octree node!");
00090   octree_marker_array_publisher_.shutdown();
00091   octree_marker_publisher_.shutdown();
00092 }
00093 
00094 void PclToOctree::pclToOctreeCallback(const sensor_msgs::PointCloud2& pointcloud2_msg)
00095 {
00096   ROS_INFO("Received a point cloud.");
00097 
00098   frame_id_ = pointcloud2_msg.header.frame_id;
00099   //sensor_msgs::PointCloud2 pointcloud2_msg;
00100   octomap_ros::OctomapBinary octree_msg;
00101 
00102   // Converting from PointCloud msg format to PointCloud2 msg format
00103   //sensor_msgs::convertPointCloudToPointCloud2(pointcloud_msg, pointcloud2_msg);
00104   pcl::PointCloud<pcl::PointXYZ> pointcloud2_pcl;
00105 
00106   octomap::point3d octomap_3d_point;
00107   octomap::Pointcloud octomap_pointcloud;
00108 
00109   //Converting PointCloud2 msg format to pcl pointcloud format in order to read the 3d data
00110   pcl::fromROSMsg(pointcloud2_msg, pointcloud2_pcl);
00111 
00112   //Reading from pcl point cloud and saving it into octomap point cloud
00113   for(unsigned int i =0; i < pointcloud2_pcl.points.size(); i++)
00114   {
00115           octomap_3d_point(0) = pointcloud2_pcl.points[i].x;
00116           octomap_3d_point(1) = pointcloud2_pcl.points[i].y;
00117           octomap_3d_point(2) = pointcloud2_pcl.points[i].z;
00118           octomap_pointcloud.push_back(octomap_3d_point);
00119   }
00120 
00121   // Converting from octomap point cloud to octomap graph
00122   octomap::pose6d offset_trans(0,0,-laser_offset_,0,0,0);
00123   octomap::pose6d laser_pose(0,0,laser_offset_,0,0,0);
00124   octomap_pointcloud.transform(offset_trans);
00125 
00126 
00127   octomap::ScanGraph* octomap_graph = new octomap::ScanGraph();
00128   octomap_graph->addNode(&octomap_pointcloud, laser_pose);
00129 
00130   ROS_INFO("Number of points in graph: %d", octomap_graph->getNumPoints());
00131 
00132   // Converting from octomap graph to octomap tree (octree)
00133   octomap::OcTreePCL* octree = new octomap::OcTreePCL(octree_res_);
00134   for (octomap::ScanGraph::iterator scan_it = octomap_graph->begin(); scan_it != octomap_graph->end(); scan_it++)
00135   {
00136     octree->insertScan(**scan_it, octree_maxrange_, false);
00137   }
00138   //octomap_server::octomapMapToMsg(*octree, octree_msg);
00139   //octree_binary_publisher_.publish(octree_msg);
00140   //ROS_INFO("Octree built and published");
00141 
00142   std::list<octomap::OcTreeVolume> voxels, leaves;
00143   //octree->getLeafNodes(leaves, level_);
00144   octree->getLeafNodes(leaves);
00145   std::list<octomap::OcTreeVolume>::iterator it1;
00146   //int cnt = 0;
00147 
00148   //find Leaf Nodes' centroids, assign controid coordinates to Leaf Node
00149   for( it1 = leaves.begin(); it1 != leaves.end(); ++it1)
00150   {
00151     //ROS_INFO("Leaf Node %d : x = %f y = %f z = %f side length = %f ", cnt++, it1->first.x(), it1->first.y(), it1->first.z(), it1->second);
00152     octomap::point3d centroid;
00153     centroid(0) = it1->first.x(),  centroid(1) = it1->first.y(),  centroid(2) = it1->first.z();
00154     octomap::OcTreeNodePCL *octree_node = octree->search(centroid);
00155     octree_node->setCentroid(centroid);
00156     //octree_node->setLabel(0);
00157   }
00158 
00159   //assign points to Leaf Nodes
00160   for(unsigned int i = 0; i < pointcloud2_pcl.points.size(); i++)
00161   {
00162     octomap_3d_point(0) = pointcloud2_pcl.points[i].x;
00163     octomap_3d_point(1) = pointcloud2_pcl.points[i].y;
00164     octomap_3d_point(2) = pointcloud2_pcl.points[i].z;
00165     octomap::OcTreeNodePCL * octree_node1 = octree->search(octomap_3d_point);
00166     octree_node1->set3DPointInliers(i);
00167   }
00168 
00169   //test if inliers stored correctly
00170   for( it1 = leaves.begin(); it1 != leaves.end(); ++it1)
00171   {
00172     //ROS_INFO("Leaf Node %d : x = %f y = %f z = %f side length = %f ", cnt, it1->first.x(), it1->first.y(), it1->first.z(), it1->second);
00173     //cnt++;
00174     octomap::point3d centroid1;
00175     centroid1(0) = it1->first.x(),  centroid1(1) = it1->first.y(),  centroid1(2) = it1->first.z();
00176     octomap::OcTreeNodePCL *octree_node_test = octree->search(centroid1);
00177     if (octree_node_test->get3DPointInliers().size() != 0)
00178     {
00179       std::stringstream inliers_stream;
00180       for (unsigned long i = 0; i < octree_node_test->get3DPointInliers().size(); i++)
00181       {
00182         inliers_stream << octree_node_test->get3DPointInliers()[i] << ", ";
00183       }
00184       //ROS_INFO("inliers: %s", inliers_stream.str().c_str());
00185       //ROS_INFO("label: %d",  octree_node_test->getLabel());
00186       //ROS_INFO("centroid: %f, %f, %f",  octree_node_test->getCentroid().x(),  octree_node_test->getCentroid().y(),
00187       //         octree_node_test->getCentroid().z());
00188     }
00189   }
00190 
00191   //print metric size of octree
00192   double sx, sy, sz;
00193   octree->getMetricSize(sx, sy, sz);
00194   ROS_INFO("Octree metric size x: %f, y: %f, z: %f", sx, sy, sz);
00195 
00196   //convert octree to OctreeBinary (serialization)
00197   octomap_server::octomapMapToMsg(*octree, octree_msg);
00198   octree_binary_publisher_.publish(octree_msg);
00199   ROS_INFO("OctreeBinary built and published");
00200 
00201   //**********************************************************************************
00202   //Visualization of Octree
00203   //**********************************************************************************
00204   if (visualize_octree_)
00205   {
00206     // each array stores all cubes of a different size, one for each depth level:
00207     octree_marker_array_msg_.markers.resize(16);
00208     double lowestRes = octree->getResolution();
00209     std::list<octomap::OcTreeVolume>::iterator it;
00210 
00211     for(unsigned int i = 0; i < 16; i++)
00212     {
00213       std::list<octomap::OcTreeVolume> all_cells;
00214       //getting the occupied cells at different depths of the octree
00215       if(visualize_only_occupied_cells_ == true)
00216       {
00217         octree->getOccupied(all_cells, i);
00218       }
00219       else
00220       {
00221         octree->getLeafNodes(all_cells, i);
00222       }
00223       for (it = all_cells.begin(); it != all_cells.end(); ++it)
00224       {
00225         // which array to store cubes in?
00226         int idx = int(log2(it->second / lowestRes) +0.5);
00227         assert (idx >= 0 && unsigned(idx) < octree_marker_array_msg_.markers.size());
00228         geometry_msgs::Point cube_center;
00229         cube_center.x = it->first.x();
00230         cube_center.y = it->first.y();
00231         cube_center.z = it->first.z();
00232         octree_marker_array_msg_.markers[idx].points.push_back(cube_center);
00233       }
00234     }
00235 
00236     for (unsigned i = 0; i < octree_marker_array_msg_.markers.size(); ++i)
00237     {
00238       octree_marker_array_msg_.markers[i].header.frame_id = frame_id_;
00239       octree_marker_array_msg_.markers[i].header.stamp = ros::Time::now();
00240 
00241       double size = lowestRes * pow(2,i);
00242 
00243       std::stringstream ss;
00244       ss <<"Level "<<i;
00245       octree_marker_array_msg_.markers[i].ns = ss.str();
00246       octree_marker_array_msg_.markers[i].id = i;
00247       octree_marker_array_msg_.markers[i].lifetime = ros::Duration::Duration();
00248       octree_marker_array_msg_.markers[i].type = visualization_msgs::Marker::CUBE_LIST;
00249       octree_marker_array_msg_.markers[i].scale.x = size;
00250       octree_marker_array_msg_.markers[i].scale.y = size;
00251       octree_marker_array_msg_.markers[i].scale.z = size;
00252       octree_marker_array_msg_.markers[i].color.r = 1.0f;
00253       octree_marker_array_msg_.markers[i].color.g = 0.0f;
00254       octree_marker_array_msg_.markers[i].color.b = 0.0f;
00255       octree_marker_array_msg_.markers[i].color.a = 0.5f;
00256 
00257 
00258       if (octree_marker_array_msg_.markers[i].points.size() > 0)
00259         octree_marker_array_msg_.markers[i].action = visualization_msgs::Marker::ADD;
00260       else
00261         octree_marker_array_msg_.markers[i].action = visualization_msgs::Marker::DELETE;
00262 
00263     }
00264 
00265     octree_marker_array_publisher_.publish(octree_marker_array_msg_);
00266 
00267 
00268     for (unsigned int i = 0; i < octree_marker_array_msg_.markers.size(); i++)
00269     {
00270       if (!octree_marker_array_msg_.markers[i].points.empty())
00271       {
00272         octree_marker_array_msg_.markers[i].points.clear();
00273       }
00274     }
00275     octree_marker_array_msg_.markers.clear();
00276   }
00277 }
00278 
00279 int main(int argc, char** argv)
00280 {
00281   ros::init(argc, argv, "pcl_to_octree");
00282   PclToOctree pcl_to_octree;
00283   return (0);
00284 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends Defines


pcl_to_octree
Author(s): Hozefa Indorewala, Dejan Pangercic
autogenerated on Sun Oct 6 2013 12:03:28