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