• 023 gtsam/examples/RangeISAMExample_plaza2.cpp


    一、说明和include files

    // Both relative poses and recovered trajectory poses will be stored as Pose2 objects
    #include 
    
    // Each variable in the system (poses and landmarks) must be identified with a unique key.
    // We can either use simple integer keys (1, 2, 3, ...) or symbols (X1, X2, L1).
    // Here we will use Symbols
    #include 
    
    // We want to use iSAM2 to solve the range-SLAM problem incrementally
    #include 
    
    // iSAM2 requires as input a set set of new factors to be added stored in a factor graph,
    // and initial guesses for any new variables used in the added factors
    #include 
    #include 
    
    // We will use a non-liear solver to batch-inituialize from the first 150 frames
    #include 
    
    // In GTSAM, measurement functions are represented as 'factors'. Several common factors
    // have been provided with the library for solving robotics SLAM problems.
    #include 
    #include 
    #include 
    
    // Standard headers, added last, so we know headers above work on their own
    #include 
    #include 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    二、加载数据集

    // load the odometry
    // DR: Odometry Input (delta distance traveled and delta heading change)
    //    Time (sec)  Delta Dist. Trav. (m) Delta Heading (rad)
    typedef pair<double, Pose2> TimedOdometry;
    list<TimedOdometry> readOdometry() {
      list<TimedOdometry> odometryList;
      string data_file = findExampleDataFile("Plaza2_DR.txt");
      ifstream is(data_file.c_str());
    
      while (is) {
        double t, distance_traveled, delta_heading;
        is >> t >> distance_traveled >> delta_heading;
        odometryList.push_back(
            TimedOdometry(t, Pose2(distance_traveled, 0, delta_heading)));
      }
      is.clear(); /* clears the end-of-file and error flags */
      return odometryList;
    }
    
    // load the ranges from TD
    //    Time (sec)  Sender / Antenna ID Receiver Node ID  Range (m)
    typedef boost::tuple<double, size_t, double> RangeTriple;
    vector<RangeTriple> readTriples() {
      vector<RangeTriple> triples;
      string data_file = findExampleDataFile("Plaza2_TD.txt");
      ifstream is(data_file.c_str());
    
      while (is) {
        double t, sender, range;
        size_t receiver;
        is >> t >> sender >> receiver >> range;
        triples.push_back(RangeTriple(t, receiver, range));
      }
      is.clear(); /* clears the end-of-file and error flags */
      return triples;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    数据读取和参数设置

      // load Plaza2 data
      list<TimedOdometry> odometry = readOdometry();
    //  size_t M = odometry.size();
    
      vector<RangeTriple> triples = readTriples();
      size_t K = triples.size();
    
      // parameters
      size_t minK = 150; // minimum number of range measurements to process initially
      size_t incK = 25; // minimum number of range measurements to process after
      bool groundTruth = false;
      bool robust = true;
    
      // Set Noise parameters
      Vector priorSigmas = Vector3(1,1,M_PI);
      Vector odoSigmas = Vector3(0.05, 0.01, 0.1);
      double sigmaR = 100; // range standard deviation
      const NM::Base::shared_ptr // all same type
      priorNoise = NM::Diagonal::Sigmas(priorSigmas), //prior
      odoNoise = NM::Diagonal::Sigmas(odoSigmas), // odometry
      gaussian = NM::Isotropic::Sigma(1, sigmaR), // non-robust
      tukey = NM::Robust::Create(NM::mEstimator::Tukey::Create(15), gaussian), //robust
      rangeNoise = robust ? tukey : gaussian;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    robust kernel
     
    初始化iSAM和添加先验

      // Initialize iSAM
      ISAM2 isam;
    
      // Add prior on first pose
      Pose2 pose0 = Pose2(-34.2086489999201, 45.3007639991120,
          M_PI - 2.02108900000000);
      NonlinearFactorGraph newFactors;
      newFactors.addPrior(0, pose0, priorNoise);
      Values initial;
      initial.insert(0, pose0);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    landmarks初始化

      //  initialize points
      if (groundTruth) { // from TL file
        initial.insert(symbol('L', 1), Point2(-68.9265, 18.3778));
        initial.insert(symbol('L', 6), Point2(-37.5805, 69.2278));
        initial.insert(symbol('L', 0), Point2(-33.6205, 26.9678));
        initial.insert(symbol('L', 5), Point2(1.7095, -5.8122));
      } else { // drawn from sigma=1 Gaussian in matlab version
        initial.insert(symbol('L', 1), Point2(3.5784, 2.76944));
        initial.insert(symbol('L', 6), Point2(-1.34989, 3.03492));
        initial.insert(symbol('L', 0), Point2(0.725404, -0.0630549));
        initial.insert(symbol('L', 5), Point2(0.714743, -0.204966));
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
      // Loop over odometry
      gttic_(iSAM);
      for(const TimedOdometry& timedOdometry: odometry) {
        //--------------------------------- odometry loop -----------------------------------------
        double t;
        Pose2 odometry;
        boost::tie(t, odometry) = timedOdometry;
    
        // add odometry factor //添加里程计因子
        newFactors.push_back(BetweenFactor<Pose2>(i-1, i, odometry, odoNoise));
    
        // predict pose and add as initial estimate //预测估计值
        Pose2 predictedPose = lastPose.compose(odometry);
        lastPose = predictedPose;
        initial.insert(i, predictedPose);
    
        // Check if there are range factors to be added
        // 添加RangeFactor
        while (k < K && t >= boost::get<0>(triples[k])) {
          size_t j = boost::get<1>(triples[k]);
          double range = boost::get<2>(triples[k]);
          newFactors.push_back(RangeFactor<Pose2, Point2>(i, symbol('L', j), range,rangeNoise));
          k = k + 1;
          countK = countK + 1;
        }
    
        // Check whether to update iSAM 2
        // 更新iSAM2
        if ((k > minK) && (countK > incK)) {
          if (!initialized) { // Do a full optimize for first minK ranges
            gttic_(batchInitialization);
            LevenbergMarquardtOptimizer batchOptimizer(newFactors, initial);
            initial = batchOptimizer.optimize();
            gttoc_(batchInitialization);
            initialized = true;
          }
          gttic_(update);
          isam.update(newFactors, initial);
          gttoc_(update);
          gttic_(calculateEstimate);
          Values result = isam.calculateEstimate();
          gttoc_(calculateEstimate);
          lastPose = result.at<Pose2>(i);
          newFactors = NonlinearFactorGraph();
          initial = Values();
          countK = 0;
        }
        i += 1;
        //--------------------------------- odometry loop -----------------------------------------
      } // end for
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
  • 相关阅读:
    使用Python进行云计算:AWS、Azure、和Google Cloud的比较
    山东大学单片机原理与应用实验 3.1 基本并行I/O口实验
    NV040D语音芯片:智能破壁机,悦享美好生活
    黑苹果系统安装常见问题汇集
    行业资讯 | 深圳:BIM法定化,开历史之先河
    C++11特性-自动类型推导
    《机械工程基础》复习题
    Kotlin 知识体系
    小米面试——计算机视觉算法实习生
    大模型下一场战事,为什么是AI Agent?
  • 原文地址:https://blog.csdn.net/weixin_43848456/article/details/127696115