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