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.Matrix;
20  import com.irurueta.algebra.WrongSizeException;
21  import com.irurueta.navigation.LockedException;
22  import com.irurueta.navigation.NotReadyException;
23  import com.irurueta.navigation.inertial.BodyKinematics;
24  import com.irurueta.navigation.inertial.calibration.AngularSpeedTriad;
25  import com.irurueta.navigation.inertial.calibration.CalibrationException;
26  import com.irurueta.navigation.inertial.calibration.StandardDeviationFrameBodyKinematics;
27  import com.irurueta.navigation.inertial.estimators.ECEFKinematicsEstimator;
28  import com.irurueta.numerical.fitting.FittingException;
29  import com.irurueta.numerical.fitting.LevenbergMarquardtMultiVariateFitter;
30  import com.irurueta.numerical.fitting.LevenbergMarquardtMultiVariateFunctionEvaluator;
31  import com.irurueta.statistics.MaxIterationsExceededException;
32  import com.irurueta.units.AngularSpeed;
33  import com.irurueta.units.AngularSpeedConverter;
34  import com.irurueta.units.AngularSpeedUnit;
35  
36  import java.util.Collection;
37  
38  /**
39   * Estimates gyroscope cross couplings and scaling factors
40   * along with G-dependent cross biases introduced on the gyroscope by the
41   * specific forces sensed by the accelerometer.
42   * <p>
43   * This calibrator uses an iterative approach to find a minimum least squared error
44   * solution.
45   * <p>
46   * To use this calibrator at least 6 measurements at different known frames must
47   * be provided. In other words, accelerometer and gyroscope (i.e. body kinematics)
48   * samples must be obtained at 6 different positions, orientations and velocities
49   * (although typically velocities are always zero).
50   * <p>
51   * Measured gyroscope angular rates is assumed to follow the model shown below:
52   * <pre>
53   *     Ωmeas = bg + (I + Mg) * Ωtrue + Gg * ftrue + w
54   * </pre>
55   * Where:
56   * - Ωmeas is the measured gyroscope angular rates. This is a 3x1 vector.
57   * - bg is the gyroscope bias. Ideally, on a perfect gyroscope, this should be a
58   * 3x1 zero vector.
59   * - I is the 3x3 identity matrix.
60   * - Mg is the 3x3 matrix containing cross-couplings and scaling factors. Ideally, on
61   * a perfect gyroscope, this should be a 3x3 zero matrix.
62   * - Ωtrue is ground-truth gyroscope angular rates.
63   * - Gg is the G-dependent cross biases introduced by the specific forces sensed
64   * by the accelerometer. Ideally, on a perfect gyroscope, this should be a 3x3
65   * zero matrix.
66   * - ftrue is ground-truth specific force. This is a 3x1 vector.
67   * - w is measurement noise. This is a 3x1 vector.
68   */
69  public class KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator implements
70          KnownBiasAndFrameGyroscopeCalibrator<StandardDeviationFrameBodyKinematics,
71                  KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener>, GyroscopeNonLinearCalibrator,
72          UnorderedStandardDeviationFrameBodyKinematicsGyroscopeCalibrator {
73  
74      /**
75       * Indicates whether by default a common z-axis is assumed for both the accelerometer
76       * and gyroscope.
77       */
78      public static final boolean DEFAULT_USE_COMMON_Z_AXIS = false;
79  
80      /**
81       * Required minimum number of measurements.
82       */
83      public static final int MINIMUM_MEASUREMENTS = 6;
84  
85      /**
86       * Number of unknowns when common z-axis is assumed for both the accelerometer
87       * and gyroscope.
88       */
89      private static final int COMMON_Z_AXIS_UNKNOWNS = 15;
90  
91      /**
92       * Number of unknowns for the general case.
93       */
94      private static final int GENERAL_UNKNOWNS = 18;
95  
96      /**
97       * Levenberg-Marquardt fitter to find a non-linear solution.
98       */
99      private final LevenbergMarquardtMultiVariateFitter fitter = new LevenbergMarquardtMultiVariateFitter();
100 
101     /**
102      * Initial x scaling factor.
103      */
104     private double initialSx;
105 
106     /**
107      * Initial y scaling factor.
108      */
109     private double initialSy;
110 
111     /**
112      * Initial z scaling factor.
113      */
114     private double initialSz;
115 
116     /**
117      * Initial x-y cross coupling error.
118      */
119     private double initialMxy;
120 
121     /**
122      * Initial x-z cross coupling error.
123      */
124     private double initialMxz;
125 
126     /**
127      * Initial y-x cross coupling error.
128      */
129     private double initialMyx;
130 
131     /**
132      * Initial y-z cross coupling error.
133      */
134     private double initialMyz;
135 
136     /**
137      * Initial z-x cross coupling error.
138      */
139     private double initialMzx;
140 
141     /**
142      * Initial z-y cross coupling error.
143      */
144     private double initialMzy;
145 
146     /**
147      * Initial G-dependent cross biases introduced on the gyroscope by the
148      * specific forces sensed by the accelerometer.
149      */
150     private Matrix initialGg;
151 
152     /**
153      * Contains a collections of body kinematics measurements taken at different
154      * frames (positions, orientations and velocities) and containing the standard
155      * deviations of accelerometer and gyroscope measurements.
156      * If a single device IMU needs to be calibrated, typically all measurements are
157      * taken at the same position, with zero velocity and multiple orientations.
158      * However, if we just want to calibrate a given IMU model (e.g. obtain
159      * an average and less precise calibration for the IMU of a given phone model),
160      * we could take measurements collected throughout the planet at multiple positions
161      * while the phone remains static (e.g. while charging), hence each measurement
162      * position will change, velocity will remain zero and orientation will be
163      * typically constant at horizontal orientation while the phone remains on a
164      * flat surface.
165      */
166     private Collection<StandardDeviationFrameBodyKinematics> measurements;
167 
168     /**
169      * This flag indicates whether z-axis is assumed to be common for accelerometer
170      * and gyroscope.
171      * When enabled, this eliminates 3 variables from Ma matrix.
172      */
173     private boolean commonAxisUsed = DEFAULT_USE_COMMON_Z_AXIS;
174 
175     /**
176      * Listener to handle events raised by this calibrator.
177      */
178     private KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener;
179 
180     /**
181      * Known x coordinate of gyroscope bias expressed in radians per second (rad/s).
182      */
183     private double biasX;
184 
185     /**
186      * Known y coordinate of gyroscope bias expressed in radians per second (rad/s).
187      */
188     private double biasY;
189 
190     /**
191      * Known z coordinate of gyroscope bias expressed in radians per second (rad/s).
192      */
193     private double biasZ;
194 
195     /**
196      * Estimated gyroscope scale factors and cross coupling errors.
197      * This is the product of matrix Tg containing cross coupling errors and Kg
198      * containing scaling factors.
199      * So that:
200      * <pre>
201      *     Mg = [sx    mxy  mxz] = Tg*Kg
202      *          [myx   sy   myz]
203      *          [mzx   mzy  sz ]
204      * </pre>
205      * Where:
206      * <pre>
207      *     Kg = [sx 0   0 ]
208      *          [0  sy  0 ]
209      *          [0  0   sz]
210      * </pre>
211      * and
212      * <pre>
213      *     Tg = [1          -alphaXy    alphaXz ]
214      *          [alphaYx    1           -alphaYz]
215      *          [-alphaZx   alphaZy     1       ]
216      * </pre>
217      * Hence:
218      * <pre>
219      *     Mg = [sx    mxy  mxz] = Tg*Kg =  [sx             -sy * alphaXy   sz * alphaXz ]
220      *          [myx   sy   myz]            [sx * alphaYx   sy              -sz * alphaYz]
221      *          [mzx   mzy  sz ]            [-sx * alphaZx  sy * alphaZy    sz           ]
222      * </pre>
223      * This instance allows any 3x3 matrix however, typically alphaYx, alphaZx and alphaZy
224      * are considered to be zero if the gyroscope z-axis is assumed to be the same
225      * as the body z-axis. When this is assumed, myx = mzx = mzy = 0 and the Mg matrix
226      * becomes upper diagonal:
227      * <pre>
228      *     Mg = [sx    mxy  mxz]
229      *          [0     sy   myz]
230      *          [0     0    sz ]
231      * </pre>
232      * Values of this matrix are unit-less.
233      */
234     private Matrix estimatedMg;
235 
236     /**
237      * Estimated G-dependent cross biases introduced on the gyroscope by the
238      * specific forces sensed by the accelerometer.
239      * This instance allows any 3x3 matrix.
240      */
241     private Matrix estimatedGg;
242 
243     /**
244      * Estimated covariance matrix for estimated position.
245      */
246     private Matrix estimatedCovariance;
247 
248     /**
249      * Estimated chi square value.
250      */
251     private double estimatedChiSq;
252 
253     /**
254      * Estimated degrees of freedom of chi square value. Degrees of freedom is equal to the number of sampled data
255      * minus the number of estimated parameters.
256      */
257     private int estimatedChiSqDegreesOfFreedom;
258 
259     /**
260      * Estimated reduced chi square value. This is equal to estimated chi square value divided by its degrees of
261      * freedom. Ideally this value should be close to 1.0.
262      */
263     private double estimatedReducedChiSq;
264 
265     /**
266      * Estimated mean square error respect to provided measurements.
267      */
268     private double estimatedMse;
269 
270     /**
271      * Estimated probability of finding a smaller chi square value expressed as a value between 0.0 and 1.0. The smaller
272      * the found chi square value is, the better the fit of the estimated parameters to the actual parameter. Thus, the
273      * smaller the chance of finding a smaller chi square value, then the better the estimated fit is.
274      */
275     private double estimatedP;
276 
277     /**
278      * Estimated measure of quality of estimated fit as a value between 0.0 and 1.0. The larger the quality value is,
279      * the better the fit that has been estimated.
280      */
281     private double estimatedQ;
282 
283     /**
284      * Indicates whether calibrator is running.
285      */
286     private boolean running;
287 
288     /**
289      * Constructor.
290      */
291     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator() {
292         try {
293             initialGg = new Matrix(BodyKinematics.COMPONENTS, BodyKinematics.COMPONENTS);
294         } catch (final WrongSizeException ignore) {
295             // never happens
296         }
297     }
298 
299     /**
300      * Constructor.
301      *
302      * @param listener listener to handle events raised by this calibrator.
303      */
304     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
305             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
306         this();
307         this.listener = listener;
308     }
309 
310     /**
311      * Constructor.
312      *
313      * @param measurements collection of body kinematics measurements with standard
314      *                     deviations taken at different frames (positions, orientations
315      *                     and velocities).
316      */
317     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
318             final Collection<StandardDeviationFrameBodyKinematics> measurements) {
319         this();
320         this.measurements = measurements;
321     }
322 
323     /**
324      * Constructor.
325      *
326      * @param measurements collection of body kinematics measurements with standard
327      *                     deviations taken at different frames (positions, orientations
328      *                     and velocities).
329      * @param listener     listener to handle events raised by this calibrator.
330      */
331     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
332             final Collection<StandardDeviationFrameBodyKinematics> measurements,
333             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
334         this(measurements);
335         this.listener = listener;
336     }
337 
338     /**
339      * Constructor.
340      *
341      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
342      *                       accelerometer and gyroscope.
343      */
344     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(final boolean commonAxisUsed) {
345         this();
346         this.commonAxisUsed = commonAxisUsed;
347     }
348 
349     /**
350      * Constructor.
351      *
352      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
353      *                       accelerometer and gyroscope.
354      * @param listener       listener to handle events raised by this calibrator.
355      */
356     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
357             final boolean commonAxisUsed,
358             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
359         this(commonAxisUsed);
360         this.listener = listener;
361     }
362 
363     /**
364      * Constructor.
365      *
366      * @param measurements   collection of body kinematics measurements with standard
367      *                       deviations taken at different frames (positions, orientations
368      *                       and velocities).
369      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
370      *                       accelerometer and gyroscope.
371      */
372     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
373             final Collection<StandardDeviationFrameBodyKinematics> measurements, final boolean commonAxisUsed) {
374         this(measurements);
375         this.commonAxisUsed = commonAxisUsed;
376     }
377 
378     /**
379      * Constructor.
380      *
381      * @param measurements   collection of body kinematics measurements with standard
382      *                       deviations taken at different frames (positions, orientations
383      *                       and velocities).
384      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
385      *                       accelerometer and gyroscope.
386      * @param listener       listener to handle events raised by this calibrator.
387      */
388     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
389             final Collection<StandardDeviationFrameBodyKinematics> measurements, final boolean commonAxisUsed,
390             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
391         this(measurements, commonAxisUsed);
392         this.listener = listener;
393     }
394 
395     /**
396      * Constructor.
397      *
398      * @param biasX known x coordinate of gyroscope bias expressed in radians per second
399      *              (rad/s).
400      * @param biasY known y coordinate of gyroscope bias expressed in radians per second
401      *              (rad/s).
402      * @param biasZ known z coordinate of gyroscope bias expressed in radians per second
403      *              (rad/s).
404      */
405     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
406             final double biasX, final double biasY, final double biasZ) {
407         this();
408         try {
409             setBiasCoordinates(biasX, biasY, biasZ);
410         } catch (final LockedException ignore) {
411             // never happens
412         }
413     }
414 
415     /**
416      * Constructor.
417      *
418      * @param biasX    known x coordinate of gyroscope bias expressed in radians per second
419      *                 (rad/s).
420      * @param biasY    known y coordinate of gyroscope bias expressed in radians per second
421      *                 (rad/s).
422      * @param biasZ    known z coordinate of gyroscope bias expressed in radians per second
423      *                 (rad/s).
424      * @param listener listener to handle events raised by this calibrator.
425      */
426     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
427             final double biasX, final double biasY, final double biasZ,
428             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
429         this(biasX, biasY, biasZ);
430         this.listener = listener;
431     }
432 
433     /**
434      * Constructor.
435      *
436      * @param measurements collection of body kinematics measurements with standard
437      *                     deviations taken at different frames (positions, orientations
438      *                     and velocities).
439      * @param biasX        known x coordinate of gyroscope bias expressed in radians per second
440      *                     (rad/s).
441      * @param biasY        known y coordinate of gyroscope bias expressed in radians per second
442      *                     (rad/s).
443      * @param biasZ        known z coordinate of gyroscope bias expressed in radians per second
444      *                     (rad/s).
445      */
446     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
447             final Collection<StandardDeviationFrameBodyKinematics> measurements,
448             final double biasX, final double biasY, final double biasZ) {
449         this(biasX, biasY, biasZ);
450         this.measurements = measurements;
451     }
452 
453     /**
454      * Constructor.
455      *
456      * @param measurements collection of body kinematics measurements with standard
457      *                     deviations taken at different frames (positions, orientations
458      *                     and velocities).
459      * @param biasX        known x coordinate of gyroscope bias expressed in radians per second
460      *                     (rad/s).
461      * @param biasY        known y coordinate of gyroscope bias expressed in radians per second
462      *                     (rad/s).
463      * @param biasZ        known z coordinate of gyroscope bias expressed in radians per second
464      *                     (rad/s).
465      * @param listener     listener to handle events raised by this calibrator.
466      */
467     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
468             final Collection<StandardDeviationFrameBodyKinematics> measurements,
469             final double biasX, final double biasY, final double biasZ,
470             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
471         this(measurements, biasX, biasY, biasZ);
472         this.listener = listener;
473     }
474 
475     /**
476      * Constructor.
477      *
478      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
479      *                       accelerometer and gyroscope.
480      * @param biasX          known x coordinate of gyroscope bias expressed in radians per second
481      *                       (rad/s).
482      * @param biasY          known y coordinate of gyroscope bias expressed in radians per second
483      *                       (rad/s).
484      * @param biasZ          known z coordinate of gyroscope bias expressed in radians per second
485      *                       (rad/s).
486      */
487     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
488             final boolean commonAxisUsed, final double biasX, final double biasY, final double biasZ) {
489         this(biasX, biasY, biasZ);
490         this.commonAxisUsed = commonAxisUsed;
491     }
492 
493     /**
494      * Constructor.
495      *
496      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
497      *                       accelerometer and gyroscope.
498      * @param biasX          known x coordinate of gyroscope bias expressed in radians per second
499      *                       (rad/s).
500      * @param biasY          known y coordinate of gyroscope bias expressed in radians per second
501      *                       (rad/s).
502      * @param biasZ          known z coordinate of gyroscope bias expressed in radians per second
503      *                       (rad/s).
504      * @param listener       listener to handle events raised by this calibrator.
505      */
506     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
507             final boolean commonAxisUsed, final double biasX, final double biasY, final double biasZ,
508             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
509         this(commonAxisUsed, biasX, biasY, biasZ);
510         this.listener = listener;
511     }
512 
513     /**
514      * Constructor.
515      *
516      * @param measurements   collection of body kinematics measurements with standard
517      *                       deviations taken at different frames (positions, orientations
518      *                       and velocities).
519      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
520      *                       accelerometer and gyroscope.
521      * @param biasX          known x coordinate of gyroscope bias expressed in radians per second
522      *                       (rad/s).
523      * @param biasY          known y coordinate of gyroscope bias expressed in radians per second
524      *                       (rad/s).
525      * @param biasZ          known z coordinate of gyroscope bias expressed in radians per second
526      *                       (rad/s).
527      */
528     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
529             final Collection<StandardDeviationFrameBodyKinematics> measurements,
530             final boolean commonAxisUsed, final double biasX, final double biasY, final double biasZ) {
531         this(commonAxisUsed, biasX, biasY, biasZ);
532         this.measurements = measurements;
533     }
534 
535     /**
536      * Constructor.
537      *
538      * @param measurements   collection of body kinematics measurements with standard
539      *                       deviations taken at different frames (positions, orientations
540      *                       and velocities).
541      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
542      *                       accelerometer and gyroscope.
543      * @param biasX          known x coordinate of gyroscope bias expressed in radians per second
544      *                       (rad/s).
545      * @param biasY          known y coordinate of gyroscope bias expressed in radians per second
546      *                       (rad/s).
547      * @param biasZ          known z coordinate of gyroscope bias expressed in radians per second
548      *                       (rad/s).
549      * @param listener       listener to handle events raised by this calibrator.
550      */
551     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
552             final Collection<StandardDeviationFrameBodyKinematics> measurements,
553             final boolean commonAxisUsed, final double biasX, final double biasY, final double biasZ,
554             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
555         this(measurements, commonAxisUsed, biasX, biasY, biasZ);
556         this.listener = listener;
557     }
558 
559     /**
560      * Constructor.
561      *
562      * @param biasX known x coordinate of gyroscope bias.
563      * @param biasY known y coordinate of gyroscope bias.
564      * @param biasZ known z coordinate of gyroscope bias.
565      */
566     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
567             final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ) {
568         this();
569         try {
570             setBiasCoordinates(biasX, biasY, biasZ);
571         } catch (final LockedException ignore) {
572             // never happens
573         }
574     }
575 
576     /**
577      * Constructor.
578      *
579      * @param biasX    known x coordinate of gyroscope bias.
580      * @param biasY    known y coordinate of gyroscope bias.
581      * @param biasZ    known z coordinate of gyroscope bias.
582      * @param listener listener to handle events raised by this calibrator.
583      */
584     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
585             final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
586             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
587         this(biasX, biasY, biasZ);
588         this.listener = listener;
589     }
590 
591     /**
592      * Constructor.
593      *
594      * @param measurements collection of body kinematics measurements with standard
595      *                     deviations taken at different frames (positions, orientations
596      *                     and velocities).
597      * @param biasX        known x coordinate of gyroscope bias.
598      * @param biasY        known y coordinate of gyroscope bias.
599      * @param biasZ        known z coordinate of gyroscope bias.
600      */
601     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
602             final Collection<StandardDeviationFrameBodyKinematics> measurements,
603             final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ) {
604         this(biasX, biasY, biasZ);
605         this.measurements = measurements;
606     }
607 
608     /**
609      * Constructor.
610      *
611      * @param measurements collection of body kinematics measurements with standard
612      *                     deviations taken at different frames (positions, orientations
613      *                     and velocities).
614      * @param biasX        known x coordinate of gyroscope bias.
615      * @param biasY        known y coordinate of gyroscope bias.
616      * @param biasZ        known z coordinate of gyroscope bias.
617      * @param listener     listener to handle events raised by this calibrator.
618      */
619     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
620             final Collection<StandardDeviationFrameBodyKinematics> measurements,
621             final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
622             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
623         this(measurements, biasX, biasY, biasZ);
624         this.listener = listener;
625     }
626 
627     /**
628      * Constructor.
629      *
630      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
631      *                       accelerometer and gyroscope.
632      * @param biasX          known x coordinate of gyroscope bias.
633      * @param biasY          known y coordinate of gyroscope bias.
634      * @param biasZ          known z coordinate of gyroscope bias.
635      */
636     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
637             final boolean commonAxisUsed, final AngularSpeed biasX, final AngularSpeed biasY,
638             final AngularSpeed biasZ) {
639         this(biasX, biasY, biasZ);
640         this.commonAxisUsed = commonAxisUsed;
641     }
642 
643     /**
644      * Constructor.
645      *
646      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
647      *                       accelerometer and gyroscope.
648      * @param biasX          known x coordinate of gyroscope bias.
649      * @param biasY          known y coordinate of gyroscope bias.
650      * @param biasZ          known z coordinate of gyroscope bias.
651      * @param listener       listener to handle events raised by this calibrator.
652      */
653     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
654             final boolean commonAxisUsed, final AngularSpeed biasX, final AngularSpeed biasY,
655             final AngularSpeed biasZ,
656             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
657         this(commonAxisUsed, biasX, biasY, biasZ);
658         this.listener = listener;
659     }
660 
661     /**
662      * Constructor.
663      *
664      * @param measurements   collection of body kinematics measurements with standard
665      *                       deviations taken at different frames (positions, orientations
666      *                       and velocities).
667      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
668      *                       accelerometer and gyroscope.
669      * @param biasX          known x coordinate of gyroscope bias.
670      * @param biasY          known y coordinate of gyroscope bias.
671      * @param biasZ          known z coordinate of gyroscope bias.
672      */
673     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
674             final Collection<StandardDeviationFrameBodyKinematics> measurements, final boolean commonAxisUsed,
675             final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ) {
676         this(commonAxisUsed, biasX, biasY, biasZ);
677         this.measurements = measurements;
678     }
679 
680     /**
681      * Constructor.
682      *
683      * @param measurements   collection of body kinematics measurements with standard
684      *                       deviations taken at different frames (positions, orientations
685      *                       and velocities).
686      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
687      *                       accelerometer and gyroscope.
688      * @param biasX          known x coordinate of gyroscope bias.
689      * @param biasY          known y coordinate of gyroscope bias.
690      * @param biasZ          known z coordinate of gyroscope bias.
691      * @param listener       listener to handle events raised by this calibrator.
692      */
693     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
694             final Collection<StandardDeviationFrameBodyKinematics> measurements, final boolean commonAxisUsed,
695             final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
696             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
697         this(measurements, commonAxisUsed, biasX, biasY, biasZ);
698         this.listener = listener;
699     }
700 
701     /**
702      * Constructor.
703      *
704      * @param biasX     known x coordinate of gyroscope bias expressed in radians per second
705      *                  (rad/s).
706      * @param biasY     known y coordinate of gyroscope bias expressed in radians per second
707      *                  (rad/s).
708      * @param biasZ     known z coordinate of gyroscope bias expressed in radians per second
709      *                  (rad/s).
710      * @param initialSx initial x scaling factor.
711      * @param initialSy initial y scaling factor.
712      * @param initialSz initial z scaling factor.
713      */
714     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
715             final double biasX, final double biasY, final double biasZ,
716             final double initialSx, final double initialSy, final double initialSz) {
717         this(biasX, biasY, biasZ);
718         try {
719             setInitialScalingFactors(initialSx, initialSy, initialSz);
720         } catch (final LockedException ignore) {
721             // never happens
722         }
723     }
724 
725     /**
726      * Constructor.
727      *
728      * @param measurements collection of body kinematics measurements with standard
729      *                     deviations taken at different frames (positions, orientations
730      *                     and velocities).
731      * @param biasX        known x coordinate of gyroscope bias expressed in radians per second
732      *                     (rad/s).
733      * @param biasY        known y coordinate of gyroscope bias expressed in radians per second
734      *                     (rad/s).
735      * @param biasZ        known z coordinate of gyroscope bias expressed in radians per second
736      *                     (rad/s).
737      * @param initialSx    initial x scaling factor.
738      * @param initialSy    initial y scaling factor.
739      * @param initialSz    initial z scaling factor.
740      */
741     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
742             final Collection<StandardDeviationFrameBodyKinematics> measurements,
743             final double biasX, final double biasY, final double biasZ,
744             final double initialSx, final double initialSy, final double initialSz) {
745         this(biasX, biasY, biasZ, initialSx, initialSy, initialSz);
746         this.measurements = measurements;
747     }
748 
749     /**
750      * Constructor.
751      *
752      * @param measurements collection of body kinematics measurements with standard
753      *                     deviations taken at different frames (positions, orientations
754      *                     and velocities).
755      * @param biasX        known x coordinate of gyroscope bias expressed in radians per second
756      *                     (rad/s).
757      * @param biasY        known y coordinate of gyroscope bias expressed in radians per second
758      *                     (rad/s).
759      * @param biasZ        known z coordinate of gyroscope bias expressed in radians per second
760      *                     (rad/s).
761      * @param initialSx    initial x scaling factor.
762      * @param initialSy    initial y scaling factor.
763      * @param initialSz    initial z scaling factor.
764      * @param listener     listener to handle events raised by this calibrator.
765      */
766     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
767             final Collection<StandardDeviationFrameBodyKinematics> measurements,
768             final double biasX, final double biasY, final double biasZ,
769             final double initialSx, final double initialSy, final double initialSz,
770             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
771         this(measurements, biasX, biasY, biasZ, initialSx, initialSy, initialSz);
772         this.listener = listener;
773     }
774 
775     /**
776      * Constructor.
777      *
778      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
779      *                       accelerometer and gyroscope.
780      * @param biasX          known x coordinate of gyroscope bias expressed in radians per second
781      *                       (rad/s).
782      * @param biasY          known y coordinate of gyroscope bias expressed in radians per second
783      *                       (rad/s).
784      * @param biasZ          known z coordinate of gyroscope bias expressed in radians per second
785      *                       (rad/s).
786      * @param initialSx      initial x scaling factor.
787      * @param initialSy      initial y scaling factor.
788      * @param initialSz      initial z scaling factor.
789      */
790     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
791             final boolean commonAxisUsed, final double biasX, final double biasY, final double biasZ,
792             final double initialSx, final double initialSy, final double initialSz) {
793         this(biasX, biasY, biasZ, initialSx, initialSy, initialSz);
794         this.commonAxisUsed = commonAxisUsed;
795     }
796 
797     /**
798      * Constructor.
799      *
800      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
801      *                       accelerometer and gyroscope.
802      * @param biasX          known x coordinate of gyroscope bias expressed in radians per second
803      *                       (rad/s).
804      * @param biasY          known y coordinate of gyroscope bias expressed in radians per second
805      *                       (rad/s).
806      * @param biasZ          known z coordinate of gyroscope bias expressed in radians per second
807      *                       (rad/s).
808      * @param initialSx      initial x scaling factor.
809      * @param initialSy      initial y scaling factor.
810      * @param initialSz      initial z scaling factor.
811      * @param listener       listener to handle events raised by this calibrator.
812      */
813     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
814             final boolean commonAxisUsed, final double biasX, final double biasY, final double biasZ,
815             final double initialSx, final double initialSy, final double initialSz,
816             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
817         this(commonAxisUsed, biasX, biasY, biasZ, initialSx, initialSy, initialSz);
818         this.listener = listener;
819     }
820 
821     /**
822      * Constructor.
823      *
824      * @param measurements   collection of body kinematics measurements with standard
825      *                       deviations taken at different frames (positions, orientations
826      *                       and velocities).
827      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
828      *                       accelerometer and gyroscope.
829      * @param biasX          known x coordinate of gyroscope bias expressed in radians per second
830      *                       (rad/s).
831      * @param biasY          known y coordinate of gyroscope bias expressed in radians per second
832      *                       (rad/s).
833      * @param biasZ          known z coordinate of gyroscope bias expressed in radians per second
834      *                       (rad/s).
835      * @param initialSx      initial x scaling factor.
836      * @param initialSy      initial y scaling factor.
837      * @param initialSz      initial z scaling factor.
838      */
839     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
840             final Collection<StandardDeviationFrameBodyKinematics> measurements, final boolean commonAxisUsed,
841             final double biasX, final double biasY, final double biasZ,
842             final double initialSx, final double initialSy, final double initialSz) {
843         this(commonAxisUsed, biasX, biasY, biasZ, initialSx, initialSy, initialSz);
844         this.measurements = measurements;
845     }
846 
847     /**
848      * Constructor.
849      *
850      * @param measurements   collection of body kinematics measurements with standard
851      *                       deviations taken at different frames (positions, orientations
852      *                       and velocities).
853      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
854      *                       accelerometer and gyroscope.
855      * @param biasX          known x coordinate of gyroscope bias expressed in radians per second
856      *                       (rad/s).
857      * @param biasY          known y coordinate of gyroscope bias expressed in radians per second
858      *                       (rad/s).
859      * @param biasZ          known z coordinate of gyroscope bias expressed in radians per second
860      *                       (rad/s).
861      * @param initialSx      initial x scaling factor.
862      * @param initialSy      initial y scaling factor.
863      * @param initialSz      initial z scaling factor.
864      * @param listener       listener to handle events raised by this calibrator.
865      */
866     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
867             final Collection<StandardDeviationFrameBodyKinematics> measurements, final boolean commonAxisUsed,
868             final double biasX, final double biasY, final double biasZ,
869             final double initialSx, final double initialSy, final double initialSz,
870             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
871         this(measurements, commonAxisUsed, biasX, biasY, biasZ, initialSx, initialSy, initialSz);
872         this.listener = listener;
873     }
874 
875     /**
876      * Constructor.
877      *
878      * @param biasX     known x coordinate of gyroscope bias.
879      * @param biasY     known y coordinate of gyroscope bias.
880      * @param biasZ     known z coordinate of gyroscope bias.
881      * @param initialSx initial x scaling factor.
882      * @param initialSy initial y scaling factor.
883      * @param initialSz initial z scaling factor.
884      */
885     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
886             final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
887             final double initialSx, final double initialSy, final double initialSz) {
888         this(biasX, biasY, biasZ);
889         try {
890             setInitialScalingFactors(initialSx, initialSy, initialSz);
891         } catch (final LockedException ignore) {
892             // never happens
893         }
894     }
895 
896     /**
897      * Constructor.
898      *
899      * @param biasX     known x coordinate of gyroscope bias.
900      * @param biasY     known y coordinate of gyroscope bias.
901      * @param biasZ     known z coordinate of gyroscope bias.
902      * @param initialSx initial x scaling factor.
903      * @param initialSy initial y scaling factor.
904      * @param initialSz initial z scaling factor.
905      * @param listener  listener to handle events raised by this calibrator.
906      */
907     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
908             final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
909             final double initialSx, final double initialSy, final double initialSz,
910             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
911         this(biasX, biasY, biasZ, initialSx, initialSy, initialSz);
912         this.listener = listener;
913     }
914 
915     /**
916      * Constructor.
917      *
918      * @param measurements collection of body kinematics measurements with standard
919      *                     deviations taken at different frames (positions, orientations
920      *                     and velocities).
921      * @param biasX        known x coordinate of gyroscope bias.
922      * @param biasY        known y coordinate of gyroscope bias.
923      * @param biasZ        known z coordinate of gyroscope bias.
924      * @param initialSx    initial x scaling factor.
925      * @param initialSy    initial y scaling factor.
926      * @param initialSz    initial z scaling factor.
927      */
928     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
929             final Collection<StandardDeviationFrameBodyKinematics> measurements,
930             final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
931             final double initialSx, final double initialSy, final double initialSz) {
932         this(biasX, biasY, biasZ, initialSx, initialSy, initialSz);
933         this.measurements = measurements;
934     }
935 
936     /**
937      * Constructor.
938      *
939      * @param measurements collection of body kinematics measurements with standard
940      *                     deviations taken at different frames (positions, orientations
941      *                     and velocities).
942      * @param biasX        known x coordinate of gyroscope bias.
943      * @param biasY        known y coordinate of gyroscope bias.
944      * @param biasZ        known z coordinate of gyroscope bias.
945      * @param initialSx    initial x scaling factor.
946      * @param initialSy    initial y scaling factor.
947      * @param initialSz    initial z scaling factor.
948      * @param listener     listener to handle events raised by this calibrator.
949      */
950     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
951             final Collection<StandardDeviationFrameBodyKinematics> measurements,
952             final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
953             final double initialSx, final double initialSy, final double initialSz,
954             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
955         this(measurements, biasX, biasY, biasZ, initialSx, initialSy, initialSz);
956         this.listener = listener;
957     }
958 
959     /**
960      * Constructor.
961      *
962      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
963      *                       accelerometer and gyroscope.
964      * @param biasX          known x coordinate of gyroscope bias.
965      * @param biasY          known y coordinate of gyroscope bias.
966      * @param biasZ          known z coordinate of gyroscope bias.
967      * @param initialSx      initial x scaling factor.
968      * @param initialSy      initial y scaling factor.
969      * @param initialSz      initial z scaling factor.
970      */
971     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
972             final boolean commonAxisUsed, final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
973             final double initialSx, final double initialSy, final double initialSz) {
974         this(biasX, biasY, biasZ, initialSx, initialSy, initialSz);
975         this.commonAxisUsed = commonAxisUsed;
976     }
977 
978     /**
979      * Constructor.
980      *
981      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
982      *                       accelerometer and gyroscope.
983      * @param biasX          known x coordinate of gyroscope bias.
984      * @param biasY          known y coordinate of gyroscope bias.
985      * @param biasZ          known z coordinate of gyroscope bias.
986      * @param initialSx      initial x scaling factor.
987      * @param initialSy      initial y scaling factor.
988      * @param initialSz      initial z scaling factor.
989      * @param listener       listener to handle events raised by this calibrator.
990      */
991     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
992             final boolean commonAxisUsed, final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
993             final double initialSx, final double initialSy, final double initialSz,
994             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
995         this(commonAxisUsed, biasX, biasY, biasZ, initialSx, initialSy, initialSz);
996         this.listener = listener;
997     }
998 
999     /**
1000      * Constructor.
1001      *
1002      * @param measurements   collection of body kinematics measurements with standard
1003      *                       deviations taken at different frames (positions, orientations
1004      *                       and velocities).
1005      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1006      *                       accelerometer and gyroscope.
1007      * @param biasX          known x coordinate of gyroscope bias.
1008      * @param biasY          known y coordinate of gyroscope bias.
1009      * @param biasZ          known z coordinate of gyroscope bias.
1010      * @param initialSx      initial x scaling factor.
1011      * @param initialSy      initial y scaling factor.
1012      * @param initialSz      initial z scaling factor.
1013      */
1014     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1015             final Collection<StandardDeviationFrameBodyKinematics> measurements, final boolean commonAxisUsed,
1016             final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
1017             final double initialSx, final double initialSy, final double initialSz) {
1018         this(commonAxisUsed, biasX, biasY, biasZ, initialSx, initialSy, initialSz);
1019         this.measurements = measurements;
1020     }
1021 
1022     /**
1023      * Constructor.
1024      *
1025      * @param measurements   collection of body kinematics measurements with standard
1026      *                       deviations taken at different frames (positions, orientations
1027      *                       and velocities).
1028      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1029      *                       accelerometer and gyroscope.
1030      * @param biasX          known x coordinate of gyroscope bias.
1031      * @param biasY          known y coordinate of gyroscope bias.
1032      * @param biasZ          known z coordinate of gyroscope bias.
1033      * @param initialSx      initial x scaling factor.
1034      * @param initialSy      initial y scaling factor.
1035      * @param initialSz      initial z scaling factor.
1036      * @param listener       listener to handle events raised by this calibrator.
1037      */
1038     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1039             final Collection<StandardDeviationFrameBodyKinematics> measurements, final boolean commonAxisUsed,
1040             final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
1041             final double initialSx, final double initialSy, final double initialSz,
1042             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1043         this(measurements, commonAxisUsed, biasX, biasY, biasZ, initialSx, initialSy, initialSz);
1044         this.listener = listener;
1045     }
1046 
1047     /**
1048      * Constructor.
1049      *
1050      * @param biasX      known x coordinate of gyroscope bias expressed in radians per second
1051      *                   (rad/s).
1052      * @param biasY      known y coordinate of gyroscope bias expressed in radians per second
1053      *                   (rad/s).
1054      * @param biasZ      known z coordinate of gyroscope bias expressed in radians per second
1055      *                   (rad/s).
1056      * @param initialSx  initial x scaling factor.
1057      * @param initialSy  initial y scaling factor.
1058      * @param initialSz  initial z scaling factor.
1059      * @param initialMxy initial x-y cross coupling error.
1060      * @param initialMxz initial x-z cross coupling error.
1061      * @param initialMyx initial y-x cross coupling error.
1062      * @param initialMyz initial y-z cross coupling error.
1063      * @param initialMzx initial z-x cross coupling error.
1064      * @param initialMzy initial z-y cross coupling error.
1065      */
1066     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1067             final double biasX, final double biasY, final double biasZ,
1068             final double initialSx, final double initialSy, final double initialSz,
1069             final double initialMxy, final double initialMxz,
1070             final double initialMyx, final double initialMyz,
1071             final double initialMzx, final double initialMzy) {
1072         this(biasX, biasY, biasZ);
1073         try {
1074             setInitialScalingFactorsAndCrossCouplingErrors(initialSx, initialSy, initialSz,
1075                     initialMxy, initialMxz, initialMyx, initialMyz, initialMzx, initialMzy);
1076         } catch (final LockedException ignore) {
1077             // never happens
1078         }
1079     }
1080 
1081     /**
1082      * Constructor.
1083      *
1084      * @param measurements collection of body kinematics measurements with standard
1085      *                     deviations taken at different frames (positions, orientations
1086      *                     and velocities).
1087      * @param biasX        known x coordinate of gyroscope bias expressed in radians per second
1088      *                     (rad/s).
1089      * @param biasY        known y coordinate of gyroscope bias expressed in radians per second
1090      *                     (rad/s).
1091      * @param biasZ        known z coordinate of gyroscope bias expressed in radians per second
1092      *                     (rad/s).
1093      * @param initialSx    initial x scaling factor.
1094      * @param initialSy    initial y scaling factor.
1095      * @param initialSz    initial z scaling factor.
1096      * @param initialMxy   initial x-y cross coupling error.
1097      * @param initialMxz   initial x-z cross coupling error.
1098      * @param initialMyx   initial y-x cross coupling error.
1099      * @param initialMyz   initial y-z cross coupling error.
1100      * @param initialMzx   initial z-x cross coupling error.
1101      * @param initialMzy   initial z-y cross coupling error.
1102      */
1103     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1104             final Collection<StandardDeviationFrameBodyKinematics> measurements,
1105             final double biasX, final double biasY, final double biasZ,
1106             final double initialSx, final double initialSy, final double initialSz,
1107             final double initialMxy, final double initialMxz,
1108             final double initialMyx, final double initialMyz,
1109             final double initialMzx, final double initialMzy) {
1110         this(biasX, biasY, biasZ, initialSx, initialSy, initialSz,
1111                 initialMxy, initialMxz, initialMyx, initialMyz, initialMzx, initialMzy);
1112         this.measurements = measurements;
1113     }
1114 
1115     /**
1116      * Constructor.
1117      *
1118      * @param measurements collection of body kinematics measurements with standard
1119      *                     deviations taken at different frames (positions, orientations
1120      *                     and velocities).
1121      * @param biasX        known x coordinate of gyroscope bias expressed in radians per second
1122      *                     (rad/s).
1123      * @param biasY        known y coordinate of gyroscope bias expressed in radians per second
1124      *                     (rad/s).
1125      * @param biasZ        known z coordinate of gyroscope bias expressed in radians per second
1126      *                     (rad/s).
1127      * @param initialSx    initial x scaling factor.
1128      * @param initialSy    initial y scaling factor.
1129      * @param initialSz    initial z scaling factor.
1130      * @param initialMxy   initial x-y cross coupling error.
1131      * @param initialMxz   initial x-z cross coupling error.
1132      * @param initialMyx   initial y-x cross coupling error.
1133      * @param initialMyz   initial y-z cross coupling error.
1134      * @param initialMzx   initial z-x cross coupling error.
1135      * @param initialMzy   initial z-y cross coupling error.
1136      * @param listener     listener to handle events raised by this calibrator.
1137      */
1138     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1139             final Collection<StandardDeviationFrameBodyKinematics> measurements,
1140             final double biasX, final double biasY, final double biasZ,
1141             final double initialSx, final double initialSy, final double initialSz,
1142             final double initialMxy, final double initialMxz,
1143             final double initialMyx, final double initialMyz,
1144             final double initialMzx, final double initialMzy,
1145             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1146         this(measurements, biasX, biasY, biasZ, initialSx, initialSy, initialSz,
1147                 initialMxy, initialMxz, initialMyx, initialMyz, initialMzx, initialMzy);
1148         this.listener = listener;
1149     }
1150 
1151     /**
1152      * Constructor.
1153      *
1154      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1155      *                       accelerometer and gyroscope.
1156      * @param biasX          known x coordinate of gyroscope bias expressed in radians per second
1157      *                       (rad/s).
1158      * @param biasY          known y coordinate of gyroscope bias expressed in radians per second
1159      *                       (rad/s).
1160      * @param biasZ          known z coordinate of gyroscope bias expressed in radians per second
1161      *                       (rad/s).
1162      * @param initialSx      initial x scaling factor.
1163      * @param initialSy      initial y scaling factor.
1164      * @param initialSz      initial z scaling factor.
1165      * @param initialMxy     initial x-y cross coupling error.
1166      * @param initialMxz     initial x-z cross coupling error.
1167      * @param initialMyx     initial y-x cross coupling error.
1168      * @param initialMyz     initial y-z cross coupling error.
1169      * @param initialMzx     initial z-x cross coupling error.
1170      * @param initialMzy     initial z-y cross coupling error.
1171      */
1172     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1173             final boolean commonAxisUsed, final double biasX, final double biasY, final double biasZ,
1174             final double initialSx, final double initialSy, final double initialSz,
1175             final double initialMxy, final double initialMxz,
1176             final double initialMyx, final double initialMyz,
1177             final double initialMzx, final double initialMzy) {
1178         this(biasX, biasY, biasZ, initialSx, initialSy, initialSz,
1179                 initialMxy, initialMxz, initialMyx, initialMyz, initialMzx, initialMzy);
1180         this.commonAxisUsed = commonAxisUsed;
1181     }
1182 
1183     /**
1184      * Constructor.
1185      *
1186      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1187      *                       accelerometer and gyroscope.
1188      * @param biasX          known x coordinate of gyroscope bias expressed in radians per second
1189      *                       (rad/s).
1190      * @param biasY          known y coordinate of gyroscope bias expressed in radians per second
1191      *                       (rad/s).
1192      * @param biasZ          known z coordinate of gyroscope bias expressed in radians per second
1193      *                       (rad/s).
1194      * @param initialSx      initial x scaling factor.
1195      * @param initialSy      initial y scaling factor.
1196      * @param initialSz      initial z scaling factor.
1197      * @param initialMxy     initial x-y cross coupling error.
1198      * @param initialMxz     initial x-z cross coupling error.
1199      * @param initialMyx     initial y-x cross coupling error.
1200      * @param initialMyz     initial y-z cross coupling error.
1201      * @param initialMzx     initial z-x cross coupling error.
1202      * @param initialMzy     initial z-y cross coupling error.
1203      * @param listener       listener to handle events raised by this calibrator.
1204      */
1205     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1206             final boolean commonAxisUsed, final double biasX, final double biasY, final double biasZ,
1207             final double initialSx, final double initialSy, final double initialSz,
1208             final double initialMxy, final double initialMxz,
1209             final double initialMyx, final double initialMyz,
1210             final double initialMzx, final double initialMzy,
1211             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1212         this(commonAxisUsed, biasX, biasY, biasZ, initialSx, initialSy, initialSz,
1213                 initialMxy, initialMxz, initialMyx, initialMyz, initialMzx, initialMzy);
1214         this.listener = listener;
1215     }
1216 
1217     /**
1218      * Constructor.
1219      *
1220      * @param measurements   collection of body kinematics measurements with standard
1221      *                       deviations taken at different frames (positions, orientations
1222      *                       and velocities).
1223      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1224      *                       accelerometer and gyroscope.
1225      * @param biasX          known x coordinate of gyroscope bias expressed in radians per second
1226      *                       (rad/s).
1227      * @param biasY          known y coordinate of gyroscope bias expressed in radians per second
1228      *                       (rad/s).
1229      * @param biasZ          known z coordinate of gyroscope bias expressed in radians per second
1230      *                       (rad/s).
1231      * @param initialSx      initial x scaling factor.
1232      * @param initialSy      initial y scaling factor.
1233      * @param initialSz      initial z scaling factor.
1234      * @param initialMxy     initial x-y cross coupling error.
1235      * @param initialMxz     initial x-z cross coupling error.
1236      * @param initialMyx     initial y-x cross coupling error.
1237      * @param initialMyz     initial y-z cross coupling error.
1238      * @param initialMzx     initial z-x cross coupling error.
1239      * @param initialMzy     initial z-y cross coupling error.
1240      */
1241     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1242             final Collection<StandardDeviationFrameBodyKinematics> measurements, final boolean commonAxisUsed,
1243             final double biasX, final double biasY, final double biasZ,
1244             final double initialSx, final double initialSy, final double initialSz,
1245             final double initialMxy, final double initialMxz, final double initialMyx,
1246             final double initialMyz, final double initialMzx, final double initialMzy) {
1247         this(commonAxisUsed, biasX, biasY, biasZ, initialSx, initialSy, initialSz,
1248                 initialMxy, initialMxz, initialMyx, initialMyz, initialMzx, initialMzy);
1249         this.measurements = measurements;
1250     }
1251 
1252     /**
1253      * Constructor.
1254      *
1255      * @param measurements   collection of body kinematics measurements with standard
1256      *                       deviations taken at different frames (positions, orientations
1257      *                       and velocities).
1258      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1259      *                       accelerometer and gyroscope.
1260      * @param biasX          known x coordinate of gyroscope bias expressed in radians per second
1261      *                       (rad/s).
1262      * @param biasY          known y coordinate of gyroscope bias expressed in radians per second
1263      *                       (rad/s).
1264      * @param biasZ          known z coordinate of gyroscope bias expressed in radians per second
1265      *                       (rad/s).
1266      * @param initialSx      initial x scaling factor.
1267      * @param initialSy      initial y scaling factor.
1268      * @param initialSz      initial z scaling factor.
1269      * @param initialMxy     initial x-y cross coupling error.
1270      * @param initialMxz     initial x-z cross coupling error.
1271      * @param initialMyx     initial y-x cross coupling error.
1272      * @param initialMyz     initial y-z cross coupling error.
1273      * @param initialMzx     initial z-x cross coupling error.
1274      * @param initialMzy     initial z-y cross coupling error.
1275      * @param listener       listener to handle events raised by this calibrator.
1276      */
1277     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1278             final Collection<StandardDeviationFrameBodyKinematics> measurements, final boolean commonAxisUsed,
1279             final double biasX, final double biasY, final double biasZ,
1280             final double initialSx, final double initialSy, final double initialSz,
1281             final double initialMxy, final double initialMxz, final double initialMyx,
1282             final double initialMyz, final double initialMzx, final double initialMzy,
1283             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1284         this(measurements, commonAxisUsed, biasX, biasY, biasZ, initialSx, initialSy, initialSz,
1285                 initialMxy, initialMxz, initialMyx, initialMyz, initialMzx, initialMzy);
1286         this.listener = listener;
1287     }
1288 
1289     /**
1290      * Constructor.
1291      *
1292      * @param biasX      known x coordinate of gyroscope bias.
1293      * @param biasY      known y coordinate of gyroscope bias.
1294      * @param biasZ      known z coordinate of gyroscope bias.
1295      * @param initialSx  initial x scaling factor.
1296      * @param initialSy  initial y scaling factor.
1297      * @param initialSz  initial z scaling factor.
1298      * @param initialMxy initial x-y cross coupling error.
1299      * @param initialMxz initial x-z cross coupling error.
1300      * @param initialMyx initial y-x cross coupling error.
1301      * @param initialMyz initial y-z cross coupling error.
1302      * @param initialMzx initial z-x cross coupling error.
1303      * @param initialMzy initial z-y cross coupling error.
1304      */
1305     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1306             final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
1307             final double initialSx, final double initialSy, final double initialSz,
1308             final double initialMxy, final double initialMxz, final double initialMyx,
1309             final double initialMyz, final double initialMzx, final double initialMzy) {
1310         this(biasX, biasY, biasZ);
1311         try {
1312             setInitialScalingFactorsAndCrossCouplingErrors(initialSx, initialSy, initialSz,
1313                     initialMxy, initialMxz, initialMyx, initialMyz, initialMzx, initialMzy);
1314         } catch (final LockedException ignore) {
1315             // never happens
1316         }
1317     }
1318 
1319     /**
1320      * Constructor.
1321      *
1322      * @param biasX      known x coordinate of gyroscope bias.
1323      * @param biasY      known y coordinate of gyroscope bias.
1324      * @param biasZ      known z coordinate of gyroscope bias.
1325      * @param initialSx  initial x scaling factor.
1326      * @param initialSy  initial y scaling factor.
1327      * @param initialSz  initial z scaling factor.
1328      * @param initialMxy initial x-y cross coupling error.
1329      * @param initialMxz initial x-z cross coupling error.
1330      * @param initialMyx initial y-x cross coupling error.
1331      * @param initialMyz initial y-z cross coupling error.
1332      * @param initialMzx initial z-x cross coupling error.
1333      * @param initialMzy initial z-y cross coupling error.
1334      * @param listener   listener to handle events raised by this calibrator.
1335      */
1336     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1337             final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
1338             final double initialSx, final double initialSy, final double initialSz,
1339             final double initialMxy, final double initialMxz, final double initialMyx,
1340             final double initialMyz, final double initialMzx, final double initialMzy,
1341             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1342         this(biasX, biasY, biasZ, initialSx, initialSy, initialSz, initialMxy, initialMxz, initialMyx,
1343                 initialMyz, initialMzx, initialMzy);
1344         this.listener = listener;
1345     }
1346 
1347     /**
1348      * Constructor.
1349      *
1350      * @param measurements collection of body kinematics measurements with standard
1351      *                     deviations taken at different frames (positions, orientations
1352      *                     and velocities).
1353      * @param biasX        known x coordinate of gyroscope bias.
1354      * @param biasY        known y coordinate of gyroscope bias.
1355      * @param biasZ        known z coordinate of gyroscope bias.
1356      * @param initialSx    initial x scaling factor.
1357      * @param initialSy    initial y scaling factor.
1358      * @param initialSz    initial z scaling factor.
1359      * @param initialMxy   initial x-y cross coupling error.
1360      * @param initialMxz   initial x-z cross coupling error.
1361      * @param initialMyx   initial y-x cross coupling error.
1362      * @param initialMyz   initial y-z cross coupling error.
1363      * @param initialMzx   initial z-x cross coupling error.
1364      * @param initialMzy   initial z-y cross coupling error.
1365      */
1366     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1367             final Collection<StandardDeviationFrameBodyKinematics> measurements,
1368             final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
1369             final double initialSx, final double initialSy, final double initialSz,
1370             final double initialMxy, final double initialMxz, final double initialMyx,
1371             final double initialMyz, final double initialMzx, final double initialMzy) {
1372         this(biasX, biasY, biasZ, initialSx, initialSy, initialSz, initialMxy, initialMxz, initialMyx,
1373                 initialMyz, initialMzx, initialMzy);
1374         this.measurements = measurements;
1375     }
1376 
1377     /**
1378      * Constructor.
1379      *
1380      * @param measurements collection of body kinematics measurements with standard
1381      *                     deviations taken at different frames (positions, orientations
1382      *                     and velocities).
1383      * @param biasX        known x coordinate of gyroscope bias.
1384      * @param biasY        known y coordinate of gyroscope bias.
1385      * @param biasZ        known z coordinate of gyroscope bias.
1386      * @param initialSx    initial x scaling factor.
1387      * @param initialSy    initial y scaling factor.
1388      * @param initialSz    initial z scaling factor.
1389      * @param initialMxy   initial x-y cross coupling error.
1390      * @param initialMxz   initial x-z cross coupling error.
1391      * @param initialMyx   initial y-x cross coupling error.
1392      * @param initialMyz   initial y-z cross coupling error.
1393      * @param initialMzx   initial z-x cross coupling error.
1394      * @param initialMzy   initial z-y cross coupling error.
1395      * @param listener     listener to handle events raised by this calibrator.
1396      */
1397     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1398             final Collection<StandardDeviationFrameBodyKinematics> measurements,
1399             final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
1400             final double initialSx, final double initialSy, final double initialSz,
1401             final double initialMxy, final double initialMxz, final double initialMyx,
1402             final double initialMyz, final double initialMzx, final double initialMzy,
1403             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1404         this(measurements, biasX, biasY, biasZ, initialSx, initialSy, initialSz, initialMxy, initialMxz, initialMyx,
1405                 initialMyz, initialMzx, initialMzy);
1406         this.listener = listener;
1407     }
1408 
1409     /**
1410      * Constructor.
1411      *
1412      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1413      *                       accelerometer and gyroscope.
1414      * @param biasX          known x coordinate of gyroscope bias expressed in radians per second
1415      *                       (rad/s).
1416      * @param biasY          known y coordinate of gyroscope bias expressed in radians per second
1417      *                       (rad/s).
1418      * @param biasZ          known z coordinate of gyroscope bias expressed in radians per second
1419      *                       (rad/s).
1420      * @param initialSx      initial x scaling factor.
1421      * @param initialSy      initial y scaling factor.
1422      * @param initialSz      initial z scaling factor.
1423      * @param initialMxy     initial x-y cross coupling error.
1424      * @param initialMxz     initial x-z cross coupling error.
1425      * @param initialMyx     initial y-x cross coupling error.
1426      * @param initialMyz     initial y-z cross coupling error.
1427      * @param initialMzx     initial z-x cross coupling error.
1428      * @param initialMzy     initial z-y cross coupling error.
1429      */
1430     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1431             final boolean commonAxisUsed, final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
1432             final double initialSx, final double initialSy, final double initialSz,
1433             final double initialMxy, final double initialMxz, final double initialMyx,
1434             final double initialMyz, final double initialMzx, final double initialMzy) {
1435         this(biasX, biasY, biasZ, initialSx, initialSy, initialSz, initialMxy, initialMxz, initialMyx,
1436                 initialMyz, initialMzx, initialMzy);
1437         this.commonAxisUsed = commonAxisUsed;
1438     }
1439 
1440     /**
1441      * Constructor.
1442      *
1443      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1444      *                       accelerometer and gyroscope.
1445      * @param biasX          known x coordinate of gyroscope bias expressed in radians per second
1446      *                       (rad/s).
1447      * @param biasY          known y coordinate of gyroscope bias expressed in radians per second
1448      *                       (rad/s).
1449      * @param biasZ          known z coordinate of gyroscope bias expressed in radians per second
1450      *                       (rad/s).
1451      * @param initialSx      initial x scaling factor.
1452      * @param initialSy      initial y scaling factor.
1453      * @param initialSz      initial z scaling factor.
1454      * @param initialMxy     initial x-y cross coupling error.
1455      * @param initialMxz     initial x-z cross coupling error.
1456      * @param initialMyx     initial y-x cross coupling error.
1457      * @param initialMyz     initial y-z cross coupling error.
1458      * @param initialMzx     initial z-x cross coupling error.
1459      * @param initialMzy     initial z-y cross coupling error.
1460      * @param listener       listener to handle events raised by this calibrator.
1461      */
1462     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1463             final boolean commonAxisUsed, final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
1464             final double initialSx, final double initialSy, final double initialSz,
1465             final double initialMxy, final double initialMxz, final double initialMyx,
1466             final double initialMyz, final double initialMzx, final double initialMzy,
1467             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1468         this(commonAxisUsed, biasX, biasY, biasZ, initialSx, initialSy, initialSz, initialMxy, initialMxz, initialMyx,
1469                 initialMyz, initialMzx, initialMzy);
1470         this.listener = listener;
1471     }
1472 
1473     /**
1474      * Constructor.
1475      *
1476      * @param measurements   collection of body kinematics measurements with standard
1477      *                       deviations taken at different frames (positions, orientations
1478      *                       and velocities).
1479      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1480      *                       accelerometer and gyroscope.
1481      * @param biasX          known x coordinate of gyroscope bias expressed in radians per second
1482      *                       (rad/s).
1483      * @param biasY          known y coordinate of gyroscope bias expressed in radians per second
1484      *                       (rad/s).
1485      * @param biasZ          known z coordinate of gyroscope bias expressed in radians per second
1486      *                       (rad/s).
1487      * @param initialSx      initial x scaling factor.
1488      * @param initialSy      initial y scaling factor.
1489      * @param initialSz      initial z scaling factor.
1490      * @param initialMxy     initial x-y cross coupling error.
1491      * @param initialMxz     initial x-z cross coupling error.
1492      * @param initialMyx     initial y-x cross coupling error.
1493      * @param initialMyz     initial y-z cross coupling error.
1494      * @param initialMzx     initial z-x cross coupling error.
1495      * @param initialMzy     initial z-y cross coupling error.
1496      */
1497     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1498             final Collection<StandardDeviationFrameBodyKinematics> measurements, final boolean commonAxisUsed,
1499             final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
1500             final double initialSx, final double initialSy, final double initialSz,
1501             final double initialMxy, final double initialMxz, final double initialMyx,
1502             final double initialMyz, final double initialMzx, final double initialMzy) {
1503         this(commonAxisUsed, biasX, biasY, biasZ, initialSx, initialSy, initialSz, initialMxy, initialMxz, initialMyx,
1504                 initialMyz, initialMzx, initialMzy);
1505         this.measurements = measurements;
1506     }
1507 
1508     /**
1509      * Constructor.
1510      *
1511      * @param measurements   collection of body kinematics measurements with standard
1512      *                       deviations taken at different frames (positions, orientations
1513      *                       and velocities).
1514      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1515      *                       accelerometer and gyroscope.
1516      * @param biasX          known x coordinate of gyroscope bias expressed in radians per second
1517      *                       (rad/s).
1518      * @param biasY          known y coordinate of gyroscope bias expressed in radians per second
1519      *                       (rad/s).
1520      * @param biasZ          known z coordinate of gyroscope bias expressed in radians per second
1521      *                       (rad/s).
1522      * @param initialSx      initial x scaling factor.
1523      * @param initialSy      initial y scaling factor.
1524      * @param initialSz      initial z scaling factor.
1525      * @param initialMxy     initial x-y cross coupling error.
1526      * @param initialMxz     initial x-z cross coupling error.
1527      * @param initialMyx     initial y-x cross coupling error.
1528      * @param initialMyz     initial y-z cross coupling error.
1529      * @param initialMzx     initial z-x cross coupling error.
1530      * @param initialMzy     initial z-y cross coupling error.
1531      * @param listener       listener to handle events raised by this calibrator.
1532      */
1533     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1534             final Collection<StandardDeviationFrameBodyKinematics> measurements,
1535             final boolean commonAxisUsed, final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ,
1536             final double initialSx, final double initialSy, final double initialSz,
1537             final double initialMxy, final double initialMxz, final double initialMyx,
1538             final double initialMyz, final double initialMzx, final double initialMzy,
1539             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1540         this(measurements, commonAxisUsed, biasX, biasY, biasZ, initialSx, initialSy, initialSz,
1541                 initialMxy, initialMxz, initialMyx, initialMyz, initialMzx, initialMzy);
1542         this.listener = listener;
1543     }
1544 
1545     /**
1546      * Constructor.
1547      *
1548      * @param bias known gyroscope bias expressed in radians per second (rad/s).
1549      *             This must have length 3.
1550      * @throws IllegalArgumentException if provided bias array does not have length 3.
1551      */
1552     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(final double[] bias) {
1553         this();
1554         try {
1555             setBias(bias);
1556         } catch (final LockedException ignore) {
1557             // never happens
1558         }
1559     }
1560 
1561     /**
1562      * Constructor.
1563      *
1564      * @param bias     known gyroscope bias expressed in radians per second (rad/s).
1565      *                 This must have length 3.
1566      * @param listener listener to handle events raised by this calibrator.
1567      * @throws IllegalArgumentException if provided bias array does not have length 3.
1568      */
1569     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1570             final double[] bias, final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1571         this(bias);
1572         this.listener = listener;
1573     }
1574 
1575     /**
1576      * Constructor.
1577      *
1578      * @param measurements collection of body kinematics measurements with standard
1579      *                     deviations taken at different frames (positions, orientations
1580      *                     and velocities).
1581      * @param bias         known gyroscope bias expressed in radians per second (rad/s).
1582      *                     This must have length 3.
1583      * @throws IllegalArgumentException if provided bias array does not have length 3.
1584      */
1585     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1586             final Collection<StandardDeviationFrameBodyKinematics> measurements, final double[] bias) {
1587         this(bias);
1588         this.measurements = measurements;
1589     }
1590 
1591     /**
1592      * Constructor.
1593      *
1594      * @param measurements collection of body kinematics measurements with standard
1595      *                     deviations taken at different frames (positions, orientations
1596      *                     and velocities).
1597      * @param bias         known gyroscope bias expressed in radians per second (rad/s).
1598      *                     This must have length 3.
1599      * @param listener     listener to handle events raised by this calibrator.
1600      * @throws IllegalArgumentException if provided bias array does not have length 3.
1601      */
1602     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1603             final Collection<StandardDeviationFrameBodyKinematics> measurements, final double[] bias,
1604             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1605         this(measurements, bias);
1606         this.listener = listener;
1607     }
1608 
1609     /**
1610      * Constructor.
1611      *
1612      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1613      *                       accelerometer and gyroscope.
1614      * @param bias           known gyroscope bias expressed in radians per second (rad/s).
1615      *                       This must have length 3.
1616      * @throws IllegalArgumentException if provided bias array does not have length 3.
1617      */
1618     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1619             final boolean commonAxisUsed, final double[] bias) {
1620         this(bias);
1621         this.commonAxisUsed = commonAxisUsed;
1622     }
1623 
1624     /**
1625      * Constructor.
1626      *
1627      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1628      *                       accelerometer and gyroscope.
1629      * @param bias           known gyroscope bias expressed in radians per second (rad/s).
1630      *                       This must have length 3.
1631      * @param listener       listener to handle events raised by this calibrator.
1632      * @throws IllegalArgumentException if provided bias array does not have length 3.
1633      */
1634     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1635             final boolean commonAxisUsed, final double[] bias,
1636             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1637         this(commonAxisUsed, bias);
1638         this.listener = listener;
1639     }
1640 
1641     /**
1642      * Constructor.
1643      *
1644      * @param measurements   collection of body kinematics measurements with standard
1645      *                       deviations taken at different frames (positions, orientations
1646      *                       and velocities).
1647      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1648      *                       accelerometer and gyroscope.
1649      * @param bias           known gyroscope bias expressed in radians per second (rad/s).
1650      *                       This must have length 3.
1651      * @throws IllegalArgumentException if provided bias array does not have length 3.
1652      */
1653     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1654             final Collection<StandardDeviationFrameBodyKinematics> measurements, final boolean commonAxisUsed,
1655             final double[] bias) {
1656         this(commonAxisUsed, bias);
1657         this.measurements = measurements;
1658     }
1659 
1660     /**
1661      * Constructor.
1662      *
1663      * @param measurements   collection of body kinematics measurements with standard
1664      *                       deviations taken at different frames (positions, orientations
1665      *                       and velocities).
1666      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1667      *                       accelerometer and gyroscope.
1668      * @param bias           known gyroscope bias expressed in radians per second (rad/s).
1669      *                       This must have length 3.
1670      * @param listener       listener to handle events raised by this calibrator.
1671      * @throws IllegalArgumentException if provided bias array does not have length 3.
1672      */
1673     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1674             final Collection<StandardDeviationFrameBodyKinematics> measurements, final boolean commonAxisUsed,
1675             final double[] bias, final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1676         this(measurements, commonAxisUsed, bias);
1677         this.listener = listener;
1678     }
1679 
1680     /**
1681      * Constructor.
1682      *
1683      * @param bias known bias expressed in radians per second (rad/s). This must
1684      *             be 3x1.
1685      * @throws IllegalArgumentException if provided bias matrix is not 3x1.
1686      */
1687     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(final Matrix bias) {
1688         this();
1689         try {
1690             setBias(bias);
1691         } catch (final LockedException ignore) {
1692             // never happens
1693         }
1694     }
1695 
1696     /**
1697      * Constructor.
1698      *
1699      * @param bias     known bias expressed in radians per second (rad/s). This must
1700      *                 be 3x1.
1701      * @param listener listener to handle events raised by this calibrator.
1702      * @throws IllegalArgumentException if provided bias matrix is not 3x1.
1703      */
1704     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1705             final Matrix bias, final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1706         this(bias);
1707         this.listener = listener;
1708     }
1709 
1710     /**
1711      * Constructor.
1712      *
1713      * @param measurements collection of body kinematics measurements with standard
1714      *                     deviations taken at different frames (positions, orientations
1715      *                     and velocities).
1716      * @param bias         known bias expressed in radians per second (rad/s). This must
1717      *                     be 3x1.
1718      * @throws IllegalArgumentException if provided bias matrix is not 3x1.
1719      */
1720     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1721             final Collection<StandardDeviationFrameBodyKinematics> measurements, final Matrix bias) {
1722         this(bias);
1723         this.measurements = measurements;
1724     }
1725 
1726     /**
1727      * Constructor.
1728      *
1729      * @param measurements collection of body kinematics measurements with standard
1730      *                     deviations taken at different frames (positions, orientations
1731      *                     and velocities).
1732      * @param bias         known bias expressed in radians per second (rad/s). This must
1733      *                     be 3x1.
1734      * @param listener     listener to handle events raised by this calibrator.
1735      * @throws IllegalArgumentException if provided bias matrix is not 3x1.
1736      */
1737     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1738             final Collection<StandardDeviationFrameBodyKinematics> measurements, final Matrix bias,
1739             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1740         this(measurements, bias);
1741         this.listener = listener;
1742     }
1743 
1744     /**
1745      * Constructor.
1746      *
1747      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1748      *                       accelerometer and gyroscope.
1749      * @param bias           known bias expressed in radians per second (rad/s). This must
1750      *                       be 3x1.
1751      * @throws IllegalArgumentException if provided bias matrix is not 3x1.
1752      */
1753     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(final boolean commonAxisUsed, final Matrix bias) {
1754         this(bias);
1755         this.commonAxisUsed = commonAxisUsed;
1756     }
1757 
1758     /**
1759      * Constructor.
1760      *
1761      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1762      *                       accelerometer and gyroscope.
1763      * @param bias           known bias expressed in radians per second (rad/s). This must
1764      *                       be 3x1.
1765      * @param listener       listener to handle events raised by this calibrator.
1766      * @throws IllegalArgumentException if provided bias matrix is not 3x1.
1767      */
1768     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1769             final boolean commonAxisUsed, final Matrix bias,
1770             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1771         this(commonAxisUsed, bias);
1772         this.listener = listener;
1773     }
1774 
1775     /**
1776      * Constructor.
1777      *
1778      * @param measurements   collection of body kinematics measurements with standard
1779      *                       deviations taken at different frames (positions, orientations
1780      *                       and velocities).
1781      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1782      *                       accelerometer and gyroscope.
1783      * @param bias           known bias expressed in radians per second (rad/s). This must
1784      *                       be 3x1.
1785      * @throws IllegalArgumentException if provided bias matrix is not 3x1.
1786      */
1787     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1788             final Collection<StandardDeviationFrameBodyKinematics> measurements, final boolean commonAxisUsed,
1789             final Matrix bias) {
1790         this(commonAxisUsed, bias);
1791         this.measurements = measurements;
1792     }
1793 
1794     /**
1795      * Constructor.
1796      *
1797      * @param measurements   collection of body kinematics measurements with standard
1798      *                       deviations taken at different frames (positions, orientations
1799      *                       and velocities).
1800      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1801      *                       accelerometer and gyroscope.
1802      * @param bias           known bias expressed in radians per second (rad/s). This must
1803      *                       be 3x1.
1804      * @param listener       listener to handle events raised by this calibrator.
1805      * @throws IllegalArgumentException if provided bias matrix is not 3x1.
1806      */
1807     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1808             final Collection<StandardDeviationFrameBodyKinematics> measurements,
1809             final boolean commonAxisUsed, final Matrix bias,
1810             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1811         this(measurements, commonAxisUsed, bias);
1812         this.listener = listener;
1813     }
1814 
1815     /**
1816      * Constructor.
1817      *
1818      * @param bias      known bias expressed in radians per second (rad/s). This must
1819      *                  be 3x1.
1820      * @param initialMg initial scale factors and cross coupling errors matrix.
1821      * @throws IllegalArgumentException if either provided bias matrix is not 3x1 or
1822      *                                  scaling and coupling error matrix is not 3x3.
1823      */
1824     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(final Matrix bias, final Matrix initialMg) {
1825         this(bias);
1826         try {
1827             setInitialMg(initialMg);
1828         } catch (final LockedException ignore) {
1829             // never happens
1830         }
1831     }
1832 
1833     /**
1834      * Constructor.
1835      *
1836      * @param bias      known bias expressed in radians per second (rad/s). This must
1837      *                  be 3x1.
1838      * @param initialMg initial scale factors and cross coupling errors matrix.
1839      * @param listener  listener to handle events raised by this calibrator.
1840      * @throws IllegalArgumentException if either provided bias matrix is not 3x1 or
1841      *                                  scaling and coupling error matrix is not 3x3.
1842      */
1843     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1844             final Matrix bias, final Matrix initialMg,
1845             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1846         this(bias, initialMg);
1847         this.listener = listener;
1848     }
1849 
1850     /**
1851      * Constructor.
1852      *
1853      * @param measurements collection of body kinematics measurements with standard
1854      *                     deviations taken at different frames (positions, orientations
1855      *                     and velocities).
1856      * @param bias         known bias expressed in radians per second (rad/s). This must
1857      *                     be 3x1.
1858      * @param initialMg    initial scale factors and cross coupling errors matrix.
1859      * @throws IllegalArgumentException if either provided bias matrix is not 3x1 or
1860      *                                  scaling and coupling error matrix is not 3x3.
1861      */
1862     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1863             final Collection<StandardDeviationFrameBodyKinematics> measurements,
1864             final Matrix bias, final Matrix initialMg) {
1865         this(bias, initialMg);
1866         this.measurements = measurements;
1867     }
1868 
1869     /**
1870      * Constructor.
1871      *
1872      * @param measurements collection of body kinematics measurements with standard
1873      *                     deviations taken at different frames (positions, orientations
1874      *                     and velocities).
1875      * @param bias         known bias expressed in radians per second (rad/s). This must
1876      *                     be 3x1.
1877      * @param initialMg    initial scale factors and cross coupling errors matrix.
1878      * @param listener     listener to handle events raised by this calibrator.
1879      * @throws IllegalArgumentException if either provided bias matrix is not 3x1 or
1880      *                                  scaling and coupling error matrix is not 3x3.
1881      */
1882     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1883             final Collection<StandardDeviationFrameBodyKinematics> measurements,
1884             final Matrix bias, final Matrix initialMg,
1885             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1886         this(measurements, bias, initialMg);
1887         this.listener = listener;
1888     }
1889 
1890     /**
1891      * Constructor.
1892      *
1893      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1894      *                       accelerometer and gyroscope.
1895      * @param bias           known bias expressed in radians per second (rad/s). This must
1896      *                       be 3x1.
1897      * @param initialMg      initial scale factors and cross coupling errors matrix.
1898      * @throws IllegalArgumentException if either provided bias matrix is not 3x1 or
1899      *                                  scaling and coupling error matrix is not 3x3.
1900      */
1901     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1902             final boolean commonAxisUsed, final Matrix bias, final Matrix initialMg) {
1903         this(bias, initialMg);
1904         this.commonAxisUsed = commonAxisUsed;
1905     }
1906 
1907     /**
1908      * Constructor.
1909      *
1910      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1911      *                       accelerometer and gyroscope.
1912      * @param bias           known bias expressed in radians per second (rad/s). This must
1913      *                       be 3x1.
1914      * @param initialMg      initial scale factors and cross coupling errors matrix.
1915      * @param listener       listener to handle events raised by this calibrator.
1916      * @throws IllegalArgumentException if either provided bias matrix is not 3x1 or
1917      *                                  scaling and coupling error matrix is not 3x3.
1918      */
1919     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1920             final boolean commonAxisUsed, final Matrix bias, final Matrix initialMg,
1921             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1922         this(commonAxisUsed, bias, initialMg);
1923         this.listener = listener;
1924     }
1925 
1926     /**
1927      * Constructor.
1928      *
1929      * @param measurements   collection of body kinematics measurements with standard
1930      *                       deviations taken at different frames (positions, orientations
1931      *                       and velocities).
1932      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1933      *                       accelerometer and gyroscope.
1934      * @param bias           known bias expressed in radians per second (rad/s). This must
1935      *                       be 3x1.
1936      * @param initialMg      initial scale factors and cross coupling errors matrix.
1937      * @throws IllegalArgumentException if either provided bias matrix is not 3x1 or
1938      *                                  scaling and coupling error matrix is not 3x3.
1939      */
1940     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1941             final Collection<StandardDeviationFrameBodyKinematics> measurements, final boolean commonAxisUsed,
1942             final Matrix bias, final Matrix initialMg) {
1943         this(commonAxisUsed, bias, initialMg);
1944         this.measurements = measurements;
1945     }
1946 
1947     /**
1948      * Constructor.
1949      *
1950      * @param measurements   collection of body kinematics measurements with standard
1951      *                       deviations taken at different frames (positions, orientations
1952      *                       and velocities).
1953      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
1954      *                       accelerometer and gyroscope.
1955      * @param bias           known bias expressed in radians per second (rad/s). This must
1956      *                       be 3x1.
1957      * @param initialMg      initial scale factors and cross coupling errors matrix.
1958      * @param listener       listener to handle events raised by this calibrator.
1959      * @throws IllegalArgumentException if either provided bias matrix is not 3x1 or
1960      *                                  scaling and coupling error matrix is not 3x3.
1961      */
1962     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1963             final Collection<StandardDeviationFrameBodyKinematics> measurements,
1964             final boolean commonAxisUsed, final Matrix bias, final Matrix initialMg,
1965             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
1966         this(measurements, commonAxisUsed, bias, initialMg);
1967         this.listener = listener;
1968     }
1969 
1970     /**
1971      * Constructor.
1972      *
1973      * @param bias      known bias expressed in radians per second (rad/s). This must
1974      *                  be 3x1.
1975      * @param initialMg initial scale factors and cross coupling errors matrix.
1976      * @param initialGg initial G-dependent cross biases.
1977      * @throws IllegalArgumentException if either provided bias matrix is not 3x1,
1978      *                                  scaling and coupling error matrix is not 3x3
1979      *                                  or g-dependant cross biases is not 3x3.
1980      */
1981     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
1982             final Matrix bias, final Matrix initialMg, final Matrix initialGg) {
1983         this(bias, initialMg);
1984         try {
1985             setInitialGg(initialGg);
1986         } catch (final LockedException ignore) {
1987             // never happens
1988         }
1989     }
1990 
1991     /**
1992      * Constructor.
1993      *
1994      * @param bias      known bias expressed in radians per second (rad/s). This must
1995      *                  be 3x1.
1996      * @param initialMg initial scale factors and cross coupling errors matrix.
1997      * @param initialGg initial G-dependent cross biases.
1998      * @param listener  listener to handle events raised by this calibrator.
1999      * @throws IllegalArgumentException if either provided bias matrix is not 3x1,
2000      *                                  scaling and coupling error matrix is not 3x3
2001      *                                  or g-dependant cross biases is not 3x3.
2002      */
2003     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
2004             final Matrix bias, final Matrix initialMg, final Matrix initialGg,
2005             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
2006         this(bias, initialMg, initialGg);
2007         this.listener = listener;
2008     }
2009 
2010     /**
2011      * Constructor.
2012      *
2013      * @param measurements collection of body kinematics measurements with standard
2014      *                     deviations taken at different frames (positions, orientations
2015      *                     and velocities).
2016      * @param bias         known bias expressed in radians per second (rad/s). This must
2017      *                     be 3x1.
2018      * @param initialMg    initial scale factors and cross coupling errors matrix.
2019      * @param initialGg    initial G-dependent cross biases.
2020      * @throws IllegalArgumentException if either provided bias matrix is not 3x1,
2021      *                                  scaling and coupling error matrix is not 3x3
2022      *                                  or g-dependant cross biases is not 3x3.
2023      */
2024     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
2025             final Collection<StandardDeviationFrameBodyKinematics> measurements,
2026             final Matrix bias, final Matrix initialMg, final Matrix initialGg) {
2027         this(bias, initialMg, initialGg);
2028         this.measurements = measurements;
2029     }
2030 
2031     /**
2032      * Constructor.
2033      *
2034      * @param measurements collection of body kinematics measurements with standard
2035      *                     deviations taken at different frames (positions, orientations
2036      *                     and velocities).
2037      * @param bias         known bias expressed in radians per second (rad/s). This must
2038      *                     be 3x1.
2039      * @param initialMg    initial scale factors and cross coupling errors matrix.
2040      * @param initialGg    initial G-dependent cross biases.
2041      * @param listener     listener to handle events raised by this calibrator.
2042      * @throws IllegalArgumentException if either provided bias matrix is not 3x1,
2043      *                                  scaling and coupling error matrix is not 3x3
2044      *                                  or g-dependant cross biases is not 3x3.
2045      */
2046     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
2047             final Collection<StandardDeviationFrameBodyKinematics> measurements,
2048             final Matrix bias, final Matrix initialMg, final Matrix initialGg,
2049             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
2050         this(measurements, bias, initialMg, initialGg);
2051         this.listener = listener;
2052     }
2053 
2054     /**
2055      * Constructor.
2056      *
2057      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
2058      *                       accelerometer and gyroscope.
2059      * @param bias           known bias expressed in radians per second (rad/s). This must
2060      *                       be 3x1.
2061      * @param initialMg      initial scale factors and cross coupling errors matrix.
2062      * @param initialGg      initial G-dependent cross biases.
2063      * @throws IllegalArgumentException if either provided bias matrix is not 3x1,
2064      *                                  scaling and coupling error matrix is not 3x3
2065      *                                  or g-dependant cross biases is not 3x3.
2066      */
2067     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
2068             final boolean commonAxisUsed, final Matrix bias, final Matrix initialMg, final Matrix initialGg) {
2069         this(bias, initialMg, initialGg);
2070         this.commonAxisUsed = commonAxisUsed;
2071     }
2072 
2073     /**
2074      * Constructor.
2075      *
2076      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
2077      *                       accelerometer and gyroscope.
2078      * @param bias           known bias expressed in radians per second (rad/s). This must
2079      *                       be 3x1.
2080      * @param initialMg      initial scale factors and cross coupling errors matrix.
2081      * @param initialGg      initial G-dependent cross biases.
2082      * @param listener       listener to handle events raised by this calibrator.
2083      * @throws IllegalArgumentException if either provided bias matrix is not 3x1,
2084      *                                  scaling and coupling error matrix is not 3x3
2085      *                                  or g-dependant cross biases is not 3x3.
2086      */
2087     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
2088             final boolean commonAxisUsed, final Matrix bias, final Matrix initialMg, final Matrix initialGg,
2089             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
2090         this(commonAxisUsed, bias, initialMg, initialGg);
2091         this.listener = listener;
2092     }
2093 
2094     /**
2095      * Constructor.
2096      *
2097      * @param measurements   collection of body kinematics measurements with standard
2098      *                       deviations taken at different frames (positions, orientations
2099      *                       and velocities).
2100      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
2101      *                       accelerometer and gyroscope.
2102      * @param bias           known bias expressed in radians per second (rad/s). This must
2103      *                       be 3x1.
2104      * @param initialMg      initial scale factors and cross coupling errors matrix.
2105      * @param initialGg      initial G-dependent cross biases.
2106      * @throws IllegalArgumentException if either provided bias matrix is not 3x1,
2107      *                                  scaling and coupling error matrix is not 3x3
2108      *                                  or g-dependant cross biases is not 3x3.
2109      */
2110     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
2111             final Collection<StandardDeviationFrameBodyKinematics> measurements,
2112             final boolean commonAxisUsed, final Matrix bias, final Matrix initialMg, final Matrix initialGg) {
2113         this(commonAxisUsed, bias, initialMg, initialGg);
2114         this.measurements = measurements;
2115     }
2116 
2117     /**
2118      * Constructor.
2119      *
2120      * @param measurements   collection of body kinematics measurements with standard
2121      *                       deviations taken at different frames (positions, orientations
2122      *                       and velocities).
2123      * @param commonAxisUsed indicates whether z-axis is assumed to be common for
2124      *                       accelerometer and gyroscope.
2125      * @param bias           known bias expressed in radians per second (rad/s). This must
2126      *                       be 3x1.
2127      * @param initialMg      initial scale factors and cross coupling errors matrix.
2128      * @param initialGg      initial G-dependent cross biases.
2129      * @param listener       listener to handle events raised by this calibrator.
2130      * @throws IllegalArgumentException if either provided bias matrix is not 3x1,
2131      *                                  scaling and coupling error matrix is not 3x3
2132      *                                  or g-dependant cross biases is not 3x3.
2133      */
2134     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibrator(
2135             final Collection<StandardDeviationFrameBodyKinematics> measurements, final boolean commonAxisUsed,
2136             final Matrix bias, final Matrix initialMg, final Matrix initialGg,
2137             final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener) {
2138         this(measurements, commonAxisUsed, bias, initialMg, initialGg);
2139         this.listener = listener;
2140     }
2141 
2142     /**
2143      * Gets initial x scaling factor.
2144      *
2145      * @return initial x scaling factor.
2146      */
2147     @Override
2148     public double getInitialSx() {
2149         return initialSx;
2150     }
2151 
2152     /**
2153      * Sets initial x scaling factor.
2154      *
2155      * @param initialSx initial x scaling factor.
2156      * @throws LockedException if calibrator is currently running.
2157      */
2158     @Override
2159     public void setInitialSx(final double initialSx) throws LockedException {
2160         if (running) {
2161             throw new LockedException();
2162         }
2163         this.initialSx = initialSx;
2164     }
2165 
2166     /**
2167      * Gets initial y scaling factor.
2168      *
2169      * @return initial y scaling factor.
2170      */
2171     @Override
2172     public double getInitialSy() {
2173         return initialSy;
2174     }
2175 
2176     /**
2177      * Sets initial y scaling factor.
2178      *
2179      * @param initialSy initial y scaling factor.
2180      * @throws LockedException if calibrator is currently running.
2181      */
2182     @Override
2183     public void setInitialSy(final double initialSy) throws LockedException {
2184         if (running) {
2185             throw new LockedException();
2186         }
2187         this.initialSy = initialSy;
2188     }
2189 
2190     /**
2191      * Gets initial z scaling factor.
2192      *
2193      * @return initial z scaling factor.
2194      */
2195     @Override
2196     public double getInitialSz() {
2197         return initialSz;
2198     }
2199 
2200     /**
2201      * Sets initial z scaling factor.
2202      *
2203      * @param initialSz initial z scaling factor.
2204      * @throws LockedException if calibrator is currently running.
2205      */
2206     @Override
2207     public void setInitialSz(final double initialSz) throws LockedException {
2208         if (running) {
2209             throw new LockedException();
2210         }
2211         this.initialSz = initialSz;
2212     }
2213 
2214     /**
2215      * Gets initial x-y cross coupling error.
2216      *
2217      * @return initial x-y cross coupling error.
2218      */
2219     @Override
2220     public double getInitialMxy() {
2221         return initialMxy;
2222     }
2223 
2224     /**
2225      * Sets initial x-y cross coupling error.
2226      *
2227      * @param initialMxy initial x-y cross coupling error.
2228      * @throws LockedException if calibrator is currently running.
2229      */
2230     @Override
2231     public void setInitialMxy(final double initialMxy) throws LockedException {
2232         if (running) {
2233             throw new LockedException();
2234         }
2235         this.initialMxy = initialMxy;
2236     }
2237 
2238     /**
2239      * Gets initial x-z cross coupling error.
2240      *
2241      * @return initial x-z cross coupling error.
2242      */
2243     @Override
2244     public double getInitialMxz() {
2245         return initialMxz;
2246     }
2247 
2248     /**
2249      * Sets initial x-z cross coupling error.
2250      *
2251      * @param initialMxz initial x-z cross coupling error.
2252      * @throws LockedException if calibrator is currently running.
2253      */
2254     @Override
2255     public void setInitialMxz(final double initialMxz) throws LockedException {
2256         if (running) {
2257             throw new LockedException();
2258         }
2259         this.initialMxz = initialMxz;
2260     }
2261 
2262     /**
2263      * Gets initial y-x cross coupling error.
2264      *
2265      * @return initial y-x cross coupling error.
2266      */
2267     @Override
2268     public double getInitialMyx() {
2269         return initialMyx;
2270     }
2271 
2272     /**
2273      * Sets initial y-x cross coupling error.
2274      *
2275      * @param initialMyx initial y-x cross coupling error.
2276      * @throws LockedException if calibrator is currently running.
2277      */
2278     @Override
2279     public void setInitialMyx(final double initialMyx) throws LockedException {
2280         if (running) {
2281             throw new LockedException();
2282         }
2283         this.initialMyx = initialMyx;
2284     }
2285 
2286     /**
2287      * Gets initial y-z cross coupling error.
2288      *
2289      * @return initial y-z cross coupling error.
2290      */
2291     @Override
2292     public double getInitialMyz() {
2293         return initialMyz;
2294     }
2295 
2296     /**
2297      * Sets initial y-z cross coupling error.
2298      *
2299      * @param initialMyz initial y-z cross coupling error.
2300      * @throws LockedException if calibrator is currently running.
2301      */
2302     @Override
2303     public void setInitialMyz(final double initialMyz) throws LockedException {
2304         if (running) {
2305             throw new LockedException();
2306         }
2307         this.initialMyz = initialMyz;
2308     }
2309 
2310     /**
2311      * Gets initial z-x cross coupling error.
2312      *
2313      * @return initial z-x cross coupling error.
2314      */
2315     @Override
2316     public double getInitialMzx() {
2317         return initialMzx;
2318     }
2319 
2320     /**
2321      * Sets initial z-x cross coupling error.
2322      *
2323      * @param initialMzx initial z-x cross coupling error.
2324      * @throws LockedException if calibrator is currently running.
2325      */
2326     @Override
2327     public void setInitialMzx(final double initialMzx) throws LockedException {
2328         if (running) {
2329             throw new LockedException();
2330         }
2331         this.initialMzx = initialMzx;
2332     }
2333 
2334     /**
2335      * Gets initial z-y cross coupling error.
2336      *
2337      * @return initial z-y cross coupling error.
2338      */
2339     @Override
2340     public double getInitialMzy() {
2341         return initialMzy;
2342     }
2343 
2344     /**
2345      * Sets initial z-y cross coupling error.
2346      *
2347      * @param initialMzy initial z-y cross coupling error.
2348      * @throws LockedException if calibrator is currently running.
2349      */
2350     @Override
2351     public void setInitialMzy(final double initialMzy) throws LockedException {
2352         if (running) {
2353             throw new LockedException();
2354         }
2355         this.initialMzy = initialMzy;
2356     }
2357 
2358     /**
2359      * Sets initial scaling factors.
2360      *
2361      * @param initialSx initial x scaling factor.
2362      * @param initialSy initial y scaling factor.
2363      * @param initialSz initial z scaling factor.
2364      * @throws LockedException if calibrator is currently running.
2365      */
2366     @Override
2367     public void setInitialScalingFactors(
2368             final double initialSx, final double initialSy, final double initialSz) throws LockedException {
2369         if (running) {
2370             throw new LockedException();
2371         }
2372         this.initialSx = initialSx;
2373         this.initialSy = initialSy;
2374         this.initialSz = initialSz;
2375     }
2376 
2377     /**
2378      * Sets initial cross coupling errors.
2379      *
2380      * @param initialMxy initial x-y cross coupling error.
2381      * @param initialMxz initial x-z cross coupling error.
2382      * @param initialMyx initial y-x cross coupling error.
2383      * @param initialMyz initial y-z cross coupling error.
2384      * @param initialMzx initial z-x cross coupling error.
2385      * @param initialMzy initial z-y cross coupling error.
2386      * @throws LockedException if calibrator is currently running.
2387      */
2388     @Override
2389     public void setInitialCrossCouplingErrors(
2390             final double initialMxy, final double initialMxz,
2391             final double initialMyx, final double initialMyz,
2392             final double initialMzx, final double initialMzy) throws LockedException {
2393         if (running) {
2394             throw new LockedException();
2395         }
2396         this.initialMxy = initialMxy;
2397         this.initialMxz = initialMxz;
2398         this.initialMyx = initialMyx;
2399         this.initialMyz = initialMyz;
2400         this.initialMzx = initialMzx;
2401         this.initialMzy = initialMzy;
2402     }
2403 
2404     /**
2405      * Sets initial scaling factors and cross coupling errors.
2406      *
2407      * @param initialSx  initial x scaling factor.
2408      * @param initialSy  initial y scaling factor.
2409      * @param initialSz  initial z scaling factor.
2410      * @param initialMxy initial x-y cross coupling error.
2411      * @param initialMxz initial x-z cross coupling error.
2412      * @param initialMyx initial y-x cross coupling error.
2413      * @param initialMyz initial y-z cross coupling error.
2414      * @param initialMzx initial z-x cross coupling error.
2415      * @param initialMzy initial z-y cross coupling error.
2416      * @throws LockedException if calibrator is currently running.
2417      */
2418     @Override
2419     public void setInitialScalingFactorsAndCrossCouplingErrors(
2420             final double initialSx, final double initialSy, final double initialSz,
2421             final double initialMxy, final double initialMxz, final double initialMyx,
2422             final double initialMyz, final double initialMzx, final double initialMzy) throws LockedException {
2423         if (running) {
2424             throw new LockedException();
2425         }
2426         setInitialScalingFactors(initialSx, initialSy, initialSz);
2427         setInitialCrossCouplingErrors(initialMxy, initialMxz, initialMyx, initialMyz, initialMzx, initialMzy);
2428     }
2429 
2430     /**
2431      * Gets initial scale factors and cross coupling errors matrix.
2432      *
2433      * @return initial scale factors and cross coupling errors matrix.
2434      */
2435     @Override
2436     public Matrix getInitialMg() {
2437         Matrix result;
2438         try {
2439             result = new Matrix(BodyKinematics.COMPONENTS, BodyKinematics.COMPONENTS);
2440             getInitialMg(result);
2441         } catch (final WrongSizeException ignore) {
2442             // never happens
2443             result = null;
2444         }
2445         return result;
2446     }
2447 
2448     /**
2449      * Gets initial scale factors and cross coupling errors matrix.
2450      *
2451      * @param result instance where data will be stored.
2452      * @throws IllegalArgumentException if provided matrix is not 3x3.
2453      */
2454     @Override
2455     public void getInitialMg(final Matrix result) {
2456         if (result.getRows() != BodyKinematics.COMPONENTS || result.getColumns() != BodyKinematics.COMPONENTS) {
2457             throw new IllegalArgumentException();
2458         }
2459         result.setElementAtIndex(0, initialSx);
2460         result.setElementAtIndex(1, initialMyx);
2461         result.setElementAtIndex(2, initialMzx);
2462 
2463         result.setElementAtIndex(3, initialMxy);
2464         result.setElementAtIndex(4, initialSy);
2465         result.setElementAtIndex(5, initialMzy);
2466 
2467         result.setElementAtIndex(6, initialMxz);
2468         result.setElementAtIndex(7, initialMyz);
2469         result.setElementAtIndex(8, initialSz);
2470     }
2471 
2472     /**
2473      * Sets initial scale factors and cross coupling errors matrix.
2474      *
2475      * @param initialMg initial scale factors and cross coupling errors matrix.
2476      * @throws IllegalArgumentException if provided matrix is not 3x3.
2477      * @throws LockedException          if calibrator is currently running.
2478      */
2479     @Override
2480     public void setInitialMg(final Matrix initialMg) throws LockedException {
2481         if (running) {
2482             throw new LockedException();
2483         }
2484         if (initialMg.getRows() != BodyKinematics.COMPONENTS || initialMg.getColumns() != BodyKinematics.COMPONENTS) {
2485             throw new IllegalArgumentException();
2486         }
2487 
2488         initialSx = initialMg.getElementAtIndex(0);
2489         initialMyx = initialMg.getElementAtIndex(1);
2490         initialMzx = initialMg.getElementAtIndex(2);
2491 
2492         initialMxy = initialMg.getElementAtIndex(3);
2493         initialSy = initialMg.getElementAtIndex(4);
2494         initialMzy = initialMg.getElementAtIndex(5);
2495 
2496         initialMxz = initialMg.getElementAtIndex(6);
2497         initialMyz = initialMg.getElementAtIndex(7);
2498         initialSz = initialMg.getElementAtIndex(8);
2499     }
2500 
2501     /**
2502      * Gets initial G-dependent cross biases introduced on the gyroscope by the
2503      * specific forces sensed by the accelerometer.
2504      *
2505      * @return a 3x3 matrix containing initial g-dependent cross biases.
2506      */
2507     @Override
2508     public Matrix getInitialGg() {
2509         return new Matrix(initialGg);
2510     }
2511 
2512     /**
2513      * Gets initial G-dependent cross biases introduced on the gyroscope by the
2514      * specific forces sensed by the accelerometer.
2515      *
2516      * @param result instance where data will be stored.
2517      * @throws IllegalArgumentException if provided matrix is not 3x3.
2518      */
2519     @Override
2520     public void getInitialGg(final Matrix result) {
2521         if (result.getRows() != BodyKinematics.COMPONENTS || result.getColumns() != BodyKinematics.COMPONENTS) {
2522             throw new IllegalArgumentException();
2523         }
2524 
2525         result.copyFrom(initialGg);
2526     }
2527 
2528     /**
2529      * Sets initial G-dependent cross biases introduced on the gyroscope by the
2530      * specific forces sensed by the accelerometer.
2531      *
2532      * @param initialGg g-dependent cross biases.
2533      * @throws LockedException          if calibrator is currently running.
2534      * @throws IllegalArgumentException if provided matrix is not 3x3.
2535      */
2536     @Override
2537     public void setInitialGg(final Matrix initialGg) throws LockedException {
2538         if (running) {
2539             throw new LockedException();
2540         }
2541 
2542         if (initialGg.getRows() != BodyKinematics.COMPONENTS || initialGg.getColumns() != BodyKinematics.COMPONENTS) {
2543             throw new IllegalArgumentException();
2544         }
2545 
2546         initialGg.copyTo(this.initialGg);
2547     }
2548 
2549     /**
2550      * Gets a collection of body kinematics measurements taken at different
2551      * frames (positions, orientations and velocities).
2552      * If a single device IMU needs to be calibrated, typically all measurements are
2553      * taken at the same position, with zero velocity and multiple orientations.
2554      * However, if we just want to calibrate a given IMU model (e.g. obtain
2555      * an average and less precise calibration for the IMU of a given phone model),
2556      * we could take measurements collected throughout the planet at multiple positions
2557      * while the phone remains static (e.g. while charging), hence each measurement
2558      * position will change, velocity will remain zero and orientation will be
2559      * typically constant at horizontal orientation while the phone remains on a
2560      * flat surface.
2561      *
2562      * @return a collection of body kinematics measurements taken at different
2563      * frames (positions, orientations and velocities).
2564      */
2565     @Override
2566     public Collection<StandardDeviationFrameBodyKinematics> getMeasurements() {
2567         return measurements;
2568     }
2569 
2570     /**
2571      * Sets a collection of body kinematics measurements taken at different
2572      * frames (positions, orientations and velocities).
2573      * If a single device IMU needs to be calibrated, typically all measurements are
2574      * taken at the same position, with zero velocity and multiple orientations.
2575      * However, if we just want to calibrate the a given IMU model (e.g. obtain
2576      * an average and less precise calibration for the IMU of a given phone model),
2577      * we could take measurements collected throughout the planet at multiple positions
2578      * while the phone remains static (e.g. while charging), hence each measurement
2579      * position will change, velocity will remain zero and orientation will be
2580      * typically constant at horizontal orientation while the phone remains on a
2581      * flat surface.
2582      *
2583      * @param measurements collection of body kinematics measurements taken at different
2584      *                     frames (positions, orientations and velocities).
2585      * @throws LockedException if calibrator is currently running.
2586      */
2587     @Override
2588     public void setMeasurements(
2589             final Collection<? extends StandardDeviationFrameBodyKinematics> measurements) throws LockedException {
2590         if (running) {
2591             throw new LockedException();
2592         }
2593         //noinspection unchecked
2594         this.measurements = (Collection<StandardDeviationFrameBodyKinematics>) measurements;
2595     }
2596 
2597     /**
2598      * Indicates the type of measurement or sequence used by this calibrator.
2599      *
2600      * @return type of measurement or sequence used by this calibrator.
2601      */
2602     @Override
2603     public GyroscopeCalibratorMeasurementOrSequenceType getMeasurementOrSequenceType() {
2604         return GyroscopeCalibratorMeasurementOrSequenceType.STANDARD_DEVIATION_FRAME_BODY_KINEMATICS_MEASUREMENT;
2605     }
2606 
2607     /**
2608      * Indicates whether this calibrator requires ordered measurements or sequences
2609      * in a list or not.
2610      *
2611      * @return true if measurements or sequences must be ordered, false otherwise.
2612      */
2613     @Override
2614     public boolean isOrderedMeasurementsOrSequencesRequired() {
2615         return false;
2616     }
2617 
2618     /**
2619      * Indicates whether this calibrator requires quality scores for each
2620      * measurement/sequence or not.
2621      *
2622      * @return true if quality scores are required, false otherwise.
2623      */
2624     @Override
2625     public boolean isQualityScoresRequired() {
2626         return false;
2627     }
2628 
2629     /**
2630      * Indicates whether z-axis is assumed to be common for accelerometer and
2631      * gyroscope.
2632      * When enabled, this eliminates 3 variables from Mg matrix.
2633      *
2634      * @return true if z-axis is assumed to be common for accelerometer and gyroscope,
2635      * false otherwise.
2636      */
2637     @Override
2638     public boolean isCommonAxisUsed() {
2639         return commonAxisUsed;
2640     }
2641 
2642     /**
2643      * Specifies whether z-axis is assumed to be common for accelerometer and
2644      * gyroscope.
2645      * When enabled, this eliminates 3 variables from Mg matrix.
2646      *
2647      * @param commonAxisUsed true if z-axis is assumed to be common for accelerometer
2648      *                       and gyroscope, false otherwise.
2649      * @throws LockedException if calibrator is currently running.
2650      */
2651     @Override
2652     public void setCommonAxisUsed(final boolean commonAxisUsed) throws LockedException {
2653         if (running) {
2654             throw new LockedException();
2655         }
2656 
2657         this.commonAxisUsed = commonAxisUsed;
2658     }
2659 
2660     /**
2661      * Gets listener to handle events raised by this calibrator.
2662      *
2663      * @return listener to handle events raised by this calibrator.
2664      */
2665     @Override
2666     public KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener getListener() {
2667         return listener;
2668     }
2669 
2670     /**
2671      * Sets listener to handle events raised by this calibrator.
2672      *
2673      * @param listener listener to handle events raised by this calibrator.
2674      * @throws LockedException if calibrator is currently running.
2675      */
2676     @Override
2677     public void setListener(final KnownBiasAndFrameGyroscopeNonLinearLeastSquaresCalibratorListener listener)
2678             throws LockedException {
2679         if (running) {
2680             throw new LockedException();
2681         }
2682 
2683         this.listener = listener;
2684     }
2685 
2686     /**
2687      * Gets known x coordinate of gyroscope bias expressed in radians per second
2688      * (rad/s).
2689      *
2690      * @return x coordinate of gyroscope bias.
2691      */
2692     @Override
2693     public double getBiasX() {
2694         return biasX;
2695     }
2696 
2697     /**
2698      * Sets known x coordinate of gyroscope bias expressed in radians per second
2699      * (rad/s).
2700      *
2701      * @param biasX x coordinate of gyroscope bias.
2702      * @throws LockedException if calibrator is currently running.
2703      */
2704     @Override
2705     public void setBiasX(final double biasX) throws LockedException {
2706         if (running) {
2707             throw new LockedException();
2708         }
2709         this.biasX = biasX;
2710     }
2711 
2712     /**
2713      * Gets known y coordinate of gyroscope bias expressed in radians per second
2714      * (rad/s).
2715      *
2716      * @return y coordinate of gyroscope bias.
2717      */
2718     @Override
2719     public double getBiasY() {
2720         return biasY;
2721     }
2722 
2723     /**
2724      * Sets known y coordinate of gyroscope bias expressed in radians per second
2725      * (rad/s).
2726      *
2727      * @param biasY y coordinate of gyroscope bias.
2728      * @throws LockedException if calibrator is currently running.
2729      */
2730     @Override
2731     public void setBiasY(final double biasY) throws LockedException {
2732         if (running) {
2733             throw new LockedException();
2734         }
2735         this.biasY = biasY;
2736     }
2737 
2738     /**
2739      * Gets known z coordinate of gyroscope bias expressed in radians per second
2740      * (rad/s).
2741      *
2742      * @return z coordinate of gyroscope bias.
2743      */
2744     @Override
2745     public double getBiasZ() {
2746         return biasZ;
2747     }
2748 
2749     /**
2750      * Sets known z coordinate of gyroscope bias expressed in radians per second
2751      * (rad/s).
2752      *
2753      * @param biasZ z coordinate of gyroscope bias.
2754      * @throws LockedException if calibrator is currently running.
2755      */
2756     @Override
2757     public void setBiasZ(final double biasZ) throws LockedException {
2758         if (running) {
2759             throw new LockedException();
2760         }
2761         this.biasZ = biasZ;
2762     }
2763 
2764     /**
2765      * Gets known x coordinate of gyroscope bias.
2766      *
2767      * @return x coordinate of gyroscope bias.
2768      */
2769     @Override
2770     public AngularSpeed getBiasAngularSpeedX() {
2771         return new AngularSpeed(biasX, AngularSpeedUnit.RADIANS_PER_SECOND);
2772     }
2773 
2774     /**
2775      * Gets known x coordinate of gyroscope bias.
2776      *
2777      * @param result instance where result data will be stored.
2778      */
2779     @Override
2780     public void getBiasAngularSpeedX(final AngularSpeed result) {
2781         result.setValue(biasX);
2782         result.setUnit(AngularSpeedUnit.RADIANS_PER_SECOND);
2783     }
2784 
2785     /**
2786      * Sets known x coordinate of gyroscope bias.
2787      *
2788      * @param biasX x coordinate of gyroscope bias.
2789      * @throws LockedException if calibrator is currently running.
2790      */
2791     @Override
2792     public void setBiasX(final AngularSpeed biasX) throws LockedException {
2793         if (running) {
2794             throw new LockedException();
2795         }
2796 
2797         this.biasX = convertAngularSpeed(biasX);
2798     }
2799 
2800     /**
2801      * Gets known y coordinate of gyroscope bias.
2802      *
2803      * @return y coordinate of gyroscope bias.
2804      */
2805     @Override
2806     public AngularSpeed getBiasAngularSpeedY() {
2807         return new AngularSpeed(biasY, AngularSpeedUnit.RADIANS_PER_SECOND);
2808     }
2809 
2810     /**
2811      * Gets known y coordinate of gyroscope bias.
2812      *
2813      * @param result instance where result data will be stored.
2814      */
2815     @Override
2816     public void getBiasAngularSpeedY(final AngularSpeed result) {
2817         result.setValue(biasY);
2818         result.setUnit(AngularSpeedUnit.RADIANS_PER_SECOND);
2819     }
2820 
2821     /**
2822      * Sets known y coordinate of gyroscope bias.
2823      *
2824      * @param biasY y coordinate of gyroscope bias.
2825      * @throws LockedException if calibrator is currently running.
2826      */
2827     @Override
2828     public void setBiasY(final AngularSpeed biasY) throws LockedException {
2829         if (running) {
2830             throw new LockedException();
2831         }
2832 
2833         this.biasY = convertAngularSpeed(biasY);
2834     }
2835 
2836     /**
2837      * Gets known z coordinate of gyroscope bias.
2838      *
2839      * @return z coordinate of gyroscope bias.
2840      */
2841     @Override
2842     public AngularSpeed getBiasAngularSpeedZ() {
2843         return new AngularSpeed(biasZ, AngularSpeedUnit.RADIANS_PER_SECOND);
2844     }
2845 
2846     /**
2847      * Gets known z coordinate of gyroscope bias.
2848      *
2849      * @param result instance where result data will be stored.
2850      */
2851     @Override
2852     public void getBiasAngularSpeedZ(final AngularSpeed result) {
2853         result.setValue(biasZ);
2854         result.setUnit(AngularSpeedUnit.RADIANS_PER_SECOND);
2855     }
2856 
2857     /**
2858      * Sets known z coordinate of gyroscope bias.
2859      *
2860      * @param biasZ z coordinate of gyroscope bias.
2861      * @throws LockedException if calibrator is currently running.
2862      */
2863     @Override
2864     public void setBiasZ(final AngularSpeed biasZ) throws LockedException {
2865         if (running) {
2866             throw new LockedException();
2867         }
2868 
2869         this.biasZ = convertAngularSpeed(biasZ);
2870     }
2871 
2872     /**
2873      * Sets known gyroscope bias coordinates expressed in radians per second
2874      * (rad/s).
2875      *
2876      * @param biasX x coordinate of gyroscope bias.
2877      * @param biasY y coordinate of gyroscope bias.
2878      * @param biasZ z coordinate of gyroscope bias.
2879      * @throws LockedException if calibrator is currently running.
2880      */
2881     @Override
2882     public void setBiasCoordinates(final double biasX, final double biasY, final double biasZ) throws LockedException {
2883         if (running) {
2884             throw new LockedException();
2885         }
2886 
2887         this.biasX = biasX;
2888         this.biasY = biasY;
2889         this.biasZ = biasZ;
2890     }
2891 
2892     /**
2893      * Sets known gyroscope bias coordinates.
2894      *
2895      * @param biasX x coordinate of gyroscope bias.
2896      * @param biasY y coordinate of gyroscope bias.
2897      * @param biasZ z coordinate of gyroscope bias.
2898      * @throws LockedException if calibrator is currently running.
2899      */
2900     @Override
2901     public void setBiasCoordinates(
2902             final AngularSpeed biasX, final AngularSpeed biasY, final AngularSpeed biasZ) throws LockedException {
2903         if (running) {
2904             throw new LockedException();
2905         }
2906 
2907         this.biasX = convertAngularSpeed(biasX);
2908         this.biasY = convertAngularSpeed(biasY);
2909         this.biasZ = convertAngularSpeed(biasZ);
2910     }
2911 
2912     /**
2913      * Gets known gyroscope bias.
2914      *
2915      * @return known gyroscope bias.
2916      */
2917     public AngularSpeedTriad getBiasAsTriad() {
2918         return new AngularSpeedTriad(AngularSpeedUnit.RADIANS_PER_SECOND, biasX, biasY, biasZ);
2919     }
2920 
2921     /**
2922      * Gets known gyroscope bias.
2923      *
2924      * @param result instance where result will be stored.
2925      */
2926     public void getBiasAsTriad(final AngularSpeedTriad result) {
2927         result.setValueCoordinatesAndUnit(biasX, biasY, biasZ, AngularSpeedUnit.RADIANS_PER_SECOND);
2928     }
2929 
2930     /**
2931      * Sets known gyroscope bias.
2932      *
2933      * @param bias gyroscope bias to be set.
2934      * @throws LockedException if calibrator is currently running.
2935      */
2936     public void setBias(final AngularSpeedTriad bias) throws LockedException {
2937         if (running) {
2938             throw new LockedException();
2939         }
2940 
2941         biasX = convertAngularSpeed(bias.getValueX(), bias.getUnit());
2942         biasY = convertAngularSpeed(bias.getValueY(), bias.getUnit());
2943         biasZ = convertAngularSpeed(bias.getValueZ(), bias.getUnit());
2944     }
2945 
2946     /**
2947      * Gets known gyroscope bias as an array.
2948      * Array values are expressed in radians per second (rad/s).
2949      *
2950      * @return array containing coordinate of known bias.
2951      */
2952     @Override
2953     public double[] getBias() {
2954         final var result = new double[BodyKinematics.COMPONENTS];
2955         getBias(result);
2956         return result;
2957     }
2958 
2959     /**
2960      * Gets known gyroscope bias as an array.
2961      * Array values are expressed in radians per second (rad/s).
2962      *
2963      * @param result instance where result data will be copied to.
2964      * @throws IllegalArgumentException if provided array does not have length 3.
2965      */
2966     @Override
2967     public void getBias(final double[] result) {
2968         if (result.length != BodyKinematics.COMPONENTS) {
2969             throw new IllegalArgumentException();
2970         }
2971         result[0] = biasX;
2972         result[1] = biasY;
2973         result[2] = biasZ;
2974     }
2975 
2976     /**
2977      * Sets known gyroscope bias as an array.
2978      * Array values are expressed in radians per second (rad/s).
2979      *
2980      * @param bias known gyroscope bias.
2981      * @throws LockedException          if calibrator is currently running.
2982      * @throws IllegalArgumentException if provided array does not have length 3.
2983      */
2984     @Override
2985     public void setBias(final double[] bias) throws LockedException {
2986         if (running) {
2987             throw new LockedException();
2988         }
2989 
2990         if (bias.length != BodyKinematics.COMPONENTS) {
2991             throw new IllegalArgumentException();
2992         }
2993         biasX = bias[0];
2994         biasY = bias[1];
2995         biasZ = bias[2];
2996     }
2997 
2998     /**
2999      * Gets known gyroscope bias as a column matrix.
3000      *
3001      * @return known gyroscope bias as a column matrix.
3002      */
3003     @Override
3004     public Matrix getBiasAsMatrix() {
3005         Matrix result;
3006         try {
3007             result = new Matrix(BodyKinematics.COMPONENTS, 1);
3008             getBiasAsMatrix(result);
3009         } catch (final WrongSizeException ignore) {
3010             // never happens
3011             result = null;
3012         }
3013         return result;
3014     }
3015 
3016     /**
3017      * Gets known gyroscope bias as a column matrix.
3018      *
3019      * @param result instance where result data will be copied to.
3020      * @throws IllegalArgumentException if provided matrix is not 3x1.
3021      */
3022     @Override
3023     public void getBiasAsMatrix(final Matrix result) {
3024         if (result.getRows() != BodyKinematics.COMPONENTS || result.getColumns() != 1) {
3025             throw new IllegalArgumentException();
3026         }
3027         result.setElementAtIndex(0, biasX);
3028         result.setElementAtIndex(1, biasY);
3029         result.setElementAtIndex(2, biasZ);
3030     }
3031 
3032     /**
3033      * Sets known gyroscope bias as a column matrix.
3034      *
3035      * @param bias gyroscope bias to be set.
3036      * @throws LockedException          if calibrator is currently running.
3037      * @throws IllegalArgumentException if provided matrix is not 3x1.
3038      */
3039     @Override
3040     public void setBias(final Matrix bias) throws LockedException {
3041         if (running) {
3042             throw new LockedException();
3043         }
3044         if (bias.getRows() != BodyKinematics.COMPONENTS || bias.getColumns() != 1) {
3045             throw new IllegalArgumentException();
3046         }
3047 
3048         biasX = bias.getElementAtIndex(0);
3049         biasY = bias.getElementAtIndex(1);
3050         biasZ = bias.getElementAtIndex(2);
3051     }
3052 
3053     /**
3054      * Gets minimum number of required measurements.
3055      *
3056      * @return minimum number of required measurements.
3057      */
3058     @Override
3059     public int getMinimumRequiredMeasurementsOrSequences() {
3060         return MINIMUM_MEASUREMENTS;
3061     }
3062 
3063     /**
3064      * Indicates whether calibrator is ready to start the calibration.
3065      *
3066      * @return true if calibrator is ready, false otherwise.
3067      */
3068     @Override
3069     public boolean isReady() {
3070         return measurements != null && measurements.size() >= MINIMUM_MEASUREMENTS;
3071     }
3072 
3073     /**
3074      * Indicates whether calibrator is currently running or not.
3075      *
3076      * @return true if calibrator is running, false otherwise.
3077      */
3078     @Override
3079     public boolean isRunning() {
3080         return running;
3081     }
3082 
3083     /**
3084      * Estimates gyroscope calibration parameters containing bias, scale factors,
3085      * cross-coupling errors and g-dependant cross biases.
3086      *
3087      * @throws LockedException      if calibrator is currently running.
3088      * @throws NotReadyException    if calibrator is not ready.
3089      * @throws CalibrationException if calibration fails for numerical reasons.
3090      */
3091     @Override
3092     public void calibrate() throws LockedException, NotReadyException, CalibrationException {
3093         if (running) {
3094             throw new LockedException();
3095         }
3096 
3097         if (!isReady()) {
3098             throw new NotReadyException();
3099         }
3100 
3101         try {
3102             running = true;
3103 
3104             if (listener != null) {
3105                 listener.onCalibrateStart(this);
3106             }
3107 
3108             if (commonAxisUsed) {
3109                 calibrateCommonAxis();
3110             } else {
3111                 calibrateGeneral();
3112             }
3113 
3114             if (listener != null) {
3115                 listener.onCalibrateEnd(this);
3116             }
3117 
3118         } catch (final AlgebraException | FittingException | com.irurueta.numerical.NotReadyException e) {
3119             throw new CalibrationException(e);
3120         } finally {
3121             running = false;
3122         }
3123     }
3124 
3125     /**
3126      * Gets estimated gyroscope scale factors and cross coupling errors.
3127      * This is the product of matrix Tg containing cross coupling errors and Kg
3128      * containing scaling factors.
3129      * So that:
3130      * <pre>
3131      *     Mg = [sx    mxy  mxz] = Tg*Kg
3132      *          [myx   sy   myz]
3133      *          [mzx   mzy  sz ]
3134      * </pre>
3135      * Where:
3136      * <pre>
3137      *     Kg = [sx 0   0 ]
3138      *          [0  sy  0 ]
3139      *          [0  0   sz]
3140      * </pre>
3141      * and
3142      * <pre>
3143      *     Tg = [1          -alphaXy    alphaXz ]
3144      *          [alphaYx    1           -alphaYz]
3145      *          [-alphaZx   alphaZy     1       ]
3146      * </pre>
3147      * Hence:
3148      * <pre>
3149      *     Mg = [sx    mxy  mxz] = Tg*Kg =  [sx             -sy * alphaXy   sz * alphaXz ]
3150      *          [myx   sy   myz]            [sx * alphaYx   sy              -sz * alphaYz]
3151      *          [mzx   mzy  sz ]            [-sx * alphaZx  sy * alphaZy    sz           ]
3152      * </pre>
3153      * This instance allows any 3x3 matrix however, typically alphaYx, alphaZx and alphaZy
3154      * are considered to be zero if the gyroscope z-axis is assumed to be the same
3155      * as the body z-axis. When this is assumed, myx = mzx = mzy = 0 and the Mg matrix
3156      * becomes upper diagonal:
3157      * <pre>
3158      *     Mg = [sx    mxy  mxz]
3159      *          [0     sy   myz]
3160      *          [0     0    sz ]
3161      * </pre>
3162      * Values of this matrix are unit-less.
3163      *
3164      * @return estimated gyroscope scale factors and cross coupling errors.
3165      */
3166     @Override
3167     public Matrix getEstimatedMg() {
3168         return estimatedMg;
3169     }
3170 
3171     /**
3172      * Gets estimated x-axis scale factor.
3173      *
3174      * @return estimated x-axis scale factor or null if not available.
3175      */
3176     @Override
3177     public Double getEstimatedSx() {
3178         return estimatedMg != null ? estimatedMg.getElementAt(0, 0) : null;
3179     }
3180 
3181     /**
3182      * Gets estimated y-axis scale factor.
3183      *
3184      * @return estimated y-axis scale factor or null if not available.
3185      */
3186     @Override
3187     public Double getEstimatedSy() {
3188         return estimatedMg != null ? estimatedMg.getElementAt(1, 1) : null;
3189     }
3190 
3191     /**
3192      * Gets estimated z-axis scale factor.
3193      *
3194      * @return estimated z-axis scale factor or null if not available.
3195      */
3196     @Override
3197     public Double getEstimatedSz() {
3198         return estimatedMg != null ? estimatedMg.getElementAt(2, 2) : null;
3199     }
3200 
3201     /**
3202      * Gets estimated x-y cross-coupling error.
3203      *
3204      * @return estimated x-y cross-coupling error or null if not available.
3205      */
3206     @Override
3207     public Double getEstimatedMxy() {
3208         return estimatedMg != null ? estimatedMg.getElementAt(0, 1) : null;
3209     }
3210 
3211     /**
3212      * Gets estimated x-z cross-coupling error.
3213      *
3214      * @return estimated x-z cross-coupling error or null if not available.
3215      */
3216     @Override
3217     public Double getEstimatedMxz() {
3218         return estimatedMg != null ? estimatedMg.getElementAt(0, 2) : null;
3219     }
3220 
3221     /**
3222      * Gets estimated y-x cross-coupling error.
3223      *
3224      * @return estimated y-x cross-coupling error or null if not available.
3225      */
3226     @Override
3227     public Double getEstimatedMyx() {
3228         return estimatedMg != null ? estimatedMg.getElementAt(1, 0) : null;
3229     }
3230 
3231     /**
3232      * Gets estimated y-z cross-coupling error.
3233      *
3234      * @return estimated y-z cross-coupling error or null if not available.
3235      */
3236     @Override
3237     public Double getEstimatedMyz() {
3238         return estimatedMg != null ? estimatedMg.getElementAt(1, 2) : null;
3239     }
3240 
3241     /**
3242      * Gets estimated z-x cross-coupling error.
3243      *
3244      * @return estimated z-x cross-coupling error or null if not available.
3245      */
3246     @Override
3247     public Double getEstimatedMzx() {
3248         return estimatedMg != null ? estimatedMg.getElementAt(2, 0) : null;
3249     }
3250 
3251     /**
3252      * Gets estimated z-y cross-coupling error.
3253      *
3254      * @return estimated z-y cross-coupling error or null if not available.
3255      */
3256     @Override
3257     public Double getEstimatedMzy() {
3258         return estimatedMg != null ? estimatedMg.getElementAt(2, 1) : null;
3259     }
3260 
3261     /**
3262      * Gets estimated G-dependent cross biases introduced on the gyroscope by the
3263      * specific forces sensed by the accelerometer.
3264      *
3265      * @return a 3x3 matrix containing g-dependent cross biases.
3266      */
3267     @Override
3268     public Matrix getEstimatedGg() {
3269         return estimatedGg;
3270     }
3271 
3272     /**
3273      * Gets estimated covariance matrix for estimated position.
3274      * Diagonal elements of the matrix contains variance for the following
3275      * parameters (following indicated order): sx, sy, sz, mxy, mxz, myx,
3276      * myz, mzx, mzy, gg11, gg21, gg31, gg12, gg22, gg32, gg13, gg23, gg33.
3277      *
3278      * @return estimated covariance matrix for estimated position.
3279      */
3280     @Override
3281     public Matrix getEstimatedCovariance() {
3282         return estimatedCovariance;
3283     }
3284 
3285     /**
3286      * Gets estimated chi square value.
3287      *
3288      * @return estimated chi square value.
3289      */
3290     @Override
3291     public double getEstimatedChiSq() {
3292         return estimatedChiSq;
3293     }
3294 
3295     /**
3296      * Gets estimated chi square degrees of freedom. Degrees of freedom is equal to the number of sampled data minus the
3297      * number of estimated parameters.
3298      *
3299      * @return estimated degrees of freedom of chi square value
3300      */
3301     @Override
3302     public int getEstimatedChiSqDegreesOfFreedom() {
3303         return estimatedChiSqDegreesOfFreedom;
3304     }
3305 
3306     /**
3307      * Gets estimated reduced chi square value. This is equal to estimated chi square value divided by its degrees of
3308      * freedom. Ideally this value should be close to 1.0, indicating that fit is optimal.
3309      * A value larger than 1.0 indicates that fit is not good or noise has been underestimated, and a value smaller than
3310      * 1.0 indicates that there is overfitting or noise has been overestimated.
3311      *
3312      * @return estimated reduced chi square value
3313      */
3314     @Override
3315     public double getEstimatedReducedChiSq() {
3316         return estimatedReducedChiSq;
3317     }
3318 
3319     /**
3320      * Gets estimated mean square error respect to provided measurements.
3321      *
3322      * @return estimated mean square error respect to provided measurements.
3323      */
3324     @Override
3325     public double getEstimatedMse() {
3326         return estimatedMse;
3327     }
3328 
3329     /**
3330      * Gets estimated probability of finding a smaller chi square value expressed as a value between 0.0 and 1.0. The
3331      * smaller the found chi square value is, the better the fit of the estimated parameters to the actual parameter.
3332      * Thus, the smaller the chance of finding a smaller chi square value, then the better the estimated fit is.
3333      *
3334      * @return estimated probability of finding a smaller chi square value.
3335      */
3336     @Override
3337     public double getEstimatedP() {
3338         return estimatedP;
3339     }
3340 
3341     /**
3342      * Gets estimated measure of quality of estimated fit as a value between 0.0 and 1.0. The larger the quality value
3343      * is, the better the fit that has been estimated.
3344      *
3345      * @return estimated measure of quality of estimated fit.
3346      */
3347     @Override
3348     public double getEstimatedQ() {
3349         return estimatedQ;
3350     }
3351 
3352     /**
3353      * Internal method to perform calibration when common z-axis is assumed for both
3354      * the accelerometer and gyroscope.
3355      *
3356      * @throws AlgebraException                         if there are numerical errors.
3357      * @throws FittingException                         if no convergence to solution is found.
3358      * @throws com.irurueta.numerical.NotReadyException if fitter is not ready.
3359      */
3360     private void calibrateCommonAxis() throws AlgebraException, FittingException,
3361             com.irurueta.numerical.NotReadyException {
3362 
3363         // The gyroscope model is:
3364         // Ωmeas = bg + (I + Mg) * Ωtrue + Gg * ftrue + w
3365 
3366         // Ideally a least squares solution tries to minimize noise component, so:
3367         // Ωmeas = bg + (I + Mg) * Ωtrue + Gg * ftrue
3368 
3369         // where myx = mzx = mzy = 0
3370 
3371         // Hence:
3372         // [Ωmeasx] = [bx] + ( [1   0   0] + [sx    mxy    mxz]) [Ωtruex] + [g11   g12   g13][ftruex]
3373         // [Ωmeasy]   [by]     [0   1   0]   [0     sy     myz]  [Ωtruey]   [g21   g22   g23][ftruey]
3374         // [Ωmeasz]   [bz]     [0   0   1]   [0     0      sz ]  [Ωtruez]   [g31   g32   g33][ftruez]
3375 
3376         // [Ωmeasx] = [bx] + ( [1+sx  mxy    mxz ]) [Ωtruex] + [g11   g12   g13][ftruex]
3377         // [Ωmeasy]   [by]     [0     1+sy   myz ]  [Ωtruey]   [g21   g22   g23][ftruey]
3378         // [Ωmeasz]   [bz]     [0     0      1+sz]  [Ωtruez]   [g31   g32   g33][ftruez]
3379 
3380         // Ωmeasx = bx + (1+sx) * Ωtruex + mxy * Ωtruey + mxz * Ωtruez + g11 * ftruex + g12 * ftruey + g13 * ftruez
3381         // Ωmeasy = by + (1+sy) * Ωtruey + myz * Ωtruez + g21 * ftruex * g22 * ftruey + g23 * ftruez
3382         // Ωmeasz = bz + (1+sz) * Ωtruez + g31 * ftruex + g32 * ftruey + g33 * ftruez
3383 
3384         // Where the unknowns are: sx, sy, sz, mxy mxz, myz, g11, g12, g13, g21, g22, g23, g31, g32, g33
3385         // Reordering:
3386         // Ωmeasx = bx + Ωtruex + sx * Ωtruex + mxy * Ωtruey + mxz * Ωtruez + g11 * ftruex + g12 * ftruey + g13 * ftruez
3387         // Ωmeasy = by + Ωtruey + sy * Ωtruey + myz * Ωtruez + g21 * ftruex * g22 * ftruey + g23 * ftruez
3388         // Ωmeasz = bz + Ωtruez + sz * Ωtruez + g31 * ftruex + g32 * ftruey + g33 * ftruez
3389 
3390         // Ωmeasx - Ωtruex - bx = sx * Ωtruex + mxy * Ωtruey + mxz * Ωtruez + g11 * ftruex + g12 * ftruey + g13 * ftruez
3391         // Ωmeasy - Ωtruey - by = sy * Ωtruey + myz * Ωtruez + g21 * ftruex * g22 * ftruey + g23 * ftruez
3392         // Ωmeasz - Ωtruez - bz = sz * Ωtruez + g31 * ftruex + g32 * ftruey + g33 * ftruez
3393 
3394         // [Ωtruex  0       0       Ωtruey  Ωtruez  0       ftruex  ftruey  ftruez  0       0       0       0       0       0     ][sx ] =  [Ωmeasx - Ωtruex - bx]
3395         // [0       Ωtruey  0       0       0       Ωtruez  0       0       0       ftruex  ftruey  ftruez  0       0       0     ][sy ]    [Ωmeasy - Ωtruey - by]
3396         // [0       0       Ωtruez  0       0       0       0       0       0       0       0       0       ftruex  ftruey  ftruez][sz ]    [Ωmeasz - Ωtruez - bz]
3397         //                                                                                                                         [mxy]
3398         //                                                                                                                         [mxz]
3399         //                                                                                                                         [myz]
3400         //                                                                                                                         [g11]
3401         //                                                                                                                         [g12]
3402         //                                                                                                                         [g13]
3403         //                                                                                                                         [g21]
3404         //                                                                                                                         [g22]
3405         //                                                                                                                         [g23]
3406         //                                                                                                                         [g31]
3407         //                                                                                                                         [g32]
3408         //                                                                                                                         [g33]
3409 
3410         fitter.setFunctionEvaluator(new LevenbergMarquardtMultiVariateFunctionEvaluator() {
3411             @Override
3412             public int getNumberOfDimensions() {
3413                 // Input points are true angular rate + specific force coordinates
3414                 return 2 * BodyKinematics.COMPONENTS;
3415             }
3416 
3417             @Override
3418             public int getNumberOfVariables() {
3419                 // The multivariate function returns the components of measured angular rate
3420                 return BodyKinematics.COMPONENTS;
3421             }
3422 
3423             @Override
3424             public double[] createInitialParametersArray() {
3425                 final var initial = new double[COMMON_Z_AXIS_UNKNOWNS];
3426 
3427                 initial[0] = initialSx;
3428                 initial[1] = initialSy;
3429                 initial[2] = initialSz;
3430 
3431                 initial[3] = initialMxy;
3432                 initial[4] = initialMxz;
3433                 initial[5] = initialMyz;
3434 
3435                 final var buffer = initialGg.getBuffer();
3436                 final var num = buffer.length;
3437                 System.arraycopy(buffer, 0, initial, 6, num);
3438 
3439                 return initial;
3440             }
3441 
3442             @Override
3443             public void evaluate(
3444                     final int i, final double[] point, final double[] result, final double[] params,
3445                     final Matrix jacobian) {
3446                 // We know that:
3447                 // Ωmeasx = bx + Ωtruex + sx * Ωtruex + mxy * Ωtruey + mxz * Ωtruez + g11 * ftruex + g12 * ftruey + g13 * ftruez
3448                 // Ωmeasy = by + Ωtruey + sy * Ωtruey + myz * Ωtruez + g21 * ftruex * g22 * ftruey + g23 * ftruez
3449                 // Ωmeasz = bz + Ωtruez + sz * Ωtruez + g31 * ftruex + g32 * ftruey + g33 * ftruez
3450 
3451                 // Hence, the derivatives respect the parameters
3452                 // sx, sy, sz, mxy mxz, myz, g11, g12, g13, g21, g22, g23,
3453                 // g31, g32, and g33 is:
3454 
3455                 // d(Ωmeasx)/d(sx) = Ωtruex
3456                 // d(Ωmeasx)/d(sy) = 0.0
3457                 // d(Ωmeasx)/d(sz) = 0.0
3458                 // d(Ωmeasx)/d(mxy) = Ωtruey
3459                 // d(Ωmeasx)/d(mxz) = Ωtruez
3460                 // d(Ωmeasx)/d(myz) = 0.0
3461                 // d(Ωmeasx)/d(g11) = ftruex
3462                 // d(Ωmeasx)/d(g12) = ftruey
3463                 // d(Ωmeasx)/d(g13) = ftruez
3464                 // d(Ωmeasx)/d(g21) = 0.0
3465                 // d(Ωmeasx)/d(g22) = 0.0
3466                 // d(Ωmeasx)/d(g23) = 0.0
3467                 // d(Ωmeasx)/d(g31) = 0.0
3468                 // d(Ωmeasx)/d(g32) = 0.0
3469                 // d(Ωmeasx)/d(g33) = 0.0
3470 
3471                 // d(Ωmeasy)/d(sx) = 0.0
3472                 // d(Ωmeasy)/d(sy) = Ωtruey
3473                 // d(Ωmeasy)/d(sz) = 0.0
3474                 // d(Ωmeasy)/d(mxy) = 0.0
3475                 // d(Ωmeasy)/d(mxz) = 0.0
3476                 // d(Ωmeasy)/d(myz) = Ωtruez
3477                 // d(Ωmeasx)/d(g11) = 0.0
3478                 // d(Ωmeasx)/d(g12) = 0.0
3479                 // d(Ωmeasx)/d(g13) = 0.0
3480                 // d(Ωmeasx)/d(g21) = ftruex
3481                 // d(Ωmeasx)/d(g22) = ftruey
3482                 // d(Ωmeasx)/d(g23) = ftruez
3483                 // d(Ωmeasx)/d(g31) = 0.0
3484                 // d(Ωmeasx)/d(g32) = 0.0
3485                 // d(Ωmeasx)/d(g33) = 0.0
3486 
3487                 // d(Ωmeasz)/d(sx) = 0.0
3488                 // d(Ωmeasz)/d(sy) = 0.0
3489                 // d(Ωmeasz)/d(sz) = Ωtruez
3490                 // d(Ωmeasz)/d(mxy) = 0.0
3491                 // d(Ωmeasz)/d(mxz) = 0.0
3492                 // d(Ωmeasz)/d(myz) = 0.0
3493                 // d(Ωmeasx)/d(g11) = 0.0
3494                 // d(Ωmeasx)/d(g12) = 0.0
3495                 // d(Ωmeasx)/d(g13) = 0.0
3496                 // d(Ωmeasx)/d(g21) = 0.0
3497                 // d(Ωmeasx)/d(g22) = 0.0
3498                 // d(Ωmeasx)/d(g23) = 0.0
3499                 // d(Ωmeasx)/d(g31) = ftruex
3500                 // d(Ωmeasx)/d(g32) = ftruey
3501                 // d(Ωmeasx)/d(g33) = ftruez
3502 
3503                 final var sx = params[0];
3504                 final var sy = params[1];
3505                 final var sz = params[2];
3506 
3507                 final var mxy = params[3];
3508                 final var mxz = params[4];
3509                 final var myz = params[5];
3510 
3511                 final var g11 = params[6];
3512                 final var g21 = params[7];
3513                 final var g31 = params[8];
3514                 final var g12 = params[9];
3515                 final var g22 = params[10];
3516                 final var g32 = params[11];
3517                 final var g13 = params[12];
3518                 final var g23 = params[13];
3519                 final var g33 = params[14];
3520 
3521                 final var omegatruex = point[0];
3522                 final var omegatruey = point[1];
3523                 final var omegatruez = point[2];
3524 
3525                 final var ftruex = point[3];
3526                 final var ftruey = point[4];
3527                 final var ftruez = point[5];
3528 
3529                 result[0] = biasX + omegatruex + sx * omegatruex + mxy * omegatruey + mxz * omegatruez
3530                         + g11 * ftruex + g12 * ftruey + g13 * ftruez;
3531                 result[1] = biasY + omegatruey + sy * omegatruey + myz * omegatruez
3532                         + g21 * ftruex * g22 * ftruey + g23 * ftruez;
3533                 result[2] = biasZ + omegatruez + sz * omegatruez
3534                         + g31 * ftruex + g32 * ftruey + g33 * ftruez;
3535 
3536                 jacobian.setElementAt(0, 0, omegatruex);
3537                 jacobian.setElementAt(0, 1, 0.0);
3538                 jacobian.setElementAt(0, 2, 0.0);
3539                 jacobian.setElementAt(0, 3, omegatruey);
3540                 jacobian.setElementAt(0, 4, omegatruez);
3541                 jacobian.setElementAt(0, 5, 0.0);
3542                 jacobian.setElementAt(0, 6, ftruex);
3543                 jacobian.setElementAt(0, 7, ftruey);
3544                 jacobian.setElementAt(0, 8, ftruez);
3545                 jacobian.setElementAt(0, 9, 0.0);
3546                 jacobian.setElementAt(0, 10, 0.0);
3547                 jacobian.setElementAt(0, 11, 0.0);
3548                 jacobian.setElementAt(0, 12, 0.0);
3549                 jacobian.setElementAt(0, 13, 0.0);
3550                 jacobian.setElementAt(0, 14, 0.0);
3551 
3552                 jacobian.setElementAt(1, 0, 0.0);
3553                 jacobian.setElementAt(1, 1, omegatruey);
3554                 jacobian.setElementAt(1, 2, 0.0);
3555                 jacobian.setElementAt(1, 3, 0.0);
3556                 jacobian.setElementAt(1, 4, 0.0);
3557                 jacobian.setElementAt(1, 5, omegatruez);
3558                 jacobian.setElementAt(1, 6, 0.0);
3559                 jacobian.setElementAt(1, 7, 0.0);
3560                 jacobian.setElementAt(1, 8, 0.0);
3561                 jacobian.setElementAt(1, 9, ftruex);
3562                 jacobian.setElementAt(1, 10, ftruey);
3563                 jacobian.setElementAt(1, 11, ftruez);
3564                 jacobian.setElementAt(1, 12, 0.0);
3565                 jacobian.setElementAt(1, 13, 0.0);
3566                 jacobian.setElementAt(1, 14, 0.0);
3567 
3568                 jacobian.setElementAt(2, 0, 0.0);
3569                 jacobian.setElementAt(2, 1, 0.0);
3570                 jacobian.setElementAt(2, 2, omegatruez);
3571                 jacobian.setElementAt(2, 3, 0.0);
3572                 jacobian.setElementAt(2, 4, 0.0);
3573                 jacobian.setElementAt(2, 5, 0.0);
3574                 jacobian.setElementAt(2, 6, 0.0);
3575                 jacobian.setElementAt(2, 7, 0.0);
3576                 jacobian.setElementAt(2, 8, 0.0);
3577                 jacobian.setElementAt(2, 9, 0.0);
3578                 jacobian.setElementAt(2, 10, 0.0);
3579                 jacobian.setElementAt(2, 11, 0.0);
3580                 jacobian.setElementAt(2, 12, ftruex);
3581                 jacobian.setElementAt(2, 13, ftruey);
3582                 jacobian.setElementAt(2, 14, ftruez);
3583             }
3584         });
3585 
3586         setInputData();
3587 
3588         fitter.fit();
3589 
3590         final var result = fitter.getA();
3591 
3592         final var sx = result[0];
3593         final var sy = result[1];
3594         final var sz = result[2];
3595 
3596         final var mxy = result[3];
3597         final var mxz = result[4];
3598         final var myz = result[5];
3599 
3600         final var g11 = result[6];
3601         final var g21 = result[7];
3602         final var g31 = result[8];
3603         final var g12 = result[9];
3604         final var g22 = result[10];
3605         final var g32 = result[11];
3606         final var g13 = result[12];
3607         final var g23 = result[13];
3608         final var g33 = result[14];
3609 
3610         if (estimatedMg == null) {
3611             estimatedMg = new Matrix(BodyKinematics.COMPONENTS, BodyKinematics.COMPONENTS);
3612         } else {
3613             estimatedMg.initialize(0.0);
3614         }
3615 
3616         estimatedMg.setElementAt(0, 0, sx);
3617 
3618         estimatedMg.setElementAt(0, 1, mxy);
3619         estimatedMg.setElementAt(1, 1, sy);
3620 
3621         estimatedMg.setElementAt(0, 2, mxz);
3622         estimatedMg.setElementAt(1, 2, myz);
3623         estimatedMg.setElementAt(2, 2, sz);
3624 
3625         if (estimatedGg == null) {
3626             estimatedGg = new Matrix(BodyKinematics.COMPONENTS, BodyKinematics.COMPONENTS);
3627         } else {
3628             estimatedGg.initialize(0.0);
3629         }
3630 
3631         estimatedGg.setElementAtIndex(0, g11);
3632         estimatedGg.setElementAtIndex(1, g21);
3633         estimatedGg.setElementAtIndex(2, g31);
3634         estimatedGg.setElementAtIndex(3, g12);
3635         estimatedGg.setElementAtIndex(4, g22);
3636         estimatedGg.setElementAtIndex(5, g32);
3637         estimatedGg.setElementAtIndex(6, g13);
3638         estimatedGg.setElementAtIndex(7, g23);
3639         estimatedGg.setElementAtIndex(8, g33);
3640 
3641         estimatedCovariance = fitter.getCovar();
3642 
3643         // propagate covariance matrix so that all parameters are taken into
3644         // account in the order: sx, sy, sz, mxy, mxz, myx, myz, mzx, mzy,
3645         // g11, g21, g31, g12, g22, g32, g13, g23, g33
3646 
3647         // We define a lineal function mapping original parameters for the common
3648         // axis case to the general case
3649         // [sx'] =   [1  0  0  0  0  0  0  0  0  0  0  0  0  0  0][sx]
3650         // [sy']     [0  1  0  0  0  0  0  0  0  0  0  0  0  0  0][sy]
3651         // [sz']     [0  0  1  0  0  0  0  0  0  0  0  0  0  0  0][sz]
3652         // [mxy']    [0  0  0  1  0  0  0  0  0  0  0  0  0  0  0][mxy]
3653         // [mxz']    [0  0  0  0  1  0  0  0  0  0  0  0  0  0  0][mxz]
3654         // [myx']    [0  0  0  0  0  0  0  0  0  0  0  0  0  0  0][myz]
3655         // [myz']    [0  0  0  0  0  1  0  0  0  0  0  0  0  0  0][g11]
3656         // [mzx']    [0  0  0  0  0  0  0  0  0  0  0  0  0  0  0][g21]
3657         // [mzy']    [0  0  0  0  0  0  0  0  0  0  0  0  0  0  0][g31]
3658         // [g11']    [0  0  0  0  0  0  1  0  0  0  0  0  0  0  0][g12]
3659         // [g21']    [0  0  0  0  0  0  0  1  0  0  0  0  0  0  0][g22]
3660         // [g31']    [0  0  0  0  0  0  0  0  1  0  0  0  0  0  0][g32]
3661         // [g12']    [0  0  0  0  0  0  0  0  0  1  0  0  0  0  0][g13]
3662         // [g22']    [0  0  0  0  0  0  0  0  0  0  1  0  0  0  0][g23]
3663         // [g32']    [0  0  0  0  0  0  0  0  0  0  0  1  0  0  0][g33]
3664         // [g13']    [0  0  0  0  0  0  0  0  0  0  0  0  1  0  0]
3665         // [g23']    [0  0  0  0  0  0  0  0  0  0  0  0  0  1  0]
3666         // [g33']    [0  0  0  0  0  0  0  0  0  0  0  0  0  0  1]
3667 
3668         // As defined in com.irurueta.statistics.MultivariateNormalDist,
3669         // if we consider the jacobian of the lineal application the matrix shown
3670         // above, then covariance can be propagated as follows
3671         final var jacobian = new Matrix(GENERAL_UNKNOWNS, COMMON_Z_AXIS_UNKNOWNS);
3672         for (var i = 0; i < 5; i++) {
3673             jacobian.setElementAt(i, i, 1.0);
3674         }
3675         jacobian.setElementAt(6, 5, 1.0);
3676 
3677         for (int j = 6, i = 9; j < 15; j++, i++) {
3678             jacobian.setElementAt(i, j, 1.0);
3679         }
3680 
3681         // propagated covariance is J * Cov * J'
3682         final var jacobianTrans = jacobian.transposeAndReturnNew();
3683         jacobian.multiply(estimatedCovariance);
3684         jacobian.multiply(jacobianTrans);
3685         estimatedCovariance = jacobian;
3686         estimatedChiSq = fitter.getChisq();
3687         estimatedChiSqDegreesOfFreedom = fitter.getChisqDegreesOfFreedom();
3688         estimatedReducedChiSq = fitter.getReducedChisq();
3689         estimatedMse = fitter.getMse();
3690         try {
3691             estimatedP = fitter.getP();
3692             estimatedQ = fitter.getQ();
3693         } catch (final MaxIterationsExceededException ignore) {
3694             // if numerical instabilities arise, we assume worst case (no fit at all)
3695             // probability of finding a smaller chi square value is 1.0
3696             // quality of fit is 0.0
3697             estimatedP = 1.0;
3698             estimatedQ = 0.0;
3699         }
3700     }
3701 
3702     /**
3703      * Internal method to perform general calibration.
3704      *
3705      * @throws AlgebraException                         if there are numerical errors.
3706      * @throws FittingException                         if no convergence to solution is found.
3707      * @throws com.irurueta.numerical.NotReadyException if fitter is not ready.
3708      */
3709     private void calibrateGeneral() throws AlgebraException, FittingException,
3710             com.irurueta.numerical.NotReadyException {
3711 
3712         // The gyroscope model is:
3713         // Ωmeas = bg + (I + Mg) * Ωtrue + Gg * ftrue + w
3714 
3715         // Ideally a least squares solution tries to minimize noise component, so:
3716         // Ωmeas = bg + (I + Mg) * Ωtrue + Gg * ftrue
3717 
3718         // Hence:
3719         // [Ωmeasx] = [bx] + ( [1   0   0] + [sx    mxy    mxz]) [Ωtruex] + [g11   g12   g13][ftruex]
3720         // [Ωmeasy]   [by]     [0   1   0]   [myx   sy     myz]  [Ωtruey]   [g21   g22   g23][ftruey]
3721         // [Ωmeasz]   [bz]     [0   0   1]   [mzx   mzy    sz ]  [Ωtruez]   [g31   g32   g33][ftruez]
3722 
3723         // [Ωmeasx] = [bx] + ( [1+sx  mxy    mxz ]) [Ωtruex] + [g11   g12   g13][ftruex]
3724         // [Ωmeasy]   [by]     [myx   1+sy   myz ]  [Ωtruey]   [g21   g22   g23][ftruey]
3725         // [Ωmeasz]   [bz]     [mzx   mzy    1+sz]  [Ωtruez]   [g31   g32   g33][ftruez]
3726 
3727         // Ωmeasx = bx + (1+sx) * Ωtruex + mxy * Ωtruey + mxz * Ωtruez + g11 * ftruex + g12 * ftruey + g13 * ftruez
3728         // Ωmeasy = by + myx * Ωtruex + (1+sy) * Ωtruey + myz * Ωtruez + g21 * ftruex * g22 * ftruey + g23 * ftruez
3729         // Ωmeasz = bz + mzx * Ωtruex + mzy * Ωtruey + (1+sz) * Ωtruez + g31 * ftruex + g32 * ftruey + g33 * ftruez
3730 
3731         // Where the unknowns are: sx, sy, sz, mxy mxz, myx, myz, mzx, mzy, g11, g12, g13, g21, g22, g23,
3732         // g31, g32, g33
3733         // Reordering:
3734         // Ωmeasx = bx + Ωtruex + sx * Ωtruex + mxy * Ωtruey + mxz * Ωtruez + g11 * ftruex + g12 * ftruey + g13 * ftruez
3735         // Ωmeasy = by + myx * Ωtruex + Ωtruey + sy * Ωtruey + myz * Ωtruez + g21 * ftruex * g22 * ftruey + g23 * ftruez
3736         // Ωmeasz = bz + mzx * Ωtruex + mzy * Ωtruey + Ωtruez + sz * Ωtruez + g31 * ftruex + g32 * ftruey + g33 * ftruez
3737 
3738         // Ωmeasx - Ωtruex - bx = sx * Ωtruex + mxy * Ωtruey + mxz * Ωtruez + g11 * ftruex + g12 * ftruey + g13 * ftruez
3739         // Ωmeasy - Ωtruey - by = myx * Ωtruex + sy * Ωtruey + myz * Ωtruez + g21 * ftruex * g22 * ftruey + g23 * ftruez
3740         // Ωmeasz - Ωtruez - bz = mzx * Ωtruex + mzy * Ωtruey + sz * Ωtruez + g31 * ftruex + g32 * ftruey + g33 * ftruez
3741 
3742         // [Ωtruex  0       0       Ωtruey  Ωtruez  0       0       0       0       ftruex  ftruey  ftruez  0       0       0       0       0       0     ][sx ] =  [Ωmeasx - Ωtruex - bx]
3743         // [0       Ωtruey  0       0       0       Ωtruex  Ωtruez  0       0       0       0       0       ftruex  ftruey  ftruez  0       0       0     ][sy ]    [Ωmeasy - Ωtruey - by]
3744         // [0       0       Ωtruez  0       0       0       0       Ωtruex  Ωtruey  0       0       0       0       0       0       ftruex  ftruey  ftruez][sz ]    [Ωmeasz - Ωtruez - bz]
3745         //                                                                                                                                                 [mxy]
3746         //                                                                                                                                                 [mxz]
3747         //                                                                                                                                                 [myx]
3748         //                                                                                                                                                 [myz]
3749         //                                                                                                                                                 [mzx]
3750         //                                                                                                                                                 [mzy]
3751         //                                                                                                                                                 [g11]
3752         //                                                                                                                                                 [g12]
3753         //                                                                                                                                                 [g13]
3754         //                                                                                                                                                 [g21]
3755         //                                                                                                                                                 [g22]
3756         //                                                                                                                                                 [g23]
3757         //                                                                                                                                                 [g31]
3758         //                                                                                                                                                 [g32]
3759         //                                                                                                                                                 [g33]
3760 
3761         fitter.setFunctionEvaluator(new LevenbergMarquardtMultiVariateFunctionEvaluator() {
3762             @Override
3763             public int getNumberOfDimensions() {
3764                 // Input points are true angular rate + specific force coordinates
3765                 return 2 * BodyKinematics.COMPONENTS;
3766             }
3767 
3768             @Override
3769             public int getNumberOfVariables() {
3770                 // The multivariate function returns the components of measured angular rate
3771                 return BodyKinematics.COMPONENTS;
3772             }
3773 
3774             @Override
3775             public double[] createInitialParametersArray() {
3776                 final var initial = new double[GENERAL_UNKNOWNS];
3777 
3778                 initial[0] = initialSx;
3779                 initial[1] = initialSy;
3780                 initial[2] = initialSz;
3781 
3782                 initial[3] = initialMxy;
3783                 initial[4] = initialMxz;
3784                 initial[5] = initialMyx;
3785                 initial[6] = initialMyz;
3786                 initial[7] = initialMzx;
3787                 initial[8] = initialMzy;
3788 
3789                 final var buffer = initialGg.getBuffer();
3790                 final var num = buffer.length;
3791                 System.arraycopy(buffer, 0, initial, 9, num);
3792 
3793                 return initial;
3794             }
3795 
3796             @Override
3797             public void evaluate(final int i, final double[] point, final double[] result, final double[] params,
3798                                  final Matrix jacobian) {
3799                 // We know that:
3800                 // Ωmeasx = bx + Ωtruex + sx * Ωtruex + mxy * Ωtruey + mxz * Ωtruez + g11 * ftruex + g12 * ftruey + g13 * ftruez
3801                 // Ωmeasy = by + myx * Ωtruex + Ωtruey + sy * Ωtruey + myz * Ωtruez + g21 * ftruex * g22 * ftruey + g23 * ftruez
3802                 // Ωmeasz = bz + mzx * Ωtruex + mzy * Ωtruey + Ωtruez + sz * Ωtruez + g31 * ftruex + g32 * ftruey + g33 * ftruez
3803 
3804                 // Hence, the derivatives respect the parameters sx, sy,
3805                 // sz, mxy, mxz, myx, myz, mzx, mzy, g11, g12, g13, g21, g22, g23,
3806                 // g31, g32 and g33 is:
3807 
3808                 // d(Ωmeasx)/d(sx) = Ωtruex
3809                 // d(Ωmeasx)/d(sy) = 0.0
3810                 // d(Ωmeasx)/d(sz) = 0.0
3811                 // d(Ωmeasx)/d(mxy) = Ωtruey
3812                 // d(Ωmeasx)/d(mxz) = Ωtruez
3813                 // d(Ωmeasx)/d(myx) = 0.0
3814                 // d(Ωmeasx)/d(myz) = 0.0
3815                 // d(Ωmeasx)/d(mzx) = 0.0
3816                 // d(Ωmeasx)/d(mzy) = 0.0
3817                 // d(Ωmeasx)/d(g11) = ftruex
3818                 // d(Ωmeasx)/d(g12) = ftruey
3819                 // d(Ωmeasx)/d(g13) = ftruez
3820                 // d(Ωmeasx)/d(g21) = 0.0
3821                 // d(Ωmeasx)/d(g22) = 0.0
3822                 // d(Ωmeasx)/d(g23) = 0.0
3823                 // d(Ωmeasx)/d(g31) = 0.0
3824                 // d(Ωmeasx)/d(g32) = 0.0
3825                 // d(Ωmeasx)/d(g33) = 0.0
3826 
3827                 // d(Ωmeasy)/d(sx) = 0.0
3828                 // d(Ωmeasy)/d(sy) = Ωtruey
3829                 // d(Ωmeasy)/d(sz) = 0.0
3830                 // d(Ωmeasy)/d(mxy) = 0.0
3831                 // d(Ωmeasy)/d(mxz) = 0.0
3832                 // d(Ωmeasy)/d(myx) = Ωtruex
3833                 // d(Ωmeasy)/d(myz) = Ωtruez
3834                 // d(Ωmeasy)/d(mzx) = 0.0
3835                 // d(Ωmeasy)/d(mzy) = 0.0
3836                 // d(Ωmeasx)/d(g11) = 0.0
3837                 // d(Ωmeasx)/d(g12) = 0.0
3838                 // d(Ωmeasx)/d(g13) = 0.0
3839                 // d(Ωmeasx)/d(g21) = ftruex
3840                 // d(Ωmeasx)/d(g22) = ftruey
3841                 // d(Ωmeasx)/d(g23) = ftruez
3842                 // d(Ωmeasx)/d(g31) = 0.0
3843                 // d(Ωmeasx)/d(g32) = 0.0
3844                 // d(Ωmeasx)/d(g33) = 0.0
3845 
3846                 // d(Ωmeasz)/d(sx) = 0.0
3847                 // d(Ωmeasz)/d(sy) = 0.0
3848                 // d(Ωmeasz)/d(sz) = Ωtruez
3849                 // d(Ωmeasz)/d(mxy) = 0.0
3850                 // d(Ωmeasz)/d(mxz) = 0.0
3851                 // d(Ωmeasz)/d(myx) = 0.0
3852                 // d(Ωmeasz)/d(myz) = 0.0
3853                 // d(Ωmeasz)/d(mzx) = Ωtruex
3854                 // d(Ωmeasz)/d(mzy) = Ωtruey
3855                 // d(Ωmeasx)/d(g11) = 0.0
3856                 // d(Ωmeasx)/d(g12) = 0.0
3857                 // d(Ωmeasx)/d(g13) = 0.0
3858                 // d(Ωmeasx)/d(g21) = 0.0
3859                 // d(Ωmeasx)/d(g22) = 0.0
3860                 // d(Ωmeasx)/d(g23) = 0.0
3861                 // d(Ωmeasx)/d(g31) = ftruex
3862                 // d(Ωmeasx)/d(g32) = ftruey
3863                 // d(Ωmeasx)/d(g33) = ftruez
3864 
3865                 final var sx = params[0];
3866                 final var sy = params[1];
3867                 final var sz = params[2];
3868 
3869                 final var mxy = params[3];
3870                 final var mxz = params[4];
3871                 final var myx = params[5];
3872                 final var myz = params[6];
3873                 final var mzx = params[7];
3874                 final var mzy = params[8];
3875 
3876                 final var g11 = params[9];
3877                 final var g21 = params[10];
3878                 final var g31 = params[11];
3879                 final var g12 = params[12];
3880                 final var g22 = params[13];
3881                 final var g32 = params[14];
3882                 final var g13 = params[15];
3883                 final var g23 = params[16];
3884                 final var g33 = params[17];
3885 
3886                 final var omegatruex = point[0];
3887                 final var omegatruey = point[1];
3888                 final var omegatruez = point[2];
3889 
3890                 final var ftruex = point[3];
3891                 final var ftruey = point[4];
3892                 final var ftruez = point[5];
3893 
3894                 result[0] = biasX + omegatruex + sx * omegatruex + mxy * omegatruey + mxz * omegatruez
3895                         + g11 * ftruex + g12 * ftruey + g13 * ftruez;
3896                 result[1] = biasY + myx * omegatruex + omegatruey + sy * omegatruey + myz * omegatruez
3897                         + g21 * ftruex * g22 * ftruey + g23 * ftruez;
3898                 result[2] = biasZ + mzx * omegatruex + mzy * omegatruey + omegatruez + sz * omegatruez
3899                         + g31 * ftruex + g32 * ftruey + g33 * ftruez;
3900 
3901                 jacobian.setElementAt(0, 0, omegatruex);
3902                 jacobian.setElementAt(0, 1, 0.0);
3903                 jacobian.setElementAt(0, 2, 0.0);
3904                 jacobian.setElementAt(0, 3, omegatruey);
3905                 jacobian.setElementAt(0, 4, omegatruez);
3906                 jacobian.setElementAt(0, 5, 0.0);
3907                 jacobian.setElementAt(0, 6, 0.0);
3908                 jacobian.setElementAt(0, 7, 0.0);
3909                 jacobian.setElementAt(0, 8, 0.0);
3910                 jacobian.setElementAt(0, 9, ftruex);
3911                 jacobian.setElementAt(0, 10, ftruey);
3912                 jacobian.setElementAt(0, 11, ftruez);
3913                 jacobian.setElementAt(0, 12, 0.0);
3914                 jacobian.setElementAt(0, 13, 0.0);
3915                 jacobian.setElementAt(0, 14, 0.0);
3916                 jacobian.setElementAt(0, 15, 0.0);
3917                 jacobian.setElementAt(0, 16, 0.0);
3918                 jacobian.setElementAt(0, 17, 0.0);
3919 
3920                 jacobian.setElementAt(1, 0, 0.0);
3921                 jacobian.setElementAt(1, 1, omegatruey);
3922                 jacobian.setElementAt(1, 2, 0.0);
3923                 jacobian.setElementAt(1, 3, 0.0);
3924                 jacobian.setElementAt(1, 4, 0.0);
3925                 jacobian.setElementAt(1, 5, omegatruex);
3926                 jacobian.setElementAt(1, 6, omegatruez);
3927                 jacobian.setElementAt(1, 7, 0.0);
3928                 jacobian.setElementAt(1, 8, 0.0);
3929                 jacobian.setElementAt(1, 9, 0.0);
3930                 jacobian.setElementAt(1, 10, 0.0);
3931                 jacobian.setElementAt(1, 11, 0.0);
3932                 jacobian.setElementAt(1, 12, ftruex);
3933                 jacobian.setElementAt(1, 13, ftruey);
3934                 jacobian.setElementAt(1, 14, ftruez);
3935                 jacobian.setElementAt(1, 15, 0.0);
3936                 jacobian.setElementAt(1, 16, 0.0);
3937                 jacobian.setElementAt(1, 17, 0.0);
3938 
3939                 jacobian.setElementAt(2, 0, 0.0);
3940                 jacobian.setElementAt(2, 1, 0.0);
3941                 jacobian.setElementAt(2, 2, omegatruez);
3942                 jacobian.setElementAt(2, 3, 0.0);
3943                 jacobian.setElementAt(2, 4, 0.0);
3944                 jacobian.setElementAt(2, 5, 0.0);
3945                 jacobian.setElementAt(2, 6, 0.0);
3946                 jacobian.setElementAt(2, 7, omegatruex);
3947                 jacobian.setElementAt(2, 8, omegatruey);
3948                 jacobian.setElementAt(2, 9, 0.0);
3949                 jacobian.setElementAt(2, 10, 0.0);
3950                 jacobian.setElementAt(2, 11, 0.0);
3951                 jacobian.setElementAt(2, 12, 0.0);
3952                 jacobian.setElementAt(2, 13, 0.0);
3953                 jacobian.setElementAt(2, 14, 0.0);
3954                 jacobian.setElementAt(2, 15, ftruex);
3955                 jacobian.setElementAt(2, 16, ftruey);
3956                 jacobian.setElementAt(2, 17, ftruez);
3957             }
3958         });
3959 
3960         setInputData();
3961 
3962         fitter.fit();
3963 
3964         final var result = fitter.getA();
3965 
3966         final var sx = result[0];
3967         final var sy = result[1];
3968         final var sz = result[2];
3969 
3970         final var mxy = result[3];
3971         final var mxz = result[4];
3972         final var myx = result[5];
3973         final var myz = result[6];
3974         final var mzx = result[7];
3975         final var mzy = result[8];
3976 
3977         final var g11 = result[9];
3978         final var g21 = result[10];
3979         final var g31 = result[11];
3980         final var g12 = result[12];
3981         final var g22 = result[13];
3982         final var g32 = result[14];
3983         final var g13 = result[15];
3984         final var g23 = result[16];
3985         final var g33 = result[17];
3986 
3987         if (estimatedMg == null) {
3988             estimatedMg = new Matrix(BodyKinematics.COMPONENTS, BodyKinematics.COMPONENTS);
3989         } else {
3990             estimatedMg.initialize(0.0);
3991         }
3992 
3993         estimatedMg.setElementAt(0, 0, sx);
3994         estimatedMg.setElementAt(1, 0, myx);
3995         estimatedMg.setElementAt(2, 0, mzx);
3996 
3997         estimatedMg.setElementAt(0, 1, mxy);
3998         estimatedMg.setElementAt(1, 1, sy);
3999         estimatedMg.setElementAt(2, 1, mzy);
4000 
4001         estimatedMg.setElementAt(0, 2, mxz);
4002         estimatedMg.setElementAt(1, 2, myz);
4003         estimatedMg.setElementAt(2, 2, sz);
4004 
4005         if (estimatedGg == null) {
4006             estimatedGg = new Matrix(BodyKinematics.COMPONENTS, BodyKinematics.COMPONENTS);
4007         } else {
4008             estimatedGg.initialize(0.0);
4009         }
4010 
4011         estimatedGg.setElementAtIndex(0, g11);
4012         estimatedGg.setElementAtIndex(1, g21);
4013         estimatedGg.setElementAtIndex(2, g31);
4014         estimatedGg.setElementAtIndex(3, g12);
4015         estimatedGg.setElementAtIndex(4, g22);
4016         estimatedGg.setElementAtIndex(5, g32);
4017         estimatedGg.setElementAtIndex(6, g13);
4018         estimatedGg.setElementAtIndex(7, g23);
4019         estimatedGg.setElementAtIndex(8, g33);
4020 
4021         estimatedCovariance = fitter.getCovar();
4022         estimatedChiSq = fitter.getChisq();
4023         estimatedChiSqDegreesOfFreedom = fitter.getChisqDegreesOfFreedom();
4024         estimatedReducedChiSq = fitter.getReducedChisq();
4025         estimatedMse = fitter.getMse();
4026         try {
4027             estimatedP = fitter.getP();
4028             estimatedQ = fitter.getQ();
4029         } catch (final MaxIterationsExceededException ignore) {
4030             // if numerical instabilities arise, we assume worst case (no fit at all)
4031             // probability of finding a smaller chi square value is 1.0
4032             // quality of fit is 0.0
4033             estimatedP = 1.0;
4034             estimatedQ = 0.0;
4035         }
4036     }
4037 
4038     /**
4039      * Sets input data into Levenberg-Marquardt fitter.
4040      *
4041      * @throws WrongSizeException never happens.
4042      */
4043     private void setInputData() throws WrongSizeException {
4044         // set input data using:
4045         // Ωmeasx = bx + Ωtruex + sx * Ωtruex + mxy * Ωtruey + mxz * Ωtruez + g11 * ftruex + g12 * ftruey + g13 * ftruez
4046         // Ωmeasy = by + myx * Ωtruex + Ωtruey + sy * Ωtruey + myz * Ωtruez + g21 * ftruex * g22 * ftruey + g23 * ftruez
4047         // Ωmeasz = bz + mzx * Ωtruex + mzy * Ωtruey + Ωtruez + sz * Ωtruez + g31 * ftruex + g32 * ftruey + g33 * ftruez
4048 
4049         // fmeasx = bx + ftruex + sx * ftruex + mxy * ftruey + mxz * ftruez
4050         // fmeasy = by + myx * ftruex + ftruey + sy * ftruey + myz * ftruez
4051         // fmeasz = bz + mzx * ftruex + mzy * ftruey + ftruez + sz * ftruez
4052 
4053         final var expectedKinematics = new BodyKinematics();
4054 
4055         final var numMeasurements = measurements.size();
4056         final var x = new Matrix(numMeasurements, 2 * BodyKinematics.COMPONENTS);
4057         final var y = new Matrix(numMeasurements, BodyKinematics.COMPONENTS);
4058         final var standardDeviations = new double[numMeasurements];
4059         var i = 0;
4060         for (final var measurement : measurements) {
4061             final var measuredKinematics = measurement.getKinematics();
4062             final var ecefFrame = measurement.getFrame();
4063             final var previousEcefFrame = measurement.getPreviousFrame();
4064             final var timeInterval = measurement.getTimeInterval();
4065 
4066             ECEFKinematicsEstimator.estimateKinematics(timeInterval, ecefFrame, previousEcefFrame, expectedKinematics);
4067 
4068             final var omegaMeasX = measuredKinematics.getAngularRateX();
4069             final var omegaMeasY = measuredKinematics.getAngularRateY();
4070             final var omegaMeasZ = measuredKinematics.getAngularRateZ();
4071 
4072             final var omegaTrueX = expectedKinematics.getAngularRateX();
4073             final var omegaTrueY = expectedKinematics.getAngularRateY();
4074             final var omegaTrueZ = expectedKinematics.getAngularRateZ();
4075 
4076             final var fTrueX = expectedKinematics.getFx();
4077             final var fTrueY = expectedKinematics.getFy();
4078             final var fTrueZ = expectedKinematics.getFz();
4079 
4080             x.setElementAt(i, 0, omegaTrueX);
4081             x.setElementAt(i, 1, omegaTrueY);
4082             x.setElementAt(i, 2, omegaTrueZ);
4083 
4084             x.setElementAt(i, 3, fTrueX);
4085             x.setElementAt(i, 4, fTrueY);
4086             x.setElementAt(i, 5, fTrueZ);
4087 
4088             y.setElementAt(i, 0, omegaMeasX);
4089             y.setElementAt(i, 1, omegaMeasY);
4090             y.setElementAt(i, 2, omegaMeasZ);
4091 
4092             standardDeviations[i] = measurement.getAngularRateStandardDeviation();
4093             i++;
4094         }
4095 
4096         fitter.setInputData(x, y, standardDeviations);
4097     }
4098 
4099     /**
4100      * Converts angular speed instance to radians per second (rad/s).
4101      *
4102      * @param value angular speed value.
4103      * @param unit  unit of angular speed value.
4104      * @return converted value.
4105      */
4106     private static double convertAngularSpeed(final double value, final AngularSpeedUnit unit) {
4107         return AngularSpeedConverter.convert(value, unit, AngularSpeedUnit.RADIANS_PER_SECOND);
4108     }
4109 
4110     /**
4111      * Converts angular speed instance to radians per second (rad/s).
4112      *
4113      * @param angularSpeed angular speed instance to be converted.
4114      * @return converted value.
4115      */
4116     private static double convertAngularSpeed(final AngularSpeed angularSpeed) {
4117         return convertAngularSpeed(angularSpeed.getValue().doubleValue(), angularSpeed.getUnit());
4118     }
4119 }