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