update credits
[librepilot.git] / flight / modules / PathFollower / vtolautotakeofffsm.cpp
blob372e01af60714508983ff1125bff59102b09f8b1
1 /*
2 ******************************************************************************
4 * @file vtolautotakeofffsm.cpp
5 * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2018
6 * The OpenPilot Team, http://www.openpilot.org Copyright (C) 2015.
7 * @brief This autotakeoff state machine is a helper state machine to the
8 * VtolAutoTakeoffController.
9 * @see The GNU Public License (GPL) Version 3
11 *****************************************************************************/
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 extern "C" {
29 #include <openpilot.h>
31 #include <math.h>
32 #include <pid.h>
33 #include <pathdesired.h>
34 #include <paths.h>
35 #include "plans.h"
36 #include <sanitycheck.h>
38 #include <homelocation.h>
39 #include <accelstate.h>
40 #include <vtolpathfollowersettings.h>
41 #include <flightstatus.h>
42 #include <flightmodesettings.h>
43 #include <pathstatus.h>
44 #include <positionstate.h>
45 #include <velocitystate.h>
46 #include <velocitydesired.h>
47 #include <stabilizationdesired.h>
48 #include <attitudestate.h>
49 #include <takeofflocation.h>
50 #include <manualcontrolcommand.h>
51 #include <systemsettings.h>
52 #include <stabilizationbank.h>
53 #include <stabilizationdesired.h>
54 #include <vtolselftuningstats.h>
55 #include <statusvtolautotakeoff.h>
56 #include <pathsummary.h>
59 // C++ includes
60 #include <vtolautotakeofffsm.h>
63 // Private constants
64 #define TIMER_COUNT_PER_SECOND (1000 / vtolPathFollowerSettings->UpdatePeriod)
65 #define TIMEOUT_SLOWSTART (2 * TIMER_COUNT_PER_SECOND)
66 #define TIMEOUT_THRUSTUP (1 * TIMER_COUNT_PER_SECOND)
67 #define TIMEOUT_THRUSTDOWN (5 * TIMER_COUNT_PER_SECOND)
68 #define AUTOTAKEOFF_SLOWDOWN_HEIGHT -5.0f
70 VtolAutoTakeoffFSM::PathFollowerFSM_AutoTakeoffStateHandler_T VtolAutoTakeoffFSM::sAutoTakeoffStateTable[AUTOTAKEOFF_STATE_SIZE] = {
71 [AUTOTAKEOFF_STATE_INACTIVE] = { .setup = &VtolAutoTakeoffFSM::setup_inactive, .run = 0 },
72 [AUTOTAKEOFF_STATE_CHECKSTATE] = { .setup = &VtolAutoTakeoffFSM::setup_checkstate, .run = 0 },
73 [AUTOTAKEOFF_STATE_SLOWSTART] = { .setup = &VtolAutoTakeoffFSM::setup_slowstart, .run = &VtolAutoTakeoffFSM::run_slowstart },
74 [AUTOTAKEOFF_STATE_THRUSTUP] = { .setup = &VtolAutoTakeoffFSM::setup_thrustup, .run = &VtolAutoTakeoffFSM::run_thrustup },
75 [AUTOTAKEOFF_STATE_TAKEOFF] = { .setup = &VtolAutoTakeoffFSM::setup_takeoff, .run = &VtolAutoTakeoffFSM::run_takeoff },
76 [AUTOTAKEOFF_STATE_HOLD] = { .setup = &VtolAutoTakeoffFSM::setup_hold, .run = &VtolAutoTakeoffFSM::run_hold },
77 [AUTOTAKEOFF_STATE_THRUSTDOWN] = { .setup = &VtolAutoTakeoffFSM::setup_thrustdown, .run = &VtolAutoTakeoffFSM::run_thrustdown },
78 [AUTOTAKEOFF_STATE_THRUSTOFF] = { .setup = &VtolAutoTakeoffFSM::setup_thrustoff, .run = &VtolAutoTakeoffFSM::run_thrustoff },
79 [AUTOTAKEOFF_STATE_DISARMED] = { .setup = &VtolAutoTakeoffFSM::setup_disarmed, .run = &VtolAutoTakeoffFSM::run_disarmed }
82 // pointer to a singleton instance
83 VtolAutoTakeoffFSM *VtolAutoTakeoffFSM::p_inst = 0;
86 VtolAutoTakeoffFSM::VtolAutoTakeoffFSM()
87 : mAutoTakeoffData(0), vtolPathFollowerSettings(0), pathDesired(0), flightStatus(0)
90 // Private types
92 // Private functions
93 // Public API methods
94 /**
95 * Initialise the module, called on startup
96 * \returns 0 on success or -1 if initialisation failed
98 int32_t VtolAutoTakeoffFSM::Initialize(VtolPathFollowerSettingsData *ptr_vtolPathFollowerSettings,
99 PathDesiredData *ptr_pathDesired,
100 FlightStatusData *ptr_flightStatus)
102 PIOS_Assert(ptr_vtolPathFollowerSettings);
103 PIOS_Assert(ptr_pathDesired);
104 PIOS_Assert(ptr_flightStatus);
106 if (mAutoTakeoffData == 0) {
107 mAutoTakeoffData = (VtolAutoTakeoffFSMData_T *)pios_malloc(sizeof(VtolAutoTakeoffFSMData_T));
108 PIOS_Assert(mAutoTakeoffData);
110 memset(mAutoTakeoffData, 0, sizeof(VtolAutoTakeoffFSMData_T));
111 vtolPathFollowerSettings = ptr_vtolPathFollowerSettings;
112 pathDesired = ptr_pathDesired;
113 flightStatus = ptr_flightStatus;
114 initFSM();
116 return 0;
119 void VtolAutoTakeoffFSM::Inactive(void)
121 memset(mAutoTakeoffData, 0, sizeof(VtolAutoTakeoffFSMData_T));
122 initFSM();
125 // Initialise the FSM
126 void VtolAutoTakeoffFSM::initFSM(void)
128 if (vtolPathFollowerSettings != 0) {
129 setState(STATUSVTOLAUTOTAKEOFF_STATE_INACTIVE, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_NONE);
130 } else {
131 mAutoTakeoffData->currentState = STATUSVTOLAUTOTAKEOFF_STATE_INACTIVE;
135 void VtolAutoTakeoffFSM::Activate()
137 memset(mAutoTakeoffData, 0, sizeof(VtolAutoTakeoffFSMData_T));
138 mAutoTakeoffData->currentState = STATUSVTOLAUTOTAKEOFF_STATE_INACTIVE;
139 mAutoTakeoffData->flLowAltitude = true;
140 mAutoTakeoffData->flAltitudeHold = false;
141 mAutoTakeoffData->boundThrustMin = 0.0f;
142 mAutoTakeoffData->boundThrustMax = 0.0f;
143 mAutoTakeoffData->flZeroStabiHorizontal = true; // turn off positional controllers
144 TakeOffLocationGet(&(mAutoTakeoffData->takeOffLocation));
145 mAutoTakeoffData->fsmAutoTakeoffStatus.AltitudeAtState[STATUSVTOLAUTOTAKEOFF_STATE_INACTIVE] = 0.0f;
146 mAutoTakeoffData->fsmAutoTakeoffStatus.ControlState = STATUSVTOLAUTOTAKEOFF_CONTROLSTATE_WAITFORARMED;
147 assessAltitude();
149 // Check if we are already flying. This can happen in pathplanner mode
150 // going into a second loop of the waypoints.
151 StabilizationDesiredData stabDesired;
152 StabilizationDesiredGet(&stabDesired);
153 if (stabDesired.Thrust > vtolPathFollowerSettings->ThrustLimits.Min) {
154 setState(STATUSVTOLAUTOTAKEOFF_STATE_HOLD, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_NONE);
155 return;
158 // initially inactive and wait for a change in controlstate.
159 setState(STATUSVTOLAUTOTAKEOFF_STATE_INACTIVE, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_NONE);
162 PathFollowerFSMState_T VtolAutoTakeoffFSM::GetCurrentState(void)
164 switch (mAutoTakeoffData->currentState) {
165 case STATUSVTOLAUTOTAKEOFF_STATE_INACTIVE:
166 return PFFSM_STATE_INACTIVE;
168 break;
169 case STATUSVTOLAUTOTAKEOFF_STATE_DISARMED:
170 return PFFSM_STATE_DISARMED;
172 break;
173 default:
174 return PFFSM_STATE_ACTIVE;
176 break;
180 void VtolAutoTakeoffFSM::Update()
182 runState();
183 if (GetCurrentState() != PFFSM_STATE_INACTIVE) {
184 runAlways();
188 int32_t VtolAutoTakeoffFSM::runState(void)
190 uint8_t flTimeout = false;
192 mAutoTakeoffData->stateRunCount++;
194 if (mAutoTakeoffData->stateTimeoutCount > 0 && mAutoTakeoffData->stateRunCount > mAutoTakeoffData->stateTimeoutCount) {
195 flTimeout = true;
198 // If the current state has a static function, call it
199 if (sAutoTakeoffStateTable[mAutoTakeoffData->currentState].run) {
200 (this->*sAutoTakeoffStateTable[mAutoTakeoffData->currentState].run)(flTimeout);
202 return 0;
205 int32_t VtolAutoTakeoffFSM::runAlways(void)
207 void assessAltitude(void);
209 return 0;
212 // PathFollower implements the PID scheme and has a objective
213 // set by a PathDesired object. Based on the mode, pathfollower
214 // uses FSM's as helper functions that manage state and event detection.
215 // PathFollower calls into FSM methods to alter its commands.
217 void VtolAutoTakeoffFSM::BoundThrust(float &ulow, float &uhigh)
219 ulow = mAutoTakeoffData->boundThrustMin;
220 uhigh = mAutoTakeoffData->boundThrustMax;
223 if (mAutoTakeoffData->flConstrainThrust) {
224 uhigh = mAutoTakeoffData->thrustLimit;
228 void VtolAutoTakeoffFSM::ConstrainStabiDesired(StabilizationDesiredData *stabDesired)
230 if (mAutoTakeoffData->flZeroStabiHorizontal && stabDesired) {
231 stabDesired->Pitch = 0.0f;
232 stabDesired->Roll = 0.0f;
233 stabDesired->Yaw = 0.0f;
237 // Set the new state and perform setup for subsequent state run calls
238 // This is called by state run functions on event detection that drive
239 // state transitions.
240 void VtolAutoTakeoffFSM::setState(StatusVtolAutoTakeoffStateOptions newState, StatusVtolAutoTakeoffStateExitReasonOptions reason)
242 mAutoTakeoffData->fsmAutoTakeoffStatus.StateExitReason[mAutoTakeoffData->currentState] = reason;
244 if (mAutoTakeoffData->currentState == newState) {
245 return;
247 mAutoTakeoffData->currentState = newState;
249 if (newState != STATUSVTOLAUTOTAKEOFF_STATE_INACTIVE) {
250 float altitudeAboveTakeoff = assessAltitude();
251 mAutoTakeoffData->fsmAutoTakeoffStatus.AltitudeAtState[newState] = altitudeAboveTakeoff;
254 // Restart state timer counter
255 mAutoTakeoffData->stateRunCount = 0;
257 // Reset state timeout to disabled/zero
258 mAutoTakeoffData->stateTimeoutCount = 0;
260 if (sAutoTakeoffStateTable[mAutoTakeoffData->currentState].setup) {
261 (this->*sAutoTakeoffStateTable[mAutoTakeoffData->currentState].setup)();
264 // Update StatusVtolAutoTakeoff UAVObject with new status
265 updateVtolAutoTakeoffFSMStatus();
269 // Timeout utility function for use by state init implementations
270 void VtolAutoTakeoffFSM::setStateTimeout(int32_t count)
272 mAutoTakeoffData->stateTimeoutCount = count;
275 // Update StatusVtolAutoTakeoff UAVObject
276 void VtolAutoTakeoffFSM::updateVtolAutoTakeoffFSMStatus()
278 mAutoTakeoffData->fsmAutoTakeoffStatus.State = mAutoTakeoffData->currentState;
279 if (mAutoTakeoffData->flLowAltitude) {
280 mAutoTakeoffData->fsmAutoTakeoffStatus.AltitudeState = STATUSVTOLAUTOTAKEOFF_ALTITUDESTATE_LOW;
281 } else {
282 mAutoTakeoffData->fsmAutoTakeoffStatus.AltitudeState = STATUSVTOLAUTOTAKEOFF_ALTITUDESTATE_HIGH;
284 StatusVtolAutoTakeoffSet(&mAutoTakeoffData->fsmAutoTakeoffStatus);
288 float VtolAutoTakeoffFSM::assessAltitude(void)
290 float positionDown;
292 PositionStateDownGet(&positionDown);
293 float takeOffDown = 0.0f;
294 if (mAutoTakeoffData->takeOffLocation.Status == TAKEOFFLOCATION_STATUS_VALID) {
295 takeOffDown = mAutoTakeoffData->takeOffLocation.Down;
297 float positionDownRelativeToTakeoff = positionDown - takeOffDown;
298 if (positionDownRelativeToTakeoff < AUTOTAKEOFF_SLOWDOWN_HEIGHT) {
299 mAutoTakeoffData->flLowAltitude = false;
300 } else {
301 mAutoTakeoffData->flLowAltitude = true;
303 // Return the altitude above takeoff, which is the negation of positionDownRelativeToTakeoff
304 return -positionDownRelativeToTakeoff;
307 // Action the required state from plans.c
308 void VtolAutoTakeoffFSM::setControlState(StatusVtolAutoTakeoffControlStateOptions controlState)
310 mAutoTakeoffData->fsmAutoTakeoffStatus.ControlState = controlState;
312 switch (controlState) {
313 case STATUSVTOLAUTOTAKEOFF_CONTROLSTATE_WAITFORARMED:
314 setState(STATUSVTOLAUTOTAKEOFF_STATE_INACTIVE, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_NONE);
315 break;
316 case STATUSVTOLAUTOTAKEOFF_CONTROLSTATE_WAITFORMIDTHROTTLE:
317 setState(STATUSVTOLAUTOTAKEOFF_STATE_INACTIVE, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_NONE);
318 break;
319 case STATUSVTOLAUTOTAKEOFF_CONTROLSTATE_REQUIREUNARMEDFIRST:
320 setState(STATUSVTOLAUTOTAKEOFF_STATE_INACTIVE, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_NONE);
321 break;
322 case STATUSVTOLAUTOTAKEOFF_CONTROLSTATE_INITIATE:
323 setState(STATUSVTOLAUTOTAKEOFF_STATE_CHECKSTATE, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_NONE);
324 break;
325 case STATUSVTOLAUTOTAKEOFF_CONTROLSTATE_POSITIONHOLD:
326 setState(STATUSVTOLAUTOTAKEOFF_STATE_HOLD, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_NONE);
327 break;
328 case STATUSVTOLAUTOTAKEOFF_CONTROLSTATE_ABORT:
329 setState(STATUSVTOLAUTOTAKEOFF_STATE_HOLD, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_NONE);
330 break;
335 // State: INACTIVE
336 void VtolAutoTakeoffFSM::setup_inactive(void)
338 // Re-initialise local variables
339 mAutoTakeoffData->flZeroStabiHorizontal = false;
340 mAutoTakeoffData->flConstrainThrust = false;
343 // State: CHECKSTATE
344 void VtolAutoTakeoffFSM::setup_checkstate(void)
346 // Assumptions that do not need to be checked if flight mode is AUTOTAKEOFF
347 // 1. Already armed
348 // 2. Not in flight. This was checked in plans.c
349 // 3. User has placed throttle position to more than 30% to allow autotakeoff
351 // If pathplanner, we need additional checks
352 // E.g. if inflight, this mode is just position hold
353 StabilizationDesiredData stabDesired;
355 StabilizationDesiredGet(&stabDesired);
356 if (stabDesired.Thrust > vtolPathFollowerSettings->ThrustLimits.Min) {
357 setState(STATUSVTOLAUTOTAKEOFF_STATE_HOLD, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_NONE);
358 return;
362 // Start from a enforced thrust off condition
363 mAutoTakeoffData->flConstrainThrust = false;
364 mAutoTakeoffData->boundThrustMin = -0.1f;
365 mAutoTakeoffData->boundThrustMax = 0.0f;
367 setState(STATUSVTOLAUTOTAKEOFF_STATE_SLOWSTART, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_TIMEOUT);
370 // STATE: SLOWSTART spools up motors to vtol min over 2 seconds for effect.
371 // PID loops may be cumulating I terms but that problem needs to be solved
372 #define SLOWSTART_INITIAL_THRUST 0.05f // assumed to be less than vtol min
373 void VtolAutoTakeoffFSM::setup_slowstart(void)
375 setStateTimeout(TIMEOUT_SLOWSTART);
376 mAutoTakeoffData->flZeroStabiHorizontal = true; // turn off positional controllers
377 StabilizationDesiredData stabDesired;
378 StabilizationDesiredGet(&stabDesired);
379 float vtol_thrust_min = vtolPathFollowerSettings->ThrustLimits.Min;
380 if (vtol_thrust_min < SLOWSTART_INITIAL_THRUST) {
381 vtol_thrust_min = SLOWSTART_INITIAL_THRUST;
383 mAutoTakeoffData->sum1 = (vtol_thrust_min - SLOWSTART_INITIAL_THRUST) / (float)TIMEOUT_SLOWSTART;
384 mAutoTakeoffData->sum2 = vtol_thrust_min;
385 mAutoTakeoffData->boundThrustMin = SLOWSTART_INITIAL_THRUST;
386 mAutoTakeoffData->boundThrustMax = SLOWSTART_INITIAL_THRUST;
387 PositionStateData positionState;
388 PositionStateGet(&positionState);
389 mAutoTakeoffData->expectedAutoTakeoffPositionNorth = positionState.North;
390 mAutoTakeoffData->expectedAutoTakeoffPositionEast = positionState.East;
393 void VtolAutoTakeoffFSM::run_slowstart(__attribute__((unused)) uint8_t flTimeout)
395 // increase thrust setpoint step by step
396 if (mAutoTakeoffData->boundThrustMin < mAutoTakeoffData->sum2) {
397 mAutoTakeoffData->boundThrustMin += mAutoTakeoffData->sum1;
399 mAutoTakeoffData->boundThrustMax += mAutoTakeoffData->sum1;
400 if (mAutoTakeoffData->boundThrustMax > mAutoTakeoffData->sum2) {
401 mAutoTakeoffData->boundThrustMax = mAutoTakeoffData->sum2;
404 if (flTimeout) {
405 setState(STATUSVTOLAUTOTAKEOFF_STATE_THRUSTUP, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_TIMEOUT);
409 // STATE: THRUSTUP spools up motors to vtol min over 1 second for effect.
410 // PID loops may be cumulating I terms but that problem needs to be solved
411 #define THRUSTUP_FINAL_THRUST_AS_RATIO_OF_VTOLMAX 0.8f
412 void VtolAutoTakeoffFSM::setup_thrustup(void)
414 setStateTimeout(TIMEOUT_THRUSTUP);
415 mAutoTakeoffData->flZeroStabiHorizontal = false;
416 mAutoTakeoffData->sum2 = THRUSTUP_FINAL_THRUST_AS_RATIO_OF_VTOLMAX * vtolPathFollowerSettings->ThrustLimits.Max;
417 mAutoTakeoffData->sum1 = (mAutoTakeoffData->sum2 - mAutoTakeoffData->boundThrustMax) / (float)TIMEOUT_THRUSTUP;
418 mAutoTakeoffData->boundThrustMin = vtolPathFollowerSettings->ThrustLimits.Min;
421 void VtolAutoTakeoffFSM::run_thrustup(__attribute__((unused)) uint8_t flTimeout)
423 // increase thrust setpoint step by step
424 mAutoTakeoffData->boundThrustMax += mAutoTakeoffData->sum1;
425 if (mAutoTakeoffData->boundThrustMax > mAutoTakeoffData->sum2) {
426 mAutoTakeoffData->boundThrustMax = mAutoTakeoffData->sum2;
429 if (flTimeout) {
430 setState(STATUSVTOLAUTOTAKEOFF_STATE_TAKEOFF, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_TIMEOUT);
435 // STATE: TAKEOFF
436 void VtolAutoTakeoffFSM::setup_takeoff(void)
438 mAutoTakeoffData->flZeroStabiHorizontal = false;
440 void VtolAutoTakeoffFSM::run_takeoff(__attribute__((unused)) uint8_t flTimeout)
442 StabilizationDesiredData stabDesired;
444 StabilizationDesiredGet(&stabDesired);
445 if (stabDesired.Thrust < 0.0f) {
446 setState(STATUSVTOLAUTOTAKEOFF_STATE_THRUSTOFF, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_ZEROTHRUST);
447 return;
450 // detect broad sideways drift.
451 PositionStateData positionState;
452 PositionStateGet(&positionState);
453 float north_error = mAutoTakeoffData->expectedAutoTakeoffPositionNorth - positionState.North;
454 float east_error = mAutoTakeoffData->expectedAutoTakeoffPositionEast - positionState.East;
455 float down_error = pathDesired->End.Down - positionState.Down;
456 float positionError = sqrtf(north_error * north_error + east_error * east_error);
457 if (positionError > 3.0f) {
458 setState(STATUSVTOLAUTOTAKEOFF_STATE_THRUSTDOWN, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_POSITIONERROR);
459 return;
461 if (fabsf(down_error) < 0.5f) {
462 setState(STATUSVTOLAUTOTAKEOFF_STATE_HOLD, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_ARRIVEDATALT);
463 return;
467 // STATE: HOLD
468 void VtolAutoTakeoffFSM::setup_hold(void)
470 mAutoTakeoffData->flZeroStabiHorizontal = false;
471 mAutoTakeoffData->flAltitudeHold = true;
473 void VtolAutoTakeoffFSM::run_hold(__attribute__((unused)) uint8_t flTimeout)
476 uint8_t VtolAutoTakeoffFSM::PositionHoldState(void)
478 return mAutoTakeoffData->flAltitudeHold;
481 // STATE: THRUSTDOWN
482 void VtolAutoTakeoffFSM::setup_thrustdown(void)
484 setStateTimeout(TIMEOUT_THRUSTDOWN);
485 mAutoTakeoffData->flZeroStabiHorizontal = true;
486 mAutoTakeoffData->flConstrainThrust = true;
487 StabilizationDesiredData stabDesired;
488 StabilizationDesiredGet(&stabDesired);
489 mAutoTakeoffData->thrustLimit = stabDesired.Thrust;
490 mAutoTakeoffData->sum1 = stabDesired.Thrust / (float)TIMEOUT_THRUSTDOWN;
491 mAutoTakeoffData->boundThrustMin = -0.1f;
492 mAutoTakeoffData->boundThrustMax = vtolPathFollowerSettings->ThrustLimits.Neutral;
495 void VtolAutoTakeoffFSM::run_thrustdown(__attribute__((unused)) uint8_t flTimeout)
497 // reduce thrust setpoint step by step
498 mAutoTakeoffData->thrustLimit -= mAutoTakeoffData->sum1;
500 StabilizationDesiredData stabDesired;
501 StabilizationDesiredGet(&stabDesired);
502 if (stabDesired.Thrust < 0.0f || mAutoTakeoffData->thrustLimit < 0.0f) {
503 setState(STATUSVTOLAUTOTAKEOFF_STATE_THRUSTOFF, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_ZEROTHRUST);
506 if (flTimeout) {
507 setState(STATUSVTOLAUTOTAKEOFF_STATE_THRUSTOFF, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_TIMEOUT);
511 // STATE: THRUSTOFF
512 void VtolAutoTakeoffFSM::setup_thrustoff(void)
514 mAutoTakeoffData->thrustLimit = -1.0f;
515 mAutoTakeoffData->flConstrainThrust = true;
516 mAutoTakeoffData->boundThrustMin = -0.1f;
517 mAutoTakeoffData->boundThrustMax = 0.0f;
520 void VtolAutoTakeoffFSM::run_thrustoff(__attribute__((unused)) uint8_t flTimeout)
522 setState(STATUSVTOLAUTOTAKEOFF_STATE_DISARMED, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_NONE);
525 // STATE: DISARMED
526 void VtolAutoTakeoffFSM::setup_disarmed(void)
528 mAutoTakeoffData->thrustLimit = -1.0f;
529 mAutoTakeoffData->flConstrainThrust = true;
530 mAutoTakeoffData->flZeroStabiHorizontal = true;
531 mAutoTakeoffData->observationCount = 0;
532 mAutoTakeoffData->boundThrustMin = -0.1f;
533 mAutoTakeoffData->boundThrustMax = 0.0f;
535 if (flightStatus->ControlChain.PathPlanner != FLIGHTSTATUS_CONTROLCHAIN_TRUE) {
536 AlarmsSet(SYSTEMALARMS_ALARM_GUIDANCE, SYSTEMALARMS_ALARM_CRITICAL);
540 void VtolAutoTakeoffFSM::run_disarmed(__attribute__((unused)) uint8_t flTimeout)
542 if (flightStatus->ControlChain.PathPlanner != FLIGHTSTATUS_CONTROLCHAIN_TRUE) {
543 AlarmsSet(SYSTEMALARMS_ALARM_GUIDANCE, SYSTEMALARMS_ALARM_CRITICAL);
545 #ifdef DEBUG_GROUNDIMPACT
546 if (mAutoTakeoffData->observationCount++ > 100) {
547 setState(AUTOTAKEOFF_STATE_WTG_FOR_GROUNDEFFECT, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_NONE);
549 #endif