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