Point Cloud Library (PCL)  1.5.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
range_image.hpp
Go to the documentation of this file.
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