Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pid update #161

Merged
merged 7 commits into from
Nov 24, 2016
Merged
6 changes: 2 additions & 4 deletions src/modules/interface/pid.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,9 @@

typedef struct
{
float desired; //< set point
float desired; //< set point
float error; //< error
float prevError; //< previous error
float errorMax; //< maximum error
float integ; //< integral
float deriv; //< derivative
float kp; //< proportional gain
Expand All @@ -117,8 +116,7 @@ typedef struct
float outI; //< integral output (debugging)
float outD; //< derivative output (debugging)
float iLimit; //< integral limit
float iLimitLow; //< integral limit
bool iCapped; //< true to stop integration
float outputLimit; //< output limit
float dt; //< delta-time dt
lpf2pData dFilter; //< filter for D term
bool enableDFilter; //< filter for D term enable flag
Expand Down
45 changes: 42 additions & 3 deletions src/modules/src/attitude_pid_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "attitude_controller.h"
#include "pid.h"
#include "param.h"
#include "log.h"

#define ATTITUDE_LPF_CUTOFF_FREQ 15.0f
#define ATTITUDE_LPF_ENABLE false
Expand All @@ -55,9 +56,13 @@ PidObject pidRoll;
PidObject pidPitch;
PidObject pidYaw;

int16_t rollOutput;
int16_t pitchOutput;
int16_t yawOutput;
static int16_t rollOutput;
static int16_t pitchOutput;
static int16_t yawOutput;

static float rpRateLimit = 150.0f;
static float yawRateLimit = 150.0f;
static float rpyRateLimitOverhead = 1.1f;

static bool isInit;

Expand Down Expand Up @@ -89,6 +94,10 @@ void attitudeControllerInit(const float updateDt)
pidSetIntegralLimit(&pidPitch, PID_PITCH_INTEGRATION_LIMIT);
pidSetIntegralLimit(&pidYaw, PID_YAW_INTEGRATION_LIMIT);

pidRollRate.outputLimit = INT16_MAX;
pidPitchRate.outputLimit = INT16_MAX;
pidYawRate.outputLimit = INT16_MAX;

isInit = true;
}

