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