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