IncrementalFixedLagSmootherExample.cpp
Go to the documentation of this file.
1 /* ----------------------------------------------------------------------------
2 
3  * GTSAM Copyright 2010-2025, Georgia Tech Research Corporation,
4  * Atlanta, Georgia 30332-0415
5  * All Rights Reserved
6  * Authors: Frank Dellaert, et al. (see THANKS for the full author list)
7 
8  * See LICENSE for the license information
9 
10  * -------------------------------------------------------------------------- */
11 
53 // STL
54 #include <iostream>
55 #include <string>
56 // GTSAM
57 #include <gtsam/geometry/Pose3.h>
58 #include <gtsam/nonlinear/ISAM2.h>
59 #include <gtsam/nonlinear/Values.h>
63 #include <gtsam/inference/Symbol.h>
64 #include <gtsam/slam/dataset.h> // for writeG2o
65 
66 using namespace std;
67 using namespace gtsam;
68 // Shorthand for symbols
69 using symbol_shorthand::X; // Pose3 (x,y,z, roll, pitch, yaw)
70 
71 // Factor types
72 enum FactorType {
73  PRIOR = 0,
74  BETWEEN = 1
75 };
76 
78 
79 /* ************************************************************************* */
86 Matrix6 readCovarianceMatrix(istringstream &iss) {
87  Matrix6 cov;
88  for (int r = 0; r < 6; ++r) {
89  for (int c = 0; c < 6; ++c) {
90  iss >> cov(r, c);
91  }
92  }
93  return cov;
94 }
95 
96 /* ************************************************************************* */
108 Pose3 createPose(double x, double y, double z, double roll, double pitch, double yaw) {
109  return Pose3(Rot3::RzRyRx(roll, pitch, yaw), Point3(x, y, z));
110 }
111 
112 /* ************************************************************************* */
121 void saveG2oGraph(const NonlinearFactorGraph &graph, const Values &estimate,
122  const string &filename, int iterCount) {
123  // Create zero-padded iteration count
124  string countStr = to_string(iterCount);
125  string paddedCount = string(5 - countStr.length(), '0') + countStr;
126  string fullFilename = filename + "_" + paddedCount + ".g2o";
127  // Write graph and estimates to g2o file
128  writeG2o(graph, estimate, fullFilename);
129  cout << "\nSaved graph to: " << fullFilename << endl;
130 }
131 
132 /* ************************************************************************* */
147 int main() {
148  string factor_loc = findExampleDataFile("issue1452.txt");
149  ifstream factor_file(factor_loc.c_str());
150  cout << "Reading factors data file: " << factor_loc << endl;
151 
152  // Configure ISAM2 parameters for the fixed-lag smoother
153  ISAM2Params isamParameters;
154  isamParameters.relinearizeThreshold = 0.1;
155  isamParameters.relinearizeSkip = 1;
156 
157  // Important!!!!!! Key parameter to ensure old factors are released after marginalization
158  isamParameters.findUnusedFactorSlots = true;
159  // Initialize fixed-lag smoother with a 1-second lag window
160  const double lag = 1.0;
161  IncrementalFixedLagSmoother smoother(lag, isamParameters);
162  // Print the iSAM2 parameters (optional)
163  isamParameters.print();
164 
165  // Containers for incremental updates
166  NonlinearFactorGraph newFactors;
167  Values newValues;
168  FixedLagSmoother::KeyTimestampMap newTimestamps;
169  // For tracking the latest estimate of all states in the sliding window
170  Values currentEstimate;
171  Pose3 lastPose;
172 
173  // Read and process each line in the factor graph file
174  string line;
175  int lineCount = 0;
176  while (getline(factor_file, line)) {
177  if (line.empty()) continue; // Skip empty lines
178  cout << "\n======================== Processing line " << ++lineCount
179  << " =========================" << endl;
180 
181  istringstream iss(line);
182  int factorType;
183  iss >> factorType;
184  // Check if the factor is PRIOR or BETWEEN
185  if (factorType == PRIOR) {
190  double timestamp;
191  int key;
192  double x, y, z, roll, pitch, yaw;
193  iss >> timestamp >> key >> x >> y >> z >> roll >> pitch >> yaw;
194  Pose3 pose = createPose(x, y, z, roll, pitch, yaw);
195  Matrix6 cov = readCovarianceMatrix(iss);
196  auto noise = noiseModel::Gaussian::Covariance(cov);
197  // Add prior factor
198  newFactors.addPrior(X(key), pose, noise);
199  cout << "Add PRIOR factor on key " << key << endl;
200  // Provide initial guess if not already in the graph
201  if (!newValues.exists(X(key))) {
202  newValues.insert(X(key), pose);
203  newTimestamps[X(key)] = timestamp;
204  }
205  } else if (factorType == BETWEEN) {
210  double timestamp;
211  int key1, key2;
212  iss >> timestamp >> key1 >> key2;
213  double x1, y1, z1, roll1, pitch1, yaw1;
214  iss >> x1 >> y1 >> z1 >> roll1 >> pitch1 >> yaw1;
215  Pose3 relativePose = createPose(x1, y1, z1, roll1, pitch1, yaw1);
216  Matrix6 cov = readCovarianceMatrix(iss);
217  auto noise = noiseModel::Gaussian::Covariance(cov);
218  // Add between factor
219  newFactors.emplace_shared<BetweenFactor<Pose3>>(X(key1), X(key2), relativePose, noise);
220  cout << "Add BETWEEN factor: " << key1 << " -> " << key2 << endl;
221  // Provide an initial guess if needed
222  if (!newValues.exists(X(key2))) {
223  newValues.insert(X(key2), lastPose.compose(relativePose));
224  newTimestamps[X(key2)] = timestamp;
225  }
226  } else {
227  cerr << "Unknown factor type: " << factorType << endl;
228  continue;
229  }
230 
231  // Print some intermediate statistics
232  cout << "Before update - Graph has " << smoother.getFactors().size()
233  << " factors, " << smoother.getFactors().nrFactors() << " nr factors." << endl;
234  cout << "New factors: " << newFactors.size()
235  << ", New values: " << newValues.size() << endl;
236 
237  // Attempt to update the smoother with new factors and values
238  try {
239  smoother.update(newFactors, newValues, newTimestamps);
240  // Optional: Perform extra internal iterations if needed
241  size_t maxExtraIterations = 3;
242  for (size_t i = 1; i < maxExtraIterations; ++i) {
243  smoother.update();
244  }
245  // you may not get expected results if you use the gtsam version lower than 4.3
246  cout << "After update - Graph has " << smoother.getFactors().size()
247  << " factors, " << smoother.getFactors().nrFactors() << " nr factors." << endl;
248 
249  // Retrieve the latest estimate
250  currentEstimate = smoother.calculateEstimate();
251  if (!currentEstimate.empty()) {
252  // Update lastPose to the last key's estimate
253  Key lastKey = currentEstimate.keys().back();
254  lastPose = currentEstimate.at<Pose3>(lastKey);
255  }
256 
257  // Clear containers for the next iteration
258  newFactors.resize(0);
259  newValues.clear();
260  newTimestamps.clear();
261  } catch (const exception &e) {
262  cerr << "Smoother update failed: " << e.what() << endl;
263  }
264  }
265 
266  // The results of the last sliding window are saved to a g2o file for visualization or further analysis.
267  saveG2oGraph(smoother.getFactors(), currentEstimate, "isam", lineCount);
268  factor_file.close();
269 
270  return 0;
271 }
272 
key1
const Symbol key1('v', 1)
gtsam::ISAM2Params::print
void print(const std::string &str="") const
print iSAM2 parameters
Definition: ISAM2Params.h:253
gtsam::ISAM2Params
Definition: ISAM2Params.h:136
gtsam::Values::exists
bool exists(Key j) const
Definition: Values.cpp:94
gtsam::Values::keys
KeyVector keys() const
Definition: Values.cpp:219
pose
static const Pose3 pose(Rot3(Vector3(1, -1, -1).asDiagonal()), Point3(0, 0, 0.5))
gtsam::Values::size
size_t size() const
Definition: Values.h:178
e
Array< double, 1, 3 > e(1./3., 0.5, 2.)
Matrix6
Eigen::Matrix< double, 6, 6 > Matrix6
Definition: IncrementalFixedLagSmootherExample.cpp:77
c
Scalar Scalar * c
Definition: benchVecAdd.cpp:17
z1
Point2 z1
Definition: testTriangulationFactor.cpp:45
saveG2oGraph
void saveG2oGraph(const NonlinearFactorGraph &graph, const Values &estimate, const string &filename, int iterCount)
Save the factor graph and estimates to a .g2o file (for visualization/debugging).
Definition: IncrementalFixedLagSmootherExample.cpp:121
gtsam::LieGroup::compose
Class compose(const Class &g) const
Definition: Lie.h:48
x
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
Definition: gnuplot_common_settings.hh:12
X
#define X
Definition: icosphere.cpp:20
main
int main()
Main function: Reads poses data from a text file and performs incremental fixed-lag smoothing.
Definition: IncrementalFixedLagSmootherExample.cpp:147
readCovarianceMatrix
Matrix6 readCovarianceMatrix(istringstream &iss)
Read a 6x6 covariance matrix from an input string stream.
Definition: IncrementalFixedLagSmootherExample.cpp:86
createPose
Pose3 createPose(double x, double y, double z, double roll, double pitch, double yaw)
Create a Pose3 object from individual pose parameters.
Definition: IncrementalFixedLagSmootherExample.cpp:108
gtsam::Values::at
const ValueType at(Key j) const
Definition: Values-inl.h:261
gtsam::FactorGraph::resize
virtual void resize(size_t size)
Definition: FactorGraph.h:367
y1
double y1(double x)
Definition: j1.c:199
gtsam::ISAM2Params::relinearizeThreshold
RelinearizationThreshold relinearizeThreshold
Definition: ISAM2Params.h:169
gtsam::IncrementalFixedLagSmoother::update
Result update(const NonlinearFactorGraph &newFactors=NonlinearFactorGraph(), const Values &newTheta=Values(), const KeyTimestampMap &timestamps=KeyTimestampMap(), const FactorIndices &factorsToRemove=FactorIndices()) override
Definition: IncrementalFixedLagSmoother.cpp:45
gtsam::IncrementalFixedLagSmoother
Definition: IncrementalFixedLagSmoother.h:34
key2
const Symbol key2('v', 2)
dataset.h
utility functions for loading datasets
BetweenFactor.h
x1
Pose3 x1
Definition: testPose3.cpp:692
relicense.filename
filename
Definition: relicense.py:57
gtsam::Pose3
Definition: Pose3.h:37
gtsam::NonlinearFactorGraph
Definition: NonlinearFactorGraph.h:55
gtsam::NonlinearFactorGraph::addPrior
void addPrior(Key key, const T &prior, const SharedNoiseModel &model=nullptr)
Definition: NonlinearFactorGraph.h:199
Symbol.h
pybind_wrapper_test_script.z
z
Definition: pybind_wrapper_test_script.py:61
y
Scalar * y
Definition: level1_cplx_impl.h:124
key
const gtsam::Symbol key('X', 0)
IncrementalFixedLagSmoother.h
An iSAM2-based fixed-lag smoother.
gtsam::FactorGraph::size
size_t size() const
Definition: FactorGraph.h:297
ISAM2.h
Incremental update functionality (ISAM2) for BayesTree, with fluid relinearization.
gtsam::IncrementalFixedLagSmoother::getFactors
const NonlinearFactorGraph & getFactors() const
Definition: IncrementalFixedLagSmoother.h:95
gtsam::FixedLagSmoother::KeyTimestampMap
std::map< Key, double > KeyTimestampMap
Typedef for a Key-Timestamp map/database.
Definition: nonlinear/FixedLagSmoother.h:41
gtsam
traits
Definition: SFMdata.h:40
PRIOR
@ PRIOR
Definition: IncrementalFixedLagSmootherExample.cpp:73
NonlinearFactorGraph.h
Factor Graph consisting of non-linear factors.
gtsam::Values
Definition: Values.h:65
gtsam::ISAM2Params::findUnusedFactorSlots
bool findUnusedFactorSlots
Definition: ISAM2Params.h:225
FactorType
FactorType
Definition: IncrementalFixedLagSmootherExample.cpp:72
std
Definition: BFloat16.h:88
gtsam::Values::clear
void clear()
Definition: Values.h:347
gtsam::Values::insert
void insert(Key j, const Value &val)
Definition: Values.cpp:156
gtsam::FactorGraph::nrFactors
size_t nrFactors() const
Definition: FactorGraph-inst.h:76
gtsam::Point3
Vector3 Point3
Definition: Point3.h:38
Eigen::Matrix< double, 6, 6 >
gtsam::findExampleDataFile
GTSAM_EXPORT std::string findExampleDataFile(const std::string &name)
Definition: dataset.cpp:70
gtsam::IncrementalFixedLagSmoother::calculateEstimate
Values calculateEstimate() const override
Definition: IncrementalFixedLagSmoother.h:74
gtsam::Values::empty
bool empty() const
Definition: Values.h:181
graph
NonlinearFactorGraph graph
Definition: doc/Code/OdometryExample.cpp:2
gtsam::Key
std::uint64_t Key
Integer nonlinear key type.
Definition: types.h:97
BETWEEN
@ BETWEEN
Definition: IncrementalFixedLagSmootherExample.cpp:74
gtsam::ISAM2Params::relinearizeSkip
int relinearizeSkip
Definition: ISAM2Params.h:171
i
int i
Definition: BiCGSTAB_step_by_step.cpp:9
Values.h
A non-templated config holding any types of Manifold-group elements.
Pose3.h
3D Pose manifold SO(3) x R^3 and group SE(3)
gtsam::FactorGraph::emplace_shared
IsDerived< DERIVEDFACTOR > emplace_shared(Args &&... args)
Emplace a shared pointer to factor of given type.
Definition: FactorGraph.h:153
gtsam::BetweenFactor
Definition: BetweenFactor.h:40
gtsam::writeG2o
void writeG2o(const NonlinearFactorGraph &graph, const Values &estimate, const std::string &filename)
This function writes a g2o file from NonlinearFactorGraph and a Values structure.
Definition: dataset.cpp:636


gtsam
Author(s):
autogenerated on Wed Mar 19 2025 03:01:49