2 ******************************************************************************
5 * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
6 * The OpenPilot Team, http://www.openpilot.org Copyright (C) 2015.
7 * @brief This module compared @ref PositionActuatl to @ref ActiveWaypoint
8 * and sets @ref AttitudeDesired. It only does this when the FlightMode field
9 * of @ref ManualControlCommand is Auto.
11 * @see The GNU Public License (GPL) Version 3
12 * @addtogroup LibrePilot LibrePilotModules Modules PathFollower Navigation
14 *****************************************************************************/
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 3 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 * Input object: PathDesired
33 * Input object: PositionState
34 * Input object: ManualControlCommand
35 * Output object: StabilizationDesired
37 * This module acts as "autopilot" - it controls the setpoints of stabilization
38 * based on current flight situation and desired flight path (PathDesired) as
39 * directed by flightmode selection or pathplanner
40 * This is a periodic delayed callback module
42 * Modules have no API, all communication to other modules is done through UAVObjects.
43 * However modules may use the API exposed by shared libraries.
44 * See the OpenPilot wiki for more details.
45 * http://www.openpilot.org/OpenPilot_Application_Architecture
50 #include <openpilot.h>
52 #include <callbackinfo.h>
56 #include <CoordinateConversions.h>
57 #include <sin_lookup.h>
58 #include <pathdesired.h>
61 #include <sanitycheck.h>
63 #include <groundpathfollowersettings.h>
64 #include <fixedwingpathfollowersettings.h>
65 #include <fixedwingpathfollowerstatus.h>
66 #include <vtolpathfollowersettings.h>
67 #include <flightstatus.h>
68 #include <flightmodesettings.h>
69 #include <pathstatus.h>
70 #include <positionstate.h>
71 #include <velocitystate.h>
72 #include <velocitydesired.h>
73 #include <stabilizationdesired.h>
74 #include <airspeedstate.h>
75 #include <attitudestate.h>
76 #include <takeofflocation.h>
77 #include <poilocation.h>
78 #include <manualcontrolcommand.h>
79 #include <systemsettings.h>
80 #include <stabilizationbank.h>
81 #include <vtolselftuningstats.h>
82 #include <pathsummary.h>
83 #include <pidstatus.h>
84 #include <homelocation.h>
85 #include <accelstate.h>
86 #include <statusvtolautotakeoff.h>
87 #include <statusvtolland.h>
88 #include <statusgrounddrive.h>
91 #include "pathfollowercontrol.h"
92 #include "vtollandcontroller.h"
93 #include "vtolautotakeoffcontroller.h"
94 #include "vtolvelocitycontroller.h"
95 #include "vtolbrakecontroller.h"
96 #include "vtolflycontroller.h"
97 #include "fixedwingflycontroller.h"
98 #include "fixedwingautotakeoffcontroller.h"
99 #include "fixedwinglandcontroller.h"
100 #include "grounddrivecontroller.h"
104 #define CALLBACK_PRIORITY CALLBACK_PRIORITY_LOW
105 #define CBTASK_PRIORITY CALLBACK_TASK_FLIGHTCONTROL
107 #define PF_IDLE_UPDATE_RATE_MS 100
109 #define STACK_SIZE_BYTES 2048
115 static DelayedCallbackInfo
*pathFollowerCBInfo
;
116 static uint32_t updatePeriod
= PF_IDLE_UPDATE_RATE_MS
;
117 static FrameType_t frameType
= FRAME_TYPE_MULTIROTOR
;
118 static PathStatusData pathStatus
;
119 static PathDesiredData pathDesired
;
120 static FixedWingPathFollowerSettingsData fixedWingPathFollowerSettings
;
121 static GroundPathFollowerSettingsData groundPathFollowerSettings
;
122 static VtolPathFollowerSettingsData vtolPathFollowerSettings
;
123 static FlightStatusData flightStatus
;
124 static PathFollowerControl
*activeController
= 0;
127 static void pathFollowerTask(void);
128 static void SettingsUpdatedCb(UAVObjEvent
*ev
);
129 static void airspeedStateUpdatedCb(UAVObjEvent
*ev
);
130 static void pathFollowerObjectiveUpdatedCb(UAVObjEvent
*ev
);
131 static void flightStatusUpdatedCb(UAVObjEvent
*ev
);
132 static void updateFixedAttitude(float *attitude
);
133 static void pathFollowerInitializeControllersForFrameType();
136 * Initialise the module, called on startup
137 * \returns 0 on success or -1 if initialisation failed
139 extern "C" int32_t PathFollowerStart()
142 PathStatusGet(&pathStatus
);
143 SettingsUpdatedCb(NULL
);
144 PIOS_CALLBACKSCHEDULER_Dispatch(pathFollowerCBInfo
);
151 * Initialise the module, called on startup
152 * \returns 0 on success or -1 if initialisation failed
154 extern "C" int32_t PathFollowerInitialize()
156 // initialize objects
157 FixedWingPathFollowerStatusInitialize();
158 FlightStatusInitialize();
159 PathStatusInitialize();
160 PathSummaryInitialize();
161 PathDesiredInitialize();
162 PositionStateInitialize();
163 VelocityStateInitialize();
164 VelocityDesiredInitialize();
165 StabilizationDesiredInitialize();
166 AirspeedStateInitialize();
167 AttitudeStateInitialize();
168 PoiLocationInitialize();
169 ManualControlCommandInitialize();
170 StabilizationBankInitialize();
171 VtolSelfTuningStatsInitialize();
172 PIDStatusInitialize();
173 StatusVtolLandInitialize();
174 StatusGroundDriveInitialize();
175 StatusVtolAutoTakeoffInitialize();
177 // VtolLandFSM additional objects
178 AccelStateInitialize();
180 // Init references to controllers
181 PathFollowerControl::Initialize(&pathDesired
, &flightStatus
, &pathStatus
);
183 // Create object queue
184 pathFollowerCBInfo
= PIOS_CALLBACKSCHEDULER_Create(&pathFollowerTask
, CALLBACK_PRIORITY
, CBTASK_PRIORITY
, CALLBACKINFO_RUNNING_PATHFOLLOWER
, STACK_SIZE_BYTES
);
185 FixedWingPathFollowerSettingsConnectCallback(&SettingsUpdatedCb
);
186 GroundPathFollowerSettingsConnectCallback(&SettingsUpdatedCb
);
187 VtolPathFollowerSettingsConnectCallback(&SettingsUpdatedCb
);
188 PathDesiredConnectCallback(&pathFollowerObjectiveUpdatedCb
);
189 FlightStatusConnectCallback(&flightStatusUpdatedCb
);
190 SystemSettingsConnectCallback(&SettingsUpdatedCb
);
191 AirspeedStateConnectCallback(&airspeedStateUpdatedCb
);
192 VtolSelfTuningStatsConnectCallback(&SettingsUpdatedCb
);
196 MODULE_INITCALL(PathFollowerInitialize
, PathFollowerStart
);
198 void pathFollowerInitializeControllersForFrameType()
200 static uint8_t multirotor_initialised
= 0;
201 static uint8_t fixedwing_initialised
= 0;
202 static uint8_t ground_initialised
= 0;
205 case FRAME_TYPE_MULTIROTOR
:
206 case FRAME_TYPE_HELI
:
207 if (!multirotor_initialised
) {
208 VtolLandController::instance()->Initialize(&vtolPathFollowerSettings
);
209 VtolAutoTakeoffController::instance()->Initialize(&vtolPathFollowerSettings
);
210 VtolVelocityController::instance()->Initialize(&vtolPathFollowerSettings
);
211 VtolFlyController::instance()->Initialize(&vtolPathFollowerSettings
);
212 VtolBrakeController::instance()->Initialize(&vtolPathFollowerSettings
);
213 multirotor_initialised
= 1;
217 case FRAME_TYPE_FIXED_WING
:
218 if (!fixedwing_initialised
) {
219 FixedWingFlyController::instance()->Initialize(&fixedWingPathFollowerSettings
);
220 FixedWingAutoTakeoffController::instance()->Initialize(&fixedWingPathFollowerSettings
);
221 FixedWingLandController::instance()->Initialize(&fixedWingPathFollowerSettings
);
222 fixedwing_initialised
= 1;
226 case FRAME_TYPE_GROUND
:
227 if (!ground_initialised
) {
228 GroundDriveController::instance()->Initialize(&groundPathFollowerSettings
);
229 ground_initialised
= 1;
238 static void pathFollowerSetActiveController(void)
240 // Init controllers for the frame type
241 if (activeController
== 0) {
243 pathFollowerInitializeControllersForFrameType();
244 AlarmsSet(SYSTEMALARMS_ALARM_GUIDANCE
, SYSTEMALARMS_ALARM_OK
);
247 case FRAME_TYPE_MULTIROTOR
:
248 case FRAME_TYPE_HELI
:
250 switch (pathDesired
.Mode
) {
251 case PATHDESIRED_MODE_BRAKE
: // brake then hold sequence controller
252 activeController
= VtolBrakeController::instance();
253 activeController
->Activate();
255 case PATHDESIRED_MODE_VELOCITY
: // velocity roam controller
256 activeController
= VtolVelocityController::instance();
257 activeController
->Activate();
259 case PATHDESIRED_MODE_GOTOENDPOINT
:
260 case PATHDESIRED_MODE_FOLLOWVECTOR
:
261 case PATHDESIRED_MODE_CIRCLERIGHT
:
262 case PATHDESIRED_MODE_CIRCLELEFT
:
263 activeController
= VtolFlyController::instance();
264 activeController
->Activate();
266 case PATHDESIRED_MODE_LAND
: // land with optional velocity roam option
267 activeController
= VtolLandController::instance();
268 activeController
->Activate();
270 case PATHDESIRED_MODE_AUTOTAKEOFF
:
271 activeController
= VtolAutoTakeoffController::instance();
272 activeController
->Activate();
275 activeController
= 0;
276 AlarmsSet(SYSTEMALARMS_ALARM_GUIDANCE
, SYSTEMALARMS_ALARM_UNINITIALISED
);
281 case FRAME_TYPE_FIXED_WING
:
283 switch (pathDesired
.Mode
) {
284 case PATHDESIRED_MODE_GOTOENDPOINT
:
285 case PATHDESIRED_MODE_FOLLOWVECTOR
:
286 case PATHDESIRED_MODE_CIRCLERIGHT
:
287 case PATHDESIRED_MODE_CIRCLELEFT
:
288 activeController
= FixedWingFlyController::instance();
289 activeController
->Activate();
291 case PATHDESIRED_MODE_LAND
: // land with optional velocity roam option
292 activeController
= FixedWingLandController::instance();
293 activeController
->Activate();
295 case PATHDESIRED_MODE_AUTOTAKEOFF
:
296 activeController
= FixedWingAutoTakeoffController::instance();
297 activeController
->Activate();
300 activeController
= 0;
301 AlarmsSet(SYSTEMALARMS_ALARM_GUIDANCE
, SYSTEMALARMS_ALARM_UNINITIALISED
);
306 case FRAME_TYPE_GROUND
:
308 switch (pathDesired
.Mode
) {
309 case PATHDESIRED_MODE_GOTOENDPOINT
:
310 case PATHDESIRED_MODE_FOLLOWVECTOR
:
311 case PATHDESIRED_MODE_CIRCLERIGHT
:
312 case PATHDESIRED_MODE_CIRCLELEFT
:
313 activeController
= GroundDriveController::instance();
314 activeController
->Activate();
317 activeController
= 0;
318 AlarmsSet(SYSTEMALARMS_ALARM_GUIDANCE
, SYSTEMALARMS_ALARM_UNINITIALISED
);
324 activeController
= 0;
325 AlarmsSet(SYSTEMALARMS_ALARM_GUIDANCE
, SYSTEMALARMS_ALARM_UNINITIALISED
);
332 * Module thread, should not return.
334 static void pathFollowerTask(void)
336 FlightStatusGet(&flightStatus
);
338 if (flightStatus
.ControlChain
.PathFollower
!= FLIGHTSTATUS_CONTROLCHAIN_TRUE
) {
339 AlarmsSet(SYSTEMALARMS_ALARM_GUIDANCE
, SYSTEMALARMS_ALARM_UNINITIALISED
);
340 PIOS_CALLBACKSCHEDULER_Schedule(pathFollowerCBInfo
, PF_IDLE_UPDATE_RATE_MS
, CALLBACK_UPDATEMODE_SOONER
);
344 pathStatus
.UID
= pathDesired
.UID
;
345 pathStatus
.Status
= PATHSTATUS_STATUS_INPROGRESS
;
347 pathFollowerSetActiveController();
349 if (activeController
) {
350 activeController
->UpdateAutoPilot();
351 PIOS_CALLBACKSCHEDULER_Schedule(pathFollowerCBInfo
, updatePeriod
, CALLBACK_UPDATEMODE_SOONER
);
355 switch (pathDesired
.Mode
) {
356 case PATHDESIRED_MODE_FIXEDATTITUDE
:
357 updateFixedAttitude(pathDesired
.ModeParameters
);
358 AlarmsSet(SYSTEMALARMS_ALARM_GUIDANCE
, SYSTEMALARMS_ALARM_OK
);
360 case PATHDESIRED_MODE_DISARMALARM
:
361 AlarmsSet(SYSTEMALARMS_ALARM_GUIDANCE
, SYSTEMALARMS_ALARM_CRITICAL
);
364 pathStatus
.Status
= PATHSTATUS_STATUS_CRITICAL
;
365 AlarmsSet(SYSTEMALARMS_ALARM_GUIDANCE
, SYSTEMALARMS_ALARM_ERROR
);
368 PathStatusSet(&pathStatus
);
370 PIOS_CALLBACKSCHEDULER_Schedule(pathFollowerCBInfo
, updatePeriod
, CALLBACK_UPDATEMODE_SOONER
);
374 static void pathFollowerObjectiveUpdatedCb(__attribute__((unused
)) UAVObjEvent
*ev
)
376 PathDesiredGet(&pathDesired
);
378 if (activeController
&& pathDesired
.Mode
!= activeController
->Mode()) {
379 activeController
->Deactivate();
380 activeController
= 0;
383 pathFollowerSetActiveController();
385 if (activeController
) {
386 activeController
->ObjectiveUpdated();
390 // we use this to deactivate active controllers as the pathdesired
391 // objective never gets updated with switching to a non-pathfollower flight mode
392 static void flightStatusUpdatedCb(__attribute__((unused
)) UAVObjEvent
*ev
)
394 if (!activeController
) {
398 FlightStatusControlChainData controlChain
;
399 FlightStatusControlChainGet(&controlChain
);
401 if (controlChain
.PathFollower
!= FLIGHTSTATUS_CONTROLCHAIN_TRUE
) {
402 activeController
->Deactivate();
403 activeController
= 0;
408 static void SettingsUpdatedCb(__attribute__((unused
)) UAVObjEvent
*ev
)
410 VtolPathFollowerSettingsGet(&vtolPathFollowerSettings
);
412 FrameType_t previous_frameType
= frameType
;
413 frameType
= GetCurrentFrameType();
415 if (frameType
== FRAME_TYPE_CUSTOM
) {
416 switch (vtolPathFollowerSettings
.TreatCustomCraftAs
) {
417 case VTOLPATHFOLLOWERSETTINGS_TREATCUSTOMCRAFTAS_FIXEDWING
:
418 frameType
= FRAME_TYPE_FIXED_WING
;
420 case VTOLPATHFOLLOWERSETTINGS_TREATCUSTOMCRAFTAS_VTOL
:
421 frameType
= FRAME_TYPE_MULTIROTOR
;
423 case VTOLPATHFOLLOWERSETTINGS_TREATCUSTOMCRAFTAS_GROUND
:
424 frameType
= FRAME_TYPE_GROUND
;
429 // If frame type changes, initialise the frame type controllers
430 if (frameType
!= previous_frameType
) {
431 pathFollowerInitializeControllersForFrameType();
435 case FRAME_TYPE_MULTIROTOR
:
436 case FRAME_TYPE_HELI
:
437 updatePeriod
= vtolPathFollowerSettings
.UpdatePeriod
;
439 case FRAME_TYPE_FIXED_WING
:
440 FixedWingPathFollowerSettingsGet(&fixedWingPathFollowerSettings
);
441 updatePeriod
= fixedWingPathFollowerSettings
.UpdatePeriod
;
443 case FRAME_TYPE_GROUND
:
444 GroundPathFollowerSettingsGet(&groundPathFollowerSettings
);
445 updatePeriod
= groundPathFollowerSettings
.UpdatePeriod
;
448 updatePeriod
= vtolPathFollowerSettings
.UpdatePeriod
;
452 if (activeController
) {
453 activeController
->SettingsUpdated();
458 static void airspeedStateUpdatedCb(__attribute__((unused
)) UAVObjEvent
*ev
)
460 FixedWingFlyController::instance()->AirspeedStateUpdatedCb(ev
);
461 FixedWingAutoTakeoffController::instance()->AirspeedStateUpdatedCb(ev
);
466 * Compute desired attitude from a fixed preset
469 static void updateFixedAttitude(float *attitude
)
471 StabilizationDesiredData stabDesired
;
473 StabilizationDesiredGet(&stabDesired
);
474 stabDesired
.Roll
= attitude
[0];
475 stabDesired
.Pitch
= attitude
[1];
476 stabDesired
.Yaw
= attitude
[2];
477 stabDesired
.Thrust
= attitude
[3];
478 stabDesired
.StabilizationMode
.Roll
= STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE
;
479 stabDesired
.StabilizationMode
.Pitch
= STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE
;
480 stabDesired
.StabilizationMode
.Yaw
= STABILIZATIONDESIRED_STABILIZATIONMODE_AXISLOCK
;
481 stabDesired
.StabilizationMode
.Thrust
= STABILIZATIONDESIRED_STABILIZATIONMODE_MANUAL
;
482 StabilizationDesiredSet(&stabDesired
);