38 #include "physical_constants.h"
45 #include "acceldesired.h"
46 #include "altitudeholdsettings.h"
47 #include "altitudeholdstate.h"
48 #include "attitudeactual.h"
49 #include "loitercommand.h"
50 #include "pathdesired.h"
51 #include "positionactual.h"
52 #include "manualcontrolcommand.h"
53 #include "flightstatus.h"
55 #include "pathstatus.h"
56 #include "stabilizationdesired.h"
57 #include "stabilizationsettings.h"
58 #include "velocitydesired.h"
59 #include "velocityactual.h"
60 #include "vtolpathfollowersettings.h"
61 #include "systemsettings.h"
74 const float *hold_pos_ned,
float alt_rate,
bool update_status);
88 PositionActualData positionActual;
89 PositionActualGet(&positionActual);
91 VelocityActualData velocityActual;
92 VelocityActualGet(&velocityActual);
95 PathStatusGet(&pathStatus);
97 const float cur_pos_ned[3] = {
98 positionActual.North +
100 positionActual.East +
102 positionActual.Down };
107 bool current_leg_completed =
108 (pathStatus.Status == PATHSTATUS_STATUS_COMPLETED) &&
109 (pathStatus.Waypoint == pathDesired->Waypoint);
112 pathStatus.error = progress->
error;
113 pathStatus.Waypoint = pathDesired->Waypoint;
117 pathDesired->Start[2], pathDesired->End[2]);
119 const float downError = altitudeSetpoint - positionActual.Down;
122 if (current_leg_completed || pathStatus.fractional_progress > 1.0f) {
123 const bool criterion_altitude =
133 if (criterion_altitude || current_leg_completed) {
134 pathStatus.Status = PATHSTATUS_STATUS_COMPLETED;
135 PathStatusSet(&pathStatus);
137 pathStatus.Status = PATHSTATUS_STATUS_INPROGRESS;
138 PathStatusSet(&pathStatus);
147 pathDesired->StartingVelocity, pathDesired->EndingVelocity);
156 float commands_ned[3];
171 VelocityDesiredData velocityDesired;
172 VelocityDesiredGet(&velocityDesired);
173 velocityDesired.North = commands_ned[0];
174 velocityDesired.East = commands_ned[1];
175 velocityDesired.Down = commands_ned[2];
176 VelocityDesiredSet(&velocityDesired);
178 pathStatus.Status = PATHSTATUS_STATUS_INPROGRESS;
179 PathStatusSet(&pathStatus);
192 const float *hold_pos_ned,
float alt_rate,
bool update_status)
194 PositionActualData positionActual;
195 VelocityDesiredData velocityDesired;
197 PositionActualGet(&positionActual);
199 VelocityActualData velocityActual;
201 VelocityActualGet(&velocityActual);
204 const float cur_pos_ned[3] = {
205 positionActual.North +
207 positionActual.East +
209 positionActual.Down };
218 float scale_horiz_error_mag = 0;
229 if (horiz_error_mag > 0.00001
f) {
236 float damped_ne[2] = { errors_ned[0] * scale_horiz_error_mag,
237 errors_ned[1] * scale_horiz_error_mag };
239 float commands_ned[3];
249 if (fabsf(alt_rate) < 0.001
f) {
257 commands_ned[2] = alt_rate;
263 velocityDesired.North = commands_ned[0];
264 velocityDesired.East = commands_ned[1];
265 velocityDesired.Down = commands_ned[2];
267 VelocityDesiredSet(&velocityDesired);
270 uint8_t
path_status = PATHSTATUS_STATUS_INPROGRESS;
272 if (fabsf(alt_rate) < 0.001
f) {
273 const bool criterion_altitude =
279 path_status = PATHSTATUS_STATUS_COMPLETED;
285 PathStatusStatusSet(&path_status);
340 VelocityDesiredData velocityDesired;
341 VelocityActualData velocityActual;
342 AccelDesiredData accelDesired;
343 NedAccelData nedAccel;
345 float north_error, north_acceleration;
346 float east_error, east_acceleration;
349 static float last_north_velocity;
350 static float last_east_velocity;
352 NedAccelGet(&nedAccel);
353 VelocityActualGet(&velocityActual);
354 VelocityDesiredGet(&velocityDesired);
357 if (
vtol_guidanceSettings.VelocityChangePrediction == VTOLPATHFOLLOWERSETTINGS_VELOCITYCHANGEPREDICTION_TRUE && dT > 0) {
358 north_acceleration = (velocityDesired.North - last_north_velocity) / dT;
359 east_acceleration = (velocityDesired.East - last_east_velocity) / dT;
360 last_north_velocity = velocityDesired.North;
361 last_east_velocity = velocityDesired.East;
363 north_acceleration = 0;
364 east_acceleration = 0;
371 north_error = velocityDesired.North - velocityActual.North;
373 -MAX_ACCELERATION, MAX_ACCELERATION, 0) +
375 -nedAccel.North *
vtol_guidanceSettings.HorizontalVelPID[VTOLPATHFOLLOWERSETTINGS_HORIZONTALVELPID_KD];
378 east_error = velocityDesired.East - velocityActual.East;
380 -MAX_ACCELERATION, MAX_ACCELERATION, 0) +
382 -nedAccel.East *
vtol_guidanceSettings.HorizontalVelPID[VTOLPATHFOLLOWERSETTINGS_HORIZONTALVELPID_KD];
384 accelDesired.North = north_acceleration;
385 accelDesired.East = east_acceleration;
391 down_error = velocityDesired.Down - velocityActual.Down;
396 AccelDesiredSet(&accelDesired);
403 AltitudeHoldStateData altitudeHoldState;
404 altitudeHoldState.VelocityDesired = downCommand;
406 altitudeHoldState.AngleGain = 1.0f;
411 AttitudeActualData attitudeActual;
412 AttitudeActualGet(&attitudeActual);
416 float fraction = attitudeActual.q1 * attitudeActual.q1 -
417 attitudeActual.q2 * attitudeActual.q2 -
418 attitudeActual.q3 * attitudeActual.q3 +
419 attitudeActual.q4 * attitudeActual.q4;
429 downCommand = (fraction > 0.1f) ? (downCommand / fraction) : 0.0f;
431 altitudeHoldState.AngleGain = 1.0f / fraction;
434 altitudeHoldState.Thrust = downCommand;
435 AltitudeHoldStateSet(&altitudeHoldState);
453 float default_adj[2] = {0,0};
456 att_adj = default_adj;
459 AccelDesiredData accelDesired;
460 AccelDesiredGet(&accelDesired);
462 StabilizationSettingsData stabSet;
463 StabilizationSettingsGet(&stabSet);
465 SystemSettingsData system_settings;
466 SystemSettingsGet( &system_settings );
468 ManualControlCommandData manual_control_command;
469 ManualControlCommandGet( &manual_control_command );
471 float northCommand = accelDesired.North;
472 float eastCommand = accelDesired.East;
476 AttitudeActualYawGet(&yaw);
477 float forward_accel_desired = -northCommand * cosf(yaw * DEG2RAD) + -eastCommand * sinf(yaw * DEG2RAD);
478 float right_accel_desired = -northCommand * sinf(yaw * DEG2RAD) + eastCommand * cosf(yaw * DEG2RAD);
480 StabilizationDesiredData stabDesired = {};
487 stabDesired.Pitch =
bound_sym(stabDesired.Pitch,
488 stabSet.MaxLevelAngle[STABILIZATIONSETTINGS_MAXLEVELANGLE_PITCH]);
489 stabDesired.Roll =
bound_sym(stabDesired.Roll,
490 stabSet.MaxLevelAngle[STABILIZATIONSETTINGS_MAXLEVELANGLE_ROLL]);
492 stabDesired.StabilizationMode[STABILIZATIONDESIRED_STABILIZATIONMODE_ROLL] = STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE;
493 stabDesired.StabilizationMode[STABILIZATIONDESIRED_STABILIZATIONMODE_PITCH] = STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE;
495 stabDesired.ThrustMode = STABILIZATIONDESIRED_THRUSTMODE_DIRECT;
496 stabDesired.ReprojectionMode = STABILIZATIONDESIRED_REPROJECTIONMODE_NONE;
500 stabDesired.Thrust = (system_settings.AirframeType == SYSTEMSETTINGS_AIRFRAMETYPE_HELICP) ? manual_control_command.Collective : manual_control_command.Throttle;
510 case VTOLPATHFOLLOWERSETTINGS_YAWMODE_RATE:
512 stabDesired.Yaw = stabSet.ManualRate[STABILIZATIONSETTINGS_MANUALRATE_YAW] * manual_control_command.Yaw;
513 stabDesired.StabilizationMode[STABILIZATIONDESIRED_STABILIZATIONMODE_YAW] = STABILIZATIONDESIRED_STABILIZATIONMODE_RATE;
515 case VTOLPATHFOLLOWERSETTINGS_YAWMODE_AXISLOCK:
516 stabDesired.Yaw = stabSet.ManualRate[STABILIZATIONSETTINGS_MANUALRATE_YAW] * manual_control_command.Yaw;
517 stabDesired.StabilizationMode[STABILIZATIONDESIRED_STABILIZATIONMODE_YAW] = STABILIZATIONDESIRED_STABILIZATIONMODE_AXISLOCK;
519 case VTOLPATHFOLLOWERSETTINGS_YAWMODE_PATH:
522 VelocityDesiredData velocityDesired;
523 VelocityDesiredGet(&velocityDesired);
524 float total_vel2 = velocityDesired.East*velocityDesired.East + velocityDesired.North*velocityDesired.North;
525 float path_direction = atan2f(velocityDesired.East, velocityDesired.North) * RAD2DEG;
526 if (total_vel2 > 1) {
527 stabDesired.Yaw = path_direction;
528 stabDesired.StabilizationMode[STABILIZATIONDESIRED_STABILIZATIONMODE_YAW] = STABILIZATIONDESIRED_STABILIZATIONMODE_ATTITUDE;
531 stabDesired.StabilizationMode[STABILIZATIONDESIRED_STABILIZATIONMODE_YAW] = STABILIZATIONDESIRED_STABILIZATIONMODE_RATE;
535 case VTOLPATHFOLLOWERSETTINGS_YAWMODE_POI:
536 stabDesired.StabilizationMode[STABILIZATIONDESIRED_STABILIZATIONMODE_YAW] = STABILIZATIONDESIRED_STABILIZATIONMODE_POI;
540 StabilizationDesiredSet(&stabDesired);
546 if (input > threshold) {
548 }
else if (input < -threshold) {
554 input /= (1 - threshold);
559 }
else if (input < -1.0
f) {
563 return expo3(input, expoPercent);
578 LoiterCommandData
cmd;
579 LoiterCommandGet(&cmd);
582 float commands_rp[2] = {
587 const float CMD_THRESHOLD = 0.2f;
604 static float historic_mag = 0.0f;
613 if (deadband_mag > historic_mag) {
614 historic_mag = deadband_mag;
619 if ((historic_mag < 0.001
f) && (fabsf(down_cmd) < 0.001
f)) {
620 att_adj[0] = 0; att_adj[1] = 0;
626 if (command_mag >= 0.001
f) {
627 commands_rp[0] /= command_mag;
628 commands_rp[1] /= command_mag;
631 commands_rp[0] = 0.0f;
632 commands_rp[1] = -1.0f;
636 PositionActualData positionActual;
637 PositionActualGet(&positionActual);
639 float cur_pos_ned[3] = { positionActual.North,
640 positionActual.East, positionActual.Down };
642 float total_poserr_ned[3];
645 if (deadband_mag >= 0.001
f) {
647 AttitudeActualYawGet(&yaw);
649 float commands_ne[2];
654 VelocityActualData velocityActual;
655 VelocityActualGet(&velocityActual);
666 float parallel_sign =
667 velocityActual.North * commands_ne[0] +
668 velocityActual.East * commands_ne[1];
670 if (parallel_sign > 0) {
671 float parallel_mag = sqrtf(
672 powf(velocityActual.North * commands_ne[0], 2) +
673 powf(velocityActual.East * commands_ne[1], 2));
675 target_vel += deadband_mag * parallel_mag;
679 hold_pos[0] = cur_pos_ned[0] +
680 commands_ne[0] * target_vel *
682 hold_pos[1] = cur_pos_ned[1] +
683 commands_ne[1] * target_vel *
690 hold_pos[0] -= scaled_error_alpha * total_poserr_ned[0];
691 hold_pos[1] -= scaled_error_alpha * total_poserr_ned[1];
694 att_adj[0] = deadband_mag * commands_rp[0] *
696 att_adj[1] = deadband_mag * commands_rp[1] *
700 if (fabsf(down_cmd) >= 0.001f) {
704 hold_pos[2] = cur_pos_ned[2];
float cubic_deadband(float in, float w, float b, float m, float r)
static int32_t vtol_follower_control_accel(float dT)
static int32_t vtol_follower_control_impl(const float *hold_pos_ned, float alt_rate, bool update_status)
static PathDesiredData pathDesired
int32_t vtol_follower_control_attitude(float dT, const float *att_adj)
float vector3_distances(const float *actual, const float *desired, float *out, bool normalize)
VtolPathFollowerSettingsData vtol_guidanceSettings
int32_t vtol_follower_control_endpoint(const float *hold_pos_ned)
void vtol_follower_control_settings_updated()
float fractional_progress
static PathStatusData pathStatus
struct pid vtol_pids[VTOL_PID_NUM]
int32_t vtol_follower_control_land(const float *hold_pos_ned, bool *landed)
float interpolate_value(const float fraction, const float beginVal, const float endVal)
void pid_configure(struct pid *pid, float p, float i, float d, float iLim, float dT)
Path calculation library with common API.
void path_progress(const PathDesiredData *pathDesired, const float *cur_point, struct path_status *status)
Compute progress along path and deviation from it.
static float loiter_errordecayalpha
void vector2_clip(float *vels, float limit)
float bound_min_max(float val, float min, float max)
Bound input value between min and max.
Includes for the internal methods.
float bound_sym(float val, float range)
Bound input value within range (plus or minus)
bool vtol_follower_control_loiter(float dT, float *hold_pos, float *att_adj, float *alt_adj)
void cubic_deadband_setup(float w, float b, float *m, float *r)
Header for Coordinate conversions library in coordinate_conversions.c.
static float loiter_deadband(float input, float threshold, float expoPercent)
int32_t vtol_follower_control_path(const PathDesiredData *pathDesired, struct path_status *progress)
Includes PiOS and core architecture components.
float vectorn_magnitude(const float *v, int n)
float correction_direction[2]
static float loiter_brakealpha
float pid_apply_antiwindup(struct pid *pid, const float err, float min_bound, float max_bound, float aw_bound)
static float vtol_follower_control_altitude(float downCommand)
static ManualControlCommandData cmd
static AltitudeHoldSettingsData altitudeHoldSettings
float expo3(float x, int32_t g)
Approximation an exponential scale curve.
void vector2_rotate(const float *original, float *out, float angle)
int32_t vtol_follower_control_altrate(const float *hold_pos_ned, float alt_adj)