Esempio n. 1
0
  // add a node at a pose
  // <pos> is x,y,th, with th in radians
  // returns node position 
  int SysSPA2d::addNode(const Vector3d &pos, int id)
  {
    Node2d nd;
    nd.nodeId = id;

    nd.arot = pos(2);
    nd.trans.head(2) = pos.head(2);
    nd.trans(2) = 1.0;

    // add in to system
    nd.setTransform();          // set up world2node transform
    nd.setDr();
    int ndi = nodes.size();
    nodes.push_back(nd);
    return ndi;
  }
Esempio n. 2
0
// set up spiral frame/frame system
void
spa2d_spiral_setup(SysSPA2d &spa, 
                 vector<Matrix<double,3,1>, Eigen::aligned_allocator<Matrix<double,3,1> > > &cps,
                 Matrix<double,3,3> prec, Matrix<double,3,3> vprec,
                 Matrix<double,3,3> a10prec, Matrix<double,3,3> a15prec,
                 double kfang, double initang, double cycles, 
                 double pnoise, double qnoise, double snoise, double dpnoise, double dqnoise)
{

  // random seed
  unsigned short seed = (unsigned short)utime();
  seed48(&seed);


  //
  // spiral trajectory
  //

  double radius = 8.0;          // initial spiral radius, m
  double rdiff  = 1.0;          // spiral radius expansion per cycle

  double ang = initang;         // initial angle
  double cycle_kfs = 360.0/kfang;
  int cyc_kfs = (int)(cycle_kfs+.01);
  printf("\n[SPA Spiral] Setting up spiral with %d keyframes, %d per cycle\n", (int)(cycles*cycle_kfs), (int)cycle_kfs);
  //  printf("[SPA Spiral] Camera poses:\n");
  
  for (int i=0; i<cycles*cycle_kfs; ++i, ang+=kfang*M_PI/180, radius+=rdiff/cycle_kfs)
    {
      if (ang > 2*M_PI)
        ang -= 2*M_PI;

      // frame rotation in the world
      double a = ang+M_PI/2.0;
      double z = radius*cos(ang);
      double x = radius*sin(ang)+radius;
      Vector3d frt(x,z,1.0);    // frame position in the world

      // make node
      Node2d nd;
      nd.arot = a;
      nd.trans = frt;
      //      cout << "Translation: " << nd.trans.transpose() << endl << endl;
      nd.normArot();
      nd.setTransform();        // set up world2node transform
      nd.setDr();

      // save it
      Matrix<double,3,1> pos;
      pos.head(2) = frt.head(2);
      pos(2) = nd.arot;
      cps.push_back(pos);

      // add to SPA
      spa.nodes.push_back(nd);

      // print out camera poses
      //      printf("   %f %f %f %f %f %f\n", x,y,z,0.0,ang+M_PI/2,0.0);
    }




  // add error to initial positions
  qnoise = M_PI*qnoise/180.0; // convert to radians
  Vector2d tinc;
  double vinc = 1.0;
  for (int i=0; i<(int)spa.nodes.size(); ++i)
    {
      Node2d &nd = spa.nodes[i];

      // add cross-links between cycles
      if (i+cyc_kfs < (int)spa.nodes.size()-2 &&
          (1 || (i%cyc_kfs < 3 || (i+cyc_kfs/2)%cyc_kfs < 3))) // add in cross-links
        {
          add_p2con2d(spa, i+cyc_kfs, i, vprec, vinc-1.0, 0.0);
          //          add_p2con(spa, i+cyc_kfs, i, vprec, vinc-1.0, 0.0);
          //          add_p2con(spa, i+cyc_kfs, i, vprec, vinc-1.0, 0.0);
          //          printf("%d %d \n", i, i+cyc_kfs);
        }


      if (i>=spa.nFixed)        // add error
        {
          Node2d &ndp = spa.nodes[i-1];
          tinc = ndp.w2n * nd.trans;

          // modify tinc each time...
          double inc = 1.0 + snoise * (drand48() - 0.5);
          tinc *= inc;
          vinc *= inc;


          Vector2d frt2(drand48()*pnoise - pnoise/2,
                        drand48()*pnoise - pnoise/2);
          frt2 += tinc;         // ok, randomly modified increment

          //          cout << endl << nd.trans.head(3).transpose() << endl;

          nd.trans.head(2) = ndp.w2n.block<2,2>(0,0).transpose()*frt2 + ndp.trans.head(2);

          //          cout << nd.trans.head(3).transpose() << endl;


          double a = drand48()*qnoise - qnoise/2;
          nd.arot += a;
          nd.normArot();
          nd.setTransform();    // set up world2node transform
          nd.setDr();           // set rotational derivatives
        }
    }

  // loop over cameras, adding measurements
  for (int i=1; i<(int)cps.size(); ++i)
    {
      add_p2con2d(spa, i-1, i, prec, 0.0, 0.0);
      if (i>2)
        add_p2con2d(spa, i-2, i, a10prec, 0.0, 0.0);
      if (i>3)
        add_p2con2d(spa, i-3, i, a15prec, 0.0, 0.0);
      //      if (i > cycle_kfs)        // add in cross-links
      //        add_p2con(spa, i, i-cycle_kfs, vprec, 0.0, 0.0);
      //      printf("[SPA Spiral] Added a measurement %d -> %d\n", i-1, i);
    }

  // finally, some initial random noise on node positions and angles
  for (int i=0; i<(int)spa.nodes.size(); ++i)
    {
      Node2d &nd = spa.nodes[i];

      if (i>=spa.nFixed)        // add error
        {
          Vector2d frt2(drand48()*dpnoise - dpnoise/2,
                        drand48()*dpnoise - dpnoise/2);
          nd.trans.head(2) += frt2;

          dqnoise = M_PI*dqnoise/180.0; // convert to radians
          double a = drand48()*dqnoise - dqnoise/2;
          nd.arot += a;
          nd.normArot();
          nd.setTransform();    // set up world2node transform
          nd.setDr();           // set rotational derivatives
        }
    }


 }
