00001 #include "quad_height/pid_height.h"
00002 #include <math.h>
00003 #include "mav_msgs/Height.h"
00004 #include <Eigen/Eigen>
00005 #include <Eigen/LU>
00006 #include <std_msgs/Float64.h>
00007
00008
00009
00010 #define _Ts 0.1
00011 #define _delta 6.74
00012
00013 bool initialized = false;
00014
00015
00016 double p_term, d_term, i_term;
00017 double ThrustMax = 23.2472;
00018 double ThrustMin = 6.5241;
00019 double ThrustCoefA = 0.102613151321317;
00020 double ThrustCoefB = 3.352893193381934;
00021 double i_error = 0;
00022 double U = 0;
00023
00025
00026
00027
00028
00029 typedef Eigen::Matrix<double, 4, 1> VecState;
00030 typedef Eigen::Matrix<double, 4, 4> MetState;
00031
00032 VecState xhat, B;
00033 MetState P, A, Q;
00034 Eigen::Matrix<double, 4, 1> K;
00035 Eigen::Matrix<double, 1, 4> C;
00036 double R, Meas, resid;
00037
00038
00039 void ZKalman_Init(){
00040 xhat << 0, 0, 0, _delta;
00041 P << 0,0,0,0,
00042 0,0,0,0,
00043 0,0,0,0,
00044 0,0,0,0;
00045 A << 1, _Ts, pow(_Ts,2)/2, 0 ,
00046 0, 1 , _Ts , 0 ,
00047 0, 0 , 0 , -1,
00048 0, 0 , 0 , 1 ;
00049 B << 0, 0, 1, 0;
00050 C << 1, 0, 0 , 0;
00051 Q << 0.1, 0 , 0 , 0 ,
00052 0 , 0.1, 0 , 0 ,
00053 0 , 0 , 0.1, 0 ,
00054 0 , 0 , 0 , 0.1;
00055 R = 0.1;
00056 initialized=true;
00057 U=0;
00058 }
00059
00060 double ZKalman_newZMeasurement(double z, double zdd){
00061 if(initialized){
00062
00063
00064 xhat = A * xhat + B *U;
00065 P = A * P * A.transpose() + Q;
00066
00067
00068 K = (P * C.transpose()) / (C * P * C.transpose() + R);
00069
00070 Meas = z;
00071 resid = Meas - C*xhat;
00072
00073 xhat = xhat + K*resid;
00074 P = (Eigen::MatrixXd::Identity(4, 4)-K*C)*P;
00075 return xhat(3);
00076 }
00077 return 0;
00078 }
00080
00081 int ThrustConversion(double AccZ, double Mass){
00082 int thrust = 0;
00083 if (AccZ<=ThrustMin){ thrust = 20;
00084 }else if (AccZ>=ThrustMax){ thrust = 210;
00085 }else{ thrust = round((AccZ*Mass-ThrustCoefB)/ThrustCoefA); }
00086
00087 if (thrust>210) thrust=210;
00088 return thrust;
00089 }
00090
00091 double PID_height(double desired_height, Height_str Height, double height_gain[5], double t, double Mass, double roll, double pitch, ros::Publisher AccZ_pub){
00092
00093 double p, d, i, i_max, i_min;
00094
00095 double error = desired_height - Height.current;
00096
00097 p = height_gain[P_GAIN];
00098 d = height_gain[D_GAIN];
00099 i = height_gain[I_GAIN];
00100 i_max = height_gain[I_MAX];
00101 i_min = height_gain[I_MIN];
00102
00103
00104 p_term = p * error;
00105
00106
00107 i_error = i_error + t * error;
00108
00109
00110 i_term = i * i_error;
00111
00112
00113 if (i_term > i_max){
00114 i_term = i_max;
00115 i_error=i_term/i;
00116 }
00117 else if (i_term < -i_min){
00118 i_term = -i_min;
00119 i_error=i_term/i;
00120 }
00121
00122
00123 ros::Duration t_d = Height.time_current-Height.time_last;
00124 double d_error = (Height.current - Height.last) / t_d.toSec();
00125
00126 if(abs(d_error)>3.0){
00127 d_error=(d_error/abs(d_error))*3.0;
00128 }
00129
00130 d_term = d * d_error;
00131
00132 double Accz =((p_term + i_term - d_term)+xhat(3));
00133
00134 U=Accz;
00135 int cmd = ThrustConversion (Accz, Mass);
00136
00137 std_msgs::Float64 az;
00138 az.data=Accz;
00139 AccZ_pub.publish(az);
00140
00141 return cmd;
00142 }