ColorOctomapServer.cpp
Go to the documentation of this file.
00001 
00006 /*
00007  * Copyright (c) 2010, A. Hornung, University of Freiburg
00008  * All rights reserved.
00009  */
00010 
00011 
00012 #include "ColorOctomapServer.h"
00013 #include "scoped_timer.h"
00014 #include <pcl_ros/transforms.h>
00015 #include <pcl_ros/impl/transforms.hpp>
00016 #include <GL/gl.h>
00017 
00018 ColorOctomapServer::ColorOctomapServer() : m_octoMap(0.05)
00019 { 
00020   reset();
00021 }
00022 
00023 
00024 ColorOctomapServer::~ColorOctomapServer() {}
00026 void ColorOctomapServer::reset()
00027 {
00028   m_octoMap.clear();
00029   ParameterServer* ps = ParameterServer::instance();
00030   m_octoMap.setClampingThresMin(ps->get<double>("octomap_clamping_min"));
00031   m_octoMap.setClampingThresMax(ps->get<double>("octomap_clamping_max"));
00032   m_octoMap.setResolution(ps->get<double>("octomap_resolution"));
00033   m_octoMap.setOccupancyThres(ps->get<double>("octomap_occupancy_threshold"));
00034   m_octoMap.setProbHit(ps->get<double>("octomap_prob_hit"));
00035   m_octoMap.setProbMiss(ps->get<double>("octomap_prob_miss"));
00036 }
00037 
00038 bool ColorOctomapServer::save(const char* filename) const
00039 {
00040   ScopedTimer s(__FUNCTION__);
00041   std::ofstream outfile(filename, std::ios_base::out | std::ios_base::binary);
00042   if (outfile.is_open()){
00043     //m_octoMap.writeConst(outfile); 
00044     if (ParameterServer::instance()->get<bool>("concurrent_io")) {
00045       ROS_INFO("Waiting for rendering thread to finish");
00046       rendering.waitForFinished();
00047     }
00048     ROS_INFO("Writing octomap to %s", filename);
00049     m_octoMap.write(outfile); 
00050     outfile.close();
00051     ROS_INFO("color tree written %s", filename);
00052     return true;
00053   }
00054   else {
00055     ROS_INFO("could not open  %s for writing", filename);
00056     return false;
00057   }
00058 }
00059 
00060 //Same as the other insertCloudCallback, but relies on the sensor position information in the cloud
00061 void ColorOctomapServer::insertCloudCallback(const pointcloud_type::ConstPtr cloud, double max_range) {
00062   
00063   ScopedTimer s(__FUNCTION__);
00064 
00065   //Conversions
00066   Eigen::Quaternionf q = cloud->sensor_orientation_;
00067   Eigen::Vector4f t = cloud->sensor_origin_;
00068   tf::Transform trans(tf::Quaternion(q.x(), q.y(), q.z(), q.w()), tf::Vector3(t[0], t[1], t[2]));
00069   octomap::point3d origin(t[0], t[1], t[2]);
00070   pointcloud_type::Ptr pcl_cloud(new pointcloud_type);
00071 
00072   //Work
00073   pcl_ros::transformPointCloud(*cloud, *pcl_cloud, trans);
00074 
00075   //Conversions
00076   boost::shared_ptr<octomap::Pointcloud> octomapCloud(new octomap::Pointcloud());
00077 
00078   //Work 
00079   octomapCloud->reserve(pcl_cloud->size());
00080   for (pointcloud_type::const_iterator it = pcl_cloud->begin(); it != pcl_cloud->end(); ++it){
00081     if (!std::isnan(it->z)) octomapCloud->push_back(it->x, it->y, it->z);
00082   }
00083 
00084   if (ParameterServer::instance()->get<bool>("concurrent_io")) {
00085     rendering.waitForFinished();
00086     rendering = QtConcurrent::run(this, &ColorOctomapServer::insertCloudCallbackCommon, octomapCloud, pcl_cloud, origin, max_range);
00087   }
00088   else {
00089     insertCloudCallbackCommon(octomapCloud, pcl_cloud, origin, max_range);
00090   }
00091 }
00092 
00093 void ColorOctomapServer::insertCloudCallbackCommon(boost::shared_ptr<octomap::Pointcloud> octomapCloud,
00094                                                    pointcloud_type::ConstPtr color_cloud,
00095                                                    const octomap::point3d& origin, double max_range) {
00096   if(m_octoMap.getResolution() != ParameterServer::instance()->get<double>("octomap_resolution")){
00097     ROS_WARN("OctoMap resolution changed from %f to %f. Resetting Octomap", 
00098              m_octoMap.getResolution(), ParameterServer::instance()->get<double>("octomap_resolution"));
00099     this->reset();
00100   }
00101   //geometry_msgs::Point origin;
00102   //tf::pointTFToMsg(trans.getOrigin(), origin);
00103 
00104   ROS_DEBUG("inserting data");
00105   m_octoMap.insertPointCloud(*octomapCloud, origin, max_range, true); 
00106   // integrate color measurements
00107   unsigned char* colors = new unsigned char[3];
00108 
00109   ROS_DEBUG("inserting color measurements");
00110   pointcloud_type::const_iterator it;
00111   for (it = color_cloud->begin(); it != color_cloud->end(); ++it) {
00112     // Check if the point is invalid
00113     if (!isnan(it->x) && !isnan(it->y) && !isnan(it->z)) {
00114 #ifndef RGB_IS_4TH_DIM
00115       const int rgb = *reinterpret_cast<const int*>(&(it->rgb));
00116 #else
00117       const int rgb = *reinterpret_cast<const int*>(&(it->data[3]));
00118 #endif
00119       colors[0] = ((rgb >> 16) & 0xff);
00120       colors[1] = ((rgb >> 8) & 0xff);
00121       colors[2] = (rgb & 0xff);
00122       m_octoMap.averageNodeColor(it->x, it->y, it->z, colors[0], colors[1], colors[2]);
00123     }
00124   }
00125 
00126   // updates inner node colors, too
00127   ROS_DEBUG("updating inner nodes");
00128   m_octoMap.updateInnerOccupancy();
00129 }
00130 
00131 //Filter, e.g. points in free space
00132 void ColorOctomapServer::occupancyFilter(pointcloud_type::ConstPtr input, 
00133                                          pointcloud_type::Ptr output, 
00134                                          double occupancy_threshold){
00135   if(output->points.capacity() < input->size()){ //cannot happen for input == output
00136     output->reserve(input->size());
00137   }
00138 
00139   Eigen::Quaternionf q = input->sensor_orientation_;
00140   Eigen::Vector4f t = input->sensor_origin_;
00141 
00142   size_t size = input->size();
00143   size_t outidx = 0;
00144   for (size_t inidx = 0; inidx < size; ++inidx){
00145     const point_type& in_point = (*input)[inidx];
00146     Eigen::Vector3f in_vec = q * in_point.getVector3fMap() + t.head<3>();
00147     if (std::isnan(in_vec.z())) 
00148       continue;
00149 
00150     const int radius = 1;
00151     int x_a = m_octoMap.coordToKey(in_vec.x()) - radius;
00152     int x_b = m_octoMap.coordToKey(in_vec.x()) + radius;
00153     int y_a = m_octoMap.coordToKey(in_vec.y()) - radius;
00154     int y_b = m_octoMap.coordToKey(in_vec.y()) + radius;
00155     int z_a = m_octoMap.coordToKey(in_vec.z()) - radius;
00156     int z_b = m_octoMap.coordToKey(in_vec.z()) + radius;
00157     double sum_of_occupancy = 0, sum_of_weights = 0;
00158     for(;x_a <= x_b; ++x_a){
00159       for(;y_a <= y_b; ++y_a){
00160         for(;z_a <= z_b; ++z_a){
00161           octomap::OcTreeNode* node = m_octoMap.search(octomap::OcTreeKey(x_a, y_a, z_a));
00162           if(node != NULL){
00163             double dx = m_octoMap.keyToCoord(x_a) - in_vec.x();
00164             double dy = m_octoMap.keyToCoord(y_a) - in_vec.y();
00165             double dz = m_octoMap.keyToCoord(z_a) - in_vec.z();
00166             double weight = dx*dx+dy*dy+dz*dz;
00167             double weighted_occ = node->getOccupancy() / weight;
00168             sum_of_weights += weight;
00169             sum_of_occupancy += weighted_occ;
00170           }
00171         }
00172       }
00173     }
00174             
00175 
00176     if(sum_of_occupancy < occupancy_threshold * sum_of_weights) //Filters points in non-existent nodes (outside of map?) 
00177     //if(node != NULL && node->getOccupancy() >= occupancy_threshold) 
00178     { //Valid point
00179       point_type& out_point = (*output)[outidx];
00180       out_point = in_point;
00181       ++outidx;
00182     } 
00183   }
00184   output->resize(outidx);//downsize
00185 }
00186 
00187 void ColorOctomapServer::render(){
00188   octomap::ColorOcTree::tree_iterator it = m_octoMap.begin_tree();
00189   octomap::ColorOcTree::tree_iterator end = m_octoMap.end_tree();
00190   int counter = 0;
00191   double occ_thresh = ParameterServer::instance()->get<double>("occupancy_filter_threshold");
00192   int level = ParameterServer::instance()->get<int>("octomap_display_level");
00193   if(occ_thresh > 0) {
00194     glDisable(GL_LIGHTING);
00195     glEnable (GL_BLEND); 
00196     //glDisable(GL_CULL_FACE);
00197     glBegin(GL_TRIANGLES);
00198     double stretch_factor = 128/(1 - occ_thresh); //occupancy range in which the displayed cubes can be
00199     for(; it != end; ++counter, ++it){
00200       if(level != it.getDepth()){
00201         continue;
00202       }
00203       double occ = it->getOccupancy();
00204       if(occ < occ_thresh){
00205         continue;
00206       }
00207       glColor4ub(it->getColor().r, it->getColor().g, it->getColor().b, 128 /*basic visibility*/ + (occ - occ_thresh) * stretch_factor );
00208       float halfsize = it.getSize()/2.0;
00209       float x = it.getX(); 
00210       float y = it.getY(); 
00211       float z = it.getZ(); 
00212       //Front
00213       glVertex3f(x-halfsize,y-halfsize,z-halfsize);
00214       glVertex3f(x-halfsize,y+halfsize,z-halfsize);
00215       glVertex3f(x+halfsize,y+halfsize,z-halfsize);
00216 
00217       glVertex3f(x-halfsize,y-halfsize,z-halfsize);
00218       glVertex3f(x+halfsize,y+halfsize,z-halfsize);
00219       glVertex3f(x+halfsize,y-halfsize,z-halfsize);
00220 
00221       //Back
00222       glVertex3f(x-halfsize,y-halfsize,z+halfsize);
00223       glVertex3f(x+halfsize,y-halfsize,z+halfsize);
00224       glVertex3f(x+halfsize,y+halfsize,z+halfsize);
00225 
00226       glVertex3f(x-halfsize,y-halfsize,z+halfsize);
00227       glVertex3f(x+halfsize,y+halfsize,z+halfsize);
00228       glVertex3f(x-halfsize,y+halfsize,z+halfsize);
00229 
00230       //Left
00231       glVertex3f(x-halfsize,y-halfsize,z-halfsize);
00232       glVertex3f(x-halfsize,y-halfsize,z+halfsize);
00233       glVertex3f(x-halfsize,y+halfsize,z+halfsize);
00234 
00235       glVertex3f(x-halfsize,y-halfsize,z-halfsize);
00236       glVertex3f(x-halfsize,y+halfsize,z+halfsize);
00237       glVertex3f(x-halfsize,y+halfsize,z-halfsize);
00238 
00239       //Right
00240       glVertex3f(x+halfsize,y-halfsize,z-halfsize);
00241       glVertex3f(x+halfsize,y+halfsize,z-halfsize);
00242       glVertex3f(x+halfsize,y+halfsize,z+halfsize);
00243 
00244       glVertex3f(x+halfsize,y-halfsize,z-halfsize);
00245       glVertex3f(x+halfsize,y+halfsize,z+halfsize);
00246       glVertex3f(x+halfsize,y-halfsize,z+halfsize);
00247 
00248       //?
00249       glVertex3f(x-halfsize,y-halfsize,z-halfsize);
00250       glVertex3f(x+halfsize,y-halfsize,z-halfsize);
00251       glVertex3f(x+halfsize,y-halfsize,z+halfsize);
00252 
00253       glVertex3f(x-halfsize,y-halfsize,z-halfsize);
00254       glVertex3f(x+halfsize,y-halfsize,z+halfsize);
00255       glVertex3f(x-halfsize,y-halfsize,z+halfsize);
00256 
00257       //?
00258       glVertex3f(x-halfsize,y+halfsize,z-halfsize);
00259       glVertex3f(x-halfsize,y+halfsize,z+halfsize);
00260       glVertex3f(x+halfsize,y+halfsize,z+halfsize);
00261 
00262       glVertex3f(x-halfsize,y+halfsize,z-halfsize);
00263       glVertex3f(x+halfsize,y+halfsize,z+halfsize);
00264       glVertex3f(x+halfsize,y+halfsize,z-halfsize);
00265     }
00266     glEnd();
00267   }
00268 }


rgbdslam_v2
Author(s): Felix Endres, Juergen Hess, Nikolas Engelhard
autogenerated on Thu Jun 6 2019 21:49:45