00001
00002
00003
00004
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
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
00039 ros::Publisher octree_marker_array_publisher_;
00040
00041
00042
00043
00044
00045 ros::Publisher octree_marker_publisher_;
00046
00047 ros::Publisher octree_binary_publisher_;
00048
00049
00050 ros::Subscriber pointcloud_subscriber_;
00051
00052
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
00100 octomap_ros::OctomapBinary octree_msg;
00101
00102
00103
00104 pcl::PointCloud<pcl::PointXYZ> pointcloud2_pcl;
00105
00106 octomap::point3d octomap_3d_point;
00107 octomap::Pointcloud octomap_pointcloud;
00108
00109
00110 pcl::fromROSMsg(pointcloud2_msg, pointcloud2_pcl);
00111
00112
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
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
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
00139
00140
00141
00142 std::list<octomap::OcTreeVolume> voxels, leaves;
00143
00144 octree->getLeafNodes(leaves);
00145 std::list<octomap::OcTreeVolume>::iterator it1;
00146
00147
00148
00149 for( it1 = leaves.begin(); it1 != leaves.end(); ++it1)
00150 {
00151
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
00157 }
00158
00159
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
00170 for( it1 = leaves.begin(); it1 != leaves.end(); ++it1)
00171 {
00172
00173
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
00185
00186
00187
00188 }
00189 }
00190
00191
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
00197 octomap_server::octomapMapToMsg(*octree, octree_msg);
00198 octree_binary_publisher_.publish(octree_msg);
00199 ROS_INFO("OctreeBinary built and published");
00200
00201
00202
00203
00204 if (visualize_octree_)
00205 {
00206
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
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
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 }