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