FilterOF.cpp
Go to the documentation of this file.
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 //Kalman Variables
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         // Predict
00110         // Propagate the state estimate and covariance matrix
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         //Update
00121         // Calculate the Kalman gain
00122         K = (P * C.transpose()) * (C * P * C.transpose() + R).inverse();
00123         // Calculate the measurement residual
00124         Resid = Z - C*Xhat;
00125         // Update the state and error covariance estimate
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     //Subscribing
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     //Publishing
00184     Kstate_pub = n.advertise<quad_PX4::KState>("HState", 10);
00185 
00186     XYKalman_Init();
00187     ros::spin();
00188     /*ros::Rate loop_rate(20);
00189 
00190     while (ros::ok()){
00191 
00192         quad_PX4::KState Kstate;
00193         Kstate.header.stamp=ros::Time::now();
00194         Kstate.x=Xhat(0,0);
00195         Kstate.y=Xhat(1,0);
00196         Kstate.vx=Xhat(2,0);
00197         Kstate.vy=Xhat(3,0);
00198         Kstate.fx=Xhat(4,0);
00199         Kstate.fy=Xhat(5,0);
00200 
00201         Kstate_pub.publish(Kstate);
00202 
00203         ros::spinOnce();
00204         loop_rate.sleep();
00205     }
00206     return 0;*/
00207 }


quad_PX4
Author(s): quad
autogenerated on Mon Jan 6 2014 11:48:37