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