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 }