|
Point Cloud Library (PCL)
1.5.1
|
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Point Cloud Library (PCL) - www.pointclouds.org 00005 * Copyright (c) 2010-2012, Willow Garage, Inc. 00006 * 00007 * All rights reserved. 00008 * 00009 * Redistribution and use in source and binary forms, with or without 00010 * modification, are permitted provided that the following conditions 00011 * are met: 00012 * 00013 * * Redistributions of source code must retain the above copyright 00014 * notice, this list of conditions and the following disclaimer. 00015 * * Redistributions in binary form must reproduce the above 00016 * copyright notice, this list of conditions and the following 00017 * disclaimer in the documentation and/or other materials provided 00018 * with the distribution. 00019 * * Neither the name of Willow Garage, Inc. nor the names of its 00020 * contributors may be used to endorse or promote products derived 00021 * from this software without specific prior written permission. 00022 * 00023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00024 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00025 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00026 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00027 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00028 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00029 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00030 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00031 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00032 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00033 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00034 * POSSIBILITY OF SUCH DAMAGE. 00035 * 00036 */ 00037 00038 #include <pcl/pcl_macros.h> 00039 #include <pcl/common/distances.h> 00040 00041 namespace pcl 00042 { 00043 00045 inline float 00046 RangeImage::asinLookUp (float value) 00047 { 00048 float ret = asin_lookup_table[pcl_lrintf ((lookup_table_size/2)*value) + lookup_table_size/2]; 00049 //std::cout << ret << "==" << asinf(value)<<"\n"; 00050 return ret; 00051 } 00052 00054 inline float 00055 RangeImage::atan2LookUp (float y, float x) 00056 { 00057 //float ret = asin_lookup_table[pcl_lrintf((lookup_table_size/2)*value) + lookup_table_size/2]; 00058 00059 float ret; 00060 if(fabsf(x) < fabsf(y)) { 00061 ret = atan_lookup_table[pcl_lrintf ((lookup_table_size/2)*(x/y)) + lookup_table_size/2]; 00062 ret = (float) (x*y > 0 ? M_PI/2-ret : -M_PI/2-ret); 00063 //if (fabsf(ret-atanf(y/x)) > 1e-3) 00064 //std::cout << "atanf("<<y<<"/"<<x<<")"<<" = "<<ret<<" = "<<atanf(y/x)<<"\n"; 00065 } 00066 else { 00067 ret = atan_lookup_table[pcl_lrintf ((lookup_table_size/2)*(y/x)) + lookup_table_size/2]; 00068 } 00069 if (x < 0) 00070 ret = (float) (y < 0 ? ret-M_PI : ret+M_PI); 00071 00072 //if (fabsf(ret-atan2f(y,x)) > 1e-3) 00073 //std::cout << "atan2f("<<y<<","<<x<<")"<<" = "<<ret<<" = "<<atan2f(y,x)<<"\n"; 00074 00075 return ret; 00076 } 00077 00079 inline float 00080 RangeImage::cosLookUp (float value) 00081 { 00082 int cell_idx = pcl_lrintf ((lookup_table_size-1)*fabsf(value)/(2.0f*M_PI)); 00083 //if (cell_idx<0 || cell_idx>=int(cos_lookup_table.size())) 00084 //{ 00085 //std::cout << PVARC(value)<<PVARN(cell_idx); 00086 //return 0.0f; 00087 //} 00088 float ret = cos_lookup_table[cell_idx]; 00089 //std::cout << ret << "==" << cos(value)<<"\n"; 00090 return ret; 00091 } 00092 00094 template <typename PointCloudType> void 00095 RangeImage::createFromPointCloud(const PointCloudType& point_cloud, float angular_resolution, float max_angle_width, float max_angle_height, 00096 const Eigen::Affine3f& sensor_pose, RangeImage::CoordinateFrame coordinate_frame, 00097 float noise_level, float min_range, int border_size) 00098 { 00099 //MEASURE_FUNCTION_TIME; 00100 00101 00102 //std::cout << "Starting to create range image from "<<point_cloud.points.size()<<" points.\n"; 00103 00104 angular_resolution_ = angular_resolution; 00105 angular_resolution_reciprocal_ = 1.0f / angular_resolution_; 00106 00107 width = pcl_lrint(floor(max_angle_width*angular_resolution_reciprocal_)); 00108 height = pcl_lrint(floor(max_angle_height*angular_resolution_reciprocal_)); 00109 image_offset_x_ = image_offset_y_ = 0; // TODO: FIX THIS 00110 is_dense = false; 00111 00112 getCoordinateFrameTransformation(coordinate_frame, to_world_system_); 00113 to_world_system_ = sensor_pose * to_world_system_; 00114 00115 to_range_image_system_ = to_world_system_.inverse (); 00116 //std::cout << "to_world_system_ is\n"<<to_world_system_<<"\nand to_range_image_system_ is\n"<<to_range_image_system_<<"\n\n"; 00117 00118 unsigned int size = width*height; 00119 points.clear(); 00120 points.resize(size, unobserved_point); 00121 00122 int top=height, right=-1, bottom=-1, left=width; 00123 doZBuffer(point_cloud, noise_level, min_range, top, right, bottom, left); 00124 00125 cropImage(border_size, top, right, bottom, left); 00126 00127 recalculate3DPointPositions(); 00128 } 00129 00130 00132 template <typename PointCloudTypeWithViewpoints> void 00133 RangeImage::createFromPointCloudWithViewpoints(const PointCloudTypeWithViewpoints& point_cloud, float angular_resolution, 00134 float max_angle_width, float max_angle_height, RangeImage::CoordinateFrame coordinate_frame, 00135 float noise_level, float min_range, int border_size) 00136 { 00137 Eigen::Vector3f average_viewpoint = getAverageViewPoint(point_cloud); 00138 00139 Eigen::Affine3f sensor_pose = (Eigen::Affine3f)Eigen::Translation3f(average_viewpoint); 00140 00141 createFromPointCloud(point_cloud, angular_resolution, max_angle_width, max_angle_height, sensor_pose, coordinate_frame, noise_level, min_range, border_size); 00142 00143 //change3dPointsToLocalCoordinateFrame(); 00144 } 00145 00147 template <typename PointCloudType> void 00148 RangeImage::createFromPointCloudWithKnownSize(const PointCloudType& point_cloud, float angular_resolution, 00149 const Eigen::Vector3f& point_cloud_center, float point_cloud_radius, 00150 const Eigen::Affine3f& sensor_pose, RangeImage::CoordinateFrame coordinate_frame, 00151 float noise_level, float min_range, int border_size) 00152 { 00153 //MEASURE_FUNCTION_TIME; 00154 00155 //std::cout << "Starting to create range image from "<<point_cloud.points.size()<<" points.\n"; 00156 00157 angular_resolution_ = angular_resolution; 00158 angular_resolution_reciprocal_ = 1.0f / angular_resolution_; 00159 00160 getCoordinateFrameTransformation(coordinate_frame, to_world_system_); 00161 to_world_system_ = sensor_pose * to_world_system_; 00162 to_range_image_system_ = to_world_system_.inverse (); 00163 00164 float max_angle_size = getMaxAngleSize(sensor_pose, point_cloud_center, point_cloud_radius); 00165 int pixel_radius = pcl_lrint(ceil(0.5f*max_angle_size*angular_resolution_reciprocal_)); 00166 width = height = 2*pixel_radius; 00167 is_dense = false; 00168 00169 image_offset_x_ = image_offset_y_ = 0; 00170 int center_pixel_x, center_pixel_y; 00171 getImagePoint(point_cloud_center, center_pixel_x, center_pixel_y); 00172 image_offset_x_ = (std::max)(0, center_pixel_x-pixel_radius); 00173 image_offset_y_ = (std::max)(0, center_pixel_y-pixel_radius); 00174 //std::cout << PVARC(image_offset_x_)<<PVARN(image_offset_y_); 00175 //std::cout << PVARC(width)<<PVARN(height); 00176 //std::cout << PVARAN(angular_resolution_); 00177 00178 points.clear(); 00179 points.resize(width*height, unobserved_point); 00180 00181 int top=height, right=-1, bottom=-1, left=width; 00182 doZBuffer(point_cloud, noise_level, min_range, top, right, bottom, left); 00183 00184 cropImage(border_size, top, right, bottom, left); 00185 00186 recalculate3DPointPositions(); 00187 } 00188 00190 template <typename PointCloudType> void 00191 RangeImage::doZBuffer(const PointCloudType& point_cloud, float noise_level, float min_range, int& top, int& right, int& bottom, int& left) 00192 { 00193 typedef typename PointCloudType::PointType PointType2; 00194 const std::vector<PointType2, Eigen::aligned_allocator<PointType2> >& points2 = point_cloud.points; 00195 00196 unsigned int size = width*height; 00197 int* counters = new int[size]; 00198 ERASE_ARRAY(counters, size); 00199 00200 top=height; right=-1; bottom=-1; left=width; 00201 00202 float x_real, y_real, range_of_current_point; 00203 int x, y; 00204 for (typename std::vector<PointType2, Eigen::aligned_allocator<PointType2> >::const_iterator it=points2.begin(); it!=points2.end(); ++it) 00205 { 00206 if (!isFinite (*it)) // Check for NAN etc 00207 continue; 00208 Vector3fMapConst current_point = it->getVector3fMap(); 00209 00210 this->getImagePoint(current_point, x_real, y_real, range_of_current_point); 00211 this->real2DToInt2D(x_real, y_real, x, y); 00212 00213 if (range_of_current_point < min_range|| !isInImage(x, y)) 00214 continue; 00215 //std::cout << "("<<current_point[0]<<", "<<current_point[1]<<", "<<current_point[2]<<") falls into pixel "<<x<<","<<y<<".\n"; 00216 00217 // Do some minor interpolation by checking the three closest neighbors to the point, that are not filled yet. 00218 int floor_x = pcl_lrint (floor (x_real)), floor_y = pcl_lrint (floor (y_real)), 00219 ceil_x = pcl_lrint (ceil (x_real)), ceil_y = pcl_lrint (ceil (y_real)); 00220 00221 int neighbor_x[4], neighbor_y[4]; 00222 neighbor_x[0]=floor_x; neighbor_y[0]=floor_y; 00223 neighbor_x[1]=floor_x; neighbor_y[1]=ceil_y; 00224 neighbor_x[2]=ceil_x; neighbor_y[2]=floor_y; 00225 neighbor_x[3]=ceil_x; neighbor_y[3]=ceil_y; 00226 //std::cout << x_real<<","<<y_real<<": "; 00227 00228 for (int i=0; i<4; ++i) 00229 { 00230 int n_x=neighbor_x[i], n_y=neighbor_y[i]; 00231 //std::cout << n_x<<","<<n_y<<" "; 00232 if (n_x==x && n_y==y) 00233 continue; 00234 if (isInImage(n_x, n_y)) 00235 { 00236 int neighbor_array_pos = n_y*width + n_x; 00237 if (counters[neighbor_array_pos]==0) 00238 { 00239 float& neighbor_range = points[neighbor_array_pos].range; 00240 neighbor_range = (pcl_isinf(neighbor_range) ? range_of_current_point : (std::min)(neighbor_range, range_of_current_point)); 00241 top=(std::min)(top, n_y); right=(std::max)(right, n_x); bottom=(std::max)(bottom, n_y); left=(std::min)(left, n_x); 00242 } 00243 } 00244 } 00245 //std::cout <<std::endl; 00246 00247 // The point itself 00248 int arrayPos = y*width + x; 00249 float& range_at_image_point = points[arrayPos].range; 00250 int& counter = counters[arrayPos]; 00251 bool addCurrentPoint=false, replace_with_current_point=false; 00252 00253 if (counter==0) 00254 { 00255 replace_with_current_point = true; 00256 } 00257 else 00258 { 00259 if (range_of_current_point < range_at_image_point-noise_level) 00260 { 00261 replace_with_current_point = true; 00262 } 00263 else if (fabs(range_of_current_point-range_at_image_point)<=noise_level) 00264 { 00265 addCurrentPoint = true; 00266 } 00267 } 00268 00269 if (replace_with_current_point) 00270 { 00271 counter = 1; 00272 range_at_image_point = range_of_current_point; 00273 top=(std::min)(top, y); right=(std::max)(right, x); bottom=(std::max)(bottom, y); left=(std::min)(left, x); 00274 //std::cout << "Adding point "<<x<<","<<y<<"\n"; 00275 } 00276 else if (addCurrentPoint) 00277 { 00278 ++counter; 00279 range_at_image_point += (range_of_current_point-range_at_image_point)/counter; 00280 } 00281 } 00282 00283 delete[] counters; 00284 } 00285 00287 void 00288 RangeImage::getImagePoint(float x, float y, float z, float& image_x, float& image_y, float& range) const 00289 { 00290 Eigen::Vector3f point(x, y, z); 00291 getImagePoint(point, image_x, image_y, range); 00292 } 00293 00295 void 00296 RangeImage::getImagePoint(float x, float y, float z, float& image_x, float& image_y) const 00297 { 00298 float range; 00299 getImagePoint(x, y, z, image_x, image_y, range); 00300 } 00301 00303 void 00304 RangeImage::getImagePoint(float x, float y, float z, int& image_x, int& image_y) const 00305 { 00306 float image_x_float, image_y_float; 00307 getImagePoint(x, y, z, image_x_float, image_y_float); 00308 real2DToInt2D(image_x_float, image_y_float, image_x, image_y); 00309 } 00310 00312 void 00313 RangeImage::getImagePoint(const Eigen::Vector3f& point, float& image_x, float& image_y, float& range) const 00314 { 00315 Eigen::Vector3f transformedPoint = to_range_image_system_ * point; 00316 range = transformedPoint.norm(); 00317 float angle_x = atan2LookUp(transformedPoint[0], transformedPoint[2]), 00318 angle_y = asinLookUp(transformedPoint[1]/range); 00319 getImagePointFromAngles(angle_x, angle_y, image_x, image_y); 00320 //std::cout << "("<<point[0]<<","<<point[1]<<","<<point[2]<<")" 00321 //<< " => ("<<transformedPoint[0]<<","<<transformedPoint[1]<<","<<transformedPoint[2]<<")" 00322 //<< " => "<<angle_x<<","<<angle_y<<" => "<<image_x<<","<<image_y<<"\n"; 00323 } 00324 00326 void 00327 RangeImage::getImagePoint(const Eigen::Vector3f& point, int& image_x, int& image_y, float& range) const { 00328 float image_x_float, image_y_float; 00329 getImagePoint(point, image_x_float, image_y_float, range); 00330 real2DToInt2D(image_x_float, image_y_float, image_x, image_y); 00331 } 00332 00334 void 00335 RangeImage::getImagePoint(const Eigen::Vector3f& point, float& image_x, float& image_y) const 00336 { 00337 float range; 00338 getImagePoint(point, image_x, image_y, range); 00339 } 00340 00342 void 00343 RangeImage::getImagePoint(const Eigen::Vector3f& point, int& image_x, int& image_y) const 00344 { 00345 float image_x_float, image_y_float; 00346 getImagePoint(point, image_x_float, image_y_float); 00347 real2DToInt2D(image_x_float, image_y_float, image_x, image_y); 00348 } 00349 00351 float 00352 RangeImage::checkPoint(const Eigen::Vector3f& point, PointWithRange& point_in_image) const 00353 { 00354 int image_x, image_y; 00355 float range; 00356 getImagePoint(point, image_x, image_y, range); 00357 if (!isInImage(image_x, image_y)) 00358 point_in_image = unobserved_point; 00359 else 00360 point_in_image = getPoint(image_x, image_y); 00361 return range; 00362 } 00363 00365 float 00366 RangeImage::getRangeDifference(const Eigen::Vector3f& point) const 00367 { 00368 int image_x, image_y; 00369 float range; 00370 getImagePoint(point, image_x, image_y, range); 00371 if (!isInImage(image_x, image_y)) 00372 return -std::numeric_limits<float>::infinity (); 00373 float image_point_range = getPoint(image_x, image_y).range; 00374 if (pcl_isinf(image_point_range)) 00375 { 00376 if (image_point_range > 0.0f) 00377 return std::numeric_limits<float>::infinity (); 00378 else 00379 return -std::numeric_limits<float>::infinity (); 00380 } 00381 return image_point_range - range; 00382 } 00383 00385 void 00386 RangeImage::getImagePointFromAngles(float angle_x, float angle_y, float& image_x, float& image_y) const 00387 { 00388 image_x = (angle_x*cosLookUp(angle_y) + float(M_PI))*angular_resolution_reciprocal_ - image_offset_x_; 00389 image_y = (angle_y + 0.5f*float(M_PI))*angular_resolution_reciprocal_ - image_offset_y_; 00390 } 00391 00393 void 00394 RangeImage::real2DToInt2D(float x, float y, int& xInt, int& yInt) const 00395 { 00396 xInt = pcl_lrint(x); yInt = pcl_lrint(y); 00397 } 00398 00400 bool 00401 RangeImage::isInImage(int x, int y) const 00402 { 00403 return x>=0 && x<(int)width && y>=0 && y<(int)height; 00404 } 00405 00407 bool 00408 RangeImage::isValid(int x, int y) const 00409 { 00410 return isInImage(x,y) && pcl_isfinite(getPoint(x,y).range); 00411 } 00412 00414 bool 00415 RangeImage::isValid(int index) const 00416 { 00417 return pcl_isfinite(getPoint(index).range); 00418 } 00419 00421 bool 00422 RangeImage::isObserved(int x, int y) const 00423 { 00424 if (!isInImage(x,y) || (pcl_isinf(getPoint(x,y).range)&&getPoint(x,y).range<0.0f)) 00425 return false; 00426 return true; 00427 } 00428 00430 bool 00431 RangeImage::isMaxRange(int x, int y) const 00432 { 00433 float range = getPoint(x,y).range; 00434 return pcl_isinf(range) && range>0.0f; 00435 } 00436 00438 const PointWithRange& 00439 RangeImage::getPointConsideringWrapAround(int image_x, int image_y) const 00440 { 00441 if (!isObserved(image_x, image_y)) 00442 { 00443 float angle_x, angle_y, image_x_f, image_y_f; 00444 getAnglesFromImagePoint((float) image_x, (float) image_y, angle_x, angle_y); 00445 angle_x = normAngle(angle_x); angle_y = normAngle(angle_y); 00446 getImagePointFromAngles(angle_x, angle_y, image_x_f, image_y_f); 00447 int new_image_x, new_image_y; 00448 real2DToInt2D(image_x_f, image_y_f, new_image_x, new_image_y); 00449 //if (image_x!=new_image_x || image_y!=new_image_y) 00450 //std::cout << image_x<<","<<image_y << " was change to "<<new_image_x<<","<<new_image_y<<"\n"; 00451 if (!isInImage(new_image_x, new_image_y)) 00452 return unobserved_point; 00453 image_x=new_image_x; image_y=new_image_y; 00454 } 00455 return points[image_y*width + image_x]; 00456 } 00457 00459 const PointWithRange& 00460 RangeImage::getPoint(int image_x, int image_y) const 00461 { 00462 if (!isInImage(image_x, image_y)) 00463 return unobserved_point; 00464 return points[image_y*width + image_x]; 00465 } 00466 00468 const PointWithRange& 00469 RangeImage::getPointNoCheck(int image_x, int image_y) const 00470 { 00471 return points[image_y*width + image_x]; 00472 } 00473 00475 PointWithRange& 00476 RangeImage::getPointNoCheck(int image_x, int image_y) 00477 { 00478 return points[image_y*width + image_x]; 00479 } 00480 00482 PointWithRange& 00483 RangeImage::getPoint(int image_x, int image_y) 00484 { 00485 return points[image_y*width + image_x]; 00486 } 00487 00488 00490 const PointWithRange& 00491 RangeImage::getPoint(int index) const 00492 { 00493 return points[index]; 00494 } 00495 00497 const PointWithRange& 00498 RangeImage::getPoint(float image_x, float image_y) const 00499 { 00500 int x, y; 00501 real2DToInt2D(image_x, image_y, x, y); 00502 return getPoint(x, y); 00503 } 00504 00506 PointWithRange& 00507 RangeImage::getPoint(float image_x, float image_y) 00508 { 00509 int x, y; 00510 real2DToInt2D(image_x, image_y, x, y); 00511 return getPoint(x, y); 00512 } 00513 00515 void 00516 RangeImage::getPoint(int image_x, int image_y, Eigen::Vector3f& point) const 00517 { 00518 //std::cout << getPoint(image_x, image_y)<< " - " << getPoint(image_x, image_y).getVector3fMap()<<"\n"; 00519 point = getPoint(image_x, image_y).getVector3fMap(); 00520 } 00521 00523 void 00524 RangeImage::getPoint(int index, Eigen::Vector3f& point) const 00525 { 00526 point = getPoint(index).getVector3fMap(); 00527 } 00528 00530 const Eigen::Map<const Eigen::Vector3f> 00531 RangeImage::getEigenVector3f(int x, int y) const 00532 { 00533 return getPoint(x, y).getVector3fMap(); 00534 } 00535 00537 const Eigen::Map<const Eigen::Vector3f> 00538 RangeImage::getEigenVector3f(int index) const 00539 { 00540 return getPoint(index).getVector3fMap(); 00541 } 00542 00544 void 00545 RangeImage::calculate3DPoint(float image_x, float image_y, float range, Eigen::Vector3f& point) const 00546 { 00547 float angle_x, angle_y; 00548 //std::cout << image_x<<","<<image_y<<","<<range; 00549 getAnglesFromImagePoint(image_x, image_y, angle_x, angle_y); 00550 00551 float cosY = cosf(angle_y); 00552 point = Eigen::Vector3f(range * sinf(angle_x) * cosY, range * sinf(angle_y), range * cosf(angle_x)*cosY); 00553 point = to_world_system_ * point; 00554 } 00555 00557 void 00558 RangeImage::calculate3DPoint(float image_x, float image_y, Eigen::Vector3f& point) const 00559 { 00560 const PointWithRange& point_in_image = getPoint(image_x, image_y); 00561 calculate3DPoint(image_x, image_y, point_in_image.range, point); 00562 } 00563 00565 void 00566 RangeImage::calculate3DPoint(float image_x, float image_y, float range, PointWithRange& point) const { 00567 point.range = range; 00568 Eigen::Vector3f tmp_point; 00569 calculate3DPoint(image_x, image_y, range, tmp_point); 00570 point.x=tmp_point[0]; point.y=tmp_point[1]; point.z=tmp_point[2]; 00571 } 00572 00574 void 00575 RangeImage::calculate3DPoint(float image_x, float image_y, PointWithRange& point) const 00576 { 00577 const PointWithRange& point_in_image = getPoint(image_x, image_y); 00578 calculate3DPoint(image_x, image_y, point_in_image.range, point); 00579 } 00580 00582 void 00583 RangeImage::getAnglesFromImagePoint(float image_x, float image_y, float& angle_x, float& angle_y) const 00584 { 00585 angle_y = (image_y+image_offset_y_)*angular_resolution_ - 0.5f*float(M_PI); 00586 float cos_angle_y = cosf(angle_y); 00587 angle_x = (cos_angle_y==0.0f ? 0.0f : ((image_x+image_offset_x_)*angular_resolution_ - float(M_PI))/cos_angle_y); 00588 } 00589 00591 float 00592 RangeImage::getImpactAngle(int x1, int y1, int x2, int y2) const 00593 { 00594 if (!isInImage(x1, y1) || !isInImage(x2,y2)) 00595 return -std::numeric_limits<float>::infinity (); 00596 return getImpactAngle(getPoint(x1,y1),getPoint(x2,y2)); 00597 } 00598 00600 float 00601 RangeImage::getImpactAngle(const PointWithRange& point1, const PointWithRange& point2) const { 00602 if ((pcl_isinf(point1.range)&&point1.range<0) || (pcl_isinf(point2.range)&&point2.range<0)) 00603 return -std::numeric_limits<float>::infinity (); 00604 00605 float r1 = (std::min)(point1.range, point2.range), 00606 r2 = (std::max)(point1.range, point2.range); 00607 float impact_angle = (float) (0.5f*M_PI); 00608 00609 if (pcl_isinf(r2)) { 00610 if (r2 > 0.0f && !pcl_isinf(r1)) 00611 impact_angle = 0.0f; 00612 } 00613 else if (!pcl_isinf(r1)) { 00614 float r1Sqr = r1*r1, 00615 r2Sqr = r2*r2, 00616 dSqr = squaredEuclideanDistance(point1, point2), 00617 d = sqrtf(dSqr); 00618 float cos_impact_angle = (r2Sqr + dSqr - r1Sqr)/(2.0f*r2*d); 00619 cos_impact_angle = (std::max)(0.0f, (std::min)(1.0f, cos_impact_angle)); 00620 impact_angle = acosf(cos_impact_angle); // Using the cosine rule 00621 } 00622 00623 if (point1.range > point2.range) 00624 impact_angle = -impact_angle; 00625 00626 return impact_angle; 00627 } 00628 00630 float 00631 RangeImage::getAcutenessValue(const PointWithRange& point1, const PointWithRange& point2) const 00632 { 00633 float impact_angle = getImpactAngle(point1, point2); 00634 if (pcl_isinf(impact_angle)) 00635 return -std::numeric_limits<float>::infinity (); 00636 float ret = 1.0f - float (fabs(impact_angle)/(0.5f*M_PI)); 00637 if (impact_angle < 0.0f) 00638 ret = -ret; 00639 //if (fabs(ret)>1) 00640 //std::cout << PVARAC(impact_angle)<<PVARN(ret); 00641 return ret; 00642 } 00643 00645 float 00646 RangeImage::getAcutenessValue(int x1, int y1, int x2, int y2) const 00647 { 00648 if (!isInImage(x1, y1) || !isInImage(x2,y2)) 00649 return -std::numeric_limits<float>::infinity (); 00650 return getAcutenessValue(getPoint(x1,y1), getPoint(x2,y2)); 00651 } 00652 00654 const Eigen::Vector3f 00655 RangeImage::getSensorPos() const 00656 { 00657 return Eigen::Vector3f(to_world_system_(0,3), to_world_system_(1,3), to_world_system_(2,3)); 00658 } 00659 00661 void 00662 RangeImage::getSurfaceAngleChange(int x, int y, int radius, float& angle_change_x, float& angle_change_y) const 00663 { 00664 angle_change_x = angle_change_y = -std::numeric_limits<float>::infinity (); 00665 if (!isValid(x,y)) 00666 return; 00667 Eigen::Vector3f point; 00668 getPoint(x, y, point); 00669 Eigen::Affine3f transformation = getTransformationToViewerCoordinateFrame(point); 00670 00671 if (isObserved(x-radius, y) && isObserved(x+radius, y)) 00672 { 00673 Eigen::Vector3f transformed_left; 00674 if (isMaxRange(x-radius, y)) 00675 transformed_left = Eigen::Vector3f(0.0f, 0.0f, -1.0f); 00676 else 00677 { 00678 Eigen::Vector3f left; 00679 getPoint(x-radius, y, left); 00680 transformed_left = -(transformation * left); 00681 //std::cout << PVARN(transformed_left[1]); 00682 transformed_left[1] = 0.0f; 00683 transformed_left.normalize(); 00684 } 00685 00686 Eigen::Vector3f transformed_right; 00687 if (isMaxRange(x+radius, y)) 00688 transformed_right = Eigen::Vector3f(0.0f, 0.0f, 1.0f); 00689 else 00690 { 00691 Eigen::Vector3f right; 00692 getPoint(x+radius, y, right); 00693 transformed_right = transformation * right; 00694 //std::cout << PVARN(transformed_right[1]); 00695 transformed_right[1] = 0.0f; 00696 transformed_right.normalize(); 00697 } 00698 angle_change_x = transformed_left.dot(transformed_right); 00699 angle_change_x = (std::max)(0.0f, (std::min)(1.0f, angle_change_x)); 00700 angle_change_x = acosf(angle_change_x); 00701 } 00702 00703 if (isObserved(x, y-radius) && isObserved(x, y+radius)) 00704 { 00705 Eigen::Vector3f transformed_top; 00706 if (isMaxRange(x, y-radius)) 00707 transformed_top = Eigen::Vector3f(0.0f, 0.0f, -1.0f); 00708 else 00709 { 00710 Eigen::Vector3f top; 00711 getPoint(x, y-radius, top); 00712 transformed_top = -(transformation * top); 00713 //std::cout << PVARN(transformed_top[0]); 00714 transformed_top[0] = 0.0f; 00715 transformed_top.normalize(); 00716 } 00717 00718 Eigen::Vector3f transformed_bottom; 00719 if (isMaxRange(x, y+radius)) 00720 transformed_bottom = Eigen::Vector3f(0.0f, 0.0f, 1.0f); 00721 else 00722 { 00723 Eigen::Vector3f bottom; 00724 getPoint(x, y+radius, bottom); 00725 transformed_bottom = transformation * bottom; 00726 //std::cout << PVARN(transformed_bottom[0]); 00727 transformed_bottom[0] = 0.0f; 00728 transformed_bottom.normalize(); 00729 } 00730 angle_change_y = transformed_top.dot(transformed_bottom); 00731 angle_change_y = (std::max)(0.0f, (std::min)(1.0f, angle_change_y)); 00732 angle_change_y = acosf(angle_change_y); 00733 } 00734 } 00735 00736 00737 //inline float RangeImage::getSurfaceChange(const PointWithRange& point, const PointWithRange& neighbor1, const PointWithRange& neighbor2) const 00738 //{ 00739 //if (!pcl_isfinite(point.range) || (!pcl_isfinite(neighbor1.range)&&neighbor1.range<0) || (!pcl_isfinite(neighbor2.range)&&neighbor2.range<0)) 00740 //return -std::numeric_limits<float>::infinity (); 00741 //if (pcl_isinf(neighbor1.range)) 00742 //{ 00743 //if (pcl_isinf(neighbor2.range)) 00744 //return 0.0f; 00745 //else 00746 //return acosf((Eigen::Vector3f(point.x, point.y, point.z)-getSensorPos()).normalized().dot((Eigen::Vector3f(neighbor2.x, neighbor2.y, neighbor2.z)-Eigen::Vector3f(point.x, point.y, point.z)).normalized())); 00747 //} 00748 //if (pcl_isinf(neighbor2.range)) 00749 //return acosf((Eigen::Vector3f(point.x, point.y, point.z)-getSensorPos()).normalized().dot((Eigen::Vector3f(neighbor1.x, neighbor1.y, neighbor1.z)-Eigen::Vector3f(point.x, point.y, point.z)).normalized())); 00750 00751 //float d1_squared = squaredEuclideanDistance(point, neighbor1), 00752 //d1 = sqrtf(d1_squared), 00753 //d2_squared = squaredEuclideanDistance(point, neighbor2), 00754 //d2 = sqrtf(d2_squared), 00755 //d3_squared = squaredEuclideanDistance(neighbor1, neighbor2); 00756 //float cos_surface_change = (d1_squared + d2_squared - d3_squared)/(2.0f*d1*d2), 00757 //surface_change = acosf(cos_surface_change); 00758 //if (pcl_isnan(surface_change)) 00759 //surface_change = float(M_PI); 00761 00762 //return surface_change; 00763 //} 00764 00766 float 00767 RangeImage::getMaxAngleSize(const Eigen::Affine3f& viewer_pose, const Eigen::Vector3f& center, float radius) 00768 { 00769 return 2.0f * asinf(radius/(viewer_pose.translation ()-center).norm()); 00770 } 00771 00773 Eigen::Vector3f 00774 RangeImage::getEigenVector3f(const PointWithRange& point) 00775 { 00776 return Eigen::Vector3f(point.x, point.y, point.z); 00777 } 00778 00780 void 00781 RangeImage::get1dPointAverage(int x, int y, int delta_x, int delta_y, int no_of_points, PointWithRange& average_point) const 00782 { 00783 //std::cout << __PRETTY_FUNCTION__<<" called.\n"; 00784 //MEASURE_FUNCTION_TIME; 00785 float weight_sum = 1.0f; 00786 average_point = getPoint(x,y); 00787 if (pcl_isinf(average_point.range)) 00788 { 00789 if (average_point.range>0.0f) // The first point is max range -> return a max range point 00790 return; 00791 weight_sum = 0.0f; 00792 average_point.x = average_point.y = average_point.z = average_point.range = 0.0f; 00793 } 00794 00795 int x2=x, y2=y; 00796 Vector4fMap average_point_eigen = average_point.getVector4fMap(); 00797 //std::cout << PVARN(no_of_points); 00798 for (int step=1; step<no_of_points; ++step) 00799 { 00800 //std::cout << PVARC(step); 00801 x2+=delta_x; y2+=delta_y; 00802 if (!isValid(x2, y2)) 00803 continue; 00804 const PointWithRange& p = getPointNoCheck(x2, y2); 00805 average_point_eigen+=p.getVector4fMap(); average_point.range+=p.range; 00806 weight_sum += 1.0f; 00807 } 00808 if (weight_sum<= 0.0f) 00809 { 00810 average_point = unobserved_point; 00811 return; 00812 } 00813 float normalization_factor = 1.0f/weight_sum; 00814 average_point_eigen *= normalization_factor; 00815 average_point.range *= normalization_factor; 00816 //std::cout << PVARN(average_point); 00817 } 00818 00820 float 00821 RangeImage::getEuclideanDistanceSquared(int x1, int y1, int x2, int y2) const 00822 { 00823 if (!isObserved(x1,y1)||!isObserved(x2,y2)) 00824 return -std::numeric_limits<float>::infinity (); 00825 const PointWithRange& point1 = getPoint(x1,y1), 00826 & point2 = getPoint(x2,y2); 00827 if (pcl_isinf(point1.range) && pcl_isinf(point2.range)) 00828 return 0.0f; 00829 if (pcl_isinf(point1.range) || pcl_isinf(point2.range)) 00830 return std::numeric_limits<float>::infinity (); 00831 return squaredEuclideanDistance(point1, point2); 00832 } 00833 00835 float 00836 RangeImage::getAverageEuclideanDistance(int x, int y, int offset_x, int offset_y, int max_steps) const 00837 { 00838 float average_pixel_distance = 0.0f; 00839 float weight=0.0f; 00840 for (int i=0; i<max_steps; ++i) 00841 { 00842 int x1=x+i*offset_x, y1=y+i*offset_y; 00843 int x2=x+(i+1)*offset_x, y2=y+(i+1)*offset_y; 00844 float pixel_distance = getEuclideanDistanceSquared(x1,y1,x2,y2); 00845 if (!pcl_isfinite(pixel_distance)) 00846 { 00847 //std::cout << x<<","<<y<<"->"<<x2<<","<<y2<<": "<<pixel_distance<<"\n"; 00848 if (i==0) 00849 return pixel_distance; 00850 else 00851 break; 00852 } 00853 //std::cout << x<<","<<y<<"->"<<x2<<","<<y2<<": "<<sqrtf(pixel_distance)<<"m\n"; 00854 weight += 1.0f; 00855 average_pixel_distance += sqrtf(pixel_distance); 00856 } 00857 average_pixel_distance /= weight; 00858 //std::cout << x<<","<<y<<","<<offset_x<<","<<offset_y<<" => "<<average_pixel_distance<<"\n"; 00859 return average_pixel_distance; 00860 } 00861 00863 float 00864 RangeImage::getImpactAngleBasedOnLocalNormal(int x, int y, int radius) const 00865 { 00866 if (!isValid(x,y)) 00867 return -std::numeric_limits<float>::infinity (); 00868 const PointWithRange& point = getPoint(x, y); 00869 int no_of_nearest_neighbors = (int) pow((double)(radius+1), 2.0); 00870 Eigen::Vector3f normal; 00871 if (!getNormalForClosestNeighbors(x, y, radius, point, no_of_nearest_neighbors, normal, 1)) 00872 return -std::numeric_limits<float>::infinity (); 00873 return deg2rad(90.0f) - acosf(normal.dot((getSensorPos()-getEigenVector3f(point)).normalized())); 00874 } 00875 00876 00878 bool 00879 RangeImage::getNormal(int x, int y, int radius, Eigen::Vector3f& normal, int step_size) const 00880 { 00881 VectorAverage3f vector_average; 00882 for (int y2=y-radius; y2<=y+radius; y2+=step_size) 00883 { 00884 for (int x2=x-radius; x2<=x+radius; x2+=step_size) 00885 { 00886 if (!isInImage(x2, y2)) 00887 continue; 00888 const PointWithRange& point = getPoint(x2, y2); 00889 if (!pcl_isfinite(point.range)) 00890 continue; 00891 vector_average.add(Eigen::Vector3f(point.x, point.y, point.z)); 00892 } 00893 } 00894 if (vector_average.getNoOfSamples() < 3) 00895 return false; 00896 Eigen::Vector3f eigen_values, eigen_vector2, eigen_vector3; 00897 vector_average.doPCA(eigen_values, normal, eigen_vector2, eigen_vector3); 00898 if (normal.dot((getSensorPos()-vector_average.getMean()).normalized()) < 0.0f) 00899 normal *= -1.0f; 00900 return true; 00901 } 00902 00904 float 00905 RangeImage::getNormalBasedAcutenessValue(int x, int y, int radius) const 00906 { 00907 float impact_angle = getImpactAngleBasedOnLocalNormal(x, y, radius); 00908 if (pcl_isinf(impact_angle)) 00909 return -std::numeric_limits<float>::infinity (); 00910 float ret = 1.0f - (float) (impact_angle/(0.5f*M_PI)); 00911 //std::cout << PVARAC(impact_angle)<<PVARN(ret); 00912 return ret; 00913 } 00914 00916 bool 00917 RangeImage::getNormalForClosestNeighbors(int x, int y, int radius, const PointWithRange& point, 00918 int no_of_nearest_neighbors, Eigen::Vector3f& normal, int step_size) const 00919 { 00920 return getNormalForClosestNeighbors(x, y, radius, Eigen::Vector3f(point.x, point.y, point.z), no_of_nearest_neighbors, normal, NULL, step_size); 00921 } 00922 00924 bool 00925 RangeImage::getNormalForClosestNeighbors(int x, int y, Eigen::Vector3f& normal, int radius) const 00926 { 00927 if (!isValid(x,y)) 00928 return false; 00929 int no_of_nearest_neighbors = (int) pow ((double)(radius+1), 2.0); 00930 return getNormalForClosestNeighbors(x, y, radius, getPoint(x,y).getVector3fMap(), no_of_nearest_neighbors, normal); 00931 } 00932 00933 namespace 00934 { // Anonymous namespace, so that this is only accessible in this file 00935 struct NeighborWithDistance 00936 { // local struct to help us with sorting 00937 float distance; 00938 const PointWithRange* neighbor; 00939 bool operator <(const NeighborWithDistance& other) const { return distance<other.distance;} 00940 }; 00941 } 00942 00944 bool 00945 RangeImage::getSurfaceInformation (int x, int y, int radius, const Eigen::Vector3f& point, int no_of_closest_neighbors, int step_size, 00946 float& max_closest_neighbor_distance_squared, 00947 Eigen::Vector3f& normal, Eigen::Vector3f& mean, Eigen::Vector3f& eigen_values, 00948 Eigen::Vector3f* normal_all_neighbors, Eigen::Vector3f* mean_all_neighbors, 00949 Eigen::Vector3f* eigen_values_all_neighbors) const 00950 { 00951 max_closest_neighbor_distance_squared=0.0f; 00952 normal.setZero(); mean.setZero(); eigen_values.setZero(); 00953 if (normal_all_neighbors!=NULL) 00954 normal_all_neighbors->setZero(); 00955 if (mean_all_neighbors!=NULL) 00956 mean_all_neighbors->setZero(); 00957 if (eigen_values_all_neighbors!=NULL) 00958 eigen_values_all_neighbors->setZero(); 00959 00960 int blocksize = (int) pow ((double)(2*radius+1), 2.0); 00961 00962 PointWithRange given_point; 00963 given_point.x=point[0]; given_point.y=point[1]; given_point.z=point[2]; 00964 00965 std::vector<NeighborWithDistance> ordered_neighbors (blocksize); 00966 int neighbor_counter = 0; 00967 for (int y2=y-radius; y2<=y+radius; y2+=step_size) 00968 { 00969 for (int x2=x-radius; x2<=x+radius; x2+=step_size) 00970 { 00971 if (!isValid(x2, y2)) 00972 continue; 00973 NeighborWithDistance& neighbor_with_distance = ordered_neighbors[neighbor_counter]; 00974 neighbor_with_distance.neighbor = &getPoint(x2, y2); 00975 neighbor_with_distance.distance = squaredEuclideanDistance(given_point, *neighbor_with_distance.neighbor); 00976 ++neighbor_counter; 00977 } 00978 } 00979 no_of_closest_neighbors = (std::min)(neighbor_counter, no_of_closest_neighbors); 00980 00981 std::sort (ordered_neighbors.begin (), ordered_neighbors.begin () + neighbor_counter); // Normal sort seems to be the fastest method (faster than partial_sort) 00982 //std::stable_sort(ordered_neighbors, ordered_neighbors+neighbor_counter); 00983 //std::partial_sort(ordered_neighbors, ordered_neighbors+no_of_closest_neighbors, ordered_neighbors+neighbor_counter); 00984 00985 max_closest_neighbor_distance_squared = ordered_neighbors[no_of_closest_neighbors-1].distance; 00986 //float max_distance_squared = max_closest_neighbor_distance_squared; 00987 float max_distance_squared = max_closest_neighbor_distance_squared*4.0f; // Double the allowed distance value 00988 //max_closest_neighbor_distance_squared = max_distance_squared; 00989 00990 VectorAverage3f vector_average; 00991 //for (int neighbor_idx=0; neighbor_idx<no_of_closest_neighbors; ++neighbor_idx) 00992 int neighbor_idx; 00993 for (neighbor_idx=0; neighbor_idx<neighbor_counter; ++neighbor_idx) 00994 { 00995 if (ordered_neighbors[neighbor_idx].distance > max_distance_squared) 00996 break; 00997 //std::cout << ordered_neighbors[neighbor_idx].distance<<"\n"; 00998 vector_average.add(ordered_neighbors[neighbor_idx].neighbor->getVector3fMap()); 00999 } 01000 01001 if (vector_average.getNoOfSamples() < 3) 01002 return false; 01003 //std::cout << PVARN(vector_average.getNoOfSamples()); 01004 Eigen::Vector3f eigen_vector2, eigen_vector3; 01005 vector_average.doPCA(eigen_values, normal, eigen_vector2, eigen_vector3); 01006 Eigen::Vector3f viewing_direction = (getSensorPos()-point).normalized(); 01007 if (normal.dot(viewing_direction) < 0.0f) 01008 normal *= -1.0f; 01009 mean = vector_average.getMean(); 01010 01011 if (normal_all_neighbors==NULL) 01012 return true; 01013 01014 // Add remaining neighbors 01015 for (int neighbor_idx2=neighbor_idx; neighbor_idx2<neighbor_counter; ++neighbor_idx2) 01016 vector_average.add(ordered_neighbors[neighbor_idx2].neighbor->getVector3fMap()); 01017 01018 vector_average.doPCA(*eigen_values_all_neighbors, *normal_all_neighbors, eigen_vector2, eigen_vector3); 01019 //std::cout << PVARN(vector_average.getNoOfSamples())<<".\n"; 01020 if (normal_all_neighbors->dot(viewing_direction) < 0.0f) 01021 *normal_all_neighbors *= -1.0f; 01022 *mean_all_neighbors = vector_average.getMean(); 01023 01024 //std::cout << viewing_direction[0]<<","<<viewing_direction[1]<<","<<viewing_direction[2]<<"\n"; 01025 01026 return true; 01027 } 01028 01030 float 01031 RangeImage::getSquaredDistanceOfNthNeighbor(int x, int y, int radius, int n, int step_size) const 01032 { 01033 const PointWithRange& point = getPoint(x, y); 01034 if (!pcl_isfinite(point.range)) 01035 return -std::numeric_limits<float>::infinity (); 01036 01037 int blocksize = (int) pow ((double)(2*radius+1), 2.0); 01038 std::vector<float> neighbor_distances (blocksize); 01039 int neighbor_counter = 0; 01040 for (int y2=y-radius; y2<=y+radius; y2+=step_size) 01041 { 01042 for (int x2=x-radius; x2<=x+radius; x2+=step_size) 01043 { 01044 if (!isValid(x2, y2) || (x2==x&&y2==y)) 01045 continue; 01046 const PointWithRange& neighbor = getPointNoCheck(x2,y2); 01047 float& neighbor_distance = neighbor_distances[neighbor_counter++]; 01048 neighbor_distance = squaredEuclideanDistance(point, neighbor); 01049 } 01050 } 01051 std::sort (neighbor_distances.begin (), neighbor_distances.begin () + neighbor_counter); // Normal sort seems to be 01052 // the fastest method (faster than partial_sort) 01053 n = (std::min)(neighbor_counter, n); 01054 return neighbor_distances[n-1]; 01055 } 01056 01057 01059 bool 01060 RangeImage::getNormalForClosestNeighbors(int x, int y, int radius, const Eigen::Vector3f& point, int no_of_nearest_neighbors, 01061 Eigen::Vector3f& normal, Eigen::Vector3f* point_on_plane, int step_size) const 01062 { 01063 Eigen::Vector3f mean, eigen_values; 01064 float used_squared_max_distance; 01065 bool ret = getSurfaceInformation(x, y, radius, point, no_of_nearest_neighbors, step_size, used_squared_max_distance, 01066 normal, mean, eigen_values); 01067 01068 if (ret) 01069 { 01070 if (point_on_plane != NULL) 01071 *point_on_plane = (normal.dot(mean) - normal.dot(point))*normal + point; 01072 } 01073 return ret; 01074 } 01075 01076 01078 float 01079 RangeImage::getCurvature(int x, int y, int radius, int step_size) const 01080 { 01081 VectorAverage3f vector_average; 01082 for (int y2=y-radius; y2<=y+radius; y2+=step_size) 01083 { 01084 for (int x2=x-radius; x2<=x+radius; x2+=step_size) 01085 { 01086 if (!isInImage(x2, y2)) 01087 continue; 01088 const PointWithRange& point = getPoint(x2, y2); 01089 if (!pcl_isfinite(point.range)) 01090 continue; 01091 vector_average.add(Eigen::Vector3f(point.x, point.y, point.z)); 01092 } 01093 } 01094 if (vector_average.getNoOfSamples() < 3) 01095 return false; 01096 Eigen::Vector3f eigen_values; 01097 vector_average.doPCA(eigen_values); 01098 return eigen_values[0]/eigen_values.sum(); 01099 } 01100 01101 01103 template <typename PointCloudTypeWithViewpoints> Eigen::Vector3f 01104 RangeImage::getAverageViewPoint(const PointCloudTypeWithViewpoints& point_cloud) 01105 { 01106 Eigen::Vector3f average_viewpoint(0,0,0); 01107 int point_counter = 0; 01108 for (unsigned int point_idx=0; point_idx<point_cloud.points.size(); ++point_idx) 01109 { 01110 const typename PointCloudTypeWithViewpoints::PointType& point = point_cloud.points[point_idx]; 01111 if (!pcl_isfinite(point.vp_x) || !pcl_isfinite(point.vp_y) || !pcl_isfinite(point.vp_z)) 01112 continue; 01113 average_viewpoint[0] += point.vp_x; 01114 average_viewpoint[1] += point.vp_y; 01115 average_viewpoint[2] += point.vp_z; 01116 ++point_counter; 01117 } 01118 average_viewpoint /= point_counter; 01119 01120 return average_viewpoint; 01121 } 01122 01124 bool 01125 RangeImage::getViewingDirection(int x, int y, Eigen::Vector3f& viewing_direction) const 01126 { 01127 if (!isValid(x, y)) 01128 return false; 01129 viewing_direction = (getPoint(x,y).getVector3fMap()-getSensorPos()).normalized(); 01130 return true; 01131 } 01132 01134 void 01135 RangeImage::getViewingDirection(const Eigen::Vector3f& point, Eigen::Vector3f& viewing_direction) const 01136 { 01137 viewing_direction = (point-getSensorPos()).normalized(); 01138 } 01139 01141 Eigen::Affine3f 01142 RangeImage::getTransformationToViewerCoordinateFrame(const Eigen::Vector3f& point) const 01143 { 01144 Eigen::Affine3f transformation; 01145 getTransformationToViewerCoordinateFrame(point, transformation); 01146 return transformation; 01147 } 01148 01150 void 01151 RangeImage::getTransformationToViewerCoordinateFrame(const Eigen::Vector3f& point, Eigen::Affine3f& transformation) const 01152 { 01153 Eigen::Vector3f viewing_direction = (point-getSensorPos()).normalized(); 01154 getTransformationFromTwoUnitVectorsAndOrigin(Eigen::Vector3f(0.0f, -1.0f, 0.0f), viewing_direction, point, transformation); 01155 } 01156 01158 void 01159 RangeImage::getRotationToViewerCoordinateFrame(const Eigen::Vector3f& point, Eigen::Affine3f& transformation) const 01160 { 01161 Eigen::Vector3f viewing_direction = (point-getSensorPos()).normalized(); 01162 getTransformationFromTwoUnitVectors(Eigen::Vector3f(0.0f, -1.0f, 0.0f), viewing_direction, transformation); 01163 } 01164 01166 inline void 01167 RangeImage::setAngularResolution (float angular_resolution) 01168 { 01169 angular_resolution_ = angular_resolution; 01170 angular_resolution_reciprocal_ = 1.0f / angular_resolution_; 01171 } 01172 01173 inline void 01174 RangeImage::setTransformationToRangeImageSystem (const Eigen::Affine3f& to_range_image_system) 01175 { 01176 to_range_image_system_ = to_range_image_system; 01177 to_world_system_ = to_range_image_system_.inverse(); 01178 } 01179 01180 } // namespace end
1.8.0