$search
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 }