00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 #include <vslam_system/vslam.h>
00036 #include <cstdio>
00037 
00038 
00039 using namespace sba;
00040 using namespace pcl;
00041 
00042 namespace vslam {
00043 
00044 VslamSystem::VslamSystem(const std::string& vocab_tree_file, const std::string& vocab_weights_file,
00045   int min_keyframe_inliers, double min_keyframe_distance, double min_keyframe_angle)
00046   : frame_processor_(10),
00047 #ifdef HOWARD
00048   vo_(boost::shared_ptr<pe::PoseEstimator>(new pe::PoseEstimatorH(10, true, 6.0, 4.0, 4.0, 0.05, 10, 17)),
00049 #else
00050   vo_(boost::shared_ptr<pe::PoseEstimator>(new pe::PoseEstimator3d(1000,true,6.0,8.0,8.0)),
00051 #endif
00052     40, 10, min_keyframe_inliers, min_keyframe_distance, min_keyframe_angle), 
00053     place_recognizer_(vocab_tree_file, vocab_weights_file),
00054 #ifdef HOWARD
00055     pose_estimator_(10, true, 6.0, 8.0, 8.0, 0.05, 10, 17)
00056 #else
00057     pose_estimator_(5000, true, 10.0, 3.0, 3.0)
00058 #endif
00059 {
00060   sba_.useCholmod(true);
00062   pose_estimator_.wx = 92;
00063   pose_estimator_.wy = 48;
00064   
00065   
00066   
00067   prInliers = 200;
00068   numPRs = 0;                   
00069   nSkip = 20;
00070   doPointPlane = true;
00071 }
00072 
00073 bool VslamSystem::addFrame(const frame_common::CamParams& camera_parameters,
00074                            const cv::Mat& left, const cv::Mat& right, int nfrac, 
00075                            bool setPointCloud)
00076 {
00077   
00078   frame_common::Frame next_frame;
00079   next_frame.setCamParams(camera_parameters); 
00080   frame_processor_.setStereoFrame(next_frame, left, right, nfrac, setPointCloud);
00081   next_frame.frameId = sba_.nodes.size(); 
00082 #ifndef HOWARD
00083   next_frame.img = cv::Mat();   
00084 #endif
00085   next_frame.imgRight = cv::Mat();
00086   
00087   if (setPointCloud && pointcloud_processor_ && doPointPlane)
00088     {
00089       pointcloud_processor_->setPointcloud(next_frame, next_frame.dense_pointcloud);
00090       printf("[Pointcloud] set a pointcloud! %d\n", (int)next_frame.pointcloud.points.size());
00091     }
00092  
00093   
00094   bool is_keyframe = vo_.addFrame(next_frame);
00095 
00096   
00097   if (is_keyframe)
00098   {
00099     addKeyframe(next_frame); 
00100   }
00101 
00102   if (frames_.size() > 1 && vo_.pose_estimator_->inliers.size() < 40)
00103     std::cout << std::endl << "******** Bad image match: " << vo_.pose_estimator_->inliers.size() 
00104               << " inliers" << std::endl << std::endl;
00105 
00106   return is_keyframe;
00107 }
00108 
00109 bool VslamSystem::addFrame(const frame_common::CamParams& camera_parameters,
00110                            const cv::Mat& left, const cv::Mat& right,
00111                            const pcl::PointCloud<PointXYZRGB>& ptcloud, int nfrac)
00112 {
00113   
00114   frame_common::Frame next_frame;
00115   next_frame.setCamParams(camera_parameters); 
00116   frame_processor_.setStereoFrame(next_frame, left, right, nfrac);
00117   next_frame.frameId = sba_.nodes.size(); 
00118 #ifndef HOWARD
00119   next_frame.img = cv::Mat();   
00120 #endif
00121   next_frame.imgRight = cv::Mat();
00122   if (pointcloud_processor_ && doPointPlane)
00123   {
00124     pointcloud_processor_->setPointcloud(next_frame, ptcloud);
00125     printf("[Pointcloud] set a pointcloud! %d\n", (int)next_frame.pointcloud.points.size());
00126   }
00127   
00128   
00129   bool is_keyframe = vo_.addFrame(next_frame);
00130 
00131   
00132   if (is_keyframe)
00133   {
00134     addKeyframe(next_frame);
00135     
00136     frames_.back().dense_pointcloud = ptcloud;
00137   }
00138 
00139   if (frames_.size() > 1 && vo_.pose_estimator_->inliers.size() < 40)
00140     std::cout << std::endl << "******** Bad image match: " << std::endl << std::endl;
00141 
00142   return is_keyframe;
00143 }
00144 
00145 void VslamSystem::addKeyframe(frame_common::Frame& next_frame)
00146 {
00147     frames_.push_back(next_frame);
00148     vo_.doPointPlane = doPointPlane;
00149     vo_.transferLatestFrame(frames_, sba_);
00150 
00151     
00152     frame_common::Frame& transferred_frame = frames_.back();
00153 
00154     
00155     
00156     std::vector<const frame_common::Frame*> place_matches;
00157     const size_t N = 5;
00158     place_recognizer_.findAndInsert(transferred_frame, transferred_frame.frameId, frames_, N, place_matches);
00159     printf("PLACEREC: Found %d matches\n", (int)place_matches.size());
00160 
00161     for (int i = 0; i < (int)place_matches.size(); ++i) 
00162     {
00163       frame_common::Frame& matched_frame = const_cast<frame_common::Frame&>(*place_matches[i]);
00164       
00165       
00166       if (matched_frame.frameId >= (int)frames_.size() - nSkip - 1) 
00167       {
00168         
00169         continue;
00170       }
00171 
00172       
00173       int inliers = pose_estimator_.estimate(matched_frame, transferred_frame);
00174       printf("\tMatch %d: %d inliers, frame index %d\n", i, inliers, matched_frame.frameId);
00175       if (inliers > prInliers) 
00176             {
00177               numPRs++;
00178 
00179               printf("\t[PlaceRec] Adding PR link between frames %d and %d\n", transferred_frame.frameId, 
00180                      matched_frame.frameId);
00181 
00182               
00183               Matrix<double,3,4> frame_to_world;
00184               Node &matched_node = sba_.nodes[matched_frame.frameId];
00185               Quaterniond fq0; 
00186               fq0 = matched_node.qrot;
00187               transformF2W(frame_to_world, matched_node.trans, fq0);
00188             
00189               addProjections(matched_frame, transferred_frame, frames_, sba_, pose_estimator_.inliers,
00190                              frame_to_world, matched_frame.frameId, transferred_frame.frameId);
00191 
00192               
00193               if (pointcloud_processor_ && doPointPlane)
00194                 {
00195                   printf("\t[PlaceRec] Adding in point cloud projections\n");
00196                   Matrix<double,3,4> f2w_transferred;
00197                   Node &transferred_node = sba_.nodes[transferred_frame.frameId];
00198                   transformF2W(f2w_transferred,transferred_node.trans,transferred_node.qrot);
00199                   pointcloud_processor_->match(matched_frame, transferred_frame, pose_estimator_.trans, Quaterniond(pose_estimator_.rot), pointcloud_matches_);
00200                   addPointCloudProjections(matched_frame, transferred_frame, sba_, pointcloud_matches_, 
00201                                            frame_to_world, f2w_transferred, matched_frame.frameId, transferred_frame.frameId);
00202                 }
00203 
00204               double cst = sba_.calcRMSCost();
00205               cout << endl << "*** RMS Cost: " << cst << endl << endl;
00206               
00207               if (cst > 4.0)
00208                 {
00209                   
00210                   int n = sba_.nodes.size();
00211                   n = n-50;
00212                   if (n < 1) n=1;
00213                   sba_.nFixed = n;
00214                   sba_.doSBA(3,1.0e-4, SBA_SPARSE_CHOLESKY);
00215                   
00216                   sba_.nFixed = 1;
00217                 }
00218             }
00219     }
00220 }
00221 
00222 void VslamSystem::refine(int initial_runs)
00223 {
00225   
00226   sba_.doSBA(initial_runs, 1.0e-4, SBA_SPARSE_CHOLESKY);
00227   if (sba_.calcRMSCost() > 4.0)
00228     sba_.doSBA(10, 1.0e-4, SBA_SPARSE_CHOLESKY);  
00229   if (sba_.calcRMSCost() > 4.0)
00230     sba_.doSBA(10, 1.0e-4, SBA_SPARSE_CHOLESKY);  
00231 }
00232 
00233 }