1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.irurueta.navigation.inertial.calibration.intervals.thresholdfactor;
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.INSLooselyCoupledKalmanInitializerConfig;
22 import com.irurueta.navigation.inertial.INSTightlyCoupledKalmanInitializerConfig;
23 import com.irurueta.navigation.inertial.calibration.AccelerometerNoiseRootPsdSource;
24 import com.irurueta.navigation.inertial.calibration.BodyKinematicsSequence;
25 import com.irurueta.navigation.inertial.calibration.CalibrationException;
26 import com.irurueta.navigation.inertial.calibration.GyroscopeNoiseRootPsdSource;
27 import com.irurueta.navigation.inertial.calibration.StandardDeviationBodyKinematics;
28 import com.irurueta.navigation.inertial.calibration.StandardDeviationBodyMagneticFluxDensity;
29 import com.irurueta.navigation.inertial.calibration.StandardDeviationTimedBodyKinematics;
30 import com.irurueta.navigation.inertial.calibration.TimedBodyKinematicsAndMagneticFluxDensity;
31 import com.irurueta.navigation.inertial.calibration.accelerometer.AccelerometerCalibratorMeasurementType;
32 import com.irurueta.navigation.inertial.calibration.accelerometer.AccelerometerNonLinearCalibrator;
33 import com.irurueta.navigation.inertial.calibration.accelerometer.KnownBiasAccelerometerCalibrator;
34 import com.irurueta.navigation.inertial.calibration.accelerometer.OrderedStandardDeviationBodyKinematicsAccelerometerCalibrator;
35 import com.irurueta.navigation.inertial.calibration.accelerometer.QualityScoredAccelerometerCalibrator;
36 import com.irurueta.navigation.inertial.calibration.accelerometer.UnknownBiasAccelerometerCalibrator;
37 import com.irurueta.navigation.inertial.calibration.accelerometer.UnorderedStandardDeviationBodyKinematicsAccelerometerCalibrator;
38 import com.irurueta.navigation.inertial.calibration.generators.AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator;
39 import com.irurueta.navigation.inertial.calibration.generators.AccelerometerGyroscopeAndMagnetometerMeasurementsGeneratorListener;
40 import com.irurueta.navigation.inertial.calibration.gyroscope.AccelerometerDependentGyroscopeCalibrator;
41 import com.irurueta.navigation.inertial.calibration.gyroscope.GyroscopeCalibratorMeasurementOrSequenceType;
42 import com.irurueta.navigation.inertial.calibration.gyroscope.GyroscopeNonLinearCalibrator;
43 import com.irurueta.navigation.inertial.calibration.gyroscope.OrderedBodyKinematicsSequenceGyroscopeCalibrator;
44 import com.irurueta.navigation.inertial.calibration.gyroscope.QualityScoredGyroscopeCalibrator;
45 import com.irurueta.navigation.inertial.calibration.gyroscope.UnknownBiasGyroscopeCalibrator;
46 import com.irurueta.navigation.inertial.calibration.intervals.TriadStaticIntervalDetector;
47 import com.irurueta.navigation.inertial.calibration.magnetometer.KnownHardIronMagnetometerCalibrator;
48 import com.irurueta.navigation.inertial.calibration.magnetometer.MagnetometerCalibratorMeasurementType;
49 import com.irurueta.navigation.inertial.calibration.magnetometer.MagnetometerNonLinearCalibrator;
50 import com.irurueta.navigation.inertial.calibration.magnetometer.OrderedStandardDeviationBodyMagneticFluxDensityMagnetometerCalibrator;
51 import com.irurueta.navigation.inertial.calibration.magnetometer.QualityScoredMagnetometerCalibrator;
52 import com.irurueta.navigation.inertial.calibration.magnetometer.UnknownHardIronMagnetometerCalibrator;
53 import com.irurueta.navigation.inertial.calibration.magnetometer.UnorderedStandardDeviationBodyMagneticFluxDensityMagnetometerCalibrator;
54 import com.irurueta.units.Acceleration;
55 import com.irurueta.units.AccelerationUnit;
56 import com.irurueta.units.Time;
57
58 import java.util.ArrayList;
59 import java.util.List;
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 public abstract class AccelerometerGyroscopeAndMagnetometerIntervalDetectorThresholdFactorOptimizer extends
77 IntervalDetectorThresholdFactorOptimizer<TimedBodyKinematicsAndMagneticFluxDensity,
78 AccelerometerGyroscopeAndMagnetometerIntervalDetectorThresholdFactorOptimizerDataSource> implements
79 AccelerometerNoiseRootPsdSource, GyroscopeNoiseRootPsdSource {
80
81
82
83
84 public static final double DEFAULT_MIN_THRESHOLD_FACTOR = 2.0;
85
86
87
88
89 public static final double DEFAULT_MAX_THRESHOLD_FACTOR = 10.0;
90
91
92
93
94 protected double minThresholdFactor = DEFAULT_MIN_THRESHOLD_FACTOR;
95
96
97
98
99 protected double maxThresholdFactor = DEFAULT_MAX_THRESHOLD_FACTOR;
100
101
102
103
104 private AccelerometerNonLinearCalibrator accelerometerCalibrator;
105
106
107
108
109 private GyroscopeNonLinearCalibrator gyroscopeCalibrator;
110
111
112
113
114 private MagnetometerNonLinearCalibrator magnetometerCalibrator;
115
116
117
118
119 private AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator generator;
120
121
122
123
124 private List<StandardDeviationBodyKinematics> accelerometerMeasurements;
125
126
127
128
129 private List<BodyKinematicsSequence<StandardDeviationTimedBodyKinematics>> gyroscopeSequences;
130
131
132
133
134 private List<StandardDeviationBodyMagneticFluxDensity> magnetometerMeasurements;
135
136
137
138
139
140 private QualityScoreMapper<StandardDeviationBodyKinematics> accelerometerQualityScoreMapper =
141 new DefaultAccelerometerQualityScoreMapper();
142
143
144
145
146
147 private QualityScoreMapper<BodyKinematicsSequence<StandardDeviationTimedBodyKinematics>>
148 gyroscopeQualityScoreMapper = new DefaultGyroscopeQualityScoreMapper();
149
150
151
152
153
154 private QualityScoreMapper<StandardDeviationBodyMagneticFluxDensity> magnetometerQualityScoreMapper =
155 new DefaultMagnetometerQualityScoreMapper();
156
157
158
159
160
161 private AccelerometerGyroscopeAndMagnetometerMseRule mseRule =
162 new DefaultAccelerometerGyroscopeAndMagnetometerMseRule();
163
164
165
166
167
168 private double angularSpeedNoiseRootPsd;
169
170
171
172
173
174
175
176
177 private double baseNoiseLevel;
178
179
180
181
182
183
184 private double threshold;
185
186
187
188
189 private Matrix estimatedAccelerometerCovariance;
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230 private Matrix estimatedAccelerometerMa;
231
232
233
234
235
236 private double[] estimatedAccelerometerBiases;
237
238
239
240
241 private Matrix estimatedGyroscopeCovariance;
242
243
244
245
246
247 private double[] estimatedGyroscopeBiases;
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288 private Matrix estimatedGyroscopeMg;
289
290
291
292
293
294
295 private Matrix estimatedGyroscopeGg;
296
297
298
299
300 private Matrix estimatedMagnetometerCovariance;
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342 private Matrix estimatedMagnetometerMm;
343
344
345
346
347
348 private double[] estimatedMagnetometerHardIron;
349
350
351
352
353 protected AccelerometerGyroscopeAndMagnetometerIntervalDetectorThresholdFactorOptimizer() {
354 initialize();
355 }
356
357
358
359
360
361
362 protected AccelerometerGyroscopeAndMagnetometerIntervalDetectorThresholdFactorOptimizer(
363 final AccelerometerGyroscopeAndMagnetometerIntervalDetectorThresholdFactorOptimizerDataSource dataSource) {
364 super(dataSource);
365 initialize();
366 }
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385 protected AccelerometerGyroscopeAndMagnetometerIntervalDetectorThresholdFactorOptimizer(
386 final AccelerometerNonLinearCalibrator accelerometerCalibrator,
387 final GyroscopeNonLinearCalibrator gyroscopeCalibrator,
388 final MagnetometerNonLinearCalibrator magnetometerCalibrator) {
389 try {
390 setAccelerometerCalibrator(accelerometerCalibrator);
391 setGyroscopeCalibrator(gyroscopeCalibrator);
392 setMagnetometerCalibrator(magnetometerCalibrator);
393 } catch (final LockedException ignore) {
394
395 }
396 initialize();
397 }
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417 protected AccelerometerGyroscopeAndMagnetometerIntervalDetectorThresholdFactorOptimizer(
418 final AccelerometerGyroscopeAndMagnetometerIntervalDetectorThresholdFactorOptimizerDataSource dataSource,
419 final AccelerometerNonLinearCalibrator accelerometerCalibrator,
420 final GyroscopeNonLinearCalibrator gyroscopeCalibrator,
421 final MagnetometerNonLinearCalibrator magnetometerCalibrator) {
422 super(dataSource);
423 try {
424 setAccelerometerCalibrator(accelerometerCalibrator);
425 setGyroscopeCalibrator(gyroscopeCalibrator);
426 setMagnetometerCalibrator(magnetometerCalibrator);
427 } catch (final LockedException ignore) {
428
429 }
430 initialize();
431 }
432
433
434
435
436
437
438 public AccelerometerNonLinearCalibrator getAccelerometerCalibrator() {
439 return accelerometerCalibrator;
440 }
441
442
443
444
445
446
447
448
449
450 public void setAccelerometerCalibrator(
451 final AccelerometerNonLinearCalibrator accelerometerCalibrator) throws LockedException {
452 if (running) {
453 throw new LockedException();
454 }
455
456 if (accelerometerCalibrator != null && accelerometerCalibrator.getMeasurementType()
457 != AccelerometerCalibratorMeasurementType.STANDARD_DEVIATION_BODY_KINEMATICS) {
458 throw new IllegalArgumentException();
459 }
460
461 this.accelerometerCalibrator = accelerometerCalibrator;
462 }
463
464
465
466
467
468
469 public GyroscopeNonLinearCalibrator getGyroscopeCalibrator() {
470 return gyroscopeCalibrator;
471 }
472
473
474
475
476
477
478
479
480
481
482 public void setGyroscopeCalibrator(final GyroscopeNonLinearCalibrator gyroscopeCalibrator) throws LockedException {
483 if (running) {
484 throw new LockedException();
485 }
486
487 if (gyroscopeCalibrator != null && gyroscopeCalibrator.getMeasurementOrSequenceType()
488 != GyroscopeCalibratorMeasurementOrSequenceType.BODY_KINEMATICS_SEQUENCE) {
489 throw new IllegalArgumentException();
490 }
491
492 this.gyroscopeCalibrator = gyroscopeCalibrator;
493 }
494
495
496
497
498
499
500 public MagnetometerNonLinearCalibrator getMagnetometerCalibrator() {
501 return magnetometerCalibrator;
502 }
503
504
505
506
507
508
509
510
511
512 public void setMagnetometerCalibrator(final MagnetometerNonLinearCalibrator magnetometerCalibrator)
513 throws LockedException {
514 if (running) {
515 throw new LockedException();
516 }
517
518 if (magnetometerCalibrator != null && magnetometerCalibrator.getMeasurementType()
519 != MagnetometerCalibratorMeasurementType.STANDARD_DEVIATION_BODY_MAGNETIC_FLUX_DENSITY) {
520 throw new IllegalArgumentException();
521 }
522
523 this.magnetometerCalibrator = magnetometerCalibrator;
524 }
525
526
527
528
529
530
531
532 public QualityScoreMapper<StandardDeviationBodyKinematics> getAccelerometerQualityScoreMapper() {
533 return accelerometerQualityScoreMapper;
534 }
535
536
537
538
539
540
541
542
543
544 public void setAccelerometerQualityScoreMapper(
545 final QualityScoreMapper<StandardDeviationBodyKinematics> accelerometerQualityScoreMapper)
546 throws LockedException {
547 if (running) {
548 throw new LockedException();
549 }
550
551 this.accelerometerQualityScoreMapper = accelerometerQualityScoreMapper;
552 }
553
554
555
556
557
558
559
560 public QualityScoreMapper<BodyKinematicsSequence<StandardDeviationTimedBodyKinematics>>
561 getGyroscopeQualityScoreMapper() {
562 return gyroscopeQualityScoreMapper;
563 }
564
565
566
567
568
569
570
571
572
573 public void setGyroscopeQualityScoreMapper(
574 final QualityScoreMapper<BodyKinematicsSequence<StandardDeviationTimedBodyKinematics>>
575 gyroscopeQualityScoreMapper) throws LockedException {
576 if (running) {
577 throw new LockedException();
578 }
579
580 this.gyroscopeQualityScoreMapper = gyroscopeQualityScoreMapper;
581 }
582
583
584
585
586
587
588
589 public QualityScoreMapper<StandardDeviationBodyMagneticFluxDensity> getMagnetometerQualityScoreMapper() {
590 return magnetometerQualityScoreMapper;
591 }
592
593
594
595
596
597
598
599
600
601 public void setMagnetometerQualityScoreMapper(
602 final QualityScoreMapper<StandardDeviationBodyMagneticFluxDensity> magnetometerQualityScoreMapper)
603 throws LockedException {
604 if (running) {
605 throw new LockedException();
606 }
607
608 this.magnetometerQualityScoreMapper = magnetometerQualityScoreMapper;
609 }
610
611
612
613
614
615
616
617
618 public AccelerometerGyroscopeAndMagnetometerMseRule getMseRule() {
619 return mseRule;
620 }
621
622
623
624
625
626
627
628
629
630
631 public void setMseRule(final AccelerometerGyroscopeAndMagnetometerMseRule mseRule) throws LockedException {
632 if (running) {
633 throw new LockedException();
634 }
635
636 this.mseRule = mseRule;
637 }
638
639
640
641
642
643
644 public double getMinThresholdFactor() {
645 return minThresholdFactor;
646 }
647
648
649
650
651
652
653 public double getMaxThresholdFactor() {
654 return maxThresholdFactor;
655 }
656
657
658
659
660
661
662
663
664
665
666
667
668 public void setThresholdFactorRange(final double minThresholdFactor, final double maxThresholdFactor)
669 throws LockedException {
670 if (running) {
671 throw new LockedException();
672 }
673 if (minThresholdFactor < 0.0 || maxThresholdFactor < 0.0 || minThresholdFactor >= maxThresholdFactor) {
674 throw new IllegalArgumentException();
675 }
676
677 this.minThresholdFactor = minThresholdFactor;
678 this.maxThresholdFactor = maxThresholdFactor;
679 }
680
681
682
683
684
685
686 @Override
687 public boolean isReady() {
688 return super.isReady() && accelerometerCalibrator != null
689 && gyroscopeCalibrator != null
690 && magnetometerCalibrator != null
691 && accelerometerQualityScoreMapper != null
692 && gyroscopeQualityScoreMapper != null
693 && magnetometerQualityScoreMapper != null
694 && mseRule != null;
695 }
696
697
698
699
700
701
702
703 public double getTimeInterval() {
704 return generator.getTimeInterval();
705 }
706
707
708
709
710
711
712
713
714
715 public void setTimeInterval(final double timeInterval) throws LockedException {
716 if (running) {
717 throw new LockedException();
718 }
719
720 generator.setTimeInterval(timeInterval);
721 }
722
723
724
725
726
727
728
729 public Time getTimeIntervalAsTime() {
730 return generator.getTimeIntervalAsTime();
731 }
732
733
734
735
736
737
738
739 public void getTimeIntervalAsTime(final Time result) {
740 generator.getTimeIntervalAsTime(result);
741 }
742
743
744
745
746
747
748
749
750
751 public void setTimeInterval(final Time timeInterval) throws LockedException {
752 if (running) {
753 throw new LockedException();
754 }
755
756 generator.setTimeInterval(timeInterval);
757 }
758
759
760
761
762
763
764
765
766
767
768 public int getMinStaticSamples() {
769 return generator.getMinStaticSamples();
770 }
771
772
773
774
775
776
777
778
779
780
781
782
783 public void setMinStaticSamples(final int minStaticSamples) throws LockedException {
784 if (running) {
785 throw new LockedException();
786 }
787
788 generator.setMinStaticSamples(minStaticSamples);
789 }
790
791
792
793
794
795
796
797 public int getMaxDynamicSamples() {
798 return generator.getMaxDynamicSamples();
799 }
800
801
802
803
804
805
806
807
808
809
810 public void setMaxDynamicSamples(final int maxDynamicSamples) throws LockedException {
811 if (running) {
812 throw new LockedException();
813 }
814
815 generator.setMaxDynamicSamples(maxDynamicSamples);
816 }
817
818
819
820
821
822
823
824
825 public int getWindowSize() {
826 return generator.getWindowSize();
827 }
828
829
830
831
832
833
834
835
836
837
838
839
840 public void setWindowSize(final int windowSize) throws LockedException {
841 if (running) {
842 throw new LockedException();
843 }
844
845 generator.setWindowSize(windowSize);
846 }
847
848
849
850
851
852
853
854
855 public int getInitialStaticSamples() {
856 return generator.getInitialStaticSamples();
857 }
858
859
860
861
862
863
864
865
866
867
868
869 public void setInitialStaticSamples(final int initialStaticSamples) throws LockedException {
870 if (running) {
871 throw new LockedException();
872 }
873
874 generator.setInitialStaticSamples(initialStaticSamples);
875 }
876
877
878
879
880
881
882
883
884
885 public double getInstantaneousNoiseLevelFactor() {
886 return generator.getInstantaneousNoiseLevelFactor();
887 }
888
889
890
891
892
893
894
895
896
897
898
899
900
901 public void setInstantaneousNoiseLevelFactor(final double instantaneousNoiseLevelFactor) throws LockedException {
902 if (running) {
903 throw new LockedException();
904 }
905
906 generator.setInstantaneousNoiseLevelFactor(instantaneousNoiseLevelFactor);
907 }
908
909
910
911
912
913
914
915
916
917 public double getBaseNoiseLevelAbsoluteThreshold() {
918 return generator.getBaseNoiseLevelAbsoluteThreshold();
919 }
920
921
922
923
924
925
926
927
928
929
930
931
932 public void setBaseNoiseLevelAbsoluteThreshold(final double baseNoiseLevelAbsoluteThreshold)
933 throws LockedException {
934 if (running) {
935 throw new LockedException();
936 }
937
938 generator.setBaseNoiseLevelAbsoluteThreshold(baseNoiseLevelAbsoluteThreshold);
939 }
940
941
942
943
944
945
946
947
948 public Acceleration getBaseNoiseLevelAbsoluteThresholdAsMeasurement() {
949 return generator.getBaseNoiseLevelAbsoluteThresholdAsMeasurement();
950 }
951
952
953
954
955
956
957
958 public void getBaseNoiseLevelAbsoluteThresholdAsMeasurement(final Acceleration result) {
959 generator.getBaseNoiseLevelAbsoluteThresholdAsMeasurement(result);
960 }
961
962
963
964
965
966
967
968
969
970
971
972 public void setBaseNoiseLevelAbsoluteThreshold(final Acceleration baseNoiseLevelAbsoluteThreshold)
973 throws LockedException {
974 if (running) {
975 throw new LockedException();
976 }
977
978 generator.setBaseNoiseLevelAbsoluteThreshold(baseNoiseLevelAbsoluteThreshold);
979 }
980
981
982
983
984
985
986
987
988
989
990
991 public double getAccelerometerBaseNoiseLevel() {
992 return baseNoiseLevel;
993 }
994
995
996
997
998
999
1000
1001
1002
1003
1004 public Acceleration getAccelerometerBaseNoiseLevelAsMeasurement() {
1005 return createMeasurement(baseNoiseLevel, getDefaultUnit());
1006 }
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016 public void getAccelerometerBaseNoiseLevelAsMeasurement(final Acceleration result) {
1017 result.setValue(baseNoiseLevel);
1018 result.setUnit(getDefaultUnit());
1019 }
1020
1021
1022
1023
1024
1025
1026
1027 public double getGyroscopeBaseNoiseLevelPsd() {
1028 return angularSpeedNoiseRootPsd * angularSpeedNoiseRootPsd;
1029 }
1030
1031
1032
1033
1034
1035
1036
1037 @Override
1038 public double getGyroscopeBaseNoiseLevelRootPsd() {
1039 return angularSpeedNoiseRootPsd;
1040 }
1041
1042
1043
1044
1045
1046
1047
1048 public double getAccelerometerBaseNoiseLevelPsd() {
1049 return baseNoiseLevel * baseNoiseLevel * getTimeInterval();
1050 }
1051
1052
1053
1054
1055
1056
1057
1058 @Override
1059 public double getAccelerometerBaseNoiseLevelRootPsd() {
1060 return baseNoiseLevel * Math.sqrt(getTimeInterval());
1061 }
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071 public double getThreshold() {
1072 return threshold;
1073 }
1074
1075
1076
1077
1078
1079
1080
1081
1082 public Acceleration getThresholdAsMeasurement() {
1083 return createMeasurement(threshold, getDefaultUnit());
1084 }
1085
1086
1087
1088
1089
1090
1091
1092 public void getThresholdAsMeasurement(final Acceleration result) {
1093 result.setValue(threshold);
1094 result.setUnit(getDefaultUnit());
1095 }
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106 public Double getEstimatedAccelerometerBiasStandardDeviationNorm() {
1107 return estimatedAccelerometerCovariance != null
1108 ? Math.sqrt(getEstimatedAccelerometerBiasFxVariance()
1109 + getEstimatedAccelerometerBiasFyVariance()
1110 + getEstimatedAccelerometerBiasFzVariance())
1111 : null;
1112 }
1113
1114
1115
1116
1117
1118
1119 public Double getEstimatedAccelerometerBiasFxVariance() {
1120 return estimatedAccelerometerCovariance != null
1121 ? estimatedAccelerometerCovariance.getElementAt(0, 0) : null;
1122 }
1123
1124
1125
1126
1127
1128
1129 public Double getEstimatedAccelerometerBiasFyVariance() {
1130 return estimatedAccelerometerCovariance != null
1131 ? estimatedAccelerometerCovariance.getElementAt(1, 1) : null;
1132 }
1133
1134
1135
1136
1137
1138
1139 public Double getEstimatedAccelerometerBiasFzVariance() {
1140 return estimatedAccelerometerCovariance != null
1141 ? estimatedAccelerometerCovariance.getElementAt(2, 2) : null;
1142 }
1143
1144
1145
1146
1147
1148
1149
1150 public double[] getEstimatedAccelerometerBiases() {
1151 return estimatedAccelerometerBiases;
1152 }
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196 public Matrix getEstimatedAccelerometerMa() {
1197 return estimatedAccelerometerMa;
1198 }
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209 public Double getEstimatedGyroscopeBiasStandardDeviationNorm() {
1210 return estimatedGyroscopeCovariance != null
1211 ? Math.sqrt(getEstimatedGyroscopeBiasXVariance()
1212 + getEstimatedGyroscopeBiasYVariance()
1213 + getEstimatedGyroscopeBiasZVariance())
1214 : null;
1215 }
1216
1217
1218
1219
1220
1221
1222 public Double getEstimatedGyroscopeBiasXVariance() {
1223 return estimatedGyroscopeCovariance != null
1224 ? estimatedGyroscopeCovariance.getElementAt(0, 0) : null;
1225 }
1226
1227
1228
1229
1230
1231
1232 public Double getEstimatedGyroscopeBiasYVariance() {
1233 return estimatedGyroscopeCovariance != null
1234 ? estimatedGyroscopeCovariance.getElementAt(1, 1) : null;
1235 }
1236
1237
1238
1239
1240
1241
1242 public Double getEstimatedGyroscopeBiasZVariance() {
1243 return estimatedGyroscopeCovariance != null
1244 ? estimatedGyroscopeCovariance.getElementAt(2, 2) : null;
1245 }
1246
1247
1248
1249
1250
1251
1252
1253 public double[] getEstimatedGyroscopeBiases() {
1254 return estimatedGyroscopeBiases;
1255 }
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298 public Matrix getEstimatedGyroscopeMg() {
1299 return estimatedGyroscopeMg;
1300 }
1301
1302
1303
1304
1305
1306
1307
1308 public Matrix getEstimatedGyroscopeGg() {
1309 return estimatedGyroscopeGg;
1310 }
1311
1312
1313
1314
1315
1316
1317
1318
1319 public double[] getEstimatedMagnetometerHardIron() {
1320 return estimatedMagnetometerHardIron;
1321 }
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366 public Matrix getEstimatedMagnetometerMm() {
1367 return estimatedMagnetometerMm;
1368 }
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382 protected double evaluateForThresholdFactor(final double thresholdFactor) throws LockedException,
1383 CalibrationException, NotReadyException, IntervalDetectorThresholdFactorOptimizerException {
1384 if (accelerometerMeasurements == null) {
1385 accelerometerMeasurements = new ArrayList<>();
1386 } else {
1387 accelerometerMeasurements.clear();
1388 }
1389
1390 if (gyroscopeSequences == null) {
1391 gyroscopeSequences = new ArrayList<>();
1392 } else {
1393 gyroscopeSequences.clear();
1394 }
1395
1396 if (magnetometerMeasurements == null) {
1397 magnetometerMeasurements = new ArrayList<>();
1398 } else {
1399 magnetometerMeasurements.clear();
1400 }
1401
1402 generator.reset();
1403 generator.setThresholdFactor(thresholdFactor);
1404
1405 var count = dataSource.count();
1406 var failed = false;
1407 for (var i = 0; i < count; i++) {
1408 final var timedBodyKinematics = dataSource.getAt(i);
1409 if (!generator.process(timedBodyKinematics)) {
1410 failed = true;
1411 break;
1412 }
1413 }
1414
1415 if (failed || generator.getStatus() == TriadStaticIntervalDetector.Status.FAILED) {
1416
1417 return Double.MAX_VALUE;
1418 }
1419
1420
1421 if (accelerometerMeasurements.size() < accelerometerCalibrator.getMinimumRequiredMeasurements()
1422 || gyroscopeSequences.size() < gyroscopeCalibrator.getMinimumRequiredMeasurementsOrSequences()
1423 || magnetometerMeasurements.size() < magnetometerCalibrator.getMinimumRequiredMeasurements()) {
1424 return Double.MAX_VALUE;
1425 }
1426
1427
1428 switch (accelerometerCalibrator.getMeasurementType()) {
1429 case STANDARD_DEVIATION_BODY_KINEMATICS:
1430 if (accelerometerCalibrator.isOrderedMeasurementsRequired()) {
1431 final var calibrator =
1432 (OrderedStandardDeviationBodyKinematicsAccelerometerCalibrator) accelerometerCalibrator;
1433
1434 calibrator.setMeasurements(accelerometerMeasurements);
1435
1436 } else {
1437 final var calibrator =
1438 (UnorderedStandardDeviationBodyKinematicsAccelerometerCalibrator) accelerometerCalibrator;
1439
1440 calibrator.setMeasurements(accelerometerMeasurements);
1441 }
1442
1443 if (accelerometerCalibrator.isQualityScoresRequired()) {
1444 final var calibrator = (QualityScoredAccelerometerCalibrator) accelerometerCalibrator;
1445
1446 final var size = accelerometerMeasurements.size();
1447 final var qualityScores = new double[size];
1448 for (var i = 0; i < size; i++) {
1449 qualityScores[i] = accelerometerQualityScoreMapper.map(accelerometerMeasurements.get(i));
1450 }
1451 calibrator.setQualityScores(qualityScores);
1452 }
1453 break;
1454 case FRAME_BODY_KINEMATICS, STANDARD_DEVIATION_FRAME_BODY_KINEMATICS:
1455
1456 default:
1457 throw new IntervalDetectorThresholdFactorOptimizerException();
1458 }
1459
1460 if (gyroscopeCalibrator.getMeasurementOrSequenceType()
1461 == GyroscopeCalibratorMeasurementOrSequenceType.BODY_KINEMATICS_SEQUENCE) {
1462 final var calibrator = (OrderedBodyKinematicsSequenceGyroscopeCalibrator) gyroscopeCalibrator;
1463
1464 calibrator.setSequences(gyroscopeSequences);
1465 } else {
1466 throw new IntervalDetectorThresholdFactorOptimizerException();
1467 }
1468
1469 if (gyroscopeCalibrator.isQualityScoresRequired()) {
1470 final var calibrator = (QualityScoredGyroscopeCalibrator) gyroscopeCalibrator;
1471
1472 final var size = gyroscopeSequences.size();
1473 final var qualityScores = new double[size];
1474 for (var i = 0; i < size; i++) {
1475 qualityScores[i] = gyroscopeQualityScoreMapper.map(gyroscopeSequences.get(i));
1476 }
1477 calibrator.setQualityScores(qualityScores);
1478 }
1479
1480 switch (magnetometerCalibrator.getMeasurementType()) {
1481 case STANDARD_DEVIATION_BODY_MAGNETIC_FLUX_DENSITY:
1482 if (magnetometerCalibrator.isOrderedMeasurementsRequired()) {
1483 final var calibrator = (OrderedStandardDeviationBodyMagneticFluxDensityMagnetometerCalibrator)
1484 magnetometerCalibrator;
1485
1486 calibrator.setMeasurements(magnetometerMeasurements);
1487 } else {
1488 final var calibrator = (UnorderedStandardDeviationBodyMagneticFluxDensityMagnetometerCalibrator)
1489 magnetometerCalibrator;
1490
1491 calibrator.setMeasurements(magnetometerMeasurements);
1492 }
1493
1494 if (magnetometerCalibrator.isQualityScoresRequired()) {
1495 final var calibrator = (QualityScoredMagnetometerCalibrator) magnetometerCalibrator;
1496
1497 final var size = magnetometerMeasurements.size();
1498 final var qualityScores = new double[size];
1499 for (var i = 0; i < size; i++) {
1500 qualityScores[i] = magnetometerQualityScoreMapper.map(magnetometerMeasurements.get(i));
1501 }
1502 calibrator.setQualityScores(qualityScores);
1503 }
1504 break;
1505 case FRAME_BODY_MAGNETIC_FLUX_DENSITY, STANDARD_DEVIATION_FRAME_BODY_MAGNETIC_FLUX_DENSITY:
1506
1507 default:
1508 throw new IntervalDetectorThresholdFactorOptimizerException();
1509 }
1510
1511 accelerometerCalibrator.calibrate();
1512
1513
1514
1515 if (gyroscopeCalibrator instanceof AccelerometerDependentGyroscopeCalibrator accelGyroCalibrator) {
1516
1517 final double[] bias;
1518 if (accelerometerCalibrator instanceof UnknownBiasAccelerometerCalibrator unknownBiasAccelerometerCalibrator) {
1519 bias = unknownBiasAccelerometerCalibrator.getEstimatedBiases();
1520
1521 } else if (accelerometerCalibrator instanceof KnownBiasAccelerometerCalibrator knownBiasAccelerometerCalibrator) {
1522 bias = knownBiasAccelerometerCalibrator.getBias();
1523 } else {
1524 bias = null;
1525 }
1526
1527 if (bias != null) {
1528 accelGyroCalibrator.setAccelerometerBias(bias);
1529 accelGyroCalibrator.setAccelerometerMa(accelerometerCalibrator.getEstimatedMa());
1530 }
1531 }
1532
1533 gyroscopeCalibrator.calibrate();
1534 magnetometerCalibrator.calibrate();
1535
1536 final var accelerometerMse = accelerometerCalibrator.getEstimatedMse();
1537 final var gyroscopeMse = gyroscopeCalibrator.getEstimatedMse();
1538 final var magnetometerMse = magnetometerCalibrator.getEstimatedMse();
1539
1540
1541 final var mse = mseRule.evaluate(accelerometerMse, gyroscopeMse, magnetometerMse);
1542 if (mse < minMse) {
1543 keepBestResult(mse, thresholdFactor);
1544 }
1545 return mse;
1546 }
1547
1548
1549
1550
1551
1552
1553
1554 private void initialize() {
1555 final var generatorListener = new AccelerometerGyroscopeAndMagnetometerMeasurementsGeneratorListener() {
1556 @Override
1557 public void onInitializationStarted(
1558 final AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator generator) {
1559
1560 }
1561
1562 @Override
1563 public void onInitializationCompleted(
1564 final AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator generator,
1565 final double accelerometerBaseNoiseLevel) {
1566
1567 }
1568
1569 @Override
1570 public void onError(
1571 final AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator generator,
1572 final TriadStaticIntervalDetector.ErrorReason reason) {
1573
1574 }
1575
1576 @Override
1577 public void onStaticIntervalDetected(
1578 final AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator generator) {
1579
1580 }
1581
1582 @Override
1583 public void onDynamicIntervalDetected(
1584 final AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator generator) {
1585
1586 }
1587
1588 @Override
1589 public void onStaticIntervalSkipped(
1590 final AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator generator) {
1591
1592 }
1593
1594 @Override
1595 public void onDynamicIntervalSkipped(
1596 final AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator generator) {
1597
1598 }
1599
1600 @Override
1601 public void onGeneratedAccelerometerMeasurement(
1602 final AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator generator,
1603 final StandardDeviationBodyKinematics measurement) {
1604 accelerometerMeasurements.add(measurement);
1605 }
1606
1607 @Override
1608 public void onGeneratedGyroscopeMeasurement(
1609 final AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator generator,
1610 final BodyKinematicsSequence<StandardDeviationTimedBodyKinematics> sequence) {
1611 gyroscopeSequences.add(sequence);
1612 }
1613
1614 @Override
1615 public void onGeneratedMagnetometerMeasurement(
1616 final AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator generator,
1617 final StandardDeviationBodyMagneticFluxDensity measurement) {
1618 magnetometerMeasurements.add(measurement);
1619 }
1620
1621 @Override
1622 public void onReset(final AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator generator) {
1623
1624 }
1625 };
1626
1627 generator = new AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator(generatorListener);
1628 }
1629
1630
1631
1632
1633
1634
1635
1636 private void keepBestResult(final double mse, final double thresholdFactor) {
1637 minMse = mse;
1638 optimalThresholdFactor = thresholdFactor;
1639
1640 angularSpeedNoiseRootPsd = generator.getGyroscopeBaseNoiseLevelRootPsd();
1641 baseNoiseLevel = generator.getAccelerometerBaseNoiseLevel();
1642 threshold = generator.getThreshold();
1643
1644 if (estimatedAccelerometerCovariance == null) {
1645 estimatedAccelerometerCovariance = new Matrix(accelerometerCalibrator.getEstimatedCovariance());
1646 } else {
1647 estimatedAccelerometerCovariance.copyFrom(accelerometerCalibrator.getEstimatedCovariance());
1648 }
1649 if (estimatedAccelerometerMa == null) {
1650 estimatedAccelerometerMa = new Matrix(accelerometerCalibrator.getEstimatedMa());
1651 } else {
1652 estimatedAccelerometerMa.copyFrom(accelerometerCalibrator.getEstimatedMa());
1653 }
1654 if (accelerometerCalibrator instanceof UnknownBiasAccelerometerCalibrator unknownBiasAccelerometerCalibrator) {
1655 estimatedAccelerometerBiases = unknownBiasAccelerometerCalibrator.getEstimatedBiases();
1656 } else if (accelerometerCalibrator instanceof KnownBiasAccelerometerCalibrator knownBiasAccelerometerCalibrator) {
1657 estimatedAccelerometerBiases = knownBiasAccelerometerCalibrator.getBias();
1658 }
1659
1660 if (estimatedGyroscopeCovariance == null) {
1661 estimatedGyroscopeCovariance = new Matrix(gyroscopeCalibrator.getEstimatedCovariance());
1662 } else {
1663 estimatedGyroscopeCovariance.copyFrom(gyroscopeCalibrator.getEstimatedCovariance());
1664 }
1665 if (estimatedGyroscopeMg == null) {
1666 estimatedGyroscopeMg = new Matrix(gyroscopeCalibrator.getEstimatedMg());
1667 } else {
1668 estimatedGyroscopeMg.copyFrom(gyroscopeCalibrator.getEstimatedMg());
1669 }
1670 if (estimatedGyroscopeGg == null) {
1671 estimatedGyroscopeGg = new Matrix(gyroscopeCalibrator.getEstimatedGg());
1672 } else {
1673 estimatedGyroscopeGg.copyFrom(gyroscopeCalibrator.getEstimatedGg());
1674 }
1675 if (gyroscopeCalibrator instanceof UnknownBiasGyroscopeCalibrator unknownBiasGyroscopeCalibrator) {
1676 estimatedGyroscopeBiases = unknownBiasGyroscopeCalibrator.getEstimatedBiases();
1677 } else if (gyroscopeCalibrator instanceof KnownBiasAccelerometerCalibrator knownBiasAccelerometerCalibrator) {
1678 estimatedGyroscopeBiases = knownBiasAccelerometerCalibrator.getBias();
1679 }
1680
1681 if (estimatedMagnetometerCovariance == null) {
1682 estimatedMagnetometerCovariance = new Matrix(magnetometerCalibrator.getEstimatedCovariance());
1683 } else {
1684 estimatedMagnetometerCovariance.copyFrom(magnetometerCalibrator.getEstimatedCovariance());
1685 }
1686 if (estimatedMagnetometerMm == null) {
1687 estimatedMagnetometerMm = new Matrix(magnetometerCalibrator.getEstimatedMm());
1688 } else {
1689 estimatedMagnetometerMm.copyFrom(magnetometerCalibrator.getEstimatedMm());
1690 }
1691 if (magnetometerCalibrator instanceof UnknownHardIronMagnetometerCalibrator unknownHardIronMagnetometerCalibrator) {
1692 estimatedMagnetometerHardIron = unknownHardIronMagnetometerCalibrator.getEstimatedHardIron();
1693 } else if (magnetometerCalibrator instanceof KnownHardIronMagnetometerCalibrator knownHardIronMagnetometerCalibrator) {
1694 estimatedMagnetometerHardIron = knownHardIronMagnetometerCalibrator.getHardIron();
1695 }
1696 }
1697
1698
1699
1700
1701
1702
1703
1704
1705 private Acceleration createMeasurement(final double value, final AccelerationUnit unit) {
1706 return new Acceleration(value, unit);
1707 }
1708
1709
1710
1711
1712
1713
1714
1715 private AccelerationUnit getDefaultUnit() {
1716 return AccelerationUnit.METERS_PER_SQUARED_SECOND;
1717 }
1718 }