00001 #include "ros/ros.h"
00002 #include <sensor_msgs/Imu.h>
00003 #include <math.h>
00004 #include "tf/transform_datatypes.h"
00005 #include <Eigen/Eigen>
00006 #include <Eigen/LU>
00007 #include "px_comm/OpticalFlow.h"
00008 #include "std_msgs/Float64.h"
00009 #include "quad_PX4/KState.h"
00010
00011
00012 tfScalar yaw, pitch, roll;
00013 bool K_init = false, Az_init = false;
00014
00015 ros::Publisher Kstate_pub;
00016
00017 typedef struct{
00018 ros::Time time_last;
00019 double last;
00020 ros::Time time_current;
00021 double current;
00022 } Az_str;
00023
00024 Az_str Az;
00025
00026
00027 Eigen::Matrix<double, 6, 6> A, P;
00028 Eigen::Matrix<double, 6, 2> B, K;
00029 Eigen::Matrix<double, 6, 1> Xhat;
00030 Eigen::Matrix<double, 2, 1> U, Resid, OF;
00031 Eigen::Matrix<double, 4, 4> Q;
00032 Eigen::Matrix<double, 6, 4> W;
00033 Eigen::Matrix<double, 2, 6> C;
00034 Eigen::Matrix<double, 2, 2> R;
00035 Eigen::Matrix<double, 3, 3> Rroll, Rpitch, Ryaw, RotMat;
00036 Eigen::Matrix<double, 3, 1> VecG, VecDir, VecAz;
00037
00038 void XYKalman_Init(){
00039 Xhat << 0, 0, 0, 0, 0, 0;
00040 P << 0,0,0,0,0,0,
00041 0,0,0,0,0,0,
00042 0,0,0,0,0,0,
00043 0,0,0,0,0,0,
00044 0,0,0,0,0,0,
00045 0,0,0,0,0,0;
00046 A << 1,0,0,0,0,0,
00047 0,1,0,0,0,0,
00048 0,0,1,0,0,0,
00049 0,0,0,1,0,0,
00050 0,0,0,0,1,0,
00051 0,0,0,0,0,1;
00052 B << 0,0,
00053 0,0,
00054 0,0,
00055 0,0,
00056 0,0,
00057 0,0;
00058 W << 0,0,0,0,
00059 0,0,0,0,
00060 0,0,0,0,
00061 0,0,0,0,
00062 0,0,1,0,
00063 0,0,0,1;
00064 Q << 0.01, 0, 0, 0,
00065 0, 0.01, 0, 0,
00066 0, 0, 0.01, 0,
00067 0, 0, 0, 0.01;
00068 R << 0.1, 0,
00069 0, 0.1;
00070 VecG << 0,0,9.81;
00071 VecDir << 0,0,1;
00072 VecAz << 0,0,0;
00073 C << 0,0,1,0,0,0,
00074 0,0,0,1,0,0;
00075 K_init=true;
00076 }
00077
00078 double XYKalman_Predict(double AccZ, double _dt){
00079 if(K_init){
00080 A(0,2)=_dt;
00081 A(1,3)=_dt;
00082 A(2,4)=_dt;
00083 A(3,5)=_dt;
00084 A(0,4)=pow(_dt,2)/2;
00085 A(1,5)=pow(_dt,2)/2;
00086 B(0,0)=pow(_dt,2)/2;
00087 B(1,1)=pow(_dt,2)/2;
00088 B(2,0)=_dt;
00089 B(3,1)=_dt;
00090 W(0,0)=pow(_dt,2)/2;
00091 W(1,1)=pow(_dt,2)/2;
00092 W(2,0)=_dt;
00093 W(3,1)=_dt;
00094
00095 Rroll << 1, 0, 0,
00096 0, cos(roll), -sin(roll),
00097 0, sin(roll), cos(roll);
00098 Rpitch << cos(pitch), 0, sin(pitch),
00099 0, 1, 0,
00100 -sin(pitch),0, cos(pitch);
00101 Ryaw << cos(yaw), -sin(yaw), 0,
00102 sin(yaw), cos(yaw), 0,
00103 0, 0, 1;
00104 RotMat=Rroll*Rpitch*Ryaw;
00105 VecAz = AccZ*RotMat*VecDir-VecG;
00106 U(0,0)=VecAz(0,0);
00107 U(1,0)=VecAz(1,0);
00108
00109
00110
00111 Xhat=A*Xhat+B*U;
00112 P=A*P*A.transpose()+W*Q*W.transpose();
00113 return 1;
00114 }
00115 return 0;
00116 }
00117
00118 double XYKalman_Update(Eigen::Matrix<double, 2, 1> Z){
00119 if(K_init){
00120
00121
00122 K = (P * C.transpose()) * (C * P * C.transpose() + R).inverse();
00123
00124 Resid = Z - C*Xhat;
00125
00126 Xhat = Xhat + K*Resid;
00127 P = (Eigen::MatrixXd::Identity(6, 6)-K*C)*P;
00128 return 1;
00129 }
00130 return 0;
00131 }
00132
00133 void AccZCallback(std_msgs::Float64 const &msg){
00134 if(!Az_init){
00135 Az.time_last=ros::Time::now();
00136 Az.last=msg.data;
00137 Az.time_current=Az.time_last;
00138 Az.current=Az.last;
00139 Az_init = true;
00140 } else{
00141 Az.time_last=Az.time_current;
00142 Az.last=Az.current;
00143 Az.time_current=ros::Time::now();
00144 Az.current=msg.data;
00145 ros::Duration t = Az.time_current - Az.time_last;
00146 XYKalman_Predict(Az.current,t.toSec());
00147 }
00148 }
00149
00150 void imuCallback(sensor_msgs::Imu const &imu){
00151 tf::Quaternion orientation;
00152 tf::quaternionMsgToTF(imu.orientation, orientation);
00153 tf::Matrix3x3(orientation).getEulerYPR(yaw, pitch, roll);
00154 }
00155
00156 void PX4Callback(px_comm::OpticalFlow const &msg){
00157 OF(0,0)=msg.velocity_x;
00158 OF(1,0)=msg.velocity_y;
00159 XYKalman_Update(OF);
00160
00161 quad_PX4::KState Kstate;
00162 Kstate.header.stamp=ros::Time::now();
00163 Kstate.x=Xhat(0,0);
00164 Kstate.y=Xhat(1,0);
00165 Kstate.vx=Xhat(2,0);
00166 Kstate.vy=Xhat(3,0);
00167 Kstate.fx=Xhat(4,0);
00168 Kstate.fy=Xhat(5,0);
00169
00170 Kstate_pub.publish(Kstate);
00171 }
00172
00173 int main(int argc, char **argv){
00174
00175 ros::init(argc, argv, "FilterOF");
00176 ros::NodeHandle n;
00177
00178
00179 ros::Subscriber sub1 = n.subscribe("/px4flow/opt_flow", 1, PX4Callback);
00180 ros::Subscriber sub2 = n.subscribe("/imu/data", 10, &imuCallback);
00181 ros::Subscriber sub3 = n.subscribe("Applied_AccZ", 10, &AccZCallback);
00182
00183
00184 Kstate_pub = n.advertise<quad_PX4::KState>("HState", 10);
00185
00186 XYKalman_Init();
00187 ros::spin();
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 }