Ocean
Loading...
Searching...
No Matches
NonLinearUniversalOptimizationDense.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_GEOMETRY_NON_LINEAR_UNIVERSAL_OPTIMIZATION_DENSE_H
9#define META_OCEAN_GEOMETRY_NON_LINEAR_UNIVERSAL_OPTIMIZATION_DENSE_H
10
13
15
16namespace Ocean
17{
18
19namespace Geometry
20{
21
22/**
23 * This class implements an optimization for universal dense problems with one model (optimization problem).
24 * The implementation allows to optimize arbitrary (universal) problems with arbitrary dimensions.
25 * @tparam tModelSize Size of the model, the number of model parameters
26 * @tparam tResultDimension Number of dimensions that result for each element (measurement) after the model has been applied
27 * @tparam tExternalModelSize Size of the external model, the number of model parameters
28 * @ingroup geometry
29 */
30template <unsigned int tModelSize, unsigned int tResultDimension, unsigned int tExternalModelSize = tModelSize>
32{
33 public:
34
35 /**
36 * Definition of a model.
37 */
39
40 /**
41 * Definition of an external model.
42 */
44
45 /**
46 * Definition of a model result.
47 */
49
50 /**
51 * Definition of a callback function for dense value calculation.
52 * The first parameter provides the external model that is applied to determine the value.<br>
53 * The second parameter provides the index of the measurement elements that is used to determine the value.<br>
54 * The third parameter receives the determined value.
55 */
57
58 /**
59 * Definition of a callback function for dense error calculation.
60 * The first parameter provides the external model that is applied to determine the error.<br>
61 * The second parameter provides the index of the measurement elements that is used to determine the error.<br>
62 * The third parameter receives the determined error.<br>
63 * The return value provides True if both models provide valid information for the measurement element.
64 */
66
67 /**
68 * Definition of a dense model transformation function.
69 * The transformation function allows to use an external model function for value and error determination while the internal model is used for the internal optimization.<br>
70 * The first parameter provides the internal model.<br>
71 * The second parameter receives the external model.
72 */
74
75 /**
76 * Definition of a dense model adjustment function.
77 * The adjustment function allows to modify the internal model (the modification should be tiny e.g., a normalization of a vector which has almost length 1) before the model will be accepted or rejected
78 * The first parameter provides the model to be adjusted
79 */
81
82 protected:
83
84 /**
85 * This class implements a dense universal optimization provider for universal models and measurement/data values.
86 */
88 {
89 public:
90
91 /**
92 * Creates a new universal optimization object.
93 * @param model The model to be optimized
94 * @param numberElements Number of elements (measurements) that are used to determine the optimized model
95 * @param valueCallback Callback function that is used to determine the value for an individual element (measurement) by application of the model
96 * @param errorCallback Callback function that is used to determine the error for an individual element (measurement)
97 * @param modelTransformationCallback Callback function allowing to transform the internal model into an extern model if intended
98 * @param modelAdjustmentCallback Callback function allowing to adjust the internal model before it will be accepted or rejected
99 */
100 inline UniversalOptimizationProvider(Model& model, const size_t numberElements, const ValueCallback& valueCallback, const ErrorCallback& errorCallback, const ModelTransformationCallback& modelTransformationCallback, const ModelAdjustmentCallback& modelAdjustmentCallback);
101
102 /**
103 * Determines the jacobian matrix for the current camera.
104 * @param jacobian Jacobian matrix
105 */
106 void determineJacobian(Matrix& jacobian) const;
107
108 /**
109 * Applies the model correction and stores the new model as candidate
110 * @param deltas Optimization deltas that define the correction
111 */
112 inline void applyCorrection(const Matrix& deltas);
113
114 /**
115 * Determines the robust error of the current candidate pose.
116 * @param weightedErrorVector Resulting (weighted - if using a robust estimator) error vector
117 * @param weightVector Vector holding the weights that have already been applied to the error vector
118 * @param invertedCovariances Optional 2x2 inverted covariance matrices
119 * @return The resulting robust error
120 * @tparam tEstimator The type of the estimator that is applied for error determination
121 */
122 template <Estimator::EstimatorType tEstimator>
123 Scalar determineRobustError(Matrix& weightedErrorVector, Matrix& weightVector, const Matrix* invertedCovariances) const;
124
125 /**
126 * Accepts the current pose candidate as better model.
127 */
128 inline void acceptCorrection();
129
130 protected:
131
132 /// Universal model that will be optimized.
134
135 /// Universal model that stores the most recent optimization result as candidate.
137
138 /// The number of measurement elements that are used to optimize the model.
139 const size_t numberElements_;
140
141 /// The value calculation callback function.
143
144 /// The error calculation callback function.
146
147 /// The Callback function allowing to transform the model into an external model before the value and error callback functions are invoked.
149
150 /// The optional callback function allowing to adjust a model before it is accepted or rejected
152 };
153
154 public:
155
156 /**
157 * Optimizes a universal model by minimizing the error the model produces.
158 * @param model Universal model that will be optimized
159 * @param numberElements Number of elements (measurements) that are used to determine the optimized model
160 * @param valueCallback Callback function that is used to determine the value for an individual element (measurement) by application of the model
161 * @param errorCallback Callback function that is used to determine the error for an individual element (measurement)
162 * @param modelTransformationCallback Optional callback function allowing to transform the internal model into an extern model if intended
163 * @param modelAdjustmentCallback Optional callback function allowing to adjust the internal (already optimized) model before it will be checked on improvements
164 * @param optimizedModel Resulting optimized model
165 * @param iterations Number of iterations to be applied at most, if no convergence can be reached
166 * @param estimator Robust error estimator to be used
167 * @param lambda Initial Levenberg-Marquardt damping value which may be changed after each iteration using the damping factor, with range [0, infinity)
168 * @param lambdaFactor Levenberg-Marquardt damping factor to be applied to the damping value, with range [1, infinity)
169 * @param initialError Optional resulting averaged pixel error for the given initial parameters, in relation to the defined estimator
170 * @param finalError Optional resulting averaged pixel error for the final optimized parameters, in relation to the defined estimator
171 * @param intermediateErrors Optional resulting intermediate (improving) errors
172 * @return True, if the model could be optimized
173 */
174 static bool optimizeUniversalModel(const Model& model, const size_t numberElements, const ValueCallback& valueCallback, const ErrorCallback& errorCallback, const ModelTransformationCallback& modelTransformationCallback, const ModelAdjustmentCallback& modelAdjustmentCallback, Model& optimizedModel, 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, Scalars* intermediateErrors = nullptr);
175};
176
177template <unsigned int tModelSize, unsigned int tResultDimension, unsigned int tExternalModelSize>
178NonLinearUniversalOptimizationDense<tModelSize, tResultDimension, tExternalModelSize>::UniversalOptimizationProvider::UniversalOptimizationProvider(Model& model, const size_t numberElements, const ValueCallback& valueCallback, const ErrorCallback& errorCallback, const ModelTransformationCallback& modelTransformationCallback, const ModelAdjustmentCallback& modelAdjustmentCallback) :
179 model_(model),
180 numberElements_(numberElements),
181 valueCallback_(valueCallback),
182 errorCallback_(errorCallback),
183 modelTransformationCallback_(modelTransformationCallback),
184 modelAdjustmentCallback_(modelAdjustmentCallback)
185{
186 ocean_assert(valueCallback_);
187 ocean_assert(errorCallback_);
188 ocean_assert(modelTransformationCallback_);
189
190 candidateModel_ = model;
191};
192
193template <unsigned int tModelSize, unsigned int tResultDimension, unsigned int tExternalModelSize>
195{
196 ocean_assert(valueCallback_);
197 ocean_assert(modelTransformationCallback_);
198
199 jacobian.resize(tResultDimension * numberElements_, tModelSize);
200
201 const Scalar eps = Numeric::weakEps();
202 const Scalar invEps = Scalar(1) / eps;
203
204 // transform the internal to the external model
205 ExternalModel externalModel;
206 modelTransformationCallback_(model_, externalModel);
207
208 // stores individual models, each model with one individual epsilon offset
210 for (size_t a = 0; a < tModelSize; ++a)
211 {
212 Model internalModel = model_;
213 internalModel[a] += eps;
214
215 modelTransformationCallback_(internalModel, externalEpsModels[a]);
216 }
217
218 Result result, epsResult;
219 for (size_t n = 0; n < numberElements_; ++n)
220 {
221 // calculate the value for the current model
222 valueCallback_(externalModel, n, result);
223
224 for (size_t m = 0; m < tModelSize; ++m)
225 {
226 // calculate the value for the epsilon model
227 valueCallback_(externalEpsModels[m], n, epsResult);
228
229 // store the individual results
230 for (size_t d = 0; d < tResultDimension; ++d)
231 {
232 jacobian[n * tResultDimension + d][m] = (epsResult[d] - result[d]) * invEps;
233 }
234 }
235 }
236}
237
238template <unsigned int tModelSize, unsigned int tResultDimension, unsigned int tExternalModelSize>
240{
241 ocean_assert(deltas.rows() == tModelSize);
242
243 for (size_t n = 0; n < tModelSize; ++n)
244 {
245 const Scalar& delta = deltas(n);
246 candidateModel_[n] = model_[n] - delta;
247 }
248
249 if (modelAdjustmentCallback_)
250 {
251 modelAdjustmentCallback_(candidateModel_);
252 }
253}
254
255template <unsigned int tModelSize, unsigned int tResultDimension, unsigned int tExternalModelSize>
256template <Estimator::EstimatorType tEstimator>
258{
259 ocean_assert(errorCallback_);
260 ocean_assert(modelTransformationCallback_);
261
262 OCEAN_SUPPRESS_UNUSED_WARNING(invertedCovariances);
263 ocean_assert(invertedCovariances == nullptr);
264
265 // set the correct size of the resulting error vector
266 weightedErrorVector.resize(tResultDimension * numberElements_, 1u);
267 Result* const weightedErrors = (Result*)weightedErrorVector.data();
268
269 ExternalModel externalModel;
270 modelTransformationCallback_(candidateModel_, externalModel);
271
272 Scalar sqrError = 0;
273 Scalars sqrErrors;
274
275 if constexpr (!Estimator::isStandardEstimator<tEstimator>())
276 {
277 sqrErrors.reserve(numberElements_);
278 }
279
280 for (size_t n = 0; n < numberElements_; ++n)
281 {
282 Result& weightedErrorPointer = *((Result*)weightedErrorVector.data() + n);
283 if (!errorCallback_(externalModel, n, weightedErrorPointer))
284 {
285 return Numeric::maxValue();
286 }
287
288 if constexpr (Estimator::isStandardEstimator<tEstimator>())
289 {
290 sqrError += Numeric::summedSqr(weightedErrorPointer.data(), tResultDimension);
291 }
292 else
293 {
294 ocean_assert(!Estimator::isStandardEstimator<tEstimator>());
295 sqrErrors.emplace_back(Numeric::summedSqr(weightedErrorPointer.data(), tResultDimension));
296 }
297 }
298
299 // check whether the standard estimator is used
300 if constexpr (Estimator::isStandardEstimator<tEstimator>())
301 {
302 // the weight vector should be and should stay invalid
303 ocean_assert(!weightVector);
304
305 ocean_assert(numberElements_ > 0);
306 return sqrError /= Scalar(numberElements_);
307 }
308 else
309 {
310 // now we need the weight vector
311 weightVector.resize(tResultDimension * numberElements_, 1u);
312
313 ocean_assert(sqrErrors.size() == numberElements_);
314
315 return sqrErrors2robustErrors<tEstimator, tResultDimension>(sqrErrors, tModelSize, weightedErrors, (StaticBuffer<Scalar, tResultDimension>*)(weightVector.data()), nullptr);
316 }
317}
318
319template <unsigned int tModelSize, unsigned int tResultDimension, unsigned int tExternalModelSize>
324
325template <unsigned int tModelSize, unsigned int tResultDimension, unsigned int tExternalModelSize>
326bool NonLinearUniversalOptimizationDense<tModelSize, tResultDimension, tExternalModelSize>::optimizeUniversalModel(const Model& model, const size_t numberElements, const ValueCallback& valueCallback, const ErrorCallback& errorCallback, const ModelTransformationCallback& modelTransformationCallback, const ModelAdjustmentCallback& modelAdjustmentCallback, Model& optimizedModel, const unsigned int iterations, const Estimator::EstimatorType estimator, Scalar lambda, const Scalar lambdaFactor, Scalar* initialError, Scalar* finalError, Scalars* intermediateErrors)
327{
328 ocean_assert(&model != &optimizedModel);
329 optimizedModel = model;
330
331 UniversalOptimizationProvider provider(optimizedModel, numberElements, valueCallback, errorCallback, modelTransformationCallback, modelAdjustmentCallback);
332 return NonLinearOptimization::denseOptimization<UniversalOptimizationProvider>(provider, iterations, estimator, lambda, lambdaFactor, initialError, finalError, nullptr, intermediateErrors);
333}
334
335}
336
337}
338
339#endif // META_OCEAN_GEOMETRY_NON_LINEAR_UNIVERSAL_OPTIMIZATION_H
This class implements a container for callback functions.
Definition Callback.h:3456
EstimatorType
Definition of individual robust estimator types.
Definition Estimator.h:34
@ ET_SQUARE
The standard square error estimator (L2).
Definition Estimator.h:52
This class implements the base optimization provider.
Definition NonLinearOptimization.h:293
This class implements the basic functions for least square or robust optimization algorithms for non ...
Definition NonLinearOptimization.h:34
This class implements a dense universal optimization provider for universal models and measurement/da...
Definition NonLinearUniversalOptimizationDense.h:88
const ModelAdjustmentCallback modelAdjustmentCallback_
The optional callback function allowing to adjust a model before it is accepted or rejected.
Definition NonLinearUniversalOptimizationDense.h:151
void determineJacobian(Matrix &jacobian) const
Determines the jacobian matrix for the current camera.
Definition NonLinearUniversalOptimizationDense.h:194
Model & model_
Universal model that will be optimized.
Definition NonLinearUniversalOptimizationDense.h:133
const ErrorCallback errorCallback_
The error calculation callback function.
Definition NonLinearUniversalOptimizationDense.h:145
void acceptCorrection()
Accepts the current pose candidate as better model.
Definition NonLinearUniversalOptimizationDense.h:320
Scalar determineRobustError(Matrix &weightedErrorVector, Matrix &weightVector, const Matrix *invertedCovariances) const
Determines the robust error of the current candidate pose.
Definition NonLinearUniversalOptimizationDense.h:257
void applyCorrection(const Matrix &deltas)
Applies the model correction and stores the new model as candidate.
Definition NonLinearUniversalOptimizationDense.h:239
Model candidateModel_
Universal model that stores the most recent optimization result as candidate.
Definition NonLinearUniversalOptimizationDense.h:136
const size_t numberElements_
The number of measurement elements that are used to optimize the model.
Definition NonLinearUniversalOptimizationDense.h:139
const ModelTransformationCallback modelTransformationCallback_
The Callback function allowing to transform the model into an external model before the value and err...
Definition NonLinearUniversalOptimizationDense.h:148
UniversalOptimizationProvider(Model &model, const size_t numberElements, const ValueCallback &valueCallback, const ErrorCallback &errorCallback, const ModelTransformationCallback &modelTransformationCallback, const ModelAdjustmentCallback &modelAdjustmentCallback)
Creates a new universal optimization object.
Definition NonLinearUniversalOptimizationDense.h:178
const ValueCallback valueCallback_
The value calculation callback function.
Definition NonLinearUniversalOptimizationDense.h:142
This class implements an optimization for universal dense problems with one model (optimization probl...
Definition NonLinearUniversalOptimizationDense.h:32
Callback< bool, const ExternalModel &, const size_t, Result & > ErrorCallback
Definition of a callback function for dense error calculation.
Definition NonLinearUniversalOptimizationDense.h:65
static bool optimizeUniversalModel(const Model &model, const size_t numberElements, const ValueCallback &valueCallback, const ErrorCallback &errorCallback, const ModelTransformationCallback &modelTransformationCallback, const ModelAdjustmentCallback &modelAdjustmentCallback, Model &optimizedModel, 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, Scalars *intermediateErrors=nullptr)
Optimizes a universal model by minimizing the error the model produces.
Definition NonLinearUniversalOptimizationDense.h:326
StaticBuffer< Scalar, tResultDimension > Result
Definition of a model result.
Definition NonLinearUniversalOptimizationDense.h:48
Callback< void, Model & > ModelAdjustmentCallback
Definition of a dense model adjustment function.
Definition NonLinearUniversalOptimizationDense.h:80
StaticBuffer< Scalar, tExternalModelSize > ExternalModel
Definition of an external model.
Definition NonLinearUniversalOptimizationDense.h:43
StaticBuffer< Scalar, tModelSize > Model
Definition of a model.
Definition NonLinearUniversalOptimizationDense.h:38
Callback< void, const ExternalModel &, const size_t, Result & > ValueCallback
Definition of a callback function for dense value calculation.
Definition NonLinearUniversalOptimizationDense.h:56
Callback< void, Model &, ExternalModel & > ModelTransformationCallback
Definition of a dense model transformation function.
Definition NonLinearUniversalOptimizationDense.h:73
const T * data() const
Returns a pointer to the internal values.
Definition Matrix.h:798
size_t rows() const
Returns the count of rows.
Definition Matrix.h:692
void resize(const size_t rows, const size_t columns)
Resizes this matrix.
static constexpr T weakEps()
Returns a weak epsilon.
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:3244
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
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
The namespace covering the entire Ocean framework.
Definition Accessor.h:15