Esempio n. 3
0
int main(int argc, char **argv)
{
  char *fin;

  if (argc < 2)
    {
      cout << "Arguments are:  <input filename> [<number of nodes to use>]" << endl;
      return -1;
    }

  // number of nodes to use
  int nnodes = 0;

  if (argc > 2)
    nnodes = atoi(argv[2]);

  int doiters = 10;
  if (argc > 3)
    doiters = atoi(argv[3]);

  fin = argv[1];

  // node translation
  std::vector< Eigen::Vector2d, Eigen::aligned_allocator<Eigen::Vector2d> > ntrans;
  // node rotation
  std::vector< double > arots;
  // constraint indices
  std::vector< Eigen::Vector2i, Eigen::aligned_allocator<Eigen::Vector2i> > cind;
  // constraint local translation 
  std::vector< Eigen::Vector2d, Eigen::aligned_allocator<Eigen::Vector2d> > ctrans;
  // constraint local rotation as quaternion
  std::vector< double > carot;
  // constraint precision
  std::vector< Eigen::Matrix<double,3,3>, Eigen::aligned_allocator<Eigen::Matrix<double,3,3> > > cvar;
  // scans
  std::vector< std::vector< Eigen::Vector2d, Eigen::aligned_allocator<Eigen::Vector2d> > > scans;

  ReadSPA2dFile(fin,ntrans,arots,cind,ctrans,carot,cvar,scans);

  cout << "# [ReadSPA2dFile] Found " << (int)ntrans.size() << " nodes and " 
       << (int)cind.size() << " constraints" << endl;


  // system
  SysSPA2d spa;
  spa.verbose=false;
  spa.print_iros_stats=false;
  //  spa.useCholmod(false);
  spa.useCholmod(true);


  // use max nodes if we haven't specified it
  if (nnodes == 0) nnodes = ntrans.size();
  if (nnodes > (int)ntrans.size()) nnodes = ntrans.size();

  // add first node
  Node2d nd;

  // rotation
  nd.arot = arots[0];
  // translation
  Vector3d v;
  v.head(2) = ntrans[0];
  v(2) = 1.0;
  nd.trans = v;

  double cumtime = 0.0;
  //cout << nd.trans.transpose() << endl << endl;

  // add to system
  nd.setTransform();            // set up world2node transform
  nd.setDr();
  spa.nodes.push_back(nd);
  // add in nodes
  for (int i=0; i<nnodes-1; i+=doiters)
    {
      for (int j=0; j<doiters; j++)
        addnode(spa, i+j+1, ntrans, arots, cind, ctrans, carot, cvar);

      // cout << "[SysSPA2d] Using " << (int)spa.nodes.size() << " nodes and " 
      //      << (int)spa.p2cons.size() << " constraints" << endl;

      long long t0, t1;

      spa.nFixed = 1;           // one fixed frame

      t0 = utime();
      //      spa.doSPA(1,1.0e-4,SBA_SPARSE_CHOLESKY);
      spa.doSPA(1,1.0e-4,SBA_BLOCK_JACOBIAN_PCG,1.0e-8,15);
      t1 = utime();
      cumtime += t1 - t0;
      if (i%100 == 0) 
        {
          cout << "[SPA2D] iteration: " << i << " squared cost " << spa.errcost << endl;
          cerr << i << " " << cumtime*.001 << " " << spa.errcost << endl;
        }
    }



  printf("[TestSPA2D] Compute took %0.2f ms/node, total time %0.2f ms; error %0.2f\n", 0.001*(double)cumtime/(double)nnodes, cumtime*0.001, spa.errcost);
  // printf("[TestSPA] Accepted iterations: %d\n", niters);
  // printf("[TestSPA] Distance cost: %0.3f m rms\n", sqrt(spa.calcCost(true)/(double)spa.p2cons.size()));

    // if (verbose()){
    //   cerr << "iteration= " << niters 
    // 	   << "\t chi2= " << spa.calcCost();
    //     << "\t time= " << 0.0
    //     << "\t cumTime= " << 0.0
    //     << "\t kurtChi2= " << this->kurtChi2()
    //     << endl;
    // }



#if 0
  ofstream ofs("opt2d-ground.txt");
  for (int i=0; i<(int)ntrans.size(); i++)
    ofs << ntrans[i].transpose() << endl;
  ofs.close();

  ofstream ofs2("opt2d-opt.txt");
  for (int i=0; i<(int)spa.nodes.size(); i++)
    ofs2 << spa.nodes[i].trans.transpose().head(2) << endl;
  ofs2.close();
#endif

  //  spa.writeSparseA("sphere-sparse.txt",true);

  return 0;
}