vslam.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 * Software License Agreement (BSD License)
00003 *
00004 *  Copyright (c) 2009, Willow Garage, Inc.
00005 *  All rights reserved.
00006 *
00007 *  Redistribution and use in source and binary forms, with or without
00008 *  modification, are permitted provided that the following conditions
00009 *  are met:
00010 *
00011 *   * Redistributions of source code must retain the above copyright
00012 *     notice, this list of conditions and the following disclaimer.
00013 *   * Redistributions in binary form must reproduce the above
00014 *     copyright notice, this list of conditions and the following
00015 *     disclaimer in the documentation and/or other materials provided
00016 *     with the distribution.
00017 *   * Neither the name of the Willow Garage nor the names of its
00018 *     contributors may be used to endorse or promote products derived
00019 *     from this software without specific prior written permission.
00020 *
00021 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 *  POSSIBILITY OF SUCH DAMAGE.
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), // 40 frames, 10 fixed
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   // pose_estimator_.windowed = false; // Commented out because this was breaking PR
00066   
00067   prInliers = 200;
00068   numPRs = 0;                   // count of PR successes
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   // Set up next frame and compute descriptors
00078   frame_common::Frame next_frame;
00079   next_frame.setCamParams(camera_parameters); // this sets the projection and reprojection matrices
00080   frame_processor_.setStereoFrame(next_frame, left, right, nfrac, setPointCloud);
00081   next_frame.frameId = sba_.nodes.size(); // index
00082 #ifndef HOWARD
00083   next_frame.img = cv::Mat();   // remove the images
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   // Add frame to visual odometer
00094   bool is_keyframe = vo_.addFrame(next_frame);
00095 
00096   // grow full SBA
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   // Set up next frame and compute descriptors
00114   frame_common::Frame next_frame;
00115   next_frame.setCamParams(camera_parameters); // this sets the projection and reprojection matrices
00116   frame_processor_.setStereoFrame(next_frame, left, right, nfrac);
00117   next_frame.frameId = sba_.nodes.size(); // index
00118 #ifndef HOWARD
00119   next_frame.img = cv::Mat();   // remove the images
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   // Add frame to visual odometer
00129   bool is_keyframe = vo_.addFrame(next_frame);
00130 
00131   // grow full SBA
00132   if (is_keyframe)
00133   {
00134     addKeyframe(next_frame);
00135     // Store the dense pointcloud.
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     // Modify the transferred frame
00152     frame_common::Frame& transferred_frame = frames_.back();
00153 
00154     // Add any matches from place recognition
00155     // frameId indexes into frames
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       // Skip if it's one of the previous nskip keyframes
00166       if (matched_frame.frameId >= (int)frames_.size() - nSkip - 1) 
00167       {
00168         //        printf("\tMatch %d: skipping, frame index %d\n", i, (int)matched_frame.frameId);
00169         continue;
00170       }
00171 
00172       // Geometric check for place recognizer
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               // More code copied from vo.cpp
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               // add in point cloud matches, if they exist
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               //        sba_.printStats();
00207               if (cst > 4.0)
00208                 {
00209                   // fix all but last NNN frames
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                   //              sba_.doSBA(3,1.0e-4,SBA_BLOCK_JACOBIAN_PCG);
00216                   sba_.nFixed = 1;
00217                 }
00218             }
00219     }
00220 }
00221 
00222 void VslamSystem::refine(int initial_runs)
00223 {
00225   //  sba_.doSBA(initial_runs, 1.0e-4, SBA_BLOCK_JACOBIAN_PCG);
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);  // do more
00229   if (sba_.calcRMSCost() > 4.0)
00230     sba_.doSBA(10, 1.0e-4, SBA_SPARSE_CHOLESKY);  // do more
00231 }
00232 
00233 } // namespace vslam


vslam_system
Author(s): Kurt Konolige, Patrick Mihelich, Helen Oleynikova
autogenerated on Thu Jan 2 2014 12:12:32