00001
00023 #include "DroneKalmanFilter.h"
00024 #include "EstimationNode.h"
00025
00026
00027 const double varSpeedObservation_xy = 2*2;
00028 const double varPoseObservation_xy = 0.2*0.2;
00029 const double varAccelerationError_xy = 8*8;
00030
00031 const double varPoseObservation_z_PTAM = 0.3*0.3;
00032 const double varPoseObservation_z_IMU = 0.25*0.25;
00033 const double varPoseObservation_z_IMU_NO_PTAM = 0.1*0.1;
00034 const double varAccelerationError_z = 1*1;
00035
00036 const double varPoseObservation_rp_PTAM = 3*3;
00037 const double varPoseObservation_rp_IMU = 1*1;
00038 const double varSpeedError_rp = 360*360 * 16;
00039
00040 const double varSpeedObservation_yaw = 50*50;
00041 const double varPoseObservation_yaw = 3*3;
00042 const double varAccelerationError_yaw = 360*360;
00043
00044
00045
00046
00047 int DroneKalmanFilter::delayRPY = 0;
00048 int DroneKalmanFilter::delayXYZ = 40;
00049 int DroneKalmanFilter::delayVideo = 75;
00050 int DroneKalmanFilter::delayControl = 100;
00051
00052 const int DroneKalmanFilter::base_delayXYZ = 40;
00053 const int DroneKalmanFilter::base_delayVideo = 50;
00054 const int DroneKalmanFilter::base_delayControl = 50;
00055
00056
00057 const double max_z_speed = 2.5;
00058 const double scaleUpdate_min_xyDist = 0.5*0.5*0.5*0.5;
00059 const double scaleUpdate_min_zDist = 0.1*0.1;
00060
00061 using namespace std;
00062
00063
00064 double angleFromTo(double angle, double min, double sup)
00065 {
00066 while(angle < min) angle += 360;
00067 while(angle >= sup) angle -= 360;
00068 return angle;
00069 }
00070
00071
00072
00073
00074
00075 pthread_mutex_t DroneKalmanFilter::filter_CS = PTHREAD_MUTEX_INITIALIZER;
00076
00077 DroneKalmanFilter::DroneKalmanFilter(EstimationNode* n)
00078 {
00079 scalePairs = new std::vector<ScaleStruct>();
00080 navdataQueue = new std::deque<ardrone_autonomy::Navdata>();
00081 velQueue = new std::deque<geometry_msgs::TwistStamped>();
00082
00083 useScalingFixpoint = false;
00084
00085 this->node = n;
00086
00087 pthread_mutex_lock( &filter_CS );
00088 reset();
00089 pthread_mutex_unlock( &filter_CS );
00090
00091
00092
00093
00094
00095 c1 = 0.58;
00096 c2 = 17.8;
00097 c3 = 10;
00098 c4 = 35;
00099 c5 = 10;
00100 c6 = 25;
00101 c7 = 1.4;
00102 c8 = 1.0;
00103
00104 }
00105
00106
00107 DroneKalmanFilter::~DroneKalmanFilter(void)
00108 {
00109
00110 }
00111
00112 void DroneKalmanFilter::release()
00113 {
00114 delete scalePairs;
00115 delete navdataQueue;
00116 delete velQueue;
00117 }
00118
00119
00120 void DroneKalmanFilter::setPing(unsigned int navPing, unsigned int vidPing)
00121 {
00122
00123
00124 navPing += 20;
00125 vidPing += 40;
00126
00127 int new_delayXYZ = base_delayXYZ;
00128 int new_delayVideo = base_delayVideo + vidPing/(int)2 - navPing/(int)2;
00129 int new_delayControl = base_delayControl + navPing;
00130
00131 delayXYZ = std::min(500,std::max(40,std::min(new_delayVideo,new_delayXYZ)));
00132 delayVideo = std::min(500,std::max(40,new_delayVideo));
00133 delayControl = std::min(200,std::max(50,new_delayControl));
00134
00135 std::cout << "new delasXYZ: " << delayXYZ << ", delayVideo: " << delayVideo << ", delayControl: " << delayControl << std::endl;
00136 }
00137
00138 void DroneKalmanFilter::reset()
00139 {
00140
00141 x = y = z = yaw = PVFilter(0);
00142 roll = pitch = PFilter(0);
00143 lastIMU_XYZ_ID = lastIMU_RPY_ID = -1;
00144 predictedUpToDroneTime = 0;
00145 last_z_heightDiff = 0;
00146 scalePairsIn = scalePairsOut = 0;
00147
00148
00149 numGoodIMUObservations = 0;
00150
00151
00152 lastIMU_XYZ_dronetime = lastIMU_RPY_dronetime = 0;
00153 lastIMU_dronetime = 0;
00154
00155
00156 clearPTAM();
00157
00158
00159 navdataQueue->clear();
00160 velQueue->clear();
00161
00162 predictdUpToTimestamp = getMS(ros::Time::now());
00163 predictedUpToTotal = -1;
00164
00165 baselineZ_Filter = baselineZ_IMU = -999999;
00166 baselinesYValid = false;
00167
00168 node->publishCommand("u l EKF has been reset to zero.");
00169 }
00170
00171 void DroneKalmanFilter::clearPTAM()
00172 {
00173
00174 offsets_xyz_initialized = scale_xyz_initialized = false;
00175 xy_scale = z_scale = scale_from_xy = scale_from_z = 1;
00176 roll_offset = pitch_offset = yaw_offset = x_offset = y_offset = z_offset = 0;
00177
00178 xyz_sum_IMUxIMU = 0.1;
00179 xyz_sum_PTAMxPTAM = 0.1;
00180 xyz_sum_PTAMxIMU = 0.1;
00181 scalePairs->clear();
00182 scalePairsIn = 1;
00183 scalePairsOut = 0;
00184
00185 rp_offset_framesContributed = 0;
00186
00187
00188 numGoodPTAMObservations = 0;
00189
00190
00191 lastPosesValid = false;
00192 }
00193
00194
00195
00196 void DroneKalmanFilter::predictInternal(geometry_msgs::Twist activeControlInfo, int timeSpanMicros, bool useControlGains)
00197 {
00198 if(timeSpanMicros <= 0) return;
00199
00200 useControlGains = useControlGains && this->useControl;
00201
00202 bool controlValid = !(activeControlInfo.linear.z > 1.01 || activeControlInfo.linear.z < -1.01 ||
00203 activeControlInfo.linear.x > 1.01 || activeControlInfo.linear.x < -1.01 ||
00204 activeControlInfo.linear.y > 1.01 || activeControlInfo.linear.y < -1.01 ||
00205 activeControlInfo.angular.z > 1.01 || activeControlInfo.angular.z < -1.01);
00206
00207
00208 double tsMillis = timeSpanMicros / 1000.0;
00209 double tsSeconds = tsMillis / 1000.0;
00210
00211
00212
00213 float rollControlGain = tsSeconds*c3*(c4 * activeControlInfo.linear.y - roll.state);
00214 float pitchControlGain = tsSeconds*c3*(c4 * activeControlInfo.linear.x - pitch.state);
00215 float yawSpeedControlGain = tsSeconds*c5*(c6 * activeControlInfo.angular.z - yaw.state[1]);
00216
00217 double yawRad = yaw.state[0] * 3.14159268 / 180;
00218 double rollRad = roll.state * 3.14159268 / 180;
00219 double pitchRad = pitch.state * 3.14159268 / 180;
00220
00221 double vz_gain = tsSeconds * c7 * (c8*activeControlInfo.linear.z - z.state[1]) * fabs(cos(rollRad)*cos(pitchRad));
00222
00223 double accelX = (cos(yawRad) * tan(rollRad) * (9.8 + vz_gain) - sin(yawRad) * tan(pitchRad) * (9.8 + vz_gain));
00224 double accelY = (-sin(yawRad) * tan(rollRad) * (9.8 + vz_gain) - cos(yawRad) * tan(pitchRad) * (9.8 + vz_gain));
00225
00226 double vx_gain = tsSeconds * c1 * (c2*accelX);
00227 double vy_gain = tsSeconds * c1 * (c2*accelY);
00228
00229 lastVXGain = vx_gain;
00230 lastVYGain = vy_gain;
00231 lastPredictedRoll = roll.state;
00232 lastPredictedPitch = pitch.state;
00233
00234 if(!useControlGains || !controlValid)
00235 {
00236 vx_gain = vy_gain = vz_gain = 0;
00237 rollControlGain = pitchControlGain = yawSpeedControlGain = 0;
00238 }
00239
00240
00241 yaw.state[0] = angleFromTo(yaw.state[0],-180,180);
00242 roll.predict(tsMillis,varSpeedError_rp, rollControlGain);
00243 pitch.predict(tsMillis,varSpeedError_rp, pitchControlGain);
00244 yaw.predict(tsMillis,varAccelerationError_yaw,TooN::makeVector(tsSeconds*yawSpeedControlGain/2,yawSpeedControlGain),1,5*5);
00245 yaw.state[0] = angleFromTo(yaw.state[0],-180,180);
00246
00247
00248 x.predict(tsMillis,varAccelerationError_xy,TooN::makeVector(tsSeconds*vx_gain/2,vx_gain),0.0001);
00249 y.predict(tsMillis,varAccelerationError_xy,TooN::makeVector(tsSeconds*vy_gain/2,vy_gain),0.0001);
00250 z.predict(tsMillis,TooN::makeVector(tsSeconds*tsSeconds*tsSeconds*tsSeconds, 9*tsSeconds,tsSeconds*tsSeconds*tsSeconds*3),
00251 TooN::makeVector(tsSeconds*vz_gain/2,vz_gain));
00252 }
00253
00254
00255
00256 void DroneKalmanFilter::observeIMU_XYZ (const ardrone_autonomy::Navdata* nav)
00257 {
00258
00259
00260
00261 double yawRad = yaw.state[0] * 3.14159268 / 180;
00262 double vx_global = (sin(yawRad) * nav->vx + cos(yawRad) * nav->vy) / 1000.0;
00263 double vy_global = (cos(yawRad) * nav->vx - sin(yawRad) * nav->vy) / 1000.0;
00264
00265 if(vx_global > 10)
00266 cout << "err";
00267
00268
00269
00270
00271 double lastX = x.state[0];
00272 double lastY = y.state[0];
00273
00274 x.observeSpeed(vx_global,varSpeedObservation_xy);
00275 y.observeSpeed(vy_global,varSpeedObservation_xy);
00276
00277
00278 if(abs(lastX-x.state[0]) > 0.2 && lastX != 0)
00279 {
00280
00281 ROS_WARN("detected large x jump. removing. should not happen usually (only e.g. if no navdata for a long time, or agressive re-scaling)");
00282 x.state[0] = lastX;
00283 }
00284 if(abs(lastY-y.state[0]) > 0.2 && lastY != 0)
00285 {
00286 y.state[0] = lastY;
00287 ROS_WARN("detected large y jump. removing. should not happen usually (only e.g. if no navdata for a long time, or agressive re-scaling)");
00288 }
00289
00290
00291 double z_obs = (nav->altd * 0.001) / sqrt(1.0 + (tan(roll.state * 3.14159268 / 180)*tan(roll.state * 3.14159268 / 180)) \
00292 + (tan(pitch.state * 3.14159268 / 180)*tan(pitch.state * 3.14159268 / 180)) );
00293
00294 if (! std::isfinite(z_obs))
00295 z_obs = nav->altd * 0.001;
00296
00297
00298
00299 if(baselineZ_Filter < -100000)
00300 {
00301 baselineZ_IMU = z_obs;
00302 baselineZ_Filter = z.state[0];
00303 }
00304
00305 if(abs(z_obs - baselineZ_IMU) < 0.150)
00306 {
00307
00308
00309 if (nav->state <= 2 && fabs(z_obs - baselineZ_IMU) < zDriftThreshold) {
00310 baselineZ_IMU = z_obs;
00311 }
00312
00313 if (lastPosesValid) {
00314 z.observePose(baselineZ_Filter + z_obs - baselineZ_IMU,varPoseObservation_z_IMU);
00315
00316 } else {
00317 if (numGoodPTAMObservations == 0 || nav->state <= 2) {
00318 z.observePose(z_obs,varPoseObservation_z_IMU_NO_PTAM);
00319
00320 } else {
00321 z.observePose(baselineZ_Filter + z_obs - baselineZ_IMU,varPoseObservation_z_IMU_NO_PTAM);
00322
00323 }
00324
00325 }
00326
00327 if(lastIMU_XYZ_dronetime > 0)
00328 {
00329 double speed = (z_obs - baselineZ_IMU) / ((getMS(nav->header.stamp) - lastIMU_XYZ_dronetime) / 1000.0);
00330 if (std::isfinite(speed))
00331 z.observeSpeed(speed,varPoseObservation_z_IMU*10);
00332 }
00333
00334 }
00335
00336 baselineZ_IMU = z_obs;
00337 baselineZ_Filter = z.state[0];
00338 lastIMU_XYZ_dronetime = getMS(nav->header.stamp);
00339 last_z_packageID = nav->header.seq;
00340
00341 }
00342
00343
00344
00345 void DroneKalmanFilter::observeIMU_RPY(const ardrone_autonomy::Navdata* nav)
00346 {
00347 roll.observe(nav->rotX,varPoseObservation_rp_IMU);
00348 pitch.observe(nav->rotY,varPoseObservation_rp_IMU);
00349
00350
00351 if(!baselinesYValid)
00352 {
00353 baselineY_IMU = nav->rotZ - node->initialYaw;
00354 baselinesYValid = true;
00355 timestampYawBaselineFrom = getMS(nav->header.stamp);
00356 lastdYaw = 0;
00357 return;
00358 }
00359
00360 double observedYaw = nav->rotZ - node->initialYaw;
00361
00362 yaw.state[0] = angleFromTo(yaw.state[0],-180,180);
00363
00364 if(yaw.state[0] < -90) {
00365 observedYaw = angleFromTo(observedYaw,-360,0);
00366 baselineY_IMU = angleFromTo(baselineY_IMU,-360,0);
00367 } else if(yaw.state[0] > 90) {
00368 observedYaw = angleFromTo(observedYaw,0,360);
00369 baselineY_IMU = angleFromTo(baselineY_IMU,0,360);
00370 } else {
00371 observedYaw = angleFromTo(observedYaw,-180,180);
00372 baselineY_IMU = angleFromTo(baselineY_IMU,-180,180);
00373 }
00374
00375 double imuYawDiff = observedYaw - baselineY_IMU;
00376 double observedYawSpeed = imuYawDiff / ((getMS(nav->header.stamp) - timestampYawBaselineFrom) / 1000.0);
00377
00378
00379
00380 if (nav->state <= 2 && fabs(imuYawDiff) < yawDriftThreshold) {
00381 imuYawDiff = 0;
00382 observedYawSpeed = 0;
00383 }
00384
00385 baselineY_IMU = observedYaw;
00386 timestampYawBaselineFrom = getMS(nav->header.stamp);
00387
00388 if (fabs(observedYawSpeed) < 720) {
00389
00390 if(lastPosesValid)
00391 {
00392 yaw.observePose(yaw.state[0] + imuYawDiff,1*1);
00393 if (std::isfinite(observedYawSpeed))
00394 yaw.observeSpeed(observedYawSpeed,varSpeedObservation_yaw);
00395 }
00396 else
00397 {
00398 yaw.observePose(yaw.state[0] + imuYawDiff,0.5*0.5);
00399 if (std::isfinite(observedYawSpeed))
00400 yaw.observeSpeed(observedYawSpeed,varSpeedObservation_yaw/2);
00401
00402 }
00403 }
00404
00405 lastdYaw = observedYaw;
00406 yaw.state[0] = angleFromTo(yaw.state[0],-180,180);
00407 }
00408
00409
00410
00411 void DroneKalmanFilter::observePTAM(TooN::Vector<6> pose)
00412 {
00413
00414
00415
00416 if(!allSyncLocked)
00417 {
00418 sync_xyz(pose[0], pose[1], pose[2]);
00419 sync_rpy(pose[3], pose[4], pose[5]);
00420 }
00421
00422 last_PTAM_pose = TooN::makeVector(pose[0], pose[1], pose[2]);
00423
00424
00425 pose.slice<0,3>() = transformPTAMObservation(pose[0], pose[1], pose[2]);
00426
00427 if(offsets_xyz_initialized)
00428 {
00429 x.observePose(pose[0],varPoseObservation_xy);
00430 y.observePose(pose[1],varPoseObservation_xy);
00431 }
00432
00433
00434 if(offsets_xyz_initialized)
00435 {
00436 z.observePose(pose[2], varPoseObservation_z_PTAM);
00437 }
00438
00439
00440 if(rp_offset_framesContributed > 1)
00441 {
00442 roll.observe(pose[3]+roll_offset,varPoseObservation_rp_PTAM);
00443 pitch.observe(pose[4]+pitch_offset,varPoseObservation_rp_PTAM);
00444
00445 yaw.state[0] = angleFromTo(yaw.state[0],-180,180);
00446 double observedYaw = pose[5]+yaw_offset;
00447
00448 if(yaw.state[0] < -90)
00449 observedYaw = angleFromTo(observedYaw,-360,0);
00450 else if(yaw.state[0] > 90)
00451 observedYaw = angleFromTo(observedYaw,0,360);
00452 else
00453 observedYaw = angleFromTo(observedYaw,-180,180);
00454
00455 yaw.observePose(observedYaw,3*3);
00456 yaw.state[0] = angleFromTo(yaw.state[0],-180,180);
00457 }
00458
00459 last_fused_pose = TooN::makeVector(x.state[0], y.state[0], z.state[0]);
00460 lastPosesValid = true;
00461 }
00462
00463
00464 void DroneKalmanFilter::sync_rpy(double roll_global, double pitch_global, double yaw_global)
00465 {
00466 if(allSyncLocked) return;
00467
00468 if(rp_offset_framesContributed < 1)
00469 yaw_offset = yaw.state[0] - yaw_global;
00470
00471
00472 if(rp_offset_framesContributed < 100)
00473 {
00474 roll_offset = rp_offset_framesContributed * roll_offset + roll.state - roll_global;
00475 pitch_offset = rp_offset_framesContributed * pitch_offset + pitch.state - pitch_global;
00476 }
00477 rp_offset_framesContributed++;
00478
00479 roll_offset /= rp_offset_framesContributed;
00480 pitch_offset /= rp_offset_framesContributed;
00481 }
00482
00483 void DroneKalmanFilter::sync_xyz(double x_global, double y_global, double z_global)
00484 {
00485 if(allSyncLocked) return;
00486
00487 if(!offsets_xyz_initialized)
00488 {
00489 x_offset = x.state[0] - x_global*xy_scale;
00490 y_offset = y.state[0] - y_global*xy_scale;
00491 z_offset = z.state[0] - z_global*z_scale;
00492 offsets_xyz_initialized = true;
00493 }
00494
00495
00496 }
00497
00498
00499
00500 void DroneKalmanFilter::flushScalePairs()
00501 {
00502 std::ofstream* fle = new std::ofstream();
00503 fle->open ("scalePairs.txt");
00504 for(unsigned int i=0;i<scalePairs->size();i++)
00505 (*fle) << (*scalePairs)[i].ptam[0] << " " <<(*scalePairs)[i].ptam[1] << " " <<(*scalePairs)[i].ptam[2] << " " <<
00506 (*scalePairs)[i].imu[0] << " " << (*scalePairs)[i].imu[1] << " " << (*scalePairs)[i].imu[2] << std::endl;
00507 fle->flush();
00508 fle->close();
00509 delete fle;
00510 }
00511
00512 void DroneKalmanFilter::updateScaleXYZ(TooN::Vector<3> ptamDiff, TooN::Vector<3> imuDiff, TooN::Vector<3> OrgPtamPose)
00513 {
00514 if(allSyncLocked) return;
00515
00516 ScaleStruct s = ScaleStruct(ptamDiff, imuDiff);
00517
00518
00519 if(s.imuNorm < 0.05 || s.ptamNorm < 0.05) return;
00520
00521
00522
00523 (*scalePairs).push_back(s);
00524
00525 double xyz_scale_old = xy_scale;
00526
00527
00528
00529 std::sort((*scalePairs).begin(), (*scalePairs).end());
00530 double median = (*scalePairs)[((*scalePairs).size()+1)/2].alphaSingleEstimate;
00531
00532
00533
00534 if((*scalePairs).size() < 5)
00535 median = initialScaleSet;
00536
00537
00538
00539 double sumII = 0;
00540 double sumPP = 0;
00541 double sumPI = 0;
00542 double totSumII = 0;
00543 double totSumPP = 0;
00544 double totSumPI = 0;
00545
00546 double sumIIxy = 0;
00547 double sumPPxy = 0;
00548 double sumPIxy = 0;
00549 double sumIIz = 0;
00550 double sumPPz = 0;
00551 double sumPIz = 0;
00552
00553 int numIn = 0;
00554 int numOut = 0;
00555 for(unsigned int i=0;i<(*scalePairs).size();i++)
00556 {
00557 if((*scalePairs).size() < 5 || ((*scalePairs)[i].alphaSingleEstimate > median * 0.2 && (*scalePairs)[i].alphaSingleEstimate < median / 0.2))
00558 {
00559 sumII += (*scalePairs)[i].ii;
00560 sumPP += (*scalePairs)[i].pp;
00561 sumPI += (*scalePairs)[i].pi;
00562
00563 sumIIxy += (*scalePairs)[i].imu[0]*(*scalePairs)[i].imu[0] + (*scalePairs)[i].imu[1]*(*scalePairs)[i].imu[1];
00564 sumPPxy += (*scalePairs)[i].ptam[0]*(*scalePairs)[i].ptam[0] + (*scalePairs)[i].ptam[1]*(*scalePairs)[i].ptam[1];
00565 sumPIxy += (*scalePairs)[i].ptam[0]*(*scalePairs)[i].imu[0] + (*scalePairs)[i].ptam[1]*(*scalePairs)[i].imu[1];
00566
00567 sumIIz += (*scalePairs)[i].imu[2]*(*scalePairs)[i].imu[2];
00568 sumPPz += (*scalePairs)[i].ptam[2]*(*scalePairs)[i].ptam[2];
00569 sumPIz += (*scalePairs)[i].ptam[2]*(*scalePairs)[i].imu[2];
00570
00571 numIn++;
00572 }
00573 else
00574 {
00575 totSumII += (*scalePairs)[i].ii;
00576 totSumPP += (*scalePairs)[i].pp;
00577 totSumPI += (*scalePairs)[i].pi;
00578 numOut++;
00579 }
00580 }
00581 xyz_sum_IMUxIMU = sumII;
00582 xyz_sum_PTAMxPTAM = sumPP;
00583 xyz_sum_PTAMxIMU = sumPI;
00584
00585 double scale_Filtered = (*scalePairs)[0].computeEstimator(sumPP,sumII,sumPI,0.2,0.01);
00586 double scale_Unfiltered = (*scalePairs)[0].computeEstimator(sumPP+totSumPP,sumII+totSumII,sumPI+totSumPI,0.2,0.01);
00587 double scale_PTAMSmallVar = (*scalePairs)[0].computeEstimator(sumPP+totSumPP,sumII+totSumII,sumPI+totSumPI,0.00001,1);
00588 double scale_IMUSmallVar = (*scalePairs)[0].computeEstimator(sumPP+totSumPP,sumII+totSumII,sumPI+totSumPI,1,0.00001);
00589
00590
00591 double scale_Filtered_xy = (*scalePairs)[0].computeEstimator(sumPPxy,sumIIxy,sumPIxy,0.2,0.01);
00592 double scale_Filtered_z = (*scalePairs)[0].computeEstimator(sumPPz,sumIIz,sumPIz,0.2,0.01);
00593
00594
00595 scalePairsIn = numIn;
00596 scalePairsOut = numOut;
00597
00598 printf("scale: in: %i; out: %i, filt: %.3f; xyz: %.1f < %.1f < %.1f; xy: %.1f < %.1f < %.1f; z: %.1f < %.1f < %.1f;\n",
00599 numIn, numOut, scale_Filtered,
00600 scale_PTAMSmallVar, scale_Unfiltered, scale_IMUSmallVar,
00601 (*scalePairs)[0].computeEstimator(sumPPxy,sumIIxy,sumPIxy,0.00001,1),
00602 scale_Filtered_xy,
00603 (*scalePairs)[0].computeEstimator(sumPPxy,sumIIxy,sumPIxy,1,0.00001),
00604 (*scalePairs)[0].computeEstimator(sumPPz,sumIIz,sumPIz,0.00001,1),
00605 scale_Filtered_z,
00606 (*scalePairs)[0].computeEstimator(sumPPz,sumIIz,sumPIz,1,0.00001)
00607 );
00608
00609 printf("sumPP: %.3f sumII: %.3f sumPI: %.3f\n",
00610 sumPP, sumII, sumPI
00611 );
00612
00613 if(scale_Filtered > 0.1)
00614 z_scale = xy_scale = scale_Filtered;
00615 else
00616 ROS_WARN("calculated scale is too small %.3f, disallowing!",scale_Filtered);
00617
00618
00619 scale_from_xy = scale_Filtered_xy;
00620 scale_from_z = scale_Filtered_z;
00621
00622 if(useScalingFixpoint)
00623 {
00624
00625 x_offset += (xyz_scale_old - xy_scale)*scalingFixpoint[0];
00626 y_offset += (xyz_scale_old - xy_scale)*scalingFixpoint[1];
00627 z_offset += (xyz_scale_old - z_scale)*scalingFixpoint[2];
00628 }
00629 else
00630 {
00631
00632 x_offset += (xyz_scale_old - xy_scale)*OrgPtamPose[0];
00633 y_offset += (xyz_scale_old - xy_scale)*OrgPtamPose[1];
00634 z_offset += (xyz_scale_old - z_scale)*OrgPtamPose[2];
00635 }
00636 scale_xyz_initialized = true;
00637 }
00638
00639 float DroneKalmanFilter::getScaleAccuracy()
00640 {
00641 return 0.5 + 0.5*std::min(1.0,std::max(0.0,xyz_sum_PTAMxIMU * xy_scale/4));
00642 }
00643
00644
00645 void DroneKalmanFilter::predictUpTo(int timestamp, bool consume, bool useControlGains)
00646 {
00647 if(predictdUpToTimestamp == timestamp) return;
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668 std::deque<geometry_msgs::TwistStamped>::iterator controlIterator = velQueue->begin();
00669 while(controlIterator != velQueue->end() &&
00670 controlIterator+1 != velQueue->end() &&
00671 getMS((controlIterator+1)->header.stamp) <= predictdUpToTimestamp - delayControl)
00672 if(consume)
00673 {
00674 velQueue->pop_front();
00675 controlIterator = velQueue->begin();
00676 }
00677 else
00678 controlIterator++;
00679 if(velQueue->size() == 0) useControlGains = false;
00680
00681
00682 std::deque<ardrone_autonomy::Navdata>::iterator xyzIterator = navdataQueue->begin();
00683 while(xyzIterator != navdataQueue->end() &&
00684 getMS(xyzIterator->header.stamp) <= predictdUpToTimestamp + delayXYZ)
00685 xyzIterator++;
00686
00687 std::deque<ardrone_autonomy::Navdata>::iterator rpyIterator = navdataQueue->begin();
00688 while(rpyIterator != navdataQueue->end() &&
00689 getMS(rpyIterator->header.stamp) <= predictdUpToTimestamp + delayRPY)
00690 if(consume)
00691 {
00692 navdataQueue->pop_front();
00693 rpyIterator = navdataQueue->begin();
00694 }
00695 else
00696 rpyIterator++;
00697
00698
00699
00700 while(true)
00701 {
00702
00703 int predictTo = timestamp;
00704
00705
00706 predictTo = min(predictTo, predictdUpToTimestamp+10);
00707
00708
00709
00710 while(xyzIterator != navdataQueue->end() &&
00711 getMS(xyzIterator->header.stamp) - delayXYZ < predictdUpToTimestamp)
00712 xyzIterator++;
00713 while(rpyIterator != navdataQueue->end() &&
00714 getMS(rpyIterator->header.stamp) - delayRPY < predictdUpToTimestamp)
00715 rpyIterator++;
00716
00717 while(controlIterator != velQueue->end() &&
00718 controlIterator+1 != velQueue->end() &&
00719 getMS((controlIterator+1)->header.stamp) + delayControl <= predictdUpToTimestamp)
00720 controlIterator++;
00721
00722
00723
00724
00725 if(rpyIterator != navdataQueue->end() )
00726 predictTo = min(predictTo, getMS(rpyIterator->header.stamp)-delayRPY);
00727 if(xyzIterator != navdataQueue->end() )
00728 predictTo = min(predictTo, getMS(xyzIterator->header.stamp)-delayXYZ);
00729
00730 predictInternal(useControlGains ? controlIterator->twist : geometry_msgs::Twist(),
00731 (predictTo - predictdUpToTimestamp)*1000,
00732 useControlGains &&
00733 getMS(controlIterator->header.stamp) + 200 > predictdUpToTimestamp - delayControl);
00734
00735
00736
00737 bool observedXYZ = false, observedRPY=false;
00738 if(rpyIterator != navdataQueue->end() && getMS(rpyIterator->header.stamp)-delayRPY == predictTo)
00739 {
00740 if(this->useNavdata)
00741 observeIMU_RPY(&(*rpyIterator));
00742
00743 observedRPY = true;
00744
00745 }
00746 if(xyzIterator != navdataQueue->end() && getMS(xyzIterator->header.stamp)-delayXYZ == predictTo)
00747 {
00748 if(this->useNavdata)
00749 observeIMU_XYZ(&(*xyzIterator));
00750
00751 observedXYZ = true;
00752
00753 }
00754
00755
00756 predictdUpToTimestamp = predictTo;
00757
00758 if(consume)
00759 {
00760 if(node->logfileFilter != NULL)
00761 {
00762 pthread_mutex_lock(&(node->logFilter_CS));
00763 (*(node->logfileFilter)) << predictdUpToTimestamp << " " << 0 << " " << 0 << " " << 0 << " " <<
00764 0 << " " << 0 << " " << 0 << " " <<
00765 controlIterator->twist.linear.y << " " << controlIterator->twist.linear.x << " " << controlIterator->twist.linear.z << " " << controlIterator->twist.angular.z << " " <<
00766 (observedRPY ? rpyIterator->rotX : -1) << " " << (observedRPY ? rpyIterator->rotY : -1) << " " << (observedRPY ? lastdYaw : -1) << " " <<
00767 (observedXYZ ? xyzIterator->vx : -1) << " " << (observedXYZ ? xyzIterator->vy : -1) << " " << (observedXYZ ? lastdZ : -1) << " " <<
00768 x.state[0] << " " << y.state[0] << " " << z.state[0] << " " << roll.state << " " << pitch.state << " " << yaw.state[0] << " " << x.state[1] << " " << y.state[1] << " " << z.state[1] << " " << yaw.state[1] << " " <<
00769 lastVXGain << " " << lastVYGain << " " << "\n";
00770 pthread_mutex_unlock(&(node->logFilter_CS));
00771 }
00772 }
00773
00774 if(observedRPY) rpyIterator++;
00775 if(observedXYZ) xyzIterator++;
00776
00777
00778
00779 if(predictTo == timestamp)
00780 break;
00781 }
00782 }
00783
00784
00785 TooN::Vector<3> DroneKalmanFilter::transformPTAMObservation(double x,double y,double z)
00786 {
00787 return transformPTAMObservation(x,y,z,yaw.state[0]);
00788 }
00789 TooN::Vector<3> DroneKalmanFilter::transformPTAMObservation(double x,double y,double z, double yaw)
00790 {
00791 double yawRad = yaw * 3.14159268 / 180;
00792 x = x_offset + xy_scale*x - 0.2*sin(yawRad);
00793 y = y_offset + xy_scale*y - 0.2*cos(yawRad);
00794 z = z_offset + z_scale*z;
00795 return TooN::makeVector(x,y,z);
00796 }
00797
00798 TooN::Vector<6> DroneKalmanFilter::transformPTAMObservation(TooN::Vector<6> obs)
00799 {
00800 obs.slice<0,3>() = transformPTAMObservation(obs[0], obs[1], obs[2], obs[5]);
00801
00802 obs[3] += roll_offset;
00803 obs[4] += pitch_offset;
00804 obs[5] += yaw_offset;
00805
00806 return obs;
00807 }
00808 TooN::Vector<6> DroneKalmanFilter::backTransformPTAMObservation(TooN::Vector<6> obs)
00809 {
00810 obs[3] -= roll_offset;
00811 obs[4] -= pitch_offset;
00812 obs[5] -= yaw_offset;
00813
00814 double yawRad = obs[5] * 3.14159268 / 180;
00815 obs[0] = (- x_offset + obs[0] + 0.2*sin(yawRad))/xy_scale;
00816 obs[1] = (- y_offset + obs[1] + 0.2*cos(yawRad))/xy_scale;
00817 obs[2] = (- z_offset + obs[2])/z_scale;
00818
00819 return obs;
00820 }
00821
00822
00823
00824 TooN::Vector<6> DroneKalmanFilter::getCurrentPose()
00825 {
00826 return TooN::makeVector(x.state[0], y.state[0], z.state[0], roll.state, pitch.state, yaw.state[0]);
00827 }
00828
00829 uga_tum_ardrone::filter_state DroneKalmanFilter::getCurrentPoseSpeed()
00830 {
00831 uga_tum_ardrone::filter_state s;
00832 s.x = x.state[0];
00833 s.y = y.state[0];
00834 s.z = z.state[0];
00835 s.yaw = yaw.state[0];
00836 s.dx = x.state[1];
00837 s.dy = y.state[1];
00838 s.dz = z.state[1];
00839 s.dyaw = yaw.state[1];
00840 s.roll = roll.state;
00841 s.pitch = pitch.state;
00842
00843 if(s.roll*s.roll < 0.001) s.roll = 0;
00844 if(s.pitch*s.pitch < 0.001) s.pitch = 0;
00845 if(s.yaw*s.yaw < 0.001) s.yaw = 0;
00846 if(s.dx*s.dx < 0.001) s.dx = 0;
00847 if(s.dy*s.dy < 0.001) s.dy = 0;
00848 if(s.dz*s.dz < 0.001) s.dz = 0;
00849 if(s.x*s.x < 0.001) s.x = 0;
00850 if(s.y*s.y < 0.001) s.y = 0;
00851 if(s.z*s.z < 0.001) s.z = 0;
00852
00853 return s;
00854 }
00855
00856 TooN::Vector<10> DroneKalmanFilter::getCurrentPoseSpeedAsVec()
00857 {
00858 return TooN::makeVector(x.state[0], y.state[0], z.state[0], roll.state, pitch.state, yaw.state[0],
00859 x.state[1], y.state[1], z.state[1],yaw.state[1]);
00860 }
00861
00862 TooN::Vector<10> DroneKalmanFilter::getCurrentPoseSpeedVariances()
00863 {
00864 return TooN::makeVector(x.var(0,0), y.var(0,0), z.var(0,0), roll.var, pitch.var, yaw.var(0,0),
00865 x.var(1,1), y.var(1,1), z.var(1,1),yaw.var(1,1));
00866 }
00867
00868 TooN::Vector<6> DroneKalmanFilter::getCurrentPoseVariances()
00869 {
00870 return TooN::makeVector(x.var(0,0), y.var(0,0), z.var(0,0), roll.var, pitch.var, yaw.var(0,0));
00871 }
00872 TooN::Vector<6> DroneKalmanFilter::getCurrentOffsets()
00873 {
00874 TooN::Vector<6> res = TooN::makeVector(0,0,0,0,0,0);
00875 if(offsets_xyz_initialized)
00876 res.slice<0,3>() = TooN::makeVector(x_offset, y_offset, z_offset);
00877 if(rp_offset_framesContributed > 1)
00878 res.slice<3,3>() = TooN::makeVector(roll_offset, pitch_offset, yaw_offset);
00879 return res;
00880 }
00881 TooN::Vector<3> DroneKalmanFilter::getCurrentScales()
00882 {
00883 return TooN::makeVector(scale_xyz_initialized ? xy_scale : 1, scale_xyz_initialized ? xy_scale : 1, scale_xyz_initialized ? z_scale : 1);
00884 }
00885 TooN::Vector<3> DroneKalmanFilter::getCurrentScalesForLog()
00886 {
00887 return TooN::makeVector(scale_xyz_initialized ? scale_from_xy : 1, scale_xyz_initialized ? scale_from_z : 1, scale_xyz_initialized ? xy_scale : 1);
00888 }
00889
00890 void DroneKalmanFilter::setCurrentScales(TooN::Vector<3> scales)
00891 {
00892 if(allSyncLocked) return;
00893 xy_scale = scales[0];
00894 z_scale = scales[0];
00895 scale_from_xy = scale_from_z = scales[0];
00896
00897 xyz_sum_IMUxIMU = 0.2 * scales[0];
00898 xyz_sum_PTAMxPTAM = 0.2 / scales[0];
00899 xyz_sum_PTAMxIMU = 0.2;
00900
00901 (*scalePairs).clear();
00902
00903 (*scalePairs).push_back(ScaleStruct(
00904 TooN::makeVector(0.2,0.2,0.2) / sqrt(scales[0]),
00905 TooN::makeVector(0.2,0.2,0.2) * sqrt(scales[0])
00906 ));
00907
00908
00909
00910 scale_xyz_initialized = true;
00911 offsets_xyz_initialized = false;
00912
00913 initialScaleSet = scales[0];
00914 }
00915
00916 void DroneKalmanFilter::addPTAMObservation(TooN::Vector<6> trans, int time)
00917 {
00918 if(time > predictdUpToTimestamp)
00919 predictUpTo(time, true,true);
00920
00921 observePTAM(trans);
00922 numGoodPTAMObservations++;
00923 }
00924 void DroneKalmanFilter::addFakePTAMObservation(int time)
00925 {
00926 if(time > predictdUpToTimestamp)
00927 predictUpTo(time, true,true);
00928
00929 lastPosesValid = false;
00930 }
00931 uga_tum_ardrone::filter_state DroneKalmanFilter::getPoseAt(ros::Time t, bool useControlGains)
00932 {
00933
00934
00935 DroneKalmanFilter scopy = DroneKalmanFilter(*this);
00936
00937
00938 scopy.predictUpTo(getMS(t),false, useControlGains);
00939
00940
00941 return scopy.getCurrentPoseSpeed();
00942 }
00943
00944 TooN::Vector<10> DroneKalmanFilter::getPoseAtAsVec(int timestamp, bool useControlGains)
00945 {
00946
00947 DroneKalmanFilter scopy = DroneKalmanFilter(*this);
00948
00949
00950 scopy.predictUpTo(timestamp,false, useControlGains);
00951
00952
00953 return scopy.getCurrentPoseSpeedAsVec();
00954
00955 }
00956
00957 bool DroneKalmanFilter::handleCommand(std::string s)
00958 {
00959
00960 return false;
00961 }