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
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
29 #include <openpilot.h>
33 #include <pathdesired.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>
60 #include <vtolautotakeofffsm.h>
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)
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
;
119 void VtolAutoTakeoffFSM::Inactive(void)
121 memset(mAutoTakeoffData
, 0, sizeof(VtolAutoTakeoffFSMData_T
));
125 // Initialise the FSM
126 void VtolAutoTakeoffFSM::initFSM(void)
128 if (vtolPathFollowerSettings
!= 0) {
129 setState(STATUSVTOLAUTOTAKEOFF_STATE_INACTIVE
, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_NONE
);
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
;
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
);
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
;
169 case STATUSVTOLAUTOTAKEOFF_STATE_DISARMED
:
170 return PFFSM_STATE_DISARMED
;
174 return PFFSM_STATE_ACTIVE
;
180 void VtolAutoTakeoffFSM::Update()
183 if (GetCurrentState() != PFFSM_STATE_INACTIVE
) {
188 int32_t VtolAutoTakeoffFSM::runState(void)
190 uint8_t flTimeout
= false;
192 mAutoTakeoffData
->stateRunCount
++;
194 if (mAutoTakeoffData
->stateTimeoutCount
> 0 && mAutoTakeoffData
->stateRunCount
> mAutoTakeoffData
->stateTimeoutCount
) {
198 // If the current state has a static function, call it
199 if (sAutoTakeoffStateTable
[mAutoTakeoffData
->currentState
].run
) {
200 (this->*sAutoTakeoffStateTable
[mAutoTakeoffData
->currentState
].run
)(flTimeout
);
205 int32_t VtolAutoTakeoffFSM::runAlways(void)
207 void assessAltitude(void);
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
) {
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
;
282 mAutoTakeoffData
->fsmAutoTakeoffStatus
.AltitudeState
= STATUSVTOLAUTOTAKEOFF_ALTITUDESTATE_HIGH
;
284 StatusVtolAutoTakeoffSet(&mAutoTakeoffData
->fsmAutoTakeoffStatus
);
288 float VtolAutoTakeoffFSM::assessAltitude(void)
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;
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
);
316 case STATUSVTOLAUTOTAKEOFF_CONTROLSTATE_WAITFORMIDTHROTTLE
:
317 setState(STATUSVTOLAUTOTAKEOFF_STATE_INACTIVE
, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_NONE
);
319 case STATUSVTOLAUTOTAKEOFF_CONTROLSTATE_REQUIREUNARMEDFIRST
:
320 setState(STATUSVTOLAUTOTAKEOFF_STATE_INACTIVE
, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_NONE
);
322 case STATUSVTOLAUTOTAKEOFF_CONTROLSTATE_INITIATE
:
323 setState(STATUSVTOLAUTOTAKEOFF_STATE_CHECKSTATE
, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_NONE
);
325 case STATUSVTOLAUTOTAKEOFF_CONTROLSTATE_POSITIONHOLD
:
326 setState(STATUSVTOLAUTOTAKEOFF_STATE_HOLD
, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_NONE
);
328 case STATUSVTOLAUTOTAKEOFF_CONTROLSTATE_ABORT
:
329 setState(STATUSVTOLAUTOTAKEOFF_STATE_HOLD
, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_NONE
);
336 void VtolAutoTakeoffFSM::setup_inactive(void)
338 // Re-initialise local variables
339 mAutoTakeoffData
->flZeroStabiHorizontal
= false;
340 mAutoTakeoffData
->flConstrainThrust
= false;
344 void VtolAutoTakeoffFSM::setup_checkstate(void)
346 // Assumptions that do not need to be checked if flight mode is AUTOTAKEOFF
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
);
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
;
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
;
430 setState(STATUSVTOLAUTOTAKEOFF_STATE_TAKEOFF
, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_TIMEOUT
);
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
);
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
);
461 if (fabsf(down_error
) < 0.5f
) {
462 setState(STATUSVTOLAUTOTAKEOFF_STATE_HOLD
, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_ARRIVEDATALT
);
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
;
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
);
507 setState(STATUSVTOLAUTOTAKEOFF_STATE_THRUSTOFF
, STATUSVTOLAUTOTAKEOFF_STATEEXITREASON_TIMEOUT
);
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
);
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
);