8#ifndef META_OCEAN_GEOMETRY_NON_LINEAR_OPTIMIZATION_H
9#define META_OCEAN_GEOMETRY_NON_LINEAR_OPTIMIZATION_H
44 template <
typename TFirst,
typename TSecond>
52 using Element = std::pair<Index32, Vector2>;
98 inline void element(
const size_t groupIndex,
const size_t elementIndex, TFirst& first, TSecond& second)
const;
106 inline const TFirst&
firstElement(
const size_t groupIndex,
const size_t elementIndex)
const;
114 inline const TSecond&
secondElement(
const size_t groupIndex,
const size_t elementIndex)
const;
236 template <
typename TAccessor>
245 template <
typename TAccessor>
261 template <
typename TAccessor>
277 template <
typename TAccessor>
285 inline size_t addObjectPoint(Elements&& poseIdImagePointPairs);
299 inline bool hasSolver()
const;
334 inline Scalar determineError();
343 inline bool determineHessianAndErrorJacobian(
Matrix& hessian,
Matrix& jacobianError);
350 inline void applyCorrection(
const Matrix& deltas);
356 inline void acceptCorrection();
363 inline bool shouldStop();
369 inline bool hasSolver()
const;
378 inline bool solve(
const Matrix& hessian,
const Matrix& jacobianError,
Matrix& deltas)
const;
401 inline Scalar determineError();
409 inline bool determineParameters();
416 inline void applyCorrection(
const Matrix& deltas);
422 inline void acceptCorrection();
429 inline bool shouldStop();
465 template <
typename T>
466 static inline bool denseOptimization(T& provider,
const unsigned int iterations = 5u,
const Estimator::EstimatorType estimator = Estimator::ET_SQUARE,
Scalar lambda =
Scalar(0.001),
const Scalar lambdaFactor =
Scalar(5),
Scalar* initialError =
nullptr,
Scalar* finalError =
nullptr,
const Matrix* invertedCovariances =
nullptr,
Scalars* intermediateErrors =
nullptr);
482 template <
typename T, Estimator::EstimatorType tEstimator>
483 static bool denseOptimization(T& provider,
const unsigned int iterations = 5u,
Scalar lambda =
Scalar(0.001),
const Scalar lambdaFactor =
Scalar(5),
Scalar* initialError =
nullptr,
Scalar* finalError =
nullptr,
const Matrix* invertedCovariances =
nullptr,
Scalars* intermediateErrors =
nullptr);
499 template <
typename T>
500 static bool sparseOptimization(T& provider,
const unsigned int iterations = 5u,
const Estimator::EstimatorType estimator = Estimator::ET_SQUARE,
Scalar lambda =
Scalar(0.001),
const Scalar lambdaFactor =
Scalar(5),
Scalar* initialError =
nullptr,
Scalar* finalError =
nullptr,
const Matrix* invertedCovariances =
nullptr,
Scalars* intermediateErrors =
nullptr);
516 template <
typename T, Estimator::EstimatorType tEstimator>
517 static bool sparseOptimization(T& provider,
const unsigned int iterations = 5u,
Scalar lambda =
Scalar(0.001),
const Scalar lambdaFactor =
Scalar(5),
Scalar* initialError =
nullptr,
Scalar* finalError =
nullptr,
const Matrix* invertedCovariances =
nullptr,
Scalars* intermediateErrors =
nullptr);
532 template <
typename T>
533 static bool advancedDenseOptimization(T& advancedDenseProvider,
const unsigned int iterations,
Scalar lambda,
const Scalar lambdaFactor,
Scalar* initialError =
nullptr,
Scalar* finalError =
nullptr,
Scalars* intermediateErrors =
nullptr);
548 template <
typename T>
549 static bool advancedSparseOptimization(T& advancedSparseProvider,
const unsigned int iterations,
Scalar lambda,
const Scalar lambdaFactor,
Scalar* initialError =
nullptr,
Scalar* finalError =
nullptr,
Scalars* intermediateErrors =
nullptr);
561 template <Estimator::EstimatorType tEstimator>
575 template <Estimator::EstimatorType tEstimator,
size_t tDimension>
589 template <Estimator::EstimatorType tEstimator>
590 static Scalar sqrErrors2robustErrors_i(
const Scalars& sqrErrors,
const size_t modelParameters,
const size_t dimension,
Scalar* weightedErrors_i,
Scalar* weightVectors_i,
const Matrix* transposedInvertedCovariances_i);
615 template <
size_t tDimension>
632template <
typename TFirst,
typename TSecond>
638template <
typename TFirst,
typename TSecond>
640 elementGroups_(elementGroups)
645template <
typename TFirst,
typename TSecond>
647 elementGroups_(std::move(elementGroups))
652template <
typename TFirst,
typename TSecond>
654 elementGroups_(accessor.elementGroups_)
659template <
typename TFirst,
typename TSecond>
661 elementGroups_(std::move(accessor.elementGroups_))
666template <
typename TFirst,
typename TSecond>
669 return elementGroups_.size();
672template <
typename TFirst,
typename TSecond>
675 ocean_assert(groupIndex < groups());
677 return elementGroups_[groupIndex].size();
680template <
typename TFirst,
typename TSecond>
683 ocean_assert(groupIndex < groups());
684 ocean_assert(elementIndex < groupElements(groupIndex));
686 const Element& element = elementGroups_[groupIndex][elementIndex];
688 first = element.first;
689 second = element.second;
692template <
typename TFirst,
typename TSecond>
695 ocean_assert(groupIndex < groups());
696 ocean_assert(elementIndex < groupElements(groupIndex));
698 return elementGroups_[groupIndex][elementIndex].first;
701template <
typename TFirst,
typename TSecond>
704 ocean_assert(groupIndex < groups());
705 ocean_assert(elementIndex < groupElements(groupIndex));
707 return elementGroups_[groupIndex][elementIndex].second;
710template <
typename TFirst,
typename TSecond>
717template <
typename TFirst,
typename TSecond>
720 if (
this != &accessor)
722 elementGroups_ = std::move(accessor.elementGroups_);
769 ocean_assert(
false &&
"Must be implemented in a derived class!");
775 ocean_assert(
false &&
"Must be implemented in a derived class!");
786 ocean_assert(
false &&
"Must be implemented in a derived class!");
792 ocean_assert(
false &&
"Must be implemented in a derived class!");
798 ocean_assert(
false &&
"Must be implemented in a derived class!");
803 ocean_assert(
false &&
"Must be implemented in a derived class!");
808 ocean_assert(
false &&
"Must be implemented in a derived class!");
819 ocean_assert(
false &&
"Must be implemented in a derived class!");
830 ocean_assert(
false &&
"Must be implemented in a derived class!");
836 ocean_assert(
false &&
"Must be implemented in a derived class!");
842 ocean_assert(
false &&
"Must be implemented in a derived class!");
847 ocean_assert(
false &&
"Must be implemented in a derived class!");
852 ocean_assert(
false &&
"Must be implemented in a derived class!");
858 ocean_assert(
false &&
"Must be implemented in a derived class!");
862template <
typename TAccessor>
866 ocean_assert(imagePoints0.size() == imagePoints1.size());
868 for (
size_t n = 0; n < imagePoints0.size(); ++n)
878template <
typename TAccessor>
884 for (
size_t n = 0; n < imagePointGroups.size(); ++n)
887 ocean_assert(imagePoints.
size() >= 2);
890 poseIndexImagePoints.reserve(imagePoints.
size());
892 for (
size_t i = 0; i < imagePoints.
size(); ++i)
894 poseIndexImagePoints.emplace_back(
Index32(i), imagePoints[i]);
901template <
typename TAccessor>
906 ocean_assert(sequentialImagePointGroups.size() % numberObjectPoints == 0);
908 const unsigned int numberImagePoints = (
unsigned int)(sequentialImagePointGroups.size() / numberObjectPoints);
910 unsigned int index = 0u;
912 for (
size_t n = 0; n < numberObjectPoints; ++n)
915 poseIndexImagePoints.reserve(numberImagePoints);
917 for (
unsigned int i = 0u; i < numberImagePoints; ++i)
919 poseIndexImagePoints.emplace_back(
Index32(i), sequentialImagePointGroups[index++]);
926template <
typename TAccessor>
931 ocean_assert(imagePoints.size() % numberObjectPoints == 0);
933 ocean_assert(numberObjectPoints != 0);
934 const unsigned int numberImagePoints = (
unsigned int)(imagePoints.size() / numberObjectPoints);
936 unsigned int poseIndex = 0u;
937 unsigned int index = 0u;
939 for (
size_t n = 0; n < numberImagePoints; ++n)
941 for (
size_t i = 0; i < numberObjectPoints; ++i)
953 ocean_assert(!poseIdImagePointPairs.empty());
955 const size_t objectPointIndex = elementGroups_.size();
957 elementGroups_.emplace_back(std::move(poseIdImagePointPairs));
959 return objectPointIndex;
968 return denseOptimization<T, Estimator::ET_SQUARE>(provider, iterations, lambda, lambdaFactor, initialError, finalError, invertedCovariances, intermediateErrors);
971 return denseOptimization<T, Estimator::ET_LINEAR>(provider, iterations, lambda, lambdaFactor, initialError, finalError, invertedCovariances, intermediateErrors);
974 return denseOptimization<T, Estimator::ET_HUBER>(provider, iterations, lambda, lambdaFactor, initialError, finalError, invertedCovariances, intermediateErrors);
977 return denseOptimization<T, Estimator::ET_TUKEY>(provider, iterations, lambda, lambdaFactor, initialError, finalError, invertedCovariances, intermediateErrors);
980 return denseOptimization<T, Estimator::ET_CAUCHY>(provider, iterations, lambda, lambdaFactor, initialError, finalError, invertedCovariances, intermediateErrors);
983 ocean_assert(
false &&
"Invalid estimator!");
988template <
typename T, Estimator::EstimatorType tEstimator>
993 ocean_assert(lambda >=
Numeric::eps() && lambda <= maxLambda);
998 Matrix weightedErrorVector, swapWeightedErrorVector;
1000 Matrix weightVector, swapWeightVector;
1002 Matrix JTJ, jErrors, deltas;
1005 Matrix intermediateCovarianceJacobian;
1006 Matrix intermediateWeightedErrorVector;
1008 Scalar bestError = provider.template determineRobustError<tEstimator>(weightedErrorVector, weightVector, invertedCovariances);
1012 ocean_assert(
false &&
"The initial model was invalid and thus the optimization cannot be applied!");
1016 if (initialError !=
nullptr)
1018 *initialError = bestError;
1021 if (intermediateErrors !=
nullptr)
1023 ocean_assert(intermediateErrors->empty());
1024 intermediateErrors->push_back(bestError);
1027 bool oneValidIteration =
false;
1029 unsigned int i = 0u;
1030 while (i < iterations)
1032 provider.determineJacobian(jacobian);
1035 if (invertedCovariances)
1083 while (i < iterations)
1090 for (
unsigned int n = 0; n < JTJ.
columns(); ++n)
1092 JTJ(n, n) = JTJdiagonal(n, 0) * (
Scalar(1) + lambda);
1099 bool solved =
false;
1101 if (provider.hasSolver())
1103 solved = provider.
solve(JTJ, jErrors, deltas);
1112 oneValidIteration =
true;
1121 provider.applyCorrection(deltas);
1123 const Scalar iterationError = provider.template determineRobustError<tEstimator>(swapWeightedErrorVector, swapWeightVector, invertedCovariances);
1126 if (iterationError >= bestError)
1129 if (lambdaFactor >
Numeric::eps() && lambda > 0 && lambda <= maxLambda)
1131 lambda *= lambdaFactor;
1135 ocean_assert(oneValidIteration &&
"At this moment we should have at least one valid iteration!");
1145 bestError = iterationError;
1147 if (intermediateErrors !=
nullptr)
1149 intermediateErrors->push_back(bestError);
1152 provider.acceptCorrection();
1154 std::swap(swapWeightedErrorVector, weightedErrorVector);
1155 std::swap(swapWeightVector, weightVector);
1162 lambda /= lambdaFactor;
1169 else if (lambda >
Numeric::eps() && lambda <= maxLambda)
1171 lambda *= lambdaFactor;
1175 ocean_assert(oneValidIteration &&
"At this moment we should have at least one valid iteration!");
1185 *finalError = bestError;
1188 return oneValidIteration;
1191template <
typename T>
1197 return sparseOptimization<T, Estimator::ET_SQUARE>(provider, iterations, lambda, lambdaFactor, initialError, finalError, invertedCovariances, intermediateErrors);
1200 return sparseOptimization<T, Estimator::ET_LINEAR>(provider, iterations, lambda, lambdaFactor, initialError, finalError, invertedCovariances, intermediateErrors);
1203 return sparseOptimization<T, Estimator::ET_HUBER>(provider, iterations, lambda, lambdaFactor, initialError, finalError, invertedCovariances, intermediateErrors);
1206 return sparseOptimization<T, Estimator::ET_TUKEY>(provider, iterations, lambda, lambdaFactor, initialError, finalError, invertedCovariances, intermediateErrors);
1209 return sparseOptimization<T, Estimator::ET_CAUCHY>(provider, iterations, lambda, lambdaFactor, initialError, finalError, invertedCovariances, intermediateErrors);
1212 ocean_assert(
false &&
"Invalid estimator!");
1217template <
typename T, Estimator::EstimatorType tEstimator>
1222 ocean_assert(lambda >=
Numeric::eps() && lambda <= maxLambda);
1227 Matrix weightedErrorVector, swapWeightedErrorVector;
1229 Matrix weightVector, swapWeightVector;
1236 Scalar bestError = provider.template determineRobustError<tEstimator>(weightedErrorVector, weightVector, invertedCovariances);
1240 ocean_assert(
false &&
"The initial model was invalid and thus the optimization cannot be applied!");
1246 *initialError = bestError;
1249 if (intermediateErrors !=
nullptr)
1251 ocean_assert(intermediateErrors->empty());
1252 intermediateErrors->push_back(bestError);
1255 bool oneValidIteration =
false;
1257 unsigned int i = 0u;
1258 while (i < iterations)
1260 provider.determineJacobian(jacobian);
1263 if (invertedCovariances)
1275 JTJ = jacobianTransposed * (invertedCovarianceMatrix * jacobian);
1281 JTJ = jacobianTransposed * (invertedCovarianceMatrix * (
SparseMatrix(weightVector.
rows(), weightVector.
rows(), weightVector,
true) * jacobian));
1286 jErrors = jacobianTransposed * (invertedCovarianceMatrix * weightedErrorVector);
1301 JTJ = jacobianTransposed * jacobian;
1307 JTJ = jacobianTransposed *
SparseMatrix(weightVector.
rows(), weightVector.
rows(), weightVector,
true) * jacobian;
1312 jErrors = jacobianTransposed * weightedErrorVector;
1318 while (i < iterations)
1325 for (
unsigned int n = 0; n < JTJ.
columns(); ++n)
1327 if (JTJdiagonal(n, 0) !=
Scalar(0))
1329 ocean_assert(!JTJ.
isZero(n, n));
1330 JTJ(n, n) = JTJdiagonal(n, 0) * (
Scalar(1) + lambda);
1338 bool solved =
false;
1340 if (provider.hasSolver())
1342 solved = provider.
solve(JTJ, jErrors, deltas);
1346 solved = JTJ.
solve(jErrors, deltas);
1351 oneValidIteration =
true;
1360 provider.applyCorrection(deltas);
1362 const Scalar iterationError = provider.template determineRobustError<tEstimator>(swapWeightedErrorVector, swapWeightVector, invertedCovariances);
1365 if (iterationError >= bestError)
1368 if (lambdaFactor >
Numeric::eps() && lambda > 0 && lambda <= maxLambda)
1370 lambda *= lambdaFactor;
1374 ocean_assert(oneValidIteration &&
"At this moment we should have at least one valid iteration!");
1384 bestError = iterationError;
1386 if (intermediateErrors !=
nullptr)
1388 intermediateErrors->push_back(bestError);
1391 provider.acceptCorrection();
1393 std::swap(swapWeightedErrorVector, weightedErrorVector);
1394 std::swap(swapWeightVector, weightVector);
1401 lambda /= lambdaFactor;
1408 else if (lambda >
Numeric::eps() && lambda <= maxLambda)
1410 lambda *= lambdaFactor;
1414 ocean_assert(oneValidIteration &&
"At this moment we should have at least one valid iteration!");
1424 *finalError = bestError;
1427 return oneValidIteration;
1430template <
typename T>
1435 ocean_assert(lambda >=
Scalar(0) && lambda <= maxLambda);
1436 ocean_assert((lambda ==
Scalar(0) && lambdaFactor ==
Scalar(1)) || (lambda >
Scalar(0) && lambdaFactor >
Scalar(1)));
1438 const bool useLevenbergMarquardt = (lambda > 0 && lambdaFactor > 1);
1441 Scalar bestError = (useLevenbergMarquardt || initialError) ? advancedDenseProvider.determineError() :
Numeric::minValue();
1445 ocean_assert(
false &&
"The initial model was invalid and thus the optimization cannot be applied!");
1451 *initialError = bestError;
1454 if (intermediateErrors !=
nullptr)
1456 ocean_assert(intermediateErrors->empty());
1457 intermediateErrors->push_back(bestError);
1460 bool oneValidIteration =
false;
1462 Matrix hessian, jacobianError, deltas;
1464 unsigned int i = 0u;
1465 while (!advancedDenseProvider.shouldStop() && i < iterations)
1473 if (!advancedDenseProvider.determineHessianAndErrorJacobian(hessian, jacobianError))
1475 ocean_assert(
false &&
"The Hessian and the Jacobian with combined error values could not be determined!");
1479 ocean_assert(hessian.
rows() == hessian.
columns());
1480 ocean_assert(hessian.
rows() == jacobianError.
rows() && jacobianError.
columns() == 1);
1485 ocean_assert(hessianDiagonal.
rows() == hessian.
rows() && hessianDiagonal.
columns() == 1);
1487 while (!advancedDenseProvider.shouldStop() && i++ < iterations)
1493 for (
unsigned int n = 0; n < hessian.
columns(); ++n)
1495 hessian(n, n) = hessianDiagonal(n, 0) * (
Scalar(1) + lambda);
1501 bool solved =
false;
1503 if (advancedDenseProvider.hasSolver())
1505 solved = advancedDenseProvider.
solve(hessian, jacobianError, deltas);
1514 oneValidIteration =
true;
1523 advancedDenseProvider.applyCorrection(deltas);
1525 const Scalar iterationError = (useLevenbergMarquardt || intermediateErrors) ? advancedDenseProvider.determineError() :
Numeric::minValue();
1528 if (useLevenbergMarquardt && iterationError >= bestError)
1531 if (lambda > 0 && lambda <= maxLambda)
1533 lambda *= lambdaFactor;
1537 ocean_assert(oneValidIteration &&
"At this moment we should have at least one valid iteration!");
1547 bestError = iterationError;
1549 if (intermediateErrors !=
nullptr)
1551 intermediateErrors->push_back(bestError);
1554 advancedDenseProvider.acceptCorrection();
1561 lambda /= lambdaFactor;
1568 else if (lambda >
Numeric::eps() && lambda <= maxLambda)
1570 lambda *= lambdaFactor;
1574 ocean_assert(oneValidIteration &&
"At this moment we should have at least one valid iteration!");
1585 if (!useLevenbergMarquardt && !intermediateErrors)
1587 bestError = advancedDenseProvider.determineError();
1590 *finalError = bestError;
1593 return oneValidIteration;
1596template <
typename T>
1601 ocean_assert(lambda >=
Scalar(0) && lambda <= maxLambda);
1602 ocean_assert((lambda ==
Scalar(0) && lambdaFactor ==
Scalar(1)) || (lambda >
Scalar(0) && lambdaFactor >
Scalar(1)));
1604 const bool useLevenbergMarquardt = (lambda > 0 && lambdaFactor > 1);
1607 Scalar bestError = (useLevenbergMarquardt || initialError) ? advancedSparseProvider.determineError() :
Numeric::minValue();
1611 ocean_assert(
false &&
"The initial model was invalid and thus the optimization cannot be applied!");
1617 *initialError = bestError;
1620 if (intermediateErrors !=
nullptr)
1622 ocean_assert(intermediateErrors->empty());
1623 intermediateErrors->push_back(bestError);
1626 bool oneValidIteration =
false;
1630 unsigned int i = 0u;
1631 while (!advancedSparseProvider.shouldStop() && i < iterations)
1637 if (!advancedSparseProvider.determineParameters())
1639 ocean_assert(
false &&
"The provider failed to determine the abstract parameters.");
1643 while (!advancedSparseProvider.shouldStop() && i++ < iterations)
1645 ocean_assert(lambda >=
Scalar(0));
1646 if (advancedSparseProvider.solve(deltas, lambda))
1648 oneValidIteration =
true;
1657 advancedSparseProvider.applyCorrection(deltas);
1659 const Scalar iterationError = (useLevenbergMarquardt || intermediateErrors) ? advancedSparseProvider.determineError() :
Numeric::minValue();
1662 if (useLevenbergMarquardt && iterationError >= bestError)
1665 if (lambda > 0 && lambda <= maxLambda)
1667 lambda *= lambdaFactor;
1671 ocean_assert(oneValidIteration &&
"At this moment we should have at least one valid iteration!");
1681 bestError = iterationError;
1683 if (intermediateErrors !=
nullptr)
1685 intermediateErrors->push_back(bestError);
1688 advancedSparseProvider.acceptCorrection();
1695 lambda /= lambdaFactor;
1702 else if (lambda >
Numeric::eps() && lambda <= maxLambda)
1704 lambda *= lambdaFactor;
1708 ocean_assert(oneValidIteration &&
"At this moment we should have at least one valid iteration!");
1719 if (!useLevenbergMarquardt && !intermediateErrors)
1721 bestError = advancedSparseProvider.determineError();
1724 *finalError = bestError;
1727 return oneValidIteration;
1730template <Estimator::EstimatorType tEstimator>
1734 const Scalar sqrSigma = Estimator::needSigma<tEstimator>() ?
Numeric::sqr(Estimator::determineSigmaSquare<tEstimator>(sqrErrors.data(), sqrErrors.size(), modelParameters)) : 0;
1738 for (
size_t n = 0; n < sqrErrors.size(); ++n)
1744 const Scalar weight = max(
Numeric::weakEps(), Estimator::robustWeightSquare<tEstimator>(sqrErrors[n], sqrSigma));
1747 if (transposedInvertedCovariances)
1749 robustError += (transposedInvertedCovariances[n].
transposed() * weightedErrors[n]).
sqr() * weight;
1753 robustError += sqrErrors[n] * weight;
1756 weightedErrors[n] *= weight;
1758 weightVectors[n] =
Vector2(weight, weight);
1762 return robustError /
Scalar(sqrErrors.size());
1765template <Estimator::EstimatorType tEstimator,
size_t tDimension>
1768 ocean_assert(transposedInvertedCovariances ==
nullptr &&
"Currently not implemented");
1769 OCEAN_SUPPRESS_UNUSED_WARNING(transposedInvertedCovariances);
1772 const Scalar sqrSigma = Estimator::needSigma<tEstimator>() ?
Numeric::sqr(Estimator::determineSigmaSquare<tEstimator>(sqrErrors.data(), sqrErrors.size(), modelParameters)) : 0;
1776 for (
size_t n = 0; n < sqrErrors.size(); ++n)
1785 const Scalar weight = max(
Numeric::weakEps(), Estimator::robustWeightSquare<tEstimator>(sqrErrors[n], sqrSigma));
1788 robustError += sqrErrors[n] * weight;
1790 for (
size_t d = 0; d < tDimension; ++d)
1792 weightedErrorsPointer[d] *= weight;
1793 weightVectorsPointer[d] = weight;
1798 return robustError /
Scalar(sqrErrors.size());
1801template <Estimator::EstimatorType tEstimator>
1804 ocean_assert(transposedInvertedCovariances_i ==
nullptr &&
"Currently not implemented");
1805 OCEAN_SUPPRESS_UNUSED_WARNING(transposedInvertedCovariances_i);
1808 const Scalar sqrSigma = Estimator::needSigma<tEstimator>() ?
Numeric::sqr(Estimator::determineSigmaSquare<tEstimator>(sqrErrors.data(), sqrErrors.size(), modelParameters)) : 0;
1812 for (
size_t n = 0; n < sqrErrors.size(); ++n)
1814 Scalar*
const weightedErrorsPointer = weightedErrors_i + n * dimension;
1815 Scalar*
const weightVectorsPointer = weightVectors_i + n * dimension;
1820 const Scalar weight = Estimator::robustWeightSquare<tEstimator>(sqrErrors[n], sqrSigma);
1823 robustError += sqrErrors[n] * weight;
1825 for (
size_t d = 0; d < dimension; ++d)
1827 weightedErrorsPointer[d] *= weight;
1828 weightVectorsPointer[d] = weight;
1833 return robustError /
Scalar(sqrErrors.size());
1841 return sqrErrors2robustErrors2<Estimator::ET_SQUARE>(sqrErrors, modelParameters, weightedErrors, weightVectors, transposedInvertedCovariances);
1844 return sqrErrors2robustErrors2<Estimator::ET_LINEAR>(sqrErrors, modelParameters, weightedErrors, weightVectors, transposedInvertedCovariances);
1847 return sqrErrors2robustErrors2<Estimator::ET_HUBER>(sqrErrors, modelParameters, weightedErrors, weightVectors, transposedInvertedCovariances);
1850 return sqrErrors2robustErrors2<Estimator::ET_TUKEY>(sqrErrors, modelParameters, weightedErrors, weightVectors, transposedInvertedCovariances);
1853 return sqrErrors2robustErrors2<Estimator::ET_CAUCHY>(sqrErrors, modelParameters, weightedErrors, weightVectors, transposedInvertedCovariances);
1856 ocean_assert(
false &&
"Invalid estimator!");
1861template <
size_t tDimension>
1867 return sqrErrors2robustErrors<Estimator::ET_SQUARE, tDimension>(sqrErrors, modelParameters, weightedErrors, weightVectors, transposedInvertedCovariances);
1870 return sqrErrors2robustErrors<Estimator::ET_LINEAR, tDimension>(sqrErrors, modelParameters, weightedErrors, weightVectors, transposedInvertedCovariances);
1873 return sqrErrors2robustErrors<Estimator::ET_HUBER, tDimension>(sqrErrors, modelParameters, weightedErrors, weightVectors, transposedInvertedCovariances);
1876 return sqrErrors2robustErrors<Estimator::ET_TUKEY, tDimension>(sqrErrors, modelParameters, weightedErrors, weightVectors, transposedInvertedCovariances);
1879 return sqrErrors2robustErrors<Estimator::ET_CAUCHY, tDimension>(sqrErrors, modelParameters, weightedErrors, weightVectors, transposedInvertedCovariances);
1882 ocean_assert(
false &&
"Invalid estimator!");
1892 return sqrErrors2robustErrors_i<Estimator::ET_SQUARE>(sqrErrors, modelParameters, dimension, weightedErrors_i, weightVectors_i, transposedInvertedCovariances_i);
1895 return sqrErrors2robustErrors_i<Estimator::ET_LINEAR>(sqrErrors, modelParameters, dimension, weightedErrors_i, weightVectors_i, transposedInvertedCovariances_i);
1898 return sqrErrors2robustErrors_i<Estimator::ET_HUBER>(sqrErrors, modelParameters, dimension, weightedErrors_i, weightVectors_i, transposedInvertedCovariances_i);
1901 return sqrErrors2robustErrors_i<Estimator::ET_TUKEY>(sqrErrors, modelParameters, dimension, weightedErrors_i, weightVectors_i, transposedInvertedCovariances_i);
1904 return sqrErrors2robustErrors_i<Estimator::ET_CAUCHY>(sqrErrors, modelParameters, dimension, weightedErrors_i, weightVectors_i, transposedInvertedCovariances_i);
1907 ocean_assert(
false &&
"Invalid estimator!");
virtual size_t size() const =0
Returns the number of accessible elements of this accessor object.
This class implements a base class for all indexed-based accessors allowing a constant reference acce...
Definition Accessor.h:241
EstimatorType
Definition of individual robust estimator types.
Definition Estimator.h:34
@ ET_HUBER
The Huber estimator type.
Definition Estimator.h:84
@ ET_TUKEY
The Tukey estimator.
Definition Estimator.h:102
@ ET_SQUARE
The standard square error estimator (L2).
Definition Estimator.h:52
@ ET_LINEAR
The linear estimator (L1).
Definition Estimator.h:66
@ ET_CAUCHY
The Cauchy estimator.
Definition Estimator.h:118
This class implements the base for an advanced dense optimization provider.
Definition NonLinearOptimization.h:326
void acceptCorrection()
Accepts the current model candidate a new (better) model than the previous one.
Definition NonLinearOptimization.h:801
Scalar determineError()
Determines the error for the current model candidate (not the actual model).
Definition NonLinearOptimization.h:784
bool determineHessianAndErrorJacobian(Matrix &hessian, Matrix &jacobianError)
Determines the Hessian matrix and the Error-Jacobian vector based on the actual/current model (the tr...
Definition NonLinearOptimization.h:790
bool hasSolver() const
Returns whether the provider comes with an own solver for the linear equation.
Definition NonLinearOptimization.h:812
bool shouldStop()
Returns whether the optimization process should stop e.g., due to an external event.
Definition NonLinearOptimization.h:806
bool solve(const Matrix &hessian, const Matrix &jacobianError, Matrix &deltas) const
Solves the linear equation Hessian * deltas = -jacobianError.
Definition NonLinearOptimization.h:817
AdvancedDenseOptimizationProvider()
Protected default constructor.
Definition NonLinearOptimization.h:779
void applyCorrection(const Matrix &deltas)
Creates a new model candidate by adjusting the current model with delta values.
Definition NonLinearOptimization.h:796
This class implements the base class for an advanced sparse optimization provider.
Definition NonLinearOptimization.h:393
void acceptCorrection()
Accepts the current model candidate a new (better) model than the previous one.
Definition NonLinearOptimization.h:845
bool determineParameters()
Determines any kind of (abstract) parameters based on the current/actual model (not the model candida...
Definition NonLinearOptimization.h:834
bool shouldStop()
Returns whether the optimization process should stop e.g., due to an external event.
Definition NonLinearOptimization.h:850
Scalar determineError()
Determines the error for the current model candidate (not the actual/actual model).
Definition NonLinearOptimization.h:828
bool solve(Matrix &deltas, const Scalar lambda=Scalar(0))
Solves the linear equation Hessian * deltas = -jacobianError based on the internal data.
Definition NonLinearOptimization.h:856
void applyCorrection(const Matrix &deltas)
Creates a new model candidate by adjusting the current/actual model with delta values.
Definition NonLinearOptimization.h:840
AdvancedSparseOptimizationProvider()
Protected default constructor.
Definition NonLinearOptimization.h:823
This class implements the base class for an accessor of groups of pairs.
Definition NonLinearOptimization.h:46
CorrespondenceGroupsAccessor(CorrespondenceGroupsAccessor< TFirst, TSecond > &&accessor)
Move constructor.
Definition NonLinearOptimization.h:660
size_t groupElements(const size_t groupIndex) const
Returns the number of elements within a specified group.
Definition NonLinearOptimization.h:673
size_t groups() const
Returns the number of groups of this accessor.
Definition NonLinearOptimization.h:667
const TSecond & secondElement(const size_t groupIndex, const size_t elementIndex) const
Returns the first element of a pair of a specific group of this object.
Definition NonLinearOptimization.h:702
CorrespondenceGroupsAccessor< TFirst, TSecond > & operator=(CorrespondenceGroupsAccessor< TFirst, TSecond > &&accessor)
Move constructor.
Definition NonLinearOptimization.h:718
CorrespondenceGroupsAccessor(const ElementGroups &elementGroups)
Creates a new accessor object.
Definition NonLinearOptimization.h:639
CorrespondenceGroupsAccessor< TFirst, TSecond > & operator=(const CorrespondenceGroupsAccessor< TFirst, TSecond > &accessor)
Copy constructor.
Definition NonLinearOptimization.h:711
void element(const size_t groupIndex, const size_t elementIndex, TFirst &first, TSecond &second) const
Returns one pair of a specific group of this object.
Definition NonLinearOptimization.h:681
const TFirst & firstElement(const size_t groupIndex, const size_t elementIndex) const
Returns the first element of a pair of a specific group of this object.
Definition NonLinearOptimization.h:693
CorrespondenceGroupsAccessor()
Creates a new accessor object.
Definition NonLinearOptimization.h:633
std::vector< Elements > ElementGroups
Definition of a vector holding a group of elements.
Definition NonLinearOptimization.h:62
CorrespondenceGroupsAccessor(const CorrespondenceGroupsAccessor< TFirst, TSecond > &accessor)
Copy constructor.
Definition NonLinearOptimization.h:653
std::vector< Element > Elements
Definition of a vector holding elements.
Definition NonLinearOptimization.h:57
std::pair< Index32, Vector2 > Element
Definition of a pair combining an object point id with an image point.
Definition NonLinearOptimization.h:52
CorrespondenceGroupsAccessor(ElementGroups &&elementGroups)
Creates a new accessor object.
Definition NonLinearOptimization.h:646
ElementGroups elementGroups_
The groups of elements of this accessor.
Definition NonLinearOptimization.h:150
This class implements an abstract specialization of the accessor for groups of pairs for object point...
Definition NonLinearOptimization.h:158
ObjectPointGroupsAccessor()
Creates a new accessor object.
Definition NonLinearOptimization.h:728
This class implements a group accessor providing access to pairs of poses and image points.
Definition NonLinearOptimization.h:222
size_t addObjectPoint(Elements &&poseIdImagePointPairs)
Adds the observations of a new object point to this accessor.
Definition NonLinearOptimization.h:951
ObjectPointToPoseIndexImagePointCorrespondenceAccessor()=default
Default constructor.
This class implements the base optimization provider.
Definition NonLinearOptimization.h:292
bool solve(const Matrix &JTJ, const Matrix &jErrors, Matrix &deltas) const
Solves the linear equation JTJ * deltas = jErrors.
Definition NonLinearOptimization.h:767
bool hasSolver() const
Returns whether the provider comes with an own solver for the linear equation.
Definition NonLinearOptimization.h:762
This class implements an abstract specialization of the accessor for groups of pairs for poses.
Definition NonLinearOptimization.h:184
PoseGroupsAccessor()
Creates a new accessor object.
Definition NonLinearOptimization.h:745
This class implements the basic functions for least square or robust optimization algorithms for non ...
Definition NonLinearOptimization.h:33
static bool denseOptimization(T &provider, const unsigned int iterations=5u, const Estimator::EstimatorType estimator=Estimator::ET_SQUARE, Scalar lambda=Scalar(0.001), const Scalar lambdaFactor=Scalar(5), Scalar *initialError=nullptr, Scalar *finalError=nullptr, const Matrix *invertedCovariances=nullptr, Scalars *intermediateErrors=nullptr)
Invokes the optimization of a dense (matrix) optimization problem.
Definition NonLinearOptimization.h:963
static bool sparseOptimization(T &provider, const unsigned int iterations=5u, const Estimator::EstimatorType estimator=Estimator::ET_SQUARE, Scalar lambda=Scalar(0.001), const Scalar lambdaFactor=Scalar(5), Scalar *initialError=nullptr, Scalar *finalError=nullptr, const Matrix *invertedCovariances=nullptr, Scalars *intermediateErrors=nullptr)
Invokes the optimization of a sparse (matrix) optimization problem.
Definition NonLinearOptimization.h:1192
static Scalar sqrErrors2robustErrors_i(const Scalars &sqrErrors, const size_t modelParameters, const size_t dimension, Scalar *weightedErrors_i, Scalar *weightVectors_i, const Matrix *transposedInvertedCovariances_i)
Translates the n/i squared errors that correspond to n elements in the error vector to robust errors.
Definition NonLinearOptimization.h:1802
static Scalar sqrErrors2robustErrors2(const Scalars &sqrErrors, const size_t modelParameters, Vector2 *weightedErrors, Vector2 *weightVectors, const SquareMatrix2 *transposedInvertedCovariances)
Translates the n/2 squared errors that correspond to n elements in the error vector to robust errors.
Definition NonLinearOptimization.h:1731
static bool advancedDenseOptimization(T &advancedDenseProvider, const unsigned int iterations, Scalar lambda, const Scalar lambdaFactor, Scalar *initialError=nullptr, Scalar *finalError=nullptr, Scalars *intermediateErrors=nullptr)
Invokes the optimization of a dense (matrix) optimization problem using an advanced optimization prov...
Definition NonLinearOptimization.h:1431
static Scalar sqrErrors2robustErrors(const Scalars &sqrErrors, const size_t modelParameters, StaticBuffer< Scalar, tDimension > *weightedErrors, StaticBuffer< Scalar, tDimension > *weightVectors, const Matrix *transposedInvertedCovariances)
Translates the n/i squared errors that correspond to n elements in the error vector to robust errors.
Definition NonLinearOptimization.h:1766
static bool advancedSparseOptimization(T &advancedSparseProvider, const unsigned int iterations, Scalar lambda, const Scalar lambdaFactor, Scalar *initialError=nullptr, Scalar *finalError=nullptr, Scalars *intermediateErrors=nullptr)
Invokes the optimization of a sparse (matrix) optimization problem using an advanced optimization pro...
Definition NonLinearOptimization.h:1597
This class implements an optimization for universal dense problems with one model (optimization probl...
Definition NonLinearUniversalOptimizationDense.h:32
MatrixT< T > transposedMultiply(const MatrixT< T > &right) const
Multiplies this transposed matrix with a second matrix.
void weightedSelfTransposedSquareMatrix(const MatrixT< T > &weightDiagonal, MatrixT< T > &result) const
Returns the matrix product of transposed matrix of this matrix and this matrix and applies a further ...
size_t columns() const
Returns the count of columns.
Definition Matrix.h:698
MatrixT< T > selfTransposedSquareMatrix() const
Returns the matrix product of transposed matrix of this matrix and this matrix.
size_t elements() const
Returns the number of entire elements, which is the product of rows and columns.
Definition Matrix.h:704
MatrixT< T > diagonal() const
Returns a vector containing the values of the diagonal.
T norm() const
Determines the L1 norm (sum of absolute elements) of this matrix.
Definition Matrix.h:772
@ MP_SYMMETRIC
The matrix is symmetric.
Definition Matrix.h:79
size_t rows() const
Returns the count of rows.
Definition Matrix.h:692
bool selfSquareDiagonalMatrixMultiply(const MatrixT< T > &right, MatrixT< T > &result) const
Interprets this matrix as diagonal matrix and multiplies a second matrix on the right of the interpre...
bool solve(const MatrixT< T > &b, MatrixT< T > &x, const MatrixProperty matrixProperty=MP_UNKNOWN) const
Solves the given linear system.
Definition Matrix.h:710
static constexpr T minValue()
Returns the min scalar value.
Definition Numeric.h:3253
static constexpr T weakEps()
Returns a weak epsilon.
static constexpr bool isWeakEqualEps(const T value)
Returns whether a value is smaller than or equal to a weak epsilon.
Definition Numeric.h:2165
static constexpr T eps()
Returns a small epsilon.
static bool isEqual(const T first, const T second)
Returns whether two values are equal up to a small epsilon.
Definition Numeric.h:2389
static constexpr T sqr(const T value)
Returns the square of a given value.
Definition Numeric.h:1495
static constexpr bool isEqualEps(const T value)
Returns whether a value is smaller than or equal to a small epsilon.
Definition Numeric.h:2090
static constexpr bool isNotEqualEps(const T value)
Returns whether a value is not smaller than or equal to a small epsilon.
Definition Numeric.h:2240
static T summedSqr(const T *values, const size_t number)
Returns the summed squares of a given values.
Definition Numeric.h:1514
static constexpr T maxValue()
Returns the max scalar value.
Definition Numeric.h:3247
This class implements a sparse matrix using a float type for its elements that is specified by T.
Definition SparseMatrix.h:61
bool isZero(const size_t row, const size_t column) const
Returns whether a specified elements is zero.
SparseMatrixT< T > transposed() const
Returns the transposes matrix of this matrix.
size_t rows() const
Returns the number of rows this matrix has.
size_t columns() const
Returns the number of columns this matrix has.
bool solve(const MatrixT< T > &b, MatrixT< T > &x) const
Solves the given linear system.
MatrixT< T > diagonal() const
Returns a vector containing the values of the diagonal.
This class implements a 2x2 square matrix.
Definition SquareMatrix2.h:73
SquareMatrixT2< T > transposed() const
Returns the transposed of this matrix.
Definition SquareMatrix2.h:665
This class implements a static buffer that has a fixed capacity.
Definition StaticBuffer.h:24
const T * data() const
Returns the buffer data pointer.
Definition StaticBuffer.h:240
unsigned int sqr(const char value)
Returns the square value of a given value.
Definition base/Utilities.h:1053
uint32_t Index32
Definition of a 32 bit index value.
Definition Base.h:84
SparseMatrixT< Scalar > SparseMatrix
Definition of the SparseMatrix object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with s...
Definition SparseMatrix.h:30
float Scalar
Definition of a scalar type.
Definition Math.h:129
std::vector< Scalar > Scalars
Definition of a vector holding Scalar objects.
Definition Math.h:145
VectorT2< Scalar > Vector2
Definition of a 2D vector.
Definition Vector2.h:28
The namespace covering the entire Ocean framework.
Definition Accessor.h:15