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