comparison Discovery/Src/motion.c @ 381:695434a6dcf6 MotionDetection

Simplified pitch detection state machine: Considering a pitch to last 1 to 2 seconds only around 5 to 10 iterations are used. As result the used counters had limits of 1 or 2 => not really needed
author ideenmodellierer
date Thu, 10 Oct 2019 22:11:59 +0200
parents 834e087505ec
children 49a02dea8ae3
comparison
equal deleted inserted replaced
380:a7331e4a9ca6 381:695434a6dcf6
14 #include "t7.h" 14 #include "t7.h"
15 #include "settings.h" 15 #include "settings.h"
16 16
17 #define STABLE_STATE_COUNT 2 /* number of count to declare a state as stable (at the moment based on 100ms) */ 17 #define STABLE_STATE_COUNT 2 /* number of count to declare a state as stable (at the moment based on 100ms) */
18 #define STABLE_STATE_TIMEOUT 5 /* Detection shall be aborted if a movement state is stable for more than 500ms */ 18 #define STABLE_STATE_TIMEOUT 5 /* Detection shall be aborted if a movement state is stable for more than 500ms */
19 #define MOVE_DELTA_SPEED 4 /* Delta speed needed to identify a valid movement */
20 #define PITCH_DELTA_COUNT 10 /* Delta count needed to identify a valid minima / maxima */
21 #define PITCH_DELTA_END 10 /* Delta allowed between start and end position */
22
23 19
24 #define SECTOR_WINDOW 80.0 /* Pitch window which is used for custom view projection */ 20 #define SECTOR_WINDOW 80.0 /* Pitch window which is used for custom view projection */
21 #define SECTOR_WINDOW_MAX 120.0 /* Pitch window which will be greater than the divers field of view */
25 #define SECTOR_HYSTERY 3 /* Additional offset to avoid fast changing displays */ 22 #define SECTOR_HYSTERY 3 /* Additional offset to avoid fast changing displays */
26 #define SECTOR_BORDER 400.0 /* Define a value which is out of limit to avoid not wanted key events */ 23 #define SECTOR_BORDER 400.0 /* Define a value which is out of limit to avoid not wanted key events */
27 #define SECTOR_FILTER 10 /* Define speed for calculated angle to follow real value */ 24 #define SECTOR_FILTER 10 /* Define speed for calculated angle to follow real value */
28 25
29 #define SECTOR_MAX 19 /* maximum number of sectors */ 26 #define SECTOR_MAX 30 /* maximum number of sectors */
30 #define SECTOR_SCROLL 7 /* number of sectors used for scroll detection */ 27 #define SECTOR_SCROLL 7 /* number of sectors used for scroll detection */
31 28
32 detectionState_t detectionState = DETECT_NOTHING; 29 static detectionState_t detectionState = DETECT_NOTHING;
33 30
34 uint8_t curSector; 31 uint8_t curSector;
35 static uint8_t targetSector; 32 static uint8_t targetSector;
36 static uint8_t sectorSize; 33 static float sectorSize;
34 static float sectorwindow;
37 static uint8_t sectorCount; 35 static uint8_t sectorCount;
38 36
39 SSector PitchSector[SECTOR_MAX]; /* max number of enabled custom views */ 37 static float sector_upperborder;
38 static float sector_lowerborder;
40 39
41 40
42 uint8_t GetSectorForPitch(float pitch) 41 uint8_t GetSectorForPitch(float pitch)
43 { 42 {
44 static float lastPitch = 1000; 43 static uint8_t lastsector = 0xFF;
45 float newPitch; 44 float newPitch;
46 uint8_t index;
47 uint8_t sector = 0; 45 uint8_t sector = 0;
48 46
49 if(lastPitch == 1000) /* init at first call */ 47
50 { 48 newPitch = pitch + (sectorwindow / 2.0); /* do not use negativ values */
51 lastPitch = pitch; 49 if (newPitch < 0.0) /* clip value */
52 } 50 {
53 51 newPitch = 0.0;
54 newPitch = lastPitch + (pitch / SECTOR_FILTER); 52 }
55 53 if (newPitch > sectorwindow) /* clip value */
56 for(index = 1; index < sectorCount; index++) 54 {
57 { 55 newPitch = sectorwindow;
58 if((pitch < PitchSector[index].upperlimit) && (pitch > PitchSector[index].lowerlimit )) 56 }
59 { 57
60 sector = index; 58 if(lastsector == 0xFF) /* First call of function => make sure a new sector is set */
61 break; 59 {
62 } 60 sector_lowerborder = SECTOR_BORDER;
63 } 61 sector_upperborder = SECTOR_BORDER * -1.0;
64 lastPitch = newPitch; 62
65 return sector; 63 }
64
65 /* switch to other sector? */
66 if((newPitch > sector_upperborder) || (newPitch <= sector_lowerborder))
67 {
68 sector = (uint16_t) newPitch / sectorSize;
69 sector_lowerborder = sector * sectorSize - SECTOR_HYSTERY;
70 sector_upperborder = (sector + 1) * sectorSize + SECTOR_HYSTERY;
71 lastsector = sector;
72 }
73
74 return lastsector;
66 } 75 }
67 76
68 void DefinePitchSectors(float centerPitch,uint8_t numOfSectors) 77 void DefinePitchSectors(float centerPitch,uint8_t numOfSectors)
69 { 78 {
70 uint8_t index;
71
72 if(numOfSectors == CUSTOMER_DEFINED_VIEWS) 79 if(numOfSectors == CUSTOMER_DEFINED_VIEWS)
73 { 80 {
74 sectorCount = t7_GetEnabled_customviews(); 81 sectorCount = t7_GetEnabled_customviews();
75 if(sectorCount > 7) 82 if(sectorCount > 7)
76 { 83 {
80 else 87 else
81 if(numOfSectors != CUSTOMER_KEEP_LAST_SECTORS) 88 if(numOfSectors != CUSTOMER_KEEP_LAST_SECTORS)
82 { 89 {
83 sectorCount = numOfSectors; 90 sectorCount = numOfSectors;
84 } 91 }
85 sectorSize = SECTOR_WINDOW / sectorCount; 92
86 93 if(sectorCount == SECTOR_MAX)
87 PitchSector[0].upperlimit = centerPitch + (SECTOR_WINDOW / 2); 94 {
88 PitchSector[0].lowerlimit = PitchSector[0].upperlimit - sectorSize - SECTOR_HYSTERY; 95 sectorwindow = SECTOR_WINDOW_MAX;
89 96 }
90 for(index = 1; index < sectorCount; index++) 97 else
91 { 98 {
92 PitchSector[index].upperlimit = PitchSector[0].upperlimit - index * sectorSize + SECTOR_HYSTERY; 99 sectorwindow = SECTOR_WINDOW;
93 PitchSector[index].lowerlimit = PitchSector[0].upperlimit - (index + 1) * sectorSize - SECTOR_HYSTERY; 100 }
94 } 101
95 102 sectorSize = sectorwindow / sectorCount;
96 PitchSector[0].upperlimit = SECTOR_BORDER;
97 PitchSector[index - 1].lowerlimit = SECTOR_BORDER * -1.0;
98 103
99 /* get the current sector */ 104 /* get the current sector */
100 curSector = GetSectorForPitch(stateRealGetPointer()->lifeData.compass_pitch); 105 curSector = GetSectorForPitch(stateRealGetPointer()->lifeData.compass_pitch);
101 targetSector = curSector; 106 targetSector = curSector;
102 } 107 }
133 newTargetSector = GetSectorForPitch(stateRealGetPointer()->lifeData.compass_pitch); 138 newTargetSector = GetSectorForPitch(stateRealGetPointer()->lifeData.compass_pitch);
134 if(lastTargetSector == newTargetSector) 139 if(lastTargetSector == newTargetSector)
135 { 140 {
136 targetSector = newTargetSector; 141 targetSector = newTargetSector;
137 } 142 }
138 lastTargetSector = newTargetSector; 143 lastTargetSector = newTargetSector;
139 if(targetSector != curSector) 144 if(targetSector != curSector)
140 { 145 {
141 if(targetSector > curSector) 146 if(targetSector > curSector)
142 { 147 {
143 curSector++; 148 curSector++;
203 detectionState = DETECT_NOTHING; 208 detectionState = DETECT_NOTHING;
204 } 209 }
205 210
206 curSector = GetSectorForPitch(stateRealGetPointer()->lifeData.compass_pitch); 211 curSector = GetSectorForPitch(stateRealGetPointer()->lifeData.compass_pitch);
207 212
208 sectorhist[sectorindex++] = curSector;
209 if(sectorindex == 20) sectorindex=0;
210
211 /* feed value into state machine */ 213 /* feed value into state machine */
212 switch (detectionState) 214 switch (detectionState)
213 { 215 {
214 case DETECT_NOTHING: if(curSector == lastSector) /* detect a stable condition before evaluating for the next move */ 216 case DETECT_NOTHING: if(curSector != lastSector) /* detect a stable condition before evaluating for the next move */
215 {
216 stableCnt++;
217 }
218 else
219 { 217 {
220 stableCnt=0; 218 stableCnt=0;
221 } 219 }
222 220
223 if(stableCnt > STABLE_STATE_COUNT) 221 if(stableCnt > STABLE_STATE_COUNT)
240 detectionState = DETECT_NEG_MOVE; 238 detectionState = DETECT_NEG_MOVE;
241 } 239 }
242 stableCnt = 0; 240 stableCnt = 0;
243 startSector = lastSector; 241 startSector = lastSector;
244 } 242 }
245 else
246 {
247 stableCnt++; /* reset start sector in case of slow movement */
248 }
249 } 243 }
250 break; 244 break;
251 case DETECT_NEG_MOVE: 245 case DETECT_NEG_MOVE:
252 case DETECT_POS_MOVE: if(curSector != lastSector) /* still moving? */ 246 case DETECT_POS_MOVE: if(curSector == lastSector) /* Moved to a max? */
253 {
254 stableCnt++;
255 }
256 else
257 { 247 {
258 if(abs(startSector - curSector) > 2) 248 if(abs(startSector - curSector) > 2)
259 { 249 {
260 detectionState++; 250 detectionState++;
261 stableCnt = 0; 251 stableCnt = 0;
262 } 252 }
263 else 253 if(stableCnt > 2)
264 { 254 {
265 stableCnt++; /* maybe on the boundary of a sector => handle as stable */ 255 detectionState = DETECT_NOTHING;
266 }
267 }
268 break;
269 case DETECT_MINIMA:
270 case DETECT_MAXIMA: /* stay at maximum for short time to add a pattern for user interaction */
271 if(curSector == lastSector)
272 {
273 stableCnt++;
274 }
275 else
276 {
277 if(stableCnt > 0) /* restart movement after a short break? */
278 {
279 detectionState++;
280 stableCnt = 0; 256 stableCnt = 0;
281 } 257 }
282 else 258 }
283 { 259 break;
284 stableCnt++; /* maybe on the boundary of a sector => handle as stable */ 260 case DETECT_MAXIMA:
285 } 261 case DETECT_MINIMA: if(curSector != lastSector) /* reset timeout detection */
262 {
263 detectionState++;
264 stableCnt = 0;
286 } 265 }
287 break; 266 break;
288 case DETECT_RISEBACK: 267 case DETECT_RISEBACK:
289 case DETECT_FALLBACK: if(curSector == lastSector) /* check if we are back at start position at end of movement */ 268 case DETECT_FALLBACK:
290 { 269 if(curSector == lastSector) /* check if we are back at start position at end of movement */
291 if(abs(startSector - curSector) <= 1) //(curSector == startSector) 270 {
292 { 271 if(abs(startSector - curSector) <= 1)
293 detectionState++; 272 {
294 stableCnt = 0; 273 if(stableCnt > 2)
295 } 274 {
296 else 275 detectionState++;
297 { 276 stableCnt = 0;
298 stableCnt++; /* maybe on the boundary of a sector => handle as stable */ 277 }
299 } 278 }
300 } 279 }
301 else 280 break;
302 {
303 stableCnt++;
304 }
305 break;
306 default: 281 default:
307 detectionState = DETECT_NOTHING; 282 detectionState = DETECT_NOTHING;
308 break; 283 break;
309 284 }
285 if(detectionState != DETECT_START)
286 {
287 stableCnt++;
310 } 288 }
311 lastSector = curSector; 289 lastSector = curSector;
312 if(stableCnt > STABLE_STATE_TIMEOUT) 290 if(stableCnt > STABLE_STATE_TIMEOUT)
313 { 291 {
314 detectionState = DETECT_NOTHING; 292 detectionState = DETECT_NOTHING;