00001
00006
00007
00008
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
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
00061 void ColorOctomapServer::insertCloudCallback(const pointcloud_type::ConstPtr cloud, double max_range) {
00062
00063 ScopedTimer s(__FUNCTION__);
00064
00065
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
00073 pcl_ros::transformPointCloud(*cloud, *pcl_cloud, trans);
00074
00075
00076 boost::shared_ptr<octomap::Pointcloud> octomapCloud(new octomap::Pointcloud());
00077
00078
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
00102
00103
00104 ROS_DEBUG("inserting data");
00105 m_octoMap.insertPointCloud(*octomapCloud, origin, max_range, true);
00106
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
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
00127 ROS_DEBUG("updating inner nodes");
00128 m_octoMap.updateInnerOccupancy();
00129 }
00130
00131
00132 void ColorOctomapServer::occupancyFilter(pointcloud_type::ConstPtr input,
00133 pointcloud_type::Ptr output,
00134 double occupancy_threshold){
00135 if(output->points.capacity() < input->size()){
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)
00177
00178 {
00179 point_type& out_point = (*output)[outidx];
00180 out_point = in_point;
00181 ++outidx;
00182 }
00183 }
00184 output->resize(outidx);
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
00197 glBegin(GL_TRIANGLES);
00198 double stretch_factor = 128/(1 - occ_thresh);
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 + (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
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
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
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
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 }