1 /*
2 * Copyright (C) 2022 Alberto Irurueta Carro (alberto@irurueta.com)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package com.irurueta.navigation.inertial.calibration.magnetometer;
17
18 import com.irurueta.algebra.Matrix;
19 import com.irurueta.navigation.LockedException;
20 import com.irurueta.navigation.NotReadyException;
21 import com.irurueta.navigation.inertial.calibration.CalibrationException;
22 import com.irurueta.navigation.inertial.calibration.StandardDeviationBodyMagneticFluxDensity;
23 import com.irurueta.numerical.robust.RANSACRobustEstimator;
24 import com.irurueta.numerical.robust.RANSACRobustEstimatorListener;
25 import com.irurueta.numerical.robust.RobustEstimator;
26 import com.irurueta.numerical.robust.RobustEstimatorException;
27 import com.irurueta.numerical.robust.RobustEstimatorMethod;
28
29 import java.util.List;
30
31 /**
32 * Robustly estimates magnetometer cross couplings and scaling factors using
33 * RANSAC algorithm.
34 * <p>
35 * To use this calibrator at least 7 measurements with known magnetic field norm at
36 * an unknown position and instant must be taken at 7 different unknown orientations
37 * when common z-axis is assumed, otherwise at least 10
38 * measurements are required.
39 * <p>
40 * Measured magnetic flux density is assumed to follow the model shown below:
41 * <pre>
42 * mBmeas = bm + (I + Mm) * mBtrue + w
43 * </pre>
44 * Where:
45 * - mBmeas is the measured magnetic flux density. This is a 3x1 vector.
46 * - bm is magnetometer hard-iron bias. Ideally, on a perfect magnetometer,
47 * this should be a 3x1 zero vector.
48 * - I is the 3x3 identity matrix.
49 * - Mm is the 3x3 soft-iron matrix containing cross-couplings and scaling
50 * factors. Ideally, on a perfect magnetometer, this should be a 3x3 zero
51 * matrix.
52 * - mBtrue is ground-truth magnetic flux density. This is a 3x1 vector.
53 * - w is measurement noise. This is a 3x1 vector.
54 * Notice that this calibrator assumes that all measurements are taken in
55 * a short span of time, where Earth magnetic field can be assumed to be
56 * constant at provided location and instant.
57 */
58 public class RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator extends
59 RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator {
60
61 /**
62 * Constant defining default threshold to determine whether samples are inliers or not.
63 */
64 public static final double DEFAULT_THRESHOLD = 1e-9;
65
66 /**
67 * Minimum value that can be set as threshold.
68 * Threshold must be strictly greater than 0.0.
69 */
70 public static final double MIN_THRESHOLD = 0.0;
71
72 /**
73 * Indicates that by default inliers will only be computed but not kept.
74 */
75 public static final boolean DEFAULT_COMPUTE_AND_KEEP_INLIERS = false;
76
77 /**
78 * Indicates that by default residuals will only be computed but not kept.
79 */
80 public static final boolean DEFAULT_COMPUTE_AND_KEEP_RESIDUALS = false;
81
82 /**
83 * Threshold to determine whether samples are inliers or not when testing possible solutions.
84 * The threshold refers to the amount of error on distance between estimated position and
85 * distances provided for each sample.
86 */
87 private double threshold = DEFAULT_THRESHOLD;
88
89 /**
90 * Indicates whether inliers must be computed and kept.
91 */
92 private boolean computeAndKeepInliers = DEFAULT_COMPUTE_AND_KEEP_INLIERS;
93
94 /**
95 * Indicates whether residuals must be computed and kept.
96 */
97 private boolean computeAndKeepResiduals = DEFAULT_COMPUTE_AND_KEEP_RESIDUALS;
98
99 /**
100 * Constructor.
101 */
102 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator() {
103 super();
104 }
105
106 /**
107 * Constructor.
108 *
109 * @param listener listener to handle events raised by this calibrator.
110 */
111 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
112 final RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibratorListener listener) {
113 super(listener);
114 }
115
116 /**
117 * Constructor.
118 *
119 * @param measurements list of body magnetic flux density
120 * measurements with standard deviation of
121 * magnetometer measurements taken at the same
122 * position with zero velocity and unknown different
123 * orientations.
124 */
125 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
126 final List<StandardDeviationBodyMagneticFluxDensity> measurements) {
127 super(measurements);
128 }
129
130 /**
131 * Constructor.
132 *
133 * @param commonAxisUsed indicates whether z-axis is assumed to be common
134 * for the accelerometer, gyroscope and magnetometer.
135 */
136 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(final boolean commonAxisUsed) {
137 super(commonAxisUsed);
138 }
139
140 /**
141 * Constructor.
142 *
143 * @param hardIron known hard-iron.
144 * @throws IllegalArgumentException if provided hard-iron array does
145 * not have length 3.
146 */
147 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(final double[] hardIron) {
148 super(hardIron);
149 }
150
151 /**
152 * Constructor.
153 *
154 * @param hardIron known hard-iron.
155 * @throws IllegalArgumentException if provided hard-iron matrix is not
156 * 3x1.
157 */
158 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(final Matrix hardIron) {
159 super(hardIron);
160 }
161
162 /**
163 * Constructor.
164 *
165 * @param hardIron known hard-iron.
166 * @param initialMm initial soft-iron matrix containing scale factors
167 * and cross coupling errors.
168 * @throws IllegalArgumentException if provided hard-iron matrix is not
169 * 3x1 or if soft-iron matrix is not
170 * 3x3.
171 */
172 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
173 final Matrix hardIron, final Matrix initialMm) {
174 super(hardIron, initialMm);
175 }
176
177 /**
178 * Constructor.
179 *
180 * @param measurements list of body magnetic flux density
181 * measurements with standard deviation of
182 * magnetometer measurements taken at the same
183 * position with zero velocity and unknown different
184 * orientations.
185 * @param listener listener to handle events raised by this calibrator.
186 */
187 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
188 final List<StandardDeviationBodyMagneticFluxDensity> measurements,
189 final RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibratorListener listener) {
190 super(measurements, listener);
191 }
192
193 /**
194 * Constructor.
195 *
196 * @param measurements collection of body magnetic flux density
197 * measurements with standard deviation of
198 * magnetometer measurements taken at the same
199 * position with zero velocity and unknown different
200 * orientations.
201 * @param commonAxisUsed indicates whether z-axis is assumed to be common
202 * for the accelerometer, gyroscope and magnetometer.
203 */
204 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
205 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed) {
206 super(measurements, commonAxisUsed);
207 }
208
209 /**
210 * Constructor.
211 *
212 * @param measurements collection of body magnetic flux density
213 * measurements with standard deviation of
214 * magnetometer measurements taken at the same
215 * position with zero velocity and unknown different
216 * orientations.
217 * @param commonAxisUsed indicates whether z-axis is assumed to be common
218 * for the accelerometer, gyroscope and magnetometer.
219 * @param listener listener to handle events raised by this calibrator.
220 */
221 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
222 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
223 final RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibratorListener listener) {
224 super(measurements, commonAxisUsed, listener);
225 }
226
227 /**
228 * Constructor.
229 *
230 * @param measurements collection of body magnetic flux density
231 * measurements with standard deviation of
232 * magnetometer measurements taken at the same
233 * position with zero velocity and unknown different
234 * orientations.
235 * @param hardIron known hard-iron.
236 * @throws IllegalArgumentException if provided hard-iron array does
237 * not have length 3.
238 */
239 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
240 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final double[] hardIron) {
241 super(measurements, hardIron);
242 }
243
244 /**
245 * Constructor.
246 *
247 * @param measurements collection of body magnetic flux density
248 * measurements with standard deviation of
249 * magnetometer measurements taken at the same
250 * position with zero velocity and unknown different
251 * orientations.
252 * @param hardIron known hard-iron.
253 * @param listener listener to handle events raised by this calibrator.
254 * @throws IllegalArgumentException if provided hard-iron array does
255 * not have length 3.
256 */
257 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
258 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final double[] hardIron,
259 final RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibratorListener listener) {
260 super(measurements, hardIron, listener);
261 }
262
263 /**
264 * Constructor.
265 *
266 * @param measurements collection of body magnetic flux density
267 * measurements with standard deviation of
268 * magnetometer measurements taken at the same
269 * position with zero velocity and unknown different
270 * orientations.
271 * @param commonAxisUsed indicates whether z-axis is assumed to be common
272 * for the accelerometer, gyroscope and magnetometer.
273 * @param hardIron known hard-iron.
274 * @throws IllegalArgumentException if provided hard-iron array does
275 * not have length 3.
276 */
277 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
278 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
279 final double[] hardIron) {
280 super(measurements, commonAxisUsed, hardIron);
281 }
282
283 /**
284 * Constructor.
285 *
286 * @param measurements collection of body magnetic flux density
287 * measurements with standard deviation of
288 * magnetometer measurements taken at the same
289 * position with zero velocity and unknown different
290 * orientations.
291 * @param commonAxisUsed indicates whether z-axis is assumed to be common
292 * for the accelerometer, gyroscope and magnetometer.
293 * @param hardIron known hard-iron.
294 * @param listener listener to handle events raised by this calibrator.
295 * @throws IllegalArgumentException if provided hard-iron array does
296 * not have length 3.
297 */
298 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
299 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
300 final double[] hardIron,
301 final RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibratorListener listener) {
302 super(measurements, commonAxisUsed, hardIron, listener);
303 }
304
305 /**
306 * Constructor.
307 *
308 * @param measurements collection of body magnetic flux density
309 * measurements with standard deviation of
310 * magnetometer measurements taken at the same
311 * position with zero velocity and unknown different
312 * orientations.
313 * @param hardIron known hard-iron.
314 * @throws IllegalArgumentException if provided hard-iron matrix is not
315 * 3x1.
316 */
317 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
318 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron) {
319 super(measurements, hardIron);
320 }
321
322 /**
323 * Constructor.
324 *
325 * @param measurements collection of body magnetic flux density
326 * measurements with standard deviation of
327 * magnetometer measurements taken at the same
328 * position with zero velocity and unknown different
329 * orientations.
330 * @param hardIron known hard-iron to find a solution.
331 * @param listener listener to handle events raised by this calibrator.
332 * @throws IllegalArgumentException if provided hard-iron matrix is not
333 * 3x1.
334 */
335 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
336 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
337 final RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibratorListener listener) {
338 super(measurements, hardIron, listener);
339 }
340
341 /**
342 * Constructor.
343 *
344 * @param measurements collection of body magnetic flux density
345 * measurements with standard deviation of
346 * magnetometer measurements taken at the same
347 * position with zero velocity and unknown different
348 * orientations.
349 * @param commonAxisUsed indicates whether z-axis is assumed to be common
350 * for the accelerometer, gyroscope and magnetometer.
351 * @param hardIron known hard-iron.
352 * @throws IllegalArgumentException if provided hard-iron matrix is not
353 * 3x1.
354 */
355 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
356 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
357 final Matrix hardIron) {
358 super(measurements, commonAxisUsed, hardIron);
359 }
360
361 /**
362 * Constructor.
363 *
364 * @param measurements collection of body magnetic flux density
365 * measurements with standard deviation of
366 * magnetometer measurements taken at the same
367 * position with zero velocity and unknown different
368 * orientations.
369 * @param commonAxisUsed indicates whether z-axis is assumed to be common
370 * for the accelerometer, gyroscope and magnetometer.
371 * @param hardIron known hard-iron.
372 * @param listener listener to handle events raised by this calibrator.
373 * @throws IllegalArgumentException if provided hard-iron matrix is not
374 * 3x1.
375 */
376 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
377 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
378 final Matrix hardIron,
379 final RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibratorListener listener) {
380 super(measurements, commonAxisUsed, hardIron, listener);
381 }
382
383 /**
384 * Constructor.
385 *
386 * @param measurements collection of body magnetic flux density
387 * measurements with standard deviation of
388 * magnetometer measurements taken at the same
389 * position with zero velocity and unknown different
390 * orientations.
391 * @param hardIron known hard-iron.
392 * @param initialMm initial soft-iron matrix containing scale factors
393 * and cross coupling errors.
394 * @throws IllegalArgumentException if provided hard-iron matrix is not
395 * 3x1 or if soft-iron matrix is not
396 * 3x3.
397 */
398 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
399 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
400 final Matrix initialMm) {
401 super(measurements, hardIron, initialMm);
402 }
403
404 /**
405 * Constructor.
406 *
407 * @param measurements collection of body magnetic flux density
408 * measurements with standard deviation of
409 * magnetometer measurements taken at the same
410 * position with zero velocity and unknown different
411 * orientations.
412 * @param hardIron known hard-iron.
413 * @param initialMm initial soft-iron matrix containing scale factors
414 * and cross coupling errors.
415 * @param listener listener to handle events raised by this calibrator.
416 * @throws IllegalArgumentException if provided hard-iron matrix is not
417 * 3x1 or if soft-iron matrix is not
418 * 3x3.
419 */
420 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
421 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
422 final Matrix initialMm,
423 final RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibratorListener listener) {
424 super(measurements, hardIron, initialMm, listener);
425 }
426
427 /**
428 * Constructor.
429 *
430 * @param measurements collection of body magnetic flux density
431 * measurements with standard deviation of
432 * magnetometer measurements taken at the same
433 * position with zero velocity and unknown different
434 * orientations.
435 * @param commonAxisUsed indicates whether z-axis is assumed to be common
436 * for the accelerometer, gyroscope and magnetometer.
437 * @param hardIron known hard-iron.
438 * @param initialMm initial soft-iron matrix containing scale factors
439 * and cross coupling errors.
440 * @throws IllegalArgumentException if provided hard-iron matrix is not
441 * 3x1 or if soft-iron matrix is not
442 * 3x3.
443 */
444 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
445 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
446 final Matrix hardIron, final Matrix initialMm) {
447 super(measurements, commonAxisUsed, hardIron, initialMm);
448 }
449
450 /**
451 * Constructor.
452 *
453 * @param measurements collection of body magnetic flux density
454 * measurements with standard deviation of
455 * magnetometer measurements taken at the same
456 * position with zero velocity and unknown different
457 * orientations.
458 * @param commonAxisUsed indicates whether z-axis is assumed to be common
459 * for the accelerometer, gyroscope and magnetometer.
460 * @param hardIron known hard-iron.
461 * @param initialMm initial soft-iron matrix containing scale factors
462 * and cross coupling errors.
463 * @param listener listener to handle events raised by this calibrator.
464 * @throws IllegalArgumentException if provided hard-iron matrix is not
465 * 3x1 or if soft-iron matrix is not
466 * 3x3.
467 */
468 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
469 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
470 final Matrix hardIron, final Matrix initialMm,
471 final RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibratorListener listener) {
472 super(measurements, commonAxisUsed, hardIron, initialMm, listener);
473 }
474
475 /**
476 * Constructor.
477 *
478 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
479 * @throws IllegalArgumentException if provided magnetic flux norm value is negative.
480 */
481 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
482 final Double groundTruthMagneticFluxDensityNorm) {
483 super(groundTruthMagneticFluxDensityNorm);
484 }
485
486 /**
487 * Constructor.
488 *
489 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
490 * @param listener listener to handle events raised by this calibrator.
491 * @throws IllegalArgumentException if provided magnetic flux norm value is negative.
492 */
493 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
494 final Double groundTruthMagneticFluxDensityNorm,
495 final RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibratorListener listener) {
496 super(groundTruthMagneticFluxDensityNorm, listener);
497 }
498
499 /**
500 * Constructor.
501 *
502 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
503 * @param measurements collection of body magnetic flux density
504 * measurements with standard deviation of
505 * magnetometer measurements taken at the same
506 * position with zero velocity and unknown different
507 * orientations.
508 * @throws IllegalArgumentException if provided magnetic flux norm value is negative.
509 */
510 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
511 final Double groundTruthMagneticFluxDensityNorm,
512 final List<StandardDeviationBodyMagneticFluxDensity> measurements) {
513 super(groundTruthMagneticFluxDensityNorm, measurements);
514 }
515
516 /**
517 * Constructor.
518 *
519 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
520 * @param commonAxisUsed indicates whether z-axis is assumed to be common
521 * for the accelerometer, gyroscope and magnetometer.
522 * @throws IllegalArgumentException if provided magnetic flux norm value is negative.
523 */
524 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
525 final Double groundTruthMagneticFluxDensityNorm, final boolean commonAxisUsed) {
526 super(groundTruthMagneticFluxDensityNorm, commonAxisUsed);
527 }
528
529 /**
530 * Constructor.
531 *
532 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
533 * @param hardIron known hard-iron.
534 * @throws IllegalArgumentException if provided magnetic flux norm value is
535 * negative, or if provided hard-iron array does
536 * not have length 3.
537 */
538 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
539 final Double groundTruthMagneticFluxDensityNorm, final double[] hardIron) {
540 super(groundTruthMagneticFluxDensityNorm, hardIron);
541 }
542
543 /**
544 * Constructor.
545 *
546 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
547 * @param hardIron known hard-iron.
548 * @throws IllegalArgumentException if provided magnetic flux norm value is
549 * negative, or if provided hard-iron matrix is not
550 * 3x1.
551 */
552 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
553 final Double groundTruthMagneticFluxDensityNorm, final Matrix hardIron) {
554 super(groundTruthMagneticFluxDensityNorm, hardIron);
555 }
556
557 /**
558 * Constructor.
559 *
560 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
561 * @param hardIron known hard-iron.
562 * @param initialMm initial soft-iron matrix containing scale factors
563 * and cross coupling errors.
564 * @throws IllegalArgumentException if provided magnetic flux norm value is
565 * negative, or if provided hard-iron matrix is not
566 * 3x1 or if soft-iron matrix is not
567 * 3x3.
568 */
569 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
570 final Double groundTruthMagneticFluxDensityNorm, final Matrix hardIron, final Matrix initialMm) {
571 super(groundTruthMagneticFluxDensityNorm, hardIron, initialMm);
572 }
573
574 /**
575 * Constructor.
576 *
577 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
578 * @param measurements collection of body magnetic flux density
579 * measurements with standard deviation of
580 * magnetometer measurements taken at the same
581 * position with zero velocity and unknown different
582 * orientations.
583 * @param listener listener to handle events raised by this calibrator.
584 * @throws IllegalArgumentException if provided magnetic flux norm value is negative.
585 */
586 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
587 final Double groundTruthMagneticFluxDensityNorm,
588 final List<StandardDeviationBodyMagneticFluxDensity> measurements,
589 final RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibratorListener listener) {
590 super(groundTruthMagneticFluxDensityNorm, measurements, listener);
591 }
592
593 /**
594 * Constructor.
595 *
596 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
597 * @param measurements collection of body magnetic flux density
598 * measurements with standard deviation of
599 * magnetometer measurements taken at the same
600 * position with zero velocity and unknown different
601 * orientations.
602 * @param commonAxisUsed indicates whether z-axis is assumed to be common
603 * for the accelerometer, gyroscope and magnetometer.
604 * @throws IllegalArgumentException if provided magnetic flux norm value is negative.
605 */
606 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
607 final Double groundTruthMagneticFluxDensityNorm,
608 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed) {
609 super(groundTruthMagneticFluxDensityNorm, measurements, commonAxisUsed);
610 }
611
612 /**
613 * Constructor.
614 *
615 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
616 * @param measurements collection of body magnetic flux density
617 * measurements with standard deviation of
618 * magnetometer measurements taken at the same
619 * position with zero velocity and unknown different
620 * orientations.
621 * @param commonAxisUsed indicates whether z-axis is assumed to be common
622 * for the accelerometer, gyroscope and magnetometer.
623 * @param listener listener to handle events raised by this calibrator.
624 * @throws IllegalArgumentException if provided magnetic flux norm value is negative.
625 */
626 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
627 final Double groundTruthMagneticFluxDensityNorm,
628 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
629 final RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibratorListener listener) {
630 super(groundTruthMagneticFluxDensityNorm, measurements, commonAxisUsed, listener);
631 }
632
633 /**
634 * Constructor.
635 *
636 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
637 * @param measurements collection of body magnetic flux density
638 * measurements with standard deviation of
639 * magnetometer measurements taken at the same
640 * position with zero velocity and unknown different
641 * orientations.
642 * @param hardIron known hard-iron.
643 * @throws IllegalArgumentException if provided magnetic flux norm value is negative,
644 * or if provided hard-iron array does not have length 3.
645 */
646 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
647 final Double groundTruthMagneticFluxDensityNorm,
648 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final double[] hardIron) {
649 super(groundTruthMagneticFluxDensityNorm, measurements, hardIron);
650 }
651
652 /**
653 * Constructor.
654 *
655 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
656 * @param measurements collection of body magnetic flux density
657 * measurements with standard deviation of
658 * magnetometer measurements taken at the same
659 * position with zero velocity and unknown different
660 * orientations.
661 * @param hardIron known hard-iron.
662 * @param listener listener to handle events raised by this calibrator.
663 * @throws IllegalArgumentException if provided magnetic flux norm value is negative,
664 * or if provided hard-iron array does not have length 3.
665 */
666 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
667 final Double groundTruthMagneticFluxDensityNorm,
668 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final double[] hardIron,
669 final RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibratorListener listener) {
670 super(groundTruthMagneticFluxDensityNorm, measurements, hardIron, listener);
671 }
672
673 /**
674 * Constructor.
675 *
676 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
677 * @param measurements collection of body magnetic flux density
678 * measurements with standard deviation of
679 * magnetometer measurements taken at the same
680 * position with zero velocity and unknown different
681 * orientations.
682 * @param commonAxisUsed indicates whether z-axis is assumed to be common
683 * for the accelerometer, gyroscope and magnetometer.
684 * @param hardIron known hard-iron.
685 * @throws IllegalArgumentException if provided magnetic flux norm value is negative,
686 * or if provided hard-iron array does not have length 3.
687 */
688 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
689 final Double groundTruthMagneticFluxDensityNorm,
690 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
691 final double[] hardIron) {
692 super(groundTruthMagneticFluxDensityNorm, measurements, commonAxisUsed, hardIron);
693 }
694
695 /**
696 * Constructor.
697 *
698 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
699 * @param measurements collection of body magnetic flux density
700 * measurements with standard deviation of
701 * magnetometer measurements taken at the same
702 * position with zero velocity and unknown different
703 * orientations.
704 * @param commonAxisUsed indicates whether z-axis is assumed to be common
705 * for the accelerometer, gyroscope and magnetometer.
706 * @param hardIron known hard-iron.
707 * @param listener listener to handle events raised by this calibrator.
708 * @throws IllegalArgumentException if provided magnetic flux norm value is negative,
709 * or if provided hard-iron array does not have length 3.
710 */
711 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
712 final Double groundTruthMagneticFluxDensityNorm,
713 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
714 final double[] hardIron,
715 final RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibratorListener listener) {
716 super(groundTruthMagneticFluxDensityNorm, measurements, commonAxisUsed, hardIron, listener);
717 }
718
719 /**
720 * Constructor.
721 *
722 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
723 * @param measurements collection of body magnetic flux density
724 * measurements with standard deviation of
725 * magnetometer measurements taken at the same
726 * position with zero velocity and unknown different
727 * orientations.
728 * @param hardIron known hard-iron.
729 * @throws IllegalArgumentException if provided magnetic flux norm value is negative,
730 * or if provided hard-iron matrix is not 3x1.
731 */
732 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
733 final Double groundTruthMagneticFluxDensityNorm,
734 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron) {
735 super(groundTruthMagneticFluxDensityNorm, measurements, hardIron);
736 }
737
738 /**
739 * Constructor.
740 *
741 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
742 * @param measurements collection of body magnetic flux density
743 * measurements with standard deviation of
744 * magnetometer measurements taken at the same
745 * position with zero velocity and unknown different
746 * orientations.
747 * @param hardIron known hard-iron.
748 * @param listener listener to handle events raised by this calibrator.
749 * @throws IllegalArgumentException if provided magnetic flux norm value is negative,
750 * or if provided hard-iron matrix is not 3x1.
751 */
752 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
753 final Double groundTruthMagneticFluxDensityNorm,
754 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
755 final RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibratorListener listener) {
756 super(groundTruthMagneticFluxDensityNorm, measurements, hardIron, listener);
757 }
758
759 /**
760 * Constructor.
761 *
762 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
763 * @param measurements collection of body magnetic flux density
764 * measurements with standard deviation of
765 * magnetometer measurements taken at the same
766 * position with zero velocity and unknown different
767 * orientations.
768 * @param commonAxisUsed indicates whether z-axis is assumed to be common
769 * for the accelerometer, gyroscope and magnetometer.
770 * @param hardIron known hard-iron.
771 * @throws IllegalArgumentException if provided magnetic flux norm value is negative,
772 * or if provided hard-iron matrix is not 3x1.
773 */
774 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
775 final Double groundTruthMagneticFluxDensityNorm,
776 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
777 final Matrix hardIron) {
778 super(groundTruthMagneticFluxDensityNorm, measurements, commonAxisUsed, hardIron);
779 }
780
781 /**
782 * Constructor.
783 *
784 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
785 * @param measurements collection of body magnetic flux density
786 * measurements with standard deviation of
787 * magnetometer measurements taken at the same
788 * position with zero velocity and unknown different
789 * orientations.
790 * @param commonAxisUsed indicates whether z-axis is assumed to be common
791 * for the accelerometer, gyroscope and magnetometer.
792 * @param hardIron known hard-iron.
793 * @param listener listener to handle events raised by this calibrator.
794 * @throws IllegalArgumentException if provided magnetic flux norm value is negative,
795 * or if provided hard-iron matrix is not 3x1.
796 */
797 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
798 final Double groundTruthMagneticFluxDensityNorm,
799 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
800 final Matrix hardIron,
801 final RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibratorListener listener) {
802 super(groundTruthMagneticFluxDensityNorm, measurements, commonAxisUsed, hardIron, listener);
803 }
804
805 /**
806 * Constructor.
807 *
808 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
809 * @param measurements collection of body magnetic flux density
810 * measurements with standard deviation of
811 * magnetometer measurements taken at the same
812 * position with zero velocity and unknown different
813 * orientations.
814 * @param hardIron known hard-iron.
815 * @param initialMm initial soft-iron matrix containing scale factors
816 * and cross coupling errors.
817 * @throws IllegalArgumentException if provided magnetic flux norm value is negative,
818 * or if provided hard-iron matrix is not 3x1 or if
819 * soft-iron matrix is not 3x3.
820 */
821 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
822 final Double groundTruthMagneticFluxDensityNorm,
823 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
824 final Matrix initialMm) {
825 super(groundTruthMagneticFluxDensityNorm, measurements, hardIron, initialMm);
826 }
827
828 /**
829 * Constructor.
830 *
831 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
832 * @param measurements collection of body magnetic flux density
833 * measurements with standard deviation of
834 * magnetometer measurements taken at the same
835 * position with zero velocity and unknown different
836 * orientations.
837 * @param hardIron known hard-iron.
838 * @param initialMm initial soft-iron matrix containing scale factors
839 * and cross coupling errors.
840 * @param listener listener to handle events raised by this calibrator.
841 * @throws IllegalArgumentException if provided magnetic flux norm value is negative,
842 * or if provided hard-iron matrix is not 3x1 or if
843 * soft-iron matrix is not 3x3.
844 */
845 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
846 final Double groundTruthMagneticFluxDensityNorm,
847 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
848 final Matrix initialMm,
849 final RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibratorListener listener) {
850 super(groundTruthMagneticFluxDensityNorm, measurements, hardIron, initialMm, listener);
851 }
852
853 /**
854 * Constructor.
855 *
856 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
857 * @param measurements collection of body magnetic flux density
858 * measurements with standard deviation of
859 * magnetometer measurements taken at the same
860 * position with zero velocity and unknown different
861 * orientations.
862 * @param commonAxisUsed indicates whether z-axis is assumed to be common
863 * for the accelerometer, gyroscope and magnetometer.
864 * @param hardIron known hard-iron.
865 * @param initialMm initial soft-iron matrix containing scale factors
866 * and cross coupling errors.
867 * @throws IllegalArgumentException if provided magnetic flux norm value is negative,
868 * or if provided hard-iron matrix is not 3x1
869 * or if soft-iron matrix is not 3x3.
870 */
871 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
872 final Double groundTruthMagneticFluxDensityNorm,
873 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
874 final Matrix hardIron, final Matrix initialMm) {
875 super(groundTruthMagneticFluxDensityNorm, measurements, commonAxisUsed, hardIron, initialMm);
876 }
877
878 /**
879 * Constructor.
880 *
881 * @param groundTruthMagneticFluxDensityNorm ground truth magnetic flux density norm expressed in Teslas (T).
882 * @param measurements collection of body magnetic flux density
883 * measurements with standard deviation of
884 * magnetometer measurements taken at the same
885 * position with zero velocity and unknown different
886 * orientations.
887 * @param commonAxisUsed indicates whether z-axis is assumed to be common
888 * for the accelerometer, gyroscope and magnetometer.
889 * @param hardIron known hard-iron.
890 * @param initialMm initial soft-iron matrix containing scale factors
891 * and cross coupling errors.
892 * @param listener listener to handle events raised by this calibrator.
893 * @throws IllegalArgumentException if provided magnetic flux norm value is negative,
894 * or if provided hard-iron matrix is not 3x1
895 * or if soft-iron matrix is not 3x3.
896 */
897 public RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator(
898 final Double groundTruthMagneticFluxDensityNorm,
899 final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
900 final Matrix hardIron, final Matrix initialMm,
901 final RobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibratorListener listener) {
902 super(groundTruthMagneticFluxDensityNorm, measurements, commonAxisUsed, hardIron, initialMm, listener);
903 }
904
905 /**
906 * Gets threshold to determine whether samples are inliers or not when testing possible solutions.
907 * The threshold refers to the amount of error on norm between measured specific forces and the
908 * ones generated with estimated calibration parameters provided for each sample.
909 *
910 * @return threshold to determine whether samples are inliers or not.
911 */
912 public double getThreshold() {
913 return threshold;
914 }
915
916 /**
917 * Sets threshold to determine whether samples are inliers or not when testing possible solutions.
918 * The threshold refers to the amount of error on norm between measured specific forces and the
919 * ones generated with estimated calibration parameters provided for each sample.
920 *
921 * @param threshold threshold to determine whether samples are inliers or not.
922 * @throws IllegalArgumentException if provided value is equal or less than zero.
923 * @throws LockedException if calibrator is currently running.
924 */
925 public void setThreshold(final double threshold) throws LockedException {
926 if (running) {
927 throw new LockedException();
928 }
929 if (threshold <= MIN_THRESHOLD) {
930 throw new IllegalArgumentException();
931 }
932 this.threshold = threshold;
933 }
934
935 /**
936 * Indicates whether inliers must be computed and kept.
937 *
938 * @return true if inliers must be computed and kept, false if inliers
939 * only need to be computed but not kept.
940 */
941 public boolean isComputeAndKeepInliersEnabled() {
942 return computeAndKeepInliers;
943 }
944
945 /**
946 * Specifies whether inliers must be computed and kept.
947 *
948 * @param computeAndKeepInliers true if inliers must be computed and kept,
949 * false if inliers only need to be computed but not kept.
950 * @throws LockedException if calibrator is currently running.
951 */
952 public void setComputeAndKeepInliersEnabled(final boolean computeAndKeepInliers) throws LockedException {
953 if (running) {
954 throw new LockedException();
955 }
956 this.computeAndKeepInliers = computeAndKeepInliers;
957 }
958
959 /**
960 * Indicates whether residuals must be computed and kept.
961 *
962 * @return true if residuals must be computed and kept, false if residuals
963 * only need to be computed but not kept.
964 */
965 public boolean isComputeAndKeepResiduals() {
966 return computeAndKeepResiduals;
967 }
968
969 /**
970 * Specifies whether residuals must be computed and kept.
971 *
972 * @param computeAndKeepResiduals true if residuals must be computed and kept,
973 * false if residuals only need to be computed but not kept.
974 * @throws LockedException if calibrator is currently running.
975 */
976 public void setComputeAndKeepResidualsEnabled(final boolean computeAndKeepResiduals) throws LockedException {
977 if (running) {
978 throw new LockedException();
979 }
980 this.computeAndKeepResiduals = computeAndKeepResiduals;
981 }
982
983 /**
984 * Estimates magnetometer calibration parameters containing hard-iron
985 * bias and soft-iron scale factors and cross-coupling errors.
986 *
987 * @throws LockedException if calibrator is currently running.
988 * @throws NotReadyException if calibrator is not ready.
989 * @throws CalibrationException if estimation fails for numerical reasons.
990 */
991 @SuppressWarnings("DuplicatedCode")
992 @Override
993 public void calibrate() throws LockedException, NotReadyException, CalibrationException {
994 if (running) {
995 throw new LockedException();
996 }
997 if (!isReady()) {
998 throw new NotReadyException();
999 }
1000
1001 final var innerEstimator = new RANSACRobustEstimator<>(new RANSACRobustEstimatorListener<PreliminaryResult>() {
1002 @Override
1003 public double getThreshold() {
1004 return threshold;
1005 }
1006
1007 @Override
1008 public int getTotalSamples() {
1009 return measurements.size();
1010 }
1011
1012 @Override
1013 public int getSubsetSize() {
1014 return preliminarySubsetSize;
1015 }
1016
1017 @Override
1018 public void estimatePreliminarSolutions(
1019 final int[] samplesIndices, final List<PreliminaryResult> solutions) {
1020 computePreliminarySolutions(samplesIndices, solutions);
1021 }
1022
1023 @Override
1024 public double computeResidual(final PreliminaryResult currentEstimation, final int i) {
1025 return computeError(measurements.get(i), currentEstimation);
1026 }
1027
1028 @Override
1029 public boolean isReady() {
1030 return RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator.super.isReady();
1031 }
1032
1033 @Override
1034 public void onEstimateStart(final RobustEstimator<PreliminaryResult> estimator) {
1035 // no action needed
1036 }
1037
1038 @Override
1039 public void onEstimateEnd(final RobustEstimator<PreliminaryResult> estimator) {
1040 // no action needed
1041 }
1042
1043 @Override
1044 public void onEstimateNextIteration(
1045 final RobustEstimator<PreliminaryResult> estimator, final int iteration) {
1046 if (listener != null) {
1047 listener.onCalibrateNextIteration(
1048 RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator.this,
1049 iteration);
1050 }
1051 }
1052
1053 @Override
1054 public void onEstimateProgressChange(
1055 final RobustEstimator<PreliminaryResult> estimator, final float progress) {
1056 if (listener != null) {
1057 listener.onCalibrateProgressChange(
1058 RANSACRobustKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator.this,
1059 progress);
1060 }
1061 }
1062 });
1063
1064 try {
1065 running = true;
1066
1067 if (listener != null) {
1068 listener.onCalibrateStart(this);
1069 }
1070
1071 inliersData = null;
1072
1073 innerEstimator.setComputeAndKeepInliersEnabled(computeAndKeepInliers || refineResult);
1074 innerEstimator.setComputeAndKeepResidualsEnabled(computeAndKeepResiduals || refineResult);
1075 innerEstimator.setConfidence(confidence);
1076 innerEstimator.setMaxIterations(maxIterations);
1077 innerEstimator.setProgressDelta(progressDelta);
1078 final var preliminaryResult = innerEstimator.estimate();
1079 inliersData = innerEstimator.getInliersData();
1080
1081 attemptRefine(preliminaryResult);
1082
1083 if (listener != null) {
1084 listener.onCalibrateEnd(this);
1085 }
1086
1087 } catch (final com.irurueta.numerical.LockedException e) {
1088 throw new LockedException(e);
1089 } catch (final com.irurueta.numerical.NotReadyException e) {
1090 throw new NotReadyException(e);
1091 } catch (final RobustEstimatorException e) {
1092 throw new CalibrationException(e);
1093 } finally {
1094 running = false;
1095 }
1096 }
1097
1098 /**
1099 * Returns method being used for robust estimation.
1100 *
1101 * @return method being used for robust estimation.
1102 */
1103 @Override
1104 public RobustEstimatorMethod getMethod() {
1105 return RobustEstimatorMethod.RANSAC;
1106 }
1107
1108 /**
1109 * Indicates whether this calibrator requires quality scores for each
1110 * measurement or not.
1111 *
1112 * @return true if quality scores are required, false otherwise.
1113 */
1114 @Override
1115 public boolean isQualityScoresRequired() {
1116 return false;
1117 }
1118 }