vis-intel.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 // Run an Intel node/point file (in TORO format) through SBA
00036 
00037 #include <ros/ros.h>
00038 #include <visualization_msgs/Marker.h>
00039 #include <visualization_msgs/MarkerArray.h>
00040 #include <geometry_msgs/Point.h>
00041 
00042 #include "sba/read_spa.h"
00043 #include "sba/sba.h"
00044 #include <sba/sba_file_io.h>
00045 #include "frame_common/frame.h"
00046 
00047 #include <iostream>
00048 #include <iomanip>
00049 #include <fstream>
00050 #include <vector>
00051 #include <sys/time.h>
00052 
00053 using namespace std;
00054 using namespace Eigen;
00055 using namespace sba;
00056 using namespace frame_common;
00057 
00058 
00059 
00060 // elapsed time in microseconds
00061 long long utime()
00062 {
00063   timeval tv;
00064   gettimeofday(&tv,NULL);
00065   long long ts = tv.tv_sec;
00066   ts *= 1000000;
00067   ts += tv.tv_usec;
00068   return ts;
00069 }
00070 
00071 #define SAVE_RESULTS
00072 
00073 
00074 // draw the graph on rviz
00075 void
00076 drawgraph(SysSBA &sba, ros::Publisher &cam_pub, ros::Publisher &pt_pub, int dec)
00077 {
00078   visualization_msgs::Marker cammark, ptmark;
00079   cammark.header.frame_id = "/pgraph";
00080   cammark.header.stamp = ros::Time();
00081   cammark.ns = "pgraph";
00082   cammark.id = 0;
00083   cammark.action = visualization_msgs::Marker::ADD;
00084   cammark.pose.position.x = 0;
00085   cammark.pose.position.y = 0;
00086   cammark.pose.position.z = 0;
00087   cammark.pose.orientation.x = 0.0;
00088   cammark.pose.orientation.y = 0.0;
00089   cammark.pose.orientation.z = 0.0;
00090   cammark.pose.orientation.w = 1.0;
00091   cammark.scale.x = 0.02;
00092   cammark.scale.y = 0.02;
00093   cammark.scale.z = 0.02;
00094   cammark.color.r = 0.0f;
00095   cammark.color.g = 1.0f;
00096   cammark.color.b = 1.0f;
00097   cammark.color.a = 1.0f;
00098   cammark.lifetime = ros::Duration();
00099   cammark.type = visualization_msgs::Marker::LINE_LIST;
00100 
00101   ptmark = cammark;
00102   ptmark.color.r = 1.0f;
00103   ptmark.color.g = 0.0f;
00104   ptmark.color.b = 0.0f;
00105   ptmark.color.a = 0.5f;
00106   ptmark.scale.x = 0.01;
00107   ptmark.scale.y = 0.01;
00108   ptmark.scale.z = 0.01;
00109   ptmark.type = visualization_msgs::Marker::POINTS;
00110 
00111 
00112   // draw points, decimated
00113   int npts = sba.tracks.size();
00114   ptmark.points.resize(npts/dec+1);
00115   for (int i=0, ii=0; i<npts; i+=dec, ii++)
00116     {
00117       Vector4d &pt = sba.tracks[i].point;
00118       ptmark.points[ii].x = pt(0);
00119       ptmark.points[ii].y = pt(2);
00120       ptmark.points[ii].z = -pt(1);
00121     }
00122 
00123   // draw cameras
00124   int ncams = sba.nodes.size();
00125   cammark.points.resize(ncams*6);
00126   for (int i=0, ii=0; i<ncams; i++)
00127     {
00128       Node &nd = sba.nodes[i];
00129       Vector3d opt;
00130       Matrix<double,3,4> tr;
00131       transformF2W(tr,nd.trans,Quaternion<double>(nd.qrot));
00132 
00133       cammark.points[ii].x = nd.trans.x();
00134       cammark.points[ii].y = nd.trans.z();
00135       cammark.points[ii++].z = -nd.trans.y();
00136       opt = tr*Vector4d(0,0,0.3,1);
00137       cammark.points[ii].x = opt.x();
00138       cammark.points[ii].y = opt.z();
00139       cammark.points[ii++].z = -opt.y();
00140 
00141       cammark.points[ii].x = nd.trans.x();
00142       cammark.points[ii].y = nd.trans.z();
00143       cammark.points[ii++].z = -nd.trans.y();
00144       opt = tr*Vector4d(0.1,0,0,1);
00145       cammark.points[ii].x = opt.x();
00146       cammark.points[ii].y = opt.z();
00147       cammark.points[ii++].z = -opt.y();
00148 
00149       cammark.points[ii].x = nd.trans.x();
00150       cammark.points[ii].y = nd.trans.z();
00151       cammark.points[ii++].z = -nd.trans.y();
00152       opt = tr*Vector4d(0,0.1,0,1);
00153       cammark.points[ii].x = opt.x();
00154       cammark.points[ii].y = opt.z();
00155       cammark.points[ii++].z = -opt.y();
00156     }
00157   
00158   cam_pub.publish(cammark);
00159   pt_pub.publish(ptmark);
00160 }
00161 
00162 
00163 
00164 //
00165 // first argument is the name of input file, Bundler format
00166 //    expects good focal length and distortion correction
00167 // runs sba
00168 //
00169 
00170 int main(int argc, char **argv)
00171 {
00172   char *fin;
00173 
00174   if (argc < 3)
00175     {
00176       cout << "Arguments are: <cam params> <input filename> [<number of nodes to use>]" << endl;
00177       return -1;
00178     }
00179 
00180   // number of nodes to use
00181   int nnodes = 1000000;
00182 
00183   if (argc > 3)
00184     nnodes = atoi(argv[3]);
00185 
00186   int doiters = 10;
00187   if (argc > 4)
00188     doiters = atoi(argv[4]);
00189 
00190   fin = argv[2];
00191 
00192   // get camera parameters, in the form: fx fy cx cy tx
00193   fstream fstr;
00194   fstr.open(argv[1],fstream::in);
00195   if (!fstr.is_open())
00196     {
00197       printf("Can't open camera file %s\n",argv[1]);
00198       exit(0);
00199     }
00200   CamParams camp;
00201   fstr >> camp.fx;
00202   fstr >> camp.fy;
00203   fstr >> camp.cx;
00204   fstr >> camp.cy;
00205   fstr >> camp.tx;
00206 
00207   cout << "Cam params: " << camp.fx << " " << camp.fy << " " << camp.cx
00208        << " " << camp.cy << " " << camp.tx << endl;
00209 
00210 
00211   // node translation
00212   std::vector< Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d> > ntrans;
00213   // node rotation
00214   std::vector< Eigen::Vector4d, Eigen::aligned_allocator<Eigen::Vector4d> > nqrot;
00215   // constraint indices
00216   std::vector< Eigen::Vector2i, Eigen::aligned_allocator<Eigen::Vector2i> > cind;
00217   // constraint local translation 
00218   std::vector< Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d> > ctrans;
00219   // constraint local rotation as quaternion
00220   std::vector< Eigen::Vector4d, Eigen::aligned_allocator<Eigen::Vector4d> > cqrot;
00221   // constraint covariance
00222   std::vector< Eigen::Matrix<double,6,6>, Eigen::aligned_allocator<Eigen::Matrix<double,6,6> > > cvar;
00223   // tracks
00224   std::vector<struct tinfo> tracks;
00225 
00226 
00227   ReadSPAFile(fin,ntrans,nqrot,cind,ctrans,cqrot,cvar,tracks);
00228 
00229   cout << "[ReadSPAFile] Found " << (int)ntrans.size() << " nodes and " 
00230        << (int)cind.size() << " constraints, " << (int)tracks.size()
00231        << " projection pairs" << endl;
00232 
00233 
00234   // set up markers for visualization
00235   ros::init(argc, argv, "VisBundler");
00236   ros::NodeHandle n ("~");
00237   ros::Publisher pt_pub = n.advertise<visualization_msgs::Marker>("points", 0);
00238   ros::Publisher cam_pub = n.advertise<visualization_msgs::Marker>("cameras", 0);
00239 
00240   // construct an SBA system
00241   SysSBA sba;
00242   Node::initDr();
00243 
00244   vector<Frame> frames;
00245   Frame frm;
00246   frm.setCamParams(camp);       // put in camera params
00247 
00248   // add in nodes
00249   for (int i=0; i<(int)ntrans.size(); i++)
00250     {
00251       if (i>=nnodes) break;
00252 
00253       Node nd;
00254 
00255       // rotation
00256       Quaternion<double> frq;
00257       frq.coeffs() = nqrot[i];
00258       frq.normalize();
00259       if (frq.w() <= 0.0) frq.coeffs() = -frq.coeffs();
00260       nd.qrot = frq.coeffs();
00261 
00262       // translation
00263       Vector4d v;
00264       v.head(3) = ntrans[i];
00265       v(3) = 1.0;
00266       nd.trans = v;
00267       nd.setTransform();        // set up world2node transform
00268       nd.setKcam(camp);         // set up node2image projection
00269       nd.setDri();              // set rotational derivatives
00270 
00271       // add to system
00272       sba.nodes.push_back(nd);
00273 
00274       // set up frame
00275       frames.push_back(frm);
00276     }
00277 
00278 
00279   // add in points and projections
00280   // first version, just do 2-point tracks
00281   std::vector<std::pair<int,int> > pairs;
00282   double ftx = camp.fx * camp.tx;
00283   for (int i=0; i<(int)tracks.size(); i++)
00284     {
00285       tinfo &ti = tracks[i];
00286       if (ti.fn0 >= (int)frames.size() || ti.fn1 >= (int)frames.size())
00287         {
00288           cout << "Bad frame index at track " << i << endl;
00289           return -1;
00290         }
00291       Frame &f0 = frames[ti.fn0];
00292       Frame &f1 = frames[ti.fn1];
00293       Node &nd0 = sba.nodes[ti.fn0];
00294       Node &nd1 = sba.nodes[ti.fn1];
00295       int fpn0 = ti.fpn0;
00296       int fpn1 = ti.fpn1;
00297       if (fpn0 >= (int)f0.kpts.size()) // new frame point
00298         {
00299           f0.kpts.resize(fpn0+1);
00300           f0.ipts.resize(fpn0+1,-1);
00301           f0.pts.resize(fpn0+1);
00302         }
00303       if (fpn1 >= (int)f1.kpts.size()) // new frame point
00304         {
00305           f1.kpts.resize(fpn1+1);
00306           f1.ipts.resize(fpn1+1,-1);
00307           f1.pts.resize(fpn1+1);
00308         }
00309 
00310       // set up point identity pairs
00311       int pn0 = f0.ipts[fpn0];
00312       int pn1 = f1.ipts[fpn1];
00313       if (pn0 < 0)              // new point
00314         f0.ipts[fpn0] = i;
00315       else
00316         pairs.push_back(std::pair<int,int>(pn0,i));
00317       if (pn1 < 0)              // new point
00318         f1.ipts[fpn1] = i;
00319       else
00320         pairs.push_back(std::pair<int,int>(pn1,i));
00321 
00322 
00323       // just add a new track for two frames
00324       Point pt0(ti.x0,ti.y0,ti.z0,1.0);
00325       Matrix<double,3,4> f2w;
00326       Quaterniond qr;
00327       qr = nd0.qrot;
00328       transformF2W(f2w,nd0.trans,qr);
00329       pt0.head(3) = f2w*pt0;
00330       sba.addPoint(pt0);
00331       Vector2d kp0,kp1;
00332       nd0.project2im(kp0,pt0);
00333 
00334       Point pt1(ti.x1,ti.y1,ti.z1,1.0);
00335       qr = nd1.qrot;
00336       transformF2W(f2w,nd1.trans,qr);
00337       pt1.head(3) = f2w*pt1;
00338       nd1.project2im(kp1,pt1);
00339 
00340 #if 0
00341       cout << kp0.transpose() << endl;
00342       cout << ti.u0 << " " << ti.v0 << " " << ti.u0-ftx/ti.z0 << endl;
00343       cout << kp1.transpose() << endl;
00344       cout << ti.u1 << " " << ti.v1 << " " << ti.u1-ftx/ti.z1 << endl;
00345       cout << pt0.head(3).transpose() << endl;
00346       cout << pt1.head(3).transpose() << endl << endl;
00347 #endif
00348 
00349       // projections
00350       int pti = sba.tracks.size() - 1;
00351       Vector3d nkp0(ti.u0,ti.v0,ti.u0-ftx/ti.z0);
00352       sba.addStereoProj(ti.fn0,pti,nkp0);
00353       Vector3d nkp1(ti.u1,ti.v1,ti.u1-ftx/ti.z1);
00354       sba.addStereoProj(ti.fn1,pti,nkp1);
00355     }
00356   
00357   
00358   cout << "Number of tracks: " << sba.tracks.size() << endl;
00359   cout << "Initial RMS cost per projection: " << sqrt(sba.calcCost()/(double)(sba.tracks.size()*2)) << endl;
00360   sba.printStats();
00361 
00362   // draw and wait
00363   cout << endl << "drawing..." << endl << endl;
00364   drawgraph(sba,cam_pub,pt_pub,2); // every 2nd point
00365   char buf[10];
00366   cin.getline(buf,10);
00367 
00368   long long t0,t1;
00369 
00370 #if 0
00371   t0 = utime();
00372   sba.doSBA(10,1.0e-4,1);
00373   t1 = utime();
00374   cout << endl << "drawing..." << endl << endl;
00375   drawgraph(sba,cam_pub,pt_pub,2); // every 2nd point
00376   cin.getline(buf,10);
00377 #endif
00378 
00379   // merge point tracks
00380   cout << "Found " << pairs.size() << " connected tracks" << endl;
00381 #if 0
00382   for (int i=0; i<(int)pairs.size(); i++)
00383     cout << pairs[i].first << " " << pairs[i].second << endl;
00384 #endif
00385   sba.mergeTracks(pairs);
00386   cout << "Number of tracks: " << sba.tracks.size() << endl;
00387   cout << "Initial RMS cost per projection: " << sqrt(sba.calcCost()/(double)(sba.tracks.size()*2)) << endl;
00388   sba.printStats();
00389 
00390 
00391 #if 1
00392   sba::writeLourakisFile((char *)"intel", sba);
00393   cout << endl << "Wrote SBA system in Lourakis format" << endl << endl;
00394 #endif
00395 
00396   // file for saving results
00397 #ifdef SAVE_RESULTS
00398   FILE *fd = fopen("results.txt","a");
00399 #endif
00400 
00401       // average track size
00402       int npts = sba.tracks.size();
00403       double tsize = 0;             // average track size
00404       for (int i=0; i<npts; i++)
00405         tsize += sba.tracks[i].projections.size();
00406       tsize = tsize/(double)npts;
00407 
00408       // matrix connections
00409       int ncams = sba.nodes.size();
00410       int nprjs = 0;
00411       MatrixXi conns;
00412       conns.setIdentity(ncams,ncams);
00413       for (int i=0; i<(int)sba.tracks.size(); i++)
00414         {
00415           ProjMap &prjs = sba.tracks[i].projections;
00416           nprjs += prjs.size();
00417           if (prjs.size()>1)
00418             for(ProjMap::iterator itr = prjs.begin(); itr != prjs.end(); itr++)
00419               {
00420                 Proj &prj = itr->second;
00421                 for(ProjMap::iterator itr2 = itr; itr2 != prjs.end(); itr2++)
00422                   {
00423                     Proj &prj2 = itr2->second;
00424                     conns(prj.ndi,prj2.ndi) = 1;
00425                     conns(prj2.ndi,prj.ndi) = 1;
00426                   }
00427               }
00428         }
00429 
00430       int tot = 0;
00431       for (int i=0; i<ncams; i++)
00432         for (int j=0; j<ncams; j++)
00433           tot += conns(i,j);
00434       double mfill = (double)tot/(double)(ncams*ncams);
00435 
00436       printf("\nCams: %d  Avg projs: %0.1f  Avg. track size: %0.1f  Percent fill: %0.1f\n\n",
00437              ncams, (double)nprjs/(double)ncams, tsize, 100.0*mfill);
00438 
00439 #ifdef SAVE_RESULTS
00440       fprintf(fd,"%d %0.1f %0.1f %0.1f ",
00441               ncams, (double)nprjs/(double)ncams, tsize, 100.0*mfill);
00442 #endif
00443 
00444   sba.nFixed = 1;
00445   sba.csp.useCholmod = true;
00446 
00447   t0 = utime();
00448   sba.doSBA(1,1.0e-4,1);
00449   t1 = utime();
00450 
00451 #ifdef SAVE_RESULTS
00452       fprintf(fd,"%0.1f %0.1f %0.1f %0.1f\n",
00453               (sba.t2-sba.t1)*0.001,
00454               (sba.t1-sba.t0)*0.001,
00455               (sba.t3-sba.t2)*0.001,
00456               (t1-t0)*0.001);
00457       fflush(fd);
00458   fclose(fd);
00459 #endif
00460 
00461 
00462   cout << endl << "drawing..." << endl << endl;
00463   drawgraph(sba,cam_pub,pt_pub,2); // every 2nd point
00464   cin.getline(buf,10);
00465 
00466   // save nodes and points to a file
00467   char *name = "intel-sys.txt";
00468   FILE *fn = fopen(name,"w");
00469   if (fn == NULL)
00470     {
00471       cout << "[WriteFile] Can't open file " << name << endl;
00472       return -1;
00473     }
00474   fprintf(fn,"Node poses: node #, trans XYZ, rot XYZW\n");
00475   for (int i=0; i<(int)sba.nodes.size(); i++)
00476     {
00477       Node nd = sba.nodes[i];
00478       fprintf(fn,"%d %f %f %f %f %f %f %f\n", i, nd.trans(0), nd.trans(1), nd.trans(2),
00479               nd.qrot.x(), nd.qrot.y(), nd.qrot.z(), nd.qrot.w());
00480     }
00481   cout << "Wrote node poses to file " << name << endl;
00482   
00483 
00484   return 0;
00485 
00486 #if 0
00487   cout << endl;
00488 
00489   cout << "Bad projs (> 100 pix): " << sba.countBad(100.0) 
00490        << "  Cost without: " << sqrt(sba.calcCost(100.0)/nprjs) << endl;
00491   cout << "Bad projs (> 20 pix): " << sba.countBad(20.0)
00492        << "  Cost without: " << sqrt(sba.calcCost(20.0)/nprjs) << endl;
00493   cout << "Bad projs (> 10 pix): " << sba.countBad(10.0)
00494        << "  Cost without: " << sqrt(sba.calcCost(10.0)/nprjs) << endl;
00495   int n = sba.removeBad(20.0);
00496   cout << "Removed " << n << " projs with >10px error" << endl;
00497   sba.printStats();
00498 #endif
00499 
00500 #if 0
00501   sba.doSBA(2);
00502   sba.setupSys(0.0);
00503   sba.writeSparseA((char *)"A819.venice");
00504 #endif
00505 
00506   //  sba.setConnMat(minpts);
00507   //  sba.setConnMatReduced(minpts);             // finds spanning tree
00508 
00509   //  sba.doSBA(30,1.0e-3,true);
00510   sba.doSBA(1,1e-3,1);
00511   drawgraph(sba,cam_pub,pt_pub,2);
00512   for (int i=0; i<20; i++)
00513     {
00514       sba.doSBA(1,0.0,1);      
00515       drawgraph(sba,cam_pub,pt_pub,2);
00516     }
00517 
00518   return 0;
00519 }


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