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.generators;
17
18 import com.irurueta.navigation.LockedException;
19 import com.irurueta.navigation.inertial.calibration.AccelerometerNoiseRootPsdSource;
20 import com.irurueta.navigation.inertial.calibration.AngularSpeedTriad;
21 import com.irurueta.navigation.inertial.calibration.BodyKinematicsSequence;
22 import com.irurueta.navigation.inertial.calibration.GyroscopeNoiseRootPsdSource;
23 import com.irurueta.navigation.inertial.calibration.StandardDeviationBodyKinematics;
24 import com.irurueta.navigation.inertial.calibration.StandardDeviationBodyMagneticFluxDensity;
25 import com.irurueta.navigation.inertial.calibration.StandardDeviationTimedBodyKinematics;
26 import com.irurueta.navigation.inertial.calibration.TimedBodyKinematics;
27 import com.irurueta.navigation.inertial.calibration.TimedBodyKinematicsAndMagneticFluxDensity;
28 import com.irurueta.navigation.inertial.calibration.intervals.TriadStaticIntervalDetector;
29 import com.irurueta.units.Acceleration;
30 import com.irurueta.units.AngularSpeed;
31 import com.irurueta.units.Time;
32 import com.irurueta.units.TimeConverter;
33 import com.irurueta.units.TimeUnit;
34
35 /**
36 * Generates measurements for the calibration of accelerometers and gyroscopes by alternating
37 * static and dynamic intervals where device is kept static or moved.
38 * Generated measurements must be used with accelerometer calibrators based
39 * on the knowledge of gravity norm (or Earth position) when the device orientation
40 * is unknown, with easy gyroscope calibrators and with magnetometer calibrators based
41 * on the knowledge of position on Earth and time instant.
42 * Notice that accuracy of the gyroscope calibration is very sensitive to the
43 * accuracy of detected dynamic intervals respect the average specific forces
44 * during static intervals.
45 * In order to increase the accuracy, calibration should be repeated trying different
46 * threshold factors {@link #getThresholdFactor()}.
47 *
48 * @see AccelerometerMeasurementsGenerator
49 * @see GyroscopeMeasurementsGenerator
50 * @see MagnetometerMeasurementsGenerator
51 */
52 public class AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator implements
53 AccelerometerNoiseRootPsdSource, GyroscopeNoiseRootPsdSource {
54
55 /**
56 * Listener to handle generated events.
57 */
58 private AccelerometerGyroscopeAndMagnetometerMeasurementsGeneratorListener listener;
59
60 /**
61 * Listener for internal accelerometer measurements generator.
62 */
63 private final AccelerometerMeasurementsGeneratorListener accelerometerListener =
64 new AccelerometerMeasurementsGeneratorListener() {
65 @Override
66 public void onInitializationStarted(final AccelerometerMeasurementsGenerator generator) {
67 // no action required
68 }
69
70 @Override
71 public void onInitializationCompleted(
72 final AccelerometerMeasurementsGenerator generator, final double baseNoiseLevel) {
73 // no action required
74 }
75
76 @Override
77 public void onError(
78 final AccelerometerMeasurementsGenerator generator,
79 final TriadStaticIntervalDetector.ErrorReason reason) {
80 if (listener != null) {
81 listener.onError(
82 AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator.this, reason);
83 }
84 }
85
86 @Override
87 public void onStaticIntervalDetected(final AccelerometerMeasurementsGenerator generator) {
88 // no action required
89 }
90
91 @Override
92 public void onDynamicIntervalDetected(final AccelerometerMeasurementsGenerator generator) {
93 // no action required
94 }
95
96 @Override
97 public void onStaticIntervalSkipped(final AccelerometerMeasurementsGenerator generator) {
98 // no action required
99 }
100
101 @Override
102 public void onDynamicIntervalSkipped(final AccelerometerMeasurementsGenerator generator) {
103 // no action required
104 }
105
106 @Override
107 public void onGeneratedMeasurement(
108 final AccelerometerMeasurementsGenerator generator,
109 final StandardDeviationBodyKinematics measurement) {
110 if (listener != null) {
111 listener.onGeneratedAccelerometerMeasurement(
112 AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator.this,
113 measurement);
114 }
115 }
116
117 @Override
118 public void onReset(final AccelerometerMeasurementsGenerator generator) {
119 // no action required
120 }
121 };
122
123 /**
124 * Listener for internal gyroscope measurements generator.
125 */
126 private final GyroscopeMeasurementsGeneratorListener gyroscopeListener =
127 new GyroscopeMeasurementsGeneratorListener() {
128 @Override
129 public void onInitializationStarted(final GyroscopeMeasurementsGenerator generator) {
130 // no action required
131 }
132
133 @Override
134 public void onInitializationCompleted(
135 final GyroscopeMeasurementsGenerator generator, final double baseNoiseLevel) {
136 // no action required
137 }
138
139 @Override
140 public void onError(
141 final GyroscopeMeasurementsGenerator generator,
142 final TriadStaticIntervalDetector.ErrorReason reason) {
143 // no action required
144 }
145
146 @Override
147 public void onStaticIntervalDetected(final GyroscopeMeasurementsGenerator generator) {
148 // no action required
149 }
150
151 @Override
152 public void onDynamicIntervalDetected(final GyroscopeMeasurementsGenerator generator) {
153 // no action required
154 }
155
156 @Override
157 public void onStaticIntervalSkipped(final GyroscopeMeasurementsGenerator generator) {
158 // no action required
159 }
160
161 @Override
162 public void onDynamicIntervalSkipped(final GyroscopeMeasurementsGenerator generator) {
163 // no action required
164 }
165
166 @Override
167 public void onGeneratedMeasurement(
168 final GyroscopeMeasurementsGenerator generator,
169 final BodyKinematicsSequence<StandardDeviationTimedBodyKinematics> measurement) {
170 if (listener != null) {
171 listener.onGeneratedGyroscopeMeasurement(
172 AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator.this, measurement);
173 }
174 }
175
176 @Override
177 public void onReset(final GyroscopeMeasurementsGenerator generator) {
178 // no action required
179 }
180 };
181
182 /**
183 * Listener for internal magnetometer measurements generator.
184 */
185 private final MagnetometerMeasurementsGeneratorListener magnetometerListener =
186 new MagnetometerMeasurementsGeneratorListener() {
187 @Override
188 public void onInitializationStarted(final MagnetometerMeasurementsGenerator generator) {
189 if (listener != null) {
190 listener.onInitializationStarted(
191 AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator.this);
192 }
193 }
194
195 @Override
196 public void onInitializationCompleted(
197 final MagnetometerMeasurementsGenerator generator, final double baseNoiseLevel) {
198 if (listener != null) {
199 listener.onInitializationCompleted(
200 AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator.this,
201 baseNoiseLevel);
202 }
203 }
204
205 @Override
206 public void onError(final MagnetometerMeasurementsGenerator generator,
207 final TriadStaticIntervalDetector.ErrorReason reason) {
208 // no action required
209 }
210
211 @Override
212 public void onStaticIntervalDetected(final MagnetometerMeasurementsGenerator generator) {
213 if (listener != null) {
214 listener.onStaticIntervalDetected(
215 AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator.this);
216 }
217 }
218
219 @Override
220 public void onDynamicIntervalDetected(final MagnetometerMeasurementsGenerator generator) {
221 if (listener != null) {
222 listener.onDynamicIntervalDetected(
223 AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator.this);
224 }
225 }
226
227 @Override
228 public void onStaticIntervalSkipped(final MagnetometerMeasurementsGenerator generator) {
229 if (listener != null) {
230 listener.onStaticIntervalSkipped(
231 AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator.this);
232 }
233 }
234
235 @Override
236 public void onDynamicIntervalSkipped(final MagnetometerMeasurementsGenerator generator) {
237 if (listener != null) {
238 listener.onDynamicIntervalSkipped(
239 AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator.this);
240 }
241 }
242
243 @Override
244 public void onGeneratedMeasurement(
245 final MagnetometerMeasurementsGenerator generator,
246 final StandardDeviationBodyMagneticFluxDensity measurement) {
247 if (listener != null) {
248 listener.onGeneratedMagnetometerMeasurement(
249 AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator.this, measurement);
250 }
251 }
252
253 @Override
254 public void onReset(final MagnetometerMeasurementsGenerator generator) {
255 // no action required
256 }
257 };
258
259 /**
260 * Internal accelerometer measurements generator.
261 */
262 private final AccelerometerMeasurementsGenerator accelerometerMeasurementsGenerator =
263 new AccelerometerMeasurementsGenerator(accelerometerListener);
264
265 /**
266 * Internal gyroscope measurements generator.
267 */
268 private final GyroscopeMeasurementsGenerator gyroscopeMeasurementsGenerator =
269 new GyroscopeMeasurementsGenerator(gyroscopeListener);
270
271 /**
272 * Internal magnetometer measurements generator.
273 */
274 private final MagnetometerMeasurementsGenerator magnetometerMeasurementsGenerator =
275 new MagnetometerMeasurementsGenerator(magnetometerListener);
276
277 /**
278 * Indicates whether generator is running or not.
279 */
280 private boolean running;
281
282 /**
283 * Timed body kinematics instance to be reused.
284 */
285 private final TimedBodyKinematics timedKinematics = new TimedBodyKinematics();
286
287 /**
288 * Constructor.
289 */
290 public AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator() {
291 }
292
293 /**
294 * Constructor.
295 *
296 * @param listener listener to handle events raised by this generator.
297 */
298 public AccelerometerGyroscopeAndMagnetometerMeasurementsGenerator(
299 final AccelerometerGyroscopeAndMagnetometerMeasurementsGeneratorListener listener) {
300 this();
301 this.listener = listener;
302 }
303
304 /**
305 * Gets time interval between input samples expressed in seconds (s).
306 *
307 * @return time interval between input samples.
308 */
309 public double getTimeInterval() {
310 return accelerometerMeasurementsGenerator.getTimeInterval();
311 }
312
313 /**
314 * Sets time interval between input samples expressed in seconds (s).
315 *
316 * @param timeInterval time interval between input samples.
317 * @throws IllegalArgumentException if provided value is negative.
318 * @throws LockedException if generator is currently running.
319 */
320 public void setTimeInterval(final double timeInterval) throws LockedException {
321 if (running) {
322 throw new LockedException();
323 }
324
325 if (timeInterval < 0.0) {
326 throw new IllegalArgumentException();
327 }
328
329 accelerometerMeasurementsGenerator.setTimeInterval(timeInterval);
330 gyroscopeMeasurementsGenerator.setTimeInterval(timeInterval);
331 magnetometerMeasurementsGenerator.setTimeInterval(timeInterval);
332 }
333
334 /**
335 * Gets time interval between input samples.
336 *
337 * @return time interval between input samples.
338 */
339 public Time getTimeIntervalAsTime() {
340 return new Time(getTimeInterval(), TimeUnit.SECOND);
341 }
342
343 /**
344 * Gets time interval between input samples.
345 *
346 * @param result instance where time interval will be stored.
347 */
348 public void getTimeIntervalAsTime(final Time result) {
349 result.setValue(getTimeInterval());
350 result.setUnit(TimeUnit.SECOND);
351 }
352
353 /**
354 * Sets time interval between input samples.
355 *
356 * @param timeInterval time interval between input samples.
357 * @throws IllegalArgumentException if provided value is negative.
358 * @throws LockedException if estimator is currently running.
359 */
360 public void setTimeInterval(final Time timeInterval) throws LockedException {
361 setTimeInterval(TimeConverter.convert(timeInterval.getValue().doubleValue(), timeInterval.getUnit(),
362 TimeUnit.SECOND));
363 }
364
365 /**
366 * Gets minimum number of samples required in a static interval to be taken into account.
367 * Smaller static intervals will be discarded.
368 *
369 * @return minimum number of samples required in a static interval to be taken into account.
370 */
371 public int getMinStaticSamples() {
372 return accelerometerMeasurementsGenerator.getMinStaticSamples();
373 }
374
375 /**
376 * Sets minimum number of samples required in a static interval to be taken into account.
377 * Smaller static intervals will be discarded.
378 *
379 * @param minStaticSamples minimum number of samples required in a static interval to be
380 * taken into account.
381 * @throws LockedException if generator is busy.
382 * @throws IllegalArgumentException if provided value is less than 2.
383 */
384 public void setMinStaticSamples(final int minStaticSamples) throws LockedException {
385 if (running) {
386 throw new LockedException();
387 }
388
389 accelerometerMeasurementsGenerator.setMinStaticSamples(minStaticSamples);
390 gyroscopeMeasurementsGenerator.setMinStaticSamples(minStaticSamples);
391 magnetometerMeasurementsGenerator.setMinStaticSamples(minStaticSamples);
392 }
393
394 /**
395 * Gets maximum number of samples allowed in dynamic intervals.
396 *
397 * @return maximum number of samples allowed in dynamic intervals.
398 */
399 public int getMaxDynamicSamples() {
400 return accelerometerMeasurementsGenerator.getMaxDynamicSamples();
401 }
402
403 /**
404 * Sets maximum number of samples allowed in dynamic intervals.
405 *
406 * @param maxDynamicSamples maximum number of samples allowed in dynamic intervals.
407 * @throws LockedException if generator is busy.
408 * @throws IllegalArgumentException if provided value is less than 2.
409 */
410 public void setMaxDynamicSamples(final int maxDynamicSamples) throws LockedException {
411 if (running) {
412 throw new LockedException();
413 }
414
415 accelerometerMeasurementsGenerator.setMaxDynamicSamples(maxDynamicSamples);
416 gyroscopeMeasurementsGenerator.setMaxDynamicSamples(maxDynamicSamples);
417 magnetometerMeasurementsGenerator.setMaxDynamicSamples(maxDynamicSamples);
418 }
419
420 /**
421 * Gets listener to handle generated events.
422 *
423 * @return listener to handle generated events.
424 */
425 public AccelerometerGyroscopeAndMagnetometerMeasurementsGeneratorListener getListener() {
426 return listener;
427 }
428
429 /**
430 * Sets listener to handle generated events.
431 *
432 * @param listener listener to handle generated events.
433 * @throws LockedException if generator is busy.
434 */
435 public void setListener(final AccelerometerGyroscopeAndMagnetometerMeasurementsGeneratorListener listener)
436 throws LockedException {
437 if (running) {
438 throw new LockedException();
439 }
440
441 this.listener = listener;
442 }
443
444 /**
445 * Gets length of number of samples to keep within the window being processed
446 * to determine instantaneous accelerometer noise level.
447 *
448 * @return length of number of samples to keep within the window.
449 */
450 public int getWindowSize() {
451 return accelerometerMeasurementsGenerator.getWindowSize();
452 }
453
454 /**
455 * Sets length of number of samples to keep within the window being processed
456 * to determine instantaneous accelerometer noise level.
457 * Window size must always be larger than allowed minimum value, which is 2 and
458 * must have an odd value.
459 *
460 * @param windowSize length of number of samples to keep within the window.
461 * @throws LockedException if detector is busy processing a previous sample.
462 * @throws IllegalArgumentException if provided value is not valid.
463 */
464 public void setWindowSize(final int windowSize) throws LockedException {
465 if (running) {
466 throw new LockedException();
467 }
468
469 accelerometerMeasurementsGenerator.setWindowSize(windowSize);
470 gyroscopeMeasurementsGenerator.setWindowSize(windowSize);
471 magnetometerMeasurementsGenerator.setWindowSize(windowSize);
472 }
473
474 /**
475 * Gets number of samples to be processed initially while keeping the sensor static in order
476 * to find the base noise level when device is static.
477 *
478 * @return number of samples to be processed initially.
479 */
480 public int getInitialStaticSamples() {
481 return accelerometerMeasurementsGenerator.getInitialStaticSamples();
482 }
483
484 /**
485 * Sets number of samples to be processed initially while keeping the sensor static in order
486 * to find the base noise level when device is static.
487 *
488 * @param initialStaticSamples number of samples to be processed initially.
489 * @throws LockedException if detector is busy.
490 * @throws IllegalArgumentException if provided value is less than
491 * {@link TriadStaticIntervalDetector#MINIMUM_INITIAL_STATIC_SAMPLES}
492 */
493 public void setInitialStaticSamples(final int initialStaticSamples) throws LockedException {
494 if (running) {
495 throw new LockedException();
496 }
497
498 accelerometerMeasurementsGenerator.setInitialStaticSamples(initialStaticSamples);
499 gyroscopeMeasurementsGenerator.setInitialStaticSamples(initialStaticSamples);
500 magnetometerMeasurementsGenerator.setInitialStaticSamples(initialStaticSamples);
501 }
502
503 /**
504 * Gets factor to be applied to detected base noise level in order to
505 * determine threshold for static/dynamic period changes. This factor is
506 * unit-less.
507 *
508 * @return factor to be applied to detected base noise level.
509 */
510 public double getThresholdFactor() {
511 return accelerometerMeasurementsGenerator.getThresholdFactor();
512 }
513
514 /**
515 * Sets factor to be applied to detected base noise level in order to
516 * determine threshold for static/dynamic period changes. This factor is
517 * unit-less.
518 *
519 * @param thresholdFactor factor to be applied to detected base noise level.
520 * @throws LockedException if detector is busy.
521 * @throws IllegalArgumentException if provided value is zero or negative.
522 */
523 public void setThresholdFactor(final double thresholdFactor) throws LockedException {
524 if (running) {
525 throw new LockedException();
526 }
527
528 accelerometerMeasurementsGenerator.setThresholdFactor(thresholdFactor);
529 gyroscopeMeasurementsGenerator.setThresholdFactor(thresholdFactor);
530 magnetometerMeasurementsGenerator.setThresholdFactor(thresholdFactor);
531 }
532
533 /**
534 * Gets factor to determine that a sudden movement has occurred during
535 * initialization if instantaneous noise level exceeds accumulated noise
536 * level by this factor amount.
537 * This factor is unit-less.
538 *
539 * @return factor to determine that a sudden movement has occurred.
540 */
541 public double getInstantaneousNoiseLevelFactor() {
542 return accelerometerMeasurementsGenerator.getInstantaneousNoiseLevelFactor();
543 }
544
545 /**
546 * Sets factor to determine that a sudden movement has occurred during
547 * initialization if instantaneous noise level exceeds accumulated noise
548 * level by this factor amount.
549 * This factor is unit-less.
550 *
551 * @param instantaneousNoiseLevelFactor factor to determine that a sudden
552 * movement has occurred during
553 * initialization.
554 * @throws LockedException if detector is busy.
555 * @throws IllegalArgumentException if provided value is zero or negative.
556 */
557 public void setInstantaneousNoiseLevelFactor(final double instantaneousNoiseLevelFactor) throws LockedException {
558 if (running) {
559 throw new LockedException();
560 }
561
562 accelerometerMeasurementsGenerator.setInstantaneousNoiseLevelFactor(instantaneousNoiseLevelFactor);
563 gyroscopeMeasurementsGenerator.setInstantaneousNoiseLevelFactor(instantaneousNoiseLevelFactor);
564 magnetometerMeasurementsGenerator.setInstantaneousNoiseLevelFactor(instantaneousNoiseLevelFactor);
565 }
566
567 /**
568 * Gets overall absolute threshold to determine whether there has been
569 * excessive motion during the whole initialization phase.
570 * Failure will be detected if estimated base noise level exceeds this
571 * threshold when initialization completes.
572 * This threshold is expressed in meters per squared second (m/s^2).
573 *
574 * @return overall absolute threshold to determine whether there has
575 * been excessive motion.
576 */
577 public double getBaseNoiseLevelAbsoluteThreshold() {
578 return accelerometerMeasurementsGenerator.getBaseNoiseLevelAbsoluteThreshold();
579 }
580
581 /**
582 * Sets overall absolute threshold to determine whether there has been
583 * excessive motion during the whole initialization phase.
584 * Failure will be detected if estimated base noise level exceeds this
585 * threshold when initialization completes.
586 * This threshold is expressed in meters per squared second (m/s^2).
587 *
588 * @param baseNoiseLevelAbsoluteThreshold overall absolute threshold to
589 * determine whether there has been
590 * excessive motion.
591 * @throws LockedException if detector is busy.
592 * @throws IllegalArgumentException if provided value is zero or negative.
593 */
594 public void setBaseNoiseLevelAbsoluteThreshold(final double baseNoiseLevelAbsoluteThreshold)
595 throws LockedException {
596 if (running) {
597 throw new LockedException();
598 }
599
600 accelerometerMeasurementsGenerator.setBaseNoiseLevelAbsoluteThreshold(baseNoiseLevelAbsoluteThreshold);
601 gyroscopeMeasurementsGenerator.setBaseNoiseLevelAbsoluteThreshold(baseNoiseLevelAbsoluteThreshold);
602 magnetometerMeasurementsGenerator.setBaseNoiseLevelAbsoluteThreshold(baseNoiseLevelAbsoluteThreshold);
603 }
604
605 /**
606 * Gets overall absolute threshold to determine whether there has been
607 * excessive motion during the whole initialization phase.
608 * Failure will be detected if estimated base noise level exceeds this
609 * threshold when initialization completes.
610 *
611 * @return overall absolute threshold to determine whether there has been
612 * excessive motion.
613 */
614 public Acceleration getBaseNoiseLevelAbsoluteThresholdAsMeasurement() {
615 return accelerometerMeasurementsGenerator.getBaseNoiseLevelAbsoluteThresholdAsMeasurement();
616 }
617
618 /**
619 * Gets overall absolute threshold to determine whether there has been
620 * excessive motion during the whole initialization phase.
621 * Failure will be detected if estimated base noise level exceeds this
622 * threshold when initialization completes.
623 *
624 * @param result instance where result will be stored.
625 */
626 public void getBaseNoiseLevelAbsoluteThresholdAsMeasurement(final Acceleration result) {
627 accelerometerMeasurementsGenerator.getBaseNoiseLevelAbsoluteThresholdAsMeasurement(result);
628 }
629
630 /**
631 * Sets overall absolute threshold to determine whether there has been
632 * excessive motion during the whole initialization phase.
633 * Failure will be detected if estimated base noise level exceeds this
634 * threshold when initialization completes.
635 *
636 * @param baseNoiseLevelAbsoluteThreshold overall absolute threshold to
637 * determine whether there has been
638 * excessive motion.
639 * @throws LockedException if detector is busy.
640 * @throws IllegalArgumentException if provided value is zero or negative.
641 */
642 public void setBaseNoiseLevelAbsoluteThreshold(final Acceleration baseNoiseLevelAbsoluteThreshold)
643 throws LockedException {
644 if (running) {
645 throw new LockedException();
646 }
647
648 accelerometerMeasurementsGenerator.setBaseNoiseLevelAbsoluteThreshold(baseNoiseLevelAbsoluteThreshold);
649 gyroscopeMeasurementsGenerator.setBaseNoiseLevelAbsoluteThreshold(baseNoiseLevelAbsoluteThreshold);
650 magnetometerMeasurementsGenerator.setBaseNoiseLevelAbsoluteThreshold(baseNoiseLevelAbsoluteThreshold);
651 }
652
653 /**
654 * Gets internal status of this generator.
655 *
656 * @return internal status of this generator.
657 */
658 public TriadStaticIntervalDetector.Status getStatus() {
659 return accelerometerMeasurementsGenerator.getStatus();
660 }
661
662 /**
663 * Gets accelerometer base noise level that has been detected during
664 * initialization expressed in meters per squared second (m/s^2).
665 * This is equal to the standard deviation of the accelerometer measurements
666 * during initialization phase.
667 *
668 * @return accelerometer base noise level.
669 */
670 public double getAccelerometerBaseNoiseLevel() {
671 return accelerometerMeasurementsGenerator.getAccelerometerBaseNoiseLevel();
672 }
673
674 /**
675 * Gets accelerometer base noise level that has been detected during
676 * initialization.
677 * This is equal to the standard deviation of the accelerometer measurements
678 * during initialization phase.
679 *
680 * @return measurement base noise level.
681 */
682 public Acceleration getAccelerometerBaseNoiseLevelAsMeasurement() {
683 return accelerometerMeasurementsGenerator.getAccelerometerBaseNoiseLevelAsMeasurement();
684 }
685
686 /**
687 * Gets accelerometer base noise level that has been detected during
688 * initialization.
689 *
690 * @param result instance where result will be stored.
691 */
692 public void getAccelerometerBaseNoiseLevelAsMeasurement(final Acceleration result) {
693 accelerometerMeasurementsGenerator.getAccelerometerBaseNoiseLevelAsMeasurement(result);
694 }
695
696 /**
697 * Gets accelerometer base noise level PSD (Power Spectral Density)
698 * expressed in (m^2 * s^-3).
699 *
700 * @return accelerometer base noise level PSD.
701 */
702 public double getAccelerometerBaseNoiseLevelPsd() {
703 return accelerometerMeasurementsGenerator.getAccelerometerBaseNoiseLevelPsd();
704 }
705
706 /**
707 * Gets accelerometer base noise level root PSD (Power Spectral Density)
708 * expressed in (m * s^-1.5).
709 *
710 * @return accelerometer base noise level root PSD.
711 */
712 @Override
713 public double getAccelerometerBaseNoiseLevelRootPsd() {
714 return accelerometerMeasurementsGenerator.getAccelerometerBaseNoiseLevelRootPsd();
715 }
716
717 /**
718 * Gets threshold to determine static/dynamic period changes expressed in
719 * meters per squared second (m/s^2).
720 *
721 * @return threshold to determine static/dynamic period changes.
722 */
723 public double getThreshold() {
724 return accelerometerMeasurementsGenerator.getThreshold();
725 }
726
727 /**
728 * Gets threshold to determine static/dynamic period changes.
729 *
730 * @return threshold to determine static/dynamic period changes.
731 */
732 public Acceleration getThresholdAsMeasurement() {
733 return accelerometerMeasurementsGenerator.getThresholdAsMeasurement();
734 }
735
736 /**
737 * Gets threshold to determine static/dynamic period changes.
738 *
739 * @param result instance where result will be stored.
740 */
741 public void getThresholdAsMeasurement(final Acceleration result) {
742 accelerometerMeasurementsGenerator.getThresholdAsMeasurement(result);
743 }
744
745 /**
746 * Gets number of samples that have been processed in a static period so far.
747 *
748 * @return number of samples that have been processed in a static period so far.
749 */
750 public int getProcessedStaticSamples() {
751 return accelerometerMeasurementsGenerator.getProcessedStaticSamples();
752 }
753
754 /**
755 * Gets number of samples that have been processed in a dynamic period so far.
756 *
757 * @return number of samples that have been processed in a dynamic period so far.
758 */
759 public int getProcessedDynamicSamples() {
760 return accelerometerMeasurementsGenerator.getProcessedDynamicSamples();
761 }
762
763 /**
764 * Indicates whether last static interval must be skipped.
765 *
766 * @return true if last static interval must be skipped.
767 */
768 public boolean isStaticIntervalSkipped() {
769 return accelerometerMeasurementsGenerator.isStaticIntervalSkipped();
770 }
771
772 /**
773 * Indicates whether last dynamic interval must be skipped.
774 *
775 * @return true if last dynamic interval must be skipped.
776 */
777 public boolean isDynamicIntervalSkipped() {
778 return accelerometerMeasurementsGenerator.isDynamicIntervalSkipped();
779 }
780
781 /**
782 * Indicates whether generator is running or not.
783 *
784 * @return true if generator is running, false otherwise.
785 */
786 public boolean isRunning() {
787 return running;
788 }
789
790 /**
791 * Processes a sample of data.
792 *
793 * @param sample sample of data to be processed.
794 * @return true if provided samples has been processed, false if provided triad has been skipped because
795 * generator previously failed. If generator previously failed, it will need to be reset before
796 * processing additional samples.
797 * @throws LockedException if generator is busy processing a previous sample.
798 */
799 public boolean process(final TimedBodyKinematicsAndMagneticFluxDensity sample) throws LockedException {
800 if (running) {
801 throw new LockedException();
802 }
803
804 try {
805 running = true;
806
807 sample.getTimedKinematics(timedKinematics);
808
809 return accelerometerMeasurementsGenerator.process(sample.getKinematics())
810 && gyroscopeMeasurementsGenerator.process(timedKinematics)
811 && magnetometerMeasurementsGenerator.process(sample);
812 } finally {
813 running = false;
814 }
815 }
816
817 /**
818 * Resets this generator.
819 *
820 * @throws LockedException if generator is busy.
821 */
822 public void reset() throws LockedException {
823 if (running) {
824 throw new LockedException();
825 }
826
827 accelerometerMeasurementsGenerator.reset();
828 gyroscopeMeasurementsGenerator.reset();
829 magnetometerMeasurementsGenerator.reset();
830
831 if (listener != null) {
832 listener.onReset(this);
833 }
834 }
835
836 /**
837 * Gets estimated average angular rate during initialization phase.
838 *
839 * @return estimated average angular rate during initialization phase.
840 */
841 public AngularSpeedTriad getInitialAvgAngularSpeedTriad() {
842 return gyroscopeMeasurementsGenerator.getInitialAvgAngularSpeedTriad();
843 }
844
845 /**
846 * Gets estimated average angular rate during initialization phase.
847 *
848 * @param result instance where result will be stored.
849 */
850 public void getInitialAvgAngularSpeedTriad(final AngularSpeedTriad result) {
851 gyroscopeMeasurementsGenerator.getInitialAvgAngularSpeedTriad(result);
852 }
853
854 /**
855 * Gets estimated standard deviation of angular rate during initialization phase.
856 *
857 * @return estimated standard deviation of angular rate during initialization phase.
858 */
859 public AngularSpeedTriad getInitialAngularSpeedTriadStandardDeviation() {
860 return gyroscopeMeasurementsGenerator.getInitialAngularSpeedTriadStandardDeviation();
861 }
862
863 /**
864 * Gets estimated standard deviation of angular rate during initialization phase.
865 *
866 * @param result instance where result will be stored.
867 */
868 public void getInitialAngularSpeedTriadStandardDeviation(final AngularSpeedTriad result) {
869 gyroscopeMeasurementsGenerator.getInitialAngularSpeedTriadStandardDeviation(result);
870 }
871
872 /**
873 * Gets gyroscope base noise level that has been detected during
874 * initialization expressed in radians per second (rad/s).
875 * This is equal to the standard deviation of the gyroscope measurements
876 * during initialization phase.
877 *
878 * @return gyroscope base noise level.
879 */
880 public double getGyroscopeBaseNoiseLevel() {
881 return gyroscopeMeasurementsGenerator.getGyroscopeBaseNoiseLevel();
882 }
883
884 /**
885 * Gets gyroscope base noise level that has been detected during
886 * initialization.
887 * This is equal to the standard deviation of the gyroscope measurements
888 * during initialization phase.
889 *
890 * @return gyroscope base noise level.
891 */
892 public AngularSpeed getGyroscopeBaseNoiseLevelAsMeasurement() {
893 return gyroscopeMeasurementsGenerator.getGyroscopeBaseNoiseLevelAsMeasurement();
894 }
895
896 /**
897 * Gets gyroscope base noise level that has been detected during
898 * initialization.
899 * This is equal to the standard deviation of the gyroscope measurements
900 * during initialization phase.
901 *
902 * @param result instance where result will be stored.
903 */
904 public void getGyroscopeBaseNoiseLevelAsMeasurement(final AngularSpeed result) {
905 gyroscopeMeasurementsGenerator.getGyroscopeBaseNoiseLevelAsMeasurement(result);
906 }
907
908 /**
909 * Gets gyroscope base noise level PSD (Power Spectral Density)
910 * expressed in (rad^2/s).
911 *
912 * @return gyroscope base noise level PSD.
913 */
914 public double getGyroscopeBaseNoiseLevelPsd() {
915 return gyroscopeMeasurementsGenerator.getGyroscopeBaseNoiseLevelPsd();
916 }
917
918 /**
919 * Gets gyroscope base noise level root PSD (Power Spectral Density)
920 * expressed in (rad * s^-0.5)
921 *
922 * @return gyroscope base noise level root PSD.
923 */
924 @Override
925 public double getGyroscopeBaseNoiseLevelRootPsd() {
926 return gyroscopeMeasurementsGenerator.getGyroscopeBaseNoiseLevelRootPsd();
927 }
928 }