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