View Javadoc
1   /*
2    * Copyright (C) 2020 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.AlgebraException;
19  import com.irurueta.algebra.Matrix;
20  import com.irurueta.algebra.Utils;
21  import com.irurueta.algebra.WrongSizeException;
22  import com.irurueta.navigation.LockedException;
23  import com.irurueta.navigation.NotReadyException;
24  import com.irurueta.navigation.frames.ECEFPosition;
25  import com.irurueta.navigation.frames.ECEFVelocity;
26  import com.irurueta.navigation.frames.NEDPosition;
27  import com.irurueta.navigation.frames.NEDVelocity;
28  import com.irurueta.navigation.frames.converters.ECEFtoNEDPositionVelocityConverter;
29  import com.irurueta.navigation.frames.converters.NEDtoECEFPositionVelocityConverter;
30  import com.irurueta.navigation.inertial.BodyKinematics;
31  import com.irurueta.navigation.inertial.BodyMagneticFluxDensity;
32  import com.irurueta.navigation.inertial.calibration.CalibrationException;
33  import com.irurueta.navigation.inertial.calibration.MagneticFluxDensityTriad;
34  import com.irurueta.navigation.inertial.calibration.StandardDeviationBodyMagneticFluxDensity;
35  import com.irurueta.navigation.inertial.wmm.WMMEarthMagneticFluxDensityEstimator;
36  import com.irurueta.navigation.inertial.wmm.WorldMagneticModel;
37  import com.irurueta.numerical.robust.InliersData;
38  import com.irurueta.numerical.robust.RobustEstimatorMethod;
39  import com.irurueta.units.MagneticFluxDensity;
40  import com.irurueta.units.MagneticFluxDensityConverter;
41  import com.irurueta.units.MagneticFluxDensityUnit;
42  
43  import java.io.IOException;
44  import java.util.ArrayList;
45  import java.util.Date;
46  import java.util.GregorianCalendar;
47  import java.util.List;
48  
49  /**
50   * This is an abstract class to robustly estimate magnetometer cross
51   * couplings and scaling factors.
52   * <p>
53   * To use this calibrator at least 7 measurements taken at a single known
54   * position and instant must be taken at 7 different unknown orientations and
55   * zero velocity when common z-axis is assumed, otherwise at least 10
56   * measurements are required.
57   * <p>
58   * Measured magnetic flux density is assumed to follow the model shown below:
59   * <pre>
60   *     mBmeas = bm + (I + Mm) * mBtrue + w
61   * </pre>
62   * Where:
63   * - mBmeas is the measured magnetic flux density. This is a 3x1 vector.
64   * - bm is magnetometer hard-iron bias. Ideally, on a perfect magnetometer,
65   * this should be a 3x1 zero vector.
66   * - I is the 3x3 identity matrix.
67   * - Mm is the 3x3 soft-iron matrix containing cross-couplings and scaling
68   * factors. Ideally, on a perfect magnetometer, this should be a 3x3 zero
69   * matrix.
70   * - mBtrue is ground-truth magnetic flux density. This is a 3x1 vector.
71   * - w is measurement noise. This is a 3x1 vector.
72   * Notice that this calibrator assumes that all measurements are taken in
73   * a short span of time where Earth magnetic field can be assumed to be
74   * constant at provided location and instant.
75   */
76  public abstract class RobustKnownHardIronPositionAndInstantMagnetometerCalibrator implements
77          MagnetometerNonLinearCalibrator, KnownHardIronMagnetometerCalibrator,
78          OrderedStandardDeviationBodyMagneticFluxDensityMagnetometerCalibrator,
79          QualityScoredMagnetometerCalibrator {
80  
81      /**
82       * Indicates whether by default a common z-axis is assumed for the accelerometer,
83       * gyroscope and magnetometer.
84       */
85      public static final boolean DEFAULT_USE_COMMON_Z_AXIS = false;
86  
87      /**
88       * Required minimum number of measurements when common z-axis is assumed.
89       */
90      public static final int MINIMUM_MEASUREMENTS_COMMON_Z_AXIS =
91              BaseKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator.MINIMUM_MEASUREMENTS_COMMON_Z_AXIS;
92  
93      /**
94       * Required minimum number of measurements for the general case.
95       */
96      public static final int MINIMUM_MEASUREMENTS_GENERAL =
97              BaseKnownHardIronMagneticFluxDensityNormMagnetometerCalibrator.MINIMUM_MEASUREMENTS_GENERAL;
98  
99      /**
100      * Default robust estimator method when none is provided.
101      */
102     public static final RobustEstimatorMethod DEFAULT_ROBUST_METHOD = RobustEstimatorMethod.LMEDS;
103 
104     /**
105      * Indicates that result is refined by default.
106      */
107     public static final boolean DEFAULT_REFINE_RESULT = true;
108 
109     /**
110      * Indicates that covariance is kept by default after refining result.
111      */
112     public static final boolean DEFAULT_KEEP_COVARIANCE = true;
113 
114     /**
115      * Default amount of progress variation before notifying a change in estimation progress.
116      * By default this is set to 5%.
117      */
118     public static final float DEFAULT_PROGRESS_DELTA = 0.05f;
119 
120     /**
121      * Minimum allowed value for progress delta.
122      */
123     public static final float MIN_PROGRESS_DELTA = 0.0f;
124 
125     /**
126      * Maximum allowed value for progress delta.
127      */
128     public static final float MAX_PROGRESS_DELTA = 1.0f;
129 
130     /**
131      * Constant defining default confidence of the estimated result, which is
132      * 99%. This means that with a probability of 99% estimation will be
133      * accurate because chosen sub-samples will be inliers.
134      */
135     public static final double DEFAULT_CONFIDENCE = 0.99;
136 
137     /**
138      * Default maximum allowed number of iterations.
139      */
140     public static final int DEFAULT_MAX_ITERATIONS = 5000;
141 
142     /**
143      * Minimum allowed confidence value.
144      */
145     public static final double MIN_CONFIDENCE = 0.0;
146 
147     /**
148      * Maximum allowed confidence value.
149      */
150     public static final double MAX_CONFIDENCE = 1.0;
151 
152     /**
153      * Minimum allowed number of iterations.
154      */
155     public static final int MIN_ITERATIONS = 1;
156 
157     /**
158      * Contains a list of body magnetic flux density measurements taken
159      * at a given position with different unknown orientations and containing the
160      * standard deviation of magnetometer measurements.
161      */
162     protected List<StandardDeviationBodyMagneticFluxDensity> measurements;
163 
164     /**
165      * Listener to be notified of events such as when calibration starts, ends or its
166      * progress significantly changes.
167      */
168     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener;
169 
170     /**
171      * Indicates whether estimator is running.
172      */
173     protected boolean running;
174 
175     /**
176      * Amount of progress variation before notifying a progress change during calibration.
177      */
178     protected float progressDelta = DEFAULT_PROGRESS_DELTA;
179 
180     /**
181      * Amount of confidence expressed as a value between 0.0 and 1.0 (which is equivalent
182      * to 100%). The amount of confidence indicates the probability that the estimated
183      * result is correct. Usually this value will be close to 1.0, but not exactly 1.0.
184      */
185     protected double confidence = DEFAULT_CONFIDENCE;
186 
187     /**
188      * Maximum allowed number of iterations. When the maximum number of iterations is
189      * exceeded, result will not be available, however an approximate result will be
190      * available for retrieval.
191      */
192     protected int maxIterations = DEFAULT_MAX_ITERATIONS;
193 
194     /**
195      * Data related to inlier found after calibration.
196      */
197     protected InliersData inliersData;
198 
199     /**
200      * Indicates whether result must be refined using a non linear calibrator over
201      * found inliers.
202      * If true, inliers will be computed and kept in any implementation regardless of the
203      * settings.
204      */
205     protected boolean refineResult = DEFAULT_REFINE_RESULT;
206 
207     /**
208      * Size of subsets to be checked during robust estimation.
209      */
210     protected int preliminarySubsetSize = MINIMUM_MEASUREMENTS_GENERAL;
211 
212     /**
213      * This flag indicates whether z-axis is assumed to be common for accelerometer,
214      * gyroscope and magnetometer.
215      * When enabled, this eliminates 3 variables from soft-iron (Mm) matrix.
216      */
217     private boolean commonAxisUsed = DEFAULT_USE_COMMON_Z_AXIS;
218 
219     /**
220      * Estimated magnetometer soft-iron matrix containing scale factors
221      * and cross coupling errors.
222      * This is the product of matrix Tm containing cross coupling errors and Km
223      * containing scaling factors.
224      * So tat:
225      * <pre>
226      *     Mm = [sx    mxy  mxz] = Tm*Km
227      *          [myx   sy   myz]
228      *          [mzx   mzy  sz ]
229      * </pre>
230      * Where:
231      * <pre>
232      *     Km = [sx 0   0 ]
233      *          [0  sy  0 ]
234      *          [0  0   sz]
235      * </pre>
236      * and
237      * <pre>
238      *     Tm = [1          -alphaXy    alphaXz ]
239      *          [alphaYx    1           -alphaYz]
240      *          [-alphaZx   alphaZy     1       ]
241      * </pre>
242      * Hence:
243      * <pre>
244      *     Mm = [sx    mxy  mxz] = Tm*Km =  [sx             -sy * alphaXy   sz * alphaXz ]
245      *          [myx   sy   myz]            [sx * alphaYx   sy              -sz * alphaYz]
246      *          [mzx   mzy  sz ]            [-sx * alphaZx  sy * alphaZy    sz           ]
247      * </pre>
248      * This instance allows any 3x3 matrix however, typically alphaYx, alphaZx and alphaZy
249      * are considered to be zero if the accelerometer z-axis is assumed to be the same
250      * as the body z-axis. When this is assumed, myx = mzx = mzy = 0 and the Mm matrix
251      * becomes upper diagonal:
252      * <pre>
253      *     Mm = [sx    mxy  mxz]
254      *          [0     sy   myz]
255      *          [0     0    sz ]
256      * </pre>
257      * Values of this matrix are unit-less.
258      */
259     private Matrix estimatedMm;
260 
261     /**
262      * Indicates whether covariance must be kept after refining result.
263      * This setting is only taken into account if result is refined.
264      */
265     private boolean keepCovariance = DEFAULT_KEEP_COVARIANCE;
266 
267     /**
268      * Estimated covariance matrix for estimated parameters.
269      */
270     private Matrix estimatedCovariance;
271 
272     /**
273      * Estimated chi square value.
274      */
275     private double estimatedChiSq;
276 
277     /**
278      * Estimated degrees of freedom of chi square value. Degrees of freedom is equal to the number of sampled data
279      * minus the number of estimated parameters.
280      */
281     private int estimatedChiSqDegreesOfFreedom;
282 
283     /**
284      * Estimated reduced chi square value. This is equal to estimated chi square value divided by its degrees of
285      * freedom. Ideally this value should be close to 1.0.
286      */
287     private double estimatedReducedChiSq;
288 
289     /**
290      * Estimated mean square error respect to provided measurements.
291      */
292     private double estimatedMse;
293 
294     /**
295      * Estimated probability of finding a smaller chi square value expressed as a value between 0.0 and 1.0. The smaller
296      * the found chi square value is, the better the fit of the estimated parameters to the actual parameter. Thus, the
297      * smaller the chance of finding a smaller chi square value, then the better the estimated fit is.
298      */
299     private double estimatedP;
300 
301     /**
302      * Estimated measure of quality of estimated fit as a value between 0.0 and 1.0. The larger the quality value is,
303      * the better the fit that has been estimated.
304      */
305     private double estimatedQ;
306 
307     /**
308      * Known x-coordinate of hard-iron bias to be used to find a solution.
309      * This is expressed in Teslas (T).
310      */
311     private double hardIronX;
312 
313     /**
314      * Known y-coordinate of hard-iron bias to be used to find a solution.
315      * This is expressed in Teslas (T).
316      */
317     private double hardIronY;
318 
319     /**
320      * Known z-coordinate of hard-iron bias to be used to find a solution.
321      * This is expressed in Teslas (T).
322      */
323     private double hardIronZ;
324 
325     /**
326      * Initial x scaling factor.
327      */
328     private double initialSx;
329 
330     /**
331      * Initial y scaling factor.
332      */
333     private double initialSy;
334 
335     /**
336      * Initial z scaling factor.
337      */
338     private double initialSz;
339 
340     /**
341      * Initial x-y cross coupling error.
342      */
343     private double initialMxy;
344 
345     /**
346      * Initial x-z cross coupling error.
347      */
348     private double initialMxz;
349 
350     /**
351      * Initial y-x cross coupling error.
352      */
353     private double initialMyx;
354 
355     /**
356      * Initial y-z cross coupling error.
357      */
358     private double initialMyz;
359 
360     /**
361      * Initial z-x cross coupling error.
362      */
363     private double initialMzx;
364 
365     /**
366      * Initial z-y cross coupling error.
367      */
368     private double initialMzy;
369 
370     /**
371      * Position where body magnetic flux density measurements have been
372      * taken.
373      */
374     private NEDPosition position;
375 
376     /**
377      * Timestamp expressed as decimal year where magnetic flux density
378      * measurements have been measured.
379      */
380     private Double year = convertTime(System.currentTimeMillis());
381 
382     /**
383      * Contains Earth's magnetic model.
384      */
385     private WorldMagneticModel magneticModel;
386 
387     /**
388      * Inner calibrator to compute calibration for each subset of data or during
389      * final refining.
390      */
391     private final KnownHardIronPositionAndInstantMagnetometerCalibrator innerCalibrator =
392             new KnownHardIronPositionAndInstantMagnetometerCalibrator();
393 
394     /**
395      * Contains magnetic field norm for current position to be reused
396      * during calibration.
397      */
398     protected double magneticDensityNorm;
399 
400     /**
401      * Contains 3x3 identify to be reused.
402      */
403     protected Matrix identity;
404 
405     /**
406      * Contains 3x3 temporary matrix.
407      */
408     protected Matrix tmp1;
409 
410     /**
411      * Contains 3x3 temporary matrix.
412      */
413     protected Matrix tmp2;
414 
415     /**
416      * Contains 3x1 temporary matrix.
417      */
418     protected Matrix tmp3;
419 
420     /**
421      * Contains 3x1 temporary matrix.
422      */
423     protected Matrix tmp4;
424 
425     /**
426      * Constructor.
427      */
428     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator() {
429     }
430 
431     /**
432      * Constructor.
433      *
434      * @param listener listener to handle events raised by this calibrator.
435      */
436     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
437             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
438         this.listener = listener;
439     }
440 
441     /**
442      * Constructor.
443      *
444      * @param measurements list of body magnetic flux density
445      *                     measurements with standard deviation of
446      *                     magnetometer measurements taken at the same
447      *                     position with zero velocity and unknown different
448      *                     orientations.
449      */
450     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
451             final List<StandardDeviationBodyMagneticFluxDensity> measurements) {
452         this.measurements = measurements;
453     }
454 
455     /**
456      * Constructor.
457      *
458      * @param commonAxisUsed indicates whether z-axis is assumed to be common
459      *                       for the accelerometer, gyroscope and magnetometer.
460      */
461     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(final boolean commonAxisUsed) {
462         this.commonAxisUsed = commonAxisUsed;
463     }
464 
465     /**
466      * Constructor.
467      *
468      * @param magneticModel Earth's magnetic model. If null, a default model
469      *                      will be used instead.
470      */
471     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(final WorldMagneticModel magneticModel) {
472         this.magneticModel = magneticModel;
473     }
474 
475     /**
476      * Constructor.
477      *
478      * @param hardIron known hard-iron.
479      * @throws IllegalArgumentException if provided hard-iron array does
480      *                                  not have length 3.
481      */
482     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(final double[] hardIron) {
483         try {
484             setHardIron(hardIron);
485         } catch (final LockedException ignore) {
486             // never happens
487         }
488     }
489 
490     /**
491      * Constructor.
492      *
493      * @param hardIron known hard-iron.
494      * @throws IllegalArgumentException if provided hard-iron matrix is not
495      *                                  3x1.
496      */
497     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(final Matrix hardIron) {
498         try {
499             setHardIron(hardIron);
500         } catch (final LockedException ignore) {
501             // never happens
502         }
503     }
504 
505     /**
506      * Constructor.
507      *
508      * @param hardIron  known hard-iron.
509      * @param initialMm initial soft-iron matrix containing scale factors
510      *                  and cross coupling errors.
511      * @throws IllegalArgumentException if provided hard-iron matrix is not
512      *                                  3x1 or if soft-iron matrix is not
513      *                                  3x3.
514      */
515     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
516             final Matrix hardIron, final Matrix initialMm) {
517         this(hardIron);
518         try {
519             setInitialMm(initialMm);
520         } catch (final LockedException ignore) {
521             // never happens
522         }
523     }
524 
525     /**
526      * Constructor.
527      *
528      * @param position position where body magnetic flux density measurements
529      *                 have been taken.
530      */
531     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(final NEDPosition position) {
532         this.position = position;
533     }
534 
535     /**
536      * Constructor.
537      *
538      * @param position     position where body magnetic flux density measurements
539      *                     have been taken.
540      * @param measurements collection of body magnetic flux density
541      *                     measurements with standard deviation of
542      *                     magnetometer measurements taken at the same
543      *                     position with zero velocity and unknown different
544      *                     orientations.
545      */
546     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
547             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements) {
548         this(position);
549         this.measurements = measurements;
550     }
551 
552     /**
553      * Constructor.
554      *
555      * @param position     position where body magnetic flux density measurements
556      *                     have been taken.
557      * @param measurements collection of body magnetic flux density
558      *                     measurements with standard deviation of
559      *                     magnetometer measurements taken at the same
560      *                     position with zero velocity and unknown different
561      *                     orientations.
562      * @param listener     listener to handle events raised by this calibrator.
563      */
564     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
565             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
566             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
567         this(position, measurements);
568         this.listener = listener;
569     }
570 
571     /**
572      * Constructor.
573      *
574      * @param position       position where body magnetic flux density measurements
575      *                       have been taken.
576      * @param measurements   collection of body magnetic flux density
577      *                       measurements with standard deviation of
578      *                       magnetometer measurements taken at the same
579      *                       position with zero velocity and unknown different
580      *                       orientations.
581      * @param commonAxisUsed indicates whether z-axis is assumed to be common
582      *                       for the accelerometer, gyroscope and magnetometer.
583      */
584     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
585             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
586             final boolean commonAxisUsed) {
587         this(position, measurements);
588         this.commonAxisUsed = commonAxisUsed;
589     }
590 
591     /**
592      * Constructor.
593      *
594      * @param position       position where body magnetic flux density measurements
595      *                       have been taken.
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      */
605     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
606             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
607             final boolean commonAxisUsed,
608             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
609         this(position, measurements, commonAxisUsed);
610         this.listener = listener;
611     }
612 
613     /**
614      * Constructor.
615      *
616      * @param position     position where body magnetic flux density measurements
617      *                     have been taken.
618      * @param measurements collection of body magnetic flux density
619      *                     measurements with standard deviation of
620      *                     magnetometer measurements taken at the same
621      *                     position with zero velocity and unknown different
622      *                     orientations.
623      * @param hardIron     known hard-iron.
624      * @throws IllegalArgumentException if provided hard-iron array does
625      *                                  not have length 3.
626      */
627     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
628             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
629             final double[] hardIron) {
630         this(hardIron);
631         this.position = position;
632         this.measurements = measurements;
633     }
634 
635     /**
636      * Constructor.
637      *
638      * @param position     position where body magnetic flux density measurements
639      *                     have been taken.
640      * @param measurements collection of body magnetic flux density
641      *                     measurements with standard deviation of
642      *                     magnetometer measurements taken at the same
643      *                     position with zero velocity and unknown different
644      *                     orientations.
645      * @param hardIron     known hard-iron.
646      * @param listener     listener to handle events raised by this calibrator.
647      * @throws IllegalArgumentException if provided hard-iron array does
648      *                                  not have length 3.
649      */
650     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
651             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
652             final double[] hardIron,
653             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
654         this(position, measurements, hardIron);
655         this.listener = listener;
656     }
657 
658     /**
659      * Constructor.
660      *
661      * @param position       position where body magnetic flux density measurements
662      *                       have been taken.
663      * @param measurements   collection of body magnetic flux density
664      *                       measurements with standard deviation of
665      *                       magnetometer measurements taken at the same
666      *                       position with zero velocity and unknown different
667      *                       orientations.
668      * @param commonAxisUsed indicates whether z-axis is assumed to be common
669      *                       for the accelerometer, gyroscope and magnetometer.
670      * @param hardIron       known hard-iron.
671      * @throws IllegalArgumentException if provided hard-iron array does
672      *                                  not have length 3.
673      */
674     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
675             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
676             final boolean commonAxisUsed, final double[] hardIron) {
677         this(position, measurements, hardIron);
678         this.commonAxisUsed = commonAxisUsed;
679     }
680 
681     /**
682      * Constructor.
683      *
684      * @param position       position where body magnetic flux density measurements
685      *                       have been taken.
686      * @param measurements   collection of body magnetic flux density
687      *                       measurements with standard deviation of
688      *                       magnetometer measurements taken at the same
689      *                       position with zero velocity and unknown different
690      *                       orientations.
691      * @param commonAxisUsed indicates whether z-axis is assumed to be common
692      *                       for the accelerometer, gyroscope and magnetometer.
693      * @param hardIron       known hard-iron.
694      * @param listener       listener to handle events raised by this calibrator.
695      * @throws IllegalArgumentException if provided hard-iron array does
696      *                                  not have length 3.
697      */
698     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
699             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
700             final boolean commonAxisUsed, final double[] hardIron,
701             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
702         this(position, measurements, commonAxisUsed, hardIron);
703         this.listener = listener;
704     }
705 
706     /**
707      * Constructor.
708      *
709      * @param position     position where body magnetic flux density measurements
710      *                     have been taken.
711      * @param measurements collection of body magnetic flux density
712      *                     measurements with standard deviation of
713      *                     magnetometer measurements taken at the same
714      *                     position with zero velocity and unknown different
715      *                     orientations.
716      * @param hardIron     known hard-iron.
717      * @throws IllegalArgumentException if provided hard-iron matrix is not
718      *                                  3x1.
719      */
720     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
721             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
722             final Matrix hardIron) {
723         this(hardIron);
724         this.position = position;
725         this.measurements = measurements;
726     }
727 
728     /**
729      * Constructor.
730      *
731      * @param position     position where body magnetic flux density measurements
732      *                     have been taken.
733      * @param measurements collection of body magnetic flux density
734      *                     measurements with standard deviation of
735      *                     magnetometer measurements taken at the same
736      *                     position with zero velocity and unknown different
737      *                     orientations.
738      * @param hardIron     known hard-iron.
739      * @param listener     listener to handle events raised by this calibrator.
740      * @throws IllegalArgumentException if provided hard-iron matrix is not
741      *                                  3x1.
742      */
743     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
744             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
745             final Matrix hardIron, final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
746         this(position, measurements, hardIron);
747         this.listener = listener;
748     }
749 
750     /**
751      * Constructor.
752      *
753      * @param position       position where body magnetic flux density measurements
754      *                       have been taken.
755      * @param measurements   collection of body magnetic flux density
756      *                       measurements with standard deviation of
757      *                       magnetometer measurements taken at the same
758      *                       position with zero velocity and unknown different
759      *                       orientations.
760      * @param commonAxisUsed indicates whether z-axis is assumed to be common
761      *                       for the accelerometer, gyroscope and magnetometer.
762      * @param hardIron       known hard-iron.
763      * @throws IllegalArgumentException if provided hard-iron matrix is not
764      *                                  3x1.
765      */
766     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
767             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
768             final boolean commonAxisUsed, final Matrix hardIron) {
769         this(position, measurements, hardIron);
770         this.commonAxisUsed = commonAxisUsed;
771     }
772 
773     /**
774      * Constructor.
775      *
776      * @param position       position where body magnetic flux density measurements
777      *                       have been taken.
778      * @param measurements   collection of body magnetic flux density
779      *                       measurements with standard deviation of
780      *                       magnetometer measurements taken at the same
781      *                       position with zero velocity and unknown different
782      *                       orientations.
783      * @param commonAxisUsed indicates whether z-axis is assumed to be common
784      *                       for the accelerometer, gyroscope and magnetometer.
785      * @param hardIron       known hard-iron.
786      * @param listener       listener to handle events raised by this calibrator.
787      * @throws IllegalArgumentException if provided hard-iron matrix is not
788      *                                  3x1.
789      */
790     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
791             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
792             final boolean commonAxisUsed, final Matrix hardIron,
793             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
794         this(position, measurements, commonAxisUsed, hardIron);
795         this.listener = listener;
796     }
797 
798     /**
799      * Constructor.
800      *
801      * @param position     position where body magnetic flux density measurements
802      *                     have been taken.
803      * @param measurements collection of body magnetic flux density
804      *                     measurements with standard deviation of
805      *                     magnetometer measurements taken at the same
806      *                     position with zero velocity and unknown different
807      *                     orientations.
808      * @param hardIron     known hard-iron.
809      * @param initialMm    initial soft-iron matrix containing scale factors
810      *                     and cross coupling errors.
811      * @throws IllegalArgumentException if provided hard-iron matrix is not
812      *                                  3x1 or if soft-iron matrix is not
813      *                                  3x3.
814      */
815     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
816             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
817             final Matrix hardIron, final Matrix initialMm) {
818         this(hardIron, initialMm);
819         this.position = position;
820         this.measurements = measurements;
821     }
822 
823     /**
824      * Constructor.
825      *
826      * @param position     position where body magnetic flux density measurements
827      *                     have been taken.
828      * @param measurements collection of body magnetic flux density
829      *                     measurements with standard deviation of
830      *                     magnetometer measurements taken at the same
831      *                     position with zero velocity and unknown different
832      *                     orientations.
833      * @param hardIron     known hard-iron.
834      * @param initialMm    initial soft-iron matrix containing scale factors
835      *                     and cross coupling errors.
836      * @param listener     listener to handle events raised by this calibrator.
837      * @throws IllegalArgumentException if provided hard-iron matrix is not
838      *                                  3x1 or if soft-iron matrix is not
839      *                                  3x3.
840      */
841     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
842             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
843             final Matrix hardIron, final Matrix initialMm,
844             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
845         this(position, measurements, hardIron, initialMm);
846         this.listener = listener;
847     }
848 
849     /**
850      * Constructor.
851      *
852      * @param position       position where body magnetic flux density measurements
853      *                       have been taken.
854      * @param measurements   collection of body magnetic flux density
855      *                       measurements with standard deviation of
856      *                       magnetometer measurements taken at the same
857      *                       position with zero velocity and unknown different
858      *                       orientations.
859      * @param commonAxisUsed indicates whether z-axis is assumed to be common
860      *                       for the accelerometer, gyroscope and magnetometer.
861      * @param hardIron       known hard-iron.
862      * @param initialMm      initial soft-iron matrix containing scale factors
863      *                       and cross coupling errors.
864      * @throws IllegalArgumentException if provided hard-iron matrix is not
865      *                                  3x1 or if soft-iron matrix is not
866      *                                  3x3.
867      */
868     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
869             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
870             final boolean commonAxisUsed, final Matrix hardIron, final Matrix initialMm) {
871         this(position, measurements, hardIron, initialMm);
872         this.commonAxisUsed = commonAxisUsed;
873     }
874 
875     /**
876      * Constructor.
877      *
878      * @param position       position where body magnetic flux density measurements
879      *                       have been taken.
880      * @param measurements   collection of body magnetic flux density
881      *                       measurements with standard deviation of
882      *                       magnetometer measurements taken at the same
883      *                       position with zero velocity and unknown different
884      *                       orientations.
885      * @param commonAxisUsed indicates whether z-axis is assumed to be common
886      *                       for the accelerometer, gyroscope and magnetometer.
887      * @param hardIron       known hard-iron.
888      * @param initialMm      initial soft-iron matrix containing scale factors
889      *                       and cross coupling errors.
890      * @param listener       listener to handle events raised by this calibrator.
891      * @throws IllegalArgumentException if provided hard-iron matrix is not
892      *                                  3x1 or if soft-iron matrix is not
893      *                                  3x3.
894      */
895     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
896             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
897             final boolean commonAxisUsed, final Matrix hardIron, final Matrix initialMm,
898             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
899         this(position, measurements, commonAxisUsed, hardIron, initialMm);
900         this.listener = listener;
901     }
902 
903     /**
904      * Constructor.
905      *
906      * @param position position where body magnetic flux density measurements
907      *                 have been taken.
908      */
909     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(final ECEFPosition position) {
910         this(convertPosition(position));
911     }
912 
913     /**
914      * Constructor.
915      *
916      * @param position     position where body magnetic flux density measurements
917      *                     have been taken.
918      * @param measurements collection of body magnetic flux density
919      *                     measurements with standard deviation of
920      *                     magnetometer measurements taken at the same
921      *                     position with zero velocity and unknown different
922      *                     orientations.
923      */
924     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
925             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements) {
926         this(convertPosition(position), measurements);
927     }
928 
929     /**
930      * Constructor.
931      *
932      * @param position     position where body magnetic flux density measurements
933      *                     have been taken.
934      * @param measurements collection of body magnetic flux density
935      *                     measurements with standard deviation of
936      *                     magnetometer measurements taken at the same
937      *                     position with zero velocity and unknown different
938      *                     orientations.
939      * @param listener     listener to handle events raised by this calibrator.
940      */
941     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
942             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
943             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
944         this(convertPosition(position), measurements, listener);
945     }
946 
947     /**
948      * Constructor.
949      *
950      * @param position       position where body magnetic flux density measurements
951      *                       have been taken.
952      * @param measurements   collection of body magnetic flux density
953      *                       measurements with standard deviation of
954      *                       magnetometer measurements taken at the same
955      *                       position with zero velocity and unknown different
956      *                       orientations.
957      * @param commonAxisUsed indicates whether z-axis is assumed to be common
958      *                       for the accelerometer, gyroscope and magnetometer.
959      */
960     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
961             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
962             final boolean commonAxisUsed) {
963         this(convertPosition(position), measurements, commonAxisUsed);
964     }
965 
966     /**
967      * Constructor.
968      *
969      * @param position       position where body magnetic flux density measurements
970      *                       have been taken.
971      * @param measurements   collection of body magnetic flux density
972      *                       measurements with standard deviation of
973      *                       magnetometer measurements taken at the same
974      *                       position with zero velocity and unknown different
975      *                       orientations.
976      * @param commonAxisUsed indicates whether z-axis is assumed to be common
977      *                       for the accelerometer, gyroscope and magnetometer.
978      * @param listener       listener to handle events raised by this calibrator.
979      */
980     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
981             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
982             final boolean commonAxisUsed,
983             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
984         this(convertPosition(position), measurements, commonAxisUsed, listener);
985     }
986 
987     /**
988      * Constructor.
989      *
990      * @param position     position where body magnetic flux density measurements
991      *                     have been taken.
992      * @param measurements collection of body magnetic flux density
993      *                     measurements with standard deviation of
994      *                     magnetometer measurements taken at the same
995      *                     position with zero velocity and unknown different
996      *                     orientations.
997      * @param hardIron     known hard-iron.
998      * @throws IllegalArgumentException if provided hard-iron array does
999      *                                  not have length 3.
1000      */
1001     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1002             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
1003             final double[] hardIron) {
1004         this(convertPosition(position), measurements, hardIron);
1005     }
1006 
1007     /**
1008      * Constructor.
1009      *
1010      * @param position     position where body magnetic flux density measurements
1011      *                     have been taken.
1012      * @param measurements collection of body magnetic flux density
1013      *                     measurements with standard deviation of
1014      *                     magnetometer measurements taken at the same
1015      *                     position with zero velocity and unknown different
1016      *                     orientations.
1017      * @param hardIron     known hard-iron.
1018      * @param listener     listener to handle events raised by this calibrator.
1019      * @throws IllegalArgumentException if provided hard-iron array does
1020      *                                  not have length 3.
1021      */
1022     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1023             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
1024             final double[] hardIron,
1025             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1026         this(convertPosition(position), measurements, hardIron, listener);
1027     }
1028 
1029     /**
1030      * Constructor.
1031      *
1032      * @param position       position where body magnetic flux density measurements
1033      *                       have been taken.
1034      * @param measurements   collection of body magnetic flux density
1035      *                       measurements with standard deviation of
1036      *                       magnetometer measurements taken at the same
1037      *                       position with zero velocity and unknown different
1038      *                       orientations.
1039      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1040      *                       for the accelerometer, gyroscope and magnetometer.
1041      * @param hardIron       known hard-iron.
1042      * @throws IllegalArgumentException if provided hard-iron array does
1043      *                                  not have length 3.
1044      */
1045     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1046             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
1047             final boolean commonAxisUsed, final double[] hardIron) {
1048         this(convertPosition(position), measurements, commonAxisUsed, hardIron);
1049     }
1050 
1051     /**
1052      * Constructor.
1053      *
1054      * @param position       position where body magnetic flux density measurements
1055      *                       have been taken.
1056      * @param measurements   collection of body magnetic flux density
1057      *                       measurements with standard deviation of
1058      *                       magnetometer measurements taken at the same
1059      *                       position with zero velocity and unknown different
1060      *                       orientations.
1061      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1062      *                       for the accelerometer, gyroscope and magnetometer.
1063      * @param hardIron       known hard-iron.
1064      * @param listener       listener to handle events raised by this calibrator.
1065      * @throws IllegalArgumentException if provided hard-iron array does
1066      *                                  not have length 3.
1067      */
1068     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1069             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
1070             final boolean commonAxisUsed, final double[] hardIron,
1071             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1072         this(convertPosition(position), measurements, commonAxisUsed, hardIron, listener);
1073     }
1074 
1075     /**
1076      * Constructor.
1077      *
1078      * @param position     position where body magnetic flux density measurements
1079      *                     have been taken.
1080      * @param measurements collection of body magnetic flux density
1081      *                     measurements with standard deviation of
1082      *                     magnetometer measurements taken at the same
1083      *                     position with zero velocity and unknown different
1084      *                     orientations.
1085      * @param hardIron     known hard-iron.
1086      * @throws IllegalArgumentException if provided hard-iron matrix is not
1087      *                                  3x1.
1088      */
1089     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1090             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
1091             final Matrix hardIron) {
1092         this(convertPosition(position), measurements, hardIron);
1093     }
1094 
1095     /**
1096      * Constructor.
1097      *
1098      * @param position     position where body magnetic flux density measurements
1099      *                     have been taken.
1100      * @param measurements collection of body magnetic flux density
1101      *                     measurements with standard deviation of
1102      *                     magnetometer measurements taken at the same
1103      *                     position with zero velocity and unknown different
1104      *                     orientations.
1105      * @param hardIron     known hard-iron.
1106      * @param listener     listener to handle events raised by this calibrator.
1107      * @throws IllegalArgumentException if provided hard-iron matrix is not
1108      *                                  3x1.
1109      */
1110     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1111             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
1112             final Matrix hardIron, final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1113         this(convertPosition(position), measurements, hardIron, listener);
1114     }
1115 
1116     /**
1117      * Constructor.
1118      *
1119      * @param position       position where body magnetic flux density measurements
1120      *                       have been taken.
1121      * @param measurements   collection of body magnetic flux density
1122      *                       measurements with standard deviation of
1123      *                       magnetometer measurements taken at the same
1124      *                       position with zero velocity and unknown different
1125      *                       orientations.
1126      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1127      *                       for the accelerometer, gyroscope and magnetometer.
1128      * @param hardIron       known hard-iron.
1129      * @throws IllegalArgumentException if provided hard-iron matrix is not
1130      *                                  3x1.
1131      */
1132     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1133             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
1134             final boolean commonAxisUsed, final Matrix hardIron) {
1135         this(convertPosition(position), measurements, commonAxisUsed, hardIron);
1136     }
1137 
1138     /**
1139      * Constructor.
1140      *
1141      * @param position       position where body magnetic flux density measurements
1142      *                       have been taken.
1143      * @param measurements   collection of body magnetic flux density
1144      *                       measurements with standard deviation of
1145      *                       magnetometer measurements taken at the same
1146      *                       position with zero velocity and unknown different
1147      *                       orientations.
1148      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1149      *                       for the accelerometer, gyroscope and magnetometer.
1150      * @param hardIron       known hard-iron.
1151      * @param listener       listener to handle events raised by this calibrator.
1152      * @throws IllegalArgumentException if provided hard-iron matrix is not
1153      *                                  3x1.
1154      */
1155     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1156             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
1157             final boolean commonAxisUsed, final Matrix hardIron,
1158             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1159         this(convertPosition(position), measurements, commonAxisUsed, hardIron, listener);
1160     }
1161 
1162     /**
1163      * Constructor.
1164      *
1165      * @param position     position where body magnetic flux density measurements
1166      *                     have been taken.
1167      * @param measurements collection of body magnetic flux density
1168      *                     measurements with standard deviation of
1169      *                     magnetometer measurements taken at the same
1170      *                     position with zero velocity and unknown different
1171      *                     orientations.
1172      * @param hardIron     known hard-iron.
1173      * @param initialMm    initial soft-iron matrix containing scale factors
1174      *                     and cross coupling errors.
1175      * @throws IllegalArgumentException if provided hard-iron matrix is not
1176      *                                  3x1 or if soft-iron matrix is not
1177      *                                  3x3.
1178      */
1179     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1180             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
1181             final Matrix hardIron, final Matrix initialMm) {
1182         this(convertPosition(position), measurements, hardIron, initialMm);
1183     }
1184 
1185     /**
1186      * Constructor.
1187      *
1188      * @param position     position where body magnetic flux density measurements
1189      *                     have been taken.
1190      * @param measurements collection of body magnetic flux density
1191      *                     measurements with standard deviation of
1192      *                     magnetometer measurements taken at the same
1193      *                     position with zero velocity and unknown different
1194      *                     orientations.
1195      * @param hardIron     known hard-iron.
1196      * @param initialMm    initial soft-iron matrix containing scale factors
1197      *                     and cross coupling errors.
1198      * @param listener     listener to handle events raised by this calibrator.
1199      * @throws IllegalArgumentException if provided hard-iron matrix is not
1200      *                                  3x1 or if soft-iron matrix is not
1201      *                                  3x3.
1202      */
1203     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1204             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
1205             final Matrix hardIron, final Matrix initialMm,
1206             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1207         this(convertPosition(position), measurements, hardIron, initialMm, listener);
1208     }
1209 
1210     /**
1211      * Constructor.
1212      *
1213      * @param position       position where body magnetic flux density measurements
1214      *                       have been taken.
1215      * @param measurements   collection of body magnetic flux density
1216      *                       measurements with standard deviation of
1217      *                       magnetometer measurements taken at the same
1218      *                       position with zero velocity and unknown different
1219      *                       orientations.
1220      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1221      *                       for the accelerometer, gyroscope and magnetometer.
1222      * @param hardIron       known hard-iron.
1223      * @param initialMm      initial soft-iron matrix containing scale factors
1224      *                       and cross coupling errors.
1225      * @throws IllegalArgumentException if provided hard-iron matrix is not
1226      *                                  3x1 or if soft-iron matrix is not
1227      *                                  3x3.
1228      */
1229     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1230             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
1231             final boolean commonAxisUsed, final Matrix hardIron, final Matrix initialMm) {
1232         this(convertPosition(position), measurements, commonAxisUsed, hardIron, initialMm);
1233     }
1234 
1235     /**
1236      * Constructor.
1237      *
1238      * @param position       position where body magnetic flux density measurements
1239      *                       have been taken.
1240      * @param measurements   collection of body magnetic flux density
1241      *                       measurements with standard deviation of
1242      *                       magnetometer measurements taken at the same
1243      *                       position with zero velocity and unknown different
1244      *                       orientations.
1245      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1246      *                       for the accelerometer, gyroscope and magnetometer.
1247      * @param hardIron       known hard-iron.
1248      * @param initialMm      initial soft-iron matrix containing scale factors
1249      *                       and cross coupling errors.
1250      * @param listener       listener to handle events raised by this calibrator.
1251      * @throws IllegalArgumentException if provided hard-iron matrix is not
1252      *                                  3x1 or if soft-iron matrix is not
1253      *                                  3x3.
1254      */
1255     protected RobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1256             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
1257             final boolean commonAxisUsed, final Matrix hardIron, final Matrix initialMm,
1258             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1259         this(convertPosition(position), measurements, commonAxisUsed, hardIron, initialMm, listener);
1260     }
1261 
1262     /**
1263      * Gets ground truth magnetic flux density norm to be expected at location where measurements have been made,
1264      * expressed in Teslas (T).
1265      *
1266      * @return ground truth magnetic flux density or null.
1267      */
1268     public Double getGroundTruthMagneticFluxDensityNorm() {
1269         return innerCalibrator.getGroundTruthMagneticFluxDensityNorm();
1270     }
1271 
1272     /**
1273      * Gets ground truth magnetic flux density norm to be expected at location where measurements have been made.
1274      *
1275      * @return ground truth magnetic flux density or null.
1276      */
1277     public MagneticFluxDensity getGroundTruthMagneticFluxDensityNormAsMagneticFluxDensity() {
1278         return innerCalibrator.getGroundTruthMagneticFluxDensityNormAsMagneticFluxDensity();
1279     }
1280 
1281     /**
1282      * Gets ground truth magnetic flux density norm to be expected at location where measurements have been made.
1283      *
1284      * @param result instance where result will be stored.
1285      * @return true if ground truth magnetic flux density norm has been defined, false if it is not available yet.
1286      */
1287     public boolean getGroundTruthMagneticFluxDensityNormAsMagneticFluxDensity(final MagneticFluxDensity result) {
1288         return innerCalibrator.getGroundTruthMagneticFluxDensityNormAsMagneticFluxDensity(result);
1289     }
1290 
1291     /**
1292      * Gets known x-coordinate of magnetometer hard-iron bias.
1293      * This is expressed in Teslas (T).
1294      *
1295      * @return known x-coordinate of magnetometer hard-iron bias.
1296      */
1297     @Override
1298     public double getHardIronX() {
1299         return hardIronX;
1300     }
1301 
1302     /**
1303      * Sets known x-coordinate of magnetometer hard-iron bias.
1304      * This is expressed in Teslas (T).
1305      *
1306      * @param hardIronX known x-coordinate of magnetometer
1307      *                  hard-iron bias.
1308      * @throws LockedException if calibrator is currently running.
1309      */
1310     @Override
1311     public void setHardIronX(final double hardIronX) throws LockedException {
1312         if (running) {
1313             throw new LockedException();
1314         }
1315         this.hardIronX = hardIronX;
1316     }
1317 
1318     /**
1319      * Gets known y-coordinate of magnetometer hard-iron bias.
1320      * This is expressed in Teslas (T).
1321      *
1322      * @return known y-coordinate of magnetometer hard-iron bias.
1323      */
1324     @Override
1325     public double getHardIronY() {
1326         return hardIronY;
1327     }
1328 
1329     /**
1330      * Sets known y-coordinate of magnetometer hard-iron bias.
1331      * This is expressed in Teslas (T).
1332      *
1333      * @param hardIronY known y-coordinate of magnetometer
1334      *                  hard-iron bias.
1335      * @throws LockedException if calibrator is currently running.
1336      */
1337     @Override
1338     public void setHardIronY(final double hardIronY) throws LockedException {
1339         if (running) {
1340             throw new LockedException();
1341         }
1342         this.hardIronY = hardIronY;
1343     }
1344 
1345     /**
1346      * Gets known z-coordinate of magnetometer hard-iron bias.
1347      * This is expressed in Teslas (T).
1348      *
1349      * @return known z-coordinate of magnetometer hard-iron bias.
1350      */
1351     @Override
1352     public double getHardIronZ() {
1353         return hardIronZ;
1354     }
1355 
1356     /**
1357      * Sets known z-coordinate of magnetometer hard-iron bias.
1358      * This is expressed in meters Teslas (T).
1359      *
1360      * @param hardIronZ known z-coordinate of magnetometer
1361      *                  hard-iron bias.
1362      * @throws LockedException if calibrator is currently running.
1363      */
1364     @Override
1365     public void setHardIronZ(final double hardIronZ) throws LockedException {
1366         if (running) {
1367             throw new LockedException();
1368         }
1369         this.hardIronZ = hardIronZ;
1370     }
1371 
1372     /**
1373      * Gets known x coordinate of magnetometer hard-iron.
1374      *
1375      * @return x coordinate of magnetometer hard-iron.
1376      */
1377     @Override
1378     public MagneticFluxDensity getHardIronXAsMagneticFluxDensity() {
1379         return new MagneticFluxDensity(hardIronX, MagneticFluxDensityUnit.TESLA);
1380     }
1381 
1382     /**
1383      * Gets known x coordinate of magnetometer hard-iron.
1384      *
1385      * @param result instance where result will be stored.
1386      */
1387     @Override
1388     public void getHardIronXAsMagneticFluxDensity(final MagneticFluxDensity result) {
1389         result.setValue(hardIronX);
1390         result.setUnit(MagneticFluxDensityUnit.TESLA);
1391     }
1392 
1393     /**
1394      * Sets known x-coordinate of magnetometer hard-iron.
1395      *
1396      * @param hardIronX known x-coordinate of magnetometer hard-iron.
1397      * @throws LockedException if calibrator is currently running.
1398      */
1399     @Override
1400     public void setHardIronX(final MagneticFluxDensity hardIronX) throws LockedException {
1401         if (running) {
1402             throw new LockedException();
1403         }
1404         this.hardIronX = convertMagneticFluxDensity(hardIronX);
1405     }
1406 
1407     /**
1408      * Gets known y coordinate of magnetometer hard-iron.
1409      *
1410      * @return y coordinate of magnetometer hard-iron.
1411      */
1412     @Override
1413     public MagneticFluxDensity getHardIronYAsMagneticFluxDensity() {
1414         return new MagneticFluxDensity(hardIronY, MagneticFluxDensityUnit.TESLA);
1415     }
1416 
1417     /**
1418      * Gets known y coordinate of magnetometer hard-iron.
1419      *
1420      * @param result instance where result will be stored.
1421      */
1422     @Override
1423     public void getHardIronYAsMagneticFluxDensity(final MagneticFluxDensity result) {
1424         result.setValue(hardIronY);
1425         result.setUnit(MagneticFluxDensityUnit.TESLA);
1426     }
1427 
1428     /**
1429      * Sets known y-coordinate of magnetometer hard-iron.
1430      *
1431      * @param hardIronY known y-coordinate of magnetometer hard-iron.
1432      * @throws LockedException if calibrator is currently running.
1433      */
1434     @Override
1435     public void setHardIronY(final MagneticFluxDensity hardIronY) throws LockedException {
1436         if (running) {
1437             throw new LockedException();
1438         }
1439         this.hardIronY = convertMagneticFluxDensity(hardIronY);
1440     }
1441 
1442     /**
1443      * Gets known z coordinate of magnetometer hard-iron.
1444      *
1445      * @return z coordinate of magnetometer hard-iron.
1446      */
1447     @Override
1448     public MagneticFluxDensity getHardIronZAsMagneticFluxDensity() {
1449         return new MagneticFluxDensity(hardIronZ, MagneticFluxDensityUnit.TESLA);
1450     }
1451 
1452     /**
1453      * Gets known z coordinate of magnetometer hard-iron.
1454      *
1455      * @param result instance where result will be stored.
1456      */
1457     @Override
1458     public void getHardIronZAsMagneticFluxDensity(final MagneticFluxDensity result) {
1459         result.setValue(hardIronZ);
1460         result.setUnit(MagneticFluxDensityUnit.TESLA);
1461     }
1462 
1463     /**
1464      * Sets known z-coordinate of magnetometer hard-iron.
1465      *
1466      * @param hardIronZ known z-coordinate of magnetometer hard-iron.
1467      * @throws LockedException if calibrator is currently running.
1468      */
1469     @Override
1470     public void setHardIronZ(final MagneticFluxDensity hardIronZ) throws LockedException {
1471         if (running) {
1472             throw new LockedException();
1473         }
1474         this.hardIronZ = convertMagneticFluxDensity(hardIronZ);
1475     }
1476 
1477     /**
1478      * Sets known hard-iron bias coordinates of magnetometer expressed in
1479      * Teslas (T).
1480      *
1481      * @param hardIronX x-coordinate of magnetometer
1482      *                  known hard-iron bias.
1483      * @param hardIronY y-coordinate of magnetometer
1484      *                  known hard-iron bias.
1485      * @param hardIronZ z-coordinate of magnetometer
1486      *                  known hard-iron bias.
1487      * @throws LockedException if calibrator is currently running.
1488      */
1489     @Override
1490     public void setHardIronCoordinates(
1491             final double hardIronX, final double hardIronY, final double hardIronZ) throws LockedException {
1492         if (running) {
1493             throw new LockedException();
1494         }
1495         this.hardIronX = hardIronX;
1496         this.hardIronY = hardIronY;
1497         this.hardIronZ = hardIronZ;
1498     }
1499 
1500     /**
1501      * Sets known hard-iron coordinates.
1502      *
1503      * @param hardIronX x-coordinate of magnetometer hard-iron.
1504      * @param hardIronY y-coordinate of magnetometer hard-iron.
1505      * @param hardIronZ z-coordinate of magnetometer hard-iron.
1506      * @throws LockedException if calibrator is currently running.
1507      */
1508     @Override
1509     public void setHardIronCoordinates(
1510             final MagneticFluxDensity hardIronX, final MagneticFluxDensity hardIronY,
1511             final MagneticFluxDensity hardIronZ) throws LockedException {
1512         if (running) {
1513             throw new LockedException();
1514         }
1515         this.hardIronX = convertMagneticFluxDensity(hardIronX);
1516         this.hardIronY = convertMagneticFluxDensity(hardIronY);
1517         this.hardIronZ = convertMagneticFluxDensity(hardIronZ);
1518     }
1519 
1520     /**
1521      * Gets known hard-iron.
1522      *
1523      * @return known hard-iron.
1524      */
1525     @Override
1526     public MagneticFluxDensityTriad getHardIronAsTriad() {
1527         return new MagneticFluxDensityTriad(MagneticFluxDensityUnit.TESLA, hardIronX, hardIronY, hardIronZ);
1528     }
1529 
1530     /**
1531      * Gets known hard-iron.
1532      *
1533      * @param result instance where result will be stored.
1534      */
1535     @Override
1536     public void getHardIronAsTriad(final MagneticFluxDensityTriad result) {
1537         result.setValueCoordinatesAndUnit(hardIronX, hardIronY, hardIronZ, MagneticFluxDensityUnit.TESLA);
1538     }
1539 
1540     /**
1541      * Sets known hard-iron.
1542      *
1543      * @param hardIron hard-iron to be set.
1544      * @throws LockedException if calibrator is currently running.
1545      */
1546     @Override
1547     public void setHardIron(final MagneticFluxDensityTriad hardIron) throws LockedException {
1548         if (running) {
1549             throw new LockedException();
1550         }
1551 
1552         hardIronX = convertMagneticFluxDensity(hardIron.getValueX(), hardIron.getUnit());
1553         hardIronY = convertMagneticFluxDensity(hardIron.getValueY(), hardIron.getUnit());
1554         hardIronZ = convertMagneticFluxDensity(hardIron.getValueZ(), hardIron.getUnit());
1555     }
1556 
1557     /**
1558      * Gets initial x scaling factor.
1559      *
1560      * @return initial x scaling factor.
1561      */
1562     @Override
1563     public double getInitialSx() {
1564         return initialSx;
1565     }
1566 
1567     /**
1568      * Sets initial x scaling factor.
1569      *
1570      * @param initialSx initial x scaling factor.
1571      * @throws LockedException if calibrator is currently running.
1572      */
1573     @Override
1574     public void setInitialSx(final double initialSx) throws LockedException {
1575         if (running) {
1576             throw new LockedException();
1577         }
1578         this.initialSx = initialSx;
1579     }
1580 
1581     /**
1582      * Gets initial y scaling factor.
1583      *
1584      * @return initial y scaling factor.
1585      */
1586     @Override
1587     public double getInitialSy() {
1588         return initialSy;
1589     }
1590 
1591     /**
1592      * Sets initial y scaling factor.
1593      *
1594      * @param initialSy initial y scaling factor.
1595      * @throws LockedException if calibrator is currently running.
1596      */
1597     @Override
1598     public void setInitialSy(final double initialSy) throws LockedException {
1599         if (running) {
1600             throw new LockedException();
1601         }
1602         this.initialSy = initialSy;
1603     }
1604 
1605     /**
1606      * Gets initial z scaling factor.
1607      *
1608      * @return initial z scaling factor.
1609      */
1610     @Override
1611     public double getInitialSz() {
1612         return initialSz;
1613     }
1614 
1615     /**
1616      * Sets initial z scaling factor.
1617      *
1618      * @param initialSz initial z scaling factor.
1619      * @throws LockedException if calibrator is currently running.
1620      */
1621     @Override
1622     public void setInitialSz(final double initialSz) throws LockedException {
1623         if (running) {
1624             throw new LockedException();
1625         }
1626         this.initialSz = initialSz;
1627     }
1628 
1629     /**
1630      * Gets initial x-y cross coupling error.
1631      *
1632      * @return initial x-y cross coupling error.
1633      */
1634     @Override
1635     public double getInitialMxy() {
1636         return initialMxy;
1637     }
1638 
1639     /**
1640      * Sets initial x-y cross coupling error.
1641      *
1642      * @param initialMxy initial x-y cross coupling error.
1643      * @throws LockedException if calibrator is currently running.
1644      */
1645     @Override
1646     public void setInitialMxy(final double initialMxy) throws LockedException {
1647         if (running) {
1648             throw new LockedException();
1649         }
1650         this.initialMxy = initialMxy;
1651     }
1652 
1653     /**
1654      * Gets initial x-z cross coupling error.
1655      *
1656      * @return initial x-z cross coupling error.
1657      */
1658     @Override
1659     public double getInitialMxz() {
1660         return initialMxz;
1661     }
1662 
1663     /**
1664      * Sets initial x-z cross coupling error.
1665      *
1666      * @param initialMxz initial x-z cross coupling error.
1667      * @throws LockedException if calibrator is currently running.
1668      */
1669     @Override
1670     public void setInitialMxz(final double initialMxz) throws LockedException {
1671         if (running) {
1672             throw new LockedException();
1673         }
1674         this.initialMxz = initialMxz;
1675     }
1676 
1677     /**
1678      * Gets initial y-x cross coupling error.
1679      *
1680      * @return initial y-x cross coupling error.
1681      */
1682     @Override
1683     public double getInitialMyx() {
1684         return initialMyx;
1685     }
1686 
1687     /**
1688      * Sets initial y-x cross coupling error.
1689      *
1690      * @param initialMyx initial y-x cross coupling error.
1691      * @throws LockedException if calibrator is currently running.
1692      */
1693     @Override
1694     public void setInitialMyx(final double initialMyx) throws LockedException {
1695         if (running) {
1696             throw new LockedException();
1697         }
1698         this.initialMyx = initialMyx;
1699     }
1700 
1701     /**
1702      * Gets initial y-z cross coupling error.
1703      *
1704      * @return initial y-z cross coupling error.
1705      */
1706     @Override
1707     public double getInitialMyz() {
1708         return initialMyz;
1709     }
1710 
1711     /**
1712      * Sets initial y-z cross coupling error.
1713      *
1714      * @param initialMyz initial y-z cross coupling error.
1715      * @throws LockedException if calibrator is currently running.
1716      */
1717     @Override
1718     public void setInitialMyz(final double initialMyz) throws LockedException {
1719         if (running) {
1720             throw new LockedException();
1721         }
1722         this.initialMyz = initialMyz;
1723     }
1724 
1725     /**
1726      * Gets initial z-x cross coupling error.
1727      *
1728      * @return initial z-x cross coupling error.
1729      */
1730     @Override
1731     public double getInitialMzx() {
1732         return initialMzx;
1733     }
1734 
1735     /**
1736      * Sets initial z-x cross coupling error.
1737      *
1738      * @param initialMzx initial z-x cross coupling error.
1739      * @throws LockedException if calibrator is currently running.
1740      */
1741     @Override
1742     public void setInitialMzx(final double initialMzx) throws LockedException {
1743         if (running) {
1744             throw new LockedException();
1745         }
1746         this.initialMzx = initialMzx;
1747     }
1748 
1749     /**
1750      * Gets initial z-y cross coupling error.
1751      *
1752      * @return initial z-y cross coupling error.
1753      */
1754     @Override
1755     public double getInitialMzy() {
1756         return initialMzy;
1757     }
1758 
1759     /**
1760      * Sets initial z-y cross coupling error.
1761      *
1762      * @param initialMzy initial z-y cross coupling error.
1763      * @throws LockedException if calibrator is currently running.
1764      */
1765     @Override
1766     public void setInitialMzy(final double initialMzy) throws LockedException {
1767         if (running) {
1768             throw new LockedException();
1769         }
1770         this.initialMzy = initialMzy;
1771     }
1772 
1773     /**
1774      * Sets initial scaling factors.
1775      *
1776      * @param initialSx initial x scaling factor.
1777      * @param initialSy initial y scaling factor.
1778      * @param initialSz initial z scaling factor.
1779      * @throws LockedException if calibrator is currently running.
1780      */
1781     @Override
1782     public void setInitialScalingFactors(final double initialSx, final double initialSy, final double initialSz)
1783             throws LockedException {
1784         if (running) {
1785             throw new LockedException();
1786         }
1787         this.initialSx = initialSx;
1788         this.initialSy = initialSy;
1789         this.initialSz = initialSz;
1790     }
1791 
1792     /**
1793      * Sets initial cross coupling errors.
1794      *
1795      * @param initialMxy initial x-y cross coupling error.
1796      * @param initialMxz initial x-z cross coupling error.
1797      * @param initialMyx initial y-x cross coupling error.
1798      * @param initialMyz initial y-z cross coupling error.
1799      * @param initialMzx initial z-x cross coupling error.
1800      * @param initialMzy initial z-y cross coupling error.
1801      * @throws LockedException if calibrator is currently running.
1802      */
1803     @Override
1804     public void setInitialCrossCouplingErrors(
1805             final double initialMxy, final double initialMxz, final double initialMyx,
1806             final double initialMyz, final double initialMzx, final double initialMzy) throws LockedException {
1807         if (running) {
1808             throw new LockedException();
1809         }
1810         this.initialMxy = initialMxy;
1811         this.initialMxz = initialMxz;
1812         this.initialMyx = initialMyx;
1813         this.initialMyz = initialMyz;
1814         this.initialMzx = initialMzx;
1815         this.initialMzy = initialMzy;
1816     }
1817 
1818     /**
1819      * Sets initial scaling factors and cross coupling errors.
1820      *
1821      * @param initialSx  initial x scaling factor.
1822      * @param initialSy  initial y scaling factor.
1823      * @param initialSz  initial z scaling factor.
1824      * @param initialMxy initial x-y cross coupling error.
1825      * @param initialMxz initial x-z cross coupling error.
1826      * @param initialMyx initial y-x cross coupling error.
1827      * @param initialMyz initial y-z cross coupling error.
1828      * @param initialMzx initial z-x cross coupling error.
1829      * @param initialMzy initial z-y cross coupling error.
1830      * @throws LockedException if calibrator is currently running.
1831      */
1832     @Override
1833     public void setInitialScalingFactorsAndCrossCouplingErrors(
1834             final double initialSx, final double initialSy, final double initialSz,
1835             final double initialMxy, final double initialMxz, final double initialMyx,
1836             final double initialMyz, final double initialMzx, final double initialMzy) throws LockedException {
1837         if (running) {
1838             throw new LockedException();
1839         }
1840         setInitialScalingFactors(initialSx, initialSy, initialSz);
1841         setInitialCrossCouplingErrors(initialMxy, initialMxz, initialMyx, initialMyz, initialMzx, initialMzy);
1842     }
1843 
1844     /**
1845      * Gets known hard-iron bias as an array.
1846      * Array values are expressed in Teslas (T).
1847      *
1848      * @return array containing coordinates of known bias.
1849      */
1850     @Override
1851     public double[] getHardIron() {
1852         final var result = new double[BodyMagneticFluxDensity.COMPONENTS];
1853         getHardIron(result);
1854         return result;
1855     }
1856 
1857     /**
1858      * Gets known hard-iron bias as an array.
1859      * Array values are expressed in Teslas (T).
1860      *
1861      * @param result instance where result data will be copied to.
1862      * @throws IllegalArgumentException if provided array does not have
1863      *                                  length 3.
1864      */
1865     @Override
1866     public void getHardIron(final double[] result) {
1867         if (result.length != BodyMagneticFluxDensity.COMPONENTS) {
1868             throw new IllegalArgumentException();
1869         }
1870         result[0] = hardIronX;
1871         result[1] = hardIronY;
1872         result[2] = hardIronZ;
1873     }
1874 
1875     /**
1876      * Sets known hard-iron bias as an array.
1877      * Array values are expressed in Teslas (T).
1878      *
1879      * @param hardIron known hard-iron.
1880      * @throws LockedException          if calibrator is currently running.
1881      * @throws IllegalArgumentException if provided array does not have length 3.
1882      */
1883     @Override
1884     public void setHardIron(final double[] hardIron) throws LockedException {
1885         if (running) {
1886             throw new LockedException();
1887         }
1888 
1889         if (hardIron.length != BodyMagneticFluxDensity.COMPONENTS) {
1890             throw new IllegalArgumentException();
1891         }
1892         hardIronX = hardIron[0];
1893         hardIronY = hardIron[1];
1894         hardIronZ = hardIron[2];
1895     }
1896 
1897     /**
1898      * Gets known hard-iron bias as a column matrix.
1899      *
1900      * @return known hard-iron bias as a column matrix.
1901      */
1902     @Override
1903     public Matrix getHardIronMatrix() {
1904         Matrix result;
1905         try {
1906             result = new Matrix(BodyMagneticFluxDensity.COMPONENTS, 1);
1907             getHardIronMatrix(result);
1908         } catch (final WrongSizeException ignore) {
1909             // never happens
1910             result = null;
1911         }
1912         return result;
1913     }
1914 
1915     /**
1916      * Gets known hard-iron bias as a column matrix.
1917      *
1918      * @param result instance where result data will be copied to.
1919      * @throws IllegalArgumentException if provided matrix is not 3x1.
1920      */
1921     @Override
1922     public void getHardIronMatrix(final Matrix result) {
1923         if (result.getRows() != BodyMagneticFluxDensity.COMPONENTS || result.getColumns() != 1) {
1924             throw new IllegalArgumentException();
1925         }
1926         result.setElementAtIndex(0, hardIronX);
1927         result.setElementAtIndex(1, hardIronY);
1928         result.setElementAtIndex(2, hardIronZ);
1929     }
1930 
1931     /**
1932      * Sets known hard-iron bias as a column matrix.
1933      *
1934      * @param hardIron known hard-iron bias.
1935      * @throws LockedException          if calibrator is currently running.
1936      * @throws IllegalArgumentException if provided matrix is not 3x1.
1937      */
1938     @Override
1939     public void setHardIron(final Matrix hardIron) throws LockedException {
1940         if (running) {
1941             throw new LockedException();
1942         }
1943         if (hardIron.getRows() != BodyMagneticFluxDensity.COMPONENTS || hardIron.getColumns() != 1) {
1944             throw new IllegalArgumentException();
1945         }
1946 
1947         hardIronX = hardIron.getElementAtIndex(0);
1948         hardIronY = hardIron.getElementAtIndex(1);
1949         hardIronZ = hardIron.getElementAtIndex(2);
1950     }
1951 
1952     /**
1953      * Gets initial scale factors and cross coupling errors matrix.
1954      *
1955      * @return initial scale factors and cross coupling errors matrix.
1956      */
1957     @Override
1958     public Matrix getInitialMm() {
1959         Matrix result;
1960         try {
1961             result = new Matrix(BodyMagneticFluxDensity.COMPONENTS, BodyMagneticFluxDensity.COMPONENTS);
1962             getInitialMm(result);
1963         } catch (final WrongSizeException ignore) {
1964             // never happens
1965             result = null;
1966         }
1967         return result;
1968     }
1969 
1970     /**
1971      * Gets initial scale factors and cross coupling errors matrix.
1972      *
1973      * @param result instance where data will be stored.
1974      * @throws IllegalArgumentException if provided matrix is not 3x3.
1975      */
1976     @Override
1977     public void getInitialMm(final Matrix result) {
1978         if (result.getRows() != BodyKinematics.COMPONENTS || result.getColumns() != BodyKinematics.COMPONENTS) {
1979             throw new IllegalArgumentException();
1980         }
1981         result.setElementAtIndex(0, initialSx);
1982         result.setElementAtIndex(1, initialMyx);
1983         result.setElementAtIndex(2, initialMzx);
1984 
1985         result.setElementAtIndex(3, initialMxy);
1986         result.setElementAtIndex(4, initialSy);
1987         result.setElementAtIndex(5, initialMzy);
1988 
1989         result.setElementAtIndex(6, initialMxz);
1990         result.setElementAtIndex(7, initialMyz);
1991         result.setElementAtIndex(8, initialSz);
1992     }
1993 
1994     /**
1995      * Sets initial scale factors and cross coupling errors matrix.
1996      *
1997      * @param initialMm initial scale factors and cross coupling errors matrix.
1998      * @throws IllegalArgumentException if provided matrix is not 3x3.
1999      * @throws LockedException          if calibrator is currently running.
2000      */
2001     @Override
2002     public void setInitialMm(final Matrix initialMm) throws LockedException {
2003         if (running) {
2004             throw new LockedException();
2005         }
2006         if (initialMm.getRows() != BodyKinematics.COMPONENTS || initialMm.getColumns() != BodyKinematics.COMPONENTS) {
2007             throw new IllegalArgumentException();
2008         }
2009 
2010         initialSx = initialMm.getElementAtIndex(0);
2011         initialMyx = initialMm.getElementAtIndex(1);
2012         initialMzx = initialMm.getElementAtIndex(2);
2013 
2014         initialMxy = initialMm.getElementAtIndex(3);
2015         initialSy = initialMm.getElementAtIndex(4);
2016         initialMzy = initialMm.getElementAtIndex(5);
2017 
2018         initialMxz = initialMm.getElementAtIndex(6);
2019         initialMyz = initialMm.getElementAtIndex(7);
2020         initialSz = initialMm.getElementAtIndex(8);
2021     }
2022 
2023     /**
2024      * Gets position where body magnetic flux density measurements have been
2025      * taken.
2026      *
2027      * @return position where body magnetic flux density measurements have
2028      * been taken.
2029      */
2030     public NEDPosition getNedPosition() {
2031         return position;
2032     }
2033 
2034     /**
2035      * Sets position where body magnetic flux density measurements have been
2036      * taken.
2037      *
2038      * @param position position where body magnetic flux density measurements
2039      *                 have been taken.
2040      * @throws LockedException if calibrator is currently running.
2041      */
2042     public void setPosition(final NEDPosition position) throws LockedException {
2043         if (running) {
2044             throw new LockedException();
2045         }
2046 
2047         this.position = position;
2048     }
2049 
2050     /**
2051      * Gets position where body magnetic flux density measurements have been
2052      * taken expressed in ECEF coordinates.
2053      *
2054      * @return position where body magnetic flux density measurements have
2055      * been taken or null if not available.
2056      */
2057     public ECEFPosition getEcefPosition() {
2058         if (position != null) {
2059             final var result = new ECEFPosition();
2060             getEcefPosition(result);
2061             return result;
2062         } else {
2063             return null;
2064         }
2065     }
2066 
2067     /**
2068      * Gets position where body magnetic flux density measurements have been
2069      * taken expressed in ECEF coordinates.
2070      *
2071      * @param result instance where result will be stored.
2072      * @return true if ECEF position could be computed, false otherwise.
2073      */
2074     public boolean getEcefPosition(final ECEFPosition result) {
2075 
2076         if (position != null) {
2077             final var velocity = new ECEFVelocity();
2078             NEDtoECEFPositionVelocityConverter.convertNEDtoECEF(
2079                     position.getLatitude(), position.getLongitude(), position.getHeight(),
2080                     0.0, 0.0, 0.0, result, velocity);
2081             return true;
2082         } else {
2083             return false;
2084         }
2085     }
2086 
2087     /**
2088      * Sets position where body magnetic flux density measurements have been
2089      * taken expressed in ECEF coordinates.
2090      *
2091      * @param position position where body magnetic flux density have been
2092      *                 taken.
2093      * @throws LockedException if calibrator is currently running.
2094      */
2095     public void setPosition(final ECEFPosition position) throws LockedException {
2096         if (running) {
2097             throw new LockedException();
2098         }
2099 
2100         this.position = convertPosition(position);
2101     }
2102 
2103     /**
2104      * Gets timestamp expressed as decimal year where magnetic flux density
2105      * measurements have been measured.
2106      *
2107      * @return timestamp expressed as decimal year or null if not defined.
2108      */
2109     public Double getYear() {
2110         return year;
2111     }
2112 
2113     /**
2114      * Sets timestamp expressed as decimal year where magnetic flux density
2115      * measurements have been measured.
2116      *
2117      * @param year timestamp expressed as decimal year.
2118      * @throws LockedException if calibrator is currently running.
2119      */
2120     public void setYear(final Double year) throws LockedException {
2121         if (running) {
2122             throw new LockedException();
2123         }
2124         this.year = year;
2125     }
2126 
2127     /**
2128      * Sets timestamp when magnetic flux density measurements have been
2129      * measured.
2130      *
2131      * @param timestampMillis a timestamp expressed in milliseconds since
2132      *                        epoch time (January 1st, 1970 at midnight).
2133      * @throws LockedException if calibrator is currently running.
2134      */
2135     public void setTime(final Long timestampMillis) throws LockedException {
2136         if (running) {
2137             throw new LockedException();
2138         }
2139         year = convertTime(timestampMillis);
2140     }
2141 
2142     /**
2143      * Sets timestamp when magnetic flux density measurements have been
2144      * measured.
2145      *
2146      * @param date a date instance containing a timestamp.
2147      * @throws LockedException if calibrator is currently running.
2148      */
2149     public void setTime(final Date date) throws LockedException {
2150         if (running) {
2151             throw new LockedException();
2152         }
2153         year = convertTime(date);
2154     }
2155 
2156     /**
2157      * Sets timestamp when magnetic flux density measurements have been
2158      * measured.
2159      *
2160      * @param calendar a calendar instance containing a timestamp.
2161      * @throws LockedException if calibrator is currently running.
2162      */
2163     public void setTime(final GregorianCalendar calendar) throws LockedException {
2164         if (running) {
2165             throw new LockedException();
2166         }
2167         year = convertTime(calendar);
2168     }
2169 
2170     /**
2171      * Gets collection of body magnetic flux density measurements taken
2172      * at a given position with different unknown orientations and containing the
2173      * standard deviation of magnetometer measurements.
2174      *
2175      * @return collection of body magnetic flux density measurements at
2176      * a known position and timestamp with unknown orientations.
2177      */
2178     @Override
2179     public List<StandardDeviationBodyMagneticFluxDensity> getMeasurements() {
2180         return measurements;
2181     }
2182 
2183     /**
2184      * Sets collection of body magnetic flux density measurements taken
2185      * at a given position with different unknown orientations and containing the
2186      * standard deviation of magnetometer measurements.
2187      *
2188      * @param measurements collection of body magnetic flux density
2189      *                     measurements at a known position and timestamp
2190      *                     with unknown orientations.
2191      * @throws LockedException if calibrator is currently running.
2192      */
2193     @Override
2194     public void setMeasurements(final List<StandardDeviationBodyMagneticFluxDensity> measurements)
2195             throws LockedException {
2196         if (running) {
2197             throw new LockedException();
2198         }
2199         this.measurements = measurements;
2200     }
2201 
2202     /**
2203      * Indicates the type of measurement used by this calibrator.
2204      *
2205      * @return type of measurement used by this calibrator.
2206      */
2207     @Override
2208     public MagnetometerCalibratorMeasurementType getMeasurementType() {
2209         return MagnetometerCalibratorMeasurementType.STANDARD_DEVIATION_BODY_MAGNETIC_FLUX_DENSITY;
2210     }
2211 
2212     /**
2213      * Indicates whether this calibrator requires ordered measurements in a
2214      * list or not.
2215      *
2216      * @return true if measurements must be ordered, false otherwise.
2217      */
2218     @Override
2219     public boolean isOrderedMeasurementsRequired() {
2220         return true;
2221     }
2222 
2223     /**
2224      * Indicates whether z-axis is assumed to be common for accelerometer,
2225      * gyroscope and magnetometer.
2226      * When enabled, this eliminates 3 variables from Mm (soft-iron) matrix.
2227      *
2228      * @return true if z-axis is assumed to be common for accelerometer,
2229      * gyroscope and magnetometer, false otherwise.
2230      */
2231     @Override
2232     public boolean isCommonAxisUsed() {
2233         return commonAxisUsed;
2234     }
2235 
2236     /**
2237      * Specifies whether z-axis is assumed to be common for accelerometer and
2238      * gyroscope.
2239      * When enabled, this eliminates 3 variables from Mm matrix.
2240      *
2241      * @param commonAxisUsed true if z-axis is assumed to be common for
2242      *                       accelerometer, gyroscope and magnetometer, false
2243      *                       otherwise.
2244      * @throws LockedException if estimator is currently running.
2245      */
2246     @Override
2247     public void setCommonAxisUsed(final boolean commonAxisUsed) throws LockedException {
2248         if (running) {
2249             throw new LockedException();
2250         }
2251 
2252         this.commonAxisUsed = commonAxisUsed;
2253     }
2254 
2255     /**
2256      * Gets listener to handle events raised by this calibrator.
2257      *
2258      * @return listener to handle events raised by this calibrator.
2259      */
2260     public RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener getListener() {
2261         return listener;
2262     }
2263 
2264     /**
2265      * Sets listener to handle events raised by this calibrator.
2266      *
2267      * @param listener listener to handle events raised by this calibrator.
2268      * @throws LockedException if calibrator is currently running.
2269      */
2270     public void setListener(final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener)
2271             throws LockedException {
2272         if (running) {
2273             throw new LockedException();
2274         }
2275 
2276         this.listener = listener;
2277     }
2278 
2279     /**
2280      * Gets minimum number of required measurements.
2281      *
2282      * @return minimum number of required measurements.
2283      */
2284     @Override
2285     public int getMinimumRequiredMeasurements() {
2286         return commonAxisUsed ? MINIMUM_MEASUREMENTS_COMMON_Z_AXIS : MINIMUM_MEASUREMENTS_GENERAL;
2287     }
2288 
2289     /**
2290      * Indicates whether calibrator is ready to start the estimator.
2291      *
2292      * @return true if calibrator is ready, false otherwise.
2293      */
2294     @Override
2295     public boolean isReady() {
2296         return measurements != null && measurements.size() >= getMinimumRequiredMeasurements()
2297                 && position != null && year != null;
2298     }
2299 
2300     /**
2301      * Indicates whether calibrator is currently running or no.
2302      *
2303      * @return true if calibrator is running, false otherwise.
2304      */
2305     @Override
2306     public boolean isRunning() {
2307         return running;
2308     }
2309 
2310     /**
2311      * Gets Earth's magnetic model.
2312      *
2313      * @return Earth's magnetic model or null if not provided.
2314      */
2315     public WorldMagneticModel getMagneticModel() {
2316         return magneticModel;
2317     }
2318 
2319     /**
2320      * Sets Earth's magnetic model.
2321      *
2322      * @param magneticModel Earth's magnetic model to be set.
2323      * @throws LockedException if calibrator is currently running.
2324      */
2325     public void setMagneticModel(final WorldMagneticModel magneticModel) throws LockedException {
2326         if (running) {
2327             throw new LockedException();
2328         }
2329         this.magneticModel = magneticModel;
2330     }
2331 
2332     /**
2333      * Returns amount of progress variation before notifying a progress change during
2334      * calibration.
2335      *
2336      * @return amount of progress variation before notifying a progress change during
2337      * calibration.
2338      */
2339     public float getProgressDelta() {
2340         return progressDelta;
2341     }
2342 
2343     /**
2344      * Sets amount of progress variation before notifying a progress change during
2345      * calibration.
2346      *
2347      * @param progressDelta amount of progress variation before notifying a progress
2348      *                      change during calibration.
2349      * @throws IllegalArgumentException if progress delta is less than zero or greater than 1.
2350      * @throws LockedException          if calibrator is currently running.
2351      */
2352     public void setProgressDelta(final float progressDelta) throws LockedException {
2353         if (running) {
2354             throw new LockedException();
2355         }
2356         if (progressDelta < MIN_PROGRESS_DELTA || progressDelta > MAX_PROGRESS_DELTA) {
2357             throw new IllegalArgumentException();
2358         }
2359         this.progressDelta = progressDelta;
2360     }
2361 
2362     /**
2363      * Returns amount of confidence expressed as a value between 0.0 and 1.0
2364      * (which is equivalent to 100%). The amount of confidence indicates the probability
2365      * that the estimated result is correct. Usually this value will be close to 1.0, but
2366      * not exactly 1.0.
2367      *
2368      * @return amount of confidence as a value between 0.0 and 1.0.
2369      */
2370     public double getConfidence() {
2371         return confidence;
2372     }
2373 
2374     /**
2375      * Sets amount of confidence expressed as a value between 0.0 and 1.0 (which is
2376      * equivalent to 100%). The amount of confidence indicates the probability that
2377      * the estimated result is correct. Usually this value will be close to 1.0, but
2378      * not exactly 1.0.
2379      *
2380      * @param confidence confidence to be set as a value between 0.0 and 1.0.
2381      * @throws IllegalArgumentException if provided value is not between 0.0 and 1.0.
2382      * @throws LockedException          if calibrator is currently running.
2383      */
2384     public void setConfidence(final double confidence) throws LockedException {
2385         if (running) {
2386             throw new LockedException();
2387         }
2388         if (confidence < MIN_CONFIDENCE || confidence > MAX_CONFIDENCE) {
2389             throw new IllegalArgumentException();
2390         }
2391         this.confidence = confidence;
2392     }
2393 
2394     /**
2395      * Returns maximum allowed number of iterations. If maximum allowed number of
2396      * iterations is achieved without converging to a result when calling calibrate(),
2397      * a RobustEstimatorException will be raised.
2398      *
2399      * @return maximum allowed number of iterations.
2400      */
2401     public int getMaxIterations() {
2402         return maxIterations;
2403     }
2404 
2405     /**
2406      * Sets maximum allowed number of iterations. When the maximum number of iterations
2407      * is exceeded, result will not be available, however an approximate result will be
2408      * available for retrieval.
2409      *
2410      * @param maxIterations maximum allowed number of iterations to be set.
2411      * @throws IllegalArgumentException if provided value is less than 1.
2412      * @throws LockedException          if calibrator is currently running.
2413      */
2414     public void setMaxIterations(final int maxIterations) throws LockedException {
2415         if (running) {
2416             throw new LockedException();
2417         }
2418         if (maxIterations < MIN_ITERATIONS) {
2419             throw new IllegalArgumentException();
2420         }
2421         this.maxIterations = maxIterations;
2422     }
2423 
2424     /**
2425      * Gets data related to inliers found after estimation.
2426      *
2427      * @return data related to inliers found after estimation.
2428      */
2429     public InliersData getInliersData() {
2430         return inliersData;
2431     }
2432 
2433     /**
2434      * Indicates whether result must be refined using a non-linear solver over found inliers.
2435      *
2436      * @return true to refine result, false to simply use result found by robust estimator
2437      * without further refining.
2438      */
2439     public boolean isResultRefined() {
2440         return refineResult;
2441     }
2442 
2443     /**
2444      * Specifies whether result must be refined using a non-linear solver over found inliers.
2445      *
2446      * @param refineResult true to refine result, false to simply use result found by robust
2447      *                     estimator without further refining.
2448      * @throws LockedException if calibrator is currently running.
2449      */
2450     public void setResultRefined(final boolean refineResult) throws LockedException {
2451         if (running) {
2452             throw new LockedException();
2453         }
2454         this.refineResult = refineResult;
2455     }
2456 
2457     /**
2458      * Indicates whether covariance must be kept after refining result.
2459      * This setting is only taken into account if result is refined.
2460      *
2461      * @return true if covariance must be kept after refining result, false otherwise.
2462      */
2463     public boolean isCovarianceKept() {
2464         return keepCovariance;
2465     }
2466 
2467     /**
2468      * Specifies whether covariance must be kept after refining result.
2469      * This setting is only taken into account if result is refined.
2470      *
2471      * @param keepCovariance true if covariance must be kept after refining result,
2472      *                       false otherwise.
2473      * @throws LockedException if calibrator is currently running.
2474      */
2475     public void setCovarianceKept(final boolean keepCovariance) throws LockedException {
2476         if (running) {
2477             throw new LockedException();
2478         }
2479         this.keepCovariance = keepCovariance;
2480     }
2481 
2482     /**
2483      * Returns quality scores corresponding to each measurement.
2484      * The larger the score value the better the quality of the sample.
2485      * This implementation always returns null.
2486      * Subclasses using quality scores must implement proper behavior.
2487      *
2488      * @return quality scores corresponding to each sample.
2489      */
2490     @Override
2491     public double[] getQualityScores() {
2492         return null;
2493     }
2494 
2495     /**
2496      * Sets quality scores corresponding to each measurement.
2497      * The larger the score value the better the quality of the sample.
2498      * This implementation makes no action.
2499      * Subclasses using quality scores must implement proper behaviour.
2500      *
2501      * @param qualityScores quality scores corresponding to each pair of
2502      *                      matched points.
2503      * @throws IllegalArgumentException if provided quality scores length
2504      *                                  is smaller than minimum required samples.
2505      * @throws LockedException          if calibrator is currently running.
2506      */
2507     @Override
2508     public void setQualityScores(final double[] qualityScores) throws LockedException {
2509     }
2510 
2511     /**
2512      * Gets estimated magnetometer soft-iron matrix containing scale factors
2513      * and cross coupling errors.
2514      * This is the product of matrix Tm containing cross coupling errors and Km
2515      * containing scaling factors.
2516      * So tat:
2517      * <pre>
2518      *     Mm = [sx    mxy  mxz] = Tm*Km
2519      *          [myx   sy   myz]
2520      *          [mzx   mzy  sz ]
2521      * </pre>
2522      * Where:
2523      * <pre>
2524      *     Km = [sx 0   0 ]
2525      *          [0  sy  0 ]
2526      *          [0  0   sz]
2527      * </pre>
2528      * and
2529      * <pre>
2530      *     Tm = [1          -alphaXy    alphaXz ]
2531      *          [alphaYx    1           -alphaYz]
2532      *          [-alphaZx   alphaZy     1       ]
2533      * </pre>
2534      * Hence:
2535      * <pre>
2536      *     Mm = [sx    mxy  mxz] = Tm*Km =  [sx             -sy * alphaXy   sz * alphaXz ]
2537      *          [myx   sy   myz]            [sx * alphaYx   sy              -sz * alphaYz]
2538      *          [mzx   mzy  sz ]            [-sx * alphaZx  sy * alphaZy    sz           ]
2539      * </pre>
2540      * This instance allows any 3x3 matrix however, typically alphaYx, alphaZx and alphaZy
2541      * are considered to be zero if the accelerometer z-axis is assumed to be the same
2542      * as the body z-axis. When this is assumed, myx = mzx = mzy = 0 and the Mm matrix
2543      * becomes upper diagonal:
2544      * <pre>
2545      *     Mm = [sx    mxy  mxz]
2546      *          [0     sy   myz]
2547      *          [0     0    sz ]
2548      * </pre>
2549      * Values of this matrix are unit-less.
2550      *
2551      * @return estimated magnetometer soft-iron scale factors and cross coupling errors,
2552      * or null if not available.
2553      */
2554     @Override
2555     public Matrix getEstimatedMm() {
2556         return estimatedMm;
2557     }
2558 
2559     /**
2560      * Gets estimated x-axis scale factor.
2561      *
2562      * @return estimated x-axis scale factor or null if not available.
2563      */
2564     @Override
2565     public Double getEstimatedSx() {
2566         return estimatedMm != null ? estimatedMm.getElementAt(0, 0) : null;
2567     }
2568 
2569     /**
2570      * Gets estimated y-axis scale factor.
2571      *
2572      * @return estimated y-axis scale factor or null if not available.
2573      */
2574     @Override
2575     public Double getEstimatedSy() {
2576         return estimatedMm != null ? estimatedMm.getElementAt(1, 1) : null;
2577     }
2578 
2579     /**
2580      * Gets estimated z-axis scale factor.
2581      *
2582      * @return estimated z-axis scale factor or null if not available.
2583      */
2584     @Override
2585     public Double getEstimatedSz() {
2586         return estimatedMm != null ? estimatedMm.getElementAt(2, 2) : null;
2587     }
2588 
2589     /**
2590      * Gets estimated x-y cross-coupling error.
2591      *
2592      * @return estimated x-y cross-coupling error or null if not available.
2593      */
2594     @Override
2595     public Double getEstimatedMxy() {
2596         return estimatedMm != null ? estimatedMm.getElementAt(0, 1) : null;
2597     }
2598 
2599     /**
2600      * Gets estimated x-z cross-coupling error.
2601      *
2602      * @return estimated x-z cross-coupling error or null if not available.
2603      */
2604     @Override
2605     public Double getEstimatedMxz() {
2606         return estimatedMm != null ? estimatedMm.getElementAt(0, 2) : null;
2607     }
2608 
2609     /**
2610      * Gets estimated y-x cross-coupling error.
2611      *
2612      * @return estimated y-x cross-coupling error or null if not available.
2613      */
2614     @Override
2615     public Double getEstimatedMyx() {
2616         return estimatedMm != null ? estimatedMm.getElementAt(1, 0) : null;
2617     }
2618 
2619     /**
2620      * Gets estimated y-z cross-coupling error.
2621      *
2622      * @return estimated y-z cross-coupling error or null if not available.
2623      */
2624     @Override
2625     public Double getEstimatedMyz() {
2626         return estimatedMm != null ? estimatedMm.getElementAt(1, 2) : null;
2627     }
2628 
2629     /**
2630      * Gets estimated z-x cross-coupling error.
2631      *
2632      * @return estimated z-x cross-coupling error or null if not available.
2633      */
2634     @Override
2635     public Double getEstimatedMzx() {
2636         return estimatedMm != null ? estimatedMm.getElementAt(2, 0) : null;
2637     }
2638 
2639     /**
2640      * Gets estimated z-y cross-coupling error.
2641      *
2642      * @return estimated z-y cross-coupling error or null if not available.
2643      */
2644     @Override
2645     public Double getEstimatedMzy() {
2646         return estimatedMm != null ? estimatedMm.getElementAt(2, 1) : null;
2647     }
2648 
2649     /**
2650      * Gets estimated chi square value.
2651      *
2652      * @return estimated chi square value.
2653      */
2654     @Override
2655     public double getEstimatedChiSq() {
2656         return estimatedChiSq;
2657     }
2658 
2659     /**
2660      * Gets estimated chi square degrees of freedom. Degrees of freedom is equal to the number of sampled data minus the
2661      * number of estimated parameters.
2662      *
2663      * @return estimated degrees of freedom of chi square value
2664      */
2665     @Override
2666     public int getEstimatedChiSqDegreesOfFreedom() {
2667         return estimatedChiSqDegreesOfFreedom;
2668     }
2669 
2670     /**
2671      * Gets estimated reduced chi square value. This is equal to estimated chi square value divided by its degrees of
2672      * freedom. Ideally this value should be close to 1.0, indicating that fit is optimal.
2673      * A value larger than 1.0 indicates that fit is not good or noise has been underestimated, and a value smaller than
2674      * 1.0 indicates that there is overfitting or noise has been overestimated.
2675      *
2676      * @return estimated reduced chi square value
2677      */
2678     @Override
2679     public double getEstimatedReducedChiSq() {
2680         return estimatedReducedChiSq;
2681     }
2682 
2683     /**
2684      * Gets estimated mean square error respect to provided measurements.
2685      *
2686      * @return estimated mean square error respect to provided measurements.
2687      */
2688     @Override
2689     public double getEstimatedMse() {
2690         return estimatedMse;
2691     }
2692 
2693     /**
2694      * Gets estimated probability of finding a smaller chi square value expressed as a value between 0.0 and 1.0. The
2695      * smaller the found chi square value is, the better the fit of the estimated parameters to the actual parameter.
2696      * Thus, the smaller the chance of finding a smaller chi square value, then the better the estimated fit is.
2697      *
2698      * @return estimated probability of finding a smaller chi square value.
2699      */
2700     @Override
2701     public double getEstimatedP() {
2702         return estimatedP;
2703     }
2704 
2705     /**
2706      * Gets estimated measure of quality of estimated fit as a value between 0.0 and 1.0. The larger the quality value
2707      * is, the better the fit that has been estimated.
2708      *
2709      * @return estimated measure of quality of estimated fit.
2710      */
2711     @Override
2712     public double getEstimatedQ() {
2713         return estimatedQ;
2714     }
2715 
2716     /**
2717      * Gets estimated covariance matrix for estimated calibration parameters.
2718      * Diagonal elements of the matrix contains variance for the following
2719      * parameters (following indicated order): sx, sy, sz, mxy, mxz, myx,
2720      * myz, mzx, mzy.
2721      *
2722      * @return estimated covariance matrix for estimated position.
2723      */
2724     @Override
2725     public Matrix getEstimatedCovariance() {
2726         return estimatedCovariance;
2727     }
2728 
2729     /**
2730      * Gets size of subsets to be checked during robust estimation.
2731      * This has to be at least {@link #MINIMUM_MEASUREMENTS_COMMON_Z_AXIS}.
2732      *
2733      * @return size of subsets to be checked during robust estimation.
2734      */
2735     public int getPreliminarySubsetSize() {
2736         return preliminarySubsetSize;
2737     }
2738 
2739     /**
2740      * Sets size of subsets to be checked during robust estimation.
2741      * This has to be at least {@link #MINIMUM_MEASUREMENTS_COMMON_Z_AXIS}.
2742      *
2743      * @param preliminarySubsetSize size of subsets to be checked during robust estimation.
2744      * @throws LockedException          if calibrator is currently running.
2745      * @throws IllegalArgumentException if provided value is less than {@link #MINIMUM_MEASUREMENTS_COMMON_Z_AXIS}.
2746      */
2747     public void setPreliminarySubsetSize(final int preliminarySubsetSize) throws LockedException {
2748         if (running) {
2749             throw new LockedException();
2750         }
2751         if (preliminarySubsetSize < MINIMUM_MEASUREMENTS_COMMON_Z_AXIS) {
2752             throw new IllegalArgumentException();
2753         }
2754 
2755         this.preliminarySubsetSize = preliminarySubsetSize;
2756     }
2757 
2758     /**
2759      * Returns method being used for robust estimation.
2760      *
2761      * @return method being used for robust estimation.
2762      */
2763     public abstract RobustEstimatorMethod getMethod();
2764 
2765     /**
2766      * Creates a robust magnetometer calibrator.
2767      *
2768      * @param method robust estimator method.
2769      * @return a robust magnetometer calibrator.
2770      */
2771     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
2772             final RobustEstimatorMethod method) {
2773         return switch (method) {
2774             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator();
2775             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator();
2776             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator();
2777             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator();
2778             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator();
2779         };
2780     }
2781 
2782     /**
2783      * Creates a robust magnetometer calibrator.
2784      *
2785      * @param listener listener to handle events raised by this calibrator.
2786      * @param method   robust estimator method.
2787      * @return a robust magnetometer calibrator.
2788      */
2789     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
2790             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
2791             final RobustEstimatorMethod method) {
2792         return switch (method) {
2793             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(listener);
2794             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(listener);
2795             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(listener);
2796             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(listener);
2797             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(listener);
2798         };
2799     }
2800 
2801     /**
2802      * Creates a robust magnetometer calibrator.
2803      *
2804      * @param measurements list of body magnetic flux density
2805      *                     measurements with standard deviation of
2806      *                     magnetometer measurements taken at the same
2807      *                     position with zero velocity and unknown different
2808      *                     orientations.
2809      * @param method       robust estimator method.
2810      * @return a robust magnetometer calibrator.
2811      */
2812     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
2813             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final RobustEstimatorMethod method) {
2814         return switch (method) {
2815             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(measurements);
2816             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(measurements);
2817             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(measurements);
2818             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(measurements);
2819             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(measurements);
2820         };
2821     }
2822 
2823     /**
2824      * Creates a robust magnetometer calibrator.
2825      *
2826      * @param commonAxisUsed indicates whether z-axis is assumed to be common
2827      *                       for the accelerometer, gyroscope and magnetometer.
2828      * @param method         robust estimator method.
2829      * @return a robust magnetometer calibrator.
2830      */
2831     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
2832             final boolean commonAxisUsed, final RobustEstimatorMethod method) {
2833         return switch (method) {
2834             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(commonAxisUsed);
2835             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(commonAxisUsed);
2836             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(commonAxisUsed);
2837             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(commonAxisUsed);
2838             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(commonAxisUsed);
2839         };
2840     }
2841 
2842     /**
2843      * Creates a robust magnetometer calibrator.
2844      *
2845      * @param magneticModel Earth's magnetic model. If null, a default model
2846      *                      will be used instead.
2847      * @param method        robust estimator method.
2848      * @return a robust magnetometer calibrator.
2849      */
2850     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
2851             final WorldMagneticModel magneticModel, final RobustEstimatorMethod method) {
2852         return switch (method) {
2853             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(magneticModel);
2854             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(magneticModel);
2855             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(magneticModel);
2856             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(magneticModel);
2857             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(magneticModel);
2858         };
2859     }
2860 
2861     /**
2862      * Creates a robust magnetometer calibrator.
2863      *
2864      * @param hardIron known hard-iron.
2865      * @param method   robust estimator method.
2866      * @return a robust magnetometer calibrator.
2867      * @throws IllegalArgumentException if provided hard-iron array does
2868      *                                  not have length 3.
2869      */
2870     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
2871             final double[] hardIron, final RobustEstimatorMethod method) {
2872         return switch (method) {
2873             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron);
2874             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron);
2875             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron);
2876             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron);
2877             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron);
2878         };
2879     }
2880 
2881     /**
2882      * Creates a robust magnetometer calibrator.
2883      *
2884      * @param hardIron known hard-iron.
2885      * @param method   robust estimator method.
2886      * @return a robust magnetometer calibrator.
2887      * @throws IllegalArgumentException if provided hard-iron matrix is not
2888      *                                  3x1.
2889      */
2890     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
2891             final Matrix hardIron, final RobustEstimatorMethod method) {
2892         return switch (method) {
2893             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron);
2894             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron);
2895             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron);
2896             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron);
2897             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron);
2898         };
2899     }
2900 
2901     /**
2902      * Creates a robust magnetometer calibrator.
2903      *
2904      * @param hardIron  known hard-iron.
2905      * @param initialMm initial soft-iron matrix containing scale factors
2906      *                  and cross coupling errors.
2907      * @param method    robust estimator method.
2908      * @return a robust magnetometer calibrator.
2909      * @throws IllegalArgumentException if provided hard-iron matrix is not
2910      *                                  3x1 or if soft-iron matrix is not
2911      *                                  3x3.
2912      */
2913     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
2914             final Matrix hardIron, final Matrix initialMm, final RobustEstimatorMethod method) {
2915         return switch (method) {
2916             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron, initialMm);
2917             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron, initialMm);
2918             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron, initialMm);
2919             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron, initialMm);
2920             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron, initialMm);
2921         };
2922     }
2923 
2924     /**
2925      * Creates a robust magnetometer calibrator.
2926      *
2927      * @param position position where body magnetic flux density measurements
2928      *                 have been taken.
2929      * @param method   robust estimator method.
2930      * @return a robust magnetometer calibrator.
2931      */
2932     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
2933             final NEDPosition position, final RobustEstimatorMethod method) {
2934         return switch (method) {
2935             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(position);
2936             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(position);
2937             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(position);
2938             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(position);
2939             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(position);
2940         };
2941     }
2942 
2943     /**
2944      * Creates a robust magnetometer calibrator.
2945      *
2946      * @param position     position where body magnetic flux density measurements
2947      *                     have been taken.
2948      * @param measurements collection of body magnetic flux density
2949      *                     measurements with standard deviation of
2950      *                     magnetometer measurements taken at the same
2951      *                     position with zero velocity and unknown different
2952      *                     orientations.
2953      * @param method       robust estimator method.
2954      * @return a robust magnetometer calibrator.
2955      */
2956     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
2957             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
2958             final RobustEstimatorMethod method) {
2959         return switch (method) {
2960             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
2961                     position, measurements);
2962             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
2963                     position, measurements);
2964             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
2965                     position, measurements);
2966             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
2967                     position, measurements);
2968             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
2969                     position, measurements);
2970         };
2971     }
2972 
2973     /**
2974      * Creates a robust magnetometer calibrator.
2975      *
2976      * @param position     position where body magnetic flux density measurements
2977      *                     have been taken.
2978      * @param measurements collection of body magnetic flux density
2979      *                     measurements with standard deviation of
2980      *                     magnetometer measurements taken at the same
2981      *                     position with zero velocity and unknown different
2982      *                     orientations.
2983      * @param listener     listener to handle events raised by this calibrator.
2984      * @param method       robust estimator method.
2985      * @return a robust magnetometer calibrator.
2986      */
2987     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
2988             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
2989             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
2990             final RobustEstimatorMethod method) {
2991         return switch (method) {
2992             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
2993                     position, measurements, listener);
2994             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
2995                     position, measurements, listener);
2996             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
2997                     position, measurements, listener);
2998             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
2999                     position, measurements, listener);
3000             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3001                     position, measurements, listener);
3002         };
3003     }
3004 
3005     /**
3006      * Creates a robust magnetometer calibrator.
3007      *
3008      * @param position       position where body magnetic flux density measurements
3009      *                       have been taken.
3010      * @param measurements   collection of body magnetic flux density
3011      *                       measurements with standard deviation of
3012      *                       magnetometer measurements taken at the same
3013      *                       position with zero velocity and unknown different
3014      *                       orientations.
3015      * @param commonAxisUsed indicates whether z-axis is assumed to be common
3016      *                       for the accelerometer, gyroscope and magnetometer.
3017      * @param method         robust estimator method.
3018      * @return a robust magnetometer calibrator.
3019      */
3020     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3021             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3022             final boolean commonAxisUsed, final RobustEstimatorMethod method) {
3023         return switch (method) {
3024             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3025                     position, measurements, commonAxisUsed);
3026             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3027                     position, measurements, commonAxisUsed);
3028             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3029                     position, measurements, commonAxisUsed);
3030             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3031                     position, measurements, commonAxisUsed);
3032             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3033                     position, measurements, commonAxisUsed);
3034         };
3035     }
3036 
3037     /**
3038      * Creates a robust magnetometer calibrator.
3039      *
3040      * @param position       position where body magnetic flux density measurements
3041      *                       have been taken.
3042      * @param measurements   collection of body magnetic flux density
3043      *                       measurements with standard deviation of
3044      *                       magnetometer measurements taken at the same
3045      *                       position with zero velocity and unknown different
3046      *                       orientations.
3047      * @param commonAxisUsed indicates whether z-axis is assumed to be common
3048      *                       for the accelerometer, gyroscope and magnetometer.
3049      * @param listener       listener to handle events raised by this calibrator.
3050      * @param method         robust estimator method.
3051      * @return a robust magnetometer calibrator.
3052      */
3053     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3054             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3055             final boolean commonAxisUsed,
3056             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
3057             final RobustEstimatorMethod method) {
3058         return switch (method) {
3059             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3060                     position, measurements, commonAxisUsed, listener);
3061             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3062                     position, measurements, commonAxisUsed, listener);
3063             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3064                     position, measurements, commonAxisUsed, listener);
3065             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3066                     position, measurements, commonAxisUsed, listener);
3067             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3068                     position, measurements, commonAxisUsed, listener);
3069         };
3070     }
3071 
3072     /**
3073      * Creates a robust magnetometer calibrator.
3074      *
3075      * @param position     position where body magnetic flux density measurements
3076      *                     have been taken.
3077      * @param measurements collection of body magnetic flux density
3078      *                     measurements with standard deviation of
3079      *                     magnetometer measurements taken at the same
3080      *                     position with zero velocity and unknown different
3081      *                     orientations.
3082      * @param hardIron     known hard-iron.
3083      * @param method       robust estimator method.
3084      * @return a robust magnetometer calibrator.
3085      * @throws IllegalArgumentException if provided hard-iron array does
3086      *                                  not have length 3.
3087      */
3088     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3089             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3090             final double[] hardIron, final RobustEstimatorMethod method) {
3091         return switch (method) {
3092             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3093                     position, measurements, hardIron);
3094             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3095                     position, measurements, hardIron);
3096             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3097                     position, measurements, hardIron);
3098             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3099                     position, measurements, hardIron);
3100             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3101                     position, measurements, hardIron);
3102         };
3103     }
3104 
3105     /**
3106      * Creates a robust magnetometer calibrator.
3107      *
3108      * @param position     position where body magnetic flux density measurements
3109      *                     have been taken.
3110      * @param measurements collection of body magnetic flux density
3111      *                     measurements with standard deviation of
3112      *                     magnetometer measurements taken at the same
3113      *                     position with zero velocity and unknown different
3114      *                     orientations.
3115      * @param hardIron     known hard-iron.
3116      * @param listener     listener to handle events raised by this calibrator.
3117      * @param method       robust estimator method.
3118      * @return a robust magnetometer calibrator.
3119      * @throws IllegalArgumentException if provided hard-iron array does
3120      *                                  not have length 3.
3121      */
3122     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3123             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3124             final double[] hardIron, final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
3125             final RobustEstimatorMethod method) {
3126         return switch (method) {
3127             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3128                     position, measurements, hardIron, listener);
3129             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3130                     position, measurements, hardIron, listener);
3131             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3132                     position, measurements, hardIron, listener);
3133             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3134                     position, measurements, hardIron, listener);
3135             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3136                     position, measurements, hardIron, listener);
3137         };
3138     }
3139 
3140     /**
3141      * Creates a robust magnetometer calibrator.
3142      *
3143      * @param position       position where body magnetic flux density measurements
3144      *                       have been taken.
3145      * @param measurements   collection of body magnetic flux density
3146      *                       measurements with standard deviation of
3147      *                       magnetometer measurements taken at the same
3148      *                       position with zero velocity and unknown different
3149      *                       orientations.
3150      * @param commonAxisUsed indicates whether z-axis is assumed to be common
3151      *                       for the accelerometer, gyroscope and magnetometer.
3152      * @param hardIron       known hard-iron.
3153      * @param method         robust estimator method.
3154      * @return a robust magnetometer calibrator.
3155      * @throws IllegalArgumentException if provided hard-iron array does
3156      *                                  not have length 3.
3157      */
3158     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3159             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3160             final boolean commonAxisUsed, final double[] hardIron, final RobustEstimatorMethod method) {
3161         return switch (method) {
3162             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3163                     position, measurements, commonAxisUsed, hardIron);
3164             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3165                     position, measurements, commonAxisUsed, hardIron);
3166             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3167                     position, measurements, commonAxisUsed, hardIron);
3168             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3169                     position, measurements, commonAxisUsed, hardIron);
3170             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3171                     position, measurements, commonAxisUsed, hardIron);
3172         };
3173     }
3174 
3175     /**
3176      * Creates a robust magnetometer calibrator.
3177      *
3178      * @param position       position where body magnetic flux density measurements
3179      *                       have been taken.
3180      * @param measurements   collection of body magnetic flux density
3181      *                       measurements with standard deviation of
3182      *                       magnetometer measurements taken at the same
3183      *                       position with zero velocity and unknown different
3184      *                       orientations.
3185      * @param commonAxisUsed indicates whether z-axis is assumed to be common
3186      *                       for the accelerometer, gyroscope and magnetometer.
3187      * @param hardIron       known hard-iron.
3188      * @param listener       listener to handle events raised by this calibrator.
3189      * @param method         robust estimator method.
3190      * @return a robust magnetometer calibrator.
3191      * @throws IllegalArgumentException if provided hard-iron array does
3192      *                                  not have length 3.
3193      */
3194     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3195             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3196             final boolean commonAxisUsed, final double[] hardIron,
3197             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
3198             final RobustEstimatorMethod method) {
3199         return switch (method) {
3200             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3201                     position, measurements, commonAxisUsed, hardIron, listener);
3202             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3203                     position, measurements, commonAxisUsed, hardIron, listener);
3204             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3205                     position, measurements, commonAxisUsed, hardIron, listener);
3206             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3207                     position, measurements, commonAxisUsed, hardIron, listener);
3208             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3209                     position, measurements, commonAxisUsed, hardIron, listener);
3210         };
3211     }
3212 
3213     /**
3214      * Creates a robust magnetometer calibrator.
3215      *
3216      * @param position     position where body magnetic flux density measurements
3217      *                     have been taken.
3218      * @param measurements collection of body magnetic flux density
3219      *                     measurements with standard deviation of
3220      *                     magnetometer measurements taken at the same
3221      *                     position with zero velocity and unknown different
3222      *                     orientations.
3223      * @param hardIron     known hard-iron.
3224      * @param method       robust estimator method.
3225      * @return a robust magnetometer calibrator.
3226      * @throws IllegalArgumentException if provided hard-iron matrix is not
3227      *                                  3x1.
3228      */
3229     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3230             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3231             final Matrix hardIron, final RobustEstimatorMethod method) {
3232         return switch (method) {
3233             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3234                     position, measurements, hardIron);
3235             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3236                     position, measurements, hardIron);
3237             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3238                     position, measurements, hardIron);
3239             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3240                     position, measurements, hardIron);
3241             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3242                     position, measurements, hardIron);
3243         };
3244     }
3245 
3246     /**
3247      * Creates a robust magnetometer calibrator.
3248      *
3249      * @param position     position where body magnetic flux density measurements
3250      *                     have been taken.
3251      * @param measurements collection of body magnetic flux density
3252      *                     measurements with standard deviation of
3253      *                     magnetometer measurements taken at the same
3254      *                     position with zero velocity and unknown different
3255      *                     orientations.
3256      * @param hardIron     known hard-iron.
3257      * @param listener     listener to handle events raised by this calibrator.
3258      * @param method       robust estimator method.
3259      * @return a robust magnetometer calibrator.
3260      * @throws IllegalArgumentException if provided hard-iron matrix is not
3261      *                                  3x1.
3262      */
3263     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3264             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3265             final Matrix hardIron, final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
3266             final RobustEstimatorMethod method) {
3267         return switch (method) {
3268             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3269                     position, measurements, hardIron, listener);
3270             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3271                     position, measurements, hardIron, listener);
3272             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3273                     position, measurements, hardIron, listener);
3274             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3275                     position, measurements, hardIron, listener);
3276             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3277                     position, measurements, hardIron, listener);
3278         };
3279     }
3280 
3281     /**
3282      * Creates a robust magnetometer calibrator.
3283      *
3284      * @param position       position where body magnetic flux density measurements
3285      *                       have been taken.
3286      * @param measurements   collection of body magnetic flux density
3287      *                       measurements with standard deviation of
3288      *                       magnetometer measurements taken at the same
3289      *                       position with zero velocity and unknown different
3290      *                       orientations.
3291      * @param commonAxisUsed indicates whether z-axis is assumed to be common
3292      *                       for the accelerometer, gyroscope and magnetometer.
3293      * @param hardIron       known hard-iron.
3294      * @param method         robust estimator method.
3295      * @return a robust magnetometer calibrator.
3296      * @throws IllegalArgumentException if provided hard-iron matrix is not
3297      *                                  3x1.
3298      */
3299     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3300             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3301             final boolean commonAxisUsed, final Matrix hardIron, final RobustEstimatorMethod method) {
3302         return switch (method) {
3303             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3304                     position, measurements, commonAxisUsed, hardIron);
3305             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3306                     position, measurements, commonAxisUsed, hardIron);
3307             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3308                     position, measurements, commonAxisUsed, hardIron);
3309             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3310                     position, measurements, commonAxisUsed, hardIron);
3311             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3312                     position, measurements, commonAxisUsed, hardIron);
3313         };
3314     }
3315 
3316     /**
3317      * Creates a robust magnetometer calibrator.
3318      *
3319      * @param position       position where body magnetic flux density measurements
3320      *                       have been taken.
3321      * @param measurements   collection of body magnetic flux density
3322      *                       measurements with standard deviation of
3323      *                       magnetometer measurements taken at the same
3324      *                       position with zero velocity and unknown different
3325      *                       orientations.
3326      * @param commonAxisUsed indicates whether z-axis is assumed to be common
3327      *                       for the accelerometer, gyroscope and magnetometer.
3328      * @param hardIron       known hard-iron.
3329      * @param listener       listener to handle events raised by this calibrator.
3330      * @param method         robust estimator method.
3331      * @return a robust magnetometer calibrator.
3332      * @throws IllegalArgumentException if provided hard-iron matrix is not
3333      *                                  3x1.
3334      */
3335     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3336             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3337             final boolean commonAxisUsed, final Matrix hardIron,
3338             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
3339             final RobustEstimatorMethod method) {
3340         return switch (method) {
3341             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3342                     position, measurements, commonAxisUsed, hardIron, listener);
3343             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3344                     position, measurements, commonAxisUsed, hardIron, listener);
3345             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3346                     position, measurements, commonAxisUsed, hardIron, listener);
3347             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3348                     position, measurements, commonAxisUsed, hardIron, listener);
3349             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3350                     position, measurements, commonAxisUsed, hardIron, listener);
3351         };
3352     }
3353 
3354     /**
3355      * Creates a robust magnetometer calibrator.
3356      *
3357      * @param position     position where body magnetic flux density measurements
3358      *                     have been taken.
3359      * @param measurements collection of body magnetic flux density
3360      *                     measurements with standard deviation of
3361      *                     magnetometer measurements taken at the same
3362      *                     position with zero velocity and unknown different
3363      *                     orientations.
3364      * @param hardIron     known hard-iron.
3365      * @param initialMm    initial soft-iron matrix containing scale factors
3366      *                     and cross coupling errors.
3367      * @param method       robust estimator method.
3368      * @return a robust magnetometer calibrator.
3369      * @throws IllegalArgumentException if provided hard-iron matrix is not
3370      *                                  3x1 or if soft-iron matrix is not
3371      *                                  3x3.
3372      */
3373     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3374             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3375             final Matrix hardIron, final Matrix initialMm, final RobustEstimatorMethod method) {
3376         return switch (method) {
3377             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3378                     position, measurements, hardIron, initialMm);
3379             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3380                     position, measurements, hardIron, initialMm);
3381             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3382                     position, measurements, hardIron, initialMm);
3383             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3384                     position, measurements, hardIron, initialMm);
3385             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3386                     position, measurements, hardIron, initialMm);
3387         };
3388     }
3389 
3390     /**
3391      * Creates a robust magnetometer calibrator.
3392      *
3393      * @param position     position where body magnetic flux density measurements
3394      *                     have been taken.
3395      * @param measurements collection of body magnetic flux density
3396      *                     measurements with standard deviation of
3397      *                     magnetometer measurements taken at the same
3398      *                     position with zero velocity and unknown different
3399      *                     orientations.
3400      * @param hardIron     known hard-iron.
3401      * @param initialMm    initial soft-iron matrix containing scale factors
3402      *                     and cross coupling errors.
3403      * @param listener     listener to handle events raised by this calibrator.
3404      * @param method       robust estimator method.
3405      * @return a robust magnetometer calibrator.
3406      * @throws IllegalArgumentException if provided hard-iron matrix is not
3407      *                                  3x1 or if soft-iron matrix is not
3408      *                                  3x3.
3409      */
3410     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3411             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3412             final Matrix hardIron, final Matrix initialMm,
3413             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
3414             final RobustEstimatorMethod method) {
3415         return switch (method) {
3416             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3417                     position, measurements, hardIron, initialMm, listener);
3418             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3419                     position, measurements, hardIron, initialMm, listener);
3420             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3421                     position, measurements, hardIron, initialMm, listener);
3422             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3423                     position, measurements, hardIron, initialMm, listener);
3424             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3425                     position, measurements, hardIron, initialMm, listener);
3426         };
3427     }
3428 
3429     /**
3430      * Creates a robust magnetometer calibrator.
3431      *
3432      * @param position       position where body magnetic flux density measurements
3433      *                       have been taken.
3434      * @param measurements   collection of body magnetic flux density
3435      *                       measurements with standard deviation of
3436      *                       magnetometer measurements taken at the same
3437      *                       position with zero velocity and unknown different
3438      *                       orientations.
3439      * @param commonAxisUsed indicates whether z-axis is assumed to be common
3440      *                       for the accelerometer, gyroscope and magnetometer.
3441      * @param hardIron       known hard-iron.
3442      * @param initialMm      initial soft-iron matrix containing scale factors
3443      *                       and cross coupling errors.
3444      * @param method         robust estimator method.
3445      * @return a robust magnetometer calibrator.
3446      * @throws IllegalArgumentException if provided hard-iron matrix is not
3447      *                                  3x1 or if soft-iron matrix is not
3448      *                                  3x3.
3449      */
3450     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3451             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3452             final boolean commonAxisUsed, final Matrix hardIron, final Matrix initialMm,
3453             final RobustEstimatorMethod method) {
3454         return switch (method) {
3455             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3456                     position, measurements, commonAxisUsed, hardIron, initialMm);
3457             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3458                     position, measurements, commonAxisUsed, hardIron, initialMm);
3459             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3460                     position, measurements, commonAxisUsed, hardIron, initialMm);
3461             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3462                     position, measurements, commonAxisUsed, hardIron, initialMm);
3463             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3464                     position, measurements, commonAxisUsed, hardIron, initialMm);
3465         };
3466     }
3467 
3468     /**
3469      * Creates a robust magnetometer calibrator.
3470      *
3471      * @param position       position where body magnetic flux density measurements
3472      *                       have been taken.
3473      * @param measurements   collection of body magnetic flux density
3474      *                       measurements with standard deviation of
3475      *                       magnetometer measurements taken at the same
3476      *                       position with zero velocity and unknown different
3477      *                       orientations.
3478      * @param commonAxisUsed indicates whether z-axis is assumed to be common
3479      *                       for the accelerometer, gyroscope and magnetometer.
3480      * @param hardIron       known hard-iron.
3481      * @param initialMm      initial soft-iron matrix containing scale factors
3482      *                       and cross coupling errors.
3483      * @param listener       listener to handle events raised by this calibrator.
3484      * @param method         robust estimator method.
3485      * @return a robust magnetometer calibrator.
3486      * @throws IllegalArgumentException if provided hard-iron matrix is not
3487      *                                  3x1 or if soft-iron matrix is not
3488      *                                  3x3.
3489      */
3490     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3491             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3492             final boolean commonAxisUsed, final Matrix hardIron, final Matrix initialMm,
3493             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
3494             final RobustEstimatorMethod method) {
3495         return switch (method) {
3496             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3497                     position, measurements, commonAxisUsed, hardIron, initialMm, listener);
3498             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3499                     position, measurements, commonAxisUsed, hardIron, initialMm, listener);
3500             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3501                     position, measurements, commonAxisUsed, hardIron, initialMm, listener);
3502             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3503                     position, measurements, commonAxisUsed, hardIron, initialMm, listener);
3504             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3505                     position, measurements, commonAxisUsed, hardIron, initialMm, listener);
3506         };
3507     }
3508 
3509     /**
3510      * Creates a robust magnetometer calibrator.
3511      *
3512      * @param position position where body magnetic flux density measurements
3513      *                 have been taken.
3514      * @param method   robust estimator method.
3515      * @return a robust magnetometer calibrator.
3516      */
3517     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3518             final ECEFPosition position, final RobustEstimatorMethod method) {
3519         return switch (method) {
3520             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(position);
3521             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(position);
3522             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(position);
3523             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(position);
3524             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(position);
3525         };
3526     }
3527 
3528     /**
3529      * Creates a robust magnetometer calibrator.
3530      *
3531      * @param position     position where body magnetic flux density measurements
3532      *                     have been taken.
3533      * @param measurements collection of body magnetic flux density
3534      *                     measurements with standard deviation of
3535      *                     magnetometer measurements taken at the same
3536      *                     position with zero velocity and unknown different
3537      *                     orientations.
3538      * @param method       robust estimator method.
3539      * @return a robust magnetometer calibrator.
3540      */
3541     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3542             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3543             final RobustEstimatorMethod method) {
3544         return switch (method) {
3545             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3546                     position, measurements);
3547             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3548                     position, measurements);
3549             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3550                     position, measurements);
3551             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3552                     position, measurements);
3553             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3554                     position, measurements);
3555         };
3556     }
3557 
3558     /**
3559      * Creates a robust magnetometer calibrator.
3560      *
3561      * @param position     position where body magnetic flux density measurements
3562      *                     have been taken.
3563      * @param measurements collection of body magnetic flux density
3564      *                     measurements with standard deviation of
3565      *                     magnetometer measurements taken at the same
3566      *                     position with zero velocity and unknown different
3567      *                     orientations.
3568      * @param listener     listener to handle events raised by this calibrator.
3569      * @param method       robust estimator method.
3570      * @return a robust magnetometer calibrator.
3571      */
3572     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3573             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3574             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
3575             final RobustEstimatorMethod method) {
3576         return switch (method) {
3577             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3578                     position, measurements, listener);
3579             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3580                     position, measurements, listener);
3581             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3582                     position, measurements, listener);
3583             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3584                     position, measurements, listener);
3585             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3586                     position, measurements, listener);
3587         };
3588     }
3589 
3590     /**
3591      * Creates a robust magnetometer calibrator.
3592      *
3593      * @param position       position where body magnetic flux density measurements
3594      *                       have been taken.
3595      * @param measurements   collection of body magnetic flux density
3596      *                       measurements with standard deviation of
3597      *                       magnetometer measurements taken at the same
3598      *                       position with zero velocity and unknown different
3599      *                       orientations.
3600      * @param commonAxisUsed indicates whether z-axis is assumed to be common
3601      *                       for the accelerometer, gyroscope and magnetometer.
3602      * @param method         robust estimator method.
3603      * @return a robust magnetometer calibrator.
3604      */
3605     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3606             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3607             final boolean commonAxisUsed, final RobustEstimatorMethod method) {
3608         return switch (method) {
3609             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3610                     position, measurements, commonAxisUsed);
3611             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3612                     position, measurements, commonAxisUsed);
3613             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3614                     position, measurements, commonAxisUsed);
3615             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3616                     position, measurements, commonAxisUsed);
3617             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3618                     position, measurements, commonAxisUsed);
3619         };
3620     }
3621 
3622     /**
3623      * Creates a robust magnetometer calibrator.
3624      *
3625      * @param position       position where body magnetic flux density measurements
3626      *                       have been taken.
3627      * @param measurements   collection of body magnetic flux density
3628      *                       measurements with standard deviation of
3629      *                       magnetometer measurements taken at the same
3630      *                       position with zero velocity and unknown different
3631      *                       orientations.
3632      * @param commonAxisUsed indicates whether z-axis is assumed to be common
3633      *                       for the accelerometer, gyroscope and magnetometer.
3634      * @param listener       listener to handle events raised by this calibrator.
3635      * @param method         robust estimator method.
3636      * @return a robust magnetometer calibrator.
3637      */
3638     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3639             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3640             final boolean commonAxisUsed,
3641             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
3642             final RobustEstimatorMethod method) {
3643         return switch (method) {
3644             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3645                     position, measurements, commonAxisUsed, listener);
3646             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3647                     position, measurements, commonAxisUsed, listener);
3648             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3649                     position, measurements, commonAxisUsed, listener);
3650             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3651                     position, measurements, commonAxisUsed, listener);
3652             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3653                     position, measurements, commonAxisUsed, listener);
3654         };
3655     }
3656 
3657     /**
3658      * Creates a robust magnetometer calibrator.
3659      *
3660      * @param position     position where body magnetic flux density measurements
3661      *                     have been taken.
3662      * @param measurements collection of body magnetic flux density
3663      *                     measurements with standard deviation of
3664      *                     magnetometer measurements taken at the same
3665      *                     position with zero velocity and unknown different
3666      *                     orientations.
3667      * @param hardIron     known hard-iron.
3668      * @param method       robust estimator method.
3669      * @return a robust magnetometer calibrator.
3670      * @throws IllegalArgumentException if provided hard-iron array does
3671      *                                  not have length 3.
3672      */
3673     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3674             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3675             final double[] hardIron, final RobustEstimatorMethod method) {
3676         return switch (method) {
3677             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3678                     position, measurements, hardIron);
3679             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3680                     position, measurements, hardIron);
3681             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3682                     position, measurements, hardIron);
3683             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3684                     position, measurements, hardIron);
3685             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3686                     position, measurements, hardIron);
3687         };
3688     }
3689 
3690     /**
3691      * Creates a robust magnetometer calibrator.
3692      *
3693      * @param position     position where body magnetic flux density measurements
3694      *                     have been taken.
3695      * @param measurements collection of body magnetic flux density
3696      *                     measurements with standard deviation of
3697      *                     magnetometer measurements taken at the same
3698      *                     position with zero velocity and unknown different
3699      *                     orientations.
3700      * @param hardIron     known hard-iron.
3701      * @param listener     listener to handle events raised by this calibrator.
3702      * @param method       robust estimator method.
3703      * @return a robust magnetometer calibrator.
3704      * @throws IllegalArgumentException if provided hard-iron array does
3705      *                                  not have length 3.
3706      */
3707     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3708             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3709             final double[] hardIron, final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
3710             final RobustEstimatorMethod method) {
3711         return switch (method) {
3712             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3713                     position, measurements, hardIron, listener);
3714             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3715                     position, measurements, hardIron, listener);
3716             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3717                     position, measurements, hardIron, listener);
3718             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3719                     position, measurements, hardIron, listener);
3720             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3721                     position, measurements, hardIron, listener);
3722         };
3723     }
3724 
3725     /**
3726      * Creates a robust magnetometer calibrator.
3727      *
3728      * @param position       position where body magnetic flux density measurements
3729      *                       have been taken.
3730      * @param measurements   collection of body magnetic flux density
3731      *                       measurements with standard deviation of
3732      *                       magnetometer measurements taken at the same
3733      *                       position with zero velocity and unknown different
3734      *                       orientations.
3735      * @param commonAxisUsed indicates whether z-axis is assumed to be common
3736      *                       for the accelerometer, gyroscope and magnetometer.
3737      * @param hardIron       known hard-iron.
3738      * @param method         robust estimator method.
3739      * @return a robust magnetometer calibrator.
3740      * @throws IllegalArgumentException if provided hard-iron array does
3741      *                                  not have length 3.
3742      */
3743     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3744             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3745             final boolean commonAxisUsed, final double[] hardIron, final RobustEstimatorMethod method) {
3746         return switch (method) {
3747             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3748                     position, measurements, commonAxisUsed, hardIron);
3749             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3750                     position, measurements, commonAxisUsed, hardIron);
3751             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3752                     position, measurements, commonAxisUsed, hardIron);
3753             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3754                     position, measurements, commonAxisUsed, hardIron);
3755             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3756                     position, measurements, commonAxisUsed, hardIron);
3757         };
3758     }
3759 
3760     /**
3761      * Creates a robust magnetometer calibrator.
3762      *
3763      * @param position       position where body magnetic flux density measurements
3764      *                       have been taken.
3765      * @param measurements   collection of body magnetic flux density
3766      *                       measurements with standard deviation of
3767      *                       magnetometer measurements taken at the same
3768      *                       position with zero velocity and unknown different
3769      *                       orientations.
3770      * @param commonAxisUsed indicates whether z-axis is assumed to be common
3771      *                       for the accelerometer, gyroscope and magnetometer.
3772      * @param hardIron       known hard-iron.
3773      * @param listener       listener to handle events raised by this calibrator.
3774      * @param method         robust estimator method.
3775      * @return a robust magnetometer calibrator.
3776      * @throws IllegalArgumentException if provided hard-iron array does
3777      *                                  not have length 3.
3778      */
3779     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3780             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3781             final boolean commonAxisUsed, final double[] hardIron,
3782             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
3783             final RobustEstimatorMethod method) {
3784         return switch (method) {
3785             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3786                     position, measurements, commonAxisUsed, hardIron, listener);
3787             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3788                     position, measurements, commonAxisUsed, hardIron, listener);
3789             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3790                     position, measurements, commonAxisUsed, hardIron, listener);
3791             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3792                     position, measurements, commonAxisUsed, hardIron, listener);
3793             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3794                     position, measurements, commonAxisUsed, hardIron, listener);
3795         };
3796     }
3797 
3798     /**
3799      * Creates a robust magnetometer calibrator.
3800      *
3801      * @param position     position where body magnetic flux density measurements
3802      *                     have been taken.
3803      * @param measurements collection of body magnetic flux density
3804      *                     measurements with standard deviation of
3805      *                     magnetometer measurements taken at the same
3806      *                     position with zero velocity and unknown different
3807      *                     orientations.
3808      * @param hardIron     known hard-iron.
3809      * @param method       robust estimator method.
3810      * @return a robust magnetometer calibrator.
3811      * @throws IllegalArgumentException if provided hard-iron matrix is not
3812      *                                  3x1.
3813      */
3814     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3815             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3816             final Matrix hardIron, final RobustEstimatorMethod method) {
3817         return switch (method) {
3818             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3819                     position, measurements, hardIron);
3820             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3821                     position, measurements, hardIron);
3822             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3823                     position, measurements, hardIron);
3824             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3825                     position, measurements, hardIron);
3826             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3827                     position, measurements, hardIron);
3828         };
3829     }
3830 
3831     /**
3832      * Creates a robust magnetometer calibrator.
3833      *
3834      * @param position     position where body magnetic flux density measurements
3835      *                     have been taken.
3836      * @param measurements collection of body magnetic flux density
3837      *                     measurements with standard deviation of
3838      *                     magnetometer measurements taken at the same
3839      *                     position with zero velocity and unknown different
3840      *                     orientations.
3841      * @param hardIron     known hard-iron.
3842      * @param listener     listener to handle events raised by this calibrator.
3843      * @param method       robust estimator method.
3844      * @return a robust magnetometer calibrator.
3845      * @throws IllegalArgumentException if provided hard-iron matrix is not
3846      *                                  3x1.
3847      */
3848     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3849             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3850             final Matrix hardIron, final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
3851             final RobustEstimatorMethod method) {
3852         return switch (method) {
3853             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3854                     position, measurements, hardIron, listener);
3855             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3856                     position, measurements, hardIron, listener);
3857             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3858                     position, measurements, hardIron, listener);
3859             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3860                     position, measurements, hardIron, listener);
3861             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3862                     position, measurements, hardIron, listener);
3863         };
3864     }
3865 
3866     /**
3867      * Creates a robust magnetometer calibrator.
3868      *
3869      * @param position       position where body magnetic flux density measurements
3870      *                       have been taken.
3871      * @param measurements   collection of body magnetic flux density
3872      *                       measurements with standard deviation of
3873      *                       magnetometer measurements taken at the same
3874      *                       position with zero velocity and unknown different
3875      *                       orientations.
3876      * @param commonAxisUsed indicates whether z-axis is assumed to be common
3877      *                       for the accelerometer, gyroscope and magnetometer.
3878      * @param hardIron       known hard-iron.
3879      * @param method         robust estimator method.
3880      * @return a robust magnetometer calibrator.
3881      * @throws IllegalArgumentException if provided hard-iron matrix is not
3882      *                                  3x1.
3883      */
3884     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3885             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3886             final boolean commonAxisUsed, final Matrix hardIron, final RobustEstimatorMethod method) {
3887         return switch (method) {
3888             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3889                     position, measurements, commonAxisUsed, hardIron);
3890             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3891                     position, measurements, commonAxisUsed, hardIron);
3892             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3893                     position, measurements, commonAxisUsed, hardIron);
3894             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3895                     position, measurements, commonAxisUsed, hardIron);
3896             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3897                     position, measurements, commonAxisUsed, hardIron);
3898         };
3899     }
3900 
3901     /**
3902      * Creates a robust magnetometer calibrator.
3903      *
3904      * @param position       position where body magnetic flux density measurements
3905      *                       have been taken.
3906      * @param measurements   collection of body magnetic flux density
3907      *                       measurements with standard deviation of
3908      *                       magnetometer measurements taken at the same
3909      *                       position with zero velocity and unknown different
3910      *                       orientations.
3911      * @param commonAxisUsed indicates whether z-axis is assumed to be common
3912      *                       for the accelerometer, gyroscope and magnetometer.
3913      * @param hardIron       known hard-iron.
3914      * @param listener       listener to handle events raised by this calibrator.
3915      * @param method         robust estimator method.
3916      * @return a robust magnetometer calibrator.
3917      * @throws IllegalArgumentException if provided hard-iron matrix is not
3918      *                                  3x1.
3919      */
3920     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3921             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3922             final boolean commonAxisUsed, final Matrix hardIron,
3923             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
3924             final RobustEstimatorMethod method) {
3925         return switch (method) {
3926             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3927                     position, measurements, commonAxisUsed, hardIron, listener);
3928             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3929                     position, measurements, commonAxisUsed, hardIron, listener);
3930             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3931                     position, measurements, commonAxisUsed, hardIron, listener);
3932             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3933                     position, measurements, commonAxisUsed, hardIron, listener);
3934             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3935                     position, measurements, commonAxisUsed, hardIron, listener);
3936         };
3937     }
3938 
3939     /**
3940      * Creates a robust magnetometer calibrator.
3941      *
3942      * @param position     position where body magnetic flux density measurements
3943      *                     have been taken.
3944      * @param measurements collection of body magnetic flux density
3945      *                     measurements with standard deviation of
3946      *                     magnetometer measurements taken at the same
3947      *                     position with zero velocity and unknown different
3948      *                     orientations.
3949      * @param hardIron     known hard-iron.
3950      * @param initialMm    initial soft-iron matrix containing scale factors
3951      *                     and cross coupling errors.
3952      * @param method       robust estimator method.
3953      * @return a robust magnetometer calibrator.
3954      * @throws IllegalArgumentException if provided hard-iron matrix is not
3955      *                                  3x1 or if soft-iron matrix is not
3956      *                                  3x3.
3957      */
3958     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3959             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3960             final Matrix hardIron, final Matrix initialMm, final RobustEstimatorMethod method) {
3961         return switch (method) {
3962             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3963                     position, measurements, hardIron, initialMm);
3964             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3965                     position, measurements, hardIron, initialMm);
3966             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3967                     position, measurements, hardIron, initialMm);
3968             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3969                     position, measurements, hardIron, initialMm);
3970             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
3971                     position, measurements, hardIron, initialMm);
3972         };
3973     }
3974 
3975     /**
3976      * Creates a robust magnetometer calibrator.
3977      *
3978      * @param position     position where body magnetic flux density measurements
3979      *                     have been taken.
3980      * @param measurements collection of body magnetic flux density
3981      *                     measurements with standard deviation of
3982      *                     magnetometer measurements taken at the same
3983      *                     position with zero velocity and unknown different
3984      *                     orientations.
3985      * @param hardIron     known hard-iron.
3986      * @param initialMm    initial soft-iron matrix containing scale factors
3987      *                     and cross coupling errors.
3988      * @param listener     listener to handle events raised by this calibrator.
3989      * @param method       robust estimator method.
3990      * @return a robust magnetometer calibrator.
3991      * @throws IllegalArgumentException if provided hard-iron matrix is not
3992      *                                  3x1 or if soft-iron matrix is not
3993      *                                  3x3.
3994      */
3995     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
3996             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
3997             final Matrix hardIron, final Matrix initialMm,
3998             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
3999             final RobustEstimatorMethod method) {
4000         return switch (method) {
4001             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4002                     position, measurements, hardIron, initialMm, listener);
4003             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4004                     position, measurements, hardIron, initialMm, listener);
4005             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4006                     position, measurements, hardIron, initialMm, listener);
4007             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4008                     position, measurements, hardIron, initialMm, listener);
4009             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4010                     position, measurements, hardIron, initialMm, listener);
4011         };
4012     }
4013 
4014     /**
4015      * Creates a robust magnetometer calibrator.
4016      *
4017      * @param position       position where body magnetic flux density measurements
4018      *                       have been taken.
4019      * @param measurements   collection of body magnetic flux density
4020      *                       measurements with standard deviation of
4021      *                       magnetometer measurements taken at the same
4022      *                       position with zero velocity and unknown different
4023      *                       orientations.
4024      * @param commonAxisUsed indicates whether z-axis is assumed to be common
4025      *                       for the accelerometer, gyroscope and magnetometer.
4026      * @param hardIron       known hard-iron.
4027      * @param initialMm      initial soft-iron matrix containing scale factors
4028      *                       and cross coupling errors.
4029      * @param method         robust estimator method.
4030      * @return a robust magnetometer calibrator.
4031      * @throws IllegalArgumentException if provided hard-iron matrix is not
4032      *                                  3x1 or if soft-iron matrix is not
4033      *                                  3x3.
4034      */
4035     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4036             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
4037             final boolean commonAxisUsed, final Matrix hardIron, final Matrix initialMm,
4038             final RobustEstimatorMethod method) {
4039         return switch (method) {
4040             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4041                     position, measurements, commonAxisUsed, hardIron, initialMm);
4042             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4043                     position, measurements, commonAxisUsed, hardIron, initialMm);
4044             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4045                     position, measurements, commonAxisUsed, hardIron, initialMm);
4046             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4047                     position, measurements, commonAxisUsed, hardIron, initialMm);
4048             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4049                     position, measurements, commonAxisUsed, hardIron, initialMm);
4050         };
4051     }
4052 
4053     /**
4054      * Creates a robust magnetometer calibrator.
4055      *
4056      * @param position       position where body magnetic flux density measurements
4057      *                       have been taken.
4058      * @param measurements   collection of body magnetic flux density
4059      *                       measurements with standard deviation of
4060      *                       magnetometer measurements taken at the same
4061      *                       position with zero velocity and unknown different
4062      *                       orientations.
4063      * @param commonAxisUsed indicates whether z-axis is assumed to be common
4064      *                       for the accelerometer, gyroscope and magnetometer.
4065      * @param hardIron       known hard-iron.
4066      * @param initialMm      initial soft-iron matrix containing scale factors
4067      *                       and cross coupling errors.
4068      * @param listener       listener to handle events raised by this calibrator.
4069      * @param method         robust estimator method.
4070      * @return a robust magnetometer calibrator.
4071      * @throws IllegalArgumentException if provided hard-iron matrix is not
4072      *                                  3x1 or if soft-iron matrix is not
4073      *                                  3x3.
4074      */
4075     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4076             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
4077             final boolean commonAxisUsed, final Matrix hardIron, final Matrix initialMm,
4078             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
4079             final RobustEstimatorMethod method) {
4080         return switch (method) {
4081             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4082                     position, measurements, commonAxisUsed, hardIron, initialMm, listener);
4083             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4084                     position, measurements, commonAxisUsed, hardIron, initialMm, listener);
4085             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4086                     position, measurements, commonAxisUsed, hardIron, initialMm, listener);
4087             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4088                     position, measurements, commonAxisUsed, hardIron, initialMm, listener);
4089             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4090                     position, measurements, commonAxisUsed, hardIron, initialMm, listener);
4091         };
4092     }
4093 
4094     /**
4095      * Creates a robust magnetometer calibrator.
4096      *
4097      * @param qualityScores quality scores corresponding to each provided
4098      *                      measurement. The larger the score value the better
4099      *                      the quality of the sample.
4100      * @param measurements  list of body magnetic flux density
4101      *                      measurements with standard deviation of
4102      *                      magnetometer measurements taken at the same
4103      *                      position with zero velocity and unknown different
4104      *                      orientations.
4105      * @param method        robust estimator method.
4106      * @return a robust magnetometer calibrator.
4107      * @throws IllegalArgumentException if provided quality scores length
4108      *                                  is smaller than 10 samples.
4109      */
4110     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4111             final double[] qualityScores, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
4112             final RobustEstimatorMethod method) {
4113         return switch (method) {
4114             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(measurements);
4115             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(measurements);
4116             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(measurements);
4117             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4118                     qualityScores, measurements);
4119             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4120                     qualityScores, measurements);
4121         };
4122     }
4123 
4124     /**
4125      * Creates a robust magnetometer calibrator.
4126      *
4127      * @param qualityScores  quality scores corresponding to each provided
4128      *                       measurement. The larger the score value the better
4129      *                       the quality of the sample.
4130      * @param commonAxisUsed indicates whether z-axis is assumed to be common
4131      *                       for the accelerometer, gyroscope and magnetometer.
4132      * @param method         robust estimator method
4133      * @return a robust magnetometer calibrator.
4134      * @throws IllegalArgumentException if provided quality scores length
4135      *                                  is smaller than 10 samples.
4136      */
4137     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4138             final double[] qualityScores, final boolean commonAxisUsed, final RobustEstimatorMethod method) {
4139         return switch (method) {
4140             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4141                     commonAxisUsed);
4142             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4143                     commonAxisUsed);
4144             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4145                     commonAxisUsed);
4146             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4147                     qualityScores, commonAxisUsed);
4148             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4149                     qualityScores, commonAxisUsed);
4150         };
4151     }
4152 
4153     /**
4154      * Creates a robust magnetometer calibrator.
4155      *
4156      * @param qualityScores quality scores corresponding to each provided
4157      *                      measurement. The larger the score value the better
4158      *                      the quality of the sample.
4159      * @param magneticModel Earth's magnetic model. If null, a default model
4160      *                      will be used instead.
4161      * @param method        robust estimator method
4162      * @return a robust magnetometer calibrator.
4163      * @throws IllegalArgumentException if provided quality scores length
4164      *                                  is smaller than 10 samples.
4165      */
4166     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4167             final double[] qualityScores, final WorldMagneticModel magneticModel, final RobustEstimatorMethod method) {
4168         return switch (method) {
4169             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(magneticModel);
4170             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(magneticModel);
4171             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(magneticModel);
4172             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4173                     qualityScores, magneticModel);
4174             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4175                     qualityScores, magneticModel);
4176         };
4177     }
4178 
4179     /**
4180      * Creates a robust magnetometer calibrator.
4181      *
4182      * @param qualityScores quality scores corresponding to each provided
4183      *                      measurement. The larger the score value the better
4184      *                      the quality of the sample.
4185      * @param hardIron      known hard-iron.
4186      * @param method        robust estimator method
4187      * @return a robust magnetometer calibrator.
4188      * @throws IllegalArgumentException if provided hard-iron array does
4189      *                                  not have length 3 or if provided
4190      *                                  quality scores length is smaller
4191      *                                  than 10 samples.
4192      */
4193     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4194             final double[] qualityScores, final double[] hardIron, final RobustEstimatorMethod method) {
4195         return switch (method) {
4196             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron);
4197             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron);
4198             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron);
4199             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4200                     qualityScores, hardIron);
4201             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4202                     qualityScores, hardIron);
4203         };
4204     }
4205 
4206     /**
4207      * Creates a robust magnetometer calibrator.
4208      *
4209      * @param qualityScores quality scores corresponding to each provided
4210      *                      measurement. The larger the score value the better
4211      *                      the quality of the sample.
4212      * @param hardIron      known hard-iron.
4213      * @param method        robust estimator method
4214      * @return a robust magnetometer calibrator.
4215      * @throws IllegalArgumentException if provided hard-iron matrix is not
4216      *                                  3x1 or if provided quality scores
4217      *                                  length is smaller than 10 samples.
4218      */
4219     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4220             final double[] qualityScores, final Matrix hardIron, final RobustEstimatorMethod method) {
4221         return switch (method) {
4222             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron);
4223             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron);
4224             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron);
4225             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4226                     qualityScores, hardIron);
4227             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4228                     qualityScores, hardIron);
4229         };
4230     }
4231 
4232     /**
4233      * Creates a robust magnetometer calibrator.
4234      *
4235      * @param qualityScores quality scores corresponding to each provided
4236      *                      measurement. The larger the score value the better
4237      *                      the quality of the sample.
4238      * @param hardIron      known hard-iron.
4239      * @param initialMm     initial soft-iron matrix containing scale factors
4240      *                      and cross coupling errors.
4241      * @param method        robust estimator method
4242      * @return a robust magnetometer calibrator.
4243      * @throws IllegalArgumentException if provided hard-iron matrix is not
4244      *                                  3x1 or if soft-iron matrix is not
4245      *                                  3x3 or if provided quality scores
4246      *                                  length is smaller than 10 samples.
4247      */
4248     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4249             final double[] qualityScores, final Matrix hardIron, final Matrix initialMm,
4250             final RobustEstimatorMethod method) {
4251         return switch (method) {
4252             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron, initialMm);
4253             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron, initialMm);
4254             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(hardIron, initialMm);
4255             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(qualityScores,
4256                     hardIron, initialMm);
4257             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(qualityScores,
4258                     hardIron, initialMm);
4259         };
4260     }
4261 
4262     /**
4263      * Creates a robust magnetometer calibrator.
4264      *
4265      * @param qualityScores quality scores corresponding to each provided
4266      *                      measurement. The larger the score value the better
4267      *                      the quality of the sample.
4268      * @param position      position where body magnetic flux density measurements
4269      *                      have been taken.
4270      * @param method        robust estimator method
4271      * @return a robust magnetometer calibrator.
4272      * @throws IllegalArgumentException if provided quality scores length
4273      *                                  is smaller than 10 samples.
4274      */
4275     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4276             final double[] qualityScores, final NEDPosition position, final RobustEstimatorMethod method) {
4277         return switch (method) {
4278             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(position);
4279             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(position);
4280             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(position);
4281             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(qualityScores,
4282                     position);
4283             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(qualityScores,
4284                     position);
4285         };
4286     }
4287 
4288     /**
4289      * Creates a robust magnetometer calibrator.
4290      *
4291      * @param qualityScores quality scores corresponding to each provided
4292      *                      measurement. The larger the score value the better
4293      *                      the quality of the sample.
4294      * @param position      position where body magnetic flux density measurements
4295      *                      have been taken.
4296      * @param measurements  collection of body magnetic flux density
4297      *                      measurements with standard deviation of
4298      *                      magnetometer measurements taken at the same
4299      *                      position with zero velocity and unknown different
4300      *                      orientations.
4301      * @param method        robust estimator method
4302      * @return a robust magnetometer calibrator.
4303      * @throws IllegalArgumentException if provided quality scores length
4304      *                                  is smaller than 10 samples.
4305      */
4306     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4307             final double[] qualityScores, final NEDPosition position,
4308             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final RobustEstimatorMethod method) {
4309         return switch (method) {
4310             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4311                     position, measurements);
4312             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4313                     position, measurements);
4314             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4315                     position, measurements);
4316             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4317                     qualityScores, position, measurements);
4318             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4319                     qualityScores, position, measurements);
4320         };
4321     }
4322 
4323     /**
4324      * Creates a robust magnetometer calibrator.
4325      *
4326      * @param qualityScores quality scores corresponding to each provided
4327      *                      measurement. The larger the score value the better
4328      *                      the quality of the sample.
4329      * @param position      position where body magnetic flux density measurements
4330      *                      have been taken.
4331      * @param measurements  collection of body magnetic flux density
4332      *                      measurements with standard deviation of
4333      *                      magnetometer measurements taken at the same
4334      *                      position with zero velocity and unknown different
4335      *                      orientations.
4336      * @param listener      listener to handle events raised by this calibrator.
4337      * @param method        robust estimator method
4338      * @return a robust magnetometer calibrator.
4339      * @throws IllegalArgumentException if provided quality scores length
4340      *                                  is smaller than 10 samples.
4341      */
4342     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4343             final double[] qualityScores, final NEDPosition position,
4344             final List<StandardDeviationBodyMagneticFluxDensity> measurements,
4345             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
4346             final RobustEstimatorMethod method) {
4347         return switch (method) {
4348             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4349                     position, measurements, listener);
4350             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4351                     position, measurements, listener);
4352             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4353                     position, measurements, listener);
4354             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4355                     qualityScores, position, measurements, listener);
4356             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4357                     qualityScores, position, measurements, listener);
4358         };
4359     }
4360 
4361     /**
4362      * Creates a robust magnetometer calibrator.
4363      *
4364      * @param qualityScores  quality scores corresponding to each provided
4365      *                       measurement. The larger the score value the better
4366      *                       the quality of the sample.
4367      * @param position       position where body magnetic flux density measurements
4368      *                       have been taken.
4369      * @param measurements   collection of body magnetic flux density
4370      *                       measurements with standard deviation of
4371      *                       magnetometer measurements taken at the same
4372      *                       position with zero velocity and unknown different
4373      *                       orientations.
4374      * @param commonAxisUsed indicates whether z-axis is assumed to be common
4375      *                       for the accelerometer, gyroscope and magnetometer.
4376      * @param method         robust estimator method
4377      * @return a robust magnetometer calibrator.
4378      * @throws IllegalArgumentException if provided quality scores length
4379      *                                  is smaller than 10 samples.
4380      */
4381     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4382             final double[] qualityScores, final NEDPosition position,
4383             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
4384             final RobustEstimatorMethod method) {
4385         return switch (method) {
4386             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4387                     position, measurements, commonAxisUsed);
4388             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4389                     position, measurements, commonAxisUsed);
4390             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4391                     position, measurements, commonAxisUsed);
4392             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4393                     qualityScores, position, measurements, commonAxisUsed);
4394             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4395                     qualityScores, position, measurements, commonAxisUsed);
4396         };
4397     }
4398 
4399     /**
4400      * Creates a robust magnetometer calibrator.
4401      *
4402      * @param qualityScores  quality scores corresponding to each provided
4403      *                       measurement. The larger the score value the better
4404      *                       the quality of the sample.
4405      * @param position       position where body magnetic flux density measurements
4406      *                       have been taken.
4407      * @param measurements   collection of body magnetic flux density
4408      *                       measurements with standard deviation of
4409      *                       magnetometer measurements taken at the same
4410      *                       position with zero velocity and unknown different
4411      *                       orientations.
4412      * @param commonAxisUsed indicates whether z-axis is assumed to be common
4413      *                       for the accelerometer, gyroscope and magnetometer.
4414      * @param listener       listener to handle events raised by this calibrator.
4415      * @param method         robust estimator method
4416      * @return a robust magnetometer calibrator.
4417      * @throws IllegalArgumentException if provided quality scores length
4418      *                                  is smaller than 10 samples.
4419      */
4420     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4421             final double[] qualityScores, final NEDPosition position,
4422             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
4423             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
4424             final RobustEstimatorMethod method) {
4425         return switch (method) {
4426             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4427                     position, measurements, commonAxisUsed, listener);
4428             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4429                     position, measurements, commonAxisUsed, listener);
4430             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4431                     position, measurements, commonAxisUsed, listener);
4432             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4433                     qualityScores, position, measurements, commonAxisUsed, listener);
4434             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4435                     qualityScores, position, measurements, commonAxisUsed, listener);
4436         };
4437     }
4438 
4439     /**
4440      * Creates a robust magnetometer calibrator.
4441      *
4442      * @param qualityScores quality scores corresponding to each provided
4443      *                      measurement. The larger the score value the better
4444      *                      the quality of the sample.
4445      * @param position      position where body magnetic flux density measurements
4446      *                      have been taken.
4447      * @param measurements  collection of body magnetic flux density
4448      *                      measurements with standard deviation of
4449      *                      magnetometer measurements taken at the same
4450      *                      position with zero velocity and unknown different
4451      *                      orientations.
4452      * @param hardIron      known hard-iron.
4453      * @param method        robust estimator method.
4454      * @return a robust magnetometer calibrator.
4455      * @throws IllegalArgumentException if provided hard-iron array does
4456      *                                  not have length 3 or if provided
4457      *                                  quality scores length is smaller
4458      *                                  than 10 samples.
4459      */
4460     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4461             final double[] qualityScores, final NEDPosition position,
4462             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final double[] hardIron,
4463             final RobustEstimatorMethod method) {
4464         return switch (method) {
4465             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4466                     position, measurements, hardIron);
4467             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4468                     position, measurements, hardIron);
4469             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4470                     position, measurements, hardIron);
4471             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4472                     qualityScores, position, measurements, hardIron);
4473             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4474                     qualityScores, position, measurements, hardIron);
4475         };
4476     }
4477 
4478     /**
4479      * Creates a robust magnetometer calibrator.
4480      *
4481      * @param qualityScores quality scores corresponding to each provided
4482      *                      measurement. The larger the score value the better
4483      *                      the quality of the sample.
4484      * @param position      position where body magnetic flux density measurements
4485      *                      have been taken.
4486      * @param measurements  collection of body magnetic flux density
4487      *                      measurements with standard deviation of
4488      *                      magnetometer measurements taken at the same
4489      *                      position with zero velocity and unknown different
4490      *                      orientations.
4491      * @param hardIron      known hard-iron.
4492      * @param listener      listener to handle events raised by this calibrator.
4493      * @param method        robust estimator method.
4494      * @return a robust magnetometer calibrator.
4495      * @throws IllegalArgumentException if provided hard-iron array does
4496      *                                  not have length 3 or if provided
4497      *                                  quality scores length is smaller
4498      *                                  than 10 samples.
4499      */
4500     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4501             final double[] qualityScores, final NEDPosition position,
4502             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final double[] hardIron,
4503             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
4504             final RobustEstimatorMethod method) {
4505         return switch (method) {
4506             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4507                     position, measurements, hardIron, listener);
4508             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4509                     position, measurements, hardIron, listener);
4510             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4511                     position, measurements, hardIron, listener);
4512             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4513                     qualityScores, position, measurements, hardIron, listener);
4514             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4515                     qualityScores, position, measurements, hardIron, listener);
4516         };
4517     }
4518 
4519     /**
4520      * Creates a robust magnetometer calibrator.
4521      *
4522      * @param qualityScores  quality scores corresponding to each provided
4523      *                       measurement. The larger the score value the better
4524      *                       the quality of the sample.
4525      * @param position       position where body magnetic flux density measurements
4526      *                       have been taken.
4527      * @param measurements   collection of body magnetic flux density
4528      *                       measurements with standard deviation of
4529      *                       magnetometer measurements taken at the same
4530      *                       position with zero velocity and unknown different
4531      *                       orientations.
4532      * @param commonAxisUsed indicates whether z-axis is assumed to be common
4533      *                       for the accelerometer, gyroscope and magnetometer.
4534      * @param hardIron       known hard-iron.
4535      * @param method         robust estimator method.
4536      * @return a robust magnetometer calibrator.
4537      * @throws IllegalArgumentException if provided hard-iron array does
4538      *                                  not have length 3 or if provided
4539      *                                  quality scores length is smaller
4540      *                                  than 10 samples.
4541      */
4542     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4543             final double[] qualityScores, final NEDPosition position,
4544             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
4545             final double[] hardIron, final RobustEstimatorMethod method) {
4546         return switch (method) {
4547             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4548                     position, measurements, commonAxisUsed, hardIron);
4549             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4550                     position, measurements, commonAxisUsed, hardIron);
4551             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4552                     position, measurements, commonAxisUsed, hardIron);
4553             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4554                     qualityScores, position, measurements, commonAxisUsed, hardIron);
4555             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4556                     qualityScores, position, measurements, commonAxisUsed, hardIron);
4557         };
4558     }
4559 
4560     /**
4561      * Creates a robust magnetometer calibrator.
4562      *
4563      * @param qualityScores  quality scores corresponding to each provided
4564      *                       measurement. The larger the score value the better
4565      *                       the quality of the sample.
4566      * @param position       position where body magnetic flux density measurements
4567      *                       have been taken.
4568      * @param measurements   collection of body magnetic flux density
4569      *                       measurements with standard deviation of
4570      *                       magnetometer measurements taken at the same
4571      *                       position with zero velocity and unknown different
4572      *                       orientations.
4573      * @param commonAxisUsed indicates whether z-axis is assumed to be common
4574      *                       for the accelerometer, gyroscope and magnetometer.
4575      * @param hardIron       known hard-iron.
4576      * @param listener       listener to handle events raised by this calibrator.
4577      * @param method         robust estimator method.
4578      * @return a robust magnetometer calibrator.
4579      * @throws IllegalArgumentException if provided hard-iron array does
4580      *                                  not have length 3 or if provided
4581      *                                  quality scores length is smaller
4582      *                                  than 10 samples.
4583      */
4584     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4585             final double[] qualityScores, final NEDPosition position,
4586             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
4587             final double[] hardIron, final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
4588             final RobustEstimatorMethod method) {
4589         return switch (method) {
4590             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4591                     position, measurements, commonAxisUsed, hardIron, listener);
4592             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4593                     position, measurements, commonAxisUsed, hardIron, listener);
4594             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4595                     position, measurements, commonAxisUsed, hardIron, listener);
4596             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4597                     qualityScores, position, measurements, commonAxisUsed, hardIron, listener);
4598             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4599                     qualityScores, position, measurements, commonAxisUsed, hardIron, listener);
4600         };
4601     }
4602 
4603     /**
4604      * Creates a robust magnetometer calibrator.
4605      *
4606      * @param qualityScores quality scores corresponding to each provided
4607      *                      measurement. The larger the score value the better
4608      *                      the quality of the sample.
4609      * @param position      position where body magnetic flux density measurements
4610      *                      have been taken.
4611      * @param measurements  collection of body magnetic flux density
4612      *                      measurements with standard deviation of
4613      *                      magnetometer measurements taken at the same
4614      *                      position with zero velocity and unknown different
4615      *                      orientations.
4616      * @param hardIron      known hard-iron.
4617      * @param method        robust estimator method.
4618      * @return a robust magnetometer calibrator.
4619      * @throws IllegalArgumentException if provided hard-iron matrix is not
4620      *                                  3x1 or if provided quality scores
4621      *                                  length is smaller than 10 samples.
4622      */
4623     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4624             final double[] qualityScores, final NEDPosition position,
4625             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
4626             final RobustEstimatorMethod method) {
4627         return switch (method) {
4628             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4629                     position, measurements, hardIron);
4630             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4631                     position, measurements, hardIron);
4632             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4633                     position, measurements, hardIron);
4634             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4635                     qualityScores, position, measurements, hardIron);
4636             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4637                     qualityScores, position, measurements, hardIron);
4638         };
4639     }
4640 
4641     /**
4642      * Creates a robust magnetometer calibrator.
4643      *
4644      * @param qualityScores quality scores corresponding to each provided
4645      *                      measurement. The larger the score value the better
4646      *                      the quality of the sample.
4647      * @param position      position where body magnetic flux density measurements
4648      *                      have been taken.
4649      * @param measurements  collection of body magnetic flux density
4650      *                      measurements with standard deviation of
4651      *                      magnetometer measurements taken at the same
4652      *                      position with zero velocity and unknown different
4653      *                      orientations.
4654      * @param hardIron      known hard-iron.
4655      * @param listener      listener to handle events raised by this calibrator.
4656      * @param method        robust estimator method.
4657      * @return a robust magnetometer calibrator.
4658      */
4659     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4660             final double[] qualityScores, final NEDPosition position,
4661             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
4662             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
4663             final RobustEstimatorMethod method) {
4664         return switch (method) {
4665             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4666                     position, measurements, hardIron, listener);
4667             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4668                     position, measurements, hardIron, listener);
4669             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4670                     position, measurements, hardIron, listener);
4671             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4672                     qualityScores, position, measurements, hardIron, listener);
4673             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4674                     qualityScores, position, measurements, hardIron, listener);
4675         };
4676     }
4677 
4678     /**
4679      * Creates a robust magnetometer calibrator.
4680      *
4681      * @param qualityScores  quality scores corresponding to each provided
4682      *                       measurement. The larger the score value the better
4683      *                       the quality of the sample.
4684      * @param position       position where body magnetic flux density measurements
4685      *                       have been taken.
4686      * @param measurements   collection of body magnetic flux density
4687      *                       measurements with standard deviation of
4688      *                       magnetometer measurements taken at the same
4689      *                       position with zero velocity and unknown different
4690      *                       orientations.
4691      * @param commonAxisUsed indicates whether z-axis is assumed to be common
4692      *                       for the accelerometer, gyroscope and magnetometer.
4693      * @param hardIron       known hard-iron.
4694      * @param method         robust estimator method.
4695      * @return a robust magnetometer calibrator.
4696      * @throws IllegalArgumentException if provided hard-iron matrix is not
4697      *                                  3x1 or if provided quality scores
4698      *                                  length is smaller than 10 samples.
4699      */
4700     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4701             final double[] qualityScores, final NEDPosition position,
4702             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
4703             final Matrix hardIron, final RobustEstimatorMethod method) {
4704         return switch (method) {
4705             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4706                     position, measurements, commonAxisUsed, hardIron);
4707             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4708                     position, measurements, commonAxisUsed, hardIron);
4709             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4710                     position, measurements, commonAxisUsed, hardIron);
4711             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4712                     qualityScores, position, measurements, commonAxisUsed, hardIron);
4713             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4714                     qualityScores, position, measurements, commonAxisUsed, hardIron);
4715         };
4716     }
4717 
4718     /**
4719      * Creates a robust magnetometer calibrator.
4720      *
4721      * @param qualityScores  quality scores corresponding to each provided
4722      *                       measurement. The larger the score value the better
4723      *                       the quality of the sample.
4724      * @param position       position where body magnetic flux density measurements
4725      *                       have been taken.
4726      * @param measurements   collection of body magnetic flux density
4727      *                       measurements with standard deviation of
4728      *                       magnetometer measurements taken at the same
4729      *                       position with zero velocity and unknown different
4730      *                       orientations.
4731      * @param commonAxisUsed indicates whether z-axis is assumed to be common
4732      *                       for the accelerometer, gyroscope and magnetometer.
4733      * @param hardIron       known hard-iron.
4734      * @param listener       listener to handle events raised by this calibrator.
4735      * @param method         robust estimator method.
4736      * @return a robust magnetometer calibrator.
4737      * @throws IllegalArgumentException if provided hard-iron matrix is not
4738      *                                  3x1 or if provided quality scores
4739      *                                  length is smaller than 10 samples.
4740      */
4741     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4742             final double[] qualityScores, final NEDPosition position,
4743             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
4744             final Matrix hardIron, final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
4745             final RobustEstimatorMethod method) {
4746         return switch (method) {
4747             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4748                     position, measurements, commonAxisUsed, hardIron, listener);
4749             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4750                     position, measurements, commonAxisUsed, hardIron, listener);
4751             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4752                     position, measurements, commonAxisUsed, hardIron, listener);
4753             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4754                     qualityScores, position, measurements, commonAxisUsed, hardIron, listener);
4755             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4756                     qualityScores, position, measurements, commonAxisUsed, hardIron, listener);
4757         };
4758     }
4759 
4760     /**
4761      * Creates a robust magnetometer calibrator.
4762      *
4763      * @param qualityScores quality scores corresponding to each provided
4764      *                      measurement. The larger the score value the better
4765      *                      the quality of the sample.
4766      * @param position      position where body magnetic flux density measurements
4767      *                      have been taken.
4768      * @param measurements  collection of body magnetic flux density
4769      *                      measurements with standard deviation of
4770      *                      magnetometer measurements taken at the same
4771      *                      position with zero velocity and unknown different
4772      *                      orientations.
4773      * @param hardIron      known hard-iron.
4774      * @param initialMm     initial soft-iron matrix containing scale factors
4775      *                      and cross coupling errors.
4776      * @param method        robust estimator method.
4777      * @return a robust magnetometer calibrator.
4778      * @throws IllegalArgumentException if provided hard-iron matrix is not
4779      *                                  3x1 or if soft-iron matrix is not
4780      *                                  3x3 or if provided quality scores
4781      *                                  length is smaller than 10 samples.
4782      */
4783     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4784             final double[] qualityScores, final NEDPosition position,
4785             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
4786             final Matrix initialMm, final RobustEstimatorMethod method) {
4787         return switch (method) {
4788             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4789                     position, measurements, hardIron, initialMm);
4790             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4791                     position, measurements, hardIron, initialMm);
4792             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4793                     position, measurements, hardIron, initialMm);
4794             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4795                     qualityScores, position, measurements, hardIron, initialMm);
4796             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4797                     qualityScores, position, measurements, hardIron, initialMm);
4798         };
4799     }
4800 
4801     /**
4802      * Creates a robust magnetometer calibrator.
4803      *
4804      * @param qualityScores quality scores corresponding to each provided
4805      *                      measurement. The larger the score value the better
4806      *                      the quality of the sample.
4807      * @param position      position where body magnetic flux density measurements
4808      *                      have been taken.
4809      * @param measurements  collection of body magnetic flux density
4810      *                      measurements with standard deviation of
4811      *                      magnetometer measurements taken at the same
4812      *                      position with zero velocity and unknown different
4813      *                      orientations.
4814      * @param hardIron      known hard-iron.
4815      * @param initialMm     initial soft-iron matrix containing scale factors
4816      *                      and cross coupling errors.
4817      * @param listener      listener to handle events raised by this calibrator.
4818      * @param method        robust estimator method.
4819      * @return a robust magnetometer calibrator.
4820      * @throws IllegalArgumentException if provided hard-iron matrix is not
4821      *                                  3x1 or if soft-iron matrix is not
4822      *                                  3x3 or if provided quality scores
4823      *                                  length is smaller than 10 samples.
4824      */
4825     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4826             final double[] qualityScores, final NEDPosition position,
4827             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
4828             final Matrix initialMm, final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
4829             final RobustEstimatorMethod method) {
4830         return switch (method) {
4831             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4832                     position, measurements, hardIron, initialMm, listener);
4833             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4834                     position, measurements, hardIron, initialMm, listener);
4835             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4836                     position, measurements, hardIron, initialMm, listener);
4837             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4838                     qualityScores, position, measurements, hardIron, initialMm, listener);
4839             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4840                     qualityScores, position, measurements, hardIron, initialMm, listener);
4841         };
4842     }
4843 
4844     /**
4845      * Creates a robust magnetometer calibrator.
4846      *
4847      * @param qualityScores  quality scores corresponding to each provided
4848      *                       measurement. The larger the score value the better
4849      *                       the quality of the sample.
4850      * @param position       position where body magnetic flux density measurements
4851      *                       have been taken.
4852      * @param measurements   collection of body magnetic flux density
4853      *                       measurements with standard deviation of
4854      *                       magnetometer measurements taken at the same
4855      *                       position with zero velocity and unknown different
4856      *                       orientations.
4857      * @param commonAxisUsed indicates whether z-axis is assumed to be common
4858      *                       for the accelerometer, gyroscope and magnetometer.
4859      * @param hardIron       known hard-iron.
4860      * @param initialMm      initial soft-iron matrix containing scale factors
4861      *                       and cross coupling errors.
4862      * @param method         robust estimator method.
4863      * @return a robust magnetometer calibrator.
4864      * @throws IllegalArgumentException if provided hard-iron matrix is not
4865      *                                  3x1 or if soft-iron matrix is not
4866      *                                  3x3 or if provided quality scores
4867      *                                  length is smaller than 10 samples.
4868      */
4869     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4870             final double[] qualityScores, final NEDPosition position,
4871             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
4872             final Matrix hardIron, final Matrix initialMm, final RobustEstimatorMethod method) {
4873         return switch (method) {
4874             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4875                     position, measurements, commonAxisUsed, hardIron, initialMm);
4876             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4877                     position, measurements, commonAxisUsed, hardIron, initialMm);
4878             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4879                     position, measurements, commonAxisUsed, hardIron, initialMm);
4880             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4881                     qualityScores, position, measurements, commonAxisUsed, hardIron, initialMm);
4882             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4883                     qualityScores, position, measurements, commonAxisUsed, hardIron, initialMm);
4884         };
4885     }
4886 
4887     /**
4888      * Creates a robust magnetometer calibrator.
4889      *
4890      * @param qualityScores  quality scores corresponding to each provided
4891      *                       measurement. The larger the score value the better
4892      *                       the quality of the sample.
4893      * @param position       position where body magnetic flux density measurements
4894      *                       have been taken.
4895      * @param measurements   collection of body magnetic flux density
4896      *                       measurements with standard deviation of
4897      *                       magnetometer measurements taken at the same
4898      *                       position with zero velocity and unknown different
4899      *                       orientations.
4900      * @param commonAxisUsed indicates whether z-axis is assumed to be common
4901      *                       for the accelerometer, gyroscope and magnetometer.
4902      * @param hardIron       known hard-iron.
4903      * @param initialMm      initial soft-iron matrix containing scale factors
4904      *                       and cross coupling errors.
4905      * @param listener       listener to handle events raised by this calibrator.
4906      * @param method         robust estimator method.
4907      * @return a robust magnetometer calibrator.
4908      * @throws IllegalArgumentException if provided hard-iron matrix is not
4909      *                                  3x1 or if soft-iron matrix is not
4910      *                                  3x3 or if provided quality scores
4911      *                                  length is smaller than 10 samples.
4912      */
4913     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4914             final double[] qualityScores, final NEDPosition position,
4915             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
4916             final Matrix hardIron, final Matrix initialMm,
4917             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
4918             final RobustEstimatorMethod method) {
4919         return switch (method) {
4920             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4921                     position, measurements, commonAxisUsed, hardIron, initialMm, listener);
4922             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4923                     position, measurements, commonAxisUsed, hardIron, initialMm, listener);
4924             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4925                     position, measurements, commonAxisUsed, hardIron, initialMm, listener);
4926             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4927                     qualityScores, position, measurements, commonAxisUsed, hardIron, initialMm, listener);
4928             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4929                     qualityScores, position, measurements, commonAxisUsed, hardIron, initialMm, listener);
4930         };
4931     }
4932 
4933     /**
4934      * Creates a robust magnetometer calibrator.
4935      *
4936      * @param qualityScores quality scores corresponding to each provided
4937      *                      measurement. The larger the score value the better
4938      *                      the quality of the sample.
4939      * @param position      position where body magnetic flux density measurements
4940      *                      have been taken.
4941      * @param method        robust estimator method.
4942      * @return a robust magnetometer calibrator.
4943      * @throws IllegalArgumentException if provided quality scores length
4944      *                                  is smaller than 10 samples.
4945      */
4946     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4947             final double[] qualityScores, final ECEFPosition position, final RobustEstimatorMethod method) {
4948         return switch (method) {
4949             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(position);
4950             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(position);
4951             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(position);
4952             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4953                     qualityScores, position);
4954             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4955                     qualityScores, position);
4956         };
4957     }
4958 
4959     /**
4960      * Creates a robust magnetometer calibrator.
4961      *
4962      * @param qualityScores quality scores corresponding to each provided
4963      *                      measurement. The larger the score value the better
4964      *                      the quality of the sample.
4965      * @param position      position where body magnetic flux density measurements
4966      *                      have been taken.
4967      * @param measurements  collection of body magnetic flux density
4968      *                      measurements with standard deviation of
4969      *                      magnetometer measurements taken at the same
4970      *                      position with zero velocity and unknown different
4971      *                      orientations.
4972      * @param method        robust estimator method.
4973      * @return a robust magnetometer calibrator.
4974      * @throws IllegalArgumentException if provided quality scores length
4975      *                                  is smaller than 10 samples.
4976      */
4977     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
4978             final double[] qualityScores, final ECEFPosition position,
4979             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final RobustEstimatorMethod method) {
4980         return switch (method) {
4981             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4982                     position, measurements);
4983             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4984                     position, measurements);
4985             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4986                     position, measurements);
4987             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4988                     qualityScores, position, measurements);
4989             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
4990                     qualityScores, position, measurements);
4991         };
4992     }
4993 
4994     /**
4995      * Creates a robust magnetometer calibrator.
4996      *
4997      * @param qualityScores quality scores corresponding to each provided
4998      *                      measurement. The larger the score value the better
4999      *                      the quality of the sample.
5000      * @param position      position where body magnetic flux density measurements
5001      *                      have been taken.
5002      * @param measurements  collection of body magnetic flux density
5003      *                      measurements with standard deviation of
5004      *                      magnetometer measurements taken at the same
5005      *                      position with zero velocity and unknown different
5006      *                      orientations.
5007      * @param listener      listener to handle events raised by this calibrator.
5008      * @param method        robust estimator method.
5009      * @return a robust magnetometer calibrator.
5010      * @throws IllegalArgumentException if provided quality scores length
5011      *                                  is smaller than 10 samples.
5012      */
5013     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5014             final double[] qualityScores, final ECEFPosition position,
5015             final List<StandardDeviationBodyMagneticFluxDensity> measurements,
5016             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
5017             final RobustEstimatorMethod method) {
5018         return switch (method) {
5019             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5020                     position, measurements, listener);
5021             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5022                     position, measurements, listener);
5023             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5024                     position, measurements, listener);
5025             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5026                     qualityScores, position, measurements, listener);
5027             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5028                     qualityScores, position, measurements, listener);
5029         };
5030     }
5031 
5032     /**
5033      * Creates a robust magnetometer calibrator.
5034      *
5035      * @param qualityScores  quality scores corresponding to each provided
5036      *                       measurement. The larger the score value the better
5037      *                       the quality of the sample.
5038      * @param position       position where body magnetic flux density measurements
5039      *                       have been taken.
5040      * @param measurements   collection of body magnetic flux density
5041      *                       measurements with standard deviation of
5042      *                       magnetometer measurements taken at the same
5043      *                       position with zero velocity and unknown different
5044      *                       orientations.
5045      * @param commonAxisUsed indicates whether z-axis is assumed to be common
5046      *                       for the accelerometer, gyroscope and magnetometer.
5047      * @param method         robust estimator method.
5048      * @return a robust magnetometer calibrator.
5049      * @throws IllegalArgumentException if provided quality scores length
5050      *                                  is smaller than 10 samples.
5051      */
5052     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5053             final double[] qualityScores, final ECEFPosition position,
5054             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
5055             final RobustEstimatorMethod method) {
5056         return switch (method) {
5057             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5058                     position, measurements, commonAxisUsed);
5059             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5060                     position, measurements, commonAxisUsed);
5061             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5062                     position, measurements, commonAxisUsed);
5063             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5064                     qualityScores, position, measurements, commonAxisUsed);
5065             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5066                     qualityScores, position, measurements, commonAxisUsed);
5067         };
5068     }
5069 
5070     /**
5071      * Creates a robust magnetometer calibrator.
5072      *
5073      * @param qualityScores  quality scores corresponding to each provided
5074      *                       measurement. The larger the score value the better
5075      *                       the quality of the sample.
5076      * @param position       position where body magnetic flux density measurements
5077      *                       have been taken.
5078      * @param measurements   collection of body magnetic flux density
5079      *                       measurements with standard deviation of
5080      *                       magnetometer measurements taken at the same
5081      *                       position with zero velocity and unknown different
5082      *                       orientations.
5083      * @param commonAxisUsed indicates whether z-axis is assumed to be common
5084      *                       for the accelerometer, gyroscope and magnetometer.
5085      * @param listener       listener to handle events raised by this calibrator.
5086      * @param method         robust estimator method.
5087      * @return a robust magnetometer calibrator.
5088      * @throws IllegalArgumentException if provided quality scores length
5089      *                                  is smaller than 10 samples.
5090      */
5091     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5092             final double[] qualityScores, final ECEFPosition position,
5093             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
5094             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
5095             final RobustEstimatorMethod method) {
5096         return switch (method) {
5097             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5098                     position, measurements, commonAxisUsed, listener);
5099             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5100                     position, measurements, commonAxisUsed, listener);
5101             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5102                     position, measurements, commonAxisUsed, listener);
5103             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5104                     qualityScores, position, measurements, commonAxisUsed, listener);
5105             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5106                     qualityScores, position, measurements, commonAxisUsed, listener);
5107         };
5108     }
5109 
5110     /**
5111      * Creates a robust magnetometer calibrator.
5112      *
5113      * @param qualityScores quality scores corresponding to each provided
5114      *                      measurement. The larger the score value the better
5115      *                      the quality of the sample.
5116      * @param position      position where body magnetic flux density measurements
5117      *                      have been taken.
5118      * @param measurements  collection of body magnetic flux density
5119      *                      measurements with standard deviation of
5120      *                      magnetometer measurements taken at the same
5121      *                      position with zero velocity and unknown different
5122      *                      orientations.
5123      * @param hardIron      known hard-iron.
5124      * @param method        robust estimator method.
5125      * @return a robust magnetometer calibrator.
5126      * @throws IllegalArgumentException if provided hard-iron array does
5127      *                                  not have length 3 or if provided
5128      *                                  quality scores length is smaller
5129      *                                  than 10 samples.
5130      */
5131     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5132             final double[] qualityScores, final ECEFPosition position,
5133             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final double[] hardIron,
5134             final RobustEstimatorMethod method) {
5135         return switch (method) {
5136             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5137                     position, measurements, hardIron);
5138             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5139                     position, measurements, hardIron);
5140             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5141                     position, measurements, hardIron);
5142             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5143                     qualityScores, position, measurements, hardIron);
5144             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5145                     qualityScores, position, measurements, hardIron);
5146         };
5147     }
5148 
5149     /**
5150      * Creates a robust magnetometer calibrator.
5151      *
5152      * @param qualityScores quality scores corresponding to each provided
5153      *                      measurement. The larger the score value the better
5154      *                      the quality of the sample.
5155      * @param position      position where body magnetic flux density measurements
5156      *                      have been taken.
5157      * @param measurements  collection of body magnetic flux density
5158      *                      measurements with standard deviation of
5159      *                      magnetometer measurements taken at the same
5160      *                      position with zero velocity and unknown different
5161      *                      orientations.
5162      * @param hardIron      known hard-iron.
5163      * @param listener      listener to handle events raised by this calibrator.
5164      * @param method        robust estimator method.
5165      * @return a robust magnetometer calibrator.
5166      * @throws IllegalArgumentException if provided hard-iron array does
5167      *                                  not have length 3 or if provided
5168      *                                  quality scores length is smaller
5169      *                                  than 10 samples.
5170      */
5171     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5172             final double[] qualityScores, final ECEFPosition position,
5173             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final double[] hardIron,
5174             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
5175             final RobustEstimatorMethod method) {
5176         return switch (method) {
5177             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5178                     position, measurements, hardIron, listener);
5179             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5180                     position, measurements, hardIron, listener);
5181             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5182                     position, measurements, hardIron, listener);
5183             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5184                     qualityScores, position, measurements, hardIron, listener);
5185             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5186                     qualityScores, position, measurements, hardIron, listener);
5187         };
5188     }
5189 
5190     /**
5191      * Creates a robust magnetometer calibrator.
5192      *
5193      * @param qualityScores  quality scores corresponding to each provided
5194      *                       measurement. The larger the score value the better
5195      *                       the quality of the sample.
5196      * @param position       position where body magnetic flux density measurements
5197      *                       have been taken.
5198      * @param measurements   collection of body magnetic flux density
5199      *                       measurements with standard deviation of
5200      *                       magnetometer measurements taken at the same
5201      *                       position with zero velocity and unknown different
5202      *                       orientations.
5203      * @param commonAxisUsed indicates whether z-axis is assumed to be common
5204      *                       for the accelerometer, gyroscope and magnetometer.
5205      * @param hardIron       known hard-iron.
5206      * @param method         robust estimator method.
5207      * @return a robust magnetometer calibrator.
5208      * @throws IllegalArgumentException if provided hard-iron array does
5209      *                                  not have length 3 or if provided
5210      *                                  quality scores length is smaller
5211      *                                  than 10 samples.
5212      */
5213     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5214             final double[] qualityScores, final ECEFPosition position,
5215             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
5216             final double[] hardIron, final RobustEstimatorMethod method) {
5217         return switch (method) {
5218             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5219                     position, measurements, commonAxisUsed, hardIron);
5220             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5221                     position, measurements, commonAxisUsed, hardIron);
5222             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5223                     position, measurements, commonAxisUsed, hardIron);
5224             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5225                     qualityScores, position, measurements, commonAxisUsed, hardIron);
5226             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5227                     qualityScores, position, measurements, commonAxisUsed, hardIron);
5228         };
5229     }
5230 
5231     /**
5232      * Creates a robust magnetometer calibrator.
5233      *
5234      * @param qualityScores  quality scores corresponding to each provided
5235      *                       measurement. The larger the score value the better
5236      *                       the quality of the sample.
5237      * @param position       position where body magnetic flux density measurements
5238      *                       have been taken.
5239      * @param measurements   collection of body magnetic flux density
5240      *                       measurements with standard deviation of
5241      *                       magnetometer measurements taken at the same
5242      *                       position with zero velocity and unknown different
5243      *                       orientations.
5244      * @param commonAxisUsed indicates whether z-axis is assumed to be common
5245      *                       for the accelerometer, gyroscope and magnetometer.
5246      * @param hardIron       known hard-iron.
5247      * @param listener       listener to handle events raised by this calibrator.
5248      * @param method         robust estimator method.
5249      * @return a robust magnetometer calibrator.
5250      * @throws IllegalArgumentException if provided hard-iron array does
5251      *                                  not have length 3 or if provided
5252      *                                  quality scores length is smaller
5253      *                                  than 10 samples.
5254      */
5255     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5256             final double[] qualityScores, final ECEFPosition position,
5257             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
5258             final double[] hardIron, final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
5259             final RobustEstimatorMethod method) {
5260         return switch (method) {
5261             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5262                     position, measurements, commonAxisUsed, hardIron, listener);
5263             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5264                     position, measurements, commonAxisUsed, hardIron, listener);
5265             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5266                     position, measurements, commonAxisUsed, hardIron, listener);
5267             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5268                     qualityScores, position, measurements, commonAxisUsed, hardIron, listener);
5269             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5270                     qualityScores, position, measurements, commonAxisUsed, hardIron, listener);
5271         };
5272     }
5273 
5274     /**
5275      * Creates a robust magnetometer calibrator.
5276      *
5277      * @param qualityScores quality scores corresponding to each provided
5278      *                      measurement. The larger the score value the better
5279      *                      the quality of the sample.
5280      * @param position      position where body magnetic flux density measurements
5281      *                      have been taken.
5282      * @param measurements  collection of body magnetic flux density
5283      *                      measurements with standard deviation of
5284      *                      magnetometer measurements taken at the same
5285      *                      position with zero velocity and unknown different
5286      *                      orientations.
5287      * @param hardIron      known hard-iron.
5288      * @param method        robust estimator method.
5289      * @return a robust magnetometer calibrator.
5290      * @throws IllegalArgumentException if provided hard-iron matrix is not
5291      *                                  3x1 or if provided quality scores
5292      *                                  length is smaller than 10 samples.
5293      */
5294     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5295             final double[] qualityScores, final ECEFPosition position,
5296             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
5297             final RobustEstimatorMethod method) {
5298         return switch (method) {
5299             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5300                     position, measurements, hardIron);
5301             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5302                     position, measurements, hardIron);
5303             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5304                     position, measurements, hardIron);
5305             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5306                     qualityScores, position, measurements, hardIron);
5307             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5308                     qualityScores, position, measurements, hardIron);
5309         };
5310     }
5311 
5312     /**
5313      * Creates a robust magnetometer calibrator.
5314      *
5315      * @param qualityScores quality scores corresponding to each provided
5316      *                      measurement. The larger the score value the better
5317      *                      the quality of the sample.
5318      * @param position      position where body magnetic flux density measurements
5319      *                      have been taken.
5320      * @param measurements  collection of body magnetic flux density
5321      *                      measurements with standard deviation of
5322      *                      magnetometer measurements taken at the same
5323      *                      position with zero velocity and unknown different
5324      *                      orientations.
5325      * @param hardIron      known hard-iron.
5326      * @param listener      listener to handle events raised by this calibrator.
5327      * @param method        robust estimator method.
5328      * @return a robust magnetometer calibrator.
5329      * @throws IllegalArgumentException if provided hard-iron matrix is not
5330      *                                  3x1 or if provided quality scores
5331      *                                  length is smaller than 10 samples.
5332      */
5333     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5334             final double[] qualityScores, final ECEFPosition position,
5335             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
5336             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
5337             final RobustEstimatorMethod method) {
5338         return switch (method) {
5339             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5340                     position, measurements, hardIron, listener);
5341             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5342                     position, measurements, hardIron, listener);
5343             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5344                     position, measurements, hardIron, listener);
5345             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5346                     qualityScores, position, measurements, hardIron, listener);
5347             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5348                     qualityScores, position, measurements, hardIron, listener);
5349         };
5350     }
5351 
5352     /**
5353      * Creates a robust magnetometer calibrator.
5354      *
5355      * @param qualityScores  quality scores corresponding to each provided
5356      *                       measurement. The larger the score value the better
5357      *                       the quality of the sample.
5358      * @param position       position where body magnetic flux density measurements
5359      *                       have been taken.
5360      * @param measurements   collection of body magnetic flux density
5361      *                       measurements with standard deviation of
5362      *                       magnetometer measurements taken at the same
5363      *                       position with zero velocity and unknown different
5364      *                       orientations.
5365      * @param commonAxisUsed indicates whether z-axis is assumed to be common
5366      *                       for the accelerometer, gyroscope and magnetometer.
5367      * @param hardIron       known hard-iron.
5368      * @param method         robust estimator method.
5369      * @return a robust magnetometer calibrator.
5370      */
5371     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5372             final double[] qualityScores, final ECEFPosition position,
5373             final List<StandardDeviationBodyMagneticFluxDensity> measurements,
5374             final boolean commonAxisUsed, final Matrix hardIron, final RobustEstimatorMethod method) {
5375         return switch (method) {
5376             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5377                     position, measurements, commonAxisUsed, hardIron);
5378             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5379                     position, measurements, commonAxisUsed, hardIron);
5380             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5381                     position, measurements, commonAxisUsed, hardIron);
5382             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5383                     qualityScores, position, measurements, commonAxisUsed, hardIron);
5384             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5385                     qualityScores, position, measurements, commonAxisUsed, hardIron);
5386         };
5387     }
5388 
5389     /**
5390      * Creates a robust magnetometer calibrator.
5391      *
5392      * @param qualityScores  quality scores corresponding to each provided
5393      *                       measurement. The larger the score value the better
5394      *                       the quality of the sample.
5395      * @param position       position where body magnetic flux density measurements
5396      *                       have been taken.
5397      * @param measurements   collection of body magnetic flux density
5398      *                       measurements with standard deviation of
5399      *                       magnetometer measurements taken at the same
5400      *                       position with zero velocity and unknown different
5401      *                       orientations.
5402      * @param commonAxisUsed indicates whether z-axis is assumed to be common
5403      *                       for the accelerometer, gyroscope and magnetometer.
5404      * @param hardIron       known hard-iron.
5405      * @param listener       listener to handle events raised by this calibrator.
5406      * @param method         robust estimator method.
5407      * @return a robust magnetometer calibrator.
5408      * @throws IllegalArgumentException if provided hard-iron matrix is not
5409      *                                  3x1 or if provided quality scores
5410      *                                  length is smaller than 10 samples.
5411      */
5412     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5413             final double[] qualityScores, final ECEFPosition position,
5414             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
5415             final Matrix hardIron, final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
5416             final RobustEstimatorMethod method) {
5417         return switch (method) {
5418             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5419                     position, measurements, commonAxisUsed, hardIron, listener);
5420             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5421                     position, measurements, commonAxisUsed, hardIron, listener);
5422             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5423                     position, measurements, commonAxisUsed, hardIron, listener);
5424             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5425                     qualityScores, position, measurements, commonAxisUsed, hardIron, listener);
5426             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5427                     qualityScores, position, measurements, commonAxisUsed, hardIron, listener);
5428         };
5429     }
5430 
5431     /**
5432      * Creates a robust magnetometer calibrator.
5433      *
5434      * @param qualityScores quality scores corresponding to each provided
5435      *                      measurement. The larger the score value the better
5436      *                      the quality of the sample.
5437      * @param position      position where body magnetic flux density measurements
5438      *                      have been taken.
5439      * @param measurements  collection of body magnetic flux density
5440      *                      measurements with standard deviation of
5441      *                      magnetometer measurements taken at the same
5442      *                      position with zero velocity and unknown different
5443      *                      orientations.
5444      * @param hardIron      known hard-iron.
5445      * @param initialMm     initial soft-iron matrix containing scale factors
5446      *                      and cross coupling errors.
5447      * @param method        robust estimator method.
5448      * @return a robust magnetometer calibrator.
5449      * @throws IllegalArgumentException if provided hard-iron matrix is not
5450      *                                  3x1 or if soft-iron matrix is not
5451      *                                  3x3 or if provided quality scores
5452      *                                  length is smaller than 10 samples.
5453      */
5454     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5455             final double[] qualityScores, final ECEFPosition position,
5456             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
5457             final Matrix initialMm, final RobustEstimatorMethod method) {
5458         return switch (method) {
5459             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5460                     position, measurements, hardIron, initialMm);
5461             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5462                     position, measurements, hardIron, initialMm);
5463             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5464                     position, measurements, hardIron, initialMm);
5465             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5466                     qualityScores, position, measurements, hardIron, initialMm);
5467             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5468                     qualityScores, position, measurements, hardIron, initialMm);
5469         };
5470     }
5471 
5472     /**
5473      * Creates a robust magnetometer calibrator.
5474      *
5475      * @param qualityScores quality scores corresponding to each provided
5476      *                      measurement. The larger the score value the better
5477      *                      the quality of the sample.
5478      * @param position      position where body magnetic flux density measurements
5479      *                      have been taken.
5480      * @param measurements  collection of body magnetic flux density
5481      *                      measurements with standard deviation of
5482      *                      magnetometer measurements taken at the same
5483      *                      position with zero velocity and unknown different
5484      *                      orientations.
5485      * @param hardIron      known hard-iron.
5486      * @param initialMm     initial soft-iron matrix containing scale factors
5487      *                      and cross coupling errors.
5488      * @param listener      listener to handle events raised by this calibrator.
5489      * @param method        robust estimator method.
5490      * @return a robust magnetometer calibrator.
5491      * @throws IllegalArgumentException if provided hard-iron matrix is not
5492      *                                  3x1 or if soft-iron matrix is not
5493      *                                  3x3 or if provided quality scores
5494      *                                  length is smaller than 10 samples.
5495      */
5496     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5497             final double[] qualityScores, final ECEFPosition position,
5498             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
5499             final Matrix initialMm, final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
5500             final RobustEstimatorMethod method) {
5501         return switch (method) {
5502             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5503                     position, measurements, hardIron, initialMm, listener);
5504             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5505                     position, measurements, hardIron, initialMm, listener);
5506             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5507                     position, measurements, hardIron, initialMm, listener);
5508             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5509                     qualityScores, position, measurements, hardIron, initialMm, listener);
5510             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5511                     qualityScores, position, measurements, hardIron, initialMm, listener);
5512         };
5513     }
5514 
5515     /**
5516      * Creates a robust magnetometer calibrator.
5517      *
5518      * @param qualityScores  quality scores corresponding to each provided
5519      *                       measurement. The larger the score value the better
5520      *                       the quality of the sample.
5521      * @param position       position where body magnetic flux density measurements
5522      *                       have been taken.
5523      * @param measurements   collection of body magnetic flux density
5524      *                       measurements with standard deviation of
5525      *                       magnetometer measurements taken at the same
5526      *                       position with zero velocity and unknown different
5527      *                       orientations.
5528      * @param commonAxisUsed indicates whether z-axis is assumed to be common
5529      *                       for the accelerometer, gyroscope and magnetometer.
5530      * @param hardIron       known hard-iron.
5531      * @param initialMm      initial soft-iron matrix containing scale factors
5532      *                       and cross coupling errors.
5533      * @param method         robust estimator method.
5534      * @return a robust magnetometer calibrator.
5535      * @throws IllegalArgumentException if provided hard-iron matrix is not
5536      *                                  3x1 or if soft-iron matrix is not
5537      *                                  3x3 or if provided quality scores
5538      *                                  length is smaller than 10 samples.
5539      */
5540     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5541             final double[] qualityScores, final ECEFPosition position,
5542             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
5543             final Matrix hardIron, final Matrix initialMm, final RobustEstimatorMethod method) {
5544         return switch (method) {
5545             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5546                     position, measurements, commonAxisUsed, hardIron, initialMm);
5547             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5548                     position, measurements, commonAxisUsed, hardIron, initialMm);
5549             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5550                     position, measurements, commonAxisUsed, hardIron, initialMm);
5551             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5552                     qualityScores, position, measurements, commonAxisUsed, hardIron, initialMm);
5553             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5554                     qualityScores, position, measurements, commonAxisUsed, hardIron, initialMm);
5555         };
5556     }
5557 
5558     /**
5559      * Creates a robust magnetometer calibrator.
5560      *
5561      * @param qualityScores  quality scores corresponding to each provided
5562      *                       measurement. The larger the score value the better
5563      *                       the quality of the sample.
5564      * @param position       position where body magnetic flux density measurements
5565      *                       have been taken.
5566      * @param measurements   collection of body magnetic flux density
5567      *                       measurements with standard deviation of
5568      *                       magnetometer measurements taken at the same
5569      *                       position with zero velocity and unknown different
5570      *                       orientations.
5571      * @param commonAxisUsed indicates whether z-axis is assumed to be common
5572      *                       for the accelerometer, gyroscope and magnetometer.
5573      * @param hardIron       known hard-iron.
5574      * @param initialMm      initial soft-iron matrix containing scale factors
5575      *                       and cross coupling errors.
5576      * @param listener       listener to handle events raised by this calibrator.
5577      * @param method         robust estimator method.
5578      * @return a robust magnetometer calibrator.
5579      * @throws IllegalArgumentException if provided hard-iron matrix is not
5580      *                                  3x1 or if soft-iron matrix is not
5581      *                                  3x3 or if provided quality scores
5582      *                                  length is smaller than 10 samples.
5583      */
5584     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5585             final double[] qualityScores, final ECEFPosition position,
5586             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
5587             final Matrix hardIron, final Matrix initialMm,
5588             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener,
5589             final RobustEstimatorMethod method) {
5590         return switch (method) {
5591             case RANSAC -> new RANSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5592                     position, measurements, commonAxisUsed, hardIron, initialMm, listener);
5593             case LMEDS -> new LMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5594                     position, measurements, commonAxisUsed, hardIron, initialMm, listener);
5595             case MSAC -> new MSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5596                     position, measurements, commonAxisUsed, hardIron, initialMm, listener);
5597             case PROSAC -> new PROSACRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5598                     qualityScores, position, measurements, commonAxisUsed, hardIron, initialMm, listener);
5599             default -> new PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
5600                     qualityScores, position, measurements, commonAxisUsed, hardIron, initialMm, listener);
5601         };
5602     }
5603 
5604     /**
5605      * Creates a robust magnetometer calibrator with default robust method.
5606      *
5607      * @return a robust magnetometer calibrator.
5608      */
5609     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create() {
5610         return create(DEFAULT_ROBUST_METHOD);
5611     }
5612 
5613     /**
5614      * Creates a robust magnetometer calibrator with default robust method.
5615      *
5616      * @param listener listener to handle events raised by this calibrator.
5617      * @return a robust magnetometer calibrator.
5618      */
5619     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5620             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
5621         return create(listener, DEFAULT_ROBUST_METHOD);
5622     }
5623 
5624     /**
5625      * Creates a robust magnetometer calibrator with default robust method.
5626      *
5627      * @param measurements list of body magnetic flux density
5628      *                     measurements with standard deviation of
5629      *                     magnetometer measurements taken at the same
5630      *                     position with zero velocity and unknown different
5631      *                     orientations.
5632      * @return a robust magnetometer calibrator.
5633      */
5634     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5635             final List<StandardDeviationBodyMagneticFluxDensity> measurements) {
5636         return create(measurements, DEFAULT_ROBUST_METHOD);
5637     }
5638 
5639     /**
5640      * Creates a robust magnetometer calibrator with default robust method.
5641      *
5642      * @param commonAxisUsed indicates whether z-axis is assumed to be common
5643      *                       for the accelerometer, gyroscope and magnetometer.
5644      * @return a robust magnetometer calibrator.
5645      */
5646     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(final boolean commonAxisUsed) {
5647         return create(commonAxisUsed, DEFAULT_ROBUST_METHOD);
5648     }
5649 
5650     /**
5651      * Creates a robust magnetometer calibrator with default robust method.
5652      *
5653      * @param magneticModel Earth's magnetic model. If null, a default model
5654      *                      will be used instead.
5655      * @return a robust magnetometer calibrator.
5656      */
5657     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5658             final WorldMagneticModel magneticModel) {
5659         return create(magneticModel, DEFAULT_ROBUST_METHOD);
5660     }
5661 
5662     /**
5663      * Creates a robust magnetometer calibrator with default robust method.
5664      *
5665      * @param hardIron known hard-iron.
5666      * @return a robust magnetometer calibrator.
5667      * @throws IllegalArgumentException if provided hard-iron array does
5668      *                                  not have length 3.
5669      */
5670     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(final double[] hardIron) {
5671         return create(hardIron, DEFAULT_ROBUST_METHOD);
5672     }
5673 
5674     /**
5675      * Creates a robust magnetometer calibrator with default robust method.
5676      *
5677      * @param hardIron known hard-iron.
5678      * @return a robust magnetometer calibrator.
5679      * @throws IllegalArgumentException if provided hard-iron matrix is not
5680      *                                  3x1.
5681      */
5682     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(final Matrix hardIron) {
5683         return create(hardIron, DEFAULT_ROBUST_METHOD);
5684     }
5685 
5686     /**
5687      * Creates a robust magnetometer calibrator with default robust method.
5688      *
5689      * @param hardIron  known hard-iron.
5690      * @param initialMm initial soft-iron matrix containing scale factors
5691      *                  and cross coupling errors.
5692      * @return a robust magnetometer calibrator.
5693      * @throws IllegalArgumentException if provided hard-iron matrix is not
5694      *                                  3x1 or if soft-iron matrix is not
5695      *                                  3x3.
5696      */
5697     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5698             final Matrix hardIron, final Matrix initialMm) {
5699         return create(hardIron, initialMm, DEFAULT_ROBUST_METHOD);
5700     }
5701 
5702     /**
5703      * Creates a robust magnetometer calibrator with default robust method.
5704      *
5705      * @param position position where body magnetic flux density measurements
5706      *                 have been taken.
5707      * @return a robust magnetometer calibrator.
5708      */
5709     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(final NEDPosition position) {
5710         return create(position, DEFAULT_ROBUST_METHOD);
5711     }
5712 
5713     /**
5714      * Creates a robust magnetometer calibrator with default robust method.
5715      *
5716      * @param position     position where body magnetic flux density measurements
5717      *                     have been taken.
5718      * @param measurements collection of body magnetic flux density
5719      *                     measurements with standard deviation of
5720      *                     magnetometer measurements taken at the same
5721      *                     position with zero velocity and unknown different
5722      *                     orientations.
5723      * @return a robust magnetometer calibrator.
5724      */
5725     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5726             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements) {
5727         return create(position, measurements, DEFAULT_ROBUST_METHOD);
5728     }
5729 
5730     /**
5731      * Creates a robust magnetometer calibrator with default robust method.
5732      *
5733      * @param position     position where body magnetic flux density measurements
5734      *                     have been taken.
5735      * @param measurements collection of body magnetic flux density
5736      *                     measurements with standard deviation of
5737      *                     magnetometer measurements taken at the same
5738      *                     position with zero velocity and unknown different
5739      *                     orientations.
5740      * @param listener     listener to handle events raised by this calibrator.
5741      * @return a robust magnetometer calibrator.
5742      */
5743     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5744             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
5745             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
5746         return create(position, measurements, listener, DEFAULT_ROBUST_METHOD);
5747     }
5748 
5749     /**
5750      * Creates a robust magnetometer calibrator with default robust method.
5751      *
5752      * @param position       position where body magnetic flux density measurements
5753      *                       have been taken.
5754      * @param measurements   collection of body magnetic flux density
5755      *                       measurements with standard deviation of
5756      *                       magnetometer measurements taken at the same
5757      *                       position with zero velocity and unknown different
5758      *                       orientations.
5759      * @param commonAxisUsed indicates whether z-axis is assumed to be common
5760      *                       for the accelerometer, gyroscope and magnetometer.
5761      * @return a robust magnetometer calibrator.
5762      */
5763     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5764             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
5765             final boolean commonAxisUsed) {
5766         return create(position, measurements, commonAxisUsed, DEFAULT_ROBUST_METHOD);
5767     }
5768 
5769     /**
5770      * Creates a robust magnetometer calibrator with default robust method.
5771      *
5772      * @param position       position where body magnetic flux density measurements
5773      *                       have been taken.
5774      * @param measurements   collection of body magnetic flux density
5775      *                       measurements with standard deviation of
5776      *                       magnetometer measurements taken at the same
5777      *                       position with zero velocity and unknown different
5778      *                       orientations.
5779      * @param commonAxisUsed indicates whether z-axis is assumed to be common
5780      *                       for the accelerometer, gyroscope and magnetometer.
5781      * @param listener       listener to handle events raised by this calibrator.
5782      * @return a robust magnetometer calibrator.
5783      */
5784     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5785             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
5786             final boolean commonAxisUsed,
5787             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
5788         return create(position, measurements, commonAxisUsed, listener, DEFAULT_ROBUST_METHOD);
5789     }
5790 
5791     /**
5792      * Creates a robust magnetometer calibrator with default robust method.
5793      *
5794      * @param position     position where body magnetic flux density measurements
5795      *                     have been taken.
5796      * @param measurements collection of body magnetic flux density
5797      *                     measurements with standard deviation of
5798      *                     magnetometer measurements taken at the same
5799      *                     position with zero velocity and unknown different
5800      *                     orientations.
5801      * @param hardIron     known hard-iron.
5802      * @return a robust magnetometer calibrator.
5803      * @throws IllegalArgumentException if provided hard-iron array does
5804      *                                  not have length 3.
5805      */
5806     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5807             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
5808             final double[] hardIron) {
5809         return create(position, measurements, hardIron, DEFAULT_ROBUST_METHOD);
5810     }
5811 
5812     /**
5813      * Creates a robust magnetometer calibrator with default robust method.
5814      *
5815      * @param position     position where body magnetic flux density measurements
5816      *                     have been taken.
5817      * @param measurements collection of body magnetic flux density
5818      *                     measurements with standard deviation of
5819      *                     magnetometer measurements taken at the same
5820      *                     position with zero velocity and unknown different
5821      *                     orientations.
5822      * @param hardIron     known hard-iron.
5823      * @param listener     listener to handle events raised by this calibrator.
5824      * @return a robust magnetometer calibrator.
5825      * @throws IllegalArgumentException if provided hard-iron array does
5826      *                                  not have length 3.
5827      */
5828     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5829             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
5830             final double[] hardIron,
5831             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
5832         return create(position, measurements, hardIron, listener, DEFAULT_ROBUST_METHOD);
5833     }
5834 
5835     /**
5836      * Creates a robust magnetometer calibrator with default robust method.
5837      *
5838      * @param position       position where body magnetic flux density measurements
5839      *                       have been taken.
5840      * @param measurements   collection of body magnetic flux density
5841      *                       measurements with standard deviation of
5842      *                       magnetometer measurements taken at the same
5843      *                       position with zero velocity and unknown different
5844      *                       orientations.
5845      * @param commonAxisUsed indicates whether z-axis is assumed to be common
5846      *                       for the accelerometer, gyroscope and magnetometer.
5847      * @param hardIron       known hard-iron.
5848      * @return a robust magnetometer calibrator.
5849      * @throws IllegalArgumentException if provided hard-iron array does
5850      *                                  not have length 3.
5851      */
5852     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5853             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
5854             final boolean commonAxisUsed, final double[] hardIron) {
5855         return create(position, measurements, commonAxisUsed, hardIron, DEFAULT_ROBUST_METHOD);
5856     }
5857 
5858     /**
5859      * Creates a robust magnetometer calibrator with default robust method.
5860      *
5861      * @param position       position where body magnetic flux density measurements
5862      *                       have been taken.
5863      * @param measurements   collection of body magnetic flux density
5864      *                       measurements with standard deviation of
5865      *                       magnetometer measurements taken at the same
5866      *                       position with zero velocity and unknown different
5867      *                       orientations.
5868      * @param commonAxisUsed indicates whether z-axis is assumed to be common
5869      *                       for the accelerometer, gyroscope and magnetometer.
5870      * @param hardIron       known hard-iron.
5871      * @param listener       listener to handle events raised by this calibrator.
5872      * @return a robust magnetometer calibrator.
5873      * @throws IllegalArgumentException if provided hard-iron array does
5874      *                                  not have length 3.
5875      */
5876     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5877             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
5878             final boolean commonAxisUsed, final double[] hardIron,
5879             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
5880         return create(position, measurements, commonAxisUsed, hardIron, listener, DEFAULT_ROBUST_METHOD);
5881     }
5882 
5883     /**
5884      * Creates a robust magnetometer calibrator with default robust method.
5885      *
5886      * @param position     position where body magnetic flux density measurements
5887      *                     have been taken.
5888      * @param measurements collection of body magnetic flux density
5889      *                     measurements with standard deviation of
5890      *                     magnetometer measurements taken at the same
5891      *                     position with zero velocity and unknown different
5892      *                     orientations.
5893      * @param hardIron     known hard-iron.
5894      * @return a robust magnetometer calibrator.
5895      * @throws IllegalArgumentException if provided hard-iron matrix is not
5896      *                                  3x1.
5897      */
5898     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5899             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
5900             final Matrix hardIron) {
5901         return create(position, measurements, hardIron, DEFAULT_ROBUST_METHOD);
5902     }
5903 
5904     /**
5905      * Creates a robust magnetometer calibrator with default robust method.
5906      *
5907      * @param position     position where body magnetic flux density measurements
5908      *                     have been taken.
5909      * @param measurements collection of body magnetic flux density
5910      *                     measurements with standard deviation of
5911      *                     magnetometer measurements taken at the same
5912      *                     position with zero velocity and unknown different
5913      *                     orientations.
5914      * @param hardIron     known hard-iron.
5915      * @param listener     listener to handle events raised by this calibrator.
5916      * @return a robust magnetometer calibrator.
5917      * @throws IllegalArgumentException if provided hard-iron matrix is not
5918      *                                  3x1.
5919      */
5920     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5921             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
5922             final Matrix hardIron, final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
5923         return create(position, measurements, hardIron, listener, DEFAULT_ROBUST_METHOD);
5924     }
5925 
5926     /**
5927      * Creates a robust magnetometer calibrator with default robust method.
5928      *
5929      * @param position       position where body magnetic flux density measurements
5930      *                       have been taken.
5931      * @param measurements   collection of body magnetic flux density
5932      *                       measurements with standard deviation of
5933      *                       magnetometer measurements taken at the same
5934      *                       position with zero velocity and unknown different
5935      *                       orientations.
5936      * @param commonAxisUsed indicates whether z-axis is assumed to be common
5937      *                       for the accelerometer, gyroscope and magnetometer.
5938      * @param hardIron       known hard-iron.
5939      * @return a robust magnetometer calibrator.
5940      * @throws IllegalArgumentException if provided hard-iron matrix is not
5941      *                                  3x1.
5942      */
5943     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5944             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
5945             final boolean commonAxisUsed, final Matrix hardIron) {
5946         return create(position, measurements, commonAxisUsed, hardIron, DEFAULT_ROBUST_METHOD);
5947     }
5948 
5949     /**
5950      * Creates a robust magnetometer calibrator with default robust method.
5951      *
5952      * @param position       position where body magnetic flux density measurements
5953      *                       have been taken.
5954      * @param measurements   collection of body magnetic flux density
5955      *                       measurements with standard deviation of
5956      *                       magnetometer measurements taken at the same
5957      *                       position with zero velocity and unknown different
5958      *                       orientations.
5959      * @param commonAxisUsed indicates whether z-axis is assumed to be common
5960      *                       for the accelerometer, gyroscope and magnetometer.
5961      * @param hardIron       known hard-iron.
5962      * @param listener       listener to handle events raised by this calibrator.
5963      * @return a robust magnetometer calibrator.
5964      * @throws IllegalArgumentException if provided hard-iron matrix is not
5965      *                                  3x1.
5966      */
5967     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5968             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
5969             final boolean commonAxisUsed, final Matrix hardIron,
5970             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
5971         return create(position, measurements, commonAxisUsed, hardIron, listener, DEFAULT_ROBUST_METHOD);
5972     }
5973 
5974     /**
5975      * Creates a robust magnetometer calibrator with default robust method.
5976      *
5977      * @param position     position where body magnetic flux density measurements
5978      *                     have been taken.
5979      * @param measurements collection of body magnetic flux density
5980      *                     measurements with standard deviation of
5981      *                     magnetometer measurements taken at the same
5982      *                     position with zero velocity and unknown different
5983      *                     orientations.
5984      * @param hardIron     known hard-iron.
5985      * @param initialMm    initial soft-iron matrix containing scale factors
5986      *                     and cross coupling errors.
5987      * @return a robust magnetometer calibrator.
5988      * @throws IllegalArgumentException if provided hard-iron matrix is not
5989      *                                  3x1 or if soft-iron matrix is not
5990      *                                  3x3.
5991      */
5992     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
5993             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
5994             final Matrix hardIron, final Matrix initialMm) {
5995         return create(position, measurements, hardIron, initialMm, DEFAULT_ROBUST_METHOD);
5996     }
5997 
5998     /**
5999      * Creates a robust magnetometer calibrator with default robust method.
6000      *
6001      * @param position     position where body magnetic flux density measurements
6002      *                     have been taken.
6003      * @param measurements collection of body magnetic flux density
6004      *                     measurements with standard deviation of
6005      *                     magnetometer measurements taken at the same
6006      *                     position with zero velocity and unknown different
6007      *                     orientations.
6008      * @param hardIron     known hard-iron.
6009      * @param initialMm    initial soft-iron matrix containing scale factors
6010      *                     and cross coupling errors.
6011      * @param listener     listener to handle events raised by this calibrator.
6012      * @return a robust magnetometer calibrator.
6013      * @throws IllegalArgumentException if provided hard-iron matrix is not
6014      *                                  3x1 or if soft-iron matrix is not
6015      *                                  3x3.
6016      */
6017     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6018             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
6019             final Matrix hardIron, final Matrix initialMm,
6020             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
6021         return create(position, measurements, hardIron, initialMm, listener, DEFAULT_ROBUST_METHOD);
6022     }
6023 
6024     /**
6025      * Creates a robust magnetometer calibrator with default robust method.
6026      *
6027      * @param position       position where body magnetic flux density measurements
6028      *                       have been taken.
6029      * @param measurements   collection of body magnetic flux density
6030      *                       measurements with standard deviation of
6031      *                       magnetometer measurements taken at the same
6032      *                       position with zero velocity and unknown different
6033      *                       orientations.
6034      * @param commonAxisUsed indicates whether z-axis is assumed to be common
6035      *                       for the accelerometer, gyroscope and magnetometer.
6036      * @param hardIron       known hard-iron.
6037      * @param initialMm      initial soft-iron matrix containing scale factors
6038      *                       and cross coupling errors.
6039      * @return a robust magnetometer calibrator.
6040      * @throws IllegalArgumentException if provided hard-iron matrix is not
6041      *                                  3x1 or if soft-iron matrix is not
6042      *                                  3x3.
6043      */
6044     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6045             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
6046             final boolean commonAxisUsed, final Matrix hardIron, final Matrix initialMm) {
6047         return create(position, measurements, commonAxisUsed, hardIron, initialMm, DEFAULT_ROBUST_METHOD);
6048     }
6049 
6050     /**
6051      * Creates a robust magnetometer calibrator with default robust method.
6052      *
6053      * @param position       position where body magnetic flux density measurements
6054      *                       have been taken.
6055      * @param measurements   collection of body magnetic flux density
6056      *                       measurements with standard deviation of
6057      *                       magnetometer measurements taken at the same
6058      *                       position with zero velocity and unknown different
6059      *                       orientations.
6060      * @param commonAxisUsed indicates whether z-axis is assumed to be common
6061      *                       for the accelerometer, gyroscope and magnetometer.
6062      * @param hardIron       known hard-iron.
6063      * @param initialMm      initial soft-iron matrix containing scale factors
6064      *                       and cross coupling errors.
6065      * @param listener       listener to handle events raised by this calibrator.
6066      * @return a robust magnetometer calibrator.
6067      * @throws IllegalArgumentException if provided hard-iron matrix is not
6068      *                                  3x1 or if soft-iron matrix is not
6069      *                                  3x3.
6070      */
6071     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6072             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
6073             final boolean commonAxisUsed, final Matrix hardIron, final Matrix initialMm,
6074             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
6075         return create(position, measurements, commonAxisUsed, hardIron, initialMm, listener, DEFAULT_ROBUST_METHOD);
6076     }
6077 
6078     /**
6079      * Creates a robust magnetometer calibrator with default robust method.
6080      *
6081      * @param position position where body magnetic flux density measurements
6082      *                 have been taken.
6083      * @return a robust magnetometer calibrator.
6084      */
6085     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(final ECEFPosition position) {
6086         return create(position, DEFAULT_ROBUST_METHOD);
6087     }
6088 
6089     /**
6090      * Creates a robust magnetometer calibrator with default robust method.
6091      *
6092      * @param position     position where body magnetic flux density measurements
6093      *                     have been taken.
6094      * @param measurements collection of body magnetic flux density
6095      *                     measurements with standard deviation of
6096      *                     magnetometer measurements taken at the same
6097      *                     position with zero velocity and unknown different
6098      *                     orientations.
6099      * @return a robust magnetometer calibrator.
6100      */
6101     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6102             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements) {
6103         return create(position, measurements, DEFAULT_ROBUST_METHOD);
6104     }
6105 
6106     /**
6107      * Creates a robust magnetometer calibrator with default robust method.
6108      *
6109      * @param position     position where body magnetic flux density measurements
6110      *                     have been taken.
6111      * @param measurements collection of body magnetic flux density
6112      *                     measurements with standard deviation of
6113      *                     magnetometer measurements taken at the same
6114      *                     position with zero velocity and unknown different
6115      *                     orientations.
6116      * @param listener     listener to handle events raised by this calibrator.
6117      * @return a robust magnetometer calibrator.
6118      */
6119     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6120             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
6121             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
6122         return create(position, measurements, listener, DEFAULT_ROBUST_METHOD);
6123     }
6124 
6125     /**
6126      * Creates a robust magnetometer calibrator with default robust method.
6127      *
6128      * @param position       position where body magnetic flux density measurements
6129      *                       have been taken.
6130      * @param measurements   collection of body magnetic flux density
6131      *                       measurements with standard deviation of
6132      *                       magnetometer measurements taken at the same
6133      *                       position with zero velocity and unknown different
6134      *                       orientations.
6135      * @param commonAxisUsed indicates whether z-axis is assumed to be common
6136      *                       for the accelerometer, gyroscope and magnetometer.
6137      * @return a robust magnetometer calibrator.
6138      */
6139     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6140             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
6141             final boolean commonAxisUsed) {
6142         return create(position, measurements, commonAxisUsed, DEFAULT_ROBUST_METHOD);
6143     }
6144 
6145     /**
6146      * Creates a robust magnetometer calibrator with default robust method.
6147      *
6148      * @param position       position where body magnetic flux density measurements
6149      *                       have been taken.
6150      * @param measurements   collection of body magnetic flux density
6151      *                       measurements with standard deviation of
6152      *                       magnetometer measurements taken at the same
6153      *                       position with zero velocity and unknown different
6154      *                       orientations.
6155      * @param commonAxisUsed indicates whether z-axis is assumed to be common
6156      *                       for the accelerometer, gyroscope and magnetometer.
6157      * @param listener       listener to handle events raised by this calibrator.
6158      * @return a robust magnetometer calibrator.
6159      */
6160     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6161             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
6162             final boolean commonAxisUsed,
6163             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
6164         return create(position, measurements, commonAxisUsed, listener, DEFAULT_ROBUST_METHOD);
6165     }
6166 
6167     /**
6168      * Creates a robust magnetometer calibrator with default robust method.
6169      *
6170      * @param position     position where body magnetic flux density measurements
6171      *                     have been taken.
6172      * @param measurements collection of body magnetic flux density
6173      *                     measurements with standard deviation of
6174      *                     magnetometer measurements taken at the same
6175      *                     position with zero velocity and unknown different
6176      *                     orientations.
6177      * @param hardIron     known hard-iron.
6178      * @return a robust magnetometer calibrator.
6179      * @throws IllegalArgumentException if provided hard-iron array does
6180      *                                  not have length 3.
6181      */
6182     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6183             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
6184             final double[] hardIron) {
6185         return create(position, measurements, hardIron, DEFAULT_ROBUST_METHOD);
6186     }
6187 
6188     /**
6189      * Creates a robust magnetometer calibrator with default robust method.
6190      *
6191      * @param position     position where body magnetic flux density measurements
6192      *                     have been taken.
6193      * @param measurements collection of body magnetic flux density
6194      *                     measurements with standard deviation of
6195      *                     magnetometer measurements taken at the same
6196      *                     position with zero velocity and unknown different
6197      *                     orientations.
6198      * @param hardIron     known hard-iron.
6199      * @param listener     listener to handle events raised by this calibrator.
6200      * @return a robust magnetometer calibrator.
6201      * @throws IllegalArgumentException if provided hard-iron array does
6202      *                                  not have length 3.
6203      */
6204     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6205             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
6206             final double[] hardIron,
6207             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
6208         return create(position, measurements, hardIron, listener, DEFAULT_ROBUST_METHOD);
6209     }
6210 
6211     /**
6212      * Creates a robust magnetometer calibrator with default robust method.
6213      *
6214      * @param position       position where body magnetic flux density measurements
6215      *                       have been taken.
6216      * @param measurements   collection of body magnetic flux density
6217      *                       measurements with standard deviation of
6218      *                       magnetometer measurements taken at the same
6219      *                       position with zero velocity and unknown different
6220      *                       orientations.
6221      * @param commonAxisUsed indicates whether z-axis is assumed to be common
6222      *                       for the accelerometer, gyroscope and magnetometer.
6223      * @param hardIron       known hard-iron.
6224      * @return a robust magnetometer calibrator.
6225      * @throws IllegalArgumentException if provided hard-iron array does
6226      *                                  not have length 3.
6227      */
6228     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6229             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
6230             final boolean commonAxisUsed, final double[] hardIron) {
6231         return create(position, measurements, commonAxisUsed, hardIron, DEFAULT_ROBUST_METHOD);
6232     }
6233 
6234     /**
6235      * Creates a robust magnetometer calibrator with default robust method.
6236      *
6237      * @param position       position where body magnetic flux density measurements
6238      *                       have been taken.
6239      * @param measurements   collection of body magnetic flux density
6240      *                       measurements with standard deviation of
6241      *                       magnetometer measurements taken at the same
6242      *                       position with zero velocity and unknown different
6243      *                       orientations.
6244      * @param commonAxisUsed indicates whether z-axis is assumed to be common
6245      *                       for the accelerometer, gyroscope and magnetometer.
6246      * @param hardIron       known hard-iron.
6247      * @param listener       listener to handle events raised by this calibrator.
6248      * @return a robust magnetometer calibrator.
6249      * @throws IllegalArgumentException if provided hard-iron array does
6250      *                                  not have length 3.
6251      */
6252     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6253             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
6254             final boolean commonAxisUsed, final double[] hardIron,
6255             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
6256         return create(position, measurements, commonAxisUsed, hardIron, listener, DEFAULT_ROBUST_METHOD);
6257     }
6258 
6259     /**
6260      * Creates a robust magnetometer calibrator with default robust method.
6261      *
6262      * @param position     position where body magnetic flux density measurements
6263      *                     have been taken.
6264      * @param measurements collection of body magnetic flux density
6265      *                     measurements with standard deviation of
6266      *                     magnetometer measurements taken at the same
6267      *                     position with zero velocity and unknown different
6268      *                     orientations.
6269      * @param hardIron     known hard-iron.
6270      * @return a robust magnetometer calibrator.
6271      * @throws IllegalArgumentException if provided hard-iron matrix is not
6272      *                                  3x1.
6273      */
6274     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6275             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
6276             final Matrix hardIron) {
6277         return create(position, measurements, hardIron, DEFAULT_ROBUST_METHOD);
6278     }
6279 
6280     /**
6281      * Creates a robust magnetometer calibrator with default robust method.
6282      *
6283      * @param position     position where body magnetic flux density measurements
6284      *                     have been taken.
6285      * @param measurements collection of body magnetic flux density
6286      *                     measurements with standard deviation of
6287      *                     magnetometer measurements taken at the same
6288      *                     position with zero velocity and unknown different
6289      *                     orientations.
6290      * @param hardIron     known hard-iron.
6291      * @param listener     listener to handle events raised by this calibrator.
6292      * @return a robust magnetometer calibrator.
6293      * @throws IllegalArgumentException if provided hard-iron matrix is not
6294      *                                  3x1.
6295      */
6296     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6297             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
6298             final Matrix hardIron, final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
6299         return create(position, measurements, hardIron, listener, DEFAULT_ROBUST_METHOD);
6300     }
6301 
6302     /**
6303      * Creates a robust magnetometer calibrator with default robust method.
6304      *
6305      * @param position       position where body magnetic flux density measurements
6306      *                       have been taken.
6307      * @param measurements   collection of body magnetic flux density
6308      *                       measurements with standard deviation of
6309      *                       magnetometer measurements taken at the same
6310      *                       position with zero velocity and unknown different
6311      *                       orientations.
6312      * @param commonAxisUsed indicates whether z-axis is assumed to be common
6313      *                       for the accelerometer, gyroscope and magnetometer.
6314      * @param hardIron       known hard-iron.
6315      * @return a robust magnetometer calibrator.
6316      * @throws IllegalArgumentException if provided hard-iron matrix is not
6317      *                                  3x1.
6318      */
6319     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6320             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
6321             final boolean commonAxisUsed, final Matrix hardIron) {
6322         return create(position, measurements, commonAxisUsed, hardIron, DEFAULT_ROBUST_METHOD);
6323     }
6324 
6325     /**
6326      * Creates a robust magnetometer calibrator with default robust method.
6327      *
6328      * @param position       position where body magnetic flux density measurements
6329      *                       have been taken.
6330      * @param measurements   collection of body magnetic flux density
6331      *                       measurements with standard deviation of
6332      *                       magnetometer measurements taken at the same
6333      *                       position with zero velocity and unknown different
6334      *                       orientations.
6335      * @param commonAxisUsed indicates whether z-axis is assumed to be common
6336      *                       for the accelerometer, gyroscope and magnetometer.
6337      * @param hardIron       known hard-iron.
6338      * @param listener       listener to handle events raised by this calibrator.
6339      * @return a robust magnetometer calibrator.
6340      * @throws IllegalArgumentException if provided hard-iron matrix is not
6341      *                                  3x1.
6342      */
6343     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6344             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
6345             final boolean commonAxisUsed, final Matrix hardIron,
6346             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
6347         return create(position, measurements, commonAxisUsed, hardIron, listener, DEFAULT_ROBUST_METHOD);
6348     }
6349 
6350     /**
6351      * Creates a robust magnetometer calibrator with default robust method.
6352      *
6353      * @param position     position where body magnetic flux density measurements
6354      *                     have been taken.
6355      * @param measurements collection of body magnetic flux density
6356      *                     measurements with standard deviation of
6357      *                     magnetometer measurements taken at the same
6358      *                     position with zero velocity and unknown different
6359      *                     orientations.
6360      * @param hardIron     known hard-iron.
6361      * @param initialMm    initial soft-iron matrix containing scale factors
6362      *                     and cross coupling errors.
6363      * @return a robust magnetometer calibrator.
6364      * @throws IllegalArgumentException if provided hard-iron matrix is not
6365      *                                  3x1 or if soft-iron matrix is not
6366      *                                  3x3.
6367      */
6368     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6369             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
6370             final Matrix hardIron, final Matrix initialMm) {
6371         return create(position, measurements, hardIron, initialMm, DEFAULT_ROBUST_METHOD);
6372     }
6373 
6374     /**
6375      * Creates a robust magnetometer calibrator with default robust method.
6376      *
6377      * @param position     position where body magnetic flux density measurements
6378      *                     have been taken.
6379      * @param measurements collection of body magnetic flux density
6380      *                     measurements with standard deviation of
6381      *                     magnetometer measurements taken at the same
6382      *                     position with zero velocity and unknown different
6383      *                     orientations.
6384      * @param hardIron     known hard-iron.
6385      * @param initialMm    initial soft-iron matrix containing scale factors
6386      *                     and cross coupling errors.
6387      * @param listener     listener to handle events raised by this calibrator.
6388      * @return a robust magnetometer calibrator.
6389      * @throws IllegalArgumentException if provided hard-iron matrix is not
6390      *                                  3x1 or if soft-iron matrix is not
6391      *                                  3x3.
6392      */
6393     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6394             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
6395             final Matrix hardIron, final Matrix initialMm,
6396             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
6397         return create(position, measurements, hardIron, initialMm, listener, DEFAULT_ROBUST_METHOD);
6398     }
6399 
6400     /**
6401      * Creates a robust magnetometer calibrator with default robust method.
6402      *
6403      * @param position       position where body magnetic flux density measurements
6404      *                       have been taken.
6405      * @param measurements   collection of body magnetic flux density
6406      *                       measurements with standard deviation of
6407      *                       magnetometer measurements taken at the same
6408      *                       position with zero velocity and unknown different
6409      *                       orientations.
6410      * @param commonAxisUsed indicates whether z-axis is assumed to be common
6411      *                       for the accelerometer, gyroscope and magnetometer.
6412      * @param hardIron       known hard-iron.
6413      * @param initialMm      initial soft-iron matrix containing scale factors
6414      *                       and cross coupling errors.
6415      * @return a robust magnetometer calibrator.
6416      * @throws IllegalArgumentException if provided hard-iron matrix is not
6417      *                                  3x1 or if soft-iron matrix is not
6418      *                                  3x3.
6419      */
6420     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6421             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
6422             final boolean commonAxisUsed, final Matrix hardIron, final Matrix initialMm) {
6423         return create(position, measurements, commonAxisUsed, hardIron, initialMm, DEFAULT_ROBUST_METHOD);
6424     }
6425 
6426     /**
6427      * Creates a robust magnetometer calibrator with default robust method.
6428      *
6429      * @param position       position where body magnetic flux density measurements
6430      *                       have been taken.
6431      * @param measurements   collection of body magnetic flux density
6432      *                       measurements with standard deviation of
6433      *                       magnetometer measurements taken at the same
6434      *                       position with zero velocity and unknown different
6435      *                       orientations.
6436      * @param commonAxisUsed indicates whether z-axis is assumed to be common
6437      *                       for the accelerometer, gyroscope and magnetometer.
6438      * @param hardIron       known hard-iron.
6439      * @param initialMm      initial soft-iron matrix containing scale factors
6440      *                       and cross coupling errors.
6441      * @param listener       listener to handle events raised by this calibrator.
6442      * @return a robust magnetometer calibrator.
6443      * @throws IllegalArgumentException if provided hard-iron matrix is not
6444      *                                  3x1 or if soft-iron matrix is not
6445      *                                  3x3.
6446      */
6447     public static RobustKnownHardIronPositionAndInstantMagnetometerCalibrator create(
6448             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
6449             final boolean commonAxisUsed, final Matrix hardIron, final Matrix initialMm,
6450             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
6451         return create(position, measurements, commonAxisUsed, hardIron, initialMm, listener, DEFAULT_ROBUST_METHOD);
6452     }
6453 
6454     /**
6455      * Initializes calibrator and estimates magnetic flux density norm
6456      * at provided position and timestamp.
6457      *
6458      * @throws IOException if world magnetic model cannot be loaded.
6459      */
6460     protected void initialize() throws IOException {
6461         final WMMEarthMagneticFluxDensityEstimator wmmEstimator;
6462         if (magneticModel != null) {
6463             wmmEstimator = new WMMEarthMagneticFluxDensityEstimator(magneticModel);
6464         } else {
6465             wmmEstimator = new WMMEarthMagneticFluxDensityEstimator();
6466         }
6467 
6468         final var pos = getNedPosition();
6469         final var earthB = wmmEstimator.estimate(pos, year);
6470         magneticDensityNorm = earthB.getNorm();
6471     }
6472 
6473     /**
6474      * Computes error of a preliminary result respect a given measurement.
6475      *
6476      * @param measurement       a measurement.
6477      * @param preliminaryResult a preliminary result.
6478      * @return computed error.
6479      */
6480     protected double computeError(
6481             final StandardDeviationBodyMagneticFluxDensity measurement, final Matrix preliminaryResult) {
6482 
6483         try {
6484             // The magnetometer model is:
6485             // mBmeas = bm + (I + Mm) * mBtrue
6486 
6487             // mBmeas - bm = (I + Mm) * mBtrue
6488 
6489             // mBtrue = (I + Mm)^-1 * (mBmeas - ba)
6490 
6491             // We know that ||mBtrue||should be equal to the magnitude of the
6492             // Earth magnetic field at provided location
6493 
6494             if (identity == null) {
6495                 identity = Matrix.identity(BodyMagneticFluxDensity.COMPONENTS, BodyMagneticFluxDensity.COMPONENTS);
6496             }
6497 
6498             if (tmp1 == null) {
6499                 tmp1 = new Matrix(BodyMagneticFluxDensity.COMPONENTS, BodyMagneticFluxDensity.COMPONENTS);
6500             }
6501 
6502             if (tmp2 == null) {
6503                 tmp2 = new Matrix(BodyKinematics.COMPONENTS, BodyKinematics.COMPONENTS);
6504             }
6505 
6506             if (tmp3 == null) {
6507                 tmp3 = new Matrix(BodyKinematics.COMPONENTS, 1);
6508             }
6509 
6510             if (tmp4 == null) {
6511                 tmp4 = new Matrix(BodyKinematics.COMPONENTS, 1);
6512             }
6513 
6514             identity.add(preliminaryResult, tmp1);
6515 
6516             Utils.inverse(tmp1, tmp2);
6517 
6518             final var measuredMagneticFluxDensity = measurement.getMagneticFluxDensity();
6519             final var bMeasX = measuredMagneticFluxDensity.getBx();
6520             final var bMeasY = measuredMagneticFluxDensity.getBy();
6521             final var bMeasZ = measuredMagneticFluxDensity.getBz();
6522 
6523             tmp3.setElementAtIndex(0, bMeasX - hardIronX);
6524             tmp3.setElementAtIndex(1, bMeasY - hardIronY);
6525             tmp3.setElementAtIndex(2, bMeasZ - hardIronZ);
6526 
6527             tmp2.multiply(tmp3, tmp4);
6528 
6529             final var norm = Utils.normF(tmp4);
6530             final var diff = magneticDensityNorm - norm;
6531 
6532             return diff * diff;
6533 
6534         } catch (final AlgebraException e) {
6535             return Double.MAX_VALUE;
6536         }
6537     }
6538 
6539     /**
6540      * Computes a preliminary solution for a subset of samples picked by a robust estimator.
6541      *
6542      * @param samplesIndices indices of samples picked by the robust estimator.
6543      * @param solutions      list where estimated preliminary solution will be stored.
6544      */
6545     protected void computePreliminarySolutions(final int[] samplesIndices, final List<Matrix> solutions) {
6546 
6547         final var meas = new ArrayList<StandardDeviationBodyMagneticFluxDensity>();
6548 
6549         for (final var samplesIndex : samplesIndices) {
6550             meas.add(this.measurements.get(samplesIndex));
6551         }
6552 
6553         try {
6554             final var result = getInitialMm();
6555 
6556             innerCalibrator.setHardIronCoordinates(hardIronX, hardIronY, hardIronZ);
6557             innerCalibrator.setInitialMm(result);
6558             innerCalibrator.setCommonAxisUsed(commonAxisUsed);
6559             innerCalibrator.setPosition(position);
6560             innerCalibrator.setYear(year);
6561             innerCalibrator.setMeasurements(meas);
6562             innerCalibrator.calibrate();
6563 
6564             result.copyFrom(innerCalibrator.getEstimatedMm());
6565 
6566             solutions.add(result);
6567 
6568         } catch (final LockedException | CalibrationException | NotReadyException e) {
6569             solutions.clear();
6570         }
6571     }
6572 
6573     /**
6574      * Attempts to refine calibration parameters if refinement is requested.
6575      * This method returns a refined solution or provided input if refinement is not
6576      * requested or has failed.
6577      * If refinement is enabled and it is requested to keep covariance, this method
6578      * will also keep covariance of refined position.
6579      *
6580      * @param preliminaryResult a preliminary result.
6581      */
6582     protected void attemptRefine(final Matrix preliminaryResult) {
6583         if (refineResult && inliersData != null) {
6584             final var inliers = inliersData.getInliers();
6585             final var nSamples = measurements.size();
6586 
6587             final var inlierMeasurements = new ArrayList<StandardDeviationBodyMagneticFluxDensity>();
6588             for (var i = 0; i < nSamples; i++) {
6589                 if (inliers.get(i)) {
6590                     // sample is inlier
6591                     inlierMeasurements.add(measurements.get(i));
6592                 }
6593             }
6594 
6595             try {
6596                 innerCalibrator.setHardIronCoordinates(hardIronX, hardIronY, hardIronZ);
6597                 innerCalibrator.setInitialMm(preliminaryResult);
6598                 innerCalibrator.setCommonAxisUsed(commonAxisUsed);
6599                 innerCalibrator.setPosition(position);
6600                 innerCalibrator.setYear(year);
6601                 innerCalibrator.setMeasurements(inlierMeasurements);
6602                 innerCalibrator.calibrate();
6603 
6604                 estimatedMm = innerCalibrator.getEstimatedMm();
6605 
6606                 if (keepCovariance) {
6607                     estimatedCovariance = innerCalibrator.getEstimatedCovariance();
6608                 } else {
6609                     estimatedCovariance = null;
6610                 }
6611 
6612                 estimatedMse = innerCalibrator.getEstimatedMse();
6613                 estimatedChiSq = innerCalibrator.getEstimatedChiSq();
6614                 estimatedChiSqDegreesOfFreedom = innerCalibrator.getEstimatedChiSqDegreesOfFreedom();
6615                 estimatedReducedChiSq = innerCalibrator.getEstimatedReducedChiSq();
6616                 estimatedP = innerCalibrator.getEstimatedP();
6617                 estimatedQ = innerCalibrator.getEstimatedQ();
6618 
6619             } catch (final LockedException | CalibrationException | NotReadyException e) {
6620                 estimatedCovariance = null;
6621                 estimatedMm = preliminaryResult;
6622                 estimatedMse = 0.0;
6623                 estimatedChiSq = 0.0;
6624                 estimatedChiSqDegreesOfFreedom = 0;
6625                 estimatedReducedChiSq = 0.0;
6626                 estimatedP = 1.0;
6627                 estimatedQ = 0.0;
6628             }
6629         } else {
6630             estimatedCovariance = null;
6631             estimatedMm = preliminaryResult;
6632             estimatedMse = 0.0;
6633             estimatedChiSq = 0.0;
6634             estimatedChiSqDegreesOfFreedom = 0;
6635             estimatedReducedChiSq = 0.0;
6636             estimatedP = 1.0;
6637             estimatedQ = 0.0;
6638         }
6639     }
6640 
6641     /**
6642      * Converts a time instance expressed in milliseconds since epoch time
6643      * (January 1st, 1970 at midnight) to a decimal year.
6644      *
6645      * @param timestampMillis milliseconds value to be converted.
6646      * @return converted value expressed in decimal years.
6647      */
6648     private static Double convertTime(final Long timestampMillis) {
6649         if (timestampMillis == null) {
6650             return null;
6651         }
6652 
6653         final var calendar = new GregorianCalendar();
6654         calendar.setTimeInMillis(timestampMillis);
6655         return convertTime(calendar);
6656     }
6657 
6658     /**
6659      * Converts a time instant contained ina date object to a
6660      * decimal year.
6661      *
6662      * @param date a time instance to be converted.
6663      * @return converted value expressed in decimal years.
6664      */
6665     private static Double convertTime(final Date date) {
6666         if (date == null) {
6667             return null;
6668         }
6669 
6670         final var calendar = new GregorianCalendar();
6671         calendar.setTime(date);
6672         return convertTime(calendar);
6673     }
6674 
6675     /**
6676      * Converts a time instant contained in a gregorian calendar to a
6677      * decimal year.
6678      *
6679      * @param calendar calendar containing a specific instant to be
6680      *                 converted.
6681      * @return converted value expressed in decimal years.
6682      */
6683     private static Double convertTime(final GregorianCalendar calendar) {
6684         if (calendar == null) {
6685             return null;
6686         }
6687 
6688         return WMMEarthMagneticFluxDensityEstimator.convertTime(calendar);
6689     }
6690 
6691     /**
6692      * Converts provided ECEF position to position expressed in NED
6693      * coordinates.
6694      *
6695      * @param position ECEF position to be converted.
6696      * @return converted position expressed in NED coordinates.
6697      */
6698     private static NEDPosition convertPosition(final ECEFPosition position) {
6699         final var velocity = new NEDVelocity();
6700         final var result = new NEDPosition();
6701         ECEFtoNEDPositionVelocityConverter.convertECEFtoNED(
6702                 position.getX(), position.getY(), position.getZ(),
6703                 0.0, 0.0, 0.0, result, velocity);
6704         return result;
6705     }
6706 
6707     /**
6708      * Converts magnetic flux density value and unit to Teslas.
6709      *
6710      * @param value magnetic flux density value.
6711      * @param unit  unit of magnetic flux density value.
6712      * @return converted value.
6713      */
6714     private static double convertMagneticFluxDensity(final double value, final MagneticFluxDensityUnit unit) {
6715         return MagneticFluxDensityConverter.convert(value, unit, MagneticFluxDensityUnit.TESLA);
6716     }
6717 
6718     /**
6719      * Converts magnetic flux density instance to Teslas.
6720      *
6721      * @param magneticFluxDensity magnetic flux density instance to be converted.
6722      * @return converted value.
6723      */
6724     private static double convertMagneticFluxDensity(final MagneticFluxDensity magneticFluxDensity) {
6725         return convertMagneticFluxDensity(magneticFluxDensity.getValue().doubleValue(), magneticFluxDensity.getUnit());
6726     }
6727 }