pid.c
Go to the documentation of this file.
00001 #include "pid.h"
00002 
00003 //volatile int64_t g_latest_ctrl_time = 0;
00004 
00005 PID pid_x, pid_y, pid_z, pid_yaw, pid_vx, pid_vy, pid_vz;
00006 
00007 extern float g_cos_psi;
00008 extern float g_sin_psi;
00009 
00010 extern float g_accel_x;
00011 extern float g_accel_y;
00012 extern float g_accel_z;
00013 
00014 extern MAV_POSE_PKT          g_pose_pkt;
00015 extern MAV_CTRL_CMD          g_ctrl_cmd;
00016 extern MAV_FLIGHT_STATE_PKT  g_flight_state_pkt;
00017 extern MAV_CTRL_DEBUG_PKT    g_ctrl_debug_pkt;
00018 extern MAV_CTRL_INPUT_PKT    g_ctrl_input_pkt;
00019 extern MAV_CTRL_CFG_PKT      g_ctrl_cfg_pkt;
00020 extern MAV_DES_VEL_PKT       g_des_vel_pkt;
00021 
00022 extern MAV_DES_POSE_PKT      g_des_pose_pkt;
00023 extern PacketInfo *          g_des_pose_pkt_info;
00024 
00025 extern MAV_PID_CFG_PKT       g_pid_cfg_pkt;
00026 extern PacketInfo *          g_pid_cfg_pkt_info;
00027 
00028 //float g_vel_x_bf_last = 0;
00029 //float g_vel_y_bf_last = 0;
00030 //float g_vel_z_last = 0;
00031 void pidReset(void)
00032 {
00033   // Check if there's a new packet with desired pose, if not set des_pose to zero
00034   if (g_des_pose_pkt_info->updated == 0)
00035   {
00036     g_des_pose_pkt.x         = 0.0;
00037     g_des_pose_pkt.y         = 0.0;
00038     g_des_pose_pkt.z         = 0.0;
00039     g_des_vel_pkt.vx         = 0.0;
00040     g_des_vel_pkt.vy         = 0.0;
00041     g_des_vel_pkt.vz         = 0.0;
00042     g_des_vel_pkt.yaw_rate   = 0.0;
00043     g_des_pose_pkt.yaw       = 0.0;
00044   }
00045 
00046   //initialize PID variables
00047   pid_x.sum_error   = 0.0;
00048   pid_y.sum_error   = 0.0;
00049   pid_z.sum_error   = 0.0;
00050   pid_vx.sum_error  = 0.0;
00051   pid_vy.sum_error  = 0.0;
00052   pid_vz.sum_error  = 0.0;
00053   pid_yaw.sum_error = 0.0;
00054 }
00055 
00056 float pidCalc(PID * pid, float error, float d_term, float d_base, float dt)
00057 {
00058   // clamp error
00059   if      (error >  pid->max_error) error =  pid->max_error;
00060   else if (error < -pid->max_error) error = -pid->max_error;
00061 
00062   pid->sum_error += error * dt;
00063 
00064   // prevent integral windup through clamping
00065   if      (pid->sum_error >  pid->max_sum_error) pid->sum_error =  pid->max_sum_error;
00066   else if (pid->sum_error < -pid->max_sum_error) pid->sum_error = -pid->max_sum_error;
00067 
00068   float error_pow = pow((1.0/d_base),abs(error));
00069   return  (pid->bias + pid->kp * error + (pid->kd *error_pow)* d_term + pid->ki * pid->sum_error);
00070 }
00071 
00072 void pidParamUpdate()
00073 {
00074   // *************** X axis par *******************
00075 
00076   pid_x.kp            = g_pid_cfg_pkt.k_p_x;
00077   pid_x.ki            = g_pid_cfg_pkt.k_i_x;
00078   pid_x.kd            = g_pid_cfg_pkt.k_d_x;
00079   pid_x.d_base        = g_pid_cfg_pkt.d_base_x;
00080   pid_x.kd2           = g_pid_cfg_pkt.k_d2_x;
00081   pid_x.bias          = g_pid_cfg_pkt.bias_x;
00082   pid_x.max_error     = g_pid_cfg_pkt.max_err_x;
00083   pid_x.max_sum_error = g_pid_cfg_pkt.max_i_x;
00084 
00085   pid_vx.kp            = g_pid_cfg_pkt.k_p_vx;
00086   pid_vx.ki            = g_pid_cfg_pkt.k_i_vx;
00087   pid_vx.kd            = g_pid_cfg_pkt.k_d_vx;
00088   pid_vx.bias          = g_pid_cfg_pkt.bias_vx;
00089   pid_vx.max_error     = g_pid_cfg_pkt.max_err_vx;
00090   pid_vx.max_sum_error = g_pid_cfg_pkt.max_i_vx;
00091 
00092   // *************** Y axis par *******************
00093 
00094   pid_y.kp          = g_pid_cfg_pkt.k_p_y;
00095   pid_y.ki          = g_pid_cfg_pkt.k_i_y;
00096   pid_y.kd          = g_pid_cfg_pkt.k_d_y;
00097   pid_y.d_base      = g_pid_cfg_pkt.d_base_y;
00098   pid_y.kd2         = g_pid_cfg_pkt.k_d2_y;
00099   pid_y.bias        = g_pid_cfg_pkt.bias_y;
00100   pid_y.max_error     = g_pid_cfg_pkt.max_err_y;
00101   pid_y.max_sum_error = g_pid_cfg_pkt.max_i_y;
00102 
00103   pid_vy.kp         = g_pid_cfg_pkt.k_p_vy;
00104   pid_vy.ki         = g_pid_cfg_pkt.k_i_vy;
00105   pid_vy.kd         = g_pid_cfg_pkt.k_d_vy;
00106   pid_vy.bias       = g_pid_cfg_pkt.bias_vy;
00107   pid_vy.max_error     = g_pid_cfg_pkt.max_err_vy;
00108   pid_vy.max_sum_error = g_pid_cfg_pkt.max_i_vy;
00109 
00110   // *************** Z axis par *******************
00111 
00112   pid_z.kp             = g_pid_cfg_pkt.k_p_z;
00113   pid_z.ki             = g_pid_cfg_pkt.k_i_z;
00114   pid_z.kd             = g_pid_cfg_pkt.k_d_z;
00115   pid_z.kd2            = g_pid_cfg_pkt.k_d2_z;
00116   pid_z.bias           = g_pid_cfg_pkt.bias_z;
00117   pid_z.max_error      = g_pid_cfg_pkt.max_err_z;
00118   pid_z.max_sum_error  = g_pid_cfg_pkt.max_i_z;
00119 
00120 
00121   pid_vz.kp         = g_pid_cfg_pkt.k_p_vz;
00122   pid_vz.ki         = g_pid_cfg_pkt.k_i_vz;
00123   pid_vz.kd         = g_pid_cfg_pkt.k_d_vz;
00124   pid_vz.bias       = g_pid_cfg_pkt.bias_vz;
00125   pid_vz.max_error     = g_pid_cfg_pkt.max_err_vz;
00126   pid_vz.max_sum_error = g_pid_cfg_pkt.max_i_vz;
00127 
00128   // ****************** Yaw par *******************
00129 
00130   pid_yaw.kp             = g_pid_cfg_pkt.k_p_yaw;
00131   pid_yaw.ki             = g_pid_cfg_pkt.k_i_yaw;
00132   pid_yaw.kd             = g_pid_cfg_pkt.k_d_yaw;
00133   pid_yaw.bias           = g_pid_cfg_pkt.bias_yaw;
00134   pid_yaw.max_error      = g_pid_cfg_pkt.max_err_yaw;
00135   pid_yaw.max_sum_error  = g_pid_cfg_pkt.max_i_yaw;
00136 }
00137 
00138 void processCtrl(void)
00139 {
00140   float dt = 0.001;//(g_timestamp - g_latest_ctrl_time) * 0.000001; //dt in sec
00141   //g_latest_ctrl_time = g_timestamp;
00142   // **** Check if there's a new packet with PID parameters ***************
00143 
00144   if (g_pid_cfg_pkt_info->updated != 0)
00145   {
00146     g_pid_cfg_pkt_info->updated = 0;
00147     pidParamUpdate();
00148   }
00149 
00150   if (g_flight_state_pkt.state == MAV_STATE_FLYING)
00151   {
00152     float roll     = LLToSIAngleRoll (LL_1khz_attitude_data.angle_roll);
00153     float pitch    = LLToSIAnglePitch(LL_1khz_attitude_data.angle_pitch);
00154 
00155     float a_x = g_accel_x * cos(pitch) + g_accel_y * sin(pitch)*sin(roll) + g_accel_z * sin(pitch)*cos(roll);
00156     float a_y = g_accel_y * cos(roll)  - g_accel_z * sin(roll);
00157 
00158     float vel_x_bf  = g_pose_pkt.vx * g_cos_psi + g_pose_pkt.vy * g_sin_psi;
00159     float vel_y_bf  = g_pose_pkt.vy * g_cos_psi - g_pose_pkt.vx * g_sin_psi;
00160     float vel_z = g_pose_pkt.vz;
00161 
00162     //float dv_x = (vel_x_bf - g_vel_x_bf_last)/dt;
00163     //float dv_y = (vel_y_bf - g_vel_y_bf_last)/dt;
00164     //float dv_z = (g_pose_pkt.vz - g_vel_z_last )/dt;
00165 
00166     //g_vel_x_bf_last = vel_x_bf;
00167     //g_vel_y_bf_last = vel_y_bf;
00168     //g_vel_z_last = vel_z;
00169 
00170     g_ctrl_debug_pkt.vel_x_bf = vel_x_bf;
00171     g_ctrl_debug_pkt.vel_y_bf = vel_y_bf;
00172     g_ctrl_debug_pkt.ax_bf = a_x;
00173     g_ctrl_debug_pkt.ay_bf = a_y;
00174     //g_ctrl_debug_pkt.az    = dv_z;
00175 
00176     // *************************** X axis ctrl*********************************
00177 
00178     if (g_ctrl_cfg_pkt.ctrl_mode_pitch == MAV_CTRL_MODE_POSITION)
00179     {
00180       float des_x_bf   = (g_des_pose_pkt.x - g_pose_pkt.x) * g_cos_psi + (g_des_pose_pkt.y - g_pose_pkt.y) * g_sin_psi;
00181       //float vel_x_bf   = g_pose_pkt.vx * g_cos_psi + g_pose_pkt.vy * g_sin_psi;
00182       //float pitch_rate = LLToSIAngleRatePitch (LL_1khz_attitude_data.angvel_pitch);
00183 
00184       g_ctrl_cmd.cmd_pitch = pidCalc(&pid_x, des_x_bf, -vel_x_bf, pid_x.d_base, dt);
00185       g_ctrl_debug_pkt.pid_error_x_bf = des_x_bf;
00186     }
00187 
00188     else if (g_ctrl_cfg_pkt.ctrl_mode_pitch == MAV_CTRL_MODE_VELOCITY)
00189     {
00190       //float des_vx_bf   = (g_des_pose_pkt.vx - g_pose_pkt.vx) * g_cos_psi + (g_des_pose_pkt.vy - g_pose_pkt.vy) * g_sin_psi;
00191       //float des_vx     = (float) g_des_pose_pkt.vx;
00192       //float current_vx = (float) g_pose_pkt.vx;
00193       float vx_error = g_des_vel_pkt.vx - vel_x_bf;
00194       g_ctrl_debug_pkt.pid_error_vx_bf = vx_error;
00195 
00196       g_ctrl_cmd.cmd_pitch = pidCalc(&pid_vx, vx_error, -a_x, 1.0, dt);
00197     }
00198 
00199     else if (g_ctrl_cfg_pkt.ctrl_mode_pitch == MAV_CTRL_MODE_DIRECT)
00200       g_ctrl_cmd.cmd_pitch = g_ctrl_input_pkt.cmd_pitch;
00201 
00202     else if (g_ctrl_cfg_pkt.ctrl_mode_pitch == MAV_CTRL_MODE_DISABLED)
00203       g_ctrl_cmd.cmd_pitch = 0;
00204 
00205     // set debug info
00206     g_ctrl_debug_pkt.pid_x_i_term = pid_x.sum_error;
00207 
00208     // *************************** Y axis ctrl *********************************
00209 
00210     if (g_ctrl_cfg_pkt.ctrl_mode_roll == MAV_CTRL_MODE_POSITION)
00211     {
00212       float des_y_bf  = (g_des_pose_pkt.y - g_pose_pkt.y)* g_cos_psi - (g_des_pose_pkt.x - g_pose_pkt.x) * g_sin_psi;
00213       //float vel_y_bf  = g_pose_pkt.vy * g_cos_psi - g_pose_pkt.vx * g_sin_psi;
00214       //float roll_rate = LLToSIAngleRateRoll (LL_1khz_attitude_data.angvel_roll);
00215 
00216       g_ctrl_cmd.cmd_roll = - pidCalc(&pid_y, des_y_bf, -vel_y_bf, pid_y.d_base, dt); // positive roll gives you negative y
00217       g_ctrl_debug_pkt.pid_error_y_bf = des_y_bf;
00218     }
00219     else if (g_ctrl_cfg_pkt.ctrl_mode_roll == MAV_CTRL_MODE_VELOCITY)
00220     {
00221       //float des_vy     = (float) g_des_pose_pkt.vy;
00222       //float current_vy = (float) g_pose_pkt.vy;
00223 
00224       float vy_error = g_des_vel_pkt.vy - vel_y_bf;
00225       g_ctrl_debug_pkt.pid_error_vy_bf = vy_error;
00226       g_ctrl_cmd.cmd_roll = -pidCalc(&pid_vy, vy_error, -a_y, 1.0, dt);
00227     }
00228 
00229     else if (g_ctrl_cfg_pkt.ctrl_mode_roll == MAV_CTRL_MODE_DIRECT)
00230       g_ctrl_cmd.cmd_roll = g_ctrl_input_pkt.cmd_roll;
00231 
00232     else if (g_ctrl_cfg_pkt.ctrl_mode_roll == MAV_CTRL_MODE_DISABLED)
00233       g_ctrl_cmd.cmd_roll = 0;
00234 
00235     // set debug info
00236     g_ctrl_debug_pkt.pid_y_i_term = pid_y.sum_error;
00237 
00238     // **************************** Z axis ctrl *********************************
00239 
00240     if (g_ctrl_cfg_pkt.ctrl_mode_thrust == MAV_CTRL_MODE_DISABLED)
00241     {
00242       g_ctrl_cmd.cmd_thrust = 0;
00243     }
00244     else
00245     {
00246       Thrust new_cmd_thrust = g_ctrl_cmd.cmd_thrust;
00247 
00248       if (g_ctrl_cfg_pkt.ctrl_mode_thrust == MAV_CTRL_MODE_POSITION)
00249       {
00250         float des_z     = g_des_pose_pkt.z;
00251         float current_z = g_pose_pkt.z;
00252 
00253         new_cmd_thrust = pidCalc(&pid_z, des_z - current_z, -vel_z, 1.0, dt);// - pid_z.kd2 * g_accel_z;
00254       }
00255 
00256       else if (g_ctrl_cfg_pkt.ctrl_mode_thrust == MAV_CTRL_MODE_VELOCITY)
00257             {
00258               float des_vz     = g_des_vel_pkt.vz;
00259 
00260               new_cmd_thrust = pidCalc(&pid_vz, des_vz - vel_z, -g_accel_z, 1.0, dt);
00261             }
00262 
00263       else if (g_ctrl_cfg_pkt.ctrl_mode_thrust == MAV_CTRL_MODE_DIRECT)
00264       {
00265         new_cmd_thrust = g_ctrl_input_pkt.cmd_thrust;
00266       }
00267 
00268       // spike guard
00269       double delta_cmd_thrust = new_cmd_thrust - g_ctrl_cmd.cmd_thrust;
00270 
00271       if      (delta_cmd_thrust > g_ctrl_cfg_pkt.cmd_thrust_delta_limit)
00272         g_ctrl_cmd.cmd_thrust += g_ctrl_cfg_pkt.cmd_thrust_delta_limit;
00273       else if (delta_cmd_thrust < -g_ctrl_cfg_pkt.cmd_thrust_delta_limit)
00274         g_ctrl_cmd.cmd_thrust -= g_ctrl_cfg_pkt.cmd_thrust_delta_limit;
00275       else
00276         g_ctrl_cmd.cmd_thrust = new_cmd_thrust;
00277 
00278       // set debug info
00279       g_ctrl_debug_pkt.pid_z_i_term = pid_z.sum_error;
00280     }
00281 
00282     // ****************************** YAW ctrl *********************************
00283 
00284     if (g_ctrl_cfg_pkt.ctrl_mode_yaw_rate == MAV_CTRL_MODE_POSITION)
00285     {
00286       float des_yaw     = g_des_pose_pkt.yaw;
00287       float current_yaw = g_pose_pkt.yaw;
00288       float yaw_rate    = LLToSIAngleRateYaw(LL_1khz_attitude_data.angvel_yaw);
00289 
00290       float error =  des_yaw - current_yaw;
00291       normalizeSIAnglePi(&error);
00292 
00293       g_ctrl_cmd.cmd_yaw_rate = pidCalc(&pid_yaw, error, -yaw_rate, 1, dt);
00294     }
00295     if (g_ctrl_cfg_pkt.ctrl_mode_yaw_rate == MAV_CTRL_MODE_VELOCITY)
00296       g_ctrl_cmd.cmd_yaw_rate = g_des_vel_pkt.yaw_rate;
00297 
00298     else if (g_ctrl_cfg_pkt.ctrl_mode_yaw_rate == MAV_CTRL_MODE_DIRECT)
00299       g_ctrl_cmd.cmd_yaw_rate = g_ctrl_input_pkt.cmd_yaw_rate;
00300 
00301     else if (g_ctrl_cfg_pkt.ctrl_mode_yaw_rate == MAV_CTRL_MODE_DISABLED)
00302       g_ctrl_cmd.cmd_yaw_rate = 0;
00303 
00304     // set debug info
00305     g_ctrl_debug_pkt.pid_yaw_i_term = pid_yaw.sum_error;
00306 
00307   }
00308 
00309   // **************************** CLAMP ********************************
00310 
00311   // Clamp roll command
00312   if      (g_ctrl_cmd.cmd_roll >  g_ctrl_cfg_pkt.cmd_roll_limit)
00313     g_ctrl_cmd.cmd_roll =  g_ctrl_cfg_pkt.cmd_roll_limit;
00314   else if (g_ctrl_cmd.cmd_roll < -g_ctrl_cfg_pkt.cmd_roll_limit)
00315     g_ctrl_cmd.cmd_roll = -g_ctrl_cfg_pkt.cmd_roll_limit;
00316 
00317   // Clamp pitch command
00318   if      (g_ctrl_cmd.cmd_pitch >  g_ctrl_cfg_pkt.cmd_pitch_limit)
00319     g_ctrl_cmd.cmd_pitch =  g_ctrl_cfg_pkt.cmd_pitch_limit;
00320   else if (g_ctrl_cmd.cmd_pitch < -g_ctrl_cfg_pkt.cmd_pitch_limit)
00321     g_ctrl_cmd.cmd_pitch = -g_ctrl_cfg_pkt.cmd_pitch_limit;
00322 
00323   // Clamp yaw rate command
00324   if      (g_ctrl_cmd.cmd_yaw_rate > g_ctrl_cfg_pkt.cmd_yaw_rate_limit)
00325     g_ctrl_cmd.cmd_yaw_rate =  g_ctrl_cfg_pkt.cmd_yaw_rate_limit;
00326   else if (g_ctrl_cmd.cmd_yaw_rate < -g_ctrl_cfg_pkt.cmd_yaw_rate_limit)
00327     g_ctrl_cmd.cmd_yaw_rate = -g_ctrl_cfg_pkt.cmd_yaw_rate_limit;
00328 
00329   // Clamp thrust command
00330   if      (g_ctrl_cmd.cmd_thrust > g_ctrl_cfg_pkt.cmd_thrust_limit)
00331     g_ctrl_cmd.cmd_thrust = g_ctrl_cfg_pkt.cmd_thrust_limit;
00332   else if (g_ctrl_cmd.cmd_thrust < 0)
00333     g_ctrl_cmd.cmd_thrust = 0;
00334 }


ccny_asctec_firmware_2
Author(s): Ivan Dryanovski, Roberto G. Valenti
autogenerated on Tue Jan 7 2014 11:04:17