Point Cloud Library (PCL)  1.4.0
 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  *  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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines