run_ps.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 <cstdio>
00053 #include <fstream>
00054 #include <dirent.h>
00055 #include <fnmatch.h>
00056 
00057 #include <opencv/highgui.h>
00058 #include <opencv2/legacy/legacy.hpp>
00059 #include <opencv2/nonfree/nonfree.hpp>
00060 
00061 using namespace std;
00062 using namespace sba;
00063 using namespace frame_common;
00064 using namespace Eigen;
00065 using namespace vslam;
00066 using namespace pcl;
00067 
00068 // visual output of matches
00069 #define VISMATCH
00070 
00071 // elapsed time in milliseconds
00072 #include <sys/time.h>
00073 static double mstime()
00074 {
00075   timeval tv;
00076   gettimeofday(&tv,NULL);
00077   long long ts = tv.tv_sec;
00078   ts *= 1000000;
00079   ts += tv.tv_usec;
00080   return (double)ts*.001;
00081 }
00082 
00083 // Names of left and right files in directory (with wildcards)
00084 char *lreg, *rreg, *dreg;
00085 
00086 // Filters for scandir
00087 int getleft(struct dirent const *entry)
00088 {
00089   if (!fnmatch(lreg,entry->d_name,0))
00090     return 1;
00091   return 0;
00092 }
00093 
00094 int getright(struct dirent const *entry)
00095 {
00096   if (!fnmatch(rreg,entry->d_name,0))
00097     return 1;
00098   return 0;
00099 }
00100 
00101 
00102 int getidir(struct dirent const *entry)
00103 {
00104   if (!fnmatch(dreg,entry->d_name,0))
00105     return 1;
00106   return 0;
00107 }
00108 
00109 
00110 // publish the point clouds on rviz
00111 void publishRegisteredPointclouds(sba::SysSBA& sba, 
00112     std::vector<frame_common::Frame, Eigen::aligned_allocator<frame_common::Frame> >& frames, 
00113     ros::Publisher& pub)
00114 {
00115   pcl::PointCloud<pcl::PointXYZRGB> cloud;
00116   pcl::PointCloud<pcl::PointXYZRGB> registered_cloud;
00117 
00118   for(size_t i=0; i < frames.size(); i++)
00119   {
00120     //    printf("Ptcloud size: %d\n", frames[i].dense_pointcloud.points.size());
00121     if (sba.nodes.size() < i)
00122       break;
00123     if (frames[i].dense_pointcloud.points.size() <= 0)
00124       continue;
00125     Eigen::Quaterniond rot = sba.nodes[i].qrot;
00126     Eigen::Vector3d trans = sba.nodes[i].trans.head<3>();
00127     
00128     transformPointCloud<PointXYZRGB>(frames[i].dense_pointcloud, cloud, Vector3f(0,0,0), rot.cast<float>());
00129     transformPointCloud<PointXYZRGB>(cloud, cloud, trans.cast<float>(), Quaternionf(1, 0, 0, 0));
00130     // rotate into rviz frame from camera frame
00131     Quaternionf qr = Quaternionf(.5, 0, 0, .5).normalized()*Quaternionf(.5, -.5, .5, -0.5).normalized(); 
00132     transformPointCloud<PointXYZRGB>(cloud, cloud, Vector3f(0,0,0), qr);
00133     
00134     registered_cloud.header = frames[i].dense_pointcloud.header;
00135     registered_cloud += cloud;
00136   }
00137   
00138   sensor_msgs::PointCloud2 cloud_out;
00139   pcl::toROSMsg (registered_cloud, cloud_out);
00140   cloud_out.header.frame_id = "/pgraph";
00141   pub.publish (cloud_out);
00142 }
00143 
00144 
00145 // draw the graph on rviz
00146 // in rviz frame, z -> y, x -> -z from camera frame
00147 void
00148 drawgraph(const SysSBA &sba, const ros::Publisher &cam_pub, const ros::Publisher &pt_pub, 
00149           int dec)
00150 {
00151   visualization_msgs::Marker cammark, ptmark, cstmark;
00152   cammark.header.frame_id = "/pgraph";
00153   cammark.header.stamp = ros::Time();
00154   cammark.ns = "pgraph";
00155   cammark.id = 0;
00156   cammark.action = visualization_msgs::Marker::ADD;
00157   cammark.pose.position.x = 0;
00158   cammark.pose.position.y = 0;
00159   cammark.pose.position.z = 0;
00160   cammark.pose.orientation.x = 0.0;
00161   cammark.pose.orientation.y = 0.0;
00162   cammark.pose.orientation.z = 0.0;
00163   cammark.pose.orientation.w = 1.0;
00164   cammark.scale.x = 0.02;
00165   cammark.scale.y = 0.02;
00166   cammark.scale.z = 0.02;
00167   cammark.color.r = 0.0f;
00168   cammark.color.g = 1.0f;
00169   cammark.color.b = 1.0f;
00170   cammark.color.a = 1.0f;
00171   cammark.lifetime = ros::Duration();
00172   cammark.type = visualization_msgs::Marker::LINE_LIST;
00173 
00174   ptmark = cammark;
00175   ptmark.color.r = 1.0f;
00176   ptmark.color.g = 0.0f;
00177   ptmark.color.b = 0.0f;
00178   ptmark.color.a = 0.5f;
00179   ptmark.scale.x = 0.01;
00180   ptmark.scale.y = 0.01;
00181   ptmark.scale.z = 0.01;
00182   ptmark.type = visualization_msgs::Marker::POINTS;
00183 
00184   cstmark = cammark;
00185   cstmark.color.r = 1.0f;
00186   cstmark.color.g = 1.0f;
00187   cstmark.color.b = 0.0f;
00188   cstmark.color.a = 1.0f;
00189   cstmark.scale.x = 0.03;
00190   cstmark.scale.y = 0.1;
00191   cstmark.scale.z = 0.1;
00192   cstmark.type = visualization_msgs::Marker::LINE_LIST;
00193 
00194 
00195   // draw points, decimated
00196   int npts = sba.tracks.size();
00197 
00198   //  cout << "Number of points to draw: " << npts << endl;
00199   if (npts <= 0) return;
00200 
00201 
00202   ptmark.points.resize(npts/dec+1);
00203   for (int i=0, ii=0; i<npts; i+=dec, ii++)
00204     {
00205       const Vector4d &pt = sba.tracks[i].point;
00206       ptmark.points[ii].x = pt(0);
00207       ptmark.points[ii].y = pt(2);
00208       ptmark.points[ii].z = -pt(1);
00209     }
00210 
00211   // draw cameras
00212   int ncams = sba.nodes.size();
00213   cammark.points.resize(ncams*6);
00214   for (int i=0, ii=0; i<ncams; i++)
00215     {
00216       const Node &nd = sba.nodes[i];
00217       Vector3d opt;
00218       Matrix<double,3,4> tr;
00219       transformF2W(tr,nd.trans,Quaternion<double>(nd.qrot));
00220 
00221       cammark.points[ii].x = nd.trans.x();
00222       cammark.points[ii].y = nd.trans.z();
00223       cammark.points[ii++].z = -nd.trans.y();
00224       opt = tr*Vector4d(0,0,0.3,1);
00225       cammark.points[ii].x = opt.x();
00226       cammark.points[ii].y = opt.z();
00227       cammark.points[ii++].z = -opt.y();
00228 
00229       cammark.points[ii].x = nd.trans.x();
00230       cammark.points[ii].y = nd.trans.z();
00231       cammark.points[ii++].z = -nd.trans.y();
00232       opt = tr*Vector4d(0.2,0,0,1);
00233       cammark.points[ii].x = opt.x();
00234       cammark.points[ii].y = opt.z();
00235       cammark.points[ii++].z = -opt.y();
00236 
00237       cammark.points[ii].x = nd.trans.x();
00238       cammark.points[ii].y = nd.trans.z();
00239       cammark.points[ii++].z = -nd.trans.y();
00240       opt = tr*Vector4d(0,0.1,0,1);
00241       cammark.points[ii].x = opt.x();
00242       cammark.points[ii].y = opt.z();
00243       cammark.points[ii++].z = -opt.y();
00244     }
00245 
00246   // draw point-plane projections
00247   int num_tracks = sba.tracks.size();
00248   int ii = cammark.points.size();
00249 
00250   for (int i=0; i < num_tracks; i++)
00251     {
00252       const ProjMap &prjs = sba.tracks[i].projections;
00253       for (ProjMap::const_iterator itr = prjs.begin(); itr != prjs.end(); itr++)
00254         {
00255           const Proj &prj = (*itr).second;
00256           if (prj.pointPlane)   // have a ptp projection
00257             {
00258               cammark.points.resize(ii+2);
00259               Point pt0 = sba.tracks[i].point;
00260               Vector3d plane_point = prj.plane_point;
00261               Vector3d plane_normal = prj.plane_normal;
00262               Eigen::Vector3d w = pt0.head<3>()-plane_point;
00263               //              Eigen::Vector3d projpt = plane_point+(w.dot(plane_normal))*plane_normal;
00264               Eigen::Vector3d projpt = pt0.head<3>() - (w.dot(plane_normal))*plane_normal;
00265               //              Vector3d pt1 = pt0.head<3>()+0.1*plane_normal;
00266               Vector3d pt1 = projpt;
00267                   
00268               cammark.points[ii].x = pt0.x();
00269               cammark.points[ii].y = pt0.z();
00270               cammark.points[ii++].z = -pt0.y();
00271               cammark.points[ii].x = pt1.x();
00272               cammark.points[ii].y = pt1.z();
00273               cammark.points[ii++].z = -pt1.y();
00274             }
00275         } 
00276     }
00277 
00278 
00279 #if 0
00280   // draw SPA constraints
00281   int ncons = spa.p2cons.size();
00282   cstmark.points.resize(ncons*6);
00283 
00284   for (int i=0, ii=0; i<ncons; i++)
00285     {
00286       ConP2 &con = spa.p2cons[i];
00287       Node &nd0 = spa.nodes[con.ndr];
00288       Node &nd1 = spa.nodes[con.nd1];
00289 
00290       Node &nd = spa.nodes[i];
00291       Vector3d opt;
00292       Matrix<double,3,4> tr;
00293       transformF2W(tr,nd.trans,Quaternion<double>(nd.qrot));
00294 
00295       cstmark.points[ii].x = nd.trans.x();
00296       cstmark.points[ii].y = nd.trans.z();
00297       cstmark.points[ii++].z = -nd.trans.y();
00298       opt = tr*Vector4d(0,0,0.3,1);
00299       cstmark.points[ii].x = opt.x();
00300       cstmark.points[ii].y = opt.z();
00301       cstmark.points[ii++].z = -opt.y();
00302 
00303       cstmark.points[ii].x = nd.trans.x();
00304       cstmark.points[ii].y = nd.trans.z();
00305       cstmark.points[ii++].z = -nd.trans.y();
00306       opt = tr*Vector4d(0.2,0,0,1);
00307       cstmark.points[ii].x = opt.x();
00308       cstmark.points[ii].y = opt.z();
00309       cstmark.points[ii++].z = -opt.y();
00310 
00311       cstmark.points[ii].x = nd.trans.x();
00312       cstmark.points[ii].y = nd.trans.z();
00313       cstmark.points[ii++].z = -nd.trans.y();
00314       opt = tr*Vector4d(0,0.1,0,1);
00315       cstmark.points[ii].x = opt.x();
00316       cstmark.points[ii].y = opt.z();
00317       cstmark.points[ii++].z = -opt.y();
00318 
00319 #if 0
00320       cstmark.points[ii].x = nd0.trans.x();
00321       cstmark.points[ii].y= nd0.trans.z();
00322       cstmark.points[ii++].z = -nd0.trans.y();
00323       cstmark.points[ii].x = nd1.trans.x();
00324       cstmark.points[ii].y = nd1.trans.z();
00325       cstmark.points[ii++].z = -nd1.trans.y();
00326 #endif
00327     }
00328 #endif // SPA
00329 
00330   cam_pub.publish(cammark);
00331   pt_pub.publish(ptmark);
00332   
00333   //cst_pub.publish(cstmark);
00334 }
00335 
00336 
00337 
00338 // main loop
00339 
00340 int main(int argc, char** argv)
00341 {
00342   if (argc < 8)
00343     {
00344       printf("Args are: <param file> <image dir> <left image file template> <right image file template> "
00345              "<vocab tree file> <vocab weights file> <calonder trees file>\n");
00346       exit(0);
00347     }
00348 
00349   // get camera parameters, in the form: fx fy cx cy tx
00350   fstream fstr;
00351   fstr.open(argv[1],fstream::in);
00352   if (!fstr.is_open())
00353     {
00354       printf("Can't open camera file %s\n",argv[1]);
00355       exit(0);
00356     }
00357   CamParams camp;
00358   fstr >> camp.fx;
00359   fstr >> camp.fy;
00360   fstr >> camp.cx;
00361   fstr >> camp.cy;
00362   fstr >> camp.tx;
00363 
00364   cout << "Cam params: " << camp.fx << " " << camp.fy << " " << camp.cx
00365        << " " << camp.cy << " " << camp.tx << endl;
00366 
00367 
00368   // set up directories
00369   struct dirent **lims, **rims, **dirs;
00370   int nlim, nrim, ndirs;
00371   string dname = argv[2];
00372   if (!dname.compare(dname.size()-1,1,"/")) // see if slash at end
00373     dname.erase(dname.size()-1);
00374 
00375   string dirfn = dname.substr(dname.rfind("/")+1);
00376   string tdir = dname.substr(0,dname.rfind("/")+1);
00377   cout << "Top directory is " << tdir << endl;
00378   cout << "Search directory name is " << dirfn << endl;
00379   dreg = (char *)dirfn.c_str();
00380 
00381   ndirs = scandir(tdir.c_str(),&dirs,getidir,alphasort);
00382   printf("Found %d directories\n", ndirs);
00383   printf("%s\n",dirs[0]->d_name);
00384 
00385   // set up structures
00386   vslam::VslamSystem vslam(argv[5], argv[6]);
00387   typedef cv::CalonderDescriptorExtractor<float> Calonder;
00388   typedef cv::SiftDescriptorExtractor Sift;
00389   //  typedef cv::BriefDescriptorExtractor Brief;
00390   vslam.frame_processor_.setFrameDescriptor(new Calonder(argv[7]));
00391   //  vslam.frame_processor_.setFrameDescriptor(new Sift);
00392 
00393   // set up point cloud processing
00394   vslam.setPointcloudProc(boost::shared_ptr<frame_common::PointcloudProc>(new frame_common::PointcloudProc()));
00395   //  vslam.doPointPlane = true;
00396   vslam.doPointPlane = false;
00397   
00398   // parameters
00399   vslam.setKeyDist(0.1);        // meters
00400   vslam.setKeyAngle(0.05);      // radians
00401   vslam.setKeyInliers(200);
00402   vslam.setHuber(40.0);          // Huber cost function cutoff
00403   vslam.vo_.pose_estimator_->wy = 92;
00404   vslam.vo_.pose_estimator_->wx = 92;
00405   vslam.vo_.pose_estimator_->numRansac = 10000;
00406   vslam.vo_.sba.verbose = false;
00407   vslam.sba_.verbose = false;
00408 
00409   
00410   // set up markers for visualization
00411   ros::init(argc, argv, "VisBundler");
00412   ros::NodeHandle nh ("~");
00413   ros::Publisher pt_pub = nh.advertise<visualization_msgs::Marker>("points", 0);
00414   ros::Publisher cam_pub = nh.advertise<visualization_msgs::Marker>("cameras", 0);
00415   ros::Publisher cst_pub = nh.advertise<visualization_msgs::Marker>("constraints", 0);
00416   ros::Publisher link_pub = nh.advertise<visualization_msgs::Marker>("links", 0);
00417   ros::Publisher pc_pub = nh.advertise<sensor_msgs::PointCloud2>("pointcloud", 1);
00418 
00419   // for RANSAC
00420   srand(mstime());
00421 
00422   // window
00423 #ifdef VISMATCH  
00424   const std::string window_name = "VO tracks";
00425   cv::namedWindow(window_name,0);
00426   cv::Mat display;
00427 #endif
00428 
00429   int iter = 0;
00430   lreg = argv[3];
00431   rreg = argv[4];
00432 
00433 
00434   // loop over directories
00435   for (int dd=0; dd<ndirs; dd++)
00436     {
00437       char dir[2048];
00438       sprintf(dir,"%s%s",tdir.c_str(),dirs[dd]->d_name);
00439       printf("Current directory: %s\n", dir);
00440 
00441       // get left/right image file names, sorted
00442       nlim = scandir(dir,&lims,getleft,alphasort);
00443       printf("Found %d left images\n", nlim);
00444       printf("%s\n",lims[0]->d_name);
00445 
00446       nrim = scandir(dir,&rims,getright,alphasort);
00447       printf("Found %d disparity images\n", nrim);
00448       printf("%s\n",rims[0]->d_name);
00449 
00450       if (nlim != nrim)
00451         {
00452           printf("Number of left/disparity images does not match: %d vs. %d\n", nlim, nrim);
00453           exit(0);
00454         }
00455 
00456 
00457 
00458       // loop over each stereo pair, adding it to the system
00459       for (int ii=0; ii<nlim; iter++, ii++)
00460         {
00461           // Load images
00462           char fn[2048];
00463           sprintf(fn,"%s/%s",dir,lims[ii]->d_name);
00464           cv::Mat image1 = cv::imread(fn,0);
00465           sprintf(fn,"%s/%s",dir,rims[ii]->d_name);
00466           cv::Mat image1r = cv::imread(fn,-1);
00467 
00468           printf("Image: %s\n", fn);
00469 #if 0
00470           printf("Image size: %d x %d\n", image1.cols, image1.rows);
00471           printf("Image size: %d x %d\n", image1r.cols, image1r.rows);
00472 #endif
00473 
00474           if (image1.rows == 0 || image1r.rows == 0)
00475             exit(0);
00476 
00477           // Add stereo pair to the system
00478           // 32 counts per pixel disparity
00479           // last arg says to convert disparity to pt cloud
00480           bool is_keyframe = vslam.addFrame(camp, image1, image1r, 32.0, true); 
00481 
00482           usleep(10);
00483 
00484           if (is_keyframe)
00485             {
00486               vslam.sba_.doSBA(10,1e-4,SBA_SPARSE_CHOLESKY);
00487 
00489               int n = vslam.sba_.nodes.size();
00490               int np = vslam.sba_.tracks.size();
00491 
00492               // draw graph
00493               //              cout << "drawing with " << n << " nodes and " << np << " points..." << endl << endl;
00494 #if 1
00495               if (n%1 == 0)
00496                 {
00497                   drawgraph(vslam.vo_.sba, cam_pub, pt_pub, 1); // every nth point
00498                   publishRegisteredPointclouds(vslam.vo_.sba, vslam.vo_.frames, pc_pub);
00499                   drawgraph(vslam.vo_.sba, cam_pub, pt_pub, 1); // every nth point
00500                   publishRegisteredPointclouds(vslam.vo_.sba, vslam.vo_.frames, pc_pub);
00501                   for (int i=0; i<5; i++)
00502                     {
00503                       //                      getchar();
00504                       cout << i << endl;
00505                       vslam.vo_.sba.doSBA(1,1.0e-5,0);          // dense version
00506                       drawgraph(vslam.vo_.sba, cam_pub, pt_pub, 1); // every nth point
00507                       publishRegisteredPointclouds(vslam.vo_.sba, vslam.vo_.frames, pc_pub);
00508                       drawgraph(vslam.vo_.sba, cam_pub, pt_pub, 1); // every nth point
00509                       publishRegisteredPointclouds(vslam.vo_.sba, vslam.vo_.frames, pc_pub);
00510                     }
00511                 }
00512 #endif
00513 
00514               // write file out
00515               if (n > 10 && n%500 == 0)
00516                 {
00517                   char fn[1024];
00518                   sprintf(fn,"newcollege%d.g2o", n);
00519                   sba::writeGraphFile(fn,vslam.sba_);
00520                   sprintf(fn,"newcollege%dm.g2o", n);
00521                   sba::writeGraphFile(fn,vslam.sba_,true);
00522                   //                  sba::writeLourakisFile(fn, vslam.sba_);
00523                   //                  vslam.sba_.doSBA(1,1.0e-4,0);
00524                   //                  sba::writeSparseA(fn, vslam.sba_);
00525                 }
00526 
00527 #if 1
00528               int nnsba = 10;
00529               if (n > 4 && n%nnsba == 0)
00530                 {
00531                   cout << "Running large SBA" << endl;
00532                   vslam.refine();
00533                 }
00534 #endif
00535             }
00536 
00537 #ifdef VISMATCH
00538           // Visualize
00539           if (1)
00540             {
00541               drawVOtracks(image1, vslam.vo_.frames, display);
00542               cv::imshow(window_name, display);
00543               cv::waitKey(0);
00544             }
00545 #endif
00546 
00547           if (!nh.ok())
00548             return 0;
00549         }
00550     }
00551   return 0;
00552 }


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