Expand Down Expand Up @@ -116,6 +125,10 @@ void attitudeControllerCorrectAttitudePID(
float eulerRollDesired, float eulerPitchDesired, float eulerYawDesired,
float* rollRateDesired, float* pitchRateDesired, float* yawRateDesired)
{
pidRoll.outputLimit = rpRateLimit * rpyRateLimitOverhead;
pidPitch.outputLimit = rpRateLimit * rpyRateLimitOverhead;
pidYaw.outputLimit = yawRateLimit * rpyRateLimitOverhead;

pidSetDesired(&pidRoll, eulerRollDesired);
*rollRateDesired = pidUpdate(&pidRoll, eulerRollActual, true);

Expand Down Expand Up @@ -151,6 +164,30 @@ void attitudeControllerGetActuatorOutput(int16_t* roll, int16_t* pitch, int16_t*
*yaw = yawOutput;
}

LOG_GROUP_START(pid_attitude)
LOG_ADD(LOG_FLOAT, roll_outP, &pidRoll.outP)
LOG_ADD(LOG_FLOAT, roll_outI, &pidRoll.outI)
LOG_ADD(LOG_FLOAT, roll_outD, &pidRoll.outD)
LOG_ADD(LOG_FLOAT, pitch_outP, &pidPitch.outP)
LOG_ADD(LOG_FLOAT, pitch_outI, &pidPitch.outI)
LOG_ADD(LOG_FLOAT, pitch_outD, &pidPitch.outD)
LOG_ADD(LOG_FLOAT, yaw_outP, &pidYaw.outP)
LOG_ADD(LOG_FLOAT, yaw_outI, &pidYaw.outI)
LOG_ADD(LOG_FLOAT, yaw_outD, &pidYaw.outD)
LOG_GROUP_STOP(pid_attitude)

LOG_GROUP_START(pid_rate)
LOG_ADD(LOG_FLOAT, roll_outP, &pidRollRate.outP)
LOG_ADD(LOG_FLOAT, roll_outI, &pidRollRate.outI)
LOG_ADD(LOG_FLOAT, roll_outD, &pidRollRate.outD)
LOG_ADD(LOG_FLOAT, pitch_outP, &pidPitchRate.outP)
LOG_ADD(LOG_FLOAT, pitch_outI, &pidPitchRate.outI)
LOG_ADD(LOG_FLOAT, pitch_outD, &pidPitchRate.outD)
LOG_ADD(LOG_FLOAT, yaw_outP, &pidYawRate.outP)
LOG_ADD(LOG_FLOAT, yaw_outI, &pidYawRate.outI)
LOG_ADD(LOG_FLOAT, yaw_outD, &pidYawRate.outD)
LOG_GROUP_STOP(pid_rate)

PARAM_GROUP_START(pid_attitude)
PARAM_ADD(PARAM_FLOAT, roll_kp, &pidRoll.kp)
PARAM_ADD(PARAM_FLOAT, roll_ki, &pidRoll.ki)
Expand All @@ -164,6 +201,8 @@ PARAM_ADD(PARAM_FLOAT, yaw_kd, &pidYaw.kd)
PARAM_GROUP_STOP(pid_attitude)

PARAM_GROUP_START(pid_rate)
PARAM_ADD(PARAM_FLOAT, rpRateLimit, &rpRateLimit)
PARAM_ADD(PARAM_FLOAT, yawRateLimit, &yawRateLimit)
PARAM_ADD(PARAM_FLOAT, roll_kp, &pidRollRate.kp)
PARAM_ADD(PARAM_FLOAT, roll_ki, &pidRollRate.ki)
PARAM_ADD(PARAM_FLOAT, roll_kd, &pidRollRate.kd)
Expand Down
63 changes: 27 additions & 36 deletions src/modules/src/pid.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,17 @@ void pidInit(PidObject* pid, const float desired, const float kp,
const float samplingRate, const float cutoffFreq,
bool enableDFilter)
{
pid->error = 0;
pid->errorMax = 0.0f;
pid->prevError = 0;
pid->integ = 0;
pid->deriv = 0;
pid->desired = desired;
pid->kp = kp;
pid->ki = ki;
pid->kd = kd;
pid->iLimit = DEFAULT_PID_INTEGRATION_LIMIT;
pid->iLimitLow = -DEFAULT_PID_INTEGRATION_LIMIT;
pid->iCapped = false;
pid->dt = dt;
pid->error = 0;
pid->prevError = 0;
pid->integ = 0;
pid->deriv = 0;
pid->desired = desired;
pid->kp = kp;
pid->ki = ki;
pid->kd = kd;
pid->iLimit = DEFAULT_PID_INTEGRATION_LIMIT;
pid->outputLimit = DEFAULT_PID_INTEGRATION_LIMIT;
pid->dt = dt;
pid->enableDFilter = enableDFilter;
if (pid->enableDFilter)
{
Expand All @@ -56,28 +54,15 @@ void pidInit(PidObject* pid, const float desired, const float kp,

float pidUpdate(PidObject* pid, const float measured, const bool updateError)
{
float output;
float output = 0.0f;

if (updateError)
{
pid->error = pid->desired - measured;
if (pid->errorMax > FLT_MIN) {
float errorMaxScaled = pid->errorMax / pid->kp;
pid->error = constrain(pid->error, -errorMaxScaled, errorMaxScaled);
}
}

if (pid->iCapped == false) {
pid->integ += pid->error * pid->dt;
if (pid->integ > pid->iLimit)
{
pid->integ = pid->iLimit;
}
else if (pid->integ < pid->iLimitLow)
{
pid->integ = pid->iLimitLow;
}
}
pid->outP = pid->kp * pid->error;
output += pid->outP;

float deriv = (pid->error - pid->prevError) / pid->dt;
if (pid->enableDFilter)
Expand All @@ -86,12 +71,22 @@ float pidUpdate(PidObject* pid, const float measured, const bool updateError)
} else {
pid->deriv = deriv;
}
if (isnan(pid->deriv)) {
pid->deriv = 0;
}
pid->outD = pid->kd * pid->deriv;
output += pid->outD;

float i = pid->integ + pid->error * pid->dt;
// Check if integral is saturated
if (abs(i) <= pid->iLimit || abs(pid->ki * i + output) <= pid->outputLimit) {
pid->integ = i;
}

pid->outP = pid->kp * pid->error;
pid->outI = pid->ki * pid->integ;
pid->outD = pid->kd * pid->deriv;
output += pid->outI;

output = pid->outP + pid->outI + pid->outD;
output = constrain(output, -pid->outputLimit, pid->outputLimit);

pid->prevError = pid->error;

Expand All @@ -103,10 +98,6 @@ void pidSetIntegralLimit(PidObject* pid, const float limit) {
}


void pidSetIntegralLimitLow(PidObject* pid, const float limitLow) {
pid->iLimitLow = limitLow;
}

void pidReset(PidObject* pid)
{
pid->error = 0;
Expand Down
44 changes: 22 additions & 22 deletions src/modules/src/position_controller_pid.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,12 @@ struct this_s {

// Maximum roll/pitch angle permited
static float rpLimit = 20;
static float rpLimitOverhead = 1.10f;
// Velocity maximums
static float xyVelMax = 1.0f;
static float zVelMax = 1.0f;
static float velMaxOverhead = 1.10f;
static const float thrustScale = 1000.0f;

#define DT (float)(1.0f/POSITION_RATE)
#define POSITION_LPF_CUTOFF_FREQ 20.0f
Expand Down Expand Up @@ -96,8 +98,8 @@ static struct this_s this = {

.pidVZ = {
.init = {
.kp = 25,
.ki = 15,
.kp = 15,
.ki = 20,
.kd = 0,
},
.pid.dt = DT,
Expand Down Expand Up @@ -125,7 +127,7 @@ static struct this_s this = {
.init = {
.kp = 2.0f,
.ki = 0,
.kd = 0.01f,
.kd = 0,
},
.pid.dt = DT,
},
Expand All @@ -150,10 +152,6 @@ void positionControllerInit()
this.pidVY.pid.dt, POSITION_RATE, POSITION_LPF_CUTOFF_FREQ, POSITION_LPF_ENABLE);
pidInit(&this.pidVZ.pid, this.pidVZ.setpoint, this.pidVZ.init.kp, this.pidVZ.init.ki, this.pidVZ.init.kd,
this.pidVZ.pid.dt, POSITION_RATE, POSITION_LPF_CUTOFF_FREQ, POSITION_LPF_ENABLE);

this.pidX.pid.errorMax = xyVelMax * velMaxOverhead;
this.pidY.pid.errorMax = xyVelMax * velMaxOverhead;
this.pidZ.pid.errorMax = zVelMax * velMaxOverhead;
}

static float runPid(float input, struct pidAxis_s *axis, float setpoint, float dt) {
Expand All @@ -166,6 +164,12 @@ static float runPid(float input, struct pidAxis_s *axis, float setpoint, float d
void positionController(float* thrust, attitude_t *attitude, const state_t *state,
const setpoint_t *setpoint)
{
this.pidX.pid.outputLimit = xyVelMax * velMaxOverhead;
this.pidY.pid.outputLimit = xyVelMax * velMaxOverhead;
// The ROS landing detector will prematurely trip if
// this value is below 0.5
this.pidZ.pid.outputLimit = max(zVelMax, 0.5) * velMaxOverhead;

// X, Y
pidSetDesired(&this.pidVX.pid, runPid(state->position.x, &this.pidX, setpoint->position.x, DT));
pidSetDesired(&this.pidVY.pid, runPid(state->position.y, &this.pidY, setpoint->position.y, DT));
Expand All @@ -177,6 +181,12 @@ void positionController(float* thrust, attitude_t *attitude, const state_t *stat
void velocityController(float* thrust, attitude_t *attitude, const state_t *state,
const setpoint_t *setpoint)
{
this.pidVX.pid.outputLimit = rpLimit * rpLimitOverhead;
this.pidVY.pid.outputLimit = rpLimit * rpLimitOverhead;
// Set the output limit to the maximum thrust range
this.pidVZ.pid.outputLimit = (UINT16_MAX / 2 / thrustScale);
//this.pidVZ.pid.outputLimit = (this.thrustBase - this.thrustMin) / thrustScale;

// Roll and Pitch
float rollRaw = pidUpdate(&this.pidVX.pid, state->velocity.x, true);
float pitchRaw = pidUpdate(&this.pidVY.pid, state->velocity.y, true);
Expand All @@ -185,28 +195,16 @@ void velocityController(float* thrust, attitude_t *attitude, const state_t *stat
attitude->pitch = -(rollRaw * cosf(yawRad)) - (pitchRaw * sinf(yawRad));
attitude->roll = -(pitchRaw * cosf(yawRad)) + (rollRaw * sinf(yawRad));

// Check for roll/pitch limits and prevent I from accumulating when capped
if (abs(attitude->roll) > rpLimit || abs(attitude->pitch) > rpLimit) {
this.pidVX.pid.iCapped = true;
this.pidVY.pid.iCapped = true;
} else {
this.pidVX.pid.iCapped = false;
this.pidVY.pid.iCapped = false;
}

attitude->roll = constrain(attitude->roll, -rpLimit, rpLimit);
attitude->pitch = constrain(attitude->pitch, -rpLimit, rpLimit);

// Thrust
float thrustRaw = pidUpdate(&this.pidVZ.pid, state->velocity.z, true);
// Scale the thrust and add feed forward term
*thrust = thrustRaw*1000 + this.thrustBase;
// Check for minimum thrust, prevent I from accumulating when capped
*thrust = thrustRaw*thrustScale + this.thrustBase;
// Check for minimum thrust
if (*thrust < this.thrustMin) {
*thrust = this.thrustMin;
this.pidVZ.pid.iCapped = true;
} else {
this.pidVZ.pid.iCapped = false;
}
}

Expand Down Expand Up @@ -281,6 +279,8 @@ PARAM_ADD(PARAM_FLOAT, zKd, &this.pidZ.pid.kd)
PARAM_ADD(PARAM_UINT16, thrustBase, &this.thrustBase)
PARAM_ADD(PARAM_UINT16, thrustMin, &this.thrustMin)

PARAM_ADD(PARAM_FLOAT, rpLimit, &rpLimit)
PARAM_ADD(PARAM_FLOAT, rpLimit, &rpLimit)
PARAM_ADD(PARAM_FLOAT, xyVelMax, &xyVelMax)
PARAM_ADD(PARAM_FLOAT, zVelMax, &zVelMax)

PARAM_GROUP_STOP(posCtlPid)
3 changes: 3 additions & 0 deletions src/utils/interface/num.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
#undef abs
#define abs(a) ((a) > 0 ? (a) : (-1*(a)))

#undef isnan
#define isnan(n) ((n != n) ? 1 : 0)


uint16_t single2half(float number);
float half2single(uint16_t number);
Expand Down