00001
00005 #include "monoslam.hpp"
00006
00007 struct timeval cycle_timer;
00008
00009
00010 int main(int argc, char** argv) {
00011
00012 ROS_INFO("Node launched.");
00013
00014 ros::init(argc, argv, "thermal_slam");
00015
00016 ros::NodeHandle private_node_handle("~");
00017
00018 slamData startupData;
00019
00020 bool inputIsValid = startupData.obtainStartingData(private_node_handle);
00021
00022 startupData.read_addr = argv[0];
00023 startupData.read_addr = startupData.read_addr.substr(0, startupData.read_addr.size()-12);
00024
00025 if (!inputIsValid) {
00026 ROS_INFO("Configuration invalid.");
00027 }
00028
00029 ROS_INFO("Startup data processed.");
00030
00031
00032
00033 ros::NodeHandle nh;
00034
00035 boost::shared_ptr < slamNode > slam_node (new slamNode (nh, startupData));
00036
00037 globalNodePtr = &slam_node;
00038
00039 signal(SIGINT, mySigintHandler);
00040
00041 ROS_INFO("Node configured.");
00042
00043 ros::AsyncSpinner spinner(2);
00044
00045 spinner.start();
00046
00047 ros::waitForShutdown();
00048
00049 ROS_INFO("Exiting.");
00050
00051 return 0;
00052
00053 }
00054
00055 void slamNode::processScorecard() {
00056
00057
00058
00059 if ((configData.initializationScorecard[0] == '.') && (configData.initializationScorecard[1] == '.')) {
00060 configData.initializationScorecard = configData.read_addr + "nodes/monoslam/config/" + configData.initializationScorecard;
00061 }
00062
00063
00064
00065 ifstream ifs(configData.initializationScorecard.c_str());
00066
00067 for (int iii = 0; iii < INITIALIZATION_SCORING_PARAMETERS; iii++) {
00068 ifs >> scorecardParams[iii][0];
00069 }
00070
00071 for (int iii = 0; iii < INITIALIZATION_SCORING_PARAMETERS; iii++) {
00072 ifs >> scorecardParams[iii][1];
00073 }
00074
00075 for (int iii = 0; iii < INITIALIZATION_SCORING_PARAMETERS; iii++) {
00076 ifs >> scorecardParams[iii][2];
00077 }
00078
00079 ifs.close();
00080
00081 for (int iii = 0; iii < INITIALIZATION_SCORING_PARAMETERS; iii++) {
00082 ROS_INFO("Criteria (%d) = (%f, %f, %f)", iii, scorecardParams[iii][0], scorecardParams[iii][1], scorecardParams[iii][2]);
00083 }
00084
00085 }
00086
00087 bool slamData::obtainStartingData(ros::NodeHandle& nh) {
00088
00089 nh.param<std::string>("stream", stream, "null");
00090
00091 if (stream != "null") {
00092 ROS_INFO("Tracker stream (%s) selected.", stream.c_str());
00093 } else {
00094 ROS_ERROR("No tracker stream specified.");
00095 return false;
00096 }
00097
00098 nh.param<bool>("logErrors", logErrors, true);
00099
00100 nh.param<bool>("keyframeEvaluationMode", keyframeEvaluationMode, false);
00101
00102 nh.param<int>("maxTestsPerFrame", maxTestsPerFrame, 10);
00103
00104 nh.param<int>("maxInitializationFrames", maxInitializationFrames, 30);
00105
00106 nh.param<int>("minStartingSeparation", minStartingSeparation, 4);
00107 nh.param<int>("maxStartingSeparation", maxStartingSeparation, 12);
00108
00109
00110 nh.param<string>("initializationScorecard", initializationScorecard, "../config/default_scorecard.txt");
00111
00112 return true;
00113 }
00114
00115 bool slamNode::checkForKeyframe() {
00116 unsigned int image_idx_2 = currentPoseIndex + 1;
00117 unsigned int previousKeyframe = keyframe_store.keyframes.at(keyframe_store.keyframes.size()-1).idx;
00118 bool keyframeAdded = false;
00119 bool hasReverted = false;
00120
00121
00122 if (keyframe_store.keyframes.at(keyframe_store.keyframes.size()-1).idx != image_idx_2) {
00123
00124 vector<unsigned int> tempIndices, maintainedIndices;
00125
00126 getActiveTracks(tempIndices, featureTrackVector, previousKeyframe, image_idx_2);
00127 filterToCompleteTracks(maintainedIndices, tempIndices, featureTrackVector, previousKeyframe, image_idx_2);
00128
00129 double motionScore = getFeatureMotion(featureTrackVector, maintainedIndices, previousKeyframe, image_idx_2);
00130
00131 vector<unsigned int> untriangulatedIndices;
00132 unsigned int trackedSinceLast = maintainedIndices.size();
00133 reduceActiveToTriangulated(featureTrackVector, maintainedIndices, untriangulatedIndices);
00134
00135
00136
00137 bool lowProportionTracked = false;
00138 if (trackedSinceLast < ((unsigned int) (((double) startingTracksCount) * configData.requiredTrackFrac))) {
00139 lowProportionTracked = true;
00140
00141 }
00142
00143
00144
00145 if (motionScore > configData.motionThreshold) {
00146 keyframe_store.addKeyframe(image_idx_2-1, blank);
00147 keyframeAdded = true;
00148 currentPoseIndex--;
00149 hasReverted = true;
00150
00151 } else if ((image_idx_2 - previousKeyframe) == configData.maxKeyframeSeparation) {
00152 keyframe_store.addKeyframe(image_idx_2, blank);
00153 keyframeAdded = true;
00154
00155 } else if (lowProportionTracked && (((int)trackedSinceLast) < configData.minTrackedFeatures) && (keyframe_store.keyframes.at(keyframe_store.keyframes.size()-1).idx != (image_idx_2-1))) {
00156
00157
00158 keyframe_store.addKeyframe(image_idx_2-1, blank);
00159 currentPoseIndex--;
00160 hasReverted = true;
00161
00162 keyframeAdded = true;
00163
00164
00165
00166
00167 } else if (lowProportionTracked && (((int)trackedSinceLast) < configData.minTrackedFeatures)) {
00168 keyframe_store.addKeyframe(image_idx_2, blank);
00169 keyframeAdded = true;
00170
00171
00172
00173
00174
00175 } else if ((((int)maintainedIndices.size()) < configData.min3dPtsForPnP) && (keyframe_store.keyframes.at(keyframe_store.keyframes.size()-1).idx != (image_idx_2-1))) {
00176
00177 keyframe_store.addKeyframe(image_idx_2-1, blank);
00178 currentPoseIndex--;
00179 hasReverted = true;
00180 keyframeAdded = true;
00181
00182
00183 } else if (((int)maintainedIndices.size()) < configData.min3dPtsForPnP) {
00184
00185
00186 }
00187
00188 } else {
00189
00190 }
00191
00192 return hasReverted;
00193
00194 if (hasReverted) {
00195
00196 return true;
00197 }
00198
00199 if (keyframeAdded) {
00200 ROS_INFO("Added frame (%d) as Keyframe [%d]", keyframe_store.keyframes.at(keyframe_store.keyframes.size()-1).idx, currentPoseIndex);
00201
00202 } else {
00203
00204
00205
00206 }
00207
00208 return false;
00209 }
00210
00211 void slamNode::show_poses() {
00212
00213 for (int iii = 0; iii < currentPoseIndex; iii++) {
00214 if (ACM[iii].rows == 4) {
00215
00216 cv::Mat temp;
00217
00218 estimatePoseFromKnownPoints(temp, configData.cameraData, featureTrackVector, iii, eye4);
00219
00220 ROS_INFO("EST[%d] = ", iii);
00221 cout << temp << endl;
00222
00223 estimatePoseFromKnownPoints(temp, configData.cameraData, featureTrackVector, iii, ACM[iii]);
00224
00225 ROS_INFO("ES2[%d] = ", iii);
00226 cout << temp << endl;
00227
00228 ROS_INFO("ACM[%d] = ", iii);
00229 cout << ACM[iii] << endl;
00230 }
00231 }
00232
00233 }
00234
00235 void slamNode::getGuidingPose(cv::Mat *srcs, cv::Mat& dst, unsigned int idx) {
00236
00237 cv::Mat eye4 = cv::Mat::eye(4, 4, CV_64FC1);
00238
00239 unsigned int maxGuides = std::min(((int) idx), configData.maxGuides);
00240
00241 if (srcs[idx].rows == 4) {
00242
00243 srcs[idx].copyTo(dst);
00244 } else if (idx == 0) {
00245
00246 eye4.copyTo(dst);
00247 } else if (srcs[idx-1].rows != 4) {
00248
00249 eye4.copyTo(dst);
00250 } else {
00251
00252
00253
00254
00255 cv::Mat R_dev, t_dev;
00256 R_dev = cv::Mat::zeros(3, 1, CV_64FC1);
00257 t_dev = cv::Mat::zeros(3, 1, CV_64FC1);
00258
00259 double total_contrib = 0.0;
00260
00261 for (unsigned int iii = idx-maxGuides; iii < idx-1; iii++) {
00262
00263 double contrib = ((double) idx) - ((double) iii);
00264 total_contrib += contrib;
00265
00266
00267
00268
00269
00270 cv::Mat R1, R2, t1, t2, rv1, rv2, rd, td;
00271
00272
00273 decomposeTransform(srcs[iii], R1, t1);
00274 Rodrigues(R1, rv1);
00275 decomposeTransform(srcs[iii+1], R2, t2);
00276 Rodrigues(R2, rv2);
00277
00278
00279 rd = rv2-rv1;
00280
00281
00282 for (unsigned int jjj = 0; jjj < 3; jjj++) {
00283
00284 while (rd.at<double>(jjj, 0) > M_PI) {
00285 rd.at<double>(jjj, 0) -= 2*M_PI;
00286 }
00287
00288 while (rd.at<double>(jjj, 0) < -M_PI) {
00289 rd.at<double>(jjj, 0) += 2*M_PI;
00290 }
00291 }
00292
00293
00294
00295 td = t2-t1;
00296
00297
00298
00299
00300 R_dev += pow(0.5, contrib) * rd;
00301 t_dev += pow(0.5, contrib) * td;
00302
00303 }
00304
00305
00306 R_dev /= total_contrib;
00307 t_dev /= total_contrib;
00308
00309
00310
00311
00312
00313 cv::Mat R_n, t_n, rv_n;
00314 decomposeTransform(srcs[idx-1], R_n, t_n);
00315 Rodrigues(R_n, rv_n);
00316
00317 rv_n += R_dev;
00318 Rodrigues(rv_n, R_n);
00319 t_n += t_dev;
00320
00321
00322
00323
00324 cv::Mat T_n;
00325 composeTransform(R_n, t_n, T_n);
00326 transformationToProjection(T_n, dst);
00327
00328
00329
00330
00331 }
00332 }
00333
00334 void mySigintHandler(int sig)
00335 {
00336 wantsToShutdown = true;
00337 ROS_WARN("Requested shutdown... terminating feeds...");
00338
00339 (*globalNodePtr)->prepareForTermination();
00340 }
00341
00342 void slamNode::estimatePose(vector<unsigned int>& basisNodes, unsigned int idx) {
00343
00344
00345
00346
00347
00348 if (ACM[idx].rows != 4) {
00349
00350 if (configData.timeDebug) poseEstimationTime.startRecording();
00351
00352 cv::Mat guidePose;
00353 getGuidingPose(ACM, guidePose, idx);
00354
00355
00356
00357
00358
00359 estimatePoseFromKnownPoints(ACM[idx], configData.cameraData, featureTrackVector, idx, guidePose);
00360
00361
00362 if (configData.timeDebug) poseEstimationTime.stopRecording();
00363
00364 if (ACM[idx-1].rows != 4) {
00365
00366
00367 } else {
00368
00369
00370
00371
00372
00373 }
00374
00375 } else {
00376
00377
00378
00379 }
00380
00381
00382
00383
00384
00385 if (1) {
00386 double avgError;
00387
00388 if (configData.timeDebug) bundleAdjustmentTime.startRecording();
00389 if (basisNodes.size() <= ((unsigned int) (configData.adjustmentFrames/2))) {
00390
00391 avgError = keyframeBundleAdjustment(configData.cameraData, featureTrackVector, ACM, basisNodes, configData.poseEstimateIterations, false, false, 1);
00392 } else if (basisNodes.size()-configData.flowback > 0) {
00393
00394
00395
00396
00397 avgError = keyframeBundleAdjustment(configData.cameraData, featureTrackVector, ACM, basisNodes, configData.poseEstimateIterations, false, false, basisNodes.size()-configData.flowback);
00398 } else {
00399
00400 avgError = keyframeBundleAdjustment(configData.cameraData, featureTrackVector, ACM, basisNodes, configData.poseEstimateIterations, false, false, 1);
00401 }
00402 if (configData.timeDebug) bundleAdjustmentTime.stopRecording();
00403
00404
00405
00406
00407 if (configData.logErrors) {
00408 error_file << idx << " " << avgError << endl;
00409 }
00410 }
00411
00412 }
00413
00414 void slamNode::getBasisNodes(vector<unsigned int>& basisNodes, unsigned int idx) {
00415
00416
00417
00418 basisNodes.clear();
00419
00420 if (idx < keyframe_store.keyframes.at(0).idx) {
00421 ROS_WARN("ERROR! IDX too low (%d / %d)", idx, keyframe_store.keyframes.at(0).idx);
00422 return;
00423 }
00424
00425 int activeCameras = ((int) idx) + 1 - ((int) keyframe_store.keyframes.at(0).idx);
00426
00427 if (activeCameras < 2) {
00428 return;
00429 }
00430
00431
00432
00433 if (activeCameras <= configData.adjustmentFrames) {
00434
00435
00436
00437 unsigned int firstNode = keyframe_store.keyframes.at(0).idx;
00438
00439 for (unsigned int iii = firstNode; iii <= idx; iii++) {
00440 basisNodes.push_back(iii);
00441 }
00442
00443
00444
00445
00446 } else {
00447
00448
00449
00450
00451
00452
00453
00454
00455 unsigned int surplus = activeCameras - configData.adjustmentFrames;
00456 unsigned int spread = surplus / configData.keyframeSpacing;
00457
00458 spread = std::min(spread, ((unsigned int) (configData.adjustmentFrames-configData.flowback)));
00459
00460
00461
00462
00463 unsigned int starting_cam = idx - configData.adjustmentFrames + spread + 2;
00464 starting_cam = starting_cam - (starting_cam % configData.keyframeSpacing);
00465 starting_cam -= configData.keyframeSpacing*(spread-1);
00466
00467
00468
00469
00470
00471 for (unsigned int iii = starting_cam; iii < (idx - configData.adjustmentFrames + spread); iii += configData.keyframeSpacing) {
00472
00473 basisNodes.push_back(iii);
00474
00475 }
00476
00477
00478
00479
00480 starting_cam = idx - configData.adjustmentFrames + 1 + spread + 1;
00481 for (unsigned int iii = starting_cam; iii <= idx; iii++) {
00482
00483 basisNodes.push_back(iii);
00484 }
00485
00486
00487
00488 }
00489
00490
00491
00492 }
00493
00494 void slamNode::processNextFrame() {
00495
00496
00497
00498
00499
00500
00501
00502 if (!matricesAreEqual(ACM[keyframe_store.keyframes.at(0).idx], eye4)) {
00503
00504 while (1) {}
00505 }
00506
00507 vector<unsigned int> basisNodes;
00508
00509
00510
00511 if (1) {
00512
00513 if (configData.timeDebug) triangulationTime.startRecording();
00514 unsigned int triangulationIndex = currentPoseIndex-configData.flowback;
00515
00516 ROS_INFO("Getting basis nodes...");
00517 getBasisNodes(basisNodes, triangulationIndex);
00518
00519 if (basisNodes.size() > 0) {
00520
00521 ROS_INFO("Finding relevant indices...");
00522
00523 vector<unsigned int> triangulatedIndices, untriangulatedIndices;
00524 findRelevantIndices(featureTrackVector, triangulatedIndices, untriangulatedIndices, basisNodes.at(0), triangulationIndex);
00525
00526
00527 if (untriangulatedIndices.size() > 0) {
00528
00529 vector<unsigned int> triangulatableIndices;
00530 findTriangulatableTracks3(featureTrackVector, triangulatableIndices, triangulationIndex, configData.framesForTriangulation);
00531
00532 if (triangulatableIndices.size() > 0) {
00533
00534 triangulateTracks(featureTrackVector, triangulatableIndices, configData.cameraData, ACM, basisNodes.at(0), triangulationIndex);
00535
00536
00537
00538
00539 if (currentPoseIndex > 60) {
00540
00541 }
00542
00543 }
00544
00545
00546 }
00547
00548 if (configData.timeDebug) triangulationTime.stopRecording();
00549
00550
00551 ROS_INFO("Performing adjustment... (%d)", ((int)basisNodes.size()));
00552
00553 for (unsigned int iii = 0; iii < basisNodes.size(); iii++) {
00554
00555 }
00556
00557 for (unsigned int iii = 0; iii < featureTrackVector.size(); iii++) {
00558
00559 if (featureTrackVector.at(iii).locations.size() > 0) {
00560
00561 }
00562
00563 }
00564
00565 if (configData.timeDebug) bundleAdjustmentTime.startRecording();
00566 double avgError = keyframeBundleAdjustment(configData.cameraData, featureTrackVector, ACM, basisNodes, configData.keyframeIterations, false, false, basisNodes.size());
00567 ROS_INFO("F(%d) Adjustment error with newly triangulated points = %f (k = %d)", currentPoseIndex, avgError, ((int)basisNodes.size()));
00568 if (configData.timeDebug) bundleAdjustmentTime.stopRecording();
00569 }
00570
00571
00572 }
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585 ROS_INFO("Getting more basis nodes...");
00586 getBasisNodes(basisNodes, currentPoseIndex);
00587 ROS_INFO("Estimating pose...");
00588 estimatePose(basisNodes, currentPoseIndex);
00589
00590 if (configData.timeDebug) {
00591 if ((currentPoseIndex % configData.timeSpacing) == 0) {
00592
00593 trackHandlingTime.calcParameters();
00594 triangulationTime.calcParameters();
00595 poseEstimationTime.calcParameters();
00596 bundleAdjustmentTime.calcParameters();
00597 ROS_WARN("Showing timing summary:");
00598 ROS_INFO("Track summary: (%d, %f, %f)", trackHandlingTime.cycles, trackHandlingTime.average * ((double) trackHandlingTime.cycles) / ((double) currentPoseIndex), trackHandlingTime.sigma* ((double) trackHandlingTime.cycles) / ((double) currentPoseIndex));
00599 ROS_INFO("Triangulation summary: (%d, %f, %f)", triangulationTime.cycles, triangulationTime.average* ((double) triangulationTime.cycles) / ((double) currentPoseIndex), triangulationTime.sigma* ((double) triangulationTime.cycles) / ((double) currentPoseIndex));
00600 ROS_INFO("Pose summary: (%d, %f, %f)", poseEstimationTime.cycles, poseEstimationTime.average* ((double) poseEstimationTime.cycles) / ((double) currentPoseIndex), poseEstimationTime.sigma* ((double) poseEstimationTime.cycles) / ((double) currentPoseIndex));
00601 ROS_INFO("Bundle summary: (%d, %f, %f)", bundleAdjustmentTime.cycles, bundleAdjustmentTime.average* ((double) bundleAdjustmentTime.cycles) / ((double) currentPoseIndex), bundleAdjustmentTime.sigma* ((double) bundleAdjustmentTime.cycles) / ((double) currentPoseIndex));
00602
00603 }
00604 }
00605
00606
00607 if (1) {
00608 update_display();
00609 currentPoseIndex++;
00610 return;
00611 }
00612
00613 if (0) {
00614 vector<unsigned int> triangulatedIndices, untriangulatedIndices;
00615 findRelevantIndices(featureTrackVector, triangulatedIndices, untriangulatedIndices, keyframe_store.keyframes.at(0).idx, currentPoseIndex);
00616
00617
00618 if (untriangulatedIndices.size() > 0) {
00619
00620 vector<unsigned int> triangulatableIndices;
00621 findTriangulatableTracks3(featureTrackVector, triangulatableIndices, currentPoseIndex, configData.framesForTriangulation);
00622
00623 if (triangulatableIndices.size() > 0) {
00624
00625 triangulateTracks(featureTrackVector, triangulatableIndices, configData.cameraData, ACM, keyframe_store.keyframes.at(0).idx, currentPoseIndex);
00626 double avgError = keyframeBundleAdjustment(configData.cameraData, featureTrackVector, ACM, basisNodes, configData.keyframeIterations, false, false, basisNodes.size()-3);
00627 if (configData.verboseMode) { ROS_INFO("F(%d) Adjustment error with newly triangulated points = %f (k = %d)", currentPoseIndex, avgError, ((int)basisNodes.size())); };
00628 }
00629
00630
00631 }
00632 }
00633
00634
00635
00636
00637 if (checkForKeyframe()) {
00638
00639 if ((currentPoseIndex+1) == keyframe_store.keyframes.at(keyframe_store.keyframes.size()-1).idx) {
00640
00641
00642 } else {
00643
00644 update_display();
00645 currentPoseIndex++;
00646 return;
00647 }
00648
00649
00650 } else {
00651
00652 if ((currentPoseIndex+1) == keyframe_store.keyframes.at(keyframe_store.keyframes.size()-1).idx) {
00653
00654
00655 basisNodes.clear();
00656 getBasisNodes(basisNodes, currentPoseIndex+1);
00657 estimatePose(basisNodes, currentPoseIndex+1);
00658 } else {
00659
00660 update_display();
00661 currentPoseIndex++;
00662 return;
00663 }
00664
00665 }
00666
00667 if (0) {
00668 update_display();
00669 currentPoseIndex++;
00670 return;
00671 }
00672
00673
00674
00675
00676 unsigned int image_idx_1 = keyframe_store.keyframes.at(keyframe_store.keyframes.size()-2).idx;
00677 unsigned int image_idx_2 = keyframe_store.keyframes.at(keyframe_store.keyframes.size()-1).idx;
00678
00679
00680
00681 vector<cv::Point2f> pts1, pts2;
00682 vector<cv::Point3f> objectPoints;
00683 getTriangulatedFullSpanPoints(featureTrackVector, pts1, pts2, image_idx_1, image_idx_2, objectPoints);
00684
00685
00686
00687
00688
00689 vector<unsigned int> adjustableKeyframeIndices;
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700 vector<unsigned int> keyframe_indices, tmp_indices, subseq_indices;
00701
00702 for (unsigned int iii = 0; iii < keyframe_store.keyframes.size()-1; iii++) {
00703 keyframe_indices.push_back(keyframe_store.keyframes.at(iii).idx);
00704 }
00705
00706
00707
00708 while (keyframe_indices.size() > (configData.adjustmentFrames / 2)) {
00709 keyframe_indices.erase(keyframe_indices.begin());
00710 }
00711
00712 for (int iii = keyframe_store.keyframes.at(keyframe_store.keyframes.size()-1).idx+1; iii < currentPoseIndex+1; iii++) {
00713 tmp_indices.push_back(iii);
00714 }
00715
00716
00717
00718 randomSelection(tmp_indices, subseq_indices, (configData.adjustmentFrames / 2));
00719
00720
00721
00722
00723 adjustableKeyframeIndices.insert(adjustableKeyframeIndices.end(), keyframe_indices.begin(), keyframe_indices.end());
00724 adjustableKeyframeIndices.insert(adjustableKeyframeIndices.end(), subseq_indices.begin(), subseq_indices.end());
00725 adjustableKeyframeIndices.push_back(image_idx_2);
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745 if (ACM[currentPoseIndex+2].rows == 4) {
00746
00747 }
00748
00749
00750
00751 if (0) {
00752 update_display();
00753 currentPoseIndex++;
00754 return;
00755 }
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770 vector<unsigned int> triangulatedIndices, untriangulatedIndices;
00771
00772
00773
00774 findRelevantIndices(featureTrackVector, triangulatedIndices, untriangulatedIndices, image_idx_1, image_idx_2);
00775
00776
00777
00778
00779 if (untriangulatedIndices.size() > 0) {
00780
00781 vector<unsigned int> triangulatableIndices;
00782 findTriangulatableTracks3(featureTrackVector, triangulatableIndices, image_idx_2, configData.framesForTriangulation);
00783
00784 if (triangulatableIndices.size() > 0) {
00785
00786 triangulateTracks(featureTrackVector, triangulatableIndices, configData.cameraData, ACM, image_idx_1, image_idx_2);
00787
00788
00789 }
00790
00791
00792 }
00793
00794 if (1) {
00795 update_display();
00796 currentPoseIndex++;
00797 return;
00798 }
00799
00800 ROS_INFO("Establishing new adjustment indices...");
00801
00802 vector<unsigned int> newAdjustmentIndices;
00803 for (unsigned int iii = 0; iii < keyframe_store.keyframes.size(); iii++) {
00804
00805 newAdjustmentIndices.push_back(keyframe_store.keyframes.at(iii).idx);
00806
00807 if (keyframe_store.keyframes.at(iii).idx == image_idx_1) {
00808 for (unsigned int jjj = image_idx_1+1; jjj < image_idx_2; jjj++) {
00809 newAdjustmentIndices.push_back(jjj);
00810 }
00811 }
00812 }
00813
00814 update_display();
00815 currentPoseIndex++;
00816 }
00817
00818 void slamNode::update_display() {
00819
00820 if (currentPoseIndex != -1) {
00821 if (ACM[currentPoseIndex].rows == 4) {
00822 assignPose(currentPose, ACM[currentPoseIndex]);
00823 pose_pub.publish(currentPose);
00824 }
00825
00826 vector<unsigned int> displayIndices;
00827 for (int iii = 0; iii <= currentPoseIndex; iii++) {
00828 if (ACM[iii].rows == 4) {
00829 displayIndices.push_back(iii);
00830 }
00831 }
00832
00833 for (unsigned int iii = 0; iii < displayIndices.size(); iii++) {
00834
00835 }
00836
00837 assignPartialSystem(display_sys, featureTrackVector, configData.cameraData, ACM, displayIndices, false);
00838
00839
00840
00841 } else {
00842 assignPose(currentPose, eye4);
00843 pose_pub.publish(currentPose);
00844
00845 display_sys.nodes.clear();
00846 display_sys.tracks.clear();
00847 }
00848
00849 drawGraph2(display_sys, camera_pub, points_pub, path_pub, decimation, bicolor);
00850
00851
00852 }
00853
00854 void slamNode::update_cameras_to_pnp() {
00855
00856 #pragma omp parallel for
00857 for (int iii = 0; iii < currentPoseIndex; iii++) {
00858 if (ACM[iii].rows == 4) {
00859 estimatePoseFromKnownPoints(ACM[iii], configData.cameraData, featureTrackVector, iii, eye4);
00860 }
00861 }
00862
00863 }
00864
00865 void slamNode::handle_tracks(const thermalvis::feature_tracksConstPtr& msg) {
00866
00867 if (configData.verboseMode) { ROS_INFO("Handling projections (%d)...", msg->projection_count); }
00868
00869 if (!infoProcessed) {
00870
00871 }
00872
00873 if (msg->indices.size() == 0) {
00874 ROS_WARN("No new tracks.");
00875 return;
00876 }
00877
00878
00879
00880 if (configData.timeDebug) trackHandlingTime.startRecording();
00881
00882 main_mutex.lock();
00883
00884 featureTrack blankTrack;
00885
00886
00887
00888 unsigned int newest_track = 0;
00889
00890 for (unsigned int iii = 0; iii < msg->projection_count; iii++) {
00891
00892
00893
00894 if (msg->indices[iii] > newest_track) {
00895 newest_track = msg->indices[iii];
00896 }
00897
00898 }
00899
00900
00901
00902 if (newest_track >= featureTrackVector.size()) {
00903 for (unsigned int iii = featureTrackVector.size(); iii <= newest_track; iii++) {
00904 featureTrackVector.push_back(blankTrack);
00905 }
00906 }
00907
00908
00909
00910 for (unsigned int iii = 0; iii < msg->projection_count; iii++) {
00911
00912 bool alreadyAdded = false;
00913
00914
00915
00916 if (((int) msg->cameras.at(iii)) > latestFrame) {
00917 latestFrame = msg->cameras.at(iii);
00918 }
00919
00920
00921
00922
00923 for (unsigned int jjj = 0; jjj < featureTrackVector.at(msg->indices.at(iii)).locations.size(); jjj++) {
00924
00925
00926
00927 if (featureTrackVector.at(msg->indices.at(iii)).locations.at(jjj).imageIndex == ((int) msg->cameras.at(iii))) {
00928
00929 alreadyAdded = true;
00930 break;
00931 }
00932
00933
00934
00935 }
00936
00937 if (!alreadyAdded) {
00938
00939
00940 cv::Point2f proj(((float) msg->projections_x.at(iii)), ((float) msg->projections_y.at(iii)));
00941
00942 indexedFeature newFeature(msg->cameras.at(iii), proj);
00943
00944 featureTrackVector.at(msg->indices.at(iii)).addFeature(newFeature);
00945
00946
00947 }
00948
00949 }
00950
00951 cv::Mat trackMatrix;
00952
00953 if (0) {
00954 if (featureTrackVector.size() > 0) {
00955
00956 if (createTrackMatrix(featureTrackVector, trackMatrix)) {
00957
00958 cv::imshow("trackMatrix_received", trackMatrix);
00959 cv::waitKey(1);
00960 }
00961
00962 }
00963 }
00964
00965
00966
00967
00968 if (configData.timeDebug) trackHandlingTime.stopRecording();
00969
00970
00971
00972
00973 main_mutex.unlock();
00974 }
00975
00976 void slamNode::main_loop(const ros::TimerEvent& event) {
00977
00978 if (configData.keyframeEvaluationMode && evaluationCompleted) {
00979 return;
00980 }
00981
00982 if (firstIteration) {
00983 main_mutex.lock();
00984 update_display();
00985 main_mutex.unlock();
00986 firstIteration = false;
00987 }
00988
00989 if (!infoProcessed) {
00990
00991 return;
00992 }
00993
00994 if (!structureValid) {
00995 if ((!configData.keyframeEvaluationMode) || (latestFrame >= configData.maxInitializationFrames)) {
00996 main_mutex.lock();
00997 structureValid = findStartingFrames();
00998 main_mutex.unlock();
00999 return;
01000 } else if (!f1 && configData.keyframeEvaluationMode) {
01001 f1 = true;
01002 ROS_INFO("Waiting for sufficient frames for evaluation...");
01003 }
01004
01005 }
01006
01007 if (!structureValid) {
01008 return;
01009 } else if (!structureFormed) {
01010 main_mutex.lock();
01011 structureFormed = formInitialStructure();
01012 putativelyEstimatedFrames = currentPoseIndex-1;
01013 main_mutex.unlock();
01014 }
01015
01016 if (!structureFormed) {
01017 return;
01018 }
01019
01020
01021
01022
01023
01024 while (currentPoseIndex < latestFrame) {
01025 main_mutex.lock();
01026
01027 processNextFrame();
01028
01029 if (currentPoseIndex == ((int) keyframe_store.keyframes.at(keyframe_store.keyframes.size()-1).idx)) {
01030
01031 }
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049 main_mutex.unlock();
01050 }
01051
01052 if (keyframe_store.keyframes.size() > 3) {
01053
01054
01055
01056 }
01057
01058
01059
01060
01061
01062
01063
01064 if (0) {
01065
01066
01067
01068 if (keyframe_store.keyframes.size() > 2) {
01069
01070 unsigned int starting_cam = keyframe_store.keyframes.at(0).idx;
01071
01072 vector<unsigned int> allIndices;
01073 for (int iii = starting_cam; iii <= currentPoseIndex; iii++) {
01074 if (ACM[iii].rows == 4) {
01075 allIndices.push_back(iii);
01076 }
01077 }
01078
01079 double avgError;
01080
01081 ROS_INFO("About to full-system adjust (%d)", currentPoseIndex);
01082
01083 avgError = keyframeBundleAdjustment(configData.cameraData, featureTrackVector, ACM, allIndices, 5, true);
01084
01085 ROS_INFO("Full-system (%d) adjustment error = %f (k = %d)", currentPoseIndex, avgError, ((int)allIndices.size()));
01086
01087
01088
01089
01090
01091
01092 update_display();
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123 }
01124
01125
01126
01127
01128 }
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146 }
01147
01148 void slamNode::handle_info(const sensor_msgs::CameraInfoConstPtr& info_msg) {
01149
01150
01151
01152 drawGraph2(display_sys, camera_pub, points_pub, path_pub, decimation, bicolor);
01153
01154 if (!infoProcessed) {
01155
01156 ROS_INFO("Handling camera info.");
01157
01158 try {
01159
01160 configData.cameraData.K = cv::Mat::eye(3, 3, CV_64FC1);
01161
01162 for (unsigned int mmm = 0; mmm < 3; mmm++) {
01163 for (unsigned int nnn = 0; nnn < 3; nnn++) {
01164 configData.cameraData.K.at<double>(mmm, nnn) = info_msg->K[3*mmm + nnn];
01165 }
01166 }
01167
01168 cout << configData.cameraData.K << endl;
01169
01170
01171
01172 configData.cameraData.K_inv = configData.cameraData.K.inv();
01173
01174
01175
01176 configData.cameraData.cameraSize.width = info_msg->width;
01177 configData.cameraData.cameraSize.height = info_msg->height;
01178
01179
01180
01181 unsigned int maxDistortionIndex;
01182 if (info_msg->distortion_model == "plumb_bob") {
01183 maxDistortionIndex = 5;
01184 } else {
01185
01186 if (info_msg->distortion_model != "rational_polynomial") {
01187 ROS_ERROR("Unfamiliar with <info_msg->distortion_model> of (%s)", info_msg->distortion_model.c_str());
01188 }
01189
01190 maxDistortionIndex = 8;
01191 }
01192
01193 configData.cameraData.distCoeffs = cv::Mat::zeros(1, maxDistortionIndex, CV_64FC1);
01194 configData.cameraData.blankCoeffs = cv::Mat::zeros(1, maxDistortionIndex, CV_64FC1);
01195
01196 for (unsigned int iii = 0; iii < maxDistortionIndex; iii++) {
01197 configData.cameraData.distCoeffs.at<double>(0, iii) = info_msg->D[iii];
01198 }
01199
01200 cout << configData.cameraData.distCoeffs << endl;
01201
01202 configData.cameraData.newCamMat = cv::Mat::zeros(3, 3, CV_64FC1);
01203
01204 cv::Rect* validPixROI = 0;
01205
01206 double alpha = 0.00;
01207 bool centerPrincipalPoint = true;
01208
01209 configData.cameraData.newCamMat = getOptimalNewCameraMatrix(configData.cameraData.K, configData.cameraData.distCoeffs, configData.cameraData.cameraSize, alpha, configData.cameraData.cameraSize, validPixROI, centerPrincipalPoint);
01210
01211
01212
01213 cout << configData.cameraData.newCamMat << endl;
01214
01215 infoProcessed = true;
01216
01217 addFixedCamera(display_sys, configData.cameraData, eye4);
01218
01219 drawGraph2(display_sys, camera_pub, points_pub, path_pub, decimation, bicolor);
01220
01221 assignPose(currentPose, eye4);
01222 pose_pub.publish(currentPose);
01223
01224 } catch (...) {
01225 ROS_ERROR("Some failure in reading in the camera parameters...");
01226 }
01227
01228 ROS_INFO("Camera information processed.");
01229
01230 }
01231
01232
01233
01234
01235 }
01236
01237 void slamNode::refreshPoses() {
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270 for (unsigned int iii = 0; iii < keyframe_store.keyframes.size(); iii++) {
01271
01272 }
01273
01274 }
01275
01276 void slamNode::prepareForTermination() {
01277 return;
01278 }
01279
01280 bool slamNode::findStartingFrames() {
01281
01282
01283
01284
01285
01286 bool foundStartingPair = false;
01287
01288 if (latestFrame < 1) {
01289 return foundStartingPair;
01290 }
01291
01292 double keyframe_scores[5];
01293 cv::Mat startingTrans;
01294
01295 cv::Mat blankMat = cv::Mat::zeros(80, 640, CV_8UC3);
01296
01297 if ((configData.keyframeEvaluationMode) && (!evaluationStream.is_open())) {
01298 ROS_WARN("Opening evaluation summary stream...");
01299 evaluationStream.open(configData.evaluationFile.c_str(), ios::out | ios::app);
01300 }
01301
01302 for (int jjj = configData.minStartingSeparation; jjj < min(latestFrame+1, configData.maxInitializationFrames); jjj++) {
01303
01304
01305
01306 vector<unsigned int> startersToTest;
01307
01308 for (int iii = max(0, ((int)jjj)-configData.maxStartingSeparation); iii < jjj-configData.minStartingSeparation; iii++) {
01309 startersToTest.push_back(iii);
01310 }
01311
01312
01313 while (((int)startersToTest.size()) > configData.maxTestsPerFrame) {
01314
01315 unsigned int randIndex = rand() % startersToTest.size();
01316 startersToTest.erase(startersToTest.begin() + randIndex);
01317
01318 }
01319
01320
01321
01322 for (unsigned int iii = 0; iii < startersToTest.size(); iii++) {
01323
01324 if ((foundStartingPair) && (!configData.keyframeEvaluationMode)) {
01325 break;
01326 }
01327
01328 if (keyframeTestFlags.at<unsigned char>(startersToTest.at(iii),jjj) == 0) {
01329
01330 vector<unsigned int> activeTracks;
01331 getActiveTracks(activeTracks, featureTrackVector, startersToTest.at(iii), jjj);
01332
01333
01334 startingTrans = cv::Mat();
01335 keyframeTestScores.at<double>(startersToTest.at(iii),jjj) = testKeyframePair(featureTrackVector, configData.cameraData, scorecardParams, startersToTest.at(iii), jjj, keyframe_scores, startingTrans, true , true);
01336
01337
01338 if (keyframeTestScores.at<double>(startersToTest.at(iii),jjj) > 0.0) {
01339
01340 }
01341
01342 if (configData.keyframeEvaluationMode) {
01343
01344 clearSystem();
01345
01346 bool result = true;
01347 char outputString[256];
01348
01349 ROS_INFO("Assigning as starting frames (%d, %d)...", startersToTest.at(iii), jjj);
01350 assignStartingFrames(startersToTest.at(iii), jjj, keyframe_scores, startingTrans);
01351 ROS_INFO("Starting frames assigned.");
01352
01353 if (startingTrans.rows > 0) {
01354
01355
01356 formInitialStructure();
01357
01358 ROS_INFO("Initial structure formed.");
01359
01360 char response = ' ';
01361
01362 blankMat = cv::Mat(blankMat.size(), blankMat.type(), CV_RGB(0,255,0));
01363
01364
01365 while ((response != 'y') && (response != 'n')) {
01366 cv::imshow("readybar", blankMat);
01367 response = cv::waitKey();
01368 }
01369
01370 blankMat = cv::Mat(blankMat.size(), blankMat.type(), CV_RGB(255,0,0));
01371 cv::imshow("readybar", blankMat);
01372 cv::waitKey(1);
01373
01374 if (response == 'y') {
01375 result = true;
01376 } else {
01377 result = false;
01378 }
01379 } else {
01380 ROS_INFO("Initial starting transformation invalid, returning failure.");
01381 result = false;
01382 }
01383
01384
01385
01386 ROS_INFO("Preparing string...");
01387 sprintf(outputString, "%06d %06d %+02.2f %+02.2f %+02.2f %+02.2f %+02.2f %1.2f %d", startersToTest.at(iii), jjj, keyframe_scores[0], keyframe_scores[1], keyframe_scores[2], keyframe_scores[3], keyframe_scores[4], keyframeTestScores.at<double>(startersToTest.at(iii),jjj), (result ? 1 : 0));
01388 ROS_INFO("String written.");
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399 evaluationStream << outputString << endl;
01400 }
01401
01402
01403 keyframeTestFlags.at<unsigned char>(startersToTest.at(iii),jjj) = 1;
01404
01405 if (keyframeTestScores.at<double>(startersToTest.at(iii),jjj) >= configData.minStartupScore) {
01406
01407
01408 foundStartingPair = true;
01409
01410 }
01411
01412 ROS_INFO("Keyframe pair (%03d, %03d) initialization score = [%f] {%1.2f, %1.2f, %1.2f, %1.2f, %1.2f}", startersToTest.at(iii), jjj, keyframeTestScores.at<double>(startersToTest.at(iii),jjj), keyframe_scores[0], keyframe_scores[1], keyframe_scores[2], keyframe_scores[3], keyframe_scores[4]);
01413
01414 }
01415
01416 }
01417
01418 if ((foundStartingPair) && (!configData.keyframeEvaluationMode)) {
01419 break;
01420 }
01421
01422 }
01423
01424 if (configData.keyframeEvaluationMode) {
01425 evaluationStream.close();
01426 evaluationCompleted = true;
01427 ROS_INFO("Keyframe evaluation results finalize. (CTRL + C) to terminate.");
01428
01429 blankMat = cv::Mat(blankMat.size(), blankMat.type(), CV_RGB(0,0,255));
01430 cv::imshow("readybar", blankMat);
01431 cv::waitKey();
01432 return false;
01433 }
01434
01435 if (foundStartingPair) {
01436
01437 double a, b;
01438 cv::Point min_coord, max_coord;
01439 unsigned int best_iii, best_jjj;
01440 minMaxLoc(keyframeTestScores, &a, &b, &min_coord, &max_coord);
01441
01442 best_iii = max_coord.y;
01443 best_jjj = max_coord.x;
01444
01445 assignStartingFrames(best_iii, best_jjj, keyframe_scores, startingTrans);
01446
01447
01448 }
01449
01450 return foundStartingPair;
01451
01452
01453 }
01454
01455 void slamNode::clearSystem() {
01456
01457 keyframe_store.connections.clear();
01458 keyframe_store.keyframes.clear();
01459 keyframe_store.count = 0;
01460
01461 for (unsigned int iii = 0; iii < featureTrackVector.size(); iii++) {
01462 featureTrackVector.at(iii).isTriangulated = false;
01463 }
01464
01465 int finalIndex;
01466
01467 if (configData.keyframeEvaluationMode) {
01468 finalIndex = configData.maxInitializationFrames + 1;
01469 } else {
01470 finalIndex = latestFrame + 1;
01471 }
01472 for (int iii = 0; iii < finalIndex; iii++) {
01473 ACM[iii] = cv::Mat();
01474 }
01475
01476 }
01477
01478 double slamNode::assignStartingFrames(unsigned int best_iii, unsigned int best_jjj, double* keyframe_scores, cv::Mat& startingTrans) {
01479
01480 printf("%s << Adding (%d) & (%d) to keyframe store... (already (%d) large)", __FUNCTION__, best_iii, best_jjj, ((int)keyframe_store.keyframes.size()));
01481
01482 keyframe_store.addKeyframe(best_iii, blank);
01483 keyframe_store.addKeyframe(best_jjj, blank);
01484
01485 double kfScore = testKeyframePair(featureTrackVector, configData.cameraData, scorecardParams, best_iii, best_jjj, keyframe_scores, startingTrans, configData.keyframeEvaluationMode, true);
01486
01487 ACM[best_iii] = cv::Mat::eye(4, 4, CV_64FC1);
01488 startingTrans.copyTo(ACM[best_jjj]);
01489
01490 ROS_INFO("kfScore = %f (%d, %d)", kfScore, best_iii, best_jjj);
01491 cout << ACM[best_iii] << endl;
01492 cout << ACM[best_jjj] << endl;
01493
01494
01495
01496 keyframe_store.addConnection(keyframe_store.count-2, keyframe_store.count-1, KF_CONNECTION_GEOMETRIC, F_arr[best_iii]);
01497
01498 return kfScore;
01499
01500 }
01501
01502 bool slamNode::formInitialStructure() {
01503
01504
01505
01506
01507
01508 double keyframe_scores[5];
01509 cv::Mat startingTrans;
01510 bool formedInitialStructure = false;
01511
01512 int keyframe_idx_1 = keyframe_store.connections.at(baseConnectionNum).idx1;
01513 int keyframe_idx_2 = keyframe_store.connections.at(baseConnectionNum).idx2;
01514
01515
01516
01517 unsigned int image_idx_1 = keyframe_store.keyframes.at(keyframe_idx_1).idx;
01518 unsigned int image_idx_2 = keyframe_store.keyframes.at(keyframe_idx_2).idx;
01519
01520
01521
01522 lastBasePose = image_idx_1;
01523
01524 vector<cv::Point2f> pts1, pts2;
01525 getPointsFromTracks(featureTrackVector, pts1, pts2, image_idx_1, image_idx_2);
01526
01527 vector<unsigned int> activeTrackIndices, fullSpanIndices, triangulatedIndices;
01528
01529 getActiveTracks(activeTrackIndices, featureTrackVector, image_idx_1, image_idx_2);
01530 filterToCompleteTracks(fullSpanIndices, activeTrackIndices, featureTrackVector, image_idx_1, image_idx_2);
01531
01532 startingTracksCount = fullSpanIndices.size();
01533
01534
01535
01536
01537
01538
01539
01540
01541 vector<cv::Point3d> ptsInCloud;
01542 cv::Mat P1, R1, t1;
01543 cv::Mat Rvec, C;
01544 vector<cv::Point2f> correspPoints;
01545
01546
01547
01548
01549
01550 bool worked = reconstructFreshSubsequencePair(featureTrackVector, ptsInCloud, triangulatedIndices, ACM[image_idx_1], ACM[image_idx_2], configData.cameraData, image_idx_1, image_idx_2);
01551
01552
01553
01554
01555
01556 if (!worked) {
01557 ROS_ERROR("2-Frame reconstruction didn't work.");
01558 }
01559
01560
01561
01562
01563
01564 double keyframeError;
01565 keyframeError = testKeyframePair(featureTrackVector, configData.cameraData, scorecardParams, image_idx_1, image_idx_2, keyframe_scores, startingTrans, configData.keyframeEvaluationMode);
01566
01567
01568
01569
01570 startingTrans.copyTo(ACM[image_idx_2]);
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588 vector<unsigned int> adjustableKeyframeIndices;
01589
01590 adjustableKeyframeIndices.push_back(image_idx_1);
01591 adjustableKeyframeIndices.push_back(image_idx_2);
01592
01593
01594
01595 keyframeError = keyframeBundleAdjustment(configData.cameraData, featureTrackVector, ACM, adjustableKeyframeIndices, configData.initialStructureIterations, false, false, 1);
01596 ROS_INFO("Adjusted error: %f", keyframeError);
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606 if (!worked) {
01607 ROS_ERROR("Reconstruction of fresh subsequence pair failed.");
01608 return false;
01609 }
01610
01611 ROS_INFO("Getting active 3d points...");
01612
01613
01614 getActive3dPoints(featureTrackVector, triangulatedIndices, ptsInCloud);
01615
01616
01617 ROS_INFO("Points acquired. GT.");
01618
01619 int relativeIndex = image_idx_2-image_idx_1;
01620
01621 printf("%s << DEBUG (%04d)\n", __FUNCTION__, 0);
01622
01623 SysSBA subsys;
01624 addPointsToSBA(subsys, ptsInCloud);
01625
01626 printf("%s << DEBUG (%04d)\n", __FUNCTION__, 1);
01627
01628
01629 addFixedCamera(subsys, configData.cameraData, ACM[image_idx_1]);
01630
01631 printf("%s << DEBUG (%04d)\n", __FUNCTION__, 2);
01632
01633 addNewCamera(subsys, configData.cameraData, ACM[image_idx_2]);
01634
01635
01636
01637 printf("%s << DEBUG (%04d)\n", __FUNCTION__, 3);
01638
01639 subsys.nFixed = 1;
01640
01641 addProjectionsToSBA(subsys, pts1, 0);
01642
01643 printf("%s << DEBUG (%04d)\n", __FUNCTION__, 4);
01644
01645 addProjectionsToSBA(subsys, pts2, 1);
01646
01647 ROS_INFO("Going through relative indices...");
01648
01649 for (int jjj = 1; jjj < relativeIndex; jjj++) {
01650
01651 vector<cv::Point2f> latestPoints;
01652
01653 printf("%s << About to get corresponding points (%d)...\n", __FUNCTION__, jjj);
01654 getCorrespondingPoints(featureTrackVector, pts1, latestPoints, image_idx_1, image_idx_1+jjj);
01655 printf("%s << Corresponding points acquired (%d)\n", __FUNCTION__, jjj);
01656
01657
01658 vector<cv::Point3f> objectPoints;
01659 cv::Point3f tmpPt;
01660
01661 for (unsigned int kkk = 0; kkk < ptsInCloud.size(); kkk++) {
01662 tmpPt = cv::Point3f((float) ptsInCloud.at(kkk).x, (float) ptsInCloud.at(kkk).y, (float) ptsInCloud.at(kkk).z);
01663 objectPoints.push_back(tmpPt);
01664 }
01665
01666 cv::Mat t, R, Rvec;
01667
01668 printf("%s << DEBUG (%03d)\n", __FUNCTION__, 0);
01669
01670 printf("%s << Solving PnP... (%d) (oP.size() = %d; lP.size() = %d)\n", __FUNCTION__, jjj, ((int)objectPoints.size()), ((int)latestPoints.size()));
01671
01672 if (objectPoints.size() != latestPoints.size()) {
01673 ROS_ERROR("Unable to find proper corresponding points!");
01674 continue;
01675 }
01676
01677 solvePnPRansac(objectPoints, latestPoints, configData.cameraData.K, configData.cameraData.blankCoeffs, Rvec, t);
01678
01679 printf("%s << DEBUG (%03d)\n", __FUNCTION__, 1);
01680
01681 Rodrigues(Rvec, R);
01682
01683
01684
01685
01686
01687 cv::Mat newCam;
01688 cv::Mat T;
01689 composeTransform(R, t, T);
01690 transformationToProjection(T, newCam);
01691
01692
01693
01694
01695
01696 cv::Mat newCamC;
01697 projectionToTransformation(newCam, newCamC);
01698 newCamC = newCamC.inv();
01699 transformationToProjection(newCamC, newCam);
01700
01701 addNewCamera(subsys, configData.cameraData, newCam);
01702
01703 addProjectionsToSBA(subsys, latestPoints, jjj+1);
01704
01705 printf("%s << DEBUG (%03d)\n", __FUNCTION__, 2);
01706
01707
01708
01709
01710
01711
01712 }
01713
01714
01715
01716
01717
01718
01719
01720 subsys.nFixed = 1;
01721 ROS_INFO("About to rescale (1)");
01722 rescaleSBA(subsys, 0, 1);
01723 ROS_INFO("About to optimize between rescalings...");
01724 double avgError = optimizeSystem(subsys, 1e-4, configData.subsequenceIterations);
01725 ROS_INFO("About to rescale (2)");
01726 rescaleSBA(subsys, 0, 1);
01727 ROS_INFO("Rescaling done");
01728
01729
01730 if (avgError < 0.0) {
01731 ROS_ERROR("Subsystem optimization failed to converge..");
01732 }
01733
01734
01735
01736
01737
01738
01739
01740
01741 retrieveCameraPose(subsys, 0, ACM[image_idx_1]);
01742 retrieveCameraPose(subsys, 1, ACM[image_idx_2]);
01743
01744
01745
01746
01747
01748
01749
01750 #pragma omp parallel for
01751 for (unsigned int ttt = 1; ttt < image_idx_2-image_idx_1; ttt++) {
01752 retrieveCameraPose(subsys, ttt+1, ACM[image_idx_1+ttt]);
01753
01754 }
01755
01756
01757
01758
01759
01760
01761
01762
01763 ptsInCloud.clear();
01764 retrieveAllPoints(ptsInCloud, subsys);
01765
01766 updateTriangulatedPoints(featureTrackVector, triangulatedIndices, ptsInCloud);
01767
01768 vector<unsigned int> basisNodes;
01769
01770 for (unsigned int iii = image_idx_1; iii <= image_idx_2; iii++) {
01771 basisNodes.push_back(iii);
01772 }
01773
01774 keyframeError = keyframeBundleAdjustment(configData.cameraData, featureTrackVector, ACM, basisNodes, configData.keyframeIterations, false, false, 1);
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798 if (1) {
01799
01800 vector<unsigned int> triangulatedIndices, untriangulatedIndices;
01801 findRelevantIndices(featureTrackVector, triangulatedIndices, untriangulatedIndices, image_idx_1, image_idx_2);
01802
01803
01804 if (untriangulatedIndices.size() > 0) {
01805
01806 vector<unsigned int> triangulatableIndices;
01807 findTriangulatableTracks3(featureTrackVector, triangulatableIndices, image_idx_2, configData.framesForTriangulation);
01808
01809 if (triangulatableIndices.size() > 0) {
01810
01811 triangulateTracks(featureTrackVector, triangulatableIndices, configData.cameraData, ACM, image_idx_1, image_idx_2);
01812
01813
01814
01815
01816 if (currentPoseIndex > 60) {
01817
01818 }
01819
01820 }
01821
01822
01823 }
01824 }
01825
01826
01827
01828 keyframeError = keyframeBundleAdjustment(configData.cameraData, featureTrackVector, ACM, basisNodes, configData.keyframeIterations, false, false, 1);
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844 currentPoseIndex = image_idx_2;
01845 formedInitialStructure = true;
01846
01847
01848
01849 for (unsigned int iii = image_idx_1; iii <= image_idx_2; iii++) {
01850
01851 }
01852
01853
01854 if (1) {
01855 update_display();
01856 }
01857
01858
01859
01860
01861 return formedInitialStructure;
01862
01863 ROS_ERROR("What!? How did I get here??");
01864 cin.get();
01865
01866
01867
01869
01870
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01884
01885
01886
01887
01888
01889
01890
01892
01894
01895
01896
01898
01899
01901
01902
01904
01905
01906
01907
01908
01909
01911
01913
01914
01915
01916
01917
01918
01919
01920
01922
01923
01924
01926
01928
01930
01932
01933
01934
01935
01936
01938
01940
01941
01943
01944
01945
01947
01948
01949
01950
01951
01952
01954
01955
01956
01957
01958
01961
01962
01963
01965
01966
01967
01968
01971
01972
01973
01974
01975
01976
01980
01981
01982
01984
01985
01986
01987
01989
01990
01991
01992
01993
01996
01997
01998
01999
02000
02001
02003
02004
02005
02006
02007
02008
02009
02010
02011
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02048
02049
02050
02051
02053
02054
02055
02056
02057
02058
02059
02060
02061 }
02062
02063 void slamNode::assignPose(geometry_msgs::PoseStamped& pPose, cv::Mat& C) {
02064 pPose.header.seq = currentPoseIndex;
02065 pPose.header.stamp = ros::Time::now();
02066
02067 cv::Mat R, t;
02068 Quaterniond Q;
02069 decomposeTransform(C, R, t);
02070 matrixToQuaternion(R, Q);
02071
02072
02073
02074
02075 pPose.pose.position.x = t.at<double>(2,0);
02076 pPose.pose.position.y = -t.at<double>(0,0);
02077 pPose.pose.position.z = -t.at<double>(1,0);
02078
02079 if (abs(pPose.pose.position.x) > MAX_RVIZ_DISPLACEMENT) {
02080 pPose.pose.position.x = 0.0;
02081 }
02082
02083 if (abs(pPose.pose.position.y) > MAX_RVIZ_DISPLACEMENT) {
02084 pPose.pose.position.y = 0.0;
02085 }
02086
02087 if (abs(pPose.pose.position.z) > MAX_RVIZ_DISPLACEMENT) {
02088 pPose.pose.position.z = 0.0;
02089 }
02090
02091
02092
02093
02094 pPose.pose.orientation.x = Q.z();
02095 pPose.pose.orientation.y = -Q.x();
02096 pPose.pose.orientation.z = -Q.y();
02097 pPose.pose.orientation.w = Q.w();
02098 }
02099
02100 void slamNode::serverCallback(thermalvis::monoslamConfig &config, uint32_t level) {
02101
02102 configData.flowback = config.flowback;
02103
02104 configData.verboseMode = config.verboseMode;
02105
02106 configData.timeSpacing = config.timeSpacing;
02107
02108 configData.poseEstimateIterations = config.poseEstimateIterations;
02109
02110 configData.minStartupScore = config.minStartupScore;
02111
02112 configData.adjustmentFrames = config.adjustmentFrames;
02113
02114 configData.motionThreshold = config.motionThreshold;
02115
02116 configData.timeDebug = config.timeDebug;
02117
02118 configData.keyframeIterations = config.keyframeIterations;
02119
02120 configData.framesForTriangulation = config.framesForTriangulation;
02121
02122 configData.maxKeyframeSeparation = config.maxKeyframeSeparation;
02123
02124 configData.min3dPtsForPnP = config.min3dPtsForPnP;
02125
02126 configData.camerasPerSys = config.camerasPerSys;
02127
02128 configData.minTrackedFeatures = config.minTrackedFeatures;
02129
02130 configData.minGeometryScore = config.minGeometryScore;
02131
02132 configData.minKeyframeScore = config.minKeyframeScore;
02133
02134 configData.requiredTrackFrac = config.requiredTrackFrac;
02135
02136 configData.fullSystemIterations = config.fullSystemIterations;
02137
02138 configData.subsequenceIterations = config.subsequenceIterations;
02139
02140 configData.keyframeSpacing = config.keyframeSpacing;
02141
02142 configData.maxGuides = config.maxGuides;
02143
02144 configData.initialStructureIterations = config.initialStructureIterations;
02145
02146
02147
02148 }
02149
02150 slamNode::slamNode(ros::NodeHandle& nh, slamData startupData) {
02151
02152 configData = startupData;
02153
02154 scorecardParams = new double*[INITIALIZATION_SCORING_PARAMETERS];
02155
02156 for (int iii = 0; iii < INITIALIZATION_SCORING_PARAMETERS; iii++) {
02157 scorecardParams[iii] = new double[3];
02158 }
02159
02160 processScorecard();
02161
02162 sprintf(nodeName, "%s", ros::this_node::getName().c_str());
02163
02164 srand(time(NULL));
02165
02166 evaluationCompleted = false;
02167
02168
02169
02170
02171
02172 putativelyEstimatedFrames = 0;
02173
02174 firstIteration = true;
02175
02176 boost::mutex cam_mutex;
02177 boost::mutex tracks_mutex;
02178 boost::mutex keyframes_mutex;
02179
02180 char timeString[256];
02181
02182 sprintf(timeString, "%010d.%09d", ros::Time::now().sec, ros::Time::now().nsec);
02183
02184
02185
02186
02187 configData.evaluationFile = configData.read_addr + "nodes/monoslam/log/" + timeString + "-" + ros::this_node::getName().substr(1,ros::this_node::getName().size()-1) + ".txt";
02188
02189 if (configData.keyframeEvaluationMode) {
02190 ROS_INFO("evaluationFile = (%s)", configData.evaluationFile.c_str());
02191 }
02192
02193
02194 decimation = DEFAULT_DRAWGRAPH_DECIMATION;
02195 bicolor = DEFAULT_DRAWGRAPH_BICOLOR;
02196
02197 display_sys.tracks.clear();
02198 display_sys.nodes.clear();
02199
02200 eye4 = cv::Mat::eye(4, 4, CV_64FC1);
02201
02202
02203 repetitionNoted = false;
02204
02205 currentPoseIndex = -1;
02206
02207 isTracking = true;
02208
02209 baseConnectionNum = 0;
02210
02211 lastBasePose = -1;
02212
02213 latestFrame = -1;
02214
02215 path_pub = nh.advertise<visualization_msgs::Marker>( "path", 1 );
02216 camera_pub = nh.advertise<visualization_msgs::Marker>( "cameras", 1 );
02217 points_pub = nh.advertise<visualization_msgs::Marker>( "points", 1);
02218
02219
02220
02221 structureValid = false;
02222 structureFormed = false;
02223
02224 sys.verbose = 0;
02225 display_sys.verbose = 0;
02226
02227
02228
02229 ROS_INFO("Setting up node.");
02230
02231 infoProcessed = false;
02232
02233
02234
02235 std::string topic_tracks = configData.stream + "tracks";
02236
02237 ROS_INFO("Connecting to tracks topic. %s", topic_tracks.c_str());
02238 tracks_sub = nh.subscribe<thermalvis::feature_tracks>(topic_tracks, 1, &slamNode::handle_tracks, this);
02239
02240 std::string topic_info = configData.stream + "camera_info";
02241
02242 ROS_INFO("Connecting to camera_info. %s", topic_info.c_str());
02243
02244 info_sub = nh.subscribe<sensor_msgs::CameraInfo>(topic_info, 1, &slamNode::handle_info, this);
02245
02246
02247
02248 ROS_INFO("Node setup.");
02249
02250 keyframeTestScores = cv::Mat::zeros(configData.maxInitializationFrames, configData.maxInitializationFrames, CV_64FC1);
02251 keyframeTestFlags = cv::Mat::zeros(configData.maxInitializationFrames, configData.maxInitializationFrames, CV_8UC1);
02252
02253 sprintf(pose_pub_name, "thermalvis%s/pose", nodeName);
02254 ROS_INFO("Configuring pose topic. %s", pose_pub_name);
02255
02256 currentPose.header.frame_id = "/pgraph";
02257 pose_pub = nh.advertise<geometry_msgs::PoseStamped>(pose_pub_name, 1);
02258
02259 timer = nh.createTimer(ros::Duration(0.01), &slamNode::main_loop, this);
02260
02261
02262
02263 if (configData.logErrors) {
02264 configData.errorFile = configData.read_addr + "nodes/monoslam/log/stability/" + timeString + "-" + ros::this_node::getName().substr(1,ros::this_node::getName().size()-1) + ".txt";
02265 ROS_INFO("Current debug filename: %s", configData.errorFile.c_str());
02266 error_file.open(configData.errorFile.c_str());
02267 }
02268
02269 ROS_INFO("Establishing server callback...");
02270 f = boost::bind (&slamNode::serverCallback, this, _1, _2);
02271 server.setCallback (f);
02272
02273 }
02274
02275 timeAnalyzer::timeAnalyzer() {
02276
02277 cycles = 0;
02278 average = 0.0;
02279 sigma = 0.0;
02280
02281 timeElapsedMS(cycle_timer, true);
02282 }
02283
02284 void timeAnalyzer::calcParameters() {
02285 if (cycles == 0) {
02286 return;
02287 }
02288
02289 average = 0.0;
02290 sigma = 0.0;
02291
02292 for (int iii = 0; iii < cycles; iii++) {
02293 average += vals[iii] / ((double) cycles);
02294 }
02295
02296 for (int iii = 0; iii < cycles; iii++) {
02297 sigma += pow(vals[iii] - average, 2.0) / ((double) cycles);
02298 }
02299
02300 sigma = pow(sigma, 0.5);
02301
02302 }
02303
02304 void timeAnalyzer::startRecording() {
02305 timeElapsedMS(cycle_timer, true);
02306 }
02307
02308 void timeAnalyzer::stopRecording() {
02309
02310 if (cycles < 1024) {
02311 vals[cycles] = timeElapsedMS(cycle_timer, true);
02312 cycles++;
02313 } else {
02314 ROS_ERROR("Too many cycles (%d) / (%d)", cycles, 1024);
02315 }
02316
02317 }
02318
02319