@@ -119,6 +119,7 @@ static const fixedWingLaunchStateDescriptor_t launchStateMachine[FW_LAUNCH_STATE
119119 },
120120 .messageType = FW_LAUNCH_MESSAGE_TYPE_NONE
121121 },
122+
122123 [FW_LAUNCH_STATE_WAIT_THROTTLE ] = {
123124 .onEntry = fwLaunchState_FW_LAUNCH_STATE_WAIT_THROTTLE ,
124125 .onEvent = {
@@ -127,6 +128,7 @@ static const fixedWingLaunchStateDescriptor_t launchStateMachine[FW_LAUNCH_STATE
127128 },
128129 .messageType = FW_LAUNCH_MESSAGE_TYPE_WAIT_THROTTLE
129130 },
131+
130132 [FW_LAUNCH_STATE_MOTOR_IDLE ] = {
131133 .onEntry = fwLaunchState_FW_LAUNCH_STATE_MOTOR_IDLE ,
132134 .onEvent = {
@@ -135,6 +137,7 @@ static const fixedWingLaunchStateDescriptor_t launchStateMachine[FW_LAUNCH_STATE
135137 },
136138 .messageType = FW_LAUNCH_MESSAGE_TYPE_WAIT_THROTTLE
137139 },
140+
138141 [FW_LAUNCH_STATE_WAIT_DETECTION ] = {
139142 .onEntry = fwLaunchState_FW_LAUNCH_STATE_WAIT_DETECTION ,
140143 .onEvent = {
@@ -143,13 +146,15 @@ static const fixedWingLaunchStateDescriptor_t launchStateMachine[FW_LAUNCH_STATE
143146 },
144147 .messageType = FW_LAUNCH_MESSAGE_TYPE_WAIT_DETECTION
145148 },
149+
146150 [FW_LAUNCH_STATE_DETECTED ] = {
147151 .onEntry = fwLaunchState_FW_LAUNCH_STATE_DETECTED ,
148152 .onEvent = {
149153 // waiting for the navigation to move on the next state FW_LAUNCH_STATE_MOTOR_DELAY
150154 },
151155 .messageType = FW_LAUNCH_MESSAGE_TYPE_WAIT_DETECTION
152156 },
157+
153158 [FW_LAUNCH_STATE_MOTOR_DELAY ] = {
154159 .onEntry = fwLaunchState_FW_LAUNCH_STATE_MOTOR_DELAY ,
155160 .onEvent = {
@@ -158,6 +163,7 @@ static const fixedWingLaunchStateDescriptor_t launchStateMachine[FW_LAUNCH_STATE
158163 },
159164 .messageType = FW_LAUNCH_MESSAGE_TYPE_IN_PROGRESS
160165 },
166+
161167 [FW_LAUNCH_STATE_MOTOR_SPINUP ] = {
162168 .onEntry = fwLaunchState_FW_LAUNCH_STATE_MOTOR_SPINUP ,
163169 .onEvent = {
@@ -166,6 +172,7 @@ static const fixedWingLaunchStateDescriptor_t launchStateMachine[FW_LAUNCH_STATE
166172 },
167173 .messageType = FW_LAUNCH_MESSAGE_TYPE_IN_PROGRESS
168174 },
175+
169176 [FW_LAUNCH_STATE_IN_PROGRESS ] = {
170177 .onEntry = fwLaunchState_FW_LAUNCH_STATE_IN_PROGRESS ,
171178 .onEvent = {
@@ -174,6 +181,7 @@ static const fixedWingLaunchStateDescriptor_t launchStateMachine[FW_LAUNCH_STATE
174181 },
175182 .messageType = FW_LAUNCH_MESSAGE_TYPE_IN_PROGRESS
176183 },
184+
177185 [FW_LAUNCH_STATE_FINISH ] = {
178186 .onEntry = fwLaunchState_FW_LAUNCH_STATE_FINISH ,
179187 .onEvent = {
@@ -186,39 +194,52 @@ static const fixedWingLaunchStateDescriptor_t launchStateMachine[FW_LAUNCH_STATE
186194
187195/* Current State Handlers */
188196
189- static timeMs_t currentStateElapsedMs (timeUs_t currentTimeUs ) {
197+ static timeMs_t currentStateElapsedMs (timeUs_t currentTimeUs )
198+ {
190199 return US2MS (currentTimeUs - fwLaunch .currentStateTimeUs );
191200}
192201
193- static void setCurrentState (fixedWingLaunchState_t nextState , timeUs_t currentTimeUs ) {
202+ static void setCurrentState (fixedWingLaunchState_t nextState , timeUs_t currentTimeUs )
203+ {
194204 fwLaunch .currentState = nextState ;
195205 fwLaunch .currentStateTimeUs = currentTimeUs ;
196206}
197207
198208/* Wing control Helpers */
199209
200- static bool isThrottleIdleEnabled (void ) {
210+ static bool isThrottleIdleEnabled (void )
211+ {
201212 return navConfig ()-> fw .launch_idle_throttle > getThrottleIdleValue ();
202213}
203214
204- static void applyThrottleIdle (void ) {
215+ static void forceMotorStopOrIdle (void )
216+ {
217+ ENABLE_STATE (NAV_MOTOR_STOP_OR_IDLE ); // If MOTOR_STOP is enabled mixer will keep motor stopped
218+ rcCommand [THROTTLE ] = getThrottleIdleValue (); // If MOTOR_STOP is disabled, motors will spin at minthrottle
219+ }
220+
221+ static void applyThrottleIdleLogic (void )
222+ {
205223 if (isThrottleIdleEnabled ()) {
206224 rcCommand [THROTTLE ] = navConfig ()-> fw .launch_idle_throttle ;
207- } else {
208- ENABLE_STATE ( NAV_MOTOR_STOP_OR_IDLE ); // If MOTOR_STOP is enabled mixer will keep motor stopped
209- rcCommand [ THROTTLE ] = getThrottleIdleValue (); // If MOTOR_STOP is disabled, motors will spin at minthrottle
225+ }
226+ else {
227+ forceMotorStopOrIdle ();
210228 }
211229}
212230
213- static inline bool isThrottleLow (void ) {
231+ static inline bool isThrottleLow (void )
232+ {
214233 return calculateThrottleStatus (THROTTLE_STATUS_TYPE_RC ) == THROTTLE_LOW ;
215234}
216235
217- static inline bool isLaunchMaxAltitudeReached (void ) {
236+ static inline bool isLaunchMaxAltitudeReached (void )
237+ {
218238 return (navConfig ()-> fw .launch_max_altitude > 0 ) && (getEstimatedActualPosition (Z ) >= navConfig ()-> fw .launch_max_altitude );
219239}
220240
221- static inline bool areSticksMoved (timeMs_t initialTime , timeUs_t currentTimeUs ) {
241+ static inline bool areSticksMoved (timeMs_t initialTime , timeUs_t currentTimeUs )
242+ {
222243 return (initialTime + currentStateElapsedMs (currentTimeUs )) > navConfig ()-> fw .launch_min_time && areSticksDeflectedMoreThanPosHoldDeadband ();
223244}
224245
@@ -230,7 +251,8 @@ static void resetPidsIfNeeded(void) {
230251 }
231252}
232253
233- static void updateRcCommand (void ) {
254+ static void updateRcCommand (void )
255+ {
234256 // lock roll and yaw and apply needed pitch angle
235257 rcCommand [ROLL ] = 0 ;
236258 rcCommand [PITCH ] = pidAngleToRcCommand (- DEGREES_TO_DECIDEGREES (fwLaunch .pitchAngle ), pidProfile ()-> max_angle_inclination [FD_PITCH ]);
@@ -239,57 +261,68 @@ static void updateRcCommand(void) {
239261
240262/* onEntry state handlers */
241263
242- static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_IDLE (timeUs_t currentTimeUs ) {
264+ static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_IDLE (timeUs_t currentTimeUs )
265+ {
243266 UNUSED (currentTimeUs );
244267
245268 return FW_LAUNCH_EVENT_NONE ;
246269}
247270
248- static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_WAIT_THROTTLE (timeUs_t currentTimeUs ) {
271+ static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_WAIT_THROTTLE (timeUs_t currentTimeUs )
272+ {
249273 UNUSED (currentTimeUs );
250274
251275 if (!isThrottleLow ()) {
252276 if (isThrottleIdleEnabled ()) {
253277 return FW_LAUNCH_EVENT_SUCCESS ;
254- } else {
278+ }
279+ else {
255280 fwLaunch .pitchAngle = navConfig ()-> fw .launch_climb_angle ;
256281 return FW_LAUNCH_EVENT_GOTO_DETECTION ;
257282 }
258283 }
284+ else {
285+ forceMotorStopOrIdle ();
286+ }
287+
259288 fwLaunch .pitchAngle = 0 ;
260289
261290 return FW_LAUNCH_EVENT_NONE ;
262291}
263292
264- static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_MOTOR_IDLE (timeUs_t currentTimeUs ) {
293+ static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_MOTOR_IDLE (timeUs_t currentTimeUs )
294+ {
265295 if (isThrottleLow ()) {
266296 return FW_LAUNCH_EVENT_THROTTLE_LOW ; // go back to FW_LAUNCH_STATE_WAIT_THROTTLE
267297 }
298+
268299 const timeMs_t elapsedTimeMs = currentStateElapsedMs (currentTimeUs );
269300 if (elapsedTimeMs > LAUNCH_MOTOR_IDLE_SPINUP_TIME ) {
270- applyThrottleIdle ();
301+ applyThrottleIdleLogic ();
271302 return FW_LAUNCH_EVENT_SUCCESS ;
272- } else {
303+ }
304+ else {
273305 rcCommand [THROTTLE ] = scaleRangef (elapsedTimeMs , 0.0f , LAUNCH_MOTOR_IDLE_SPINUP_TIME , getThrottleIdleValue (), navConfig ()-> fw .launch_idle_throttle );
274306 fwLaunch .pitchAngle = scaleRangef (elapsedTimeMs , 0.0f , LAUNCH_MOTOR_IDLE_SPINUP_TIME , 0 , navConfig ()-> fw .launch_climb_angle );
275307 }
276308
277309 return FW_LAUNCH_EVENT_NONE ;
278310}
279311
280- static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_WAIT_DETECTION (timeUs_t currentTimeUs ) {
312+ static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_WAIT_DETECTION (timeUs_t currentTimeUs )
313+ {
281314 if (isThrottleLow ()) {
282315 return FW_LAUNCH_EVENT_THROTTLE_LOW ; // go back to FW_LAUNCH_STATE_WAIT_THROTTLE
283316 }
284-
317+
285318 const float swingVelocity = (fabsf (imuMeasuredRotationBF .z ) > SWING_LAUNCH_MIN_ROTATION_RATE ) ? (imuMeasuredAccelBF .y / imuMeasuredRotationBF .z ) : 0 ;
286319 const bool isForwardAccelerationHigh = (imuMeasuredAccelBF .x > navConfig ()-> fw .launch_accel_thresh );
287320 const bool isAircraftAlmostLevel = (calculateCosTiltAngle () >= cos_approx (DEGREES_TO_RADIANS (navConfig ()-> fw .launch_max_angle )));
288321
289322 const bool isBungeeLaunched = isForwardAccelerationHigh && isAircraftAlmostLevel ;
290323 const bool isSwingLaunched = (swingVelocity > navConfig ()-> fw .launch_velocity_thresh ) && (imuMeasuredAccelBF .x > 0 );
291324
292- applyThrottleIdle ();
325+ applyThrottleIdleLogic ();
293326
294327 if (isBungeeLaunched || isSwingLaunched ) {
295328 if (currentStateElapsedMs (currentTimeUs ) > navConfig ()-> fw .launch_time_thresh ) {
@@ -302,28 +335,32 @@ static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_WAIT_DETECTION(timeU
302335 return FW_LAUNCH_EVENT_NONE ;
303336}
304337
305- static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_DETECTED (timeUs_t currentTimeUs ) {
338+ static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_DETECTED (timeUs_t currentTimeUs )
339+ {
306340 UNUSED (currentTimeUs );
307341 // waiting for the navigation to move it to next step FW_LAUNCH_STATE_MOTOR_DELAY
308- applyThrottleIdle ();
342+ applyThrottleIdleLogic ();
309343
310344 return FW_LAUNCH_EVENT_NONE ;
311345}
312346
313- static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_MOTOR_DELAY (timeUs_t currentTimeUs ) {
314- applyThrottleIdle ();
347+ static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_MOTOR_DELAY (timeUs_t currentTimeUs )
348+ {
349+ applyThrottleIdleLogic ();
315350
316351 if (areSticksMoved (0 , currentTimeUs )) {
317352 return FW_LAUNCH_EVENT_ABORT ; // jump to FW_LAUNCH_STATE_IDLE
318353 }
354+
319355 if (currentStateElapsedMs (currentTimeUs ) > navConfig ()-> fw .launch_motor_timer ) {
320356 return FW_LAUNCH_EVENT_SUCCESS ;
321357 }
322358
323359 return FW_LAUNCH_EVENT_NONE ;
324360}
325361
326- static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_MOTOR_SPINUP (timeUs_t currentTimeUs ) {
362+ static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_MOTOR_SPINUP (timeUs_t currentTimeUs )
363+ {
327364 if (areSticksMoved (navConfig ()-> fw .launch_motor_timer , currentTimeUs )) {
328365 return FW_LAUNCH_EVENT_ABORT ; // jump to FW_LAUNCH_STATE_IDLE
329366 }
@@ -335,31 +372,40 @@ static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_MOTOR_SPINUP(timeUs_
335372 if (elapsedTimeMs > motorSpinUpMs ) {
336373 rcCommand [THROTTLE ] = launchThrottle ;
337374 return FW_LAUNCH_EVENT_SUCCESS ;
338- } else {
375+ }
376+ else {
339377 const uint16_t minIdleThrottle = MAX (getThrottleIdleValue (), navConfig ()-> fw .launch_idle_throttle );
340378 rcCommand [THROTTLE ] = scaleRangef (elapsedTimeMs , 0.0f , motorSpinUpMs , minIdleThrottle , launchThrottle );
341379 }
342380
343381 return FW_LAUNCH_EVENT_NONE ;
344382}
345383
346- static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_IN_PROGRESS (timeUs_t currentTimeUs ) {
384+ static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_IN_PROGRESS (timeUs_t currentTimeUs )
385+ {
347386 rcCommand [THROTTLE ] = navConfig ()-> fw .launch_throttle ;
348387
388+ if (isLaunchMaxAltitudeReached ()) {
389+ return FW_LAUNCH_EVENT_SUCCESS ; // cancel the launch and do the FW_LAUNCH_STATE_FINISH state
390+ }
391+
349392 if (areSticksMoved (navConfig ()-> fw .launch_motor_timer + navConfig ()-> fw .launch_motor_spinup_time , currentTimeUs )) {
350393 return FW_LAUNCH_EVENT_ABORT ; // cancel the launch and do the FW_LAUNCH_STATE_IDLE state
351394 }
395+
352396 if (isLaunchMaxAltitudeReached ()) {
353397 return FW_LAUNCH_EVENT_SUCCESS ; // cancel the launch and do the FW_LAUNCH_STATE_FINISH state
354398 }
399+
355400 if (currentStateElapsedMs (currentTimeUs ) > navConfig ()-> fw .launch_timeout ) {
356401 return FW_LAUNCH_EVENT_SUCCESS ; // launch timeout. go to FW_LAUNCH_STATE_FINISH
357402 }
358403
359404 return FW_LAUNCH_EVENT_NONE ;
360405}
361406
362- static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_FINISH (timeUs_t currentTimeUs ) {
407+ static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_FINISH (timeUs_t currentTimeUs )
408+ {
363409 const timeMs_t elapsedTimeMs = currentStateElapsedMs (currentTimeUs );
364410 const timeMs_t endTimeMs = navConfig ()-> fw .launch_end_time ;
365411
@@ -368,7 +414,8 @@ static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_FINISH(timeUs_t curr
368414 }
369415 if (elapsedTimeMs > endTimeMs ) {
370416 return FW_LAUNCH_EVENT_SUCCESS ;
371- } else {
417+ }
418+ else {
372419 // make a smooth transition from the launch state to the current state for throttle and the pitch angle
373420 rcCommand [THROTTLE ] = scaleRangef (elapsedTimeMs , 0.0f , endTimeMs , navConfig ()-> fw .launch_throttle , rcCommand [THROTTLE ]);
374421 fwLaunch .pitchAngle = scaleRangef (elapsedTimeMs , 0.0f , endTimeMs , navConfig ()-> fw .launch_climb_angle , rcCommand [PITCH ]);
@@ -379,9 +426,10 @@ static fixedWingLaunchEvent_t fwLaunchState_FW_LAUNCH_STATE_FINISH(timeUs_t curr
379426
380427// Public methods ---------------------------------------------------------------
381428
382- void applyFixedWingLaunchController (timeUs_t currentTimeUs ) {
429+ void applyFixedWingLaunchController (timeUs_t currentTimeUs )
430+ {
383431 // Called at PID rate
384-
432+
385433 // process the current state, set the next state or exit if FW_LAUNCH_EVENT_NONE
386434 while (launchStateMachine [fwLaunch .currentState ].onEntry ) {
387435 fixedWingLaunchEvent_t newEvent = launchStateMachine [fwLaunch .currentState ].onEntry (currentTimeUs );
@@ -397,41 +445,52 @@ void applyFixedWingLaunchController(timeUs_t currentTimeUs) {
397445 // Control beeper
398446 if (fwLaunch .currentState == FW_LAUNCH_STATE_WAIT_THROTTLE ) {
399447 beeper (BEEPER_LAUNCH_MODE_LOW_THROTTLE );
400- } else {
448+ }
449+ else {
401450 beeper (BEEPER_LAUNCH_MODE_ENABLED );
402451 }
403452}
404453
405- void resetFixedWingLaunchController (timeUs_t currentTimeUs ) {
454+ void resetFixedWingLaunchController (timeUs_t currentTimeUs )
455+ {
406456 setCurrentState (FW_LAUNCH_STATE_WAIT_THROTTLE , currentTimeUs );
407457}
408458
409- bool isFixedWingLaunchDetected (void ) {
459+ bool isFixedWingLaunchDetected (void )
460+ {
410461 return fwLaunch .currentState == FW_LAUNCH_STATE_DETECTED ;
411462}
412463
413- void enableFixedWingLaunchController (timeUs_t currentTimeUs ) {
464+ void enableFixedWingLaunchController (timeUs_t currentTimeUs )
465+ {
414466 setCurrentState (FW_LAUNCH_STATE_MOTOR_DELAY , currentTimeUs );
415467}
416468
417- bool isFixedWingLaunchFinishedOrAborted (void ) {
469+ bool isFixedWingLaunchFinishedOrAborted (void )
470+ {
418471 return fwLaunch .currentState == FW_LAUNCH_STATE_IDLE ;
419472}
420473
421- void abortFixedWingLaunch (void ) {
474+ void abortFixedWingLaunch (void )
475+ {
422476 setCurrentState (FW_LAUNCH_STATE_IDLE , 0 );
423477}
424478
425- const char * fixedWingLaunchStateMessage (void ) {
479+ const char * fixedWingLaunchStateMessage (void )
480+ {
426481 switch (launchStateMachine [fwLaunch .currentState ].messageType ) {
427482 case FW_LAUNCH_MESSAGE_TYPE_WAIT_THROTTLE :
428483 return FW_LAUNCH_MESSAGE_TEXT_WAIT_THROTTLE ;
484+
429485 case FW_LAUNCH_MESSAGE_TYPE_WAIT_DETECTION :
430486 return FW_LAUNCH_MESSAGE_TEXT_WAIT_DETECTION ;
487+
431488 case FW_LAUNCH_MESSAGE_TYPE_IN_PROGRESS :
432489 return FW_LAUNCH_MESSAGE_TEXT_IN_PROGRESS ;
490+
433491 case FW_LAUNCH_MESSAGE_TYPE_FINISHING :
434492 return FW_LAUNCH_MESSAGE_TEXT_FINISHING ;
493+
435494 default :
436495 return NULL ;
437496 }
0 commit comments