00001
00024 #include "PTAMWrapper.h"
00025 #include <cvd/gl_helpers.h>
00026 #include <gvars3/instances.h>
00027 #include "PTAM/ATANCamera.h"
00028 #include "PTAM/MapMaker.h"
00029 #include "PTAM/Tracker.h"
00030 #include "PTAM/Map.h"
00031 #include "PTAM/MapPoint.h"
00032 #include "../HelperFunctions.h"
00033 #include "Predictor.h"
00034 #include "DroneKalmanFilter.h"
00035 #include <cv_bridge/cv_bridge.h>
00036 #include <sensor_msgs/image_encodings.h>
00037 #include "GLWindow2.h"
00038 #include "EstimationNode.h"
00039 #include <iostream>
00040 #include <fstream>
00041 #include <string>
00042
00043 pthread_mutex_t PTAMWrapper::navInfoQueueCS = PTHREAD_MUTEX_INITIALIZER;
00044 pthread_mutex_t PTAMWrapper::shallowMapCS = PTHREAD_MUTEX_INITIALIZER;
00045
00046 pthread_mutex_t PTAMWrapper::logScalePairs_CS = PTHREAD_MUTEX_INITIALIZER;
00047
00048 PTAMWrapper::PTAMWrapper(DroneKalmanFilter* f, EstimationNode* nde)
00049 {
00050 filter = f;
00051 node = nde;
00052
00053 mpMap = 0;
00054 mpMapMaker = 0;
00055 mpTracker = 0;
00056 predConvert = 0;
00057 predIMUOnlyForScale = 0;
00058 mpCamera = 0;
00059 newImageAvailable = false;
00060
00061 mapPointsTransformed = std::vector<tvec3>();
00062 keyFramesTransformed = std::vector<tse3>();
00063
00064
00065 predConvert = new Predictor();
00066 predIMUOnlyForScale = new Predictor();
00067 imuOnlyPred = new Predictor();
00068
00069 drawUI = UI_PRES;
00070 frameWidth = frameHeight = 0;
00071
00072 minKFDist = 0;
00073 minKFWiggleDist = 0;
00074 minKFTimeDist = 0;
00075
00076 maxKF = 60;
00077
00078 logfileScalePairs = 0;
00079 }
00080
00081 void PTAMWrapper::ResetInternal()
00082 {
00083 mimFrameBW.resize(CVD::ImageRef(frameWidth, frameHeight));
00084 mimFrameBW_workingCopy.resize(CVD::ImageRef(frameWidth, frameHeight));
00085
00086
00087 if(mpMapMaker != 0) delete mpMapMaker;
00088 if(mpMap != 0) delete mpMap;
00089 if(mpTracker != 0) delete mpTracker;
00090 if(mpCamera != 0) delete mpCamera;
00091
00092
00093
00094 std::string file = node->calibFile;
00095 while(node->arDroneVersion == 0)
00096 {
00097 std::cout << "Waiting for first navdata to determine drone version!" << std::endl;
00098 usleep(250000);
00099 }
00100 if(file.size()==0)
00101 {
00102 if(node->arDroneVersion == 1)
00103 file = node->packagePath + "/camcalib/ardrone1_default.txt";
00104 else if(node->arDroneVersion == 2)
00105 file = node->packagePath + "/camcalib/ardrone2_default.txt";
00106 }
00107
00108 std::ifstream fleH (file.c_str());
00109 TooN::Vector<5> camPar;
00110 fleH >> camPar[0] >> camPar[1] >> camPar[2] >> camPar[3] >> camPar[4];
00111 fleH.close();
00112 std::cout<< "Set Camera Paramerer to: " << camPar[0] << " " << camPar[1] << " " << camPar[2] << " " << camPar[3] << " " << camPar[4] << std::endl;
00113
00114
00115
00116 mpMap = new Map;
00117 mpCamera = new ATANCamera(camPar);
00118 mpMapMaker = new MapMaker(*mpMap, *mpCamera);
00119 mpTracker = new Tracker(CVD::ImageRef(frameWidth, frameHeight), *mpCamera, *mpMap, *mpMapMaker);
00120
00121 setPTAMPars(minKFTimeDist, minKFWiggleDist, minKFDist, min_tol, max_tol);
00122
00123 predConvert->setPosRPY(0,0,0,0,0,0);
00124 predIMUOnlyForScale->setPosRPY(0,0,0,0,0,0);
00125
00126 resetPTAMRequested = false;
00127 forceKF = false;
00128 isGoodCount = 0;
00129 lastAnimSentClock = 0;
00130 lockNextFrame = false;
00131 PTAMInitializedClock = 0;
00132 lastPTAMMessage = "";
00133
00134 flushMapKeypoints = false;
00135
00136 node->publishCommand("u l PTAM has been reset.");
00137 }
00138
00139 void PTAMWrapper::setPTAMPars(double minKFTimeDist, double minKFWiggleDist, double minKFDist,
00140 double min_tol, double max_tol)
00141 {
00142 if(mpMapMaker != 0)
00143 mpMapMaker->minKFDist = minKFDist;
00144 if(mpMapMaker != 0)
00145 mpMapMaker->minKFWiggleDist = minKFWiggleDist;
00146 if(mpTracker != 0)
00147 mpTracker->minKFTimeDist = minKFTimeDist;
00148
00149 if(mpMapMaker != 0)
00150 mpMapMaker->min_tol = min_tol;
00151 if(mpMapMaker != 0)
00152 mpMapMaker->max_tol = max_tol;
00153
00154 this->minKFDist = minKFDist;
00155 this->minKFWiggleDist = minKFWiggleDist;
00156 this->minKFTimeDist = minKFTimeDist;
00157 this->min_tol = min_tol;
00158 this->max_tol = max_tol;
00159 }
00160
00161 PTAMWrapper::~PTAMWrapper(void)
00162 {
00163 if(mpCamera != 0) delete mpCamera;
00164 if(mpMap != 0) delete mpMap;
00165 if(mpMapMaker != 0) delete mpMapMaker;
00166 if(mpTracker != 0) delete mpTracker;
00167 if(predConvert != 0) delete predConvert;
00168 if(predIMUOnlyForScale != 0) delete predIMUOnlyForScale;
00169 if(imuOnlyPred != 0) delete imuOnlyPred;
00170
00171 }
00172
00173
00174 void PTAMWrapper::startSystem()
00175 {
00176 keepRunning = true;
00177 changeSizeNextRender = false;
00178 start();
00179 }
00180
00181 void PTAMWrapper::stopSystem()
00182 {
00183 keepRunning = false;
00184 new_frame_signal.notify_all();
00185 join();
00186 }
00187
00188
00189 void PTAMWrapper::run()
00190 {
00191 std::cout << "Waiting for Video" << std::endl;
00192
00193
00194 while(!newImageAvailable)
00195 usleep(100000);
00196 newImageAvailable = false;
00197 while(!newImageAvailable)
00198 usleep(100000);
00199
00200
00201 frameWidth = mimFrameBW.size().x;
00202 frameHeight = mimFrameBW.size().y;
00203
00204 ResetInternal();
00205
00206
00207 snprintf(charBuf,200,"Video resolution: %d x %d",frameWidth,frameHeight);
00208 ROS_INFO("%s", charBuf);
00209 node->publishCommand(std::string("u l ")+charBuf);
00210
00211
00212 myGLWindow = new GLWindow2(CVD::ImageRef(frameWidth,frameHeight), "PTAM Drone Camera Feed", this);
00213 myGLWindow->set_title("PTAM Drone Camera Feed");
00214
00215 changeSizeNextRender = true;
00216 if(frameWidth < 640)
00217 desiredWindowSize = CVD::ImageRef(frameWidth*2,frameHeight*2);
00218 else
00219 desiredWindowSize = CVD::ImageRef(frameWidth,frameHeight);
00220
00221
00222 boost::unique_lock<boost::mutex> lock(new_frame_signal_mutex);
00223
00224 while(keepRunning)
00225 {
00226 if(newImageAvailable)
00227 {
00228 newImageAvailable = false;
00229
00230
00231 mimFrameBW_workingCopy.copy_from(mimFrameBW);
00232 mimFrameTime_workingCopy = mimFrameTime;
00233 mimFrameSEQ_workingCopy = mimFrameSEQ;
00234 mimFrameTimeRos_workingCopy = mimFrameTimeRos;
00235
00236
00237 lock.unlock();
00238
00239 HandleFrame();
00240
00241
00242 if(changeSizeNextRender)
00243 {
00244 myGLWindow->set_size(desiredWindowSize);
00245 changeSizeNextRender = false;
00246 }
00247
00248
00249 lock.lock();
00250 }
00251 else
00252 new_frame_signal.wait(lock);
00253 }
00254
00255 lock.unlock();
00256 delete myGLWindow;
00257 }
00258
00259
00260
00261
00262
00263
00264 void PTAMWrapper::HandleFrame()
00265 {
00266
00267
00268
00269
00270 msg = "";
00271 ros::Time startedFunc = ros::Time::now();
00272
00273
00274 if(resetPTAMRequested)
00275 ResetInternal();
00276
00277
00278
00279
00280 pthread_mutex_lock( &filter->filter_CS );
00281
00282 TooN::Vector<10> filterPosePrePTAM = filter->getPoseAtAsVec(mimFrameTime_workingCopy-filter->delayVideo,true);
00283 pthread_mutex_unlock( &filter->filter_CS );
00284
00285
00286 myGLWindow->SetupViewport();
00287 myGLWindow->SetupVideoOrtho();
00288 myGLWindow->SetupVideoRasterPosAndZoom();
00289
00290
00291
00292
00293 TooN::Vector<6> PTAMPoseGuess = filter->backTransformPTAMObservation(filterPosePrePTAM.slice<0,6>());
00294
00295 predConvert->setPosRPY(PTAMPoseGuess[0], PTAMPoseGuess[1], PTAMPoseGuess[2], PTAMPoseGuess[3], PTAMPoseGuess[4], PTAMPoseGuess[5]);
00296
00297 TooN::SE3<> PTAMPoseGuessSE3 = predConvert->droneToFrontNT * predConvert->globaltoDrone;
00298
00299
00300
00301 mpTracker->setPredictedCamFromW(PTAMPoseGuessSE3);
00302
00303 mpTracker->setLastFrameLost((isGoodCount < -20), (mimFrameSEQ_workingCopy%3 == 0));
00304
00305
00306 ros::Time startedPTAM = ros::Time::now();
00307 mpTracker->TrackFrame(mimFrameBW_workingCopy, true);
00308 TooN::SE3<> PTAMResultSE3 = mpTracker->GetCurrentPose();
00309 lastPTAMMessage = msg = mpTracker->GetMessageForUser();
00310 ros::Duration timePTAM= ros::Time::now() - startedPTAM;
00311
00312 TooN::Vector<6> PTAMResultSE3TwistOrg = PTAMResultSE3.ln();
00313
00314 node->publishTf(mpTracker->GetCurrentPose(),mimFrameTimeRos_workingCopy, mimFrameSEQ_workingCopy,"cam_front");
00315
00316
00317
00318
00319 predConvert->setPosSE3_globalToDrone(predConvert->frontToDroneNT * PTAMResultSE3);
00320 TooN::Vector<6> PTAMResult = TooN::makeVector(predConvert->x, predConvert->y, predConvert->z, predConvert->roll, predConvert->pitch, predConvert->yaw);
00321
00322
00323 TooN::Vector<6> PTAMResultTransformed = filter->transformPTAMObservation(PTAMResult);
00324
00325
00326
00327
00328
00329 if(mpTracker->lastStepResult == mpTracker->I_FAILED)
00330 {
00331 ROS_INFO("initializing PTAM failed, resetting!");
00332 resetPTAMRequested = true;
00333 }
00334 if(mpTracker->lastStepResult == mpTracker->I_SECOND)
00335 {
00336 PTAMInitializedClock = getMS();
00337 filter->setCurrentScales(TooN::makeVector(mpMapMaker->initialScaleFactor*1.2,mpMapMaker->initialScaleFactor*1.2,mpMapMaker->initialScaleFactor*1.2));
00338 mpMapMaker->currentScaleFactor = filter->getCurrentScales()[0];
00339 ROS_INFO("PTAM initialized!");
00340 ROS_INFO("initial scale: %f\n",mpMapMaker->initialScaleFactor*1.2);
00341 node->publishCommand("u l PTAM initialized (took second KF)");
00342 framesIncludedForScaleXYZ = -1;
00343 lockNextFrame = true;
00344 imuOnlyPred->resetPos();
00345 }
00346 if(mpTracker->lastStepResult == mpTracker->I_FIRST)
00347 {
00348 node->publishCommand("u l PTAM initialization started (took first KF)");
00349 }
00350
00351
00352
00353
00354
00355
00356
00357 bool isGood = true;
00358 bool isVeryGood = true;
00359
00360 TooN::Vector<6> diffs = PTAMResultTransformed - filterPosePrePTAM.slice<0,6>();
00361 for(int i=0;1<1;i++) diffs[i] = abs(diffs[i]);
00362
00363
00364 if(filter->getNumGoodPTAMObservations() < 10 && mpMap->IsGood())
00365 {
00366 isGood = true;
00367 isVeryGood = false;
00368 }
00369 else if(mpTracker->lastStepResult == mpTracker->I_FIRST ||
00370 mpTracker->lastStepResult == mpTracker->I_SECOND ||
00371 mpTracker->lastStepResult == mpTracker->I_FAILED ||
00372 mpTracker->lastStepResult == mpTracker->T_LOST ||
00373 mpTracker->lastStepResult == mpTracker->NOT_TRACKING ||
00374 mpTracker->lastStepResult == mpTracker->INITIALIZING)
00375 isGood = isVeryGood = false;
00376 else
00377 {
00378
00379 bool dodgy = mpTracker->lastStepResult == mpTracker->T_DODGY ||
00380 mpTracker->lastStepResult == mpTracker->T_RECOVERED_DODGY;
00381
00382
00383
00384 double maxYawDiff = 10.0 + (getMS()-lastGoodYawClock)*0.002;
00385 if(maxYawDiff > 20) maxYawDiff = 1000;
00386 if(false && diffs[5] > maxYawDiff)
00387 isGood = false;
00388
00389 if(diffs[5] < 10)
00390 lastGoodYawClock = getMS();
00391
00392 if(diffs[5] > 4.0)
00393 isVeryGood = false;
00394
00395
00396 if(diffs[3] > 20 || diffs[4] > 20)
00397 isGood = false;
00398
00399 if(diffs[3] > 3 || diffs[4] > 3 || dodgy)
00400 isVeryGood = false;
00401 }
00402
00403 if(isGood)
00404 {
00405 if(isGoodCount < 0) isGoodCount = 0;
00406 isGoodCount++;
00407 }
00408 else
00409 {
00410 if(isGoodCount > 0) isGoodCount = 0;
00411 isGoodCount--;
00412
00413 if(mpTracker->lastStepResult == mpTracker->T_RECOVERED_DODGY)
00414 isGoodCount = std::max(isGoodCount,-2);
00415 if(mpTracker->lastStepResult == mpTracker->T_RECOVERED_GOOD)
00416 isGoodCount = std::max(isGoodCount,-5);
00417
00418 }
00419
00420 TooN::Vector<10> filterPosePostPTAM;
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 pthread_mutex_lock( &filter->filter_CS );
00433 if(filter->usePTAM && isGoodCount >= 3)
00434 {
00435 filter->addPTAMObservation(PTAMResult,mimFrameTime_workingCopy-filter->delayVideo);
00436 }
00437 else
00438 filter->addFakePTAMObservation(mimFrameTime_workingCopy-filter->delayVideo);
00439
00440 filterPosePostPTAM = filter->getCurrentPoseSpeedAsVec();
00441 pthread_mutex_unlock( &filter->filter_CS );
00442
00443
00444
00445 int includedTime = mimFrameTime_workingCopy - ptamPositionForScaleTakenTimestamp;
00446 if(framesIncludedForScaleXYZ >= 0) framesIncludedForScaleXYZ++;
00447
00448
00449 if(includedTime > 3000)
00450 {
00451 framesIncludedForScaleXYZ = -1;
00452 }
00453
00454 if(isGoodCount >= 3)
00455 {
00456
00457 lastScaleEKFtimestamp = mimFrameTime_workingCopy;
00458
00459 if(includedTime >= 2000 && framesIncludedForScaleXYZ > 1)
00460 {
00461 TooN::Vector<3> diffPTAM = PTAMResult.slice<0,3>() - PTAMPositionForScale;
00462 bool zCorrupted, allCorrupted;
00463 float pressureStart = 0, pressureEnd = 0;
00464 TooN::Vector<3> diffIMU = evalNavQue(ptamPositionForScaleTakenTimestamp - filter->delayVideo + filter->delayXYZ,mimFrameTime_workingCopy - filter->delayVideo + filter->delayXYZ,&zCorrupted, &allCorrupted, &pressureStart, &pressureEnd);
00465
00466 pthread_mutex_lock(&logScalePairs_CS);
00467 if(logfileScalePairs != 0)
00468 (*logfileScalePairs) <<
00469 pressureStart << " " <<
00470 pressureEnd << " " <<
00471 diffIMU[2] << " " <<
00472 diffPTAM[2] << std::endl;
00473 pthread_mutex_unlock(&logScalePairs_CS);
00474
00475
00476 if(!allCorrupted)
00477 {
00478
00479 double xyFactor = 0.05;
00480 double zFactor = zCorrupted ? 0 : 3;
00481
00482 diffPTAM.slice<0,2>() *= xyFactor; diffPTAM[2] *= zFactor;
00483 diffIMU.slice<0,2>() *= xyFactor; diffIMU[2] *= zFactor;
00484
00485 filter->updateScaleXYZ(diffPTAM, diffIMU, PTAMResult.slice<0,3>());
00486 mpMapMaker->currentScaleFactor = filter->getCurrentScales()[0];
00487 }
00488 framesIncludedForScaleXYZ = -1;
00489 }
00490
00491 if(framesIncludedForScaleXYZ == -1)
00492 {
00493 framesIncludedForScaleXYZ = 0;
00494 PTAMPositionForScale = PTAMResult.slice<0,3>();
00495
00496 ptamPositionForScaleTakenTimestamp = mimFrameTime_workingCopy;
00497 }
00498 }
00499
00500
00501 if(lockNextFrame && isGood)
00502 {
00503 filter->scalingFixpoint = PTAMResult.slice<0,3>();
00504 lockNextFrame = false;
00505
00506
00507 snprintf(charBuf,500,"locking scale fixpoint to %.3f %.3f %.3f",PTAMResultTransformed[0], PTAMResultTransformed[1], PTAMResultTransformed[2]);
00508 ROS_INFO("%s", charBuf);
00509 node->publishCommand(std::string("u l ")+charBuf);
00510 }
00511
00512
00513
00514 if(!mapLocked && isVeryGood && (forceKF || (int)(mpMap->vpKeyFrames.size()) < maxKF || maxKF <= 1))
00515 {
00516 mpTracker->TakeKF(forceKF);
00517 forceKF = false;
00518 }
00519
00520
00521 if(mpTracker->lastStepResult == mpTracker->NOT_TRACKING)
00522 PTAMStatus = PTAM_IDLE;
00523 else if(mpTracker->lastStepResult == mpTracker->I_FIRST ||
00524 mpTracker->lastStepResult == mpTracker->I_SECOND ||
00525 mpTracker->lastStepResult == mpTracker->T_TOOK_KF)
00526 PTAMStatus = PTAM_TOOKKF;
00527 else if(mpTracker->lastStepResult == mpTracker->INITIALIZING)
00528 PTAMStatus = PTAM_INITIALIZING;
00529 else if(isVeryGood)
00530 PTAMStatus = PTAM_BEST;
00531 else if(isGood)
00532 PTAMStatus = PTAM_GOOD;
00533 else if(mpTracker->lastStepResult == mpTracker->T_DODGY ||
00534 mpTracker->lastStepResult == mpTracker->T_GOOD)
00535 PTAMStatus = PTAM_FALSEPOSITIVE;
00536 else
00537 PTAMStatus = PTAM_LOST;
00538
00539
00540
00541 if(!mapLocked && rand()%5==0)
00542 {
00543 pthread_mutex_lock(&shallowMapCS);
00544 mapPointsTransformed.clear();
00545 keyFramesTransformed.clear();
00546 for(unsigned int i=0;i<mpMap->vpKeyFrames.size();i++)
00547 {
00548 predConvert->setPosSE3_globalToDrone(predConvert->frontToDroneNT * mpMap->vpKeyFrames[i]->se3CfromW);
00549 TooN::Vector<6> CamPos = TooN::makeVector(predConvert->x, predConvert->y, predConvert->z, predConvert->roll, predConvert->pitch, predConvert->yaw);
00550 CamPos = filter->transformPTAMObservation(CamPos);
00551 predConvert->setPosRPY(CamPos[0], CamPos[1], CamPos[2], CamPos[3], CamPos[4], CamPos[5]);
00552 keyFramesTransformed.push_back(predConvert->droneToGlobal);
00553 }
00554 TooN::Vector<3> PTAMScales = filter->getCurrentScales();
00555 TooN::Vector<3> PTAMOffsets = filter->getCurrentOffsets().slice<0,3>();
00556 for(unsigned int i=0;i<mpMap->vpPoints.size();i++)
00557 {
00558 TooN::Vector<3> pos = (mpMap->vpPoints)[i]->v3WorldPos;
00559 pos[0] *= PTAMScales[0];
00560 pos[1] *= PTAMScales[1];
00561 pos[2] *= PTAMScales[2];
00562 pos += PTAMOffsets;
00563 mapPointsTransformed.push_back(pos);
00564 }
00565
00566
00567 if(flushMapKeypoints)
00568 {
00569 std::ofstream* fle = new std::ofstream();
00570 fle->open("pointcloud.txt");
00571
00572 for(unsigned int i=0;i<mapPointsTransformed.size();i++)
00573 {
00574 (*fle) << mapPointsTransformed[i][0] << " "
00575 << mapPointsTransformed[i][1] << " "
00576 << mapPointsTransformed[i][2] << std::endl;
00577 }
00578
00579 fle->flush();
00580 fle->close();
00581
00582 printf("FLUSHED %lu KEYPOINTS to file pointcloud.txt\n\n",mapPointsTransformed.size());
00583
00584 flushMapKeypoints = false;
00585 }
00586
00587
00588 pthread_mutex_unlock(&shallowMapCS);
00589
00590 }
00591
00592
00593
00594
00595 ros::Duration timeALL = ros::Time::now() - startedFunc;
00596 if(isVeryGood) snprintf(charBuf,1000,"\nQuality: best ");
00597 else if(isGood) snprintf(charBuf,1000,"\nQuality: good ");
00598 else snprintf(charBuf,1000,"\nQuality: lost ");
00599
00600 snprintf(charBuf+20,800, "scale: %.3f (acc: %.3f) ",filter->getCurrentScales()[0],(double)filter->getScaleAccuracy());
00601 snprintf(charBuf+50,800, "PTAM time: %i ms ",(int)(1000*timeALL.toSec()));
00602 snprintf(charBuf+68,800, "(%i ms total) ",(int)(1000*timeALL.toSec()));
00603 if(mapLocked) snprintf(charBuf+83,800, "m.l. ");
00604 else snprintf(charBuf+83,800, " ");
00605 if(filter->allSyncLocked) snprintf(charBuf+88,800, "s.l. ");
00606 else snprintf(charBuf+88,800, " ");
00607
00608
00609 msg += charBuf;
00610
00611 if(mpMap->IsGood())
00612 {
00613 if(drawUI == UI_DEBUG)
00614 {
00615 snprintf(charBuf,1000,"\nPTAM Diffs: ");
00616 snprintf(charBuf+13,800, "x: %.3f ",diffs[0]);
00617 snprintf(charBuf+23,800, "y: %.3f ",diffs[1]);
00618 snprintf(charBuf+33,800, "z: %.3f ",diffs[2]);
00619 snprintf(charBuf+43,800, "r: %.2f ",diffs[3]);
00620 snprintf(charBuf+53,800, "p: %.2f ",diffs[4]);
00621 snprintf(charBuf+63,800, "y: %.2f",diffs[5]);
00622 msg += charBuf;
00623
00624
00625 snprintf(charBuf,1000,"\nPTAM Pose: ");
00626 snprintf(charBuf+13,800, "x: %.3f ",PTAMResultTransformed[0]);
00627 snprintf(charBuf+23,800, "y: %.3f ",PTAMResultTransformed[1]);
00628 snprintf(charBuf+33,800, "z: %.3f ",PTAMResultTransformed[2]);
00629 snprintf(charBuf+43,800, "r: %.2f ",PTAMResultTransformed[3]);
00630 snprintf(charBuf+53,800, "p: %.2f ",PTAMResultTransformed[4]);
00631 snprintf(charBuf+63,800, "y: %.2f",PTAMResultTransformed[5]);
00632 msg += charBuf;
00633
00634
00635 snprintf(charBuf,1000,"\nPTAM WiggleDist: ");
00636 snprintf(charBuf+18,800, "%.3f ",mpMapMaker->lastWiggleDist);
00637 snprintf(charBuf+24,800, "MetricDist: %.3f",mpMapMaker->lastMetricDist);
00638 msg += charBuf;
00639 }
00640 }
00641
00642 if(drawUI != UI_NONE)
00643 {
00644
00645 predConvert->setPosRPY(filterPosePostPTAM[0], filterPosePostPTAM[1], filterPosePostPTAM[2], filterPosePostPTAM[3], filterPosePostPTAM[4], filterPosePostPTAM[5]);
00646
00647
00648
00649
00650
00651
00652
00653 {
00654 myGLWindow->SetupViewport();
00655 myGLWindow->SetupVideoOrtho();
00656 myGLWindow->SetupVideoRasterPosAndZoom();
00657
00658
00659 glLineWidth(2);
00660 glBegin(GL_LINES);
00661 glColor3f(0,0,1);
00662
00663 glVertex2f(0,frameHeight/2);
00664 glVertex2f(frameWidth,frameHeight/2);
00665
00666 glVertex2f(frameWidth/2,0);
00667 glVertex2f(frameWidth/2,frameHeight);
00668
00669
00670 glVertex2f(0.25*frameWidth,0.48*frameHeight);
00671 glVertex2f(0.25*frameWidth,0.52*frameHeight);
00672 glVertex2f(0.75*frameWidth,0.48*frameHeight);
00673 glVertex2f(0.75*frameWidth,0.52*frameHeight);
00674 glVertex2f(0.48*frameWidth,0.25*frameHeight);
00675 glVertex2f(0.52*frameWidth,0.25*frameHeight);
00676 glVertex2f(0.48*frameWidth,0.75*frameHeight);
00677 glVertex2f(0.52*frameWidth,0.75*frameHeight);
00678
00679 glEnd();
00680 }
00681
00682
00683 myGLWindow->DrawCaption(msg);
00684 }
00685
00686 lastPTAMResultRaw = PTAMResultSE3;
00687
00688
00689 if(node->logfilePTAM != NULL)
00690 {
00691 TooN::Vector<3> scales = filter->getCurrentScalesForLog();
00692 TooN::Vector<3> sums = TooN::makeVector(0,0,0);
00693 TooN::Vector<6> offsets = filter->getCurrentOffsets();
00694 pthread_mutex_lock(&(node->logPTAM_CS));
00695
00696
00697
00698
00699
00700 if(node->logfilePTAM != NULL)
00701 (*(node->logfilePTAM)) << (isGood ? (isVeryGood ? 2 : 1) : 0) << " " <<
00702 (mimFrameTime_workingCopy-filter->delayVideo) << " " << filterPosePrePTAM[0] << " " << filterPosePrePTAM[1] << " " << filterPosePrePTAM[2] << " " << filterPosePrePTAM[3] << " " << filterPosePrePTAM[4] << " " << filterPosePrePTAM[5] << " " << filterPosePrePTAM[6] << " " << filterPosePrePTAM[7] << " " << filterPosePrePTAM[8] << " " << filterPosePrePTAM[9] << " " <<
00703 filterPosePostPTAM[0] << " " << filterPosePostPTAM[1] << " " << filterPosePostPTAM[2] << " " << filterPosePostPTAM[3] << " " << filterPosePostPTAM[4] << " " << filterPosePostPTAM[5] << " " << filterPosePostPTAM[6] << " " << filterPosePostPTAM[7] << " " << filterPosePostPTAM[8] << " " << filterPosePostPTAM[9] << " " <<
00704 PTAMResultTransformed[0] << " " << PTAMResultTransformed[1] << " " << PTAMResultTransformed[2] << " " << PTAMResultTransformed[3] << " " << PTAMResultTransformed[4] << " " << PTAMResultTransformed[5] << " " <<
00705 scales[0] << " " << scales[1] << " " << scales[2] << " " <<
00706 offsets[0] << " " << offsets[1] << " " << offsets[2] << " " << offsets[3] << " " << offsets[4] << " " << offsets[5] << " " <<
00707 sums[0] << " " << sums[1] << " " << sums[2] << " " <<
00708 PTAMResult[0] << " " << PTAMResult[1] << " " << PTAMResult[2] << " " << PTAMResult[3] << " " << PTAMResult[4] << " " << PTAMResult[5] << " " <<
00709 PTAMResultSE3TwistOrg[0] << " " << PTAMResultSE3TwistOrg[1] << " " << PTAMResultSE3TwistOrg[2] << " " << PTAMResultSE3TwistOrg[3] << " " << PTAMResultSE3TwistOrg[4] << " " << PTAMResultSE3TwistOrg[5] << " " <<
00710 videoFramePing << " " << mimFrameTimeRos_workingCopy << " " << mimFrameSEQ_workingCopy << std::endl;
00711
00712 pthread_mutex_unlock(&(node->logPTAM_CS));
00713 }
00714
00715 myGLWindow->swap_buffers();
00716 myGLWindow->HandlePendingEvents();
00717
00718 }
00719
00720
00721
00722 void PTAMWrapper::renderGrid(TooN::SE3<> camFromWorld)
00723 {
00724 myGLWindow->SetupViewport();
00725 myGLWindow->SetupVideoOrtho();
00726 myGLWindow->SetupVideoRasterPosAndZoom();
00727
00728 camFromWorld.get_translation() *= 1;
00729
00730
00731
00732 glColor4f(0,0,0,0.6);
00733
00734
00735 int nHalfCells = 5;
00736 int nTot = nHalfCells * 2 + 1;
00737 CVD::Image<Vector<2> > imVertices(CVD::ImageRef(nTot,nTot));
00738 for(int i=0; i<nTot; i++)
00739 for(int j=0; j<nTot; j++)
00740 {
00741 Vector<3> v3;
00742 v3[0] = (i - nHalfCells) * 1;
00743 v3[1] = (j - nHalfCells) * 1;
00744 v3[2] = 0.0;
00745 Vector<3> v3Cam = camFromWorld * v3;
00746
00747 if(v3Cam[2] < 0.001)
00748 v3Cam = TooN::makeVector(100000*v3Cam[0],100000*v3Cam[1],0.0001);
00749
00750 imVertices[i][j] = mpCamera->Project(TooN::project(v3Cam))*0.5;
00751 }
00752
00753 glEnable(GL_LINE_SMOOTH);
00754 glEnable(GL_BLEND);
00755 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00756 glLineWidth(2);
00757 for(int i=0; i<nTot; i++)
00758 {
00759 glBegin(GL_LINE_STRIP);
00760 for(int j=0; j<nTot; j++)
00761 CVD::glVertex(imVertices[i][j]);
00762 glEnd();
00763
00764 glBegin(GL_LINE_STRIP);
00765 for(int j=0; j<nTot; j++)
00766 CVD::glVertex(imVertices[j][i]);
00767 glEnd();
00768 };
00769
00770 glLineWidth(1);
00771 glColor3f(1,0,0);
00772
00773
00774
00775 }
00776
00777 TooN::Vector<3> PTAMWrapper::evalNavQue(unsigned int from, unsigned int to, bool* zCorrupted, bool* allCorrupted, float* out_start_pressure, float* out_end_pressure)
00778 {
00779 predIMUOnlyForScale->resetPos();
00780
00781 int firstAdded = 0, lastAdded = 0;
00782 pthread_mutex_lock(&navInfoQueueCS);
00783 int skipped=0;
00784 int used = 0;
00785 double firstZ = 0;
00786
00787 float sum_first=0, num_first=0, sum_last=0, num_last=0;
00788 int pressureAverageRange = 100;
00789
00790
00791 for(std::deque<ardrone_autonomy::Navdata>::iterator cur = navInfoQueue.begin();
00792 cur != navInfoQueue.end();
00793 )
00794 {
00795 int curStampMs = getMS(cur->header.stamp);
00796
00797 if(curStampMs < (int)from-pressureAverageRange)
00798 cur = navInfoQueue.erase(cur);
00799 else
00800 {
00801 if(curStampMs >= (int)from-pressureAverageRange && curStampMs <= (int)from+pressureAverageRange)
00802 {
00803 sum_first += cur->pressure;
00804 num_first++;
00805 }
00806
00807 if(curStampMs >= (int)to-pressureAverageRange && curStampMs <= (int)to+pressureAverageRange)
00808 {
00809 sum_last += cur->pressure;
00810 num_last++;
00811 }
00812 cur++;
00813 }
00814 }
00815
00816 for(std::deque<ardrone_autonomy::Navdata>::iterator cur = navInfoQueue.begin();
00817 cur != navInfoQueue.end();
00818 cur++
00819 )
00820 {
00821 int frontStamp = getMS(cur->header.stamp);
00822 if(frontStamp < (int)from)
00823 {
00824
00825 skipped++;
00826 }
00827 else if(frontStamp >= (int)from && frontStamp <= (int)to)
00828 {
00829 if(firstAdded == 0)
00830 {
00831 firstAdded = frontStamp;
00832 firstZ = (cur->altd * 0.001) / sqrt(1.0 + (tan(cur->rotX * 3.14159268 / 180)*tan(cur->rotX * 3.14159268 / 180)) \
00833 + (tan(cur->rotY * 3.14159268 / 180)*tan(cur->rotY * 3.14159268 / 180)) );
00834
00835 if (! std::isfinite(firstZ))
00836 firstZ = cur->altd * 0.001;
00837
00838 predIMUOnlyForScale->z = firstZ;
00839 }
00840 lastAdded = frontStamp;
00841
00842 predIMUOnlyForScale->predictOneStep(&(*cur));
00843
00844
00845 used++;
00846 }
00847 else
00848 break;
00849
00850 }
00851
00852 predIMUOnlyForScale->z -= firstZ;
00853
00854 *zCorrupted = predIMUOnlyForScale->zCorrupted;
00855 *allCorrupted = abs(firstAdded - (int)from) + abs(lastAdded - (int)to) > 80;
00856 pthread_mutex_unlock(&navInfoQueueCS);
00857
00858 if(*allCorrupted)
00859 printf("scalePackage corrupted (imu data gap for %ims)\n",abs(firstAdded - (int)from) + abs(lastAdded - (int)to));
00860 else if(*zCorrupted)
00861 printf("scalePackage z corrupted (jump in meters: %.3f)!\n",predIMUOnlyForScale->zCorruptedJump);
00862
00863 printf("from: %u to: %u; first: %d last: %d firstZ %f => z alt diff: %f\n",
00864 from,
00865 to,
00866 firstAdded,
00867 lastAdded,
00868 firstZ,
00869 predIMUOnlyForScale->z
00870 );
00871
00872
00873 *out_end_pressure = sum_last/num_last;
00874 *out_start_pressure = sum_first/num_first;
00875
00876 return TooN::makeVector(predIMUOnlyForScale->x,predIMUOnlyForScale->y,predIMUOnlyForScale->z);
00877 }
00878
00879 void PTAMWrapper::newNavdata(ardrone_autonomy::Navdata* nav)
00880 {
00881 lastNavinfoReceived = *nav;
00882
00883 if(getMS(lastNavinfoReceived.header.stamp) > 2000000)
00884 {
00885 printf("PTAMSystem: ignoring navdata package with timestamp %f\n", lastNavinfoReceived.tm);
00886 return;
00887 }
00888 if(lastNavinfoReceived.header.seq > 2000000 || lastNavinfoReceived.header.seq < 0)
00889 {
00890 printf("PTAMSystem: ignoring navdata package with ID %i\n", lastNavinfoReceived.header.seq);
00891 return;
00892 }
00893
00894
00895 lastNavinfoReceived.rotZ = filter->getCurrentPose()[5];
00896
00897 pthread_mutex_lock( &navInfoQueueCS );
00898 navInfoQueue.push_back(lastNavinfoReceived);
00899
00900 if(navInfoQueue.size() > 1000)
00901 {
00902 navInfoQueue.pop_front();
00903 if(!navQueueOverflown)
00904 printf("NavQue Overflow detected!\n");
00905 navQueueOverflown = true;
00906 }
00907 pthread_mutex_unlock( &navInfoQueueCS );
00908
00909
00910
00911 imuOnlyPred->yaw = filter->getCurrentPose()[5];
00912 imuOnlyPred->predictOneStep(&lastNavinfoReceived);
00913 }
00914
00915 void PTAMWrapper::newImage(sensor_msgs::ImageConstPtr img)
00916 {
00917
00918
00919 cv_bridge::CvImagePtr cv_ptr = cv_bridge::toCvCopy(img, sensor_msgs::image_encodings::MONO8);
00920
00921
00922 boost::unique_lock<boost::mutex> lock(new_frame_signal_mutex);
00923
00924
00925 if(ros::Time::now() - img->header.stamp > ros::Duration(30.0))
00926 mimFrameTimeRos = (ros::Time::now()-ros::Duration(0.001));
00927 else
00928 mimFrameTimeRos = (img->header.stamp);
00929
00930 mimFrameTime = getMS(mimFrameTimeRos);
00931
00932
00933 mimFrameSEQ = img->header.seq;
00934
00935
00936
00937 if((int)(mimFrameBW.size().x) != img->width || (int)(mimFrameBW.size().y) != img->height)
00938 mimFrameBW.resize(CVD::ImageRef(img->width, img->height));
00939
00940 memcpy(mimFrameBW.data(),cv_ptr->image.data,img->width * img->height);
00941 newImageAvailable = true;
00942
00943 lock.unlock();
00944 new_frame_signal.notify_all();
00945 }
00946
00947
00948
00949 void PTAMWrapper::on_key_down(int key)
00950 {
00951 if(key == 114)
00952 {
00953 node->publishCommand("p reset");
00954 }
00955 if(key == 117)
00956 {
00957 node->publishCommand("p toggleUI");
00958 }
00959 if(key == 32)
00960 {
00961 node->publishCommand("p space");
00962 }
00963 if(key == 107)
00964 {
00965 node->publishCommand("p keyframe");
00966 }
00967 if(key == 108)
00968 {
00969 node->publishCommand("toggleLog");
00970 }
00971 if(key == 115)
00972 {
00973 pthread_mutex_lock(&logScalePairs_CS);
00974 if(logfileScalePairs == 0)
00975 {
00976 logfileScalePairs = new std::ofstream();
00977 logfileScalePairs->open ("logScalePairs.txt");
00978 printf("\nSTART logging scale pairs\n\n");
00979 }
00980 else
00981 {
00982 logfileScalePairs->flush();
00983 logfileScalePairs->close();
00984 delete logfileScalePairs;
00985 logfileScalePairs = NULL;
00986 printf("\nEND logging scale pairs\n\n");
00987 }
00988 pthread_mutex_unlock(&logScalePairs_CS);
00989 }
00990
00991 if(key == 109)
00992 {
00993 node->publishCommand("p toggleLockMap");
00994 }
00995
00996 if(key == 110)
00997 {
00998
00999 node->publishCommand("p toggleLockSync");
01000 }
01001
01002 if(key == 116)
01003 {
01004
01005 flushMapKeypoints = true;
01006 }
01007
01008 }
01009
01010
01011
01012 bool PTAMWrapper::handleCommand(std::string s)
01013 {
01014 if(s.length() == 5 && s.substr(0,5) == "space")
01015 {
01016 if (mpTracker == 0) {
01017 ROS_INFO("Haven't received the first video frame yet, can't start the tracker");
01018 return true;
01019 }
01020 mpTracker->pressSpacebar();
01021 }
01022
01023
01024 if(s.length() == 5 && s.substr(0,5) == "reset")
01025 {
01026
01027 Reset();
01028
01029 }
01030
01031 if(s.length() == 8 && s.substr(0,8) == "keyframe")
01032 {
01033 forceKF = true;
01034 }
01035
01036 if(s.length() == 8 && s.substr(0,8) == "toggleUI")
01037 {
01038 if(drawUI == UI_NONE) drawUI = UI_DEBUG;
01039 else if(drawUI == UI_DEBUG) drawUI = UI_PRES;
01040 else if(drawUI == UI_PRES) drawUI = UI_NONE;
01041 else drawUI = UI_PRES;
01042 }
01043
01044 if(s.length() == 11 && s.substr(0,11) == "lockScaleFP")
01045 {
01046 lockNextFrame = true;
01047 }
01048
01049 if(s.length() == 13 && s.substr(0,13) == "toggleLockMap")
01050 {
01051 mapLocked = !mapLocked;
01052
01053
01054 if(mapLocked)
01055 {
01056 node->publishCommand("u l PTAM map locked.");
01057 printf("\n\nMAP LOCKED!\n\n\n");
01058 }
01059 else
01060 {
01061 printf("\n\nMAP UNLOCKED!\n\n\n");
01062 node->publishCommand("u l PTAM map UNlocked.");
01063 }
01064 }
01065
01066 if(s.length() == 14 && s.substr(0,14) == "toggleLockSync")
01067 {
01068 filter->allSyncLocked = !filter->allSyncLocked;
01069
01070
01071 if(filter->allSyncLocked)
01072 {
01073 printf("\n\nSYNC LOCKED!\n\n\n");
01074 node->publishCommand("u l PTAM sync locked.");
01075 }
01076 else
01077 {
01078 printf("\n\nSYNC UNLOCKED!\n\n\n");
01079 node->publishCommand("u l PTAM sync UNlocked.");
01080 }
01081 }
01082
01083 return true;
01084 }
01085
01086 void PTAMWrapper::on_mouse_down(CVD::ImageRef where, int state, int button)
01087 {
01088 double x = 4*(where.x/(double)this->myGLWindow->size().x - 0.5);
01089 double y = -4*(where.y/(double)this->myGLWindow->size().y - 0.5);
01090 char bf[100];
01091
01092
01093 node->publishCommand("c clearCommands");
01094 node->publishCommand("c lockScaleFP");
01095
01096 if(button == 1)
01097 snprintf(bf,100,"c moveByRel %.3f %.3f 0 0",x,y);
01098 else
01099 snprintf(bf,100,"c moveByRel 0 0 %.3f %.3f",y,x*45);
01100
01101 node->publishCommand(bf);
01102 }