Arguments
							parent
							
								
									3f11c5dd01
								
							
						
					
					
						commit
						ee2f3c5c2b
					
				| 
						 | 
				
			
			@ -31,11 +31,12 @@
 | 
			
		|||
 | 
			
		||||
#include <boost/algorithm/string/classification.hpp>
 | 
			
		||||
#include <boost/algorithm/string/split.hpp>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
using namespace gtsam;
 | 
			
		||||
using namespace boost::algorithm;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -43,25 +44,30 @@ using symbol_shorthand::L;
 | 
			
		|||
using symbol_shorthand::M;
 | 
			
		||||
using symbol_shorthand::X;
 | 
			
		||||
 | 
			
		||||
const size_t kMaxLoopCount = 3000;  // Example default value
 | 
			
		||||
 | 
			
		||||
// 3000: {1: 62s, 2: 21s, 3: 20s, 4: 31s, 5: 39s} No DT optimizations
 | 
			
		||||
// 3000: {1: 65s, 2: 20s, 3: 16s, 4: 21s, 5: 28s} With DT optimizations
 | 
			
		||||
// 3000: {1: 59s, 2: 19s, 3: 18s, 4: 26s, 5: 33s} With DT optimizations + merge
 | 
			
		||||
const size_t kUpdateFrequency = 3;
 | 
			
		||||
 | 
			
		||||
const size_t kMaxNrHypotheses = 10;
 | 
			
		||||
 | 
			
		||||
auto kOpenLoopModel = noiseModel::Diagonal::Sigmas(Vector3::Ones() * 10);
 | 
			
		||||
const double kOpenLoopConstant = kOpenLoopModel->negLogConstant();
 | 
			
		||||
 | 
			
		||||
auto kPriorNoiseModel = noiseModel::Diagonal::Sigmas(
 | 
			
		||||
    (Vector(3) << 0.0001, 0.0001, 0.0001).finished());
 | 
			
		||||
 | 
			
		||||
auto kPoseNoiseModel = noiseModel::Diagonal::Sigmas(
 | 
			
		||||
    (Vector(3) << 1.0 / 30.0, 1.0 / 30.0, 1.0 / 100.0).finished());
 | 
			
		||||
const double kPoseNoiseConstant = kPoseNoiseModel->negLogConstant();
 | 
			
		||||
 | 
			
		||||
// Experiment Class
 | 
			
		||||
class Experiment {
 | 
			
		||||
 public:
 | 
			
		||||
  // Parameters with default values
 | 
			
		||||
  size_t maxLoopCount = 3000;
 | 
			
		||||
 | 
			
		||||
  // 3000: {1: 62s, 2: 21s, 3: 20s, 4: 31s, 5: 39s} No DT optimizations
 | 
			
		||||
  // 3000: {1: 65s, 2: 20s, 3: 16s, 4: 21s, 5: 28s} With DT optimizations
 | 
			
		||||
  // 3000: {1: 59s, 2: 19s, 3: 18s, 4: 26s, 5: 33s} With DT optimizations +
 | 
			
		||||
  // merge
 | 
			
		||||
  size_t updateFrequency = 3;
 | 
			
		||||
 | 
			
		||||
  size_t maxNrHypotheses = 10;
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  std::string filename_;
 | 
			
		||||
  HybridSmoother smoother_;
 | 
			
