DroneKalmanFilter.h
Go to the documentation of this file.
00001 #pragma once
00002 
00021 #ifndef __DRONEKALMANFILTER_H
00022 #define __DRONEKALMANFILTER_H
00023 
00024 #include <TooN/TooN.h>
00025 #include <deque>
00026 #include <iostream>
00027 #include <fstream>
00028 #include <ardrone_autonomy/Navdata.h>
00029 #include <geometry_msgs/Twist.h>
00030 #include <geometry_msgs/TwistStamped.h>
00031 #include <pthread.h>
00032 #include "../HelperFunctions.h"
00033 #include "tum_ardrone/filter_state.h"
00034 
00035 class EstimationNode;
00036 
00037 
00038 class ScaleStruct
00039 {
00040 public:
00041         TooN::Vector<3> ptam;
00042         TooN::Vector<3> imu;
00043         double ptamNorm;
00044         double imuNorm;
00045         double alphaSingleEstimate;
00046         double pp, ii, pi;
00047 
00048         inline double computeEstimator(double spp, double sii, double spi, double stdDevPTAM = 0.2, double stdDevIMU = 0.1)
00049         {
00050                 double sII = stdDevPTAM * stdDevPTAM * sii;
00051                 double sPP = stdDevIMU * stdDevIMU * spp;
00052                 double sPI = stdDevIMU * stdDevPTAM * spi;
00053 
00054                 double tmp = (sII-sPP)*(sII-sPP) + 4*sPI*sPI;
00055                 if(tmp <= 0) tmp = 1e-5;        // numeric issues
00056                 return 0.5*((sII-sPP)+sqrt(tmp)) / (stdDevPTAM * stdDevPTAM * spi);
00057 
00058         }
00059 
00060         inline ScaleStruct(TooN::Vector<3> ptamDist, TooN::Vector<3> imuDist)
00061         {
00062                 ptam = ptamDist;
00063                 imu = imuDist;
00064                 pp = ptam[0]*ptam[0] + ptam[1]*ptam[1] + ptam[2]*ptam[2];
00065                 ii = imu[0]*imu[0] + imu[1]*imu[1] + imu[2]*imu[2];
00066                 pi = imu[0]*ptam[0] + imu[1]*ptam[1] + imu[2]*ptam[2];
00067 
00068                 ptamNorm = sqrt(pp);
00069                 imuNorm = sqrt(ii);
00070 
00071                 alphaSingleEstimate = computeEstimator(pp,ii,pi);
00072         }
00073 
00074         inline bool operator < (const ScaleStruct& comp) const
00075         {
00076                 return alphaSingleEstimate < comp.alphaSingleEstimate;
00077         }
00078 };
00079 
00080 
00081 // KalmanFilter with two components (pose, speed)
00082 class PVFilter
00083 {
00084 public:
00085         TooN::Vector<2> state;
00086         TooN::Matrix<2,2> var;
00087         
00088 
00089         // constructors
00090         inline PVFilter(TooN::Vector<2> state, TooN::Matrix<2,2> var)
00091                 : state(state), var(var)
00092         {
00093         }
00094 
00095         inline PVFilter(double pose, double speed)
00096                 : state(TooN::makeVector(pose,speed)), var(TooN::Zeros)
00097         {
00098         }
00099 
00100         inline PVFilter(double pose)
00101                 : state(TooN::makeVector(pose,0)), var(TooN::Zeros)
00102         {
00103                 var(1,1) = 1e10;
00104         }
00105 
00106         inline PVFilter()
00107                 : state(TooN::makeVector(0,0)), var(TooN::Zeros)
00108         {
00109                 var(1,1) = var(0,0) = 1e10;
00110         }
00111 
00112         // observe
00113         inline void observePose(double obs, double obsVar)
00114         {
00115                 /* MATLAB:
00116                 H = [1 0];
00117                 K = (uncertainty * H') / ((H * uncertainty * H') + obsVar);
00118                 state = state + K * (obs - H*state);
00119                 var = (eye(2)-K*H) * var;
00120                 */
00121                 TooN::Vector<2> K = var[0] / (obsVar + var(0,0));       //K is first col = first row of var.
00122                 state = state + K * (obs - state[0]);
00123                 TooN::Matrix<2> tmp = TooN::Identity;
00124                 tmp(0,0) -= K[0]; 
00125                 tmp(1,0) -= K[1];
00126                 var = tmp * var;
00127 
00128         }
00129 
00130 
00131         inline void observeSpeed(double obs, double obsVar)
00132         {
00133                 /* MATLAB:
00134                 H = [0 1];
00135                 K = (uncertainty * H') / ((H * uncertainty * H') + obsVar);
00136                 state = state + K * (observation - H*state);
00137                 uncertainty = (eye(2)-K*H) * uncertainty;
00138                 */
00139                 TooN::Vector<2> K = var[1] / (obsVar + var(1,1));       //K is second col = second row of var.
00140                 state = state + K * (obs - state[1]);
00141                 TooN::Matrix<2> tmp = TooN::Identity;
00142                 tmp(0,1) -= K[0]; 
00143                 tmp(1,1) -= K[1];
00144                 var = tmp * var;
00145         }
00146 
00147 
00148         // predict
00149         // calculates prediction variance matrix based on gaussian acceleration as error.
00150         inline void predict(double ms, double accelerationVar, TooN::Vector<2> controlGains = TooN::makeVector(0,0), double coVarFac = 1, double speedVarFac = 1)
00151         {
00152                 /* MATLAB:
00153                 G = [1 ms/1000; 0 1];
00154                 E = [((ms/1000)^2)/2; ms/1000]; % assume normal distributed constant ACCELERATION.
00155                 state = G*state;
00156                 var = G * var * G' + accelerationVarPerS*(E*E');
00157                 */
00158 
00159                 ms /= 1000;
00160 
00161                 TooN::Matrix<2,2> G = TooN::Identity;
00162                 G(0,1) = ms;
00163 
00164                 state = G * state + controlGains;
00165                 var  = G * var * G.T();
00166                 var(0,0) += accelerationVar * 0.25 * ms*ms*ms*ms;
00167                 var(1,0) += coVarFac * accelerationVar * 0.5 * ms*ms*ms * 4;
00168                 var(0,1) += coVarFac * accelerationVar * 0.5 * ms*ms*ms * 4;
00169                 var(1,1) += speedVarFac * accelerationVar * 1 * ms*ms * 4 * 4;
00170         }
00171 
00172         // predict
00173         // calculates prediction using the given uncertainty matrix
00174         // vars is var(0) var(1) covar(0,1)
00175         inline void predict(double ms, TooN::Vector<3> vars, TooN::Vector<2> controlGains = TooN::makeVector(0,0))
00176         {
00177                 /* MATLAB:
00178                 G = [1 ms/1000; 0 1];
00179                 E = [((ms/1000)^2)/2; ms/1000]; % assume normal distributed constant ACCELERATION.
00180                 state = G*state;
00181                 var = G * var * G' + accelerationVarPerS*(E*E');
00182                 */
00183 
00184                 ms /= 1000;
00185 
00186                 TooN::Matrix<2,2> G = TooN::Identity;
00187                 G(0,1) = ms;
00188 
00189                 state = G * state + controlGains;
00190                 var  = G * var * G.T();
00191                 var(0,0) += vars[0];
00192                 var(1,0) += vars[2];
00193                 var(0,1) += vars[2];
00194                 var(1,1) += vars[1];
00195         }
00196 };
00197 
00198 
00199 // KalmanFilter with only one component (pose, is observed directly)
00200 class PFilter
00201 {
00202 public:
00203         double state;
00204         double var;
00205         
00206         inline PFilter() : state(0), var(1e10) {};
00207         inline PFilter(double initState) : state(initState), var(0) {};
00208 
00209         inline void predict(double ms, double speedVar, double controlGains = 0)
00210         {
00211                 /* MATLAB:
00212                 state = state;
00213                 var = var + speedVar*((ms/1000)^2);
00214                 */
00215                 state += controlGains;
00216                 var += speedVar * ms * ms / 1000000;
00217         }
00218 
00219         inline void observe(double obs, double obsVar)
00220         {
00221                 /* MATLAB:
00222                 obs_w = var / (var + obsVar);
00223                 state = state * (1-obs_w) + obs * obs_w;
00224                 var = var*obsVar / (var + obsVar);
00225                 */
00226                 double w = var / (var + obsVar);
00227                 state = (1-w) * state + w * obs;
00228                 var = var * obsVar / (var + obsVar);
00229         }
00230 };
00231 
00232 
00233 class DroneKalmanFilter
00234 {
00235 private:
00236         // filter
00237         PVFilter x;
00238         PVFilter y;
00239         PVFilter z;
00240         PFilter roll;
00241         PFilter pitch;
00242         PVFilter yaw;
00243 
00244 
00245         // relation parameters (ptam to imu scale / offset)
00246         double x_offset, y_offset, z_offset;
00247         double xy_scale, z_scale;
00248         double scale_from_z;
00249         double scale_from_xy;
00250         double roll_offset, pitch_offset, yaw_offset;
00251         bool offsets_xyz_initialized;
00252         bool scale_xyz_initialized;
00253 
00254         // intermediate values for re-estimation of relaton parameters
00255         double xyz_sum_IMUxIMU;
00256         double xyz_sum_PTAMxPTAM;
00257         double xyz_sum_PTAMxIMU;
00258         double rp_offset_framesContributed;
00259         std::vector<ScaleStruct>* scalePairs;
00260 
00261         // parameters used for height and yaw differentiation
00262         double last_yaw_IMU;
00263         double last_z_IMU;
00264         long last_yaw_droneTime;
00265         long last_z_droneTime;
00266         long last_z_packageID;
00267         
00268         // contains the last ptam-pose added (raw ptam-data).
00269         TooN::Vector<3> last_PTAM_pose;
00270 
00271         // contains the pose directly after the last ptam-fuse.
00272         TooN::Vector<3> last_fused_pose;
00273         bool lastPosesValid;
00274 
00275 
00276         // statistics parameters
00277         int numGoodIMUObservations;
00278         int numGoodPTAMObservations;
00279 
00280         // parameters used for adding / timing
00281         long lastIMU_XYZ_dronetime;
00282         long lastIMU_RPY_dronetime;
00283         long lastIMU_dronetime;
00284         int lastIMU_XYZ_ID;
00285         int lastIMU_RPY_ID;
00286         double lastPredictedRoll;
00287         double lastPredictedPitch;
00288         double initialScaleSet;
00289 
00290         // internal add functions
00291         void predictInternal(geometry_msgs::Twist activeControlInfo, int timeSpanMicros, bool useControlGains = true);
00292         void observeIMU_XYZ(const ardrone_autonomy::Navdata* nav);
00293         void observeIMU_RPY(const ardrone_autonomy::Navdata* nav);
00294         void observePTAM(TooN::Vector<6> pose);
00295 
00296 
00297         // internal sync functions. called on ptam-add.
00298         void sync_xyz(double x_global, double y_global, double z_global);
00299         void sync_rpy(double roll_global, double pitch_global, double yaw_global);
00300 
00301         // ms state of filter
00302         int predictedUpToTotal;
00303         long predictedUpToDroneTime;
00304 
00305         // logging
00306         double lastdYaw, lastdZ;
00307         double baselineZ_IMU;
00308         double baselineZ_Filter;
00309         double last_z_heightDiff;
00310         double baselineY_IMU;
00311         double baselineY_Filter;
00312         bool baselinesYValid;
00313         int timestampYawBaselineFrom;
00314         double lastVXGain;
00315         double lastVYGain;
00316 
00317 
00318 
00319         EstimationNode* node;
00320 public:
00321         DroneKalmanFilter(EstimationNode* node);
00322         ~DroneKalmanFilter(void);
00323         void release();
00324 
00325         static int delayRPY;    // assumed 0 (fastest data).
00326         static int delayXYZ;    // assumed 70 (gets here 70ms later than rpy)
00327         static int delayVideo;  // assumed 120 (gets here 120ms later than rpy)
00328         static int delayControl;        // assumed 120 (gets here 120ms later than rpy)
00329         
00330         static const int base_delayXYZ;
00331         static const int base_delayVideo;
00332         static const int base_delayControl;
00333 
00334         std::deque<ardrone_autonomy::Navdata>* navdataQueue;    // new navdata messages
00335         std::deque<geometry_msgs::TwistStamped>* velQueue;              // new velocity messages
00336         static pthread_mutex_t filter_CS;
00337 
00338 
00339         int predictdUpToTimestamp;
00340         int scalePairsIn, scalePairsOut;
00341 
00342 
00343 
00344         // resets everything to zero.
00345         void reset();
00346 
00347 
00348         // resets everything to do with PTAM to zero (call if tracking continues, but PTAM tracking is reset)
00349         void clearPTAM();
00350 
00351         // predicts up to a specified time in ms, using all available data.
00352         // if consume=false, does not delete anything from queues.
00353         void predictUpTo(int timestamp, bool consume = true, bool useControlGains = true);
00354         
00355         void setPing(unsigned int navPing, unsigned int vidPing);
00356 
00357         // gets current pose and variances (up to where predictUpTo has been called)
00358         TooN::Vector<6> getCurrentPose();
00359         tum_ardrone::filter_state getCurrentPoseSpeed();
00360         TooN::Vector<10> getCurrentPoseSpeedAsVec();
00361         TooN::Vector<10> getCurrentPoseSpeedVariances();
00362         TooN::Vector<6> getCurrentPoseVariances();
00363         TooN::Vector<6> getCurrentOffsets();
00364         TooN::Vector<3> getCurrentScales();
00365         TooN::Vector<3> getCurrentScalesForLog();
00366         float getScaleAccuracy();
00367         void setCurrentScales(TooN::Vector<3> scales);
00368 
00369         // adds a PTAM observation. automatically predicts up to timestamp.
00370         void updateScaleXYZ(TooN::Vector<3> ptamDiff, TooN::Vector<3> imuDiff, TooN::Vector<3> OrgPtamPose);
00371 
00372 
00373         // does not actually change the state of the filter.
00374         // makes a compy of it, flushes all queued navdata into it, then predicts up to timestamp.
00375         // relatively costly (!)
00376 
00377         // transforms a PTAM observation.
00378         // translates from front to center, scales and adds offsets.
00379         TooN::Vector<3> transformPTAMObservation(double x,double y,double z);
00380         TooN::Vector<3> transformPTAMObservation(double x,double y,double z, double yaw);
00381         TooN::Vector<6> transformPTAMObservation(TooN::Vector<6> obs);
00382         TooN::Vector<6> backTransformPTAMObservation(TooN::Vector<6> obs);
00383 
00384         inline int getNumGoodPTAMObservations() {return numGoodPTAMObservations;}
00385 
00386         // when scaling factors are updated, exacly one point stays the same.
00387         // if useScalingFixpoint, this point is the current PTAM pose, otherwise it is sclingFixpoint (which is a PTAM-coordinate(!))
00388         TooN::Vector<3> scalingFixpoint;        // in PTAM's system (!)
00389         bool useScalingFixpoint;
00390 
00391         //
00392         void flushScalePairs();
00393         
00394         // locking
00395         bool allSyncLocked;
00396         bool useControl;
00397         bool useNavdata;
00398         bool usePTAM;
00399 
00400         // motion model parameters
00401         float c1;
00402         float c2;
00403         float c3;
00404         float c4;
00405         float c5;
00406         float c6;
00407         float c7;
00408         float c8;
00409 
00410 
00411 
00412         bool handleCommand(std::string s);
00413 
00414         // new ROS interface functions
00415         void addPTAMObservation(TooN::Vector<6> trans, int time);
00416         void addFakePTAMObservation(int time);
00417         tum_ardrone::filter_state getPoseAt(ros::Time t, bool useControlGains = true);
00418         TooN::Vector<10> getPoseAtAsVec(int timestamp, bool useControlGains = true);
00419 
00420 };
00421 #endif /* __DRONEKALMANFILTER_H */


tum_ardrone
Author(s):
autogenerated on Sat Jun 8 2019 20:27:22