1 /*
2 * Copyright (C) 2020 Alberto Irurueta Carro (alberto@irurueta.com)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package com.irurueta.navigation.inertial.calibration.accelerometer;
17
18 import com.irurueta.algebra.Matrix;
19 import com.irurueta.navigation.LockedException;
20 import com.irurueta.navigation.NotReadyException;
21 import com.irurueta.navigation.inertial.calibration.CalibrationException;
22 import com.irurueta.navigation.inertial.calibration.StandardDeviationFrameBodyKinematics;
23 import com.irurueta.numerical.robust.LMedSRobustEstimator;
24 import com.irurueta.numerical.robust.LMedSRobustEstimatorListener;
25 import com.irurueta.numerical.robust.RobustEstimator;
26 import com.irurueta.numerical.robust.RobustEstimatorException;
27 import com.irurueta.numerical.robust.RobustEstimatorMethod;
28 import com.irurueta.units.Acceleration;
29
30 import java.util.List;
31
32 /**
33 * Robustly estimates accelerometer cross couplings and scaling factors using
34 * a LMedS algorithm to discard outliers.
35 * This estimator assumes that biases are known.
36 * <p>
37 * To use this calibrator at least 4 measurements at different known frames must
38 * be provided. In other words, accelerometer samples must be obtained at 4
39 * different positions, orientations and velocities (although typically velocities are
40 * always zero).
41 * <p>
42 * Measured specific force is assumed to follow the model shown below:
43 * <pre>
44 * fmeas = ba + (I + Ma) * ftrue + w
45 * </pre>
46 * Where:
47 * - fmeas is the measured specific force. This is a 3x1 vector.
48 * - ba is accelerometer bias. Ideally, on a perfect accelerometer, this should be a
49 * 3x1 zero vector.
50 * - I is the 3x3 identity matrix.
51 * - Ma is the 3x3 matrix containing cross-couplings and scaling factors. Ideally, on
52 * a perfect accelerometer, this should be a 3x3 zero matrix.
53 * - ftrue is ground-truth specific force.
54 * - w is measurement noise.
55 */
56 public class LMedSRobustKnownBiasAndFrameAccelerometerCalibrator extends
57 RobustKnownBiasAndFrameAccelerometerCalibrator {
58
59 /**
60 * Default value to be used for stop threshold. Stop threshold can be used to
61 * avoid keeping the algorithm unnecessarily iterating in case that best
62 * estimated threshold using median of residuals is not small enough. Once a
63 * solution is found that generates a threshold below this value, the
64 * algorithm will stop.
65 * The stop threshold can be used to prevent the LMedS algorithm iterating
66 * too many times in cases where samples have a very similar accuracy.
67 * For instance, in cases where proportion of outliers is very small (close
68 * to 0%), and samples are very accurate (i.e. 1e-6), the algorithm would
69 * iterate for a long time trying to find the best solution when indeed
70 * there is no need to do that if a reasonable threshold has already been
71 * reached.
72 * Because of this behaviour the stop threshold can be set to a value much
73 * lower than the one typically used in RANSAC, and yet the algorithm could
74 * still produce even smaller thresholds in estimated results.
75 */
76 public static final double DEFAULT_STOP_THRESHOLD = 1e-5;
77
78 /**
79 * Minimum allowed stop threshold value.
80 */
81 public static final double MIN_STOP_THRESHOLD = 0.0;
82
83 /**
84 * Threshold to be used to keep the algorithm iterating in case that best
85 * estimated threshold using median of residuals is not small enough. Once
86 * a solution is found that generates a threshold below this value, the
87 * algorithm will stop.
88 * The stop threshold can be used to prevent the LMedS algorithm iterating
89 * too many times in cases where samples have a very similar accuracy.
90 * For instance, in cases where proportion of outliers is very small (close
91 * to 0%), and samples are very accurate (i.e. 1e-6), the algorithm would
92 * iterate for a long time trying to find the best solution when indeed
93 * there is no need to do that if a reasonable threshold has already been
94 * reached.
95 * Because of this behaviour the stop threshold can be set to a value much
96 * lower than the one typically used in RANSAC, and yet the algorithm could
97 * still produce even smaller thresholds in estimated results.
98 */
99 private double stopThreshold = DEFAULT_STOP_THRESHOLD;
100
101 /**
102 * Constructor.
103 */
104 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator() {
105 super();
106 }
107
108 /**
109 * Constructor.
110 *
111 * @param listener listener to be notified of events such as when estimation
112 * starts, ends or its progress significantly changes.
113 */
114 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
115 final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
116 super(listener);
117 }
118
119 /**
120 * Constructor.
121 *
122 * @param measurements list of body kinematics measurements with standard
123 * deviations taken at different frames (positions, orientations
124 * and velocities).
125 */
126 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
127 final List<StandardDeviationFrameBodyKinematics> measurements) {
128 super(measurements);
129 }
130
131 /**
132 * Constructor.
133 *
134 * @param measurements list of body kinematics measurements with standard
135 * deviations taken at different frames (positions, orientations
136 * and velocities).
137 * @param listener listener to handle events raised by this calibrator.
138 */
139 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
140 final List<StandardDeviationFrameBodyKinematics> measurements,
141 final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
142 super(measurements, listener);
143 }
144
145 /**
146 * Constructor.
147 *
148 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
149 * accelerometer and gyroscope.
150 */
151 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(final boolean commonAxisUsed) {
152 super(commonAxisUsed);
153 }
154
155 /**
156 * Constructor.
157 *
158 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
159 * accelerometer and gyroscope.
160 * @param listener listener to handle events raised by this calibrator.
161 */
162 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
163 final boolean commonAxisUsed, final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
164 super(commonAxisUsed, listener);
165 }
166
167 /**
168 * Constructor.
169 *
170 * @param measurements list of body kinematics measurements with standard
171 * deviations taken at different frames (positions, orientations
172 * and velocities).
173 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
174 * accelerometer and gyroscope.
175 */
176 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
177 final List<StandardDeviationFrameBodyKinematics> measurements, final boolean commonAxisUsed) {
178 super(measurements, commonAxisUsed);
179 }
180
181 /**
182 * Constructor.
183 *
184 * @param measurements list of body kinematics measurements with standard
185 * deviations taken at different frames (positions, orientations
186 * and velocities).
187 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
188 * accelerometer and gyroscope.
189 * @param listener listener to handle events raised by this calibrator.
190 */
191 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
192 final List<StandardDeviationFrameBodyKinematics> measurements, final boolean commonAxisUsed,
193 final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
194 super(measurements, commonAxisUsed, listener);
195 }
196
197 /**
198 * Constructor.
199 *
200 * @param biasX known x coordinate of accelerometer bias expressed in meters per
201 * squared second (m/s^2).
202 * @param biasY known y coordinate of accelerometer bias expressed in meters per
203 * squared second (m/s^2).
204 * @param biasZ known z coordinate of accelerometer bias expressed in meters per
205 * squared second (m/s^2).
206 */
207 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
208 final double biasX, final double biasY, final double biasZ) {
209 super(biasX, biasY, biasZ);
210 }
211
212 /**
213 * Constructor.
214 *
215 * @param biasX known x coordinate of accelerometer bias expressed in meters per
216 * squared second (m/s^2).
217 * @param biasY known y coordinate of accelerometer bias expressed in meters per
218 * squared second (m/s^2).
219 * @param biasZ known z coordinate of accelerometer bias expressed in meters per
220 * squared second (m/s^2).
221 * @param listener listener to be notified of events such as when estimation
222 * starts, ends or its progress significantly changes.
223 */
224 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
225 final double biasX, final double biasY, final double biasZ,
226 final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
227 super(biasX, biasY, biasZ, listener);
228 }
229
230 /**
231 * Constructor.
232 *
233 * @param measurements list of body kinematics measurements with standard
234 * deviations taken at different frames (positions, orientations
235 * and velocities).
236 * @param biasX known x coordinate of accelerometer bias expressed in meters per
237 * squared second (m/s^2).
238 * @param biasY known y coordinate of accelerometer bias expressed in meters per
239 * squared second (m/s^2).
240 * @param biasZ known z coordinate of accelerometer bias expressed in meters per
241 * squared second (m/s^2).
242 */
243 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
244 final List<StandardDeviationFrameBodyKinematics> measurements,
245 final double biasX, final double biasY, final double biasZ) {
246 super(measurements, biasX, biasY, biasZ);
247 }
248
249 /**
250 * Constructor.
251 *
252 * @param measurements list of body kinematics measurements with standard
253 * deviations taken at different frames (positions, orientations
254 * and velocities).
255 * @param biasX known x coordinate of accelerometer bias expressed in meters per
256 * squared second (m/s^2).
257 * @param biasY known y coordinate of accelerometer bias expressed in meters per
258 * squared second (m/s^2).
259 * @param biasZ known z coordinate of accelerometer bias expressed in meters per
260 * squared second (m/s^2).
261 * @param listener listener to handle events raised by this calibrator.
262 */
263 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
264 final List<StandardDeviationFrameBodyKinematics> measurements,
265 final double biasX, final double biasY, final double biasZ,
266 final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
267 super(measurements, biasX, biasY, biasZ, listener);
268 }
269
270 /**
271 * Constructor.
272 *
273 * @param biasX known x coordinate of accelerometer bias expressed in meters per
274 * squared second (m/s^2).
275 * @param biasY known y coordinate of accelerometer bias expressed in meters per
276 * squared second (m/s^2).
277 * @param biasZ known z coordinate of accelerometer bias expressed in meters per
278 * squared second (m/s^2).
279 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
280 * accelerometer and gyroscope.
281 */
282 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
283 final double biasX, final double biasY, final double biasZ, final boolean commonAxisUsed) {
284 super(biasX, biasY, biasZ, commonAxisUsed);
285 }
286
287 /**
288 * Constructor.
289 *
290 * @param biasX known x coordinate of accelerometer bias expressed in meters per
291 * squared second (m/s^2).
292 * @param biasY known y coordinate of accelerometer bias expressed in meters per
293 * squared second (m/s^2).
294 * @param biasZ known z coordinate of accelerometer bias expressed in meters per
295 * squared second (m/s^2).
296 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
297 * accelerometer and gyroscope.
298 * @param listener listener to handle events raised by this calibrator.
299 */
300 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
301 final double biasX, final double biasY, final double biasZ, final boolean commonAxisUsed,
302 final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
303 super(biasX, biasY, biasZ, commonAxisUsed, listener);
304 }
305
306 /**
307 * Constructor.
308 *
309 * @param measurements list of body kinematics measurements with standard
310 * deviations taken at different frames (positions, orientations
311 * and velocities).
312 * @param biasX known x coordinate of accelerometer bias expressed in meters per
313 * squared second (m/s^2).
314 * @param biasY known y coordinate of accelerometer bias expressed in meters per
315 * squared second (m/s^2).
316 * @param biasZ known z coordinate of accelerometer bias expressed in meters per
317 * squared second (m/s^2).
318 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
319 * accelerometer and gyroscope.
320 */
321 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
322 final List<StandardDeviationFrameBodyKinematics> measurements,
323 final double biasX, final double biasY, final double biasZ, final boolean commonAxisUsed) {
324 super(measurements, biasX, biasY, biasZ, commonAxisUsed);
325 }
326
327 /**
328 * Constructor.
329 *
330 * @param measurements list of body kinematics measurements with standard
331 * deviations taken at different frames (positions, orientations
332 * and velocities).
333 * @param biasX known x coordinate of accelerometer bias expressed in meters per
334 * squared second (m/s^2).
335 * @param biasY known y coordinate of accelerometer bias expressed in meters per
336 * squared second (m/s^2).
337 * @param biasZ known z coordinate of accelerometer bias expressed in meters per
338 * squared second (m/s^2).
339 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
340 * accelerometer and gyroscope.
341 * @param listener listener to handle events raised by this calibrator.
342 */
343 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
344 final List<StandardDeviationFrameBodyKinematics> measurements,
345 final double biasX, final double biasY, final double biasZ, final boolean commonAxisUsed,
346 final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
347 super(measurements, biasX, biasY, biasZ, commonAxisUsed, listener);
348 }
349
350 /**
351 * Constructor.
352 *
353 * @param biasX known x coordinate of accelerometer bias.
354 * @param biasY known y coordinate of accelerometer bias.
355 * @param biasZ known z coordinate of accelerometer bias.
356 */
357 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
358 final Acceleration biasX, final Acceleration biasY, final Acceleration biasZ) {
359 super(biasX, biasY, biasZ);
360 }
361
362 /**
363 * Constructor.
364 *
365 * @param biasX known x coordinate of accelerometer bias.
366 * @param biasY known y coordinate of accelerometer bias.
367 * @param biasZ known z coordinate of accelerometer bias.
368 * @param listener listener to be notified of events such as when estimation
369 * starts, ends or its progress significantly changes.
370 */
371 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
372 final Acceleration biasX, final Acceleration biasY, final Acceleration biasZ,
373 final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
374 super(biasX, biasY, biasZ, listener);
375 }
376
377 /**
378 * Constructor.
379 *
380 * @param measurements list of body kinematics measurements with standard
381 * deviations taken at different frames (positions, orientations
382 * and velocities).
383 * @param biasX known x coordinate of accelerometer bias.
384 * @param biasY known y coordinate of accelerometer bias.
385 * @param biasZ known z coordinate of accelerometer bias.
386 */
387 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
388 final List<StandardDeviationFrameBodyKinematics> measurements,
389 final Acceleration biasX, final Acceleration biasY, final Acceleration biasZ) {
390 super(measurements, biasX, biasY, biasZ);
391 }
392
393 /**
394 * Constructor.
395 *
396 * @param measurements list of body kinematics measurements with standard
397 * deviations taken at different frames (positions, orientations
398 * and velocities).
399 * @param biasX known x coordinate of accelerometer bias.
400 * @param biasY known y coordinate of accelerometer bias.
401 * @param biasZ known z coordinate of accelerometer bias.
402 * @param listener listener to handle events raised by this calibrator.
403 */
404 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
405 final List<StandardDeviationFrameBodyKinematics> measurements,
406 final Acceleration biasX, final Acceleration biasY, final Acceleration biasZ,
407 final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
408 super(measurements, biasX, biasY, biasZ, listener);
409 }
410
411 /**
412 * Constructor.
413 *
414 * @param biasX known x coordinate of accelerometer bias.
415 * @param biasY known y coordinate of accelerometer bias.
416 * @param biasZ known z coordinate of accelerometer bias.
417 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
418 * accelerometer and gyroscope.
419 */
420 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
421 final Acceleration biasX, final Acceleration biasY, final Acceleration biasZ,
422 final boolean commonAxisUsed) {
423 super(biasX, biasY, biasZ, commonAxisUsed);
424 }
425
426 /**
427 * Constructor.
428 *
429 * @param biasX known x coordinate of accelerometer bias.
430 * @param biasY known y coordinate of accelerometer bias.
431 * @param biasZ known z coordinate of accelerometer bias.
432 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
433 * accelerometer and gyroscope.
434 * @param listener listener to handle events raised by this calibrator.
435 */
436 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
437 final Acceleration biasX, final Acceleration biasY, final Acceleration biasZ, final boolean commonAxisUsed,
438 final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
439 super(biasX, biasY, biasZ, commonAxisUsed, listener);
440 }
441
442 /**
443 * Constructor.
444 *
445 * @param measurements list of body kinematics measurements with standard
446 * deviations taken at different frames (positions, orientations
447 * and velocities).
448 * @param biasX known x coordinate of accelerometer bias.
449 * @param biasY known y coordinate of accelerometer bias.
450 * @param biasZ known z coordinate of accelerometer bias.
451 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
452 * accelerometer and gyroscope.
453 */
454 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
455 final List<StandardDeviationFrameBodyKinematics> measurements,
456 final Acceleration biasX, final Acceleration biasY, final Acceleration biasZ,
457 final boolean commonAxisUsed) {
458 super(measurements, biasX, biasY, biasZ, commonAxisUsed);
459 }
460
461 /**
462 * Constructor.
463 *
464 * @param measurements list of body kinematics measurements with standard
465 * deviations taken at different frames (positions, orientations
466 * and velocities).
467 * @param biasX known x coordinate of accelerometer bias.
468 * @param biasY known y coordinate of accelerometer bias.
469 * @param biasZ known z coordinate of accelerometer bias.
470 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
471 * accelerometer and gyroscope.
472 * @param listener listener to handle events raised by this calibrator.
473 */
474 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
475 final List<StandardDeviationFrameBodyKinematics> measurements,
476 final Acceleration biasX, final Acceleration biasY, final Acceleration biasZ, final boolean commonAxisUsed,
477 final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
478 super(measurements, biasX, biasY, biasZ, commonAxisUsed, listener);
479 }
480
481 /**
482 * Constructor.
483 *
484 * @param bias known accelerometer bias.
485 * @throws IllegalArgumentException if provided array does not have length 3.
486 */
487 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(final double[] bias) {
488 super(bias);
489 }
490
491 /**
492 * Constructor.
493 *
494 * @param bias known accelerometer bias.
495 * @param listener listener to be notified of events such as when estimation
496 * starts, ends or its progress significantly changes.
497 * @throws IllegalArgumentException if provided array does not have length 3.
498 */
499 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
500 final double[] bias, final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
501 super(bias, listener);
502 }
503
504 /**
505 * Constructor.
506 *
507 * @param measurements list of body kinematics measurements with standard
508 * deviations taken at different frames (positions, orientations
509 * and velocities).
510 * @param bias known accelerometer bias.
511 * @throws IllegalArgumentException if provided array does not have length 3.
512 */
513 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
514 final List<StandardDeviationFrameBodyKinematics> measurements, final double[] bias) {
515 super(measurements, bias);
516 }
517
518 /**
519 * Constructor.
520 *
521 * @param measurements list of body kinematics measurements with standard
522 * deviations taken at different frames (positions, orientations
523 * and velocities).
524 * @param bias known accelerometer bias.
525 * @param listener listener to handle events raised by this calibrator.
526 * @throws IllegalArgumentException if provided array does not have length 3.
527 */
528 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
529 final List<StandardDeviationFrameBodyKinematics> measurements, final double[] bias,
530 final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
531 super(measurements, bias, listener);
532 }
533
534 /**
535 * Constructor.
536 *
537 * @param bias known accelerometer bias.
538 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
539 * accelerometer and gyroscope.
540 * @throws IllegalArgumentException if provided array does not have length 3.
541 */
542 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(final double[] bias, final boolean commonAxisUsed) {
543 super(bias, commonAxisUsed);
544 }
545
546 /**
547 * Constructor.
548 *
549 * @param bias known accelerometer bias.
550 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
551 * accelerometer and gyroscope.
552 * @param listener listener to handle events raised by this calibrator.
553 * @throws IllegalArgumentException if provided array does not have length 3.
554 */
555 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
556 final double[] bias, final boolean commonAxisUsed,
557 final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
558 super(bias, commonAxisUsed, listener);
559 }
560
561 /**
562 * Constructor.
563 *
564 * @param measurements list of body kinematics measurements with standard
565 * deviations taken at different frames (positions, orientations
566 * and velocities).
567 * @param bias known accelerometer bias.
568 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
569 * accelerometer and gyroscope.
570 * @throws IllegalArgumentException if provided array does not have length 3.
571 */
572 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
573 final List<StandardDeviationFrameBodyKinematics> measurements, final double[] bias,
574 final boolean commonAxisUsed) {
575 super(measurements, bias, commonAxisUsed);
576 }
577
578 /**
579 * Constructor.
580 *
581 * @param measurements list of body kinematics measurements with standard
582 * deviations taken at different frames (positions, orientations
583 * and velocities).
584 * @param bias known accelerometer bias.
585 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
586 * accelerometer and gyroscope.
587 * @param listener listener to handle events raised by this calibrator.
588 * @throws IllegalArgumentException if provided array does not have length 3.
589 */
590 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
591 final List<StandardDeviationFrameBodyKinematics> measurements, final double[] bias,
592 final boolean commonAxisUsed, final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
593 super(measurements, bias, commonAxisUsed, listener);
594 }
595
596 /**
597 * Constructor.
598 *
599 * @param bias known accelerometer bias.
600 * @throws IllegalArgumentException if provided matrix is not 3x1.
601 */
602 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(final Matrix bias) {
603 super(bias);
604 }
605
606 /**
607 * Constructor.
608 *
609 * @param bias known accelerometer bias.
610 * @param listener listener to be notified of events such as when estimation
611 * starts, ends or its progress significantly changes.
612 * @throws IllegalArgumentException if provided matrix is not 3x1.
613 */
614 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
615 final Matrix bias, final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
616 super(bias, listener);
617 }
618
619 /**
620 * Constructor.
621 *
622 * @param measurements list of body kinematics measurements with standard
623 * deviations taken at different frames (positions, orientations
624 * and velocities).
625 * @param bias known accelerometer bias.
626 * @throws IllegalArgumentException if provided matrix is not 3x1.
627 */
628 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
629 final List<StandardDeviationFrameBodyKinematics> measurements, final Matrix bias) {
630 super(measurements, bias);
631 }
632
633 /**
634 * Constructor.
635 *
636 * @param measurements list of body kinematics measurements with standard
637 * deviations taken at different frames (positions, orientations
638 * and velocities).
639 * @param bias known accelerometer bias.
640 * @param listener listener to handle events raised by this calibrator.
641 * @throws IllegalArgumentException if provided matrix is not 3x1.
642 */
643 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
644 final List<StandardDeviationFrameBodyKinematics> measurements, final Matrix bias,
645 final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
646 super(measurements, bias, listener);
647 }
648
649 /**
650 * Constructor.
651 *
652 * @param bias known accelerometer bias.
653 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
654 * accelerometer and gyroscope.
655 * @throws IllegalArgumentException if provided matrix is not 3x1.
656 */
657 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(final Matrix bias, final boolean commonAxisUsed) {
658 super(bias, commonAxisUsed);
659 }
660
661 /**
662 * Constructor.
663 *
664 * @param bias known accelerometer bias.
665 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
666 * accelerometer and gyroscope.
667 * @param listener listener to handle events raised by this calibrator.
668 * @throws IllegalArgumentException if provided matrix is not 3x1.
669 */
670 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
671 final Matrix bias, final boolean commonAxisUsed,
672 final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
673 super(bias, commonAxisUsed, listener);
674 }
675
676 /**
677 * Constructor.
678 *
679 * @param measurements list of body kinematics measurements with standard
680 * deviations taken at different frames (positions, orientations
681 * and velocities).
682 * @param bias known accelerometer bias.
683 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
684 * accelerometer and gyroscope.
685 * @throws IllegalArgumentException if provided matrix is not 3x1.
686 */
687 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
688 final List<StandardDeviationFrameBodyKinematics> measurements, final Matrix bias,
689 final boolean commonAxisUsed) {
690 super(measurements, bias, commonAxisUsed);
691 }
692
693 /**
694 * Constructor.
695 *
696 * @param measurements list of body kinematics measurements with standard
697 * deviations taken at different frames (positions, orientations
698 * and velocities).
699 * @param bias known accelerometer bias.
700 * @param commonAxisUsed indicates whether z-axis is assumed to be common for
701 * accelerometer and gyroscope.
702 * @param listener listener to handle events raised by this calibrator.
703 * @throws IllegalArgumentException if provided matrix is not 3x1.
704 */
705 public LMedSRobustKnownBiasAndFrameAccelerometerCalibrator(
706 final List<StandardDeviationFrameBodyKinematics> measurements, final Matrix bias,
707 final boolean commonAxisUsed, final RobustKnownBiasAndFrameAccelerometerCalibratorListener listener) {
708 super(measurements, bias, commonAxisUsed, listener);
709 }
710
711 /**
712 * Returns threshold to be used to keep the algorithm iterating in case that
713 * best estimated threshold using median of residuals is not small enough.
714 * Once a solution is found that generates a threshold below this value, the
715 * algorithm will stop.
716 * The stop threshold can be used to prevent the LMedS algorithm to iterate
717 * too many times in cases where samples have a very similar accuracy.
718 * For instance, in cases where proportion of outliers is very small (close
719 * to 0%), and samples are very accurate (i.e. 1e-6), the algorithm would
720 * iterate for a long time trying to find the best solution when indeed
721 * there is no need to do that if a reasonable threshold has already been
722 * reached.
723 * Because of this behaviour the stop threshold can be set to a value much
724 * lower than the one typically used in RANSAC, and yet the algorithm could
725 * still produce even smaller thresholds in estimated results.
726 *
727 * @return stop threshold to stop the algorithm prematurely when a certain
728 * accuracy has been reached.
729 */
730 public double getStopThreshold() {
731 return stopThreshold;
732 }
733
734 /**
735 * Sets threshold to be used to keep the algorithm iterating in case that
736 * best estimated threshold using median of residuals is not small enough.
737 * Once a solution is found that generates a threshold below this value,
738 * the algorithm will stop.
739 * The stop threshold can be used to prevent the LMedS algorithm to iterate
740 * too many times in cases where samples have a very similar accuracy.
741 * For instance, in cases where proportion of outliers is very small (close
742 * to 0%), and samples are very accurate (i.e. 1e-6), the algorithm would
743 * iterate for a long time trying to find the best solution when indeed
744 * there is no need to do that if a reasonable threshold has already been
745 * reached.
746 * Because of this behaviour the stop threshold can be set to a value much
747 * lower than the one typically used in RANSAC, and yet the algorithm could
748 * still produce even smaller thresholds in estimated results.
749 *
750 * @param stopThreshold stop threshold to stop the algorithm prematurely
751 * when a certain accuracy has been reached.
752 * @throws IllegalArgumentException if provided value is zero or negative.
753 * @throws LockedException if calibrator is currently running.
754 */
755 public void setStopThreshold(final double stopThreshold) throws LockedException {
756 if (running) {
757 throw new LockedException();
758 }
759 if (stopThreshold <= MIN_STOP_THRESHOLD) {
760 throw new IllegalArgumentException();
761 }
762
763 this.stopThreshold = stopThreshold;
764 }
765
766 /**
767 * Estimates accelerometer calibration parameters containing scale factors
768 * and cross-coupling errors.
769 *
770 * @throws LockedException if calibrator is currently running.
771 * @throws NotReadyException if calibrator is not ready.
772 * @throws CalibrationException if estimation fails for numerical reasons.
773 */
774 @SuppressWarnings("DuplicatedCode")
775 @Override
776 public void calibrate() throws LockedException, NotReadyException, CalibrationException {
777 if (running) {
778 throw new LockedException();
779 }
780 if (!isReady()) {
781 throw new NotReadyException();
782 }
783
784 final var innerEstimator = new LMedSRobustEstimator<>(new LMedSRobustEstimatorListener<Matrix>() {
785 @Override
786 public int getTotalSamples() {
787 return measurements.size();
788 }
789
790 @Override
791 public int getSubsetSize() {
792 return preliminarySubsetSize;
793 }
794
795 @Override
796 public void estimatePreliminarSolutions(final int[] samplesIndices, final List<Matrix> solutions) {
797 computePreliminarySolutions(samplesIndices, solutions);
798 }
799
800 @Override
801 public double computeResidual(final Matrix currentEstimation, final int i) {
802 return computeError(measurements.get(i), currentEstimation);
803 }
804
805 @Override
806 public boolean isReady() {
807 return LMedSRobustKnownBiasAndFrameAccelerometerCalibrator.this.isReady();
808 }
809
810 @Override
811 public void onEstimateStart(final RobustEstimator<Matrix> estimator) {
812 // no action needed
813 }
814
815 @Override
816 public void onEstimateEnd(final RobustEstimator<Matrix> estimator) {
817 // no action needed
818 }
819
820 @Override
821 public void onEstimateNextIteration(final RobustEstimator<Matrix> estimator, final int iteration) {
822 if (listener != null) {
823 listener.onCalibrateNextIteration(
824 LMedSRobustKnownBiasAndFrameAccelerometerCalibrator.this, iteration);
825 }
826 }
827
828 @Override
829 public void onEstimateProgressChange(final RobustEstimator<Matrix> estimator, final float progress) {
830 if (listener != null) {
831 listener.onCalibrateProgressChange(
832 LMedSRobustKnownBiasAndFrameAccelerometerCalibrator.this, progress);
833 }
834 }
835 });
836
837 try {
838 running = true;
839
840 if (listener != null) {
841 listener.onCalibrateStart(this);
842 }
843
844 inliersData = null;
845 innerEstimator.setConfidence(confidence);
846 innerEstimator.setMaxIterations(maxIterations);
847 innerEstimator.setProgressDelta(progressDelta);
848 innerEstimator.setStopThreshold(stopThreshold);
849 final var preliminaryResult = innerEstimator.estimate();
850 inliersData = innerEstimator.getInliersData();
851
852 attemptRefine(preliminaryResult);
853
854 if (listener != null) {
855 listener.onCalibrateEnd(this);
856 }
857
858 } catch (final com.irurueta.numerical.LockedException e) {
859 throw new LockedException(e);
860 } catch (final com.irurueta.numerical.NotReadyException e) {
861 throw new NotReadyException(e);
862 } catch (final RobustEstimatorException e) {
863 throw new CalibrationException(e);
864 } finally {
865 running = false;
866 }
867 }
868
869 /**
870 * Returns method being used for robust estimation.
871 *
872 * @return method being used for robust estimation.
873 */
874 @Override
875 public RobustEstimatorMethod getMethod() {
876 return RobustEstimatorMethod.LMEDS;
877 }
878
879 /**
880 * Indicates whether this calibrator requires quality scores for each
881 * measurement or not.
882 *
883 * @return true if quality scores are required, false otherwise.
884 */
885 @Override
886 public boolean isQualityScoresRequired() {
887 return false;
888 }
889 }