		||||
| 
						 | 
				
			
			@ -78,7 +84,7 @@ class Experiment {
 | 
			
		|||
   */
 | 
			
		||||
  void writeResult(const Values& result, size_t numPoses,
 | 
			
		||||
                   const std::string& filename = "Hybrid_city10000.txt") {
 | 
			
		||||
    ofstream outfile;
 | 
			
		||||
    std::ofstream outfile;
 | 
			
		||||
    outfile.open(filename);
 | 
			
		||||
 | 
			
		||||
    for (size_t i = 0; i < numPoses; ++i) {
 | 
			
		||||
| 
						 | 
				
			
			@ -104,9 +110,8 @@ class Experiment {
 | 
			
		|||
    auto f1 = std::make_shared<BetweenFactor<Pose2>>(
 | 
			
		||||
        X(keyS), X(keyT), measurement, kPoseNoiseModel);
 | 
			
		||||
 | 
			
		||||
    std::vector<NonlinearFactorValuePair> factors{
 | 
			
		||||
        {f0, kOpenLoopModel->negLogConstant()},
 | 
			
		||||
        {f1, kPoseNoiseModel->negLogConstant()}};
 | 
			
		||||
    std::vector<NonlinearFactorValuePair> factors{{f0, kOpenLoopConstant},
 | 
			
		||||
                                                  {f1, kPoseNoiseConstant}};
 | 
			
		||||
    HybridNonlinearFactor mixtureFactor(l, factors);
 | 
			
		||||
    return mixtureFactor;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -114,14 +119,14 @@ class Experiment {
 | 
			
		|||
  /// @brief Create hybrid odometry factor with discrete measurement choices.
 | 
			
		||||
  HybridNonlinearFactor hybridOdometryFactor(
 | 
			
		||||
      size_t numMeasurements, size_t keyS, size_t keyT, const DiscreteKey& m,
 | 
			
		||||
      const std::vector<Pose2>& poseArray,
 | 
			
		||||
      const SharedNoiseModel& poseNoiseModel) {
 | 
			
		||||
      const std::vector<Pose2>& poseArray) {
 | 
			
		||||
    auto f0 = std::make_shared<BetweenFactor<Pose2>>(
 | 
			
		||||
        X(keyS), X(keyT), poseArray[0], poseNoiseModel);
 | 
			
		||||
        X(keyS), X(keyT), poseArray[0], kPoseNoiseModel);
 | 
			
		||||
    auto f1 = std::make_shared<BetweenFactor<Pose2>>(
 | 
			
		||||
        X(keyS), X(keyT), poseArray[1], poseNoiseModel);
 | 
			
		||||
        X(keyS), X(keyT), poseArray[1], kPoseNoiseModel);
 | 
			
		||||
 | 
			
		||||
    std::vector<NonlinearFactorValuePair> factors{{f0, 0.0}, {f1, 0.0}};
 | 
			
		||||
    std::vector<NonlinearFactorValuePair> factors{{f0, kPoseNoiseConstant},
 | 
			
		||||
                                                  {f1, kPoseNoiseConstant}};
 | 
			
		||||
    HybridNonlinearFactor mixtureFactor(m, factors);
 | 
			
		||||
    return mixtureFactor;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -129,9 +134,9 @@ class Experiment {
 | 
			
		|||
  /// @brief Perform smoother update and optimize the graph.
 | 
			
		||||
  void smootherUpdate(HybridSmoother& smoother,
 | 
			
		||||
                      HybridNonlinearFactorGraph& graph, const Values& initial,
 | 
			
		||||
                      size_t kMaxNrHypotheses, Values* result) {
 | 
			
		||||
                      size_t maxNrHypotheses, Values* result) {
 | 
			
		||||
    HybridGaussianFactorGraph linearized = *graph.linearize(initial);
 | 
			
		||||
    smoother.update(linearized, kMaxNrHypotheses);
 | 
			
		||||
    smoother.update(linearized, maxNrHypotheses);
 | 
			
		||||
    // throw if x0 not in hybridBayesNet_:
 | 
			
		||||
    const KeySet& keys = smoother.hybridBayesNet().keys();
 | 
			
		||||
    if (keys.find(X(0)) == keys.end()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -148,11 +153,11 @@ class Experiment {
 | 
			
		|||
      : filename_(filename), smoother_(0.99) {}
 | 
			
		||||
 | 
			
		||||
  /// @brief Run the main experiment with a given maxLoopCount.
 | 
			
		||||
  void run(size_t maxLoopCount) {
 | 
			
		||||
  void run() {
 | 
			
		||||
    // Prepare reading
 | 
			
		||||
    ifstream in(filename_);
 | 
			
		||||
    std::ifstream in(filename_);
 | 
			
		||||
    if (!in.is_open()) {
 | 
			
		||||
      cerr << "Failed to open file: " << filename_ << endl;
 | 
			
		||||
      std::cerr << "Failed to open file: " << filename_ << std::endl;
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -173,7 +178,7 @@ class Experiment {
 | 
			
		|||
 | 
			
		||||
    // Initial update
 | 
			
		||||
    clock_t beforeUpdate = clock();
 | 
			
		||||
    smootherUpdate(smoother_, graph_, initial_, kMaxNrHypotheses, &result_);
 | 
			
		||||
    smootherUpdate(smoother_, graph_, initial_, maxNrHypotheses, &result_);
 | 
			
		||||
    clock_t afterUpdate = clock();
 | 
			
		||||
    std::vector<std::pair<size_t, double>> smootherUpdateTimes;
 | 
			
		||||
    smootherUpdateTimes.push_back({index, afterUpdate - beforeUpdate});
 | 
			
		||||
| 
						 | 
				
			
			@ -208,8 +213,8 @@ class Experiment {
 | 
			
		|||
        if (numMeasurements > 1) {
 | 
			
		||||
          // Add hybrid factor
 | 
			
		||||
          DiscreteKey m(M(discreteCount), numMeasurements);
 | 
			
		||||
          HybridNonlinearFactor mixtureFactor = hybridOdometryFactor(
 | 
			
		||||
              numMeasurements, keyS, keyT, m, poseArray, kPoseNoiseModel);
 | 
			
		||||
          HybridNonlinearFactor mixtureFactor =
 | 
			
		||||
              hybridOdometryFactor(numMeasurements, keyS, keyT, m, poseArray);
 | 
			
		||||
          graph_.push_back(mixtureFactor);
 | 
			
		||||
          discreteCount++;
 | 
			
		||||
          numberOfHybridFactors += 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -231,12 +236,12 @@ class Experiment {
 | 
			
		|||
        loopCount++;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (numberOfHybridFactors>=kUpdateFrequency) {
 | 
			
		||||
      if (numberOfHybridFactors >= updateFrequency) {
 | 
			
		||||
        // print the keys involved in the smoother update
 | 
			
		||||
        std::cout << "Smoother update: " << graph_.size() << std::endl;
 | 
			
		||||
        gttic_(SmootherUpdate);
 | 
			
		||||
        beforeUpdate = clock();
 | 
			
		||||
        smootherUpdate(smoother_, graph_, initial_, kMaxNrHypotheses, &result_);
 | 
			
		||||
        smootherUpdate(smoother_, graph_, initial_, maxNrHypotheses, &result_);
 | 
			
		||||
        afterUpdate = clock();
 | 
			
		||||
        smootherUpdateTimes.push_back({index, afterUpdate - beforeUpdate});
 | 
			
		||||
        gttoc_(SmootherUpdate);
 | 
			
		||||
| 
						 | 
				
			
			@ -266,7 +271,7 @@ class Experiment {
 | 
			
		|||
 | 
			
		||||
    // Final update
 | 
			
		||||
    beforeUpdate = clock();
 | 
			
		||||
    smootherUpdate(smoother_, graph_, initial_, kMaxNrHypotheses, &result_);
 | 
			
		||||
    smootherUpdate(smoother_, graph_, initial_, maxNrHypotheses, &result_);
 | 
			
		||||
    afterUpdate = clock();
 | 
			
		||||
    smootherUpdateTimes.push_back({index, afterUpdate - beforeUpdate});
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -296,7 +301,7 @@ class Experiment {
 | 
			
		|||
    //  }
 | 
			
		||||
 | 
			
		||||
    // Write timing info to file
 | 
			
		||||
    ofstream outfileTime;
 | 
			
		||||
    std::ofstream outfileTime;
 | 
			
		||||
    std::string timeFileName = "Hybrid_City10000_time.txt";
 | 
			
		||||
    outfileTime.open(timeFileName);
 | 
			
		||||
    for (auto accTime : timeList) {
 | 
			
		||||
| 
						 | 
				
			
			@ -308,15 +313,47 @@ class Experiment {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
int main() {
 | 
			
		||||
// Function to parse command-line arguments
 | 
			
		||||
void parseArguments(int argc, char* argv[], size_t& maxLoopCount,
 | 
			
		||||
                    size_t& updateFrequency, size_t& maxNrHypotheses) {
 | 
			
		||||
  for (int i = 1; i < argc; ++i) {
 | 
			
		||||
    std::string arg = argv[i];
 | 
			
		||||
    if (arg == "--max-loop-count" && i + 1 < argc) {
 | 
			
		||||
      maxLoopCount = std::stoul(argv[++i]);
 | 
			
		||||
    } else if (arg == "--update-frequency" && i + 1 < argc) {
 | 
			
		||||
      updateFrequency = std::stoul(argv[++i]);
 | 
			
		||||
    } else if (arg == "--max-nr-hypotheses" && i + 1 < argc) {
 | 
			
		||||
      maxNrHypotheses = std::stoul(argv[++i]);
 | 
			
		||||
    } else if (arg == "--help") {
 | 
			
		||||
      std::cout << "Usage: " << argv[0] << " [options]\n"
 | 
			
		||||
                << "Options:\n"
 | 
			
		||||
                << "  --max-loop-count <value>       Set the maximum loop "
 | 
			
		||||
                   "count (default: 3000)\n"
 | 
			
		||||
                << "  --update-frequency <value>     Set the update frequency "
 | 
			
		||||
                   "(default: 3)\n"
 | 
			
		||||
                << "  --max-nr-hypotheses <value>    Set the maximum number of "
 | 
			
		||||
                   "hypotheses (default: 10)\n"
 | 
			
		||||
                << "  --help                         Show this help message\n";
 | 
			
		||||
      std::exit(0);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
// Main function
 | 
			
		||||
int main(int argc, char* argv[]) {
 | 
			
		||||
  Experiment experiment(findExampleDataFile("T1_city10000_04.txt"));
 | 
			
		||||
  // Experiment experiment("../data/mh_T1_city10000_04.txt"); //Type #1 only
 | 
			
		||||
  // Experiment experiment("../data/mh_T3b_city10000_10.txt"); //Type #3 only
 | 
			
		||||
  // Experiment experiment("../data/mh_T1_T3_city10000_04.txt"); //Type #1 +
 | 
			
		||||
  // Type #3
 | 
			
		||||
 | 
			
		||||
  // Parse command-line arguments
 | 
			
		||||
  parseArguments(argc, argv, experiment.maxLoopCount,
 | 
			
		||||
                 experiment.updateFrequency, experiment.maxNrHypotheses);
 | 
			
		||||
 | 
			
		||||
  // Run the experiment
 | 
			
		||||
  experiment.run(kMaxLoopCount);
 | 
			
		||||
  experiment.run();
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue