Formula Student Autonomous Systems
The code for the main driverless system
Loading...
Searching...
No Matches
sliding_window_levenberg_optimizer.cpp
Go to the documentation of this file.
2
3#include <gtsam/base/timing.h>
4#include <gtsam/inference/Symbol.h>
5#include <gtsam/linear/GaussianFactorGraph.h>
6#include <gtsam/nonlinear/NonlinearFactorGraph.h>
7#include <gtsam/nonlinear/Values.h>
8
9#include <Eigen/SparseCore>
10
11std::shared_ptr<BaseOptimizer> SlidingWindowLevenbergOptimizer::clone() const {
12 return std::make_shared<SlidingWindowLevenbergOptimizer>(*this);
13}
14
17
19 gtsam::NonlinearFactorGraph& factor_graph, gtsam::Values& graph_values,
20 [[maybe_unused]] unsigned int pose_num, [[maybe_unused]] unsigned int landmark_num) {
21 // Retrieve the last poses added to the graph
22 std::set<gtsam::Key> pose_keys;
23 std::set<gtsam::Key> landmark_keys;
24 gtsam::NonlinearFactorGraph sliding_window_graph;
25 gtsam::Values sliding_window_values;
26 for (int i = std::max<int>(1, pose_num - _params_.sliding_window_size_ + 1);
27 i <= static_cast<int>(pose_num); ++i) {
28 pose_keys.insert(gtsam::Symbol('x', i));
29 }
30
31 // Add relevant factors
32 for (const auto& factor : factor_graph) {
33 auto involved_keys = factor->keys();
34 bool include = false;
35 for (const auto& key : involved_keys) {
36 if (gtsam::Symbol(key).chr() == 'x' && pose_keys.count(key) == 0) {
37 // If one of the involved nodes in the factor is a pose
38 // and not one in the sliding window, ignore the factor
39 include = false;
40 break;
41 } else if (gtsam::Symbol(key).chr() == 'x' && pose_keys.count(key) > 0) {
42 // If one of the involved nodes in the factor is a pose
43 // and is in the sliding window, include the factor, but
44 // wait to check if the other node is a pose and not in the
45 // sliding window
46 include = true;
47 }
48 }
49 if (include) {
50 sliding_window_graph.add(factor);
51 }
52 }
53
54 // Determine relevant landmarks through factors
55 for (const auto& factor : sliding_window_graph) {
56 auto involved_keys = factor->keys();
57 for (const auto& key : involved_keys) {
58 if (gtsam::Symbol(key).chr() == 'l') {
59 landmark_keys.insert(key);
60 }
61 }
62 }
63
64 // Add prior factors for included landmarks only
65 for (const auto& factor : factor_graph) {
66 const auto& keys = factor->keys();
67
68 // Check if this is a prior factor on a landmark in the current window
69 if (keys.size() == 1) {
70 gtsam::Symbol symbol(keys[0]);
71 if (symbol.chr() == 'l' && landmark_keys.count(keys[0]) > 0) {
72 sliding_window_graph.add(factor);
73 }
74 }
75 }
76
77 // Add relevant values
78 for (const auto& key : landmark_keys) {
79 sliding_window_values.insert(key, graph_values.at(key));
80 }
81 for (const auto& key : pose_keys) {
82 sliding_window_values.insert(key, graph_values.at(key));
83 }
84
85 // Define parameters
86 gtsam::LevenbergMarquardtParams lm_params;
87 gtsam::Ordering ordering;
88 for (const auto& key : landmark_keys) {
89 ordering.push_back(key);
90 }
91 for (const auto& key : pose_keys) {
92 ordering.push_back(key);
93 }
94 lm_params.setOrdering(ordering);
95 // lm_params.setMaxIterations(2); // steady latency
96 // lm_params.setlambdaInitial(1e-3); // sane start
97 lm_params.setlambdaUpperBound(1e3); // clamp runaway damping
98 // lm_params.setlambdaFactor(10.0); // backoff multiplier
99 // lm_params.setAbsoluteErrorTol(0); // disable early-stopping by tolerance (latency focus)
100 // lm_params.setRelativeErrorTol(0); // "
101 // lm_params.setLinearSolverType(gtsam::LevenbergMarquardtParams::MULTIFRONTAL_CHOLESKY);
102 // lm_params.setOrderingType(
103 // gtsam::LevenbergMarquardtParams::OrderingType::CUSTOM); // supply your ordering
104 // TODO: determine best parameters and expose them to YAML
105
106 // Optimize the sliding window
107 rclcpp::Time start_time = rclcpp::Clock().now();
108 gtsam::LevenbergMarquardtOptimizer optimizer(sliding_window_graph, sliding_window_values,
109 lm_params);
110 graph_values.update(optimizer.optimize());
111 rclcpp::Duration optimization_time = rclcpp::Clock().now() - start_time;
112 RCLCPP_DEBUG(
113 rclcpp::get_logger("slam"),
114 "SlidingWindowLevenbergOptimizer - Optimized %d poses and %d landmarks, including %d factors",
115 static_cast<int>(pose_keys.size()), static_cast<int>(landmark_keys.size()),
116 static_cast<int>(sliding_window_graph.size()));
117 RCLCPP_DEBUG(rclcpp::get_logger("slam"),
118 "SlidingWindowLevenbergOptimizer - Lambda at start: %lf, end: %lf",
119 lm_params.lambdaInitial, optimizer.lambda());
120 RCLCPP_DEBUG(rclcpp::get_logger("slam"),
121 "SlidingWindowLevenbergOptimizer - Number of iterations: "
122 "%ld\nOptimization time: %f",
123 optimizer.iterations(), optimization_time.seconds());
124 return graph_values;
125}
Base class for graph optimizers.
const SLAMParameters & _params_
std::shared_ptr< BaseOptimizer > clone() const override
Clone the optimizer.
SlidingWindowLevenbergOptimizer(const SLAMParameters &params)
gtsam::Values optimize(gtsam::NonlinearFactorGraph &factor_graph, gtsam::Values &graph_values, unsigned int pose_num, unsigned int landmark_num) override
Optimize the graph.
Parameters for the SLAM node.
unsigned int sliding_window_size_