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.Matrix;
19  import com.irurueta.navigation.LockedException;
20  import com.irurueta.navigation.NotReadyException;
21  import com.irurueta.navigation.frames.ECEFPosition;
22  import com.irurueta.navigation.frames.NEDPosition;
23  import com.irurueta.navigation.inertial.calibration.CalibrationException;
24  import com.irurueta.navigation.inertial.calibration.StandardDeviationBodyMagneticFluxDensity;
25  import com.irurueta.navigation.inertial.wmm.WorldMagneticModel;
26  import com.irurueta.numerical.robust.PROMedSRobustEstimator;
27  import com.irurueta.numerical.robust.PROMedSRobustEstimatorListener;
28  import com.irurueta.numerical.robust.RobustEstimator;
29  import com.irurueta.numerical.robust.RobustEstimatorException;
30  import com.irurueta.numerical.robust.RobustEstimatorMethod;
31  
32  import java.io.IOException;
33  import java.util.List;
34  
35  /**
36   * Robustly estimates magnetometer cross couplings and scaling factors
37   * using PROMedS algorithm.
38   * <p>
39   * To use this calibrator at least 7 measurements taken at a single known
40   * position and instant must be taken at 7 different unknown orientations and
41   * zero velocity when common z-axis is assumed, otherwise at least 10
42   * measurements are required.
43   * <p>
44   * Measured magnetic flux density is assumed to follow the model shown below:
45   * <pre>
46   *     mBmeas = bm + (I + Mm) * mBtrue + w
47   * </pre>
48   * Where:
49   * - mBmeas is the measured magnetic flux density. This is a 3x1 vector.
50   * - bm is magnetometer hard-iron bias. Ideally, on a perfect magnetometer,
51   * this should be a 3x1 zero vector.
52   * - I is the 3x3 identity matrix.
53   * - Mm is the 3x3 soft-iron matrix containing cross-couplings and scaling
54   * factors. Ideally, on a perfect magnetometer, this should be a 3x3 zero
55   * matrix.
56   * - mBtrue is ground-truth magnetic flux density. This is a 3x1 vector.
57   * - w is measurement noise. This is a 3x1 vector.
58   * Notice that this calibrator assumes that all measurements are taken in
59   * a short span of time, where Earth magnetic field can be assumed to be
60   * constant at provided location and instant.
61   */
62  public class PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator extends
63          RobustKnownHardIronPositionAndInstantMagnetometerCalibrator {
64  
65      /**
66       * Default value to be used for stop threshold. Stop threshold can be used to
67       * avoid keeping the algorithm unnecessarily iterating in case that best
68       * estimated threshold using median of residuals is not small enough. Once a
69       * solution is found that generates a threshold below this value, the
70       * algorithm will stop.
71       * The stop threshold can be used to prevent the LMedS algorithm iterating
72       * too many times in cases where samples have a very similar accuracy.
73       * For instance, in cases where proportion of outliers is very small (close
74       * to 0%), and samples are very accurate (i.e. 1e-6), the algorithm would
75       * iterate for a long time trying to find the best solution when indeed
76       * there is no need to do that if a reasonable threshold has already been
77       * reached.
78       * Because of this behaviour the stop threshold can be set to a value much
79       * lower than the one typically used in RANSAC, and yet the algorithm could
80       * still produce even smaller thresholds in estimated results.
81       */
82      public static final double DEFAULT_STOP_THRESHOLD = 1e-9;
83  
84      /**
85       * Minimum allowed stop threshold value.
86       */
87      public static final double MIN_STOP_THRESHOLD = 0.0;
88  
89      /**
90       * Threshold to be used to keep the algorithm iterating in case that best
91       * estimated threshold using median of residuals is not small enough. Once
92       * a solution is found that generates a threshold below this value, the
93       * algorithm will stop.
94       * The stop threshold can be used to prevent the LMedS algorithm iterating
95       * too many times in cases where samples have a very similar accuracy.
96       * For instance, in cases where proportion of outliers is very small (close
97       * to 0%), and samples are very accurate (i.e. 1e-6), the algorithm would
98       * iterate for a long time trying to find the best solution when indeed
99       * there is no need to do that if a reasonable threshold has already been
100      * reached.
101      * Because of this behaviour the stop threshold can be set to a value much
102      * lower than the one typically used in RANSAC, and yet the algorithm could
103      * still produce even smaller thresholds in estimated results.
104      */
105     private double stopThreshold = DEFAULT_STOP_THRESHOLD;
106 
107     /**
108      * Quality scores corresponding to each provided sample.
109      * The larger the score value the better the quality of the sample.
110      */
111     private double[] qualityScores;
112 
113     /**
114      * Constructor.
115      */
116     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator() {
117         super();
118     }
119 
120     /**
121      * Constructor.
122      *
123      * @param listener listener to handle events raised by this calibrator.
124      */
125     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
126             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
127         super(listener);
128     }
129 
130     /**
131      * Constructor.
132      *
133      * @param measurements list of body magnetic flux density
134      *                     measurements with standard deviation of
135      *                     magnetometer measurements taken at the same
136      *                     position with zero velocity and unknown different
137      *                     orientations.
138      */
139     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
140             final List<StandardDeviationBodyMagneticFluxDensity> measurements) {
141         super(measurements);
142     }
143 
144     /**
145      * Constructor.
146      *
147      * @param commonAxisUsed indicates whether z-axis is assumed to be common
148      *                       for the accelerometer, gyroscope and magnetometer.
149      */
150     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(final boolean commonAxisUsed) {
151         super(commonAxisUsed);
152     }
153 
154     /**
155      * Constructor.
156      *
157      * @param magneticModel Earth's magnetic model. If null, a default model
158      *                      will be used instead.
159      */
160     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(final WorldMagneticModel magneticModel) {
161         super(magneticModel);
162     }
163 
164     /**
165      * Constructor.
166      *
167      * @param hardIron known hard-iron.
168      * @throws IllegalArgumentException if provided hard-iron array does
169      *                                  not have length 3.
170      */
171     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(final double[] hardIron) {
172         super(hardIron);
173     }
174 
175     /**
176      * Constructor.
177      *
178      * @param hardIron known hard-iron.
179      * @throws IllegalArgumentException if provided hard-iron matrix is not
180      *                                  3x1.
181      */
182     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(final Matrix hardIron) {
183         super(hardIron);
184     }
185 
186     /**
187      * Constructor.
188      *
189      * @param hardIron  known hard-iron.
190      * @param initialMm initial soft-iron matrix containing scale factors
191      *                  and cross coupling errors.
192      * @throws IllegalArgumentException if provided hard-iron matrix is not
193      *                                  3x1 or if soft-iron matrix is not
194      *                                  3x3.
195      */
196     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
197             final Matrix hardIron, final Matrix initialMm) {
198         super(hardIron, initialMm);
199     }
200 
201     /**
202      * Constructor.
203      *
204      * @param position position where body magnetic flux density measurements
205      *                 have been taken.
206      */
207     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(final NEDPosition position) {
208         super(position);
209     }
210 
211     /**
212      * Constructor.
213      *
214      * @param position     position where body magnetic flux density measurements
215      *                     have been taken.
216      * @param measurements collection of body magnetic flux density
217      *                     measurements with standard deviation of
218      *                     magnetometer measurements taken at the same
219      *                     position with zero velocity and unknown different
220      *                     orientations.
221      */
222     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
223             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements) {
224         super(position, measurements);
225     }
226 
227     /**
228      * Constructor.
229      *
230      * @param position     position where body magnetic flux density measurements
231      *                     have been taken.
232      * @param measurements collection of body magnetic flux density
233      *                     measurements with standard deviation of
234      *                     magnetometer measurements taken at the same
235      *                     position with zero velocity and unknown different
236      *                     orientations.
237      * @param listener     listener to handle events raised by this calibrator.
238      */
239     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
240             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
241             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
242         super(position, measurements, listener);
243     }
244 
245     /**
246      * Constructor.
247      *
248      * @param position       position where body magnetic flux density measurements
249      *                       have been taken.
250      * @param measurements   collection of body magnetic flux density
251      *                       measurements with standard deviation of
252      *                       magnetometer measurements taken at the same
253      *                       position with zero velocity and unknown different
254      *                       orientations.
255      * @param commonAxisUsed indicates whether z-axis is assumed to be common
256      *                       for the accelerometer, gyroscope and magnetometer.
257      */
258     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
259             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
260             final boolean commonAxisUsed) {
261         super(position, measurements, commonAxisUsed);
262     }
263 
264     /**
265      * Constructor.
266      *
267      * @param position       position where body magnetic flux density measurements
268      *                       have been taken.
269      * @param measurements   collection of body magnetic flux density
270      *                       measurements with standard deviation of
271      *                       magnetometer measurements taken at the same
272      *                       position with zero velocity and unknown different
273      *                       orientations.
274      * @param commonAxisUsed indicates whether z-axis is assumed to be common
275      *                       for the accelerometer, gyroscope and magnetometer.
276      * @param listener       listener to handle events raised by this calibrator.
277      */
278     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
279             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
280             final boolean commonAxisUsed,
281             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
282         super(position, measurements, commonAxisUsed, listener);
283     }
284 
285     /**
286      * Constructor.
287      *
288      * @param position     position where body magnetic flux density measurements
289      *                     have been taken.
290      * @param measurements collection of body magnetic flux density
291      *                     measurements with standard deviation of
292      *                     magnetometer measurements taken at the same
293      *                     position with zero velocity and unknown different
294      *                     orientations.
295      * @param hardIron     known hard-iron.
296      * @throws IllegalArgumentException if provided hard-iron array does
297      *                                  not have length 3.
298      */
299     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
300             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
301             final double[] hardIron) {
302         super(position, measurements, hardIron);
303     }
304 
305     /**
306      * Constructor.
307      *
308      * @param position     position where body magnetic flux density measurements
309      *                     have been taken.
310      * @param measurements collection of body magnetic flux density
311      *                     measurements with standard deviation of
312      *                     magnetometer measurements taken at the same
313      *                     position with zero velocity and unknown different
314      *                     orientations.
315      * @param hardIron     known hard-iron.
316      * @param listener     listener to handle events raised by this calibrator.
317      * @throws IllegalArgumentException if provided hard-iron array does
318      *                                  not have length 3.
319      */
320     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
321             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
322             final double[] hardIron,
323             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
324         super(position, measurements, hardIron, listener);
325     }
326 
327     /**
328      * Constructor.
329      *
330      * @param position       position where body magnetic flux density measurements
331      *                       have been taken.
332      * @param measurements   collection of body magnetic flux density
333      *                       measurements with standard deviation of
334      *                       magnetometer measurements taken at the same
335      *                       position with zero velocity and unknown different
336      *                       orientations.
337      * @param commonAxisUsed indicates whether z-axis is assumed to be common
338      *                       for the accelerometer, gyroscope and magnetometer.
339      * @param hardIron       known hard-iron.
340      * @throws IllegalArgumentException if provided hard-iron array does
341      *                                  not have length 3.
342      */
343     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
344             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
345             final boolean commonAxisUsed, final double[] hardIron) {
346         super(position, measurements, commonAxisUsed, hardIron);
347     }
348 
349     /**
350      * Constructor.
351      *
352      * @param position       position where body magnetic flux density measurements
353      *                       have been taken.
354      * @param measurements   collection of body magnetic flux density
355      *                       measurements with standard deviation of
356      *                       magnetometer measurements taken at the same
357      *                       position with zero velocity and unknown different
358      *                       orientations.
359      * @param commonAxisUsed indicates whether z-axis is assumed to be common
360      *                       for the accelerometer, gyroscope and magnetometer.
361      * @param hardIron       known hard-iron.
362      * @param listener       listener to handle events raised by this calibrator.
363      * @throws IllegalArgumentException if provided hard-iron array does
364      *                                  not have length 3.
365      */
366     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
367             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
368             final boolean commonAxisUsed, final double[] hardIron,
369             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
370         super(position, measurements, commonAxisUsed, hardIron, listener);
371     }
372 
373     /**
374      * Constructor.
375      *
376      * @param position     position where body magnetic flux density measurements
377      *                     have been taken.
378      * @param measurements collection of body magnetic flux density
379      *                     measurements with standard deviation of
380      *                     magnetometer measurements taken at the same
381      *                     position with zero velocity and unknown different
382      *                     orientations.
383      * @param hardIron     known hard-iron.
384      * @throws IllegalArgumentException if provided hard-iron matrix is not
385      *                                  3x1.
386      */
387     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
388             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
389             final Matrix hardIron) {
390         super(position, measurements, hardIron);
391     }
392 
393     /**
394      * Constructor.
395      *
396      * @param position     position where body magnetic flux density measurements
397      *                     have been taken.
398      * @param measurements collection of body magnetic flux density
399      *                     measurements with standard deviation of
400      *                     magnetometer measurements taken at the same
401      *                     position with zero velocity and unknown different
402      *                     orientations.
403      * @param hardIron     known hard-iron.
404      * @param listener     listener to handle events raised by this calibrator.
405      * @throws IllegalArgumentException if provided hard-iron matrix is not
406      *                                  3x1.
407      */
408     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
409             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
410             final Matrix hardIron, final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
411         super(position, measurements, hardIron, listener);
412     }
413 
414     /**
415      * Constructor.
416      *
417      * @param position       position where body magnetic flux density measurements
418      *                       have been taken.
419      * @param measurements   collection of body magnetic flux density
420      *                       measurements with standard deviation of
421      *                       magnetometer measurements taken at the same
422      *                       position with zero velocity and unknown different
423      *                       orientations.
424      * @param commonAxisUsed indicates whether z-axis is assumed to be common
425      *                       for the accelerometer, gyroscope and magnetometer.
426      * @param hardIron       known hard-iron.
427      * @throws IllegalArgumentException if provided hard-iron matrix is not
428      *                                  3x1.
429      */
430     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
431             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
432             final boolean commonAxisUsed, final Matrix hardIron) {
433         super(position, measurements, commonAxisUsed, hardIron);
434     }
435 
436     /**
437      * Constructor.
438      *
439      * @param position       position where body magnetic flux density measurements
440      *                       have been taken.
441      * @param measurements   collection of body magnetic flux density
442      *                       measurements with standard deviation of
443      *                       magnetometer measurements taken at the same
444      *                       position with zero velocity and unknown different
445      *                       orientations.
446      * @param commonAxisUsed indicates whether z-axis is assumed to be common
447      *                       for the accelerometer, gyroscope and magnetometer.
448      * @param hardIron       known hard-iron.
449      * @param listener       listener to handle events raised by this calibrator.
450      * @throws IllegalArgumentException if provided hard-iron matrix is not
451      *                                  3x1.
452      */
453     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
454             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
455             final boolean commonAxisUsed, final Matrix hardIron,
456             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
457         super(position, measurements, commonAxisUsed, hardIron, listener);
458     }
459 
460     /**
461      * Constructor.
462      *
463      * @param position     position where body magnetic flux density measurements
464      *                     have been taken.
465      * @param measurements collection of body magnetic flux density
466      *                     measurements with standard deviation of
467      *                     magnetometer measurements taken at the same
468      *                     position with zero velocity and unknown different
469      *                     orientations.
470      * @param hardIron     known hard-iron.
471      * @param initialMm    initial soft-iron matrix containing scale factors
472      *                     and cross coupling errors.
473      * @throws IllegalArgumentException if provided hard-iron matrix is not
474      *                                  3x1 or if soft-iron matrix is not
475      *                                  3x3.
476      */
477     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
478             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
479             final Matrix hardIron, final Matrix initialMm) {
480         super(position, measurements, hardIron, initialMm);
481     }
482 
483     /**
484      * Constructor.
485      *
486      * @param position     position where body magnetic flux density measurements
487      *                     have been taken.
488      * @param measurements collection of body magnetic flux density
489      *                     measurements with standard deviation of
490      *                     magnetometer measurements taken at the same
491      *                     position with zero velocity and unknown different
492      *                     orientations.
493      * @param hardIron     known hard-iron.
494      * @param initialMm    initial soft-iron matrix containing scale factors
495      *                     and cross coupling errors.
496      * @param listener     listener to handle events raised by this calibrator.
497      * @throws IllegalArgumentException if provided hard-iron matrix is not
498      *                                  3x1 or if soft-iron matrix is not
499      *                                  3x3.
500      */
501     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
502             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
503             final Matrix hardIron, final Matrix initialMm,
504             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
505         super(position, measurements, hardIron, initialMm, listener);
506     }
507 
508     /**
509      * Constructor.
510      *
511      * @param position       position where body magnetic flux density measurements
512      *                       have been taken.
513      * @param measurements   collection of body magnetic flux density
514      *                       measurements with standard deviation of
515      *                       magnetometer measurements taken at the same
516      *                       position with zero velocity and unknown different
517      *                       orientations.
518      * @param commonAxisUsed indicates whether z-axis is assumed to be common
519      *                       for the accelerometer, gyroscope and magnetometer.
520      * @param hardIron       known hard-iron.
521      * @param initialMm      initial soft-iron matrix containing scale factors
522      *                       and cross coupling errors.
523      * @throws IllegalArgumentException if provided hard-iron matrix is not
524      *                                  3x1 or if soft-iron matrix is not
525      *                                  3x3.
526      */
527     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
528             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
529             final boolean commonAxisUsed, final Matrix hardIron, final Matrix initialMm) {
530         super(position, measurements, commonAxisUsed, hardIron, initialMm);
531     }
532 
533     /**
534      * Constructor.
535      *
536      * @param position       position where body magnetic flux density measurements
537      *                       have been taken.
538      * @param measurements   collection of body magnetic flux density
539      *                       measurements with standard deviation of
540      *                       magnetometer measurements taken at the same
541      *                       position with zero velocity and unknown different
542      *                       orientations.
543      * @param commonAxisUsed indicates whether z-axis is assumed to be common
544      *                       for the accelerometer, gyroscope and magnetometer.
545      * @param hardIron       known hard-iron.
546      * @param initialMm      initial soft-iron matrix containing scale factors
547      *                       and cross coupling errors.
548      * @param listener       listener to handle events raised by this calibrator.
549      * @throws IllegalArgumentException if provided hard-iron matrix is not
550      *                                  3x1 or if soft-iron matrix is not
551      *                                  3x3.
552      */
553     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
554             final NEDPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
555             final boolean commonAxisUsed, final Matrix hardIron, final Matrix initialMm,
556             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
557         super(position, measurements, commonAxisUsed, hardIron, initialMm, listener);
558     }
559 
560     /**
561      * Constructor.
562      *
563      * @param position position where body magnetic flux density measurements
564      *                 have been taken.
565      */
566     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(final ECEFPosition position) {
567         super(position);
568     }
569 
570     /**
571      * Constructor.
572      *
573      * @param position     position where body magnetic flux density measurements
574      *                     have been taken.
575      * @param measurements collection of body magnetic flux density
576      *                     measurements with standard deviation of
577      *                     magnetometer measurements taken at the same
578      *                     position with zero velocity and unknown different
579      *                     orientations.
580      */
581     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
582             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements) {
583         super(position, measurements);
584     }
585 
586     /**
587      * Constructor.
588      *
589      * @param position     position where body magnetic flux density measurements
590      *                     have been taken.
591      * @param measurements collection of body magnetic flux density
592      *                     measurements with standard deviation of
593      *                     magnetometer measurements taken at the same
594      *                     position with zero velocity and unknown different
595      *                     orientations.
596      * @param listener     listener to handle events raised by this calibrator.
597      */
598     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
599             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
600             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
601         super(position, measurements, listener);
602     }
603 
604     /**
605      * Constructor.
606      *
607      * @param position       position where body magnetic flux density measurements
608      *                       have been taken.
609      * @param measurements   collection of body magnetic flux density
610      *                       measurements with standard deviation of
611      *                       magnetometer measurements taken at the same
612      *                       position with zero velocity and unknown different
613      *                       orientations.
614      * @param commonAxisUsed indicates whether z-axis is assumed to be common
615      *                       for the accelerometer, gyroscope and magnetometer.
616      */
617     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
618             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
619             final boolean commonAxisUsed) {
620         super(position, measurements, commonAxisUsed);
621     }
622 
623     /**
624      * Constructor.
625      *
626      * @param position       position where body magnetic flux density measurements
627      *                       have been taken.
628      * @param measurements   collection of body magnetic flux density
629      *                       measurements with standard deviation of
630      *                       magnetometer measurements taken at the same
631      *                       position with zero velocity and unknown different
632      *                       orientations.
633      * @param commonAxisUsed indicates whether z-axis is assumed to be common
634      *                       for the accelerometer, gyroscope and magnetometer.
635      * @param listener       listener to handle events raised by this calibrator.
636      */
637     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
638             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
639             final boolean commonAxisUsed,
640             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
641         super(position, measurements, commonAxisUsed, listener);
642     }
643 
644     /**
645      * Constructor.
646      *
647      * @param position     position where body magnetic flux density measurements
648      *                     have been taken.
649      * @param measurements collection of body magnetic flux density
650      *                     measurements with standard deviation of
651      *                     magnetometer measurements taken at the same
652      *                     position with zero velocity and unknown different
653      *                     orientations.
654      * @param hardIron     known hard-iron.
655      * @throws IllegalArgumentException if provided hard-iron array does
656      *                                  not have length 3.
657      */
658     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
659             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
660             final double[] hardIron) {
661         super(position, measurements, hardIron);
662     }
663 
664     /**
665      * Constructor.
666      *
667      * @param position     position where body magnetic flux density measurements
668      *                     have been taken.
669      * @param measurements collection of body magnetic flux density
670      *                     measurements with standard deviation of
671      *                     magnetometer measurements taken at the same
672      *                     position with zero velocity and unknown different
673      *                     orientations.
674      * @param hardIron     known hard-iron.
675      * @param listener     listener to handle events raised by this calibrator.
676      * @throws IllegalArgumentException if provided hard-iron array does
677      *                                  not have length 3.
678      */
679     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
680             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
681             final double[] hardIron,
682             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
683         super(position, measurements, hardIron, listener);
684     }
685 
686     /**
687      * Constructor.
688      *
689      * @param position       position where body magnetic flux density measurements
690      *                       have been taken.
691      * @param measurements   collection of body magnetic flux density
692      *                       measurements with standard deviation of
693      *                       magnetometer measurements taken at the same
694      *                       position with zero velocity and unknown different
695      *                       orientations.
696      * @param commonAxisUsed indicates whether z-axis is assumed to be common
697      *                       for the accelerometer, gyroscope and magnetometer.
698      * @param hardIron       known hard-iron.
699      * @throws IllegalArgumentException if provided hard-iron array does
700      *                                  not have length 3.
701      */
702     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
703             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
704             final boolean commonAxisUsed, final double[] hardIron) {
705         super(position, measurements, commonAxisUsed, hardIron);
706     }
707 
708     /**
709      * Constructor.
710      *
711      * @param position       position where body magnetic flux density measurements
712      *                       have been taken.
713      * @param measurements   collection of body magnetic flux density
714      *                       measurements with standard deviation of
715      *                       magnetometer measurements taken at the same
716      *                       position with zero velocity and unknown different
717      *                       orientations.
718      * @param commonAxisUsed indicates whether z-axis is assumed to be common
719      *                       for the accelerometer, gyroscope and magnetometer.
720      * @param hardIron       known hard-iron.
721      * @param listener       listener to handle events raised by this calibrator.
722      * @throws IllegalArgumentException if provided hard-iron array does
723      *                                  not have length 3.
724      */
725     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
726             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
727             final boolean commonAxisUsed, final double[] hardIron,
728             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
729         super(position, measurements, commonAxisUsed, hardIron, listener);
730     }
731 
732     /**
733      * Constructor.
734      *
735      * @param position        position where body magnetic flux density measurements
736      *                        have been taken.
737      * @param measurements    collection of body magnetic flux density
738      *                        measurements with standard deviation of
739      *                        magnetometer measurements taken at the same
740      *                        position with zero velocity and unknown different
741      *                        orientations.
742      * @param initialHardIron initial hard-iron to find a solution.
743      * @throws IllegalArgumentException if provided hard-iron matrix is not
744      *                                  3x1.
745      */
746     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
747             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
748             final Matrix initialHardIron) {
749         super(position, measurements, initialHardIron);
750     }
751 
752     /**
753      * Constructor.
754      *
755      * @param position     position where body magnetic flux density measurements
756      *                     have been taken.
757      * @param measurements collection of body magnetic flux density
758      *                     measurements with standard deviation of
759      *                     magnetometer measurements taken at the same
760      *                     position with zero velocity and unknown different
761      *                     orientations.
762      * @param hardIron     known hard-iron.
763      * @param listener     listener to handle events raised by this calibrator.
764      * @throws IllegalArgumentException if provided hard-iron matrix is not
765      *                                  3x1.
766      */
767     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
768             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
769             final Matrix hardIron,
770             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
771         super(position, measurements, hardIron, listener);
772     }
773 
774     /**
775      * Constructor.
776      *
777      * @param position       position where body magnetic flux density measurements
778      *                       have been taken.
779      * @param measurements   collection of body magnetic flux density
780      *                       measurements with standard deviation of
781      *                       magnetometer measurements taken at the same
782      *                       position with zero velocity and unknown different
783      *                       orientations.
784      * @param commonAxisUsed indicates whether z-axis is assumed to be common
785      *                       for the accelerometer, gyroscope and magnetometer.
786      * @param hardIron       known hard-iron.
787      * @throws IllegalArgumentException if provided hard-iron matrix is not
788      *                                  3x1.
789      */
790     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
791             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
792             final boolean commonAxisUsed, final Matrix hardIron) {
793         super(position, measurements, commonAxisUsed, hardIron);
794     }
795 
796     /**
797      * Constructor.
798      *
799      * @param position       position where body magnetic flux density measurements
800      *                       have been taken.
801      * @param measurements   collection of body magnetic flux density
802      *                       measurements with standard deviation of
803      *                       magnetometer measurements taken at the same
804      *                       position with zero velocity and unknown different
805      *                       orientations.
806      * @param commonAxisUsed indicates whether z-axis is assumed to be common
807      *                       for the accelerometer, gyroscope and magnetometer.
808      * @param hardIron       known hard-iron.
809      * @param listener       listener to handle events raised by this calibrator.
810      * @throws IllegalArgumentException if provided hard-iron matrix is not
811      *                                  3x1.
812      */
813     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
814             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
815             final boolean commonAxisUsed, final Matrix hardIron,
816             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
817         super(position, measurements, commonAxisUsed, hardIron, listener);
818     }
819 
820     /**
821      * Constructor.
822      *
823      * @param position     position where body magnetic flux density measurements
824      *                     have been taken.
825      * @param measurements collection of body magnetic flux density
826      *                     measurements with standard deviation of
827      *                     magnetometer measurements taken at the same
828      *                     position with zero velocity and unknown different
829      *                     orientations.
830      * @param hardIron     known hard-iron.
831      * @param initialMm    initial soft-iron matrix containing scale factors
832      *                     and cross coupling errors.
833      * @throws IllegalArgumentException if provided hard-iron matrix is not
834      *                                  3x1 or if soft-iron matrix is not
835      *                                  3x3.
836      */
837     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
838             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
839             final Matrix hardIron, final Matrix initialMm) {
840         super(position, measurements, hardIron, initialMm);
841     }
842 
843     /**
844      * Constructor.
845      *
846      * @param position     position where body magnetic flux density measurements
847      *                     have been taken.
848      * @param measurements collection of body magnetic flux density
849      *                     measurements with standard deviation of
850      *                     magnetometer measurements taken at the same
851      *                     position with zero velocity and unknown different
852      *                     orientations.
853      * @param hardIron     known hard-iron.
854      * @param initialMm    initial soft-iron matrix containing scale factors
855      *                     and cross coupling errors.
856      * @param listener     listener to handle events raised by this calibrator.
857      * @throws IllegalArgumentException if provided hard-iron matrix is not
858      *                                  3x1 or if soft-iron matrix is not
859      *                                  3x3.
860      */
861     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
862             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
863             final Matrix hardIron, final Matrix initialMm,
864             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
865         super(position, measurements, hardIron, initialMm, listener);
866     }
867 
868     /**
869      * Constructor.
870      *
871      * @param position       position where body magnetic flux density measurements
872      *                       have been taken.
873      * @param measurements   collection of body magnetic flux density
874      *                       measurements with standard deviation of
875      *                       magnetometer measurements taken at the same
876      *                       position with zero velocity and unknown different
877      *                       orientations.
878      * @param commonAxisUsed indicates whether z-axis is assumed to be common
879      *                       for the accelerometer, gyroscope and magnetometer.
880      * @param hardIron       known hard-iron.
881      * @param initialMm      initial soft-iron matrix containing scale factors
882      *                       and cross coupling errors.
883      * @throws IllegalArgumentException if provided hard-iron matrix is not
884      *                                  3x1 or if soft-iron matrix is not
885      *                                  3x3.
886      */
887     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
888             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
889             final boolean commonAxisUsed, final Matrix hardIron, final Matrix initialMm) {
890         super(position, measurements, commonAxisUsed, hardIron,
891                 initialMm);
892     }
893 
894     /**
895      * Constructor.
896      *
897      * @param position       position where body magnetic flux density measurements
898      *                       have been taken.
899      * @param measurements   collection of body magnetic flux density
900      *                       measurements with standard deviation of
901      *                       magnetometer measurements taken at the same
902      *                       position with zero velocity and unknown different
903      *                       orientations.
904      * @param commonAxisUsed indicates whether z-axis is assumed to be common
905      *                       for the accelerometer, gyroscope and magnetometer.
906      * @param hardIron       known hard-iron.
907      * @param initialMm      initial soft-iron matrix containing scale factors
908      *                       and cross coupling errors.
909      * @param listener       listener to handle events raised by this calibrator.
910      * @throws IllegalArgumentException if provided hard-iron matrix is not
911      *                                  3x1 or if soft-iron matrix is not
912      *                                  3x3.
913      */
914     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
915             final ECEFPosition position, final List<StandardDeviationBodyMagneticFluxDensity> measurements,
916             final boolean commonAxisUsed, final Matrix hardIron, final Matrix initialMm,
917             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
918         super(position, measurements, commonAxisUsed, hardIron, initialMm, listener);
919     }
920 
921     /**
922      * Constructor.
923      *
924      * @param qualityScores quality scores corresponding to each provided
925      *                      measurement. The larger the score value the better
926      *                      the quality of the sample.
927      * @param measurements  list of body magnetic flux density
928      *                      measurements with standard deviation of
929      *                      magnetometer measurements taken at the same
930      *                      position with zero velocity and unknown different
931      *                      orientations.
932      * @throws IllegalArgumentException if provided quality scores length
933      *                                  is smaller than 7 samples.
934      */
935     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
936             final double[] qualityScores, final List<StandardDeviationBodyMagneticFluxDensity> measurements) {
937         super(measurements);
938         internalSetQualityScores(qualityScores);
939     }
940 
941     /**
942      * Constructor.
943      *
944      * @param qualityScores  quality scores corresponding to each provided
945      *                       measurement. The larger the score value the better
946      *                       the quality of the sample.
947      * @param commonAxisUsed indicates whether z-axis is assumed to be common
948      *                       for the accelerometer, gyroscope and magnetometer.
949      * @throws IllegalArgumentException if provided quality scores length
950      *                                  is smaller than 7 samples.
951      */
952     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
953             final double[] qualityScores, final boolean commonAxisUsed) {
954         super(commonAxisUsed);
955         internalSetQualityScores(qualityScores);
956     }
957 
958     /**
959      * Constructor.
960      *
961      * @param qualityScores quality scores corresponding to each provided
962      *                      measurement. The larger the score value the better
963      *                      the quality of the sample.
964      * @param magneticModel Earth's magnetic model. If null, a default model
965      *                      will be used instead.
966      * @throws IllegalArgumentException if provided quality scores length
967      *                                  is smaller than 7 samples.
968      */
969     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
970             final double[] qualityScores, final WorldMagneticModel magneticModel) {
971         super(magneticModel);
972         internalSetQualityScores(qualityScores);
973     }
974 
975     /**
976      * Constructor.
977      *
978      * @param qualityScores quality scores corresponding to each provided
979      *                      measurement. The larger the score value the better
980      *                      the quality of the sample.
981      * @param hardIron      known hard-iron.
982      * @throws IllegalArgumentException if provided hard-iron array does
983      *                                  not have length 3 or if provided
984      *                                  quality scores length is smaller
985      *                                  than 7 samples.
986      */
987     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
988             final double[] qualityScores, final double[] hardIron) {
989         super(hardIron);
990         internalSetQualityScores(qualityScores);
991     }
992 
993     /**
994      * Constructor.
995      *
996      * @param qualityScores quality scores corresponding to each provided
997      *                      measurement. The larger the score value the better
998      *                      the quality of the sample.
999      * @param hardIron      known hard-iron.
1000      * @throws IllegalArgumentException if provided hard-iron matrix is not
1001      *                                  3x1 or if provided quality scores
1002      *                                  length is smaller than 7 samples.
1003      */
1004     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1005             final double[] qualityScores, final Matrix hardIron) {
1006         super(hardIron);
1007         internalSetQualityScores(qualityScores);
1008     }
1009 
1010     /**
1011      * Constructor.
1012      *
1013      * @param qualityScores quality scores corresponding to each provided
1014      *                      measurement. The larger the score value the better
1015      *                      the quality of the sample.
1016      * @param hardIron      known hard-iron.
1017      * @param initialMm     initial soft-iron matrix containing scale factors
1018      *                      and cross coupling errors.
1019      * @throws IllegalArgumentException if provided hard-iron matrix is not
1020      *                                  3x1 or if soft-iron matrix is not
1021      *                                  3x3 or if provided quality scores
1022      *                                  length is smaller than 7 samples.
1023      */
1024     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1025             final double[] qualityScores, final Matrix hardIron, final Matrix initialMm) {
1026         super(hardIron, initialMm);
1027         internalSetQualityScores(qualityScores);
1028     }
1029 
1030     /**
1031      * Constructor.
1032      *
1033      * @param qualityScores quality scores corresponding to each provided
1034      *                      measurement. The larger the score value the better
1035      *                      the quality of the sample.
1036      * @param position      position where body magnetic flux density measurements
1037      *                      have been taken.
1038      * @throws IllegalArgumentException if provided quality scores length
1039      *                                  is smaller than 7 samples.
1040      */
1041     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1042             final double[] qualityScores, final NEDPosition position) {
1043         super(position);
1044         internalSetQualityScores(qualityScores);
1045     }
1046 
1047     /**
1048      * Constructor.
1049      *
1050      * @param qualityScores quality scores corresponding to each provided
1051      *                      measurement. The larger the score value the better
1052      *                      the quality of the sample.
1053      * @param position      position where body magnetic flux density measurements
1054      *                      have been taken.
1055      * @param measurements  collection of body magnetic flux density
1056      *                      measurements with standard deviation of
1057      *                      magnetometer measurements taken at the same
1058      *                      position with zero velocity and unknown different
1059      *                      orientations.
1060      * @throws IllegalArgumentException if provided quality scores length
1061      *                                  is smaller than 7 samples.
1062      */
1063     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1064             final double[] qualityScores, final NEDPosition position,
1065             final List<StandardDeviationBodyMagneticFluxDensity> measurements) {
1066         super(position, measurements);
1067         internalSetQualityScores(qualityScores);
1068     }
1069 
1070     /**
1071      * Constructor.
1072      *
1073      * @param qualityScores quality scores corresponding to each provided
1074      *                      measurement. The larger the score value the better
1075      *                      the quality of the sample.
1076      * @param position      position where body magnetic flux density measurements
1077      *                      have been taken.
1078      * @param measurements  collection of body magnetic flux density
1079      *                      measurements with standard deviation of
1080      *                      magnetometer measurements taken at the same
1081      *                      position with zero velocity and unknown different
1082      *                      orientations.
1083      * @param listener      listener to handle events raised by this calibrator.
1084      * @throws IllegalArgumentException if provided quality scores length
1085      *                                  is smaller than 7 samples.
1086      */
1087     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1088             final double[] qualityScores, final NEDPosition position,
1089             final List<StandardDeviationBodyMagneticFluxDensity> measurements,
1090             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1091         super(position, measurements, listener);
1092         internalSetQualityScores(qualityScores);
1093     }
1094 
1095     /**
1096      * Constructor.
1097      *
1098      * @param qualityScores  quality scores corresponding to each provided
1099      *                       measurement. The larger the score value the better
1100      *                       the quality of the sample.
1101      * @param position       position where body magnetic flux density measurements
1102      *                       have been taken.
1103      * @param measurements   collection of body magnetic flux density
1104      *                       measurements with standard deviation of
1105      *                       magnetometer measurements taken at the same
1106      *                       position with zero velocity and unknown different
1107      *                       orientations.
1108      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1109      *                       for the accelerometer, gyroscope and magnetometer.
1110      * @throws IllegalArgumentException if provided quality scores length
1111      *                                  is smaller than 7 samples.
1112      */
1113     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1114             final double[] qualityScores, final NEDPosition position,
1115             final List<StandardDeviationBodyMagneticFluxDensity> measurements,
1116             final boolean commonAxisUsed) {
1117         super(position, measurements, commonAxisUsed);
1118         internalSetQualityScores(qualityScores);
1119     }
1120 
1121     /**
1122      * Constructor.
1123      *
1124      * @param qualityScores  quality scores corresponding to each provided
1125      *                       measurement. The larger the score value the better
1126      *                       the quality of the sample.
1127      * @param position       position where body magnetic flux density measurements
1128      *                       have been taken.
1129      * @param measurements   collection of body magnetic flux density
1130      *                       measurements with standard deviation of
1131      *                       magnetometer measurements taken at the same
1132      *                       position with zero velocity and unknown different
1133      *                       orientations.
1134      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1135      *                       for the accelerometer, gyroscope and magnetometer.
1136      * @param listener       listener to handle events raised by this calibrator.
1137      * @throws IllegalArgumentException if provided quality scores length
1138      *                                  is smaller than 7 samples.
1139      */
1140     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1141             final double[] qualityScores, final NEDPosition position,
1142             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
1143             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1144         super(position, measurements, commonAxisUsed, listener);
1145         internalSetQualityScores(qualityScores);
1146     }
1147 
1148     /**
1149      * Constructor.
1150      *
1151      * @param qualityScores quality scores corresponding to each provided
1152      *                      measurement. The larger the score value the better
1153      *                      the quality of the sample.
1154      * @param position      position where body magnetic flux density measurements
1155      *                      have been taken.
1156      * @param measurements  collection of body magnetic flux density
1157      *                      measurements with standard deviation of
1158      *                      magnetometer measurements taken at the same
1159      *                      position with zero velocity and unknown different
1160      *                      orientations.
1161      * @param hardIron      known hard-iron.
1162      * @throws IllegalArgumentException if provided hard-iron array does
1163      *                                  not have length 3 or if provided
1164      *                                  quality scores length is smaller
1165      *                                  than 7 samples.
1166      */
1167     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1168             final double[] qualityScores, final NEDPosition position,
1169             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final double[] hardIron) {
1170         super(position, measurements, hardIron);
1171         internalSetQualityScores(qualityScores);
1172     }
1173 
1174     /**
1175      * Constructor.
1176      *
1177      * @param qualityScores quality scores corresponding to each provided
1178      *                      measurement. The larger the score value the better
1179      *                      the quality of the sample.
1180      * @param position      position where body magnetic flux density measurements
1181      *                      have been taken.
1182      * @param measurements  collection of body magnetic flux density
1183      *                      measurements with standard deviation of
1184      *                      magnetometer measurements taken at the same
1185      *                      position with zero velocity and unknown different
1186      *                      orientations.
1187      * @param hardIron      known hard-iron.
1188      * @param listener      listener to handle events raised by this calibrator.
1189      * @throws IllegalArgumentException if provided hard-iron array does
1190      *                                  not have length 3 or if provided
1191      *                                  quality scores length is smaller
1192      *                                  than 7 samples.
1193      */
1194     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1195             final double[] qualityScores, final NEDPosition position,
1196             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final double[] hardIron,
1197             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1198         super(position, measurements, hardIron, listener);
1199         internalSetQualityScores(qualityScores);
1200     }
1201 
1202     /**
1203      * Constructor.
1204      *
1205      * @param qualityScores  quality scores corresponding to each provided
1206      *                       measurement. The larger the score value the better
1207      *                       the quality of the sample.
1208      * @param position       position where body magnetic flux density measurements
1209      *                       have been taken.
1210      * @param measurements   collection of body magnetic flux density
1211      *                       measurements with standard deviation of
1212      *                       magnetometer measurements taken at the same
1213      *                       position with zero velocity and unknown different
1214      *                       orientations.
1215      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1216      *                       for the accelerometer, gyroscope and magnetometer.
1217      * @param hardIron       known hard-iron.
1218      * @throws IllegalArgumentException if provided hard-iron array does
1219      *                                  not have length 3 or if provided
1220      *                                  quality scores length is smaller
1221      *                                  than 7 samples.
1222      */
1223     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1224             final double[] qualityScores, final NEDPosition position,
1225             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
1226             final double[] hardIron) {
1227         super(position, measurements, commonAxisUsed, hardIron);
1228         internalSetQualityScores(qualityScores);
1229     }
1230 
1231     /**
1232      * Constructor.
1233      *
1234      * @param qualityScores  quality scores corresponding to each provided
1235      *                       measurement. The larger the score value the better
1236      *                       the quality of the sample.
1237      * @param position       position where body magnetic flux density measurements
1238      *                       have been taken.
1239      * @param measurements   collection of body magnetic flux density
1240      *                       measurements with standard deviation of
1241      *                       magnetometer measurements taken at the same
1242      *                       position with zero velocity and unknown different
1243      *                       orientations.
1244      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1245      *                       for the accelerometer, gyroscope and magnetometer.
1246      * @param hardIron       known hard-iron.
1247      * @param listener       listener to handle events raised by this calibrator.
1248      * @throws IllegalArgumentException if provided hard-iron array does
1249      *                                  not have length 3 or if provided
1250      *                                  quality scores length is smaller
1251      *                                  than 7 samples.
1252      */
1253     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1254             final double[] qualityScores, final NEDPosition position,
1255             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
1256             final double[] hardIron,
1257             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1258         super(position, measurements, commonAxisUsed, hardIron, listener);
1259         internalSetQualityScores(qualityScores);
1260     }
1261 
1262     /**
1263      * Constructor.
1264      *
1265      * @param qualityScores quality scores corresponding to each provided
1266      *                      measurement. The larger the score value the better
1267      *                      the quality of the sample.
1268      * @param position      position where body magnetic flux density measurements
1269      *                      have been taken.
1270      * @param measurements  collection of body magnetic flux density
1271      *                      measurements with standard deviation of
1272      *                      magnetometer measurements taken at the same
1273      *                      position with zero velocity and unknown different
1274      *                      orientations.
1275      * @param hardIron      known hard-iron.
1276      * @throws IllegalArgumentException if provided hard-iron matrix is not
1277      *                                  3x1 or if provided quality scores
1278      *                                  length is smaller than 7 samples.
1279      */
1280     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1281             final double[] qualityScores, final NEDPosition position,
1282             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron) {
1283         super(position, measurements, hardIron);
1284         internalSetQualityScores(qualityScores);
1285     }
1286 
1287     /**
1288      * Constructor.
1289      *
1290      * @param qualityScores quality scores corresponding to each provided
1291      *                      measurement. The larger the score value the better
1292      *                      the quality of the sample.
1293      * @param position      position where body magnetic flux density measurements
1294      *                      have been taken.
1295      * @param measurements  collection of body magnetic flux density
1296      *                      measurements with standard deviation of
1297      *                      magnetometer measurements taken at the same
1298      *                      position with zero velocity and unknown different
1299      *                      orientations.
1300      * @param hardIron      known hard-iron.
1301      * @param listener      listener to handle events raised by this calibrator.
1302      * @throws IllegalArgumentException if provided hard-iron matrix is not
1303      *                                  3x1 or if provided quality scores
1304      *                                  length is smaller than 7 samples.
1305      */
1306     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1307             final double[] qualityScores, final NEDPosition position,
1308             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
1309             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1310         super(position, measurements, hardIron, listener);
1311         internalSetQualityScores(qualityScores);
1312     }
1313 
1314     /**
1315      * Constructor.
1316      *
1317      * @param qualityScores  quality scores corresponding to each provided
1318      *                       measurement. The larger the score value the better
1319      *                       the quality of the sample.
1320      * @param position       position where body magnetic flux density measurements
1321      *                       have been taken.
1322      * @param measurements   collection of body magnetic flux density
1323      *                       measurements with standard deviation of
1324      *                       magnetometer measurements taken at the same
1325      *                       position with zero velocity and unknown different
1326      *                       orientations.
1327      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1328      *                       for the accelerometer, gyroscope and magnetometer.
1329      * @param hardIron       known hard-iron.
1330      * @throws IllegalArgumentException if provided hard-iron matrix is not
1331      *                                  3x1 or if provided quality scores
1332      *                                  length is smaller than 7 samples.
1333      */
1334     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1335             final double[] qualityScores, final NEDPosition position,
1336             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
1337             final Matrix hardIron) {
1338         super(position, measurements, commonAxisUsed, hardIron);
1339         internalSetQualityScores(qualityScores);
1340     }
1341 
1342     /**
1343      * Constructor.
1344      *
1345      * @param qualityScores  quality scores corresponding to each provided
1346      *                       measurement. The larger the score value the better
1347      *                       the quality of the sample.
1348      * @param position       position where body magnetic flux density measurements
1349      *                       have been taken.
1350      * @param measurements   collection of body magnetic flux density
1351      *                       measurements with standard deviation of
1352      *                       magnetometer measurements taken at the same
1353      *                       position with zero velocity and unknown different
1354      *                       orientations.
1355      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1356      *                       for the accelerometer, gyroscope and magnetometer.
1357      * @param hardIron       known hard-iron.
1358      * @param listener       listener to handle events raised by this calibrator.
1359      * @throws IllegalArgumentException if provided hard-iron matrix is not
1360      *                                  3x1 or if provided quality scores
1361      *                                  length is smaller than 7 samples.
1362      */
1363     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1364             final double[] qualityScores, final NEDPosition position,
1365             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
1366             final Matrix hardIron, final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1367         super(position, measurements, commonAxisUsed, hardIron, listener);
1368         internalSetQualityScores(qualityScores);
1369     }
1370 
1371     /**
1372      * Constructor.
1373      *
1374      * @param qualityScores quality scores corresponding to each provided
1375      *                      measurement. The larger the score value the better
1376      *                      the quality of the sample.
1377      * @param position      position where body magnetic flux density measurements
1378      *                      have been taken.
1379      * @param measurements  collection of body magnetic flux density
1380      *                      measurements with standard deviation of
1381      *                      magnetometer measurements taken at the same
1382      *                      position with zero velocity and unknown different
1383      *                      orientations.
1384      * @param hardIron      known hard-iron.
1385      * @param initialMm     initial soft-iron matrix containing scale factors
1386      *                      and cross coupling errors.
1387      * @throws IllegalArgumentException if provided hard-iron matrix is not
1388      *                                  3x1 or if soft-iron matrix is not
1389      *                                  3x3 or if provided quality scores
1390      *                                  length is smaller than 7 samples.
1391      */
1392     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1393             final double[] qualityScores, final NEDPosition position,
1394             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
1395             final Matrix initialMm) {
1396         super(position, measurements, hardIron, initialMm);
1397         internalSetQualityScores(qualityScores);
1398     }
1399 
1400     /**
1401      * Constructor.
1402      *
1403      * @param qualityScores quality scores corresponding to each provided
1404      *                      measurement. The larger the score value the better
1405      *                      the quality of the sample.
1406      * @param position      position where body magnetic flux density measurements
1407      *                      have been taken.
1408      * @param measurements  collection of body magnetic flux density
1409      *                      measurements with standard deviation of
1410      *                      magnetometer measurements taken at the same
1411      *                      position with zero velocity and unknown different
1412      *                      orientations.
1413      * @param hardIron      known hard-iron.
1414      * @param initialMm     initial soft-iron matrix containing scale factors
1415      *                      and cross coupling errors.
1416      * @param listener      listener to handle events raised by this calibrator.
1417      * @throws IllegalArgumentException if provided hard-iron matrix is not
1418      *                                  3x1 or if soft-iron matrix is not
1419      *                                  3x3 or if provided quality scores
1420      *                                  length is smaller than 7 samples.
1421      */
1422     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1423             final double[] qualityScores, final NEDPosition position,
1424             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
1425             final Matrix initialMm,
1426             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1427         super(position, measurements, hardIron, initialMm, listener);
1428         internalSetQualityScores(qualityScores);
1429     }
1430 
1431     /**
1432      * Constructor.
1433      *
1434      * @param qualityScores  quality scores corresponding to each provided
1435      *                       measurement. The larger the score value the better
1436      *                       the quality of the sample.
1437      * @param position       position where body magnetic flux density measurements
1438      *                       have been taken.
1439      * @param measurements   collection of body magnetic flux density
1440      *                       measurements with standard deviation of
1441      *                       magnetometer measurements taken at the same
1442      *                       position with zero velocity and unknown different
1443      *                       orientations.
1444      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1445      *                       for the accelerometer, gyroscope and magnetometer.
1446      * @param hardIron       known hard-iron.
1447      * @param initialMm      initial soft-iron matrix containing scale factors
1448      *                       and cross coupling errors.
1449      * @throws IllegalArgumentException if provided hard-iron matrix is not
1450      *                                  3x1 or if soft-iron matrix is not
1451      *                                  3x3 or if provided quality scores
1452      *                                  length is smaller than 7 samples.
1453      */
1454     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1455             final double[] qualityScores, final NEDPosition position,
1456             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
1457             final Matrix hardIron, final Matrix initialMm) {
1458         super(position, measurements, commonAxisUsed, hardIron, initialMm);
1459         internalSetQualityScores(qualityScores);
1460     }
1461 
1462     /**
1463      * Constructor.
1464      *
1465      * @param qualityScores  quality scores corresponding to each provided
1466      *                       measurement. The larger the score value the better
1467      *                       the quality of the sample.
1468      * @param position       position where body magnetic flux density measurements
1469      *                       have been taken.
1470      * @param measurements   collection of body magnetic flux density
1471      *                       measurements with standard deviation of
1472      *                       magnetometer measurements taken at the same
1473      *                       position with zero velocity and unknown different
1474      *                       orientations.
1475      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1476      *                       for the accelerometer, gyroscope and magnetometer.
1477      * @param hardIron       known hard-iron.
1478      * @param initialMm      initial soft-iron matrix containing scale factors
1479      *                       and cross coupling errors.
1480      * @param listener       listener to handle events raised by this calibrator.
1481      * @throws IllegalArgumentException if provided hard-iron matrix is not
1482      *                                  3x1 or if soft-iron matrix is not
1483      *                                  3x3 or if provided quality scores
1484      *                                  length is smaller than 7 samples.
1485      */
1486     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1487             final double[] qualityScores, final NEDPosition position,
1488             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
1489             final Matrix hardIron, final Matrix initialMm,
1490             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1491         super(position, measurements, commonAxisUsed, hardIron, initialMm, listener);
1492         internalSetQualityScores(qualityScores);
1493     }
1494 
1495     /**
1496      * Constructor.
1497      *
1498      * @param qualityScores quality scores corresponding to each provided
1499      *                      measurement. The larger the score value the better
1500      *                      the quality of the sample.
1501      * @param position      position where body magnetic flux density measurements
1502      *                      have been taken.
1503      * @throws IllegalArgumentException if provided quality scores length
1504      *                                  is smaller than 7 samples.
1505      */
1506     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1507             final double[] qualityScores, final ECEFPosition position) {
1508         super(position);
1509         internalSetQualityScores(qualityScores);
1510     }
1511 
1512     /**
1513      * Constructor.
1514      *
1515      * @param qualityScores quality scores corresponding to each provided
1516      *                      measurement. The larger the score value the better
1517      *                      the quality of the sample.
1518      * @param position      position where body magnetic flux density measurements
1519      *                      have been taken.
1520      * @param measurements  collection of body magnetic flux density
1521      *                      measurements with standard deviation of
1522      *                      magnetometer measurements taken at the same
1523      *                      position with zero velocity and unknown different
1524      *                      orientations.
1525      * @throws IllegalArgumentException if provided quality scores length
1526      *                                  is smaller than 7 samples.
1527      */
1528     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1529             final double[] qualityScores, final ECEFPosition position,
1530             final List<StandardDeviationBodyMagneticFluxDensity> measurements) {
1531         super(position, measurements);
1532         internalSetQualityScores(qualityScores);
1533     }
1534 
1535     /**
1536      * Constructor.
1537      *
1538      * @param qualityScores quality scores corresponding to each provided
1539      *                      measurement. The larger the score value the better
1540      *                      the quality of the sample.
1541      * @param position      position where body magnetic flux density measurements
1542      *                      have been taken.
1543      * @param measurements  collection of body magnetic flux density
1544      *                      measurements with standard deviation of
1545      *                      magnetometer measurements taken at the same
1546      *                      position with zero velocity and unknown different
1547      *                      orientations.
1548      * @param listener      listener to handle events raised by this calibrator.
1549      * @throws IllegalArgumentException if provided quality scores length
1550      *                                  is smaller than 7 samples.
1551      */
1552     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1553             final double[] qualityScores, final ECEFPosition position,
1554             final List<StandardDeviationBodyMagneticFluxDensity> measurements,
1555             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1556         super(position, measurements, listener);
1557         internalSetQualityScores(qualityScores);
1558     }
1559 
1560     /**
1561      * Constructor.
1562      *
1563      * @param qualityScores  quality scores corresponding to each provided
1564      *                       measurement. The larger the score value the better
1565      *                       the quality of the sample.
1566      * @param position       position where body magnetic flux density measurements
1567      *                       have been taken.
1568      * @param measurements   collection of body magnetic flux density
1569      *                       measurements with standard deviation of
1570      *                       magnetometer measurements taken at the same
1571      *                       position with zero velocity and unknown different
1572      *                       orientations.
1573      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1574      *                       for the accelerometer, gyroscope and magnetometer.
1575      * @throws IllegalArgumentException if provided quality scores length
1576      *                                  is smaller than 7 samples.
1577      */
1578     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1579             final double[] qualityScores, final ECEFPosition position,
1580             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed) {
1581         super(position, measurements, commonAxisUsed);
1582         internalSetQualityScores(qualityScores);
1583     }
1584 
1585     /**
1586      * Constructor.
1587      *
1588      * @param qualityScores  quality scores corresponding to each provided
1589      *                       measurement. The larger the score value the better
1590      *                       the quality of the sample.
1591      * @param position       position where body magnetic flux density measurements
1592      *                       have been taken.
1593      * @param measurements   collection of body magnetic flux density
1594      *                       measurements with standard deviation of
1595      *                       magnetometer measurements taken at the same
1596      *                       position with zero velocity and unknown different
1597      *                       orientations.
1598      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1599      *                       for the accelerometer, gyroscope and magnetometer.
1600      * @param listener       listener to handle events raised by this calibrator.
1601      * @throws IllegalArgumentException if provided quality scores length
1602      *                                  is smaller than 7 samples.
1603      */
1604     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1605             final double[] qualityScores, final ECEFPosition position,
1606             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
1607             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1608         super(position, measurements, commonAxisUsed, listener);
1609         internalSetQualityScores(qualityScores);
1610     }
1611 
1612     /**
1613      * Constructor.
1614      *
1615      * @param qualityScores quality scores corresponding to each provided
1616      *                      measurement. The larger the score value the better
1617      *                      the quality of the sample.
1618      * @param position      position where body magnetic flux density measurements
1619      *                      have been taken.
1620      * @param measurements  collection of body magnetic flux density
1621      *                      measurements with standard deviation of
1622      *                      magnetometer measurements taken at the same
1623      *                      position with zero velocity and unknown different
1624      *                      orientations.
1625      * @param hardIron      known hard-iron.
1626      * @throws IllegalArgumentException if provided hard-iron array does
1627      *                                  not have length 3 or if provided
1628      *                                  quality scores length is smaller
1629      *                                  than 7 samples.
1630      */
1631     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1632             final double[] qualityScores, final ECEFPosition position,
1633             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final double[] hardIron) {
1634         super(position, measurements, hardIron);
1635         internalSetQualityScores(qualityScores);
1636     }
1637 
1638     /**
1639      * Constructor.
1640      *
1641      * @param qualityScores quality scores corresponding to each provided
1642      *                      measurement. The larger the score value the better
1643      *                      the quality of the sample.
1644      * @param position      position where body magnetic flux density measurements
1645      *                      have been taken.
1646      * @param measurements  collection of body magnetic flux density
1647      *                      measurements with standard deviation of
1648      *                      magnetometer measurements taken at the same
1649      *                      position with zero velocity and unknown different
1650      *                      orientations.
1651      * @param hardIron      known hard-iron.
1652      * @param listener      listener to handle events raised by this calibrator.
1653      * @throws IllegalArgumentException if provided hard-iron array does
1654      *                                  not have length 3 or if provided
1655      *                                  quality scores length is smaller
1656      *                                  than 7 samples.
1657      */
1658     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1659             final double[] qualityScores, final ECEFPosition position,
1660             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final double[] hardIron,
1661             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1662         super(position, measurements, hardIron, listener);
1663         internalSetQualityScores(qualityScores);
1664     }
1665 
1666     /**
1667      * Constructor.
1668      *
1669      * @param qualityScores  quality scores corresponding to each provided
1670      *                       measurement. The larger the score value the better
1671      *                       the quality of the sample.
1672      * @param position       position where body magnetic flux density measurements
1673      *                       have been taken.
1674      * @param measurements   collection of body magnetic flux density
1675      *                       measurements with standard deviation of
1676      *                       magnetometer measurements taken at the same
1677      *                       position with zero velocity and unknown different
1678      *                       orientations.
1679      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1680      *                       for the accelerometer, gyroscope and magnetometer.
1681      * @param hardIron       known hard-iron.
1682      * @throws IllegalArgumentException if provided hard-iron array does
1683      *                                  not have length 3 or if provided
1684      *                                  quality scores length is smaller
1685      *                                  than 7 samples.
1686      */
1687     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1688             final double[] qualityScores, final ECEFPosition position,
1689             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
1690             final double[] hardIron) {
1691         super(position, measurements, commonAxisUsed, hardIron);
1692         internalSetQualityScores(qualityScores);
1693     }
1694 
1695     /**
1696      * Constructor.
1697      *
1698      * @param qualityScores  quality scores corresponding to each provided
1699      *                       measurement. The larger the score value the better
1700      *                       the quality of the sample.
1701      * @param position       position where body magnetic flux density measurements
1702      *                       have been taken.
1703      * @param measurements   collection of body magnetic flux density
1704      *                       measurements with standard deviation of
1705      *                       magnetometer measurements taken at the same
1706      *                       position with zero velocity and unknown different
1707      *                       orientations.
1708      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1709      *                       for the accelerometer, gyroscope and magnetometer.
1710      * @param hardIron       known hard-iron.
1711      * @param listener       listener to handle events raised by this calibrator.
1712      * @throws IllegalArgumentException if provided hard-iron array does
1713      *                                  not have length 3 or if provided
1714      *                                  quality scores length is smaller
1715      *                                  than 7 samples.
1716      */
1717     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1718             final double[] qualityScores, final ECEFPosition position,
1719             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
1720             final double[] hardIron,
1721             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1722         super(position, measurements, commonAxisUsed, hardIron, listener);
1723         internalSetQualityScores(qualityScores);
1724     }
1725 
1726     /**
1727      * Constructor.
1728      *
1729      * @param qualityScores quality scores corresponding to each provided
1730      *                      measurement. The larger the score value the better
1731      *                      the quality of the sample.
1732      * @param position      position where body magnetic flux density measurements
1733      *                      have been taken.
1734      * @param measurements  collection of body magnetic flux density
1735      *                      measurements with standard deviation of
1736      *                      magnetometer measurements taken at the same
1737      *                      position with zero velocity and unknown different
1738      *                      orientations.
1739      * @param hardIron      known hard-iron.
1740      * @throws IllegalArgumentException if provided hard-iron matrix is not
1741      *                                  3x1 or if provided quality scores
1742      *                                  length is smaller than 7 samples.
1743      */
1744     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1745             final double[] qualityScores, final ECEFPosition position,
1746             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron) {
1747         super(position, measurements, hardIron);
1748         internalSetQualityScores(qualityScores);
1749     }
1750 
1751     /**
1752      * Constructor.
1753      *
1754      * @param qualityScores quality scores corresponding to each provided
1755      *                      measurement. The larger the score value the better
1756      *                      the quality of the sample.
1757      * @param position      position where body magnetic flux density measurements
1758      *                      have been taken.
1759      * @param measurements  collection of body magnetic flux density
1760      *                      measurements with standard deviation of
1761      *                      magnetometer measurements taken at the same
1762      *                      position with zero velocity and unknown different
1763      *                      orientations.
1764      * @param hardIron      known hard-iron.
1765      * @param listener      listener to handle events raised by this calibrator.
1766      * @throws IllegalArgumentException if provided hard-iron matrix is not
1767      *                                  3x1 or if provided quality scores
1768      *                                  length is smaller than 7 samples.
1769      */
1770     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1771             final double[] qualityScores, final ECEFPosition position,
1772             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
1773             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1774         super(position, measurements, hardIron, listener);
1775         internalSetQualityScores(qualityScores);
1776     }
1777 
1778     /**
1779      * Constructor.
1780      *
1781      * @param qualityScores  quality scores corresponding to each provided
1782      *                       measurement. The larger the score value the better
1783      *                       the quality of the sample.
1784      * @param position       position where body magnetic flux density measurements
1785      *                       have been taken.
1786      * @param measurements   collection of body magnetic flux density
1787      *                       measurements with standard deviation of
1788      *                       magnetometer measurements taken at the same
1789      *                       position with zero velocity and unknown different
1790      *                       orientations.
1791      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1792      *                       for the accelerometer, gyroscope and magnetometer.
1793      * @param hardIron       known hard-iron.
1794      * @throws IllegalArgumentException if provided hard-iron matrix is not
1795      *                                  3x1 or if provided quality scores
1796      *                                  length is smaller than 7 samples.
1797      */
1798     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1799             final double[] qualityScores, final ECEFPosition position,
1800             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
1801             final Matrix hardIron) {
1802         super(position, measurements, commonAxisUsed, hardIron);
1803         internalSetQualityScores(qualityScores);
1804     }
1805 
1806     /**
1807      * Constructor.
1808      *
1809      * @param qualityScores  quality scores corresponding to each provided
1810      *                       measurement. The larger the score value the better
1811      *                       the quality of the sample.
1812      * @param position       position where body magnetic flux density measurements
1813      *                       have been taken.
1814      * @param measurements   collection of body magnetic flux density
1815      *                       measurements with standard deviation of
1816      *                       magnetometer measurements taken at the same
1817      *                       position with zero velocity and unknown different
1818      *                       orientations.
1819      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1820      *                       for the accelerometer, gyroscope and magnetometer.
1821      * @param hardIron       known hard-iron.
1822      * @param listener       listener to handle events raised by this calibrator.
1823      * @throws IllegalArgumentException if provided hard-iron matrix is not
1824      *                                  3x1 or if provided quality scores
1825      *                                  length is smaller than 7 samples.
1826      */
1827     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1828             final double[] qualityScores, final ECEFPosition position,
1829             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
1830             final Matrix hardIron, final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1831         super(position, measurements, commonAxisUsed, hardIron, listener);
1832         internalSetQualityScores(qualityScores);
1833     }
1834 
1835     /**
1836      * Constructor.
1837      *
1838      * @param qualityScores quality scores corresponding to each provided
1839      *                      measurement. The larger the score value the better
1840      *                      the quality of the sample.
1841      * @param position      position where body magnetic flux density measurements
1842      *                      have been taken.
1843      * @param measurements  collection of body magnetic flux density
1844      *                      measurements with standard deviation of
1845      *                      magnetometer measurements taken at the same
1846      *                      position with zero velocity and unknown different
1847      *                      orientations.
1848      * @param hardIron      known hard-iron.
1849      * @param initialMm     initial soft-iron matrix containing scale factors
1850      *                      and cross coupling errors.
1851      * @throws IllegalArgumentException if provided hard-iron matrix is not
1852      *                                  3x1 or if soft-iron matrix is not
1853      *                                  3x3 or if provided quality scores
1854      *                                  length is smaller than 7 samples.
1855      */
1856     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1857             final double[] qualityScores, final ECEFPosition position,
1858             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
1859             final Matrix initialMm) {
1860         super(position, measurements, hardIron, initialMm);
1861         internalSetQualityScores(qualityScores);
1862     }
1863 
1864     /**
1865      * Constructor.
1866      *
1867      * @param qualityScores quality scores corresponding to each provided
1868      *                      measurement. The larger the score value the better
1869      *                      the quality of the sample.
1870      * @param position      position where body magnetic flux density measurements
1871      *                      have been taken.
1872      * @param measurements  collection of body magnetic flux density
1873      *                      measurements with standard deviation of
1874      *                      magnetometer measurements taken at the same
1875      *                      position with zero velocity and unknown different
1876      *                      orientations.
1877      * @param hardIron      known hard-iron.
1878      * @param initialMm     initial soft-iron matrix containing scale factors
1879      *                      and cross coupling errors.
1880      * @param listener      listener to handle events raised by this calibrator.
1881      * @throws IllegalArgumentException if provided hard-iron matrix is not
1882      *                                  3x1 or if soft-iron matrix is not
1883      *                                  3x3 or if provided quality scores
1884      *                                  length is smaller than 7 samples.
1885      */
1886     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1887             final double[] qualityScores, final ECEFPosition position,
1888             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final Matrix hardIron,
1889             final Matrix initialMm,
1890             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1891         super(position, measurements, hardIron, initialMm, listener);
1892         internalSetQualityScores(qualityScores);
1893     }
1894 
1895     /**
1896      * Constructor.
1897      *
1898      * @param qualityScores  quality scores corresponding to each provided
1899      *                       measurement. The larger the score value the better
1900      *                       the quality of the sample.
1901      * @param position       position where body magnetic flux density measurements
1902      *                       have been taken.
1903      * @param measurements   collection of body magnetic flux density
1904      *                       measurements with standard deviation of
1905      *                       magnetometer measurements taken at the same
1906      *                       position with zero velocity and unknown different
1907      *                       orientations.
1908      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1909      *                       for the accelerometer, gyroscope and magnetometer.
1910      * @param hardIron       known hard-iron.
1911      * @param initialMm      initial soft-iron matrix containing scale factors
1912      *                       and cross coupling errors.
1913      * @throws IllegalArgumentException if provided hard-iron matrix is not
1914      *                                  3x1 or if soft-iron matrix is not
1915      *                                  3x3 or if provided quality scores
1916      *                                  length is smaller than 7 samples.
1917      */
1918     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1919             final double[] qualityScores, final ECEFPosition position,
1920             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
1921             final Matrix hardIron, final Matrix initialMm) {
1922         super(position, measurements, commonAxisUsed, hardIron, initialMm);
1923         internalSetQualityScores(qualityScores);
1924     }
1925 
1926     /**
1927      * Constructor.
1928      *
1929      * @param qualityScores  quality scores corresponding to each provided
1930      *                       measurement. The larger the score value the better
1931      *                       the quality of the sample.
1932      * @param position       position where body magnetic flux density measurements
1933      *                       have been taken.
1934      * @param measurements   collection of body magnetic flux density
1935      *                       measurements with standard deviation of
1936      *                       magnetometer measurements taken at the same
1937      *                       position with zero velocity and unknown different
1938      *                       orientations.
1939      * @param commonAxisUsed indicates whether z-axis is assumed to be common
1940      *                       for the accelerometer, gyroscope and magnetometer.
1941      * @param hardIron       known hard-iron.
1942      * @param initialMm      initial soft-iron matrix containing scale factors
1943      *                       and cross coupling errors.
1944      * @param listener       listener to handle events raised by this calibrator.
1945      * @throws IllegalArgumentException if provided hard-iron matrix is not
1946      *                                  3x1 or if soft-iron matrix is not
1947      *                                  3x3 or if provided quality scores
1948      *                                  length is smaller than 7 samples.
1949      */
1950     public PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator(
1951             final double[] qualityScores, final ECEFPosition position,
1952             final List<StandardDeviationBodyMagneticFluxDensity> measurements, final boolean commonAxisUsed,
1953             final Matrix hardIron, final Matrix initialMm,
1954             final RobustKnownHardIronPositionAndInstantMagnetometerCalibratorListener listener) {
1955         super(position, measurements, commonAxisUsed, hardIron, initialMm, listener);
1956         internalSetQualityScores(qualityScores);
1957     }
1958 
1959     /**
1960      * Returns threshold to be used to keep the algorithm iterating in case that
1961      * best estimated threshold using median of residuals is not small enough.
1962      * Once a solution is found that generates a threshold below this value, the
1963      * algorithm will stop.
1964      * The stop threshold can be used to prevent the LMedS algorithm to iterate
1965      * too many times in cases where samples have a very similar accuracy.
1966      * For instance, in cases where proportion of outliers is very small (close
1967      * to 0%), and samples are very accurate (i.e. 1e-6), the algorithm would
1968      * iterate for a long time trying to find the best solution when indeed
1969      * there is no need to do that if a reasonable threshold has already been
1970      * reached.
1971      * Because of this behaviour the stop threshold can be set to a value much
1972      * lower than the one typically used in RANSAC, and yet the algorithm could
1973      * still produce even smaller thresholds in estimated results.
1974      *
1975      * @return stop threshold to stop the algorithm prematurely when a certain
1976      * accuracy has been reached.
1977      */
1978     public double getStopThreshold() {
1979         return stopThreshold;
1980     }
1981 
1982     /**
1983      * Sets threshold to be used to keep the algorithm iterating in case that
1984      * best estimated threshold using median of residuals is not small enough.
1985      * Once a solution is found that generates a threshold below this value,
1986      * the algorithm will stop.
1987      * The stop threshold can be used to prevent the LMedS algorithm to iterate
1988      * too many times in cases where samples have a very similar accuracy.
1989      * For instance, in cases where proportion of outliers is very small (close
1990      * to 0%), and samples are very accurate (i.e. 1e-6), the algorithm would
1991      * iterate for a long time trying to find the best solution when indeed
1992      * there is no need to do that if a reasonable threshold has already been
1993      * reached.
1994      * Because of this behaviour the stop threshold can be set to a value much
1995      * lower than the one typically used in RANSAC, and yet the algorithm could
1996      * still produce even smaller thresholds in estimated results.
1997      *
1998      * @param stopThreshold stop threshold to stop the algorithm prematurely
1999      *                      when a certain accuracy has been reached.
2000      * @throws IllegalArgumentException if provided value is zero or negative.
2001      * @throws LockedException          if calibrator is currently running.
2002      */
2003     public void setStopThreshold(final double stopThreshold) throws LockedException {
2004         if (running) {
2005             throw new LockedException();
2006         }
2007         if (stopThreshold <= MIN_STOP_THRESHOLD) {
2008             throw new IllegalArgumentException();
2009         }
2010 
2011         this.stopThreshold = stopThreshold;
2012     }
2013 
2014     /**
2015      * Returns quality scores corresponding to each provided sample.
2016      * The larger the score value the better the quality of the sample.
2017      *
2018      * @return quality scores corresponding to each sample.
2019      */
2020     @Override
2021     public double[] getQualityScores() {
2022         return qualityScores;
2023     }
2024 
2025     /**
2026      * Sets quality scores corresponding to each provided sample.
2027      * The larger the score value the better the quality of the sample.
2028      *
2029      * @param qualityScores quality scores corresponding to each sample.
2030      * @throws IllegalArgumentException if provided quality scores length
2031      *                                  is smaller than minimum required samples.
2032      * @throws LockedException          if calibrator is currently running.
2033      */
2034     @Override
2035     public void setQualityScores(final double[] qualityScores) throws LockedException {
2036         if (running) {
2037             throw new LockedException();
2038         }
2039         internalSetQualityScores(qualityScores);
2040     }
2041 
2042     /**
2043      * Indicates whether solver is ready to find a solution.
2044      *
2045      * @return true if solver is ready, false otherwise.
2046      */
2047     @Override
2048     public boolean isReady() {
2049         return super.isReady() && qualityScores != null && qualityScores.length == measurements.size();
2050     }
2051 
2052     /**
2053      * Estimates magnetometer calibration parameters containing soft-iron
2054      * scale factors and cross-coupling errors.
2055      *
2056      * @throws LockedException      if calibrator is currently running.
2057      * @throws NotReadyException    if calibrator is not ready.
2058      * @throws CalibrationException if estimation fails for numerical reasons.
2059      */
2060     @Override
2061     public void calibrate() throws LockedException, NotReadyException, CalibrationException {
2062         if (running) {
2063             throw new LockedException();
2064         }
2065         if (!isReady()) {
2066             throw new NotReadyException();
2067         }
2068 
2069         final var innerEstimator = new PROMedSRobustEstimator<>(new PROMedSRobustEstimatorListener<Matrix>() {
2070                     @Override
2071                     public double[] getQualityScores() {
2072                         return qualityScores;
2073                     }
2074 
2075                     @Override
2076                     public double getThreshold() {
2077                         return stopThreshold;
2078                     }
2079 
2080                     @Override
2081                     public int getTotalSamples() {
2082                         return measurements.size();
2083                     }
2084 
2085                     @Override
2086                     public int getSubsetSize() {
2087                         return preliminarySubsetSize;
2088                     }
2089 
2090                     @Override
2091                     public void estimatePreliminarSolutions(final int[] samplesIndices, final List<Matrix> solutions) {
2092                         computePreliminarySolutions(samplesIndices, solutions);
2093                     }
2094 
2095                     @Override
2096                     public double computeResidual(final Matrix currentEstimation, final int i) {
2097                         return computeError(measurements.get(i), currentEstimation);
2098                     }
2099 
2100                     @Override
2101                     public boolean isReady() {
2102                         return PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator.this.isReady();
2103                     }
2104 
2105                     @Override
2106                     public void onEstimateStart(final RobustEstimator<Matrix> estimator) {
2107                         // no action needed
2108                     }
2109 
2110                     @Override
2111                     public void onEstimateEnd(final RobustEstimator<Matrix> estimator) {
2112                         // no action needed
2113                     }
2114 
2115                     @Override
2116                     public void onEstimateNextIteration(final RobustEstimator<Matrix> estimator, int iteration) {
2117                         if (listener != null) {
2118                             listener.onCalibrateNextIteration(
2119                                     PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator.this,
2120                                     iteration);
2121                         }
2122                     }
2123 
2124                     @Override
2125                     public void onEstimateProgressChange(
2126                             final RobustEstimator<Matrix> estimator, final float progress) {
2127                         if (listener != null) {
2128                             listener.onCalibrateProgressChange(
2129                                     PROMedSRobustKnownHardIronPositionAndInstantMagnetometerCalibrator.this,
2130                                     progress);
2131                         }
2132                     }
2133                 });
2134 
2135         try {
2136             running = true;
2137 
2138             if (listener != null) {
2139                 listener.onCalibrateStart(this);
2140             }
2141 
2142             inliersData = null;
2143 
2144             initialize();
2145 
2146             innerEstimator.setUseInlierThresholds(true);
2147             innerEstimator.setConfidence(confidence);
2148             innerEstimator.setMaxIterations(maxIterations);
2149             innerEstimator.setProgressDelta(progressDelta);
2150             final var preliminaryResult = innerEstimator.estimate();
2151             inliersData = innerEstimator.getInliersData();
2152 
2153             attemptRefine(preliminaryResult);
2154 
2155             if (listener != null) {
2156                 listener.onCalibrateEnd(this);
2157             }
2158 
2159         } catch (final com.irurueta.numerical.LockedException e) {
2160             throw new LockedException(e);
2161         } catch (final com.irurueta.numerical.NotReadyException e) {
2162             throw new NotReadyException(e);
2163         } catch (final RobustEstimatorException | IOException e) {
2164             throw new CalibrationException(e);
2165         } finally {
2166             running = false;
2167         }
2168     }
2169 
2170     /**
2171      * Returns method being used for robust estimation.
2172      *
2173      * @return method being used for robust estimation.
2174      */
2175     @Override
2176     public RobustEstimatorMethod getMethod() {
2177         return RobustEstimatorMethod.PROMEDS;
2178     }
2179 
2180     /**
2181      * Indicates whether this calibrator requires quality scores for each
2182      * measurement or not.
2183      *
2184      * @return true if quality scores are required, false otherwise.
2185      */
2186     @Override
2187     public boolean isQualityScoresRequired() {
2188         return true;
2189     }
2190 
2191     /**
2192      * Sets quality scores corresponding to each provided sample.
2193      * This method is used internally and does not check whether instance is
2194      * locked or not.
2195      *
2196      * @param qualityScores quality scores to be set.
2197      * @throws IllegalArgumentException if provided quality scores length
2198      *                                  is smaller than 4 samples.
2199      */
2200     private void internalSetQualityScores(final double[] qualityScores) {
2201         if (qualityScores == null || qualityScores.length < MINIMUM_MEASUREMENTS_COMMON_Z_AXIS) {
2202             throw new IllegalArgumentException();
2203         }
2204 
2205         this.qualityScores = qualityScores;
2206     }
2207 }