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 
00036 
00037 
00038 
00039 
00040 
00041 #include <ros/ros.h>
00042 #include <visualization_msgs/Marker.h>
00043 #include <visualization_msgs/MarkerArray.h>
00044 #include <geometry_msgs/Point.h>
00045 
00046 #include <vslam_system/vslam.h>
00047 #include <posest/pe3d.h>
00048 #include <sba/sba.h>
00049 #include <sba/sba_file_io.h>
00050 #include <frame_common/frame.h>
00051 #include <boost/shared_ptr.hpp>
00052 #include <fstream>
00053 #include <dirent.h>
00054 #include <fnmatch.h>
00055 #include <time.h>
00056 #include <opencv/highgui.h>
00057 #include <opencv2/legacy/legacy.hpp>
00058 #include <opencv2/nonfree/nonfree.hpp>
00059 #include <rosbag/bag.h>
00060 #include <rosbag/view.h>
00061 #include <sensor_msgs/CameraInfo.h>
00062 #include <stereo_msgs/DisparityImage.h>
00063 #include <sensor_msgs/Image.h>
00064 #include <cv_bridge/CvBridge.h>
00065 
00066 using namespace std;
00067 using namespace sba;
00068 using namespace frame_common;
00069 using namespace Eigen;
00070 using namespace vslam;
00071 using namespace pcl;
00072 
00073 
00074 #define VISMATCH
00075 
00076 
00077 class VisBundler
00078 {
00079   public:
00080     VisBundler( const string& bag_filename, const string& vocabulary_tree_filename,
00081                 const string& voc_weights_filename, cv::DescriptorExtractor* descriptor_extractor );
00082     ~VisBundler();
00083 
00084     bool step();
00085     void spin();
00086   protected:
00087     void publishRegisteredPointclouds( ) const;
00088     void drawgraph( int dec ) const;
00089 
00090     
00091     ros::NodeHandle node_handle_;
00092     vslam::VslamSystem vslam_;
00093     rosbag::Bag bag_;
00094     rosbag::View view_;
00095     rosbag::View::iterator message_iterator_;
00096     ros::Publisher pt_pub_;
00097     ros::Publisher cam_pub_;
00098     ros::Publisher pc_pub_;
00099 };
00100 
00101 VisBundler::VisBundler( const string& bag_filename, const string& vocabulary_tree_filename,
00102                         const string& vocabulary_weights_filename, cv::DescriptorExtractor* descriptor_extractor )
00103         : node_handle_("~")
00104         , vslam_( vocabulary_tree_filename, vocabulary_weights_filename )
00105         , bag_( bag_filename )
00106         , view_( bag_ )
00107         , message_iterator_( view_.begin() )
00108         , pt_pub_( node_handle_.advertise<visualization_msgs::Marker>("points", 0) )
00109         , cam_pub_( node_handle_.advertise<visualization_msgs::Marker>("cameras", 0) )
00110         , pc_pub_( node_handle_.advertise<sensor_msgs::PointCloud2>("pointcloud", 1) )
00111 {
00112   vslam_.frame_processor_.setFrameDescriptor( descriptor_extractor );
00113   vslam_.setPointcloudProc(boost::shared_ptr<frame_common::PointcloudProc>(new frame_common::PointcloudProc()));
00114   vslam_.doPointPlane = false;
00115   
00116   
00117   vslam_.setKeyDist(0.01);      
00118   vslam_.setKeyAngle(0.05);     
00119   vslam_.setKeyInliers(200);
00120   vslam_.setHuber(40.0);          
00121   vslam_.vo_.pose_estimator_->wy = 128;
00122   vslam_.vo_.pose_estimator_->wx = 128;
00123   vslam_.vo_.pose_estimator_->numRansac = 10000;
00124   vslam_.vo_.sba.verbose = false;
00125   vslam_.sba_.verbose = false;
00126   
00127   srand(time(0));
00128 
00129   #ifdef VISMATCH
00130   cv::namedWindow("VO tracks",0);
00131   cv::namedWindow("color image");
00132   #endif
00133 }
00134 
00135 VisBundler::~VisBundler()
00136 {
00137 }
00138 
00139 void VisBundler::publishRegisteredPointclouds( ) const
00140 {
00141   pcl::PointCloud<pcl::PointXYZRGB> cloud;
00142   pcl::PointCloud<pcl::PointXYZRGB> registered_cloud;
00143 
00144   for(size_t i=0; i < vslam_.vo_.frames.size(); i++)
00145   {
00146     
00147     if (vslam_.vo_.sba.nodes.size() < i)
00148       break;
00149     if (vslam_.vo_.frames[i].dense_pointcloud.points.size() <= 0)
00150       continue;
00151     Eigen::Quaterniond rot = vslam_.vo_.sba.nodes[i].qrot;
00152     Eigen::Vector3d trans = vslam_.vo_.sba.nodes[i].trans.head<3>();
00153 
00154     transformPointCloud<PointXYZRGB>(vslam_.vo_.frames[i].dense_pointcloud, cloud, Vector3f(0,0,0), rot.cast<float>());
00155     transformPointCloud<PointXYZRGB>(cloud, cloud, trans.cast<float>(), Quaternionf(1, 0, 0, 0));
00156     
00157     Quaternionf qr = Quaternionf(.5, 0, 0, .5).normalized()*Quaternionf(.5, -.5, .5, -0.5).normalized();
00158     transformPointCloud<PointXYZRGB>(cloud, cloud, Vector3f(0,0,0), qr);
00159 
00160     registered_cloud.header = vslam_.vo_.frames[i].dense_pointcloud.header;
00161     registered_cloud += cloud;
00162   }
00163 
00164   sensor_msgs::PointCloud2 cloud_out;
00165   pcl::toROSMsg (registered_cloud, cloud_out);
00166   cloud_out.header.frame_id = "/pgraph";
00167   pc_pub_.publish (cloud_out);
00168 }
00169 
00170 
00171 
00172 
00173 void VisBundler::drawgraph( int dec ) const
00174 {
00175   visualization_msgs::Marker cammark, ptmark, cstmark;
00176   cammark.header.frame_id = "/pgraph";
00177   cammark.header.stamp = ros::Time();
00178   cammark.ns = "pgraph";
00179   cammark.id = 0;
00180   cammark.action = visualization_msgs::Marker::ADD;
00181   cammark.pose.position.x = 0;
00182   cammark.pose.position.y = 0;
00183   cammark.pose.position.z = 0;
00184   cammark.pose.orientation.x = 0.0;
00185   cammark.pose.orientation.y = 0.0;
00186   cammark.pose.orientation.z = 0.0;
00187   cammark.pose.orientation.w = 1.0;
00188   cammark.scale.x = 0.02;
00189   cammark.scale.y = 0.02;
00190   cammark.scale.z = 0.02;
00191   cammark.color.r = 0.0f;
00192   cammark.color.g = 1.0f;
00193   cammark.color.b = 1.0f;
00194   cammark.color.a = 1.0f;
00195   cammark.lifetime = ros::Duration();
00196   cammark.type = visualization_msgs::Marker::LINE_LIST;
00197 
00198   ptmark = cammark;
00199   ptmark.color.r = 1.0f;
00200   ptmark.color.g = 0.0f;
00201   ptmark.color.b = 0.0f;
00202   ptmark.color.a = 0.5f;
00203   ptmark.scale.x = 0.01;
00204   ptmark.scale.y = 0.01;
00205   ptmark.scale.z = 0.01;
00206   ptmark.type = visualization_msgs::Marker::POINTS;
00207 
00208   cstmark = cammark;
00209   cstmark.color.r = 1.0f;
00210   cstmark.color.g = 1.0f;
00211   cstmark.color.b = 0.0f;
00212   cstmark.color.a = 1.0f;
00213   cstmark.scale.x = 0.03;
00214   cstmark.scale.y = 0.1;
00215   cstmark.scale.z = 0.1;
00216   cstmark.type = visualization_msgs::Marker::LINE_LIST;
00217 
00218 
00219   
00220   int npts = vslam_.vo_.sba.tracks.size();
00221 
00222   
00223   if (npts <= 0) return;
00224 
00225 
00226   ptmark.points.resize(npts/dec+1);
00227   for (int i=0, ii=0; i<npts; i+=dec, ii++)
00228     {
00229       const Vector4d &pt = vslam_.vo_.sba.tracks[i].point;
00230       ptmark.points[ii].x = pt(0);
00231       ptmark.points[ii].y = pt(2);
00232       ptmark.points[ii].z = -pt(1);
00233     }
00234 
00235   
00236   int ncams = vslam_.vo_.sba.nodes.size();
00237   cammark.points.resize(ncams*6);
00238   for (int i=0, ii=0; i<ncams; i++)
00239     {
00240       const Node &nd = vslam_.vo_.sba.nodes[i];
00241       Vector3d opt;
00242       Matrix<double,3,4> tr;
00243       transformF2W(tr,nd.trans,Quaternion<double>(nd.qrot));
00244 
00245       cammark.points[ii].x = nd.trans.x();
00246       cammark.points[ii].y = nd.trans.z();
00247       cammark.points[ii++].z = -nd.trans.y();
00248       opt = tr*Vector4d(0,0,0.3,1);
00249       cammark.points[ii].x = opt.x();
00250       cammark.points[ii].y = opt.z();
00251       cammark.points[ii++].z = -opt.y();
00252 
00253       cammark.points[ii].x = nd.trans.x();
00254       cammark.points[ii].y = nd.trans.z();
00255       cammark.points[ii++].z = -nd.trans.y();
00256       opt = tr*Vector4d(0.2,0,0,1);
00257       cammark.points[ii].x = opt.x();
00258       cammark.points[ii].y = opt.z();
00259       cammark.points[ii++].z = -opt.y();
00260 
00261       cammark.points[ii].x = nd.trans.x();
00262       cammark.points[ii].y = nd.trans.z();
00263       cammark.points[ii++].z = -nd.trans.y();
00264       opt = tr*Vector4d(0,0.1,0,1);
00265       cammark.points[ii].x = opt.x();
00266       cammark.points[ii].y = opt.z();
00267       cammark.points[ii++].z = -opt.y();
00268     }
00269 
00270   
00271   int num_tracks = vslam_.vo_.sba.tracks.size();
00272   int ii = cammark.points.size();
00273 
00274   for (int i=0; i < num_tracks; i++)
00275     {
00276       const ProjMap &prjs = vslam_.vo_.sba.tracks[i].projections;
00277       for (ProjMap::const_iterator itr = prjs.begin(); itr != prjs.end(); itr++)
00278         {
00279           const Proj &prj = (*itr).second;
00280           if (prj.pointPlane)   
00281             {
00282               cammark.points.resize(ii+2);
00283               Point pt0 = vslam_.vo_.sba.tracks[i].point;
00284               Vector3d plane_point = prj.plane_point;
00285               Vector3d plane_normal = prj.plane_normal;
00286               Eigen::Vector3d w = pt0.head<3>()-plane_point;
00287               
00288               Eigen::Vector3d projpt = pt0.head<3>() - (w.dot(plane_normal))*plane_normal;
00289               
00290               Vector3d pt1 = projpt;
00291                   
00292               cammark.points[ii].x = pt0.x();
00293               cammark.points[ii].y = pt0.z();
00294               cammark.points[ii++].z = -pt0.y();
00295               cammark.points[ii].x = pt1.x();
00296               cammark.points[ii].y = pt1.z();
00297               cammark.points[ii++].z = -pt1.y();
00298             }
00299         } 
00300     }
00301 
00302 
00303 #if 0
00304   
00305   int ncons = vslam_.vo_.spa.p2cons.size();
00306   cstmark.points.resize(ncons*6);
00307 
00308   for (int i=0, ii=0; i<ncons; i++)
00309     {
00310       ConP2 &con = vslam_.vo_.spa.p2cons[i];
00311       Node &nd0 = vslam_.vo_.spa.nodes[con.ndr];
00312       Node &nd1 = vslam_.vo_.spa.nodes[con.nd1];
00313 
00314       Node &nd = vslam_.vo_.spa.nodes[i];
00315       Vector3d opt;
00316       Matrix<double,3,4> tr;
00317       transformF2W(tr,nd.trans,Quaternion<double>(nd.qrot));
00318 
00319       cstmark.points[ii].x = nd.trans.x();
00320       cstmark.points[ii].y = nd.trans.z();
00321       cstmark.points[ii++].z = -nd.trans.y();
00322       opt = tr*Vector4d(0,0,0.3,1);
00323       cstmark.points[ii].x = opt.x();
00324       cstmark.points[ii].y = opt.z();
00325       cstmark.points[ii++].z = -opt.y();
00326 
00327       cstmark.points[ii].x = nd.trans.x();
00328       cstmark.points[ii].y = nd.trans.z();
00329       cstmark.points[ii++].z = -nd.trans.y();
00330       opt = tr*Vector4d(0.2,0,0,1);
00331       cstmark.points[ii].x = opt.x();
00332       cstmark.points[ii].y = opt.z();
00333       cstmark.points[ii++].z = -opt.y();
00334 
00335       cstmark.points[ii].x = nd.trans.x();
00336       cstmark.points[ii].y = nd.trans.z();
00337       cstmark.points[ii++].z = -nd.trans.y();
00338       opt = tr*Vector4d(0,0.1,0,1);
00339       cstmark.points[ii].x = opt.x();
00340       cstmark.points[ii].y = opt.z();
00341       cstmark.points[ii++].z = -opt.y();
00342 
00343 #if 0
00344       cstmark.points[ii].x = nd0.trans.x();
00345       cstmark.points[ii].y= nd0.trans.z();
00346       cstmark.points[ii++].z = -nd0.trans.y();
00347       cstmark.points[ii].x = nd1.trans.x();
00348       cstmark.points[ii].y = nd1.trans.z();
00349       cstmark.points[ii++].z = -nd1.trans.y();
00350 #endif
00351     }
00352 #endif // SPA
00353 
00354   cam_pub_.publish(cammark);
00355   pt_pub_.publish(ptmark);
00356   
00357   
00358 }
00359 
00360 
00361 bool VisBundler::step( )
00362 {
00363   static boost::shared_ptr< sensor_msgs::CameraInfo > camera_info_left;
00364   static boost::shared_ptr< sensor_msgs::CameraInfo > camera_info_right;
00365   static boost::shared_ptr< sensor_msgs::Image > color_image;
00366   static boost::shared_ptr< stereo_msgs::DisparityImage > disparity_image;
00367 
00368   static int message_count = 0;
00369   while( message_iterator_ != view_.end() )
00370   {
00371     if( message_iterator_->getTopic() == "/primesense/left/camera_info" )
00372     {
00373       camera_info_left = message_iterator_->instantiate<sensor_msgs::CameraInfo>();
00374     }
00375 
00376     else if( message_iterator_->getTopic() == "/primesense/right/camera_info" )
00377     {
00378       camera_info_right = message_iterator_->instantiate<sensor_msgs::CameraInfo>();
00379     }
00380 
00381     else if( message_iterator_->getTopic() == "/primesense/left/color_image_raw" )
00382     {
00383       color_image = message_iterator_->instantiate<sensor_msgs::Image>();
00384     }
00385     else if( message_iterator_->getTopic() == "/primesense/disparity" )
00386     {
00387       disparity_image = message_iterator_->instantiate<stereo_msgs::DisparityImage>();
00388     }
00389     
00390     ++message_iterator_;
00391     ++message_count;
00392 
00393     if( message_count > 3 )
00394     {
00395       ros::Time oldest = min( min( color_image->header.stamp, camera_info_right->header.stamp ) ,
00396                               min( camera_info_left->header.stamp, disparity_image->header.stamp ) );
00397 
00398       ros::Time newest = max( max( color_image->header.stamp, camera_info_right->header.stamp ) ,
00399                               max( camera_info_left->header.stamp, disparity_image->header.stamp ) );
00400 
00401       if( oldest == newest )
00402       {
00403         CamParams camera_params;
00404         camera_params.fx = camera_info_left->K[0];
00405         camera_params.fy = camera_info_left->K[4];
00406         camera_params.cx = camera_info_left->K[2];
00407         camera_params.cx = camera_info_left->K[5];
00408         camera_params.tx = - camera_info_right->P[3] / camera_params.fx;
00409 
00410         static sensor_msgs::CvBridge cvImageBridge;
00411         cv::Mat image( cvImageBridge.imgMsgToCv( color_image ) );
00412 
00413         cv::Mat grayImage;
00414         cv::cvtColor( image, grayImage, CV_RGB2GRAY );
00415         static sensor_msgs::CvBridge cvDisparityBridge;
00416         cvDisparityBridge.fromImage( disparity_image->image );
00417         cv::Mat disp_image32f = cvDisparityBridge.toIpl();
00418         cv::Mat disp_image16u;
00419 
00420         disp_image32f.convertTo( disp_image16u, CV_16UC1, 32.0 );
00421 
00422         bool is_keyframe = vslam_.addFrame( camera_params, grayImage, disp_image16u, 32.0, true );
00423 
00424         if (is_keyframe)
00425         {
00426 
00427           imshow("color image", image );
00428           vslam_.sba_.doSBA(10,1e-4,SBA_SPARSE_CHOLESKY);
00429 
00431           int n = vslam_.sba_.nodes.size();
00432 
00433           
00434           
00435           if (n%1 == 0)
00436           {
00437             drawgraph( 1 ); 
00438             publishRegisteredPointclouds( );
00439             drawgraph( 1 ); 
00440             publishRegisteredPointclouds( );
00441             for (int i=0; i<5; i++)
00442               {
00443                 
00444                 cout << i << endl;
00445                 vslam_.vo_.sba.doSBA( 1,1.0e-5,0 );          
00446                 drawgraph( 1 ); 
00447                 publishRegisteredPointclouds( );
00448                 drawgraph( 1 ); 
00449                 publishRegisteredPointclouds( );
00450               }
00451           }
00452 
00453           
00454           if (n > 10 && n%500 == 0)
00455           {
00456             char fn[1024];
00457             sprintf(fn,"newcollege%d.g2o", n);
00458             sba::writeGraphFile(fn,vslam_.sba_);
00459             sprintf(fn,"newcollege%dm.g2o", n);
00460             sba::writeGraphFile(fn,vslam_.sba_,true);
00461           }
00462 
00463           int nnsba = 10;
00464           if (n > 4 && n%nnsba == 0)
00465           {
00466             cout << "Running large SBA" << endl;
00467             vslam_.refine();
00468           }
00469 
00470           break;
00471         }
00472 #ifdef VISMATCH
00473         cv::Mat display;
00474         drawVOtracks(grayImage, vslam_.vo_.frames, display);
00475         cv::imshow("VO tracks", display);
00476 #endif
00477       }
00478     }
00479   }
00480 
00481   return (message_iterator_ != view_.end());
00482 }
00483 
00484 
00485 void VisBundler::spin()
00486 {
00487   bool quit = false;
00488   bool paused = true;
00489   while( node_handle_.ok() && !quit )
00490   {
00491     ros::spinOnce();
00492     char key = cv::waitKey( 10 ) & 0xFF;
00493     switch( key )
00494     {
00495       case 27:
00496       case 'Q':
00497       case 'q':
00498         quit = true;
00499         break;
00500       case ' ':
00501         paused = !paused;
00502         break;
00503       case 's':
00504       case 'S':
00505         paused = true;
00506         step();
00507         break;
00508     }
00509     if( !paused )
00510     {
00511       step();
00512     }
00513   }
00514 }
00515 
00516 int main(int argc, char** argv)
00517 {
00518   if (argc < 5)
00519   {
00520     cout <<"Usage: " << argv[0] << " <bag file> <vocab tree file> <vocab weights file> <calonder trees file>" << endl;
00521     exit(0);
00522   }
00523   
00524   
00525   ros::init(argc, argv, "VisBundler");
00526   typedef cv::CalonderDescriptorExtractor<float> Calonder;
00527   typedef cv::SiftDescriptorExtractor Sift;
00528   VisBundler visbundler( argv[1], argv[2], argv[3], new Calonder(argv[4]) );
00529 
00530   visbundler.spin();
00531 
00532   return 0;
00533 }