Avionics
Core avionics package for CURE flight computers
Loading...
Searching...
No Matches
LaunchDetector.cpp
Go to the documentation of this file.
2
3// #define DEBUG
4
5#ifdef DEBUG
6#include "ArduinoHAL.h"
7#endif
8
9LaunchDetector::LaunchDetector(float accelerationThreshold_ms2, //NOLINT(bugprone-easily-swappable-parameters)
10 uint16_t windowSize_ms,
11 uint16_t windowInterval_ms)
12 : AclMagSqWindow_ms2(windowSize_ms / windowInterval_ms),
13 accelerationThresholdSq_ms2(accelerationThreshold_ms2 * accelerationThreshold_ms2),
14 windowInterval_ms(windowInterval_ms),
15 launched(false),
16 launchedTime_ms(0),
17 acceptableTimeDifference_ms(static_cast<uint16_t>(static_cast<float>(windowInterval_ms) * ACCEPTABLE_PERCENT_DIFFERENCE_WINDOW_INTERVAL)),
18 median_acceleration_squared(0)
19{
20 // These must remain here because they rely on AclMagSqWindow_ms2 being constructed
21 min_window_size_ms = (windowInterval_ms - acceptableTimeDifference_ms) *
22 (AclMagSqWindow_ms2.getMaxSize() - 1);
23 max_window_size_ms = (windowInterval_ms + acceptableTimeDifference_ms) *
24 (AclMagSqWindow_ms2.getMaxSize() - 1);
25}
26
27
29{
30 // :xac: The x acceleration data point in ms^2
31 // :yac: The y acceleration data point in ms^2
32 // :zac: The z acceleration data point in ms^2
33
34 // Return false if the data is ignored, true if the data is accepted
35 // Will set the launched flag if the data is accepted and the launch is detected
36
37
38 // If launched, don't update
39 if (launched)
40 {
41 #ifdef DEBUG
42 Serial.println("LaunchDetector: Data point ignored because already launched");
43 #endif
45 }
46 // Calculate the magnitude of the acceleration squared
47 const float aclMagSq = accel.x.data * accel.x.data + accel.y.data * accel.y.data + accel.z.data * accel.z.data;
48
49 // Take the average of the timestamps
50 // Ideally these should all be the same
51 const uint32_t time_ms = (accel.x.timestamp_ms + accel.y.timestamp_ms + accel.z.timestamp_ms) / 3;
52
53 // Making sure the new time is greater than the last time
54 if (time_ms < AclMagSqWindow_ms2.getFromHead(0).timestamp_ms)
55 {
56 #ifdef DEBUG
57 Serial.println("LaunchDetector: Data point ignored because of time is earlier than head");
58 Serial.printf("Incoming time: %d\n", time_ms);
59 Serial.printf("Head time: %d\n", AclMagSqWindow_ms2.getFromHead(0).timestamp_ms);
60 #endif
62 }
63
64 // If the window isn't full yet, just push the data point
65 if (!AclMagSqWindow_ms2.isFull())
66 {
67 #ifdef DEBUG
68 // Serial.println("LaunchDetector: Populating initial window");
69 #endif
70 AclMagSqWindow_ms2.push(DataPoint(time_ms, aclMagSq));
71
73 }
74
75 // Make sure we are near the window interval +- 10%
76 uint32_t time_diff = time_ms - AclMagSqWindow_ms2.getFromHead(0).timestamp_ms; //NOLINT(cppcoreguidelines-init-variables)
77
78 // Check that the data didn't come in too fast
79 if (time_diff < windowInterval_ms - acceptableTimeDifference_ms){
80 #ifdef DEBUG
81 Serial.println("LaunchDetector: DATA TOO EARLY");
82 Serial.printf("Time diff: %d\n", time_diff);
83 Serial.printf("Window interval: %d\n", windowInterval_ms);
84 Serial.printf("Incoming time: %d\n", time_ms);
85 Serial.printf("Head time: %d\n", AclMagSqWindow_ms2.getFromHead(0).timestamp_ms);
86 #endif
87 return LP_DATA_TOO_FAST;
88 }
89
90 if (time_diff > windowInterval_ms + acceptableTimeDifference_ms)
91 {
92 #ifdef DEBUG
93 Serial.println("LaunchDetector: DATA TOO LATE");
94 Serial.printf("Time diff: %d\n", time_diff);
95 Serial.printf("Window interval: %d\n", windowInterval_ms);
96 Serial.printf("Incoming time: %d\n", time_ms);
97 Serial.printf("Head time: %d\n", AclMagSqWindow_ms2.getFromHead(0).timestamp_ms);
98 Serial.println("LaunchDetector: Clearing window");
99 #endif
100
101 AclMagSqWindow_ms2.clear();
103 }
104
105 // Push the new data point
106 #ifdef DEBUG
107 Serial.print("LaunchDetector: Pushing timestamp: ");
108 Serial.println(time_ms);
109 #endif
110
111 AclMagSqWindow_ms2.push(DataPoint(time_ms, aclMagSq));
112
113 const uint32_t head_timeStamp_ms = AclMagSqWindow_ms2.getFromHead(0).timestamp_ms; //NOLINT(cppcoreguidelines-init-variables)
114 const uint32_t tail_timeStamp_ms = AclMagSqWindow_ms2.getFromHead(AclMagSqWindow_ms2.getMaxSize() - 1).timestamp_ms; //NOLINT(cppcoreguidelines-init-variables)
115 const uint32_t time_range = head_timeStamp_ms - tail_timeStamp_ms;
116
117 // Ensure the time_range isn't too small
118 if (time_range < min_window_size_ms)
119 {
120 #ifdef DEBUG
121 Serial.println("LaunchDetector: Time range too small, waiting...");
122 Serial.printf("Time range: %d\n", time_range);
123 Serial.printf("Min Time Range: %d\n", min_window_size_ms);
124 Serial.printf("Incoming time: %d\n", time_ms);
125 Serial.printf("Head time: %d\n", AclMagSqWindow_ms2.getFromHead(0).timestamp_ms);
126 Serial.printf("Tail time: %d\n", AclMagSqWindow_ms2.getFromHead(AclMagSqWindow_ms2.getMaxSize() - 1).timestamp_ms);
127 #endif
128
130 }
131
132 // Ensure the time_range isn't too large
133 if (time_range > max_window_size_ms)
134 {
135 #ifdef DEBUG
136 Serial.println("LaunchDetector: Time range too large, waiting...");
137 Serial.printf("Time range: %d\n", time_range);
138 Serial.printf("Max Time Range: %d\n", max_window_size_ms);
139 Serial.printf("Incoming time: %d\n", time_ms);
140 Serial.printf("Head time: %d\n", AclMagSqWindow_ms2.getFromHead(0).timestamp_ms);
141 Serial.printf("Tail time: %d\n", AclMagSqWindow_ms2.getFromHead(AclMagSqWindow_ms2.getMaxSize() - 1).timestamp_ms);
142 #endif
143
145 }
146
147 // Check that the window is full
148 if (!AclMagSqWindow_ms2.isFull())
149 {
150 return LP_WINDOW_NOT_FULL;
151 }
152
153 this->median_acceleration_squared = AclMagSqWindow_ms2.getMedian().data;
154
155 // Check if the median is above the threshold
156 if (median_acceleration_squared > accelerationThresholdSq_ms2)
157 {
158 launched = true;
159 launchedTime_ms = time_ms;
160 return LP_LAUNCH_DETECTED;
161 }
162
163 #ifdef DEBUG
164 Serial.println("LaunchDetector: Median below threshold");
165 // Print the median without being able to use %f because of the Arduino
166 Serial.print("Median: ");
167 Serial.println(median_acceleration_squared);
168 Serial.print("Threshold: ");
169 Serial.println(accelerationThresholdSq_ms2);
170 #endif
171 return LP_ACL_TOO_LOW;
172}
173
175{
176 launched = false;
177 launchedTime_ms = 0;
178
179 // Clear the window
180 AclMagSqWindow_ms2.clear();
181}
@ LP_LAUNCH_DETECTED
@ LP_WINDOW_NOT_FULL
@ LP_ACL_TOO_LOW
@ LP_INITIAL_POPULATION
@ LP_DATA_TOO_FAST
@ LP_WINDOW_TIME_RANGE_TOO_LARGE
@ LP_YOUNGER_TIMESTAMP
@ LP_WINDOW_DATA_STALE
@ LP_WINDOW_TIME_RANGE_TOO_SMALL
@ LP_ALREADY_LAUNCHED
constexpr float ACCEPTABLE_PERCENT_DIFFERENCE_WINDOW_INTERVAL
Timestamped float measurement container.
Definition DataPoint.h:11
float data
Definition DataPoint.h:14
uint32_t timestamp_ms
Definition DataPoint.h:13
LaunchDetector(float accelerationThreshold_ms2, uint16_t windowSize_ms, uint16_t windowInterval_ms)
int update(AccelerationTriplet accel)
MockSerial Serial