1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-01-29 14:52:12 +01:00

OP-1156 changed PID control loops to use generic pid library, readded unnecessary integral and derivative terms to vtolpathfollower

This commit is contained in:
Corvus Corax 2014-08-15 20:36:14 +02:00
parent b1675a2804
commit 915c24c8b6
3 changed files with 101 additions and 110 deletions

View File

@ -89,12 +89,13 @@
#define DEADBAND_LOW -0.10f
// Private types
struct Integrals {
float vel[3];
float course;
float speed;
float power;
float airspeed;
struct Globals {
struct pid PIDposH[2];
struct pid PIDposV;
struct pid PIDvel[3];
struct pid PIDcourse;
struct pid PIDspeed;
struct pid PIDpower;
float poiRadius;
float vtolEmergencyFallback;
bool vtolEmergencyFallbackSwitch;
@ -104,7 +105,7 @@ struct Integrals {
// Private variables
static DelayedCallbackInfo *pathFollowerCBInfo;
static uint32_t updatePeriod = PF_IDLE_UPDATE_RATE_MS;
static struct Integrals i;
static struct Globals global;
static PathStatusData pathStatus;
static PathDesiredData pathDesired;
static FixedWingPathFollowerSettingsData fixedWingPathFollowerSettings;
@ -116,7 +117,7 @@ static float indicatedAirspeedStateBias = 0.0f;
// Private functions
static void pathFollowerTask(void);
static void resetIntegrals();
static void resetGlobals();
static void SettingsUpdatedCb(UAVObjEvent *ev);
static uint8_t updateAutoPilotByFrameType();
static uint8_t updateAutoPilotFixedWing();
@ -126,7 +127,7 @@ static float updateCourseBearing();
static float updatePathBearing();
static float updatePOIBearing();
static void processPOI();
static void updatePathVelocity(float kFF, float kH, float kV, bool limited);
static void updatePathVelocity(float kFF, bool limited);
static uint8_t updateFixedDesiredAttitude();
static int8_t updateVtolDesiredAttitude(bool yaw_attitude, float yaw_direction);
static void updateFixedAttitude();
@ -174,7 +175,7 @@ int32_t PathFollowerInitialize()
StabilizationBankInitialize();
// reset integrals
resetIntegrals();
resetGlobals();
// Create object queue
pathFollowerCBInfo = PIOS_CALLBACKSCHEDULER_Create(&pathFollowerTask, CALLBACK_PRIORITY, CBTASK_PRIORITY, CALLBACKINFO_RUNNING_PATHFOLLOWER, STACK_SIZE_BYTES);
@ -198,7 +199,7 @@ static void pathFollowerTask(void)
FlightStatusGet(&flightStatus);
if (flightStatus.ControlChain.PathFollower != FLIGHTSTATUS_CONTROLCHAIN_TRUE) {
resetIntegrals();
resetGlobals();
AlarmsSet(SYSTEMALARMS_ALARM_GUIDANCE, SYSTEMALARMS_ALARM_UNINITIALISED);
PIOS_CALLBACKSCHEDULER_Schedule(pathFollowerCBInfo, PF_IDLE_UPDATE_RATE_MS, CALLBACK_UPDATEMODE_SOONER);
return;
@ -246,7 +247,19 @@ static void pathFollowerTask(void)
static void SettingsUpdatedCb(__attribute__((unused)) UAVObjEvent *ev)
{
FixedWingPathFollowerSettingsGet(&fixedWingPathFollowerSettings);
pid_configure(&global.PIDcourse, fixedWingPathFollowerSettings.CoursePI.Kp, fixedWingPathFollowerSettings.CoursePI.Ki, 0.0f, fixedWingPathFollowerSettings.CoursePI.ILimit);
pid_configure(&global.PIDspeed, fixedWingPathFollowerSettings.SpeedPI.Kp, fixedWingPathFollowerSettings.SpeedPI.Ki, 0.0f, fixedWingPathFollowerSettings.SpeedPI.ILimit);
pid_configure(&global.PIDpower, fixedWingPathFollowerSettings.PowerPI.Kp, fixedWingPathFollowerSettings.PowerPI.Ki, 0.0f, fixedWingPathFollowerSettings.PowerPI.ILimit);
VtolPathFollowerSettingsGet(&vtolPathFollowerSettings);
pid_configure(&global.PIDvel[0], vtolPathFollowerSettings.HorizontalVelPID.Kp, vtolPathFollowerSettings.HorizontalVelPID.Ki, vtolPathFollowerSettings.HorizontalVelPID.Kd, vtolPathFollowerSettings.HorizontalVelPID.ILimit);
pid_configure(&global.PIDvel[1], vtolPathFollowerSettings.HorizontalVelPID.Kp, vtolPathFollowerSettings.HorizontalVelPID.Ki, vtolPathFollowerSettings.HorizontalVelPID.Kd, vtolPathFollowerSettings.HorizontalVelPID.ILimit);
pid_configure(&global.PIDvel[2], vtolPathFollowerSettings.VerticalVelPID.Kp, vtolPathFollowerSettings.VerticalVelPID.Ki, vtolPathFollowerSettings.VerticalVelPID.Kd, vtolPathFollowerSettings.VerticalVelPID.ILimit);
pid_configure(&global.PIDvel[2], vtolPathFollowerSettings.VerticalVelPID.Kp, vtolPathFollowerSettings.VerticalVelPID.Ki, vtolPathFollowerSettings.VerticalVelPID.Kd, vtolPathFollowerSettings.VerticalVelPID.ILimit);
PathDesiredGet(&pathDesired);
}
@ -278,18 +291,20 @@ static void airspeedStateUpdatedCb(__attribute__((unused)) UAVObjEvent *ev)
/**
* reset integrals
*/
static void resetIntegrals()
static void resetGlobals()
{
i.vel[0] = 0.0f;
i.vel[1] = 0.0f;
i.vel[2] = 0.0f;
i.course = 0.0f;
i.speed = 0.0f;
i.power = 0.0f;
i.airspeed = 0.0f;
i.poiRadius = 0.0f;
i.vtolEmergencyFallback = 0;
i.vtolEmergencyFallbackSwitch = false;
pid_zero(&global.PIDposH[0]);
pid_zero(&global.PIDposH[1]);
pid_zero(&global.PIDposV);
pid_zero(&global.PIDvel[0]);
pid_zero(&global.PIDvel[1]);
pid_zero(&global.PIDvel[2]);
pid_zero(&global.PIDcourse);
pid_zero(&global.PIDspeed);
pid_zero(&global.PIDpower);
global.poiRadius = 0.0f;
global.vtolEmergencyFallback = 0;
global.vtolEmergencyFallbackSwitch = false;
}
static uint8_t updateAutoPilotByFrameType()
@ -330,7 +345,10 @@ static uint8_t updateAutoPilotByFrameType()
*/
static uint8_t updateAutoPilotFixedWing()
{
updatePathVelocity(fixedWingPathFollowerSettings.CourseFeedForward, fixedWingPathFollowerSettings.HorizontalPosP, fixedWingPathFollowerSettings.VerticalPosP, true);
pid_configure(&global.PIDposH[0], fixedWingPathFollowerSettings.HorizontalPosP, 0.0f, 0.0f, 0.0f);
pid_configure(&global.PIDposH[1], fixedWingPathFollowerSettings.HorizontalPosP, 0.0f, 0.0f, 0.0f);
pid_configure(&global.PIDposV, fixedWingPathFollowerSettings.VerticalPosP, 0.0f, 0.0f, 0.0f);
updatePathVelocity(fixedWingPathFollowerSettings.CourseFeedForward, true);
return updateFixedDesiredAttitude();
}
@ -341,13 +359,19 @@ static uint8_t updateAutoPilotFixedWing()
*/
static uint8_t updateAutoPilotVtol()
{
if (!i.vtolEmergencyFallbackSwitch) {
if (!global.vtolEmergencyFallbackSwitch) {
if (vtolPathFollowerSettings.FlyawayEmergencyFallback == VTOLPATHFOLLOWERSETTINGS_FLYAWAYEMERGENCYFALLBACK_ALWAYS) {
updatePathVelocity(vtolPathFollowerSettings.CourseFeedForward, vtolPathFollowerSettings.HorizontalPosP, vtolPathFollowerSettings.VerticalPosP, true);
pid_configure(&global.PIDposH[0], 1.0f, 0.0f, 0.0f, 0.0f);
pid_configure(&global.PIDposH[1], 1.0f, 0.0f, 0.0f, 0.0f);
pid_configure(&global.PIDposV, vtolPathFollowerSettings.VerticalPosPI.Kp, vtolPathFollowerSettings.HorizontalPosPI.Ki, 0.0f, vtolPathFollowerSettings.HorizontalPosPI.ILimit);
updatePathVelocity(vtolPathFollowerSettings.CourseFeedForward, true);
updateVtolDesiredAttitudeEmergencyFallback();
return 1;
} else {
updatePathVelocity(vtolPathFollowerSettings.CourseFeedForward, vtolPathFollowerSettings.HorizontalPosP, vtolPathFollowerSettings.VerticalPosP, false);
pid_configure(&global.PIDposH[0], vtolPathFollowerSettings.HorizontalPosPI.Kp, vtolPathFollowerSettings.HorizontalPosPI.Ki, 0.0f, vtolPathFollowerSettings.HorizontalPosPI.ILimit);
pid_configure(&global.PIDposH[1], vtolPathFollowerSettings.HorizontalPosPI.Kp, vtolPathFollowerSettings.HorizontalPosPI.Ki, 0.0f, vtolPathFollowerSettings.HorizontalPosPI.ILimit);
pid_configure(&global.PIDposV, vtolPathFollowerSettings.VerticalPosPI.Kp, vtolPathFollowerSettings.HorizontalPosPI.Ki, 0.0f, vtolPathFollowerSettings.HorizontalPosPI.ILimit);
updatePathVelocity(vtolPathFollowerSettings.CourseFeedForward, false);
uint8_t result = 1;
bool yaw_attitude = true;
float yaw = 0.0f;
@ -370,12 +394,15 @@ static uint8_t updateAutoPilotVtol()
}
result = updateVtolDesiredAttitude(yaw_attitude, yaw);
if (!result && (vtolPathFollowerSettings.FlyawayEmergencyFallback == VTOLPATHFOLLOWERSETTINGS_FLYAWAYEMERGENCYFALLBACK_ENABLED || vtolPathFollowerSettings.FlyawayEmergencyFallback == VTOLPATHFOLLOWERSETTINGS_FLYAWAYEMERGENCYFALLBACK_DEBUGTEST)) {
i.vtolEmergencyFallbackSwitch = true;
global.vtolEmergencyFallbackSwitch = true;
}
return result;
}
} else {
updatePathVelocity(vtolPathFollowerSettings.CourseFeedForward, vtolPathFollowerSettings.HorizontalPosP, vtolPathFollowerSettings.VerticalPosP, true);
pid_configure(&global.PIDposH[0], 1.0f, 0.0f, 0.0f, 0.0f);
pid_configure(&global.PIDposH[1], 1.0f, 0.0f, 0.0f, 0.0f);
pid_configure(&global.PIDposV, vtolPathFollowerSettings.VerticalPosPI.Kp, vtolPathFollowerSettings.HorizontalPosPI.Ki, 0.0f, vtolPathFollowerSettings.HorizontalPosPI.ILimit);
updatePathVelocity(vtolPathFollowerSettings.CourseFeedForward, true);
updateVtolDesiredAttitudeEmergencyFallback();
return 0;
}
@ -454,7 +481,7 @@ static float updatePOIBearing()
PositionStateData positionState;
PositionStateGet(&positionState);
float dT = updatePeriod / 1000.0f;
const float dT = updatePeriod / 1000.0f;
float dLoc[3];
float yaw = 0;
/*float elevation = 0;*/
@ -487,7 +514,7 @@ static float updatePOIBearing()
**/
static void processPOI()
{
float dT = updatePeriod / 1000.0f;
const float dT = updatePeriod / 1000.0f;
PositionStateData positionState;
@ -536,14 +563,14 @@ static void processPOI()
pathAngle = -(manualControlData.Roll - DEADBAND_LOW) * dT * 300.0f;
} else if (manualControlData.Roll >= DEADBAND_LOW && manualControlData.Roll <= DEADBAND_HIGH) {
// change radius only when not circling
i.poiRadius = distance + changeRadius;
global.poiRadius = distance + changeRadius;
}
// don't try to move any closer
if (i.poiRadius >= 3.0f || changeRadius > 0) {
if (global.poiRadius >= 3.0f || changeRadius > 0) {
if (fabsf(pathAngle) > 0.0f || fabsf(changeRadius) > 0.0f) {
pathDesired.End.North = poi.North + (i.poiRadius * cosf(DEG2RAD(pathAngle + yaw - 180.0f)));
pathDesired.End.East = poi.East + (i.poiRadius * sinf(DEG2RAD(pathAngle + yaw - 180.0f)));
pathDesired.End.North = poi.North + (global.poiRadius * cosf(DEG2RAD(pathAngle + yaw - 180.0f)));
pathDesired.End.East = poi.East + (global.poiRadius * sinf(DEG2RAD(pathAngle + yaw - 180.0f)));
pathDesired.StartingVelocity = 1.0f;
pathDesired.EndingVelocity = 0.0f;
pathDesired.Mode = PATHDESIRED_MODE_FLYENDPOINT;
@ -565,7 +592,7 @@ static void processPOI()
/**
* Compute desired velocity from the current position and path
*/
static void updatePathVelocity(float kFF, float kH, float kV, bool limited)
static void updatePathVelocity(float kFF, bool limited)
{
PositionStateData positionState;
@ -573,10 +600,12 @@ static void updatePathVelocity(float kFF, float kH, float kV, bool limited)
VelocityStateData velocityState;
VelocityStateGet(&velocityState);
const float dT = updatePeriod / 1000.0f;
// look ahead kFF seconds
float cur[3] = { positionState.North + (velocityState.North * kFF),
positionState.East + (velocityState.East * kFF),
positionState.Down + (velocityState.Down * kFF) };
float cur[3] = { positionState.North + (velocityState.North * kFF),
positionState.East + (velocityState.East * kFF),
positionState.Down + (velocityState.Down * kFF) };
struct path_status progress;
path_progress(&pathDesired, cur, &progress);
@ -606,10 +635,10 @@ static void updatePathVelocity(float kFF, float kH, float kV, bool limited)
;
} else {
// calculate correction
velocityDesired.North += progress.correction_vector[0] * kH;
velocityDesired.East += progress.correction_vector[1] * kH;
velocityDesired.North += pid_apply(&global.PIDposH[0], progress.correction_vector[0], dT);
velocityDesired.East += pid_apply(&global.PIDposH[1], progress.correction_vector[1], dT);
}
velocityDesired.Down += progress.correction_vector[2] * kV;
velocityDesired.Down += pid_apply(&global.PIDposV, progress.correction_vector[2], dT);
// update pathstatus
pathStatus.error = progress.error;
@ -750,15 +779,6 @@ static uint8_t updateFixedDesiredAttitude()
/**
* Compute desired thrust command
*/
// compute saturated integral error thrust response. Make integral leaky for better performance. Approximately 30s time constant.
if (fixedWingPathFollowerSettings.PowerPI.Ki > 0.0f) {
i.power = boundf(i.power + -descentspeedError * dT,
-fixedWingPathFollowerSettings.PowerPI.ILimit / fixedWingPathFollowerSettings.PowerPI.Ki,
fixedWingPathFollowerSettings.PowerPI.ILimit / fixedWingPathFollowerSettings.PowerPI.Ki
) * (1.0f - 1.0f / (1.0f + 30.0f / dT));
} else {
i.power = 0.0f;
}
// Compute the cross feed from vertical speed to pitch, with saturation
float speedErrorToPowerCommandComponent = boundf(
@ -768,13 +788,12 @@ static uint8_t updateFixedDesiredAttitude()
);
// Compute final thrust response
powerCommand = -descentspeedError * fixedWingPathFollowerSettings.PowerPI.Kp +
i.power * fixedWingPathFollowerSettings.PowerPI.Ki +
powerCommand = pid_apply(&global.PIDpower, -descentspeedError, dT) +
speedErrorToPowerCommandComponent;
// Output internal state to telemetry
fixedWingPathFollowerStatus.Error.Power = descentspeedError;
fixedWingPathFollowerStatus.ErrorInt.Power = i.power;
fixedWingPathFollowerStatus.ErrorInt.Power = global.PIDpower.iAccumulator;
fixedWingPathFollowerStatus.Command.Power = powerCommand;
// set thrust
@ -803,17 +822,9 @@ static uint8_t updateFixedDesiredAttitude()
result = 0;
}
/**
* Compute desired pitch command
*/
if (fixedWingPathFollowerSettings.SpeedPI.Ki > 0) {
// Integrate with saturation
i.airspeed = boundf(i.airspeed + airspeedError * dT,
-fixedWingPathFollowerSettings.SpeedPI.ILimit / fixedWingPathFollowerSettings.SpeedPI.Ki,
fixedWingPathFollowerSettings.SpeedPI.ILimit / fixedWingPathFollowerSettings.SpeedPI.Ki);
}
// Compute the cross feed from vertical speed to pitch, with saturation
float verticalSpeedToPitchCommandComponent = boundf(-descentspeedError * fixedWingPathFollowerSettings.VerticalToPitchCrossFeed.Kp,
-fixedWingPathFollowerSettings.VerticalToPitchCrossFeed.Max,
@ -821,12 +832,10 @@ static uint8_t updateFixedDesiredAttitude()
);
// Compute the pitch command as err*Kp + errInt*Ki + X_feed.
pitchCommand = -(airspeedError * fixedWingPathFollowerSettings.SpeedPI.Kp
+ i.airspeed * fixedWingPathFollowerSettings.SpeedPI.Ki
) + verticalSpeedToPitchCommandComponent;
pitchCommand = -pid_apply(&global.PIDspeed, airspeedError, dT) + verticalSpeedToPitchCommandComponent;
fixedWingPathFollowerStatus.Error.Speed = airspeedError;
fixedWingPathFollowerStatus.ErrorInt.Speed = i.airspeed;
fixedWingPathFollowerStatus.ErrorInt.Speed = global.PIDspeed.iAccumulator;
fixedWingPathFollowerStatus.Command.Speed = pitchCommand;
stabDesired.Pitch = boundf(fixedWingPathFollowerSettings.PitchLimit.Neutral + pitchCommand,
@ -869,14 +878,10 @@ static uint8_t updateFixedDesiredAttitude()
courseError -= 360.0f;
}
i.course = boundf(i.course + courseError * dT * fixedWingPathFollowerSettings.CoursePI.Ki,
-fixedWingPathFollowerSettings.CoursePI.ILimit,
fixedWingPathFollowerSettings.CoursePI.ILimit);
courseCommand = (courseError * fixedWingPathFollowerSettings.CoursePI.Kp +
i.course);
courseCommand = pid_apply(&global.PIDcourse, courseError, dT);
fixedWingPathFollowerStatus.Error.Course = courseError;
fixedWingPathFollowerStatus.ErrorInt.Course = i.course;
fixedWingPathFollowerStatus.ErrorInt.Course = global.PIDcourse.iAccumulator;
fixedWingPathFollowerStatus.Command.Course = courseCommand;
stabDesired.Roll = boundf(fixedWingPathFollowerSettings.RollLimit.Neutral +
@ -1013,7 +1018,7 @@ static bool correctCourse(float *C, float *V, float *F, float s)
*/
static int8_t updateVtolDesiredAttitude(bool yaw_attitude, float yaw_direction)
{
float dT = updatePeriod / 1000.0f;
const float dT = updatePeriod / 1000.0f;
uint8_t result = 1;
VelocityDesiredData velocityDesired;
@ -1056,28 +1061,17 @@ static int8_t updateVtolDesiredAttitude(bool yaw_attitude, float yaw_direction)
// Compute desired north command
northError = velocityDesired.North - velocityState.North;
i.vel[0] = boundf(i.vel[0] + northError * dT * vtolPathFollowerSettings.HorizontalVelPI.Ki,
-vtolPathFollowerSettings.HorizontalVelPI.ILimit,
vtolPathFollowerSettings.HorizontalVelPI.ILimit);
northCommand = (northError * vtolPathFollowerSettings.HorizontalVelPI.Kp + i.vel[0]
+ velocityDesired.North * vtolPathFollowerSettings.VelocityFeedforward);
northCommand = pid_apply(&global.PIDvel[0], northError, dT) + velocityDesired.North * vtolPathFollowerSettings.VelocityFeedforward;
// Compute desired east command
eastError = velocityDesired.East - velocityState.East;
i.vel[1] = boundf(i.vel[1] + eastError * dT * vtolPathFollowerSettings.HorizontalVelPI.Ki,
-vtolPathFollowerSettings.HorizontalVelPI.ILimit,
vtolPathFollowerSettings.HorizontalVelPI.ILimit);
eastCommand = (eastError * vtolPathFollowerSettings.HorizontalVelPI.Kp + i.vel[1]
+ velocityDesired.East * vtolPathFollowerSettings.VelocityFeedforward);
eastError = velocityDesired.East - velocityState.East;
eastCommand = pid_apply(&global.PIDvel[1], eastError, dT) + velocityDesired.East * vtolPathFollowerSettings.VelocityFeedforward;
// Compute desired down command
downError = velocityDesired.Down - velocityState.Down;
downError = velocityDesired.Down - velocityState.Down;
// Must flip this sign
downError = -downError;
i.vel[2] = boundf(i.vel[2] + downError * dT * vtolPathFollowerSettings.VerticalVelPI.Ki,
-vtolPathFollowerSettings.VerticalVelPI.ILimit,
vtolPathFollowerSettings.VerticalVelPI.ILimit);
downCommand = (downError * vtolPathFollowerSettings.VerticalVelPI.Kp + i.vel[2]);
downError = -downError;
downCommand = pid_apply(&global.PIDvel[2], downError, dT);
stabDesired.Thrust = boundf(downCommand + vtolPathFollowerSettings.ThrustLimits.Neutral, vtolPathFollowerSettings.ThrustLimits.Min, vtolPathFollowerSettings.ThrustLimits.Max);
@ -1092,22 +1086,22 @@ static int8_t updateVtolDesiredAttitude(bool yaw_attitude, float yaw_direction)
if ( // emergency flyaway detection
( // integral already at its limit
vtolPathFollowerSettings.HorizontalVelPI.ILimit - fabsf(i.vel[0]) < 1e-6f ||
vtolPathFollowerSettings.HorizontalVelPI.ILimit - fabsf(i.vel[1]) < 1e-6f
vtolPathFollowerSettings.HorizontalVelPID.ILimit - fabsf(global.PIDvel[0].iAccumulator) < 1e-6f ||
vtolPathFollowerSettings.HorizontalVelPID.ILimit - fabsf(global.PIDvel[1].iAccumulator) < 1e-6f
) &&
// angle between desired and actual velocity >90 degrees (by dot product)
(velocityDesired.North * velocityState.North + velocityDesired.East * velocityState.East < 0.0f) &&
// quad is moving at significant speed (during flyaway it would keep speeding up)
squaref(velocityState.North) + squaref(velocityState.East) > 1.0f
) {
i.vtolEmergencyFallback += dT;
if (i.vtolEmergencyFallback >= vtolPathFollowerSettings.FlyawayEmergencyFallbackTriggerTime) {
global.vtolEmergencyFallback += dT;
if (global.vtolEmergencyFallback >= vtolPathFollowerSettings.FlyawayEmergencyFallbackTriggerTime) {
// after emergency timeout, trigger alarm - everything else is handled by callers
// (switch to emergency algorithm, switch to emergency waypoint in pathplanner, alarms, ...)
result = 0;
}
} else {
i.vtolEmergencyFallback = 0.0f;
global.vtolEmergencyFallback = 0.0f;
}
// Project the north and east command signals into the pitch and roll based on yaw. For this to behave well the
@ -1146,7 +1140,7 @@ static int8_t updateVtolDesiredAttitude(bool yaw_attitude, float yaw_direction)
*/
static void updateVtolDesiredAttitudeEmergencyFallback()
{
float dT = updatePeriod / 1000.0f;
const float dT = updatePeriod / 1000.0f;
VelocityDesiredData velocityDesired;
VelocityStateData velocityState;
@ -1182,10 +1176,7 @@ static void updateVtolDesiredAttitudeEmergencyFallback()
downError = velocityDesired.Down - velocityState.Down;
// Must flip this sign
downError = -downError;
i.vel[2] = boundf(i.vel[2] + downError * dT * vtolPathFollowerSettings.VerticalVelPI.Ki,
-vtolPathFollowerSettings.VerticalVelPI.ILimit,
vtolPathFollowerSettings.VerticalVelPI.ILimit);
downCommand = (downError * vtolPathFollowerSettings.VerticalVelPI.Kp + i.vel[2]);
downCommand = pid_apply(&global.PIDvel[2], downError, dT);
stabDesired.Thrust = boundf(downCommand + vtolPathFollowerSettings.ThrustLimits.Neutral, vtolPathFollowerSettings.ThrustLimits.Min, vtolPathFollowerSettings.ThrustLimits.Max);

View File

@ -15,9 +15,9 @@
<field name="ReverseCourseOverlap" units="deg" type="float" elements="1" defaultvalue="20.0"/>
<!-- how big the overlapping area behind the plane is, where, if the desired course lies behind, the current bank angle will determine if the plane goes left or right -->
<field name="HorizontalPosP" units="(m/s)/m" type="float" elements="1" defaultvalue="0.05"/>
<field name="HorizontalPosP" units="(m/s)/m" type="float" elements="1" defaultvalue="0.2"/>
<!-- proportional coefficient for correction vector in path vector field to get back on course - reduce for fast planes to prevent course oscillations -->
<field name="VerticalPosP" units="(m/s)/m" type="float" elements="1" defaultvalue="0.2"/>
<field name="VerticalPosP" units="(m/s)/m" type="float" elements="1" defaultvalue="0.4"/>
<!-- proportional coefficient for desired vertical speed in relation to altitude displacement-->
<!-- these coefficients control actual control outputs -->
@ -38,7 +38,7 @@
in relation to vertical speed error (absolute but including crossfeed) -->
<!-- output limits -->
<field name="RollLimit" units="deg" type="float" elements="3" elementnames="Min,Neutral,Max" defaultvalue="-35,0,35" />
<field name="RollLimit" units="deg" type="float" elements="3" elementnames="Min,Neutral,Max" defaultvalue="-45,0,45" />
<!-- maximum allowed bank angles in navigates flight -->
<field name="PitchLimit" units="deg" type="float" elements="3" elementnames="Min,Neutral,Max" defaultvalue="-10,5,20" />
<!-- maximum allowed pitch angles and setpoint for neutral pitch -->
@ -46,7 +46,7 @@
<!-- minimum and maximum allowed thrust and setpoint for cruise speed -->
<field name="Safetymargins" units="" type="float"
elementnames="Wind, Stallspeed, Lowspeed, Highspeed, Overspeed, Lowpower, Highpower, Pitchcontrol"
defaultvalue="90, 1.0, 0.5, 1.5, 1.0, 1, 1, 1" />
defaultvalue="90, 1.0, 0.5, 1.5, 1.0, 1, 0, 1" />
<!-- Wind: degrees of crabbing allowed
Speeds: percentage (1.0=100%) of the limit to be over/onder
Power & Control: flag to turn on/off 0.0 =off 1.0 = on -->

View File

@ -2,22 +2,22 @@
<object name="VtolPathFollowerSettings" singleinstance="true" settings="true" category="Control">
<description>Settings for the @ref VtolPathFollowerModule</description>
<field name="TreatCustomCraftAs" units="switch" type="enum" elements="1" options="FixedWing,VTOL" defaultvalue="FixedWing"/>
<field name="HorizontalVelMax" units="m/s" type="float" elements="1" defaultvalue="2.0"/>
<field name="HorizontalVelMax" units="m/s" type="float" elements="1" defaultvalue="5.0"/>
<field name="VerticalVelMax" units="m/s" type="float" elements="1" defaultvalue="1.0"/>
<field name="CourseFeedForward" units="s" type="float" elements="1" defaultvalue="1.0"/>
<field name="HorizontalPosP" units="(m/s)/m" type="float" elements="1" defaultvalue="0.25"/>
<field name="VerticalPosP" units="" type="float" elements="1" defaultvalue="0.4"/>
<field name="HorizontalVelPI" units="deg/(m/s)" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="8.0, 0.5, 10"/>
<field name="VerticalVelPI" units="" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="0.1, 0.01, 1.0"/>
<field name="HorizontalPosPI" units="(m/s)/m" type="float" elementnames="Kp,Ki,ILimit" defaultvalue="0.25,0.0,0.0"/>
<field name="VerticalPosPI" units="" type="float" elements="1" elementnames="Kp,Ki,Ilimit" defaultvalue="0.4,0.0,0.0"/>
<field name="HorizontalVelPID" units="deg/(m/s)" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="8.0, 0.5, 0.0, 15"/>
<field name="VerticalVelPID" units="" type="float" elementnames="Kp,Ki,Kd,ILimit" defaultvalue="0.1, 0.01, 0.0, 1.0"/>
<field name="ThrustLimits" units="" type="float" elementnames="Min,Neutral,Max" defaultvalue="0.2, 0.5, 0.9"/>
<field name="VelocityFeedforward" units="deg/(m/s)" type="float" elements="1" defaultvalue="2"/>
<field name="ThrustControl" units="" type="enum" elements="1" options="manual,auto" defaultvalue="manual"/>
<field name="YawControl" units="" type="enum" elements="1" options="manual,tailin,movementdirection,pathdirection,poi" defaultvalue="manual"/>
<field name="FlyawayEmergencyFallback" units="switch" type="enum" elements="1" options="disabled,enabled,always,debugtest" defaultvalue="enabled"/>
<field name="FlyawayEmergencyFallbackTriggerTime" units="s" type="float" elements="1" defaultvalue="10.0"/>
<field name="EmergencyFallbackAttitude" units="deg" type="float" elementnames="Roll,Pitch" defaultvalue="0,-10.0"/>
<field name="EmergencyFallbackAttitude" units="deg" type="float" elementnames="Roll,Pitch" defaultvalue="0,-20.0"/>
<field name="EmergencyFallbackYawRate" units="(deg/s)/deg" type="float" elementnames="kP,Max" defaultvalue="2.0, 30.0"/>
<field name="MaxRollPitch" units="deg" type="float" elements="1" defaultvalue="20"/>
<field name="MaxRollPitch" units="deg" type="float" elements="1" defaultvalue="25"/>
<field name="UpdatePeriod" units="ms" type="uint16" elements="1" defaultvalue="50"/>
<access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="true" updatemode="onchange" period="0"/>