fitting_surface_im.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2012-, Open Perception, 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 the copyright holder(s) 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  */
00037 
00038 #include <pcl/surface/on_nurbs/fitting_surface_im.h>
00039 #include <stdexcept>
00040 
00041 using namespace pcl;
00042 using namespace on_nurbs;
00043 
00044 pcl::PointXYZRGB
00045 FittingSurfaceIM::computeMean () const
00046 {
00047   pcl::PointXYZRGB u;
00048   u.x = 0.0;
00049   u.y = 0.0;
00050   u.z = 0.0;
00051 
00052   double ds = 1.0 / double (m_indices.size ());
00053 
00054   const pcl::PointCloud<pcl::PointXYZRGB> &cloud_ref = *m_cloud;
00055   for (size_t idx = 0; idx < m_indices.size (); idx++)
00056   {
00057     int i = m_indices[idx] % cloud_ref.width;
00058     int j = m_indices[idx] / cloud_ref.width;
00059 
00060     const pcl::PointXYZRGB &point = cloud_ref (i, j);
00061     if (pcl_isnan (point.x) || pcl_isnan (point.y) || pcl_isnan (point.z))
00062       continue;
00063 
00064     u.x += point.x * float (ds);
00065     u.y += point.y * float (ds);
00066     u.z += point.z * float (ds);
00067   }
00068 
00069   return u;
00070 }
00071 
00072 Eigen::Vector4d
00073 FittingSurfaceIM::computeIndexBoundingBox (pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud,
00074                                            const std::vector<int> &indices)
00075 {
00076   Eigen::Vector4d bb = Eigen::Vector4d (DBL_MAX, 0, DBL_MAX, 0);
00077   const pcl::PointCloud<pcl::PointXYZRGB> &cloud_ref = *cloud;
00078 
00079   for (size_t idx = 0; idx < indices.size (); idx++)
00080   {
00081     int i = indices[idx] % cloud_ref.width;
00082     int j = indices[idx] / cloud_ref.width;
00083 
00084     const pcl::PointXYZRGB &point = cloud_ref (i, j);
00085     if (pcl_isnan (point.x) || pcl_isnan (point.y) || pcl_isnan (point.z))
00086       continue;
00087 
00088     if (i < bb (0))
00089       bb (0) = i;
00090     if (i > bb (1))
00091       bb (1) = i;
00092     if (j < bb (2))
00093       bb (2) = j;
00094     if (j > bb (3))
00095       bb (3) = j;
00096   }
00097   return bb;
00098 }
00099 
00100 void
00101 FittingSurfaceIM::setInputCloud (pcl::PointCloud<pcl::PointXYZRGB>::Ptr _cloud)
00102 {
00103   m_cloud = _cloud;
00104 }
00105 
00106 void
00107 FittingSurfaceIM::setIndices (std::vector<int> &_indices)
00108 {
00109   m_indices = _indices;
00110 }
00111 
00112 void
00113 FittingSurfaceIM::setCamera (const Eigen::Matrix3d &i)
00114 {
00115   m_intrinsic = i;
00116 }
00117 
00118 void
00119 FittingSurfaceIM::setCamera (const Eigen::Matrix3f &i)
00120 {
00121   printf("[FittingSurfaceIM::setCamera] Warning, this function is not tested!\n");
00122   m_intrinsic << i (0, 0), i (0, 1), i (0, 2), i (1, 0), i (1, 1), i (1, 2), i (2, 0), i (2, 1), i (2, 2);
00123 }
00124 
00125 std::vector<double>
00126 FittingSurfaceIM::getElementVector (const ON_NurbsSurface &nurbs, int dim) // !
00127 {
00128   std::vector<double> result;
00129 
00130   int idx_min = 0;
00131   int idx_max = nurbs.KnotCount (dim) - 1;
00132   if (nurbs.IsClosed (dim))
00133   {
00134     idx_min = nurbs.Order (dim) - 2;
00135     idx_max = nurbs.KnotCount (dim) - nurbs.Order (dim) + 1;
00136   }
00137 
00138   const double* knots = nurbs.Knot (dim);
00139 
00140   result.push_back (knots[idx_min]);
00141 
00142   //for(int E=(m_nurbs.Order(0)-2); E<(m_nurbs.KnotCount(0)-m_nurbs.Order(0)+2); E++) {
00143   for (int E = idx_min + 1; E <= idx_max; E++)
00144   {
00145 
00146     if (knots[E] != knots[E - 1]) // do not count double knots
00147       result.push_back (knots[E]);
00148 
00149   }
00150 
00151   return result;
00152 }
00153 
00154 void
00155 FittingSurfaceIM::refine ()
00156 {
00157   {
00158     int dim = 0;
00159     std::vector<double> elements = getElementVector (m_nurbs, dim);
00160     for (unsigned i = 0; i < elements.size () - 1; i++)
00161     {
00162       double xi = elements[i] + 0.5 * (elements[i + 1] - elements[i]);
00163       m_nurbs.InsertKnot (dim, xi, 1);
00164     }
00165   }
00166   {
00167     int dim = 1;
00168     std::vector<double> elements = getElementVector (m_nurbs, dim);
00169     for (unsigned i = 0; i < elements.size () - 1; i++)
00170     {
00171       double xi = elements[i] + 0.5 * (elements[i + 1] - elements[i]);
00172       m_nurbs.InsertKnot (dim, xi, 1);
00173     }
00174   }
00175 
00176   Eigen::Vector2d bbx (m_nurbs.Knot (0, 0), m_nurbs.Knot (0, m_nurbs.KnotCount (0) - 1));
00177   Eigen::Vector2d bby (m_nurbs.Knot (1, 0), m_nurbs.Knot (1, m_nurbs.KnotCount (1) - 1));
00178 
00179   int dx = int (bbx (1) - bbx (0));
00180   int dy = int (bby (1) - bby (0));
00181   double ddx = double (dx) / (m_nurbs.CVCount (0) - 1);
00182   double ddy = double (dy) / (m_nurbs.CVCount (1) - 1);
00183 
00184   m_cps_px.clear ();
00185   for (int i = 0; i < m_nurbs.CVCount (0); i++)
00186   {
00187     for (int j = 0; j < m_nurbs.CVCount (1); j++)
00188     {
00189       int px = int (bbx (0) + ddx * i);
00190       int py = int (bby (0) + ddy * j);
00191       m_cps_px.push_back (Eigen::Vector2i (px, py));
00192     }
00193   }
00194 }
00195 
00196 //void
00197 //FittingSurfaceIM::compute (int nurbs_order, double damp)
00198 //{
00199 //  initSurface (nurbs_order);
00200 //  assemble ();
00201 //  solve (damp);
00202 //}
00203 
00204 void
00205 FittingSurfaceIM::initSurface (int order, const Eigen::Vector4d &bb)
00206 {
00207   m_cps_px.clear ();
00208 
00209   // bounding box in parameter space
00210   m_bb = bb;
00211 
00212   pcl::PointXYZRGB pt = computeMean ();
00213 
00214   double dx = bb (1) - bb (0);
00215   double dy = bb (3) - bb (2);
00216   double ddx = dx / (order - 1);
00217   double ddy = dy / (order - 1);
00218 
00219   //  printf ("cloud: %d %d\n", m_cloud->width, m_cloud->height);
00220   //  printf ("bb: %d %d %d %d\n", m_bb (0), m_bb (1), m_bb (2), m_bb (3));
00221 
00222   m_nurbs = ON_NurbsSurface (3, false, order, order, order, order);
00223   m_nurbs.MakeClampedUniformKnotVector (0, dx);
00224   m_nurbs.MakeClampedUniformKnotVector (1, dy);
00225 
00226   for (int i = 0; i < m_nurbs.KnotCount (0); i++)
00227   {
00228     double k = m_nurbs.Knot (0, i);
00229     m_nurbs.SetKnot (0, i, k + m_bb (0));
00230   }
00231 
00232   for (int i = 0; i < m_nurbs.KnotCount (1); i++)
00233   {
00234     double k = m_nurbs.Knot (1, i);
00235     m_nurbs.SetKnot (1, i, k + m_bb (2));
00236   }
00237 
00238   for (int i = 0; i < m_nurbs.Order (0); i++)
00239   {
00240     for (int j = 0; j < m_nurbs.Order (1); j++)
00241     {
00242       int px = int (m_bb (0) + ddx * i + 0.5);
00243       int py = int (m_bb (2) + ddy * j + 0.5);
00244 
00245       m_cps_px.push_back (Eigen::Vector2i (px, py));
00246 
00247       ON_3dPoint p;
00248       p.x = pt.z * (px - m_intrinsic (0, 2)) / m_intrinsic (0, 0);
00249       p.y = pt.z * (py - m_intrinsic (1, 2)) / m_intrinsic (1, 1);
00250       p.z = pt.z;
00251 
00252       m_nurbs.SetCV (i, j, p);
00253     }
00254   }
00255 
00256   //  ON_TextLog out;
00257   //  m_nurbs.Dump (out);
00258 }
00259 
00260 void
00261 FittingSurfaceIM::assemble (bool inverse_mapping)
00262 {
00263   int nInt = int (m_indices.size ());
00264   int nCageReg = (m_nurbs.m_cv_count[0] - 2) * (m_nurbs.m_cv_count[1] - 2);
00265   int nCageRegBnd = 2 * (m_nurbs.m_cv_count[0] - 1) + 2 * (m_nurbs.m_cv_count[1] - 1);
00266 
00267   int rows = nInt + nCageReg + nCageRegBnd;
00268   int ncps = m_nurbs.CVCount ();
00269 
00270   m_solver.assign (rows, ncps, 1);
00271 
00272   unsigned row (0);
00273 
00274   // assemble data points
00275   const pcl::PointCloud<pcl::PointXYZRGB> &cloud_ref = *m_cloud;
00276   for (size_t i = 0; i < m_indices.size (); i++)
00277   {
00278     int px = m_indices[i] % cloud_ref.width;
00279     int py = m_indices[i] / cloud_ref.width;
00280 
00281     const pcl::PointXYZRGB &pt = cloud_ref.at (m_indices[i]);
00282     Eigen::Vector2i params (px, py);
00283 
00284     if (pcl_isnan (pt.z) || pt.z == 0.0)
00285       throw std::runtime_error ("[FittingSurfaceIM::assemble] Error, not a number (pt.z)");
00286 
00287     if (inverse_mapping)
00288     {
00289       Eigen::Vector3d point (pt.x, pt.y, pt.z);
00290       double error;
00291       Eigen::Vector3d p, tu, tv;
00292       Eigen::Vector2d params1 (params (0), params (1));
00293       params1 = inverseMapping (m_nurbs, point, params1, error, p, tu, tv, 200, 1e-6, true);
00294       params (0) = int (params1 (0));
00295       params (1) = int (params1 (1));
00296     }
00297 
00298     addPointConstraint (params, pt.z, 1.0, row);
00299 
00300     //    double point[3];
00301     //    m_nurbs.Evaluate (params (0), params (1), 0, 3, point);
00302     //    Eigen::Vector3d p (point[0], point[1], point[2]);
00303     //
00304     //    if (!(params (0) % 20) && !(params (1) % 20))
00305     //    {
00306     //      m_viewer->AddLine3D (p (0), p (1), p (2), pt.x, pt.y, pt.z, 0, 255, 0, 1.0);
00307     //    }
00308   }
00309 
00310   // cage regularisation
00311   double smooth (0.1);
00312   if (nCageReg > 0)
00313     addCageInteriorRegularisation (smooth, row);
00314 
00315   if (nCageRegBnd > 0)
00316   {
00317     addCageBoundaryRegularisation (smooth, NORTH, row);
00318     addCageBoundaryRegularisation (smooth, SOUTH, row);
00319     addCageBoundaryRegularisation (smooth, WEST, row);
00320     addCageBoundaryRegularisation (smooth, EAST, row);
00321     addCageCornerRegularisation (smooth * 2.0, row);
00322   }
00323 
00324   //  printf ("\n\n");
00325   //  m_solver.printK ();
00326   //  printf ("\n\n");
00327   //  m_solver.printF ();
00328   //  printf ("\n\n");
00329 }
00330 
00331 void
00332 FittingSurfaceIM::addPointConstraint (const Eigen::Vector2i &params, double z, double weight, unsigned &row)
00333 {
00334   double *N0 = new double[m_nurbs.Order (0) * m_nurbs.Order (0)];
00335   double *N1 = new double[m_nurbs.Order (1) * m_nurbs.Order (1)];
00336 
00337   int E = ON_NurbsSpanIndex (m_nurbs.m_order[0], m_nurbs.m_cv_count[0], m_nurbs.m_knot[0], params (0), 0, 0);
00338   int F = ON_NurbsSpanIndex (m_nurbs.m_order[1], m_nurbs.m_cv_count[1], m_nurbs.m_knot[1], params (1), 0, 0);
00339 
00340   ON_EvaluateNurbsBasis (m_nurbs.Order (0), m_nurbs.m_knot[0] + E, params (0), N0);
00341   ON_EvaluateNurbsBasis (m_nurbs.Order (1), m_nurbs.m_knot[1] + F, params (1), N1);
00342 
00343   m_solver.f (row, 0, z * weight);
00344 
00345   for (int i = 0; i < m_nurbs.Order (0); i++)
00346   {
00347 
00348     for (int j = 0; j < m_nurbs.Order (1); j++)
00349     {
00350 
00351       m_solver.K (row, lrc2gl (E, F, i, j), weight * N0[i] * N1[j]);
00352 
00353     } // j
00354 
00355   } // i
00356 
00357   row++;
00358 
00359   delete [] N1;
00360   delete [] N0;
00361 }
00362 
00363 void
00364 FittingSurfaceIM::addCageInteriorRegularisation (double weight, unsigned &row)
00365 {
00366   for (int i = 1; i < (m_nurbs.m_cv_count[0] - 1); i++)
00367   {
00368     for (int j = 1; j < (m_nurbs.m_cv_count[1] - 1); j++)
00369     {
00370 
00371       m_solver.f (row, 0, 0.0);
00372 
00373       m_solver.K (row, grc2gl (i + 0, j + 0), -4.0 * weight);
00374       m_solver.K (row, grc2gl (i + 0, j - 1), 1.0 * weight);
00375       m_solver.K (row, grc2gl (i + 0, j + 1), 1.0 * weight);
00376       m_solver.K (row, grc2gl (i - 1, j + 0), 1.0 * weight);
00377       m_solver.K (row, grc2gl (i + 1, j + 0), 1.0 * weight);
00378 
00379       row++;
00380     }
00381   }
00382 }
00383 
00384 void
00385 FittingSurfaceIM::addCageBoundaryRegularisation (double weight, int side, unsigned &row)
00386 {
00387   int i = 0;
00388   int j = 0;
00389 
00390   switch (side)
00391   {
00392     case SOUTH:
00393       j = m_nurbs.m_cv_count[1] - 1;
00394     case NORTH:
00395       for (i = 1; i < (m_nurbs.m_cv_count[0] - 1); i++)
00396       {
00397 
00398         m_solver.f (row, 0, 0.0);
00399 
00400         m_solver.K (row, grc2gl (i + 0, j), -2.0 * weight);
00401         m_solver.K (row, grc2gl (i - 1, j), 1.0 * weight);
00402         m_solver.K (row, grc2gl (i + 1, j), 1.0 * weight);
00403 
00404         row++;
00405       }
00406       break;
00407 
00408     case EAST:
00409       i = m_nurbs.m_cv_count[0] - 1;
00410     case WEST:
00411       for (j = 1; j < (m_nurbs.m_cv_count[1] - 1); j++)
00412       {
00413 
00414         m_solver.f (row, 0, 0.0);
00415 
00416         m_solver.K (row, grc2gl (i, j + 0), -2.0 * weight);
00417         m_solver.K (row, grc2gl (i, j - 1), 1.0 * weight);
00418         m_solver.K (row, grc2gl (i, j + 1), 1.0 * weight);
00419 
00420         row++;
00421       }
00422       break;
00423   }
00424 }
00425 
00426 void
00427 FittingSurfaceIM::addCageCornerRegularisation (double weight, unsigned &row)
00428 {
00429   { // NORTH-WEST
00430     int i = 0;
00431     int j = 0;
00432 
00433     m_solver.f (row, 0, 0.0);
00434 
00435     m_solver.K (row, grc2gl (i + 0, j + 0), -2.0 * weight);
00436     m_solver.K (row, grc2gl (i + 1, j + 0), 1.0 * weight);
00437     m_solver.K (row, grc2gl (i + 0, j + 1), 1.0 * weight);
00438 
00439     row++;
00440   }
00441 
00442   { // NORTH-EAST
00443     int i = m_nurbs.m_cv_count[0] - 1;
00444     int j = 0;
00445 
00446     m_solver.f (row, 0, 0.0);
00447 
00448     m_solver.K (row, grc2gl (i + 0, j + 0), -2.0 * weight);
00449     m_solver.K (row, grc2gl (i - 1, j + 0), 1.0 * weight);
00450     m_solver.K (row, grc2gl (i + 0, j + 1), 1.0 * weight);
00451 
00452     row++;
00453   }
00454 
00455   { // SOUTH-EAST
00456     int i = m_nurbs.m_cv_count[0] - 1;
00457     int j = m_nurbs.m_cv_count[1] - 1;
00458 
00459     m_solver.f (row, 0, 0.0);
00460 
00461     m_solver.K (row, grc2gl (i + 0, j + 0), -2.0 * weight);
00462     m_solver.K (row, grc2gl (i - 1, j + 0), 1.0 * weight);
00463     m_solver.K (row, grc2gl (i + 0, j - 1), 1.0 * weight);
00464 
00465     row++;
00466   }
00467 
00468   { // SOUTH-WEST
00469     int i = 0;
00470     int j = m_nurbs.m_cv_count[1] - 1;
00471 
00472     m_solver.f (row, 0, 0.0);
00473 
00474     m_solver.K (row, grc2gl (i + 0, j + 0), -2.0 * weight);
00475     m_solver.K (row, grc2gl (i + 1, j + 0), 1.0 * weight);
00476     m_solver.K (row, grc2gl (i + 0, j - 1), 1.0 * weight);
00477 
00478     row++;
00479   }
00480 
00481 }
00482 
00483 void
00484 FittingSurfaceIM::solve (double damp)
00485 {
00486   if (m_solver.solve ())
00487     updateSurf (damp);
00488 }
00489 
00490 void
00491 FittingSurfaceIM::updateSurf (double damp)
00492 {
00493   int ncp = m_nurbs.CVCount ();
00494 
00495   for (int A = 0; A < ncp; A++)
00496   {
00497 
00498     int I = gl2gr (A);
00499     int J = gl2gc (A);
00500 
00501     ON_3dPoint cp_prev;
00502     m_nurbs.GetCV (I, J, cp_prev);
00503 
00504     ON_3dPoint cp;
00505     cp.z = cp_prev.z + damp * (m_solver.x (A, 0) - cp_prev.z);
00506     cp.x = cp.z * (m_cps_px[A] (0) - m_intrinsic (0, 2)) / m_intrinsic (0, 0);
00507     cp.y = cp.z * (m_cps_px[A] (1) - m_intrinsic (1, 2)) / m_intrinsic (1, 1);
00508 
00509     m_nurbs.SetCV (I, J, cp);
00510 
00511   }
00512 
00513 }
00514 
00515 Eigen::Vector2d
00516 FittingSurfaceIM::findClosestElementMidPoint (const ON_NurbsSurface &nurbs, const Eigen::Vector3d &pt)
00517 {
00518   Eigen::Vector2d hint;
00519   Eigen::Vector3d r;
00520   std::vector<double> elementsU = getElementVector (nurbs, 0);
00521   std::vector<double> elementsV = getElementVector (nurbs, 1);
00522 
00523   double d_shortest (DBL_MAX);
00524   for (unsigned i = 0; i < elementsU.size () - 1; i++)
00525   {
00526     for (unsigned j = 0; j < elementsV.size () - 1; j++)
00527     {
00528       double points[3];
00529       double d;
00530 
00531       double xi = elementsU[i] + 0.5 * (elementsU[i + 1] - elementsU[i]);
00532       double eta = elementsV[j] + 0.5 * (elementsV[j + 1] - elementsV[j]);
00533 
00534       nurbs.Evaluate (xi, eta, 0, 3, points);
00535       r (0) = points[0] - pt (0);
00536       r (1) = points[1] - pt (1);
00537       r (2) = points[2] - pt (2);
00538 
00539       d = r.squaredNorm ();
00540 
00541       if ((i == 0 && j == 0) || d < d_shortest)
00542       {
00543         d_shortest = d;
00544         hint (0) = xi;
00545         hint (1) = eta;
00546       }
00547     }
00548   }
00549 
00550   return hint;
00551 }
00552 
00553 Eigen::Vector2d
00554 FittingSurfaceIM::inverseMapping (const ON_NurbsSurface &nurbs, const Eigen::Vector3d &pt, const Eigen::Vector2d &hint,
00555                                   double &error, Eigen::Vector3d &p, Eigen::Vector3d &tu, Eigen::Vector3d &tv,
00556                                   int maxSteps, double accuracy, bool quiet)
00557 {
00558 
00559   double pointAndTangents[9];
00560 
00561   Eigen::Vector2d current, delta;
00562   Eigen::Matrix2d A;
00563   Eigen::Vector2d b;
00564   Eigen::Vector3d r;
00565   std::vector<double> elementsU = getElementVector (nurbs, 0);
00566   std::vector<double> elementsV = getElementVector (nurbs, 1);
00567   double minU = elementsU[0];
00568   double minV = elementsV[0];
00569   double maxU = elementsU[elementsU.size () - 1];
00570   double maxV = elementsV[elementsV.size () - 1];
00571 
00572   current = hint;
00573 
00574   for (int k = 0; k < maxSteps; k++)
00575   {
00576 
00577     nurbs.Evaluate (current (0), current (1), 1, 3, pointAndTangents);
00578     p (0) = pointAndTangents[0];
00579     p (1) = pointAndTangents[1];
00580     p (2) = pointAndTangents[2];
00581     tu (0) = pointAndTangents[3];
00582     tu (1) = pointAndTangents[4];
00583     tu (2) = pointAndTangents[5];
00584     tv (0) = pointAndTangents[6];
00585     tv (1) = pointAndTangents[7];
00586     tv (2) = pointAndTangents[8];
00587 
00588     r = p - pt;
00589 
00590     b (0) = -r.dot (tu);
00591     b (1) = -r.dot (tv);
00592 
00593     A (0, 0) = tu.dot (tu);
00594     A (0, 1) = tu.dot (tv);
00595     A (1, 0) = A (0, 1);
00596     A (1, 1) = tv.dot (tv);
00597 
00598     delta = A.ldlt ().solve (b);
00599 
00600     if (delta.norm () < accuracy)
00601     {
00602 
00603       error = r.norm ();
00604       return current;
00605 
00606     }
00607     else
00608     {
00609       current = current + delta;
00610 
00611       if (current (0) < minU)
00612         current (0) = minU;
00613       else if (current (0) > maxU)
00614         current (0) = maxU;
00615 
00616       if (current (1) < minV)
00617         current (1) = minV;
00618       else if (current (1) > maxV)
00619         current (1) = maxV;
00620 
00621     }
00622 
00623   }
00624 
00625   error = r.norm ();
00626 
00627   if (!quiet)
00628   {
00629     printf ("[FittingSurface::inverseMapping] Warning: Method did not converge (%e %d)\n", accuracy, maxSteps);
00630     printf ("  %f %f ... %f %f\n", hint (0), hint (1), current (0), current (1));
00631   }
00632 
00633   return current;
00634 
00635 }


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:24:09