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