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