17 #ifndef ARUCO_MM__LevMarq_H
18 #define ARUCO_MM__LevMarq_H
20 #include <Eigen/Cholesky>
45 typedef Eigen::Matrix<T, Eigen::Dynamic, 1>
eVector;
47 typedef std::function<void(
const eVector &, Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &)>
F_z_J;
61 LevMarq(
int maxIters,
double minError,
double min_step_error_diff = 0,
double tau = 1,
62 double der_epsilon = 1e-3);
76 void setParams(
int maxIters,
double minError,
double min_step_error_diff = 0,
77 double tau = 1,
double der_epsilon = 1e-3);
157 Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>
I,
J;
165 template <
typename T>
169 _minErrorAllowed = 0;
174 _min_step_error_diff = 0;
188 template <
typename T>
192 _maxIters = maxIters;
193 _minErrorAllowed = minError;
194 _der_epsilon = der_epsilon;
198 _min_step_error_diff = min_step_error_diff;
213 template <
typename T>
215 double tau,
double der_epsilon)
217 _maxIters = maxIters;
218 _minErrorAllowed = minError;
219 _der_epsilon = der_epsilon;
221 _min_step_error_diff = min_step_error_diff;
225 template <
typename T>
227 Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &j,
F_z_x f_z_x)
229 for (
int i = 0; i < z.rows(); i++)
232 zp(i) += _der_epsilon;
233 zm(i) -= _der_epsilon;
237 eVector dif = (xp - xm) / (2.
f * _der_epsilon);
238 j.middleCols(i, 1) = dif;
242 template <
typename T>
245 return solve(z, f_z_x,
247 std::placeholders::_2, f_z_x));
249 template <
typename T>
253 std::placeholders::_2, f_z_x));
256 template <
typename T>
260 I.resize(z.rows(), z.rows());
263 minErr = currErr = prevErr = x64.cwiseProduct(x64).sum();
264 J.resize(x64.rows(), z.rows());
269 #define splm_get_time(a, b) \
270 std::chrono::duration_cast<std::chrono::duration<double>>(a - b).count()
273 template <
typename T>
277 Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> Jt = J.transpose();
278 Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> JtJ = (Jt * J);
284 for (
int j = 1; j < JtJ.cols(); j++)
285 if (JtJ(j, j) > JtJ(max, max))
287 mu = JtJ(max, max) * _tau;
290 double gain = 0, prev_mu = 0;
292 bool isStepAccepted =
false;
297 for (
int j = 0; j < JtJ.cols(); j++)
298 JtJ(j, j) += mu - prev_mu;
300 eVector delta = JtJ.ldlt().solve(B);
301 eVector estimated_z = curr_z + delta;
303 f_z_x(estimated_z, x64);
304 auto err = x64.cwiseProduct(x64).sum();
305 auto L = 0.5 * delta.transpose() * ((mu * delta) - B);
306 gain = (err - prevErr) / L(0, 0);
310 mu = mu * std::max(
double(0.33), 1. - pow(2 * gain - 1, 3));
313 curr_z = estimated_z;
314 isStepAccepted =
true;
322 }
while (gain <= 0 && ntries++ < 5);
325 std::cout << std::setprecision(5) <<
"Curr Error=" << currErr
326 <<
" AErr(prev-curr)=" << prevErr - currErr <<
" gain=" << gain
327 <<
" dumping factor=" << mu << std::endl;
329 if (currErr < prevErr)
330 std::swap(currErr, prevErr);
332 return isStepAccepted;
336 template <
typename T>
342 template <
typename T>
353 _step_callback(curr_z);
354 }
while (!_stopFunction(curr_z));
360 for (
int i = 0; i < _maxIters && !mustExit; i++)
363 std::cerr <<
"iteration " << i <<
"/" << _maxIters <<
" ";
364 bool isStepAccepted = step(f_z_x, f_J);
366 if (currErr < _minErrorAllowed)
368 if (fabs(prevErr - currErr) <= _min_step_error_diff || !isStepAccepted)
371 if (currErr < prevErr)
375 _step_callback(curr_z);