run_ps_bag.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 
00036 //
00037 // runs a sequence of depth/visual images from a PS sensor into an SBA engine
00038 // visualize in rviz
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 // visual output of matches
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     // member vaiables
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   // parameters
00117   vslam_.setKeyDist(0.01);      // meters
00118   vslam_.setKeyAngle(0.05);     // radians
00119   vslam_.setKeyInliers(200);
00120   vslam_.setHuber(40.0);          // Huber cost function cutoff
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     //    printf("Ptcloud size: %d\n", frames[i].dense_pointcloud.points.size());
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     // rotate into rviz frame from camera frame
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 // draw the graph on rviz
00172 // in rviz frame, z -> y, x -> -z from camera frame
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   // draw points, decimated
00220   int npts = vslam_.vo_.sba.tracks.size();
00221 
00222   //  cout << "Number of points to draw: " << npts << endl;
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   // draw cameras
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   // draw point-plane projections
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)   // have a ptp projection
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               //              Eigen::Vector3d projpt = plane_point+(w.dot(plane_normal))*plane_normal;
00288               Eigen::Vector3d projpt = pt0.head<3>() - (w.dot(plane_normal))*plane_normal;
00289               //              Vector3d pt1 = pt0.head<3>()+0.1*plane_normal;
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   // draw SPA constraints
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   //cst_pub.publish(cstmark);
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           // draw graph
00434           //              cout << "drawing with " << n << " nodes and " << np << " points..." << endl << endl;
00435           if (n%1 == 0)
00436           {
00437             drawgraph( 1 ); // every nth point
00438             publishRegisteredPointclouds( );
00439             drawgraph( 1 ); // every nth point
00440             publishRegisteredPointclouds( );
00441             for (int i=0; i<5; i++)
00442               {
00443                 //                      getchar();
00444                 cout << i << endl;
00445                 vslam_.vo_.sba.doSBA( 1,1.0e-5,0 );          // dense version
00446                 drawgraph( 1 ); // every nth point
00447                 publishRegisteredPointclouds( );
00448                 drawgraph( 1 ); // every nth point
00449                 publishRegisteredPointclouds( );
00450               }
00451           }
00452 
00453           // write file out
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 // main loop
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   // set up markers for visualization
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 }


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