2 ******************************************************************************
4 * @file grounddrivecontroller.cpp
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2015.
6 * @brief Ground drive controller
7 * the required PathDesired LAND mode.
8 * @see The GNU Public License (GPL) Version 3
10 *****************************************************************************/
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <openpilot.h>
30 #include <callbackinfo.h>
34 #include <CoordinateConversions.h>
35 #include <sin_lookup.h>
36 #include <pathdesired.h>
39 #include <sanitycheck.h>
41 #include <homelocation.h>
42 #include <accelstate.h>
43 #include <groundpathfollowersettings.h>
44 #include <flightstatus.h>
45 #include <flightmodesettings.h>
46 #include <pathstatus.h>
47 #include <positionstate.h>
48 #include <velocitystate.h>
49 #include <velocitydesired.h>
50 #include <stabilizationdesired.h>
51 #include <airspeedstate.h>
52 #include <attitudestate.h>
53 #include <takeofflocation.h>
54 #include <poilocation.h>
55 #include <manualcontrolcommand.h>
56 #include <systemsettings.h>
57 #include <stabilizationbank.h>
58 #include <stabilizationdesired.h>
59 #include <pathsummary.h>
60 #include <statusgrounddrive.h>
64 #include "grounddrivecontroller.h"
68 // pointer to a singleton instance
69 GroundDriveController
*GroundDriveController::p_inst
= 0;
71 GroundDriveController::GroundDriveController()
72 : groundSettings(0), mActive(false), mMode(0)
75 // Called when mode first engaged
76 void GroundDriveController::Activate(void)
82 mMode
= pathDesired
->Mode
;
86 uint8_t GroundDriveController::IsActive(void)
91 uint8_t GroundDriveController::Mode(void)
96 // Objective updated in pathdesired
97 void GroundDriveController::ObjectiveUpdated(void)
100 void GroundDriveController::Deactivate(void)
104 controlNE
.Deactivate();
109 void GroundDriveController::SettingsUpdated(void)
111 const float dT
= groundSettings
->UpdatePeriod
/ 1000.0f
;
113 controlNE
.UpdatePositionalParameters(groundSettings
->HorizontalPosP
);
114 controlNE
.UpdateParameters(groundSettings
->SpeedPI
.Kp
,
115 groundSettings
->SpeedPI
.Ki
,
116 groundSettings
->SpeedPI
.Kd
,
117 groundSettings
->SpeedPI
.Beta
,
119 groundSettings
->HorizontalVelMax
);
122 // max/min are NE command values equivalent to thrust but must be symmetrical as this is NE not forward/reverse.
123 controlNE
.UpdateCommandParameters(-groundSettings
->ThrustLimit
.Max
, groundSettings
->ThrustLimit
.Max
, groundSettings
->VelocityFeedForward
);
127 * Initialise the module, called on startup
128 * \returns 0 on success or -1 if initialisation failed
130 int32_t GroundDriveController::Initialize(GroundPathFollowerSettingsData
*ptr_groundSettings
)
132 PIOS_Assert(ptr_groundSettings
);
134 groundSettings
= ptr_groundSettings
;
139 void GroundDriveController::UpdateAutoPilot()
141 uint8_t result
= updateAutoPilotGround();
144 AlarmsSet(SYSTEMALARMS_ALARM_GUIDANCE
, SYSTEMALARMS_ALARM_OK
);
146 pathStatus
->Status
= PATHSTATUS_STATUS_CRITICAL
;
147 AlarmsSet(SYSTEMALARMS_ALARM_GUIDANCE
, SYSTEMALARMS_ALARM_WARNING
);
150 PathStatusSet(pathStatus
);
154 * fixed wing autopilot:
156 * 1. update path velocity for limited motion crafts
157 * 2. update attitude according to default fixed wing pathfollower algorithm
159 uint8_t GroundDriveController::updateAutoPilotGround()
161 updatePathVelocity(groundSettings
->CourseFeedForward
);
162 return updateGroundDesiredAttitude();
166 * Compute desired velocity from the current position and path
168 void GroundDriveController::updatePathVelocity(float kFF
)
170 PositionStateData positionState
;
172 PositionStateGet(&positionState
);
173 VelocityStateData velocityState
;
174 VelocityStateGet(&velocityState
);
175 VelocityDesiredData velocityDesired
;
176 controlNE
.UpdateVelocityState(velocityState
.North
, velocityState
.East
);
178 // look ahead kFF seconds
179 float cur
[3] = { positionState
.North
+ (velocityState
.North
* kFF
),
180 positionState
.East
+ (velocityState
.East
* kFF
),
181 positionState
.Down
+ (velocityState
.Down
* kFF
) };
182 struct path_status progress
;
183 path_progress(pathDesired
, cur
, &progress
, false);
185 // GOTOENDPOINT: correction_vector is distance array to endpoint, path_vector is velocity vector
186 // FOLLOWVECTOR: correct_vector is distance to vector path, path_vector is the desired velocity vector
188 // Calculate the desired velocity from the lateral vector path errors (correct_vector) and the desired velocity vector (path_vector)
189 controlNE
.ControlPositionWithPath(&progress
);
191 controlNE
.GetVelocityDesired(&north
, &east
);
192 velocityDesired
.North
= north
;
193 velocityDesired
.East
= east
;
194 velocityDesired
.Down
= 0.0f
;
197 pathStatus
->error
= progress
.error
;
198 pathStatus
->fractional_progress
= progress
.fractional_progress
;
199 // FOLLOWVECTOR: desired velocity vector
200 pathStatus
->path_direction_north
= progress
.path_vector
[0];
201 pathStatus
->path_direction_east
= progress
.path_vector
[1];
202 pathStatus
->path_direction_down
= progress
.path_vector
[2];
204 // FOLLOWVECTOR: correction distance to vector path
205 pathStatus
->correction_direction_north
= progress
.correction_vector
[0];
206 pathStatus
->correction_direction_east
= progress
.correction_vector
[1];
207 pathStatus
->correction_direction_down
= progress
.correction_vector
[2];
209 VelocityDesiredSet(&velocityDesired
);
213 * Compute desired attitude for ground vehicles
215 uint8_t GroundDriveController::updateGroundDesiredAttitude()
217 StatusGroundDriveData statusGround
;
218 VelocityStateData velocityState
;
220 VelocityStateGet(&velocityState
);
221 AttitudeStateData attitudeState
;
222 AttitudeStateGet(&attitudeState
);
223 statusGround
.State
.Yaw
= attitudeState
.Yaw
;
224 statusGround
.State
.Velocity
= sqrtf(velocityState
.North
* velocityState
.North
+ velocityState
.East
* velocityState
.East
);
226 StabilizationDesiredData stabDesired
;
227 StabilizationDesiredGet(&stabDesired
);
229 // estimate a north/east command value to control the velocity error.
230 // ThrustLimits.Max(+-) limits the range. Think of this as a command unit vector
231 // of the ultimate direction to reduce lateral error and achieve the target direction (desired angle).
232 float northCommand
, eastCommand
;
233 controlNE
.GetNECommand(&northCommand
, &eastCommand
);
235 // Get current vehicle orientation
236 float angle_radians
= DEG2RAD(attitudeState
.Yaw
); // (+-pi)
237 float cos_angle
= cosf(angle_radians
);
238 float sine_angle
= sinf(angle_radians
);
240 float courseCommand
= 0.0f
;
241 float speedCommand
= 0.0f
;
242 float lateralCommand
= boundf(-northCommand
* sine_angle
+ eastCommand
* cos_angle
, -groundSettings
->ThrustLimit
.Max
, groundSettings
->ThrustLimit
.Max
);
243 float forwardCommand
= boundf(northCommand
* cos_angle
+ eastCommand
* sine_angle
, -groundSettings
->ThrustLimit
.Max
, groundSettings
->ThrustLimit
.Max
);
244 // +ve facing correct direction, lateral command should just correct angle,
245 if (forwardCommand
> 0.0f
) {
246 // if +ve forward command, -+ lateralCommand drives steering to manage lateral error and angular error
248 courseCommand
= boundf(lateralCommand
, -1.0f
, 1.0f
);
249 speedCommand
= boundf(forwardCommand
, groundSettings
->ThrustLimit
.SlowForward
, groundSettings
->ThrustLimit
.Max
);
251 // reinstate max thrust
252 controlNE
.UpdateCommandParameters(-groundSettings
->ThrustLimit
.Max
, groundSettings
->ThrustLimit
.Max
, groundSettings
->VelocityFeedForward
);
254 statusGround
.ControlState
= STATUSGROUNDDRIVE_CONTROLSTATE_ONTRACK
;
256 // -ve facing opposite direction, lateral command irrelevant, need to turn to change direction and do so slowly.
258 // Reduce steering angle based on current velocity
259 float steeringReductionFactor
= 1.0f
;
260 if (stabDesired
.Thrust
> 0.3f
) {
261 steeringReductionFactor
= (groundSettings
->HorizontalVelMax
- statusGround
.State
.Velocity
) / groundSettings
->HorizontalVelMax
;
262 steeringReductionFactor
= boundf(steeringReductionFactor
, 0.05f
, 1.0f
);
265 // should we turn left or right?
266 if (lateralCommand
>= 0.1f
) {
267 courseCommand
= 1.0f
* steeringReductionFactor
;
268 statusGround
.ControlState
= STATUSGROUNDDRIVE_CONTROLSTATE_TURNAROUNDRIGHT
;
270 courseCommand
= -1.0f
* steeringReductionFactor
;
271 statusGround
.ControlState
= STATUSGROUNDDRIVE_CONTROLSTATE_TURNAROUNDLEFT
;
274 // Impose limits to slow down.
275 controlNE
.UpdateCommandParameters(-groundSettings
->ThrustLimit
.SlowForward
, groundSettings
->ThrustLimit
.SlowForward
, 0.0f
);
277 speedCommand
= groundSettings
->ThrustLimit
.SlowForward
;
280 stabDesired
.Roll
= 0.0f
;
281 stabDesired
.Pitch
= 0.0f
;
282 stabDesired
.Yaw
= courseCommand
;
284 // Mix yaw into thrust limit TODO
285 stabDesired
.Thrust
= boundf(speedCommand
, groundSettings
->ThrustLimit
.Min
, groundSettings
->ThrustLimit
.Max
);
287 stabDesired
.StabilizationMode
.Roll
= STABILIZATIONDESIRED_STABILIZATIONMODE_MANUAL
;
288 stabDesired
.StabilizationMode
.Pitch
= STABILIZATIONDESIRED_STABILIZATIONMODE_MANUAL
;
289 stabDesired
.StabilizationMode
.Yaw
= STABILIZATIONDESIRED_STABILIZATIONMODE_MANUAL
;
290 stabDesired
.StabilizationMode
.Thrust
= STABILIZATIONDESIRED_STABILIZATIONMODE_MANUAL
;
291 StabilizationDesiredSet(&stabDesired
);
293 statusGround
.NECommand
.North
= northCommand
;
294 statusGround
.NECommand
.East
= eastCommand
;
295 statusGround
.State
.Thrust
= stabDesired
.Thrust
;
296 statusGround
.BodyCommand
.Forward
= forwardCommand
;
297 statusGround
.BodyCommand
.Right
= lateralCommand
;
298 statusGround
.ControlCommand
.Course
= courseCommand
;
299 statusGround
.ControlCommand
.Speed
= speedCommand
;
300 StatusGroundDriveSet(&statusGround
);