Formula Student Autonomous Systems
The code for the main driverless system
Loading...
Searching...
No Matches
graph_slam_solver.cpp
Go to the documentation of this file.
2
3#include <gtsam/base/Vector.h>
4#include <gtsam/geometry/Point2.h>
5#include <gtsam/geometry/Pose2.h>
6#include <gtsam/geometry/Rot2.h>
7#include <gtsam/inference/Symbol.h>
8#include <gtsam/nonlinear/LevenbergMarquardtOptimizer.h>
9#include <gtsam/nonlinear/Marginals.h>
10#include <gtsam/nonlinear/Values.h>
11#include <gtsam/sam/BearingFactor.h>
12#include <gtsam/sam/BearingRangeFactor.h>
13#include <gtsam/sam/RangeFactor.h>
14#include <gtsam/slam/BetweenFactor.h>
15#include <gtsam/slam/PriorFactor.h>
16#include <gtsam/slam/ProjectionFactor.h>
17
18#include <iostream>
19#include <rclcpp/rclcpp.hpp>
20
26
28 std::shared_ptr<DataAssociationModel> data_association,
29 std::shared_ptr<V2PMotionModel> motion_model,
30 std::shared_ptr<LandmarkFilter> landmark_filter,
31 std::shared_ptr<std::vector<double>> execution_times,
32 std::shared_ptr<LoopClosure> loop_closure)
33 : SLAMSolver(params, data_association, motion_model, landmark_filter, execution_times,
34 loop_closure) {
35 this->_graph_slam_instance_ = std::make_shared<GraphSLAMInstance>(
38 this->_odometry_model = std::make_shared<OdometryModel>();
39}
40
41void GraphSLAMSolver::init([[maybe_unused]] std::weak_ptr<rclcpp::Node> node) {
42 if (const auto node_ptr = node.lock()) {
43 this->_reentrant_group_ = node_ptr->create_callback_group(
44 rclcpp::CallbackGroupType::Reentrant); // Allow callbacks to execute in parallel
45 }
46 // Create a timer for asynchronous optimization
47 if (this->_params_.slam_optimization_mode_ != "async" ||
48 this->_params_.slam_optimization_period_ <= 0.0) {
49 RCLCPP_INFO(rclcpp::get_logger("slam"), "Optimization is synchronous");
50 } else if (const auto node_ptr = node.lock()) {
51 this->_optimization_timer_ = node_ptr->create_wall_timer(
52 std::chrono::milliseconds(
53 static_cast<int>(this->_params_.slam_optimization_period_ * 1000)),
54 [this]() { this->_asynchronous_optimization_routine(); }, this->_reentrant_group_);
55 RCLCPP_INFO(rclcpp::get_logger("slam"), "Optimization timer created with period %f seconds",
57 } else {
58 this->_params_.slam_optimization_period_ = 0.0; // Trigger optimization on observations
59 RCLCPP_ERROR(rclcpp::get_logger("slam"),
60 "Failed to create optimization timer, node is not valid");
61 }
62}
63
65 const std::shared_ptr<PoseUpdater> pose_updater,
66 const std::shared_ptr<GraphSLAMInstance> graph_slam_instance, bool force_update) {
67 if (pose_updater->pose_ready_for_graph_update() || force_update) {
68 // If the pose updater is ready to update the pose, we can proceed with the pose update
69 // Eigen::Vector3d pose_difference_noise = {0.2, 0.2, 0.3};
70 graph_slam_instance->process_new_pose(
71 pose_difference_eigen(pose_updater->get_last_graphed_pose(), pose_updater->get_last_pose()),
72 pose_updater->get_pose_difference_noise(), pose_updater->get_last_pose(),
73 pose_updater->get_last_pose_update());
74
75 pose_updater->update_pose(
76 pose_updater->get_last_pose()); // Reset the accumulated pose difference
77 return true;
78 }
79
80 return false;
81}
82
84 std::unique_lock lock(this->_mutex_);
85 RCLCPP_DEBUG(rclcpp::get_logger("slam"), "add_odometry - Mutex accessed");
86 rclcpp::Time start_time, motion_model_time, factor_graph_time;
87
88 // Apply motion model
89 MotionData odometry_data(std::make_shared<Eigen::VectorXd>(3),
90 std::make_shared<Eigen::VectorXd>(3), odometry.timestamp);
91 odometry_data.motion_data_->head<3>() << odometry.position.x, odometry.position.y,
92 odometry.orientation;
93 odometry_data.motion_data_noise_->head<3>() << odometry.position.x_noise,
94 odometry.position.y_noise, odometry.orientation_noise;
95 start_time = rclcpp::Clock().now();
96 if (this->_optimization_under_way_) {
97 this->_motion_data_queue_.push(odometry_data);
98 RCLCPP_DEBUG(rclcpp::get_logger("slam"),
99 "add_odometry - Optimization under way, pushing motion data");
100 }
101 this->_pose_updater_->predict_pose(odometry_data, this->_odometry_model);
102 motion_model_time = rclcpp::Clock().now();
103 RCLCPP_DEBUG(rclcpp::get_logger("slam"), "add_odometry - Pose updated");
104
105 // Add motion data to the graph
106 bool added_factors =
108 factor_graph_time = rclcpp::Clock().now();
109 RCLCPP_DEBUG(rclcpp::get_logger("slam"), "add_odometry - Factors added? %d", added_factors);
110
111 // Timekeeping
112 if (this->_execution_times_ == nullptr) {
113 return;
114 }
115 this->_execution_times_->at(9) = (motion_model_time - start_time).seconds() * 1000.0;
116 this->_execution_times_->at(10) = (factor_graph_time - motion_model_time).seconds() * 1000.0;
117 RCLCPP_DEBUG(rclcpp::get_logger("slam"), "add_odometry - Mutex unlocked");
118}
119
121 RCLCPP_DEBUG(rclcpp::get_logger("slam"), "add_velocities - Mutex waiting to lock");
122 std::unique_lock lock(this->_mutex_);
123 RCLCPP_DEBUG(rclcpp::get_logger("slam"), "add_velocities - Mutex accessed");
124 rclcpp::Time start_time, motion_model_time, factor_graph_time;
125
126 // Construct motion data
127 MotionData velocities_data(std::make_shared<Eigen::VectorXd>(4),
128 std::make_shared<Eigen::VectorXd>(4), velocities.timestamp_);
129 velocities_data.motion_data_->head<4>() << velocities.velocity_x, velocities.velocity_y,
130 velocities.rotational_velocity, this->_last_imu_data_.acceleration_x;
131 velocities_data.motion_data_noise_->head<4>() << _params_.velocity_x_noise_,
134 velocities_data.timestamp_ = velocities.timestamp_;
135 start_time = rclcpp::Clock().now();
136 if (this->_optimization_under_way_) {
137 this->_motion_data_queue_.push(velocities_data);
138 RCLCPP_DEBUG(rclcpp::get_logger("slam"),
139 "add_velocities - Optimization under way, pushing motion data");
140 }
141
142 // Apply motion model
143 this->_pose_updater_->predict_pose(velocities_data, this->_motion_model_);
144 motion_model_time = rclcpp::Clock().now();
145 RCLCPP_DEBUG(rclcpp::get_logger("slam"), "add_velocities - Pose updated: (%f, %f, %f)",
146 this->_pose_updater_->get_last_pose()(0), this->_pose_updater_->get_last_pose()(1),
147 this->_pose_updater_->get_last_pose()(2));
148
149 // Add motion data to the graph
150 bool added_factors =
152 factor_graph_time = rclcpp::Clock().now();
153 RCLCPP_DEBUG(rclcpp::get_logger("slam"), "add_velocities - Factors added? %d", added_factors);
154
155 // Timekeeping
156 if (this->_execution_times_ == nullptr) {
157 return;
158 }
159 this->_execution_times_->at(9) = (motion_model_time - start_time).seconds() * 1000.0;
160 this->_execution_times_->at(10) = (factor_graph_time - motion_model_time).seconds() * 1000.0;
161 RCLCPP_DEBUG(rclcpp::get_logger("slam"), "add_velocities - Mutex unlocked");
162}
163
165 this->_last_imu_data_ = imu_data;
166}
167
168void GraphSLAMSolver::add_observations(const std::vector<common_lib::structures::Cone>& cones,
169 rclcpp::Time cones_timestamp) {
170 if (cones.empty()) {
171 // this->_landmark_filter_->filter(Eigen::VectorXd::Zero(0), Eigen::VectorXd::Zero(0),
172 // Eigen::VectorXi::Zero(0));
173 this->_observations_global_ = Eigen::VectorXd::Zero(0);
174 this->_associations_ = Eigen::VectorXi::Zero(0);
175 return;
176 }
177
178 // Prepare the data structures for observations
179 rclcpp::Time start_time, initialization_time, covariance_time, association_time,
180 factor_graph_time, optimization_time;
181 start_time = rclcpp::Clock().now();
182 Eigen::VectorXd observations(cones.size() * 2);
183 Eigen::VectorXd observations_confidences(cones.size());
184 Eigen::VectorXd observations_global(cones.size() * 2);
185 Eigen::VectorXd landmarks, state;
186 Eigen::Vector3d pose;
187 Eigen::MatrixXd covariance;
188 for (unsigned int i = 0; i < cones.size(); i++) {
189 // Iterate through the cones
190 observations(i * 2) = cones[i].position.x;
191 observations(i * 2 + 1) = cones[i].position.y;
192 observations_confidences(i) = cones[i].certainty;
193 }
194
195 {
196 RCLCPP_DEBUG(rclcpp::get_logger("slam"), "add_observations - Shared mutex accessed");
197 const std::shared_lock lock(this->_mutex_);
198 state = this->_graph_slam_instance_->get_state_vector();
199 landmarks = state.segment(3, state.size() - 3);
200 pose = this->_pose_updater_->get_last_pose(); // get the last pose
201 Eigen::Vector3d adjusted_pose = this->_pose_updater_->get_pose_at_timestamp(
202 cones_timestamp); // get closest pose to observation
203 observations_global =
204 common_lib::maths::local_to_global_coordinates(adjusted_pose, observations);
205 initialization_time = rclcpp::Clock().now();
206 covariance = this->_graph_slam_instance_->get_covariance_matrix();
207 covariance_time = rclcpp::Clock().now();
208 }
209 RCLCPP_INFO(rclcpp::get_logger("slam"), "add_observations - State and covariance obtained");
210 Eigen::VectorXi associations;
211 Eigen::VectorXd filtered_new_observations;
212 {
213 RCLCPP_DEBUG(rclcpp::get_logger("slam"),
214 "add_observations - Mutex locked - association/filter/loop-closure/graph update");
215 std::unique_lock uniq_lock(this->_mutex_);
216
217 // Data association
218 associations = this->_data_association_->associate(
219 landmarks, observations_global, covariance,
220 observations_confidences); // TODO: implement different mahalanobis distance
221 this->_associations_ = associations;
222 this->_observations_global_ = observations_global;
223 this->_map_coordinates_ = state.segment(3, state.size() - 3);
224 association_time = rclcpp::Clock().now();
225 RCLCPP_DEBUG(rclcpp::get_logger("slam"), "add_observations - Associations calculated");
226
227 RCLCPP_INFO(rclcpp::get_logger("slam"), "add_observations - Associations:");
228
229 // Landmark filtering
230 filtered_new_observations = this->_landmark_filter_->filter(
231 observations_global, observations_confidences, associations);
232 RCLCPP_INFO(rclcpp::get_logger("slam"), "add_observations - Filtered new observations");
233
234 // Loop closure detection
235 LoopClosure::Result result =
236 _loop_closure_->detect(pose, landmarks, associations, observations);
237 if (result.detected) {
238 lap_counter_++;
239 // Create a (hard-ish) lock on the landmarks' positions after the first lap.
240 if (lap_counter_ == 1) {
241 RCLCPP_INFO(rclcpp::get_logger("slam"),
242 "add_observations - First lap detected, locking landmarks");
243 this->_graph_slam_instance_->lock_landmarks();
244 }
245 RCLCPP_INFO(rclcpp::get_logger("slam"), "Lap counter: %d", lap_counter_);
246 }
247 RCLCPP_INFO(rclcpp::get_logger("slam"), "add_observations - Loop closure checked");
248
249 // Add observations to the graph
250 ObservationData observation_data(std::make_shared<Eigen::VectorXd>(observations),
251 std::make_shared<Eigen::VectorXi>(associations),
252 std::make_shared<Eigen::VectorXd>(observations_global),
253 std::make_shared<Eigen::VectorXd>(observations_confidences),
254 cones_timestamp);
255 if (this->_optimization_under_way_) {
256 this->_observation_data_queue_.push(observation_data);
257 RCLCPP_INFO(rclcpp::get_logger("slam"),
258 "add_observations - Optimization under way, pushing observation data");
259 }
260 // Update the pose in the graph, as the vehicle might have moved since the last time a factor
261 // was added by the motion callback
263 this->_graph_slam_instance_->process_observations(observation_data);
264 this->_landmark_filter_->delete_landmarks(filtered_new_observations);
265 }
266
267 RCLCPP_INFO(rclcpp::get_logger("slam"), "add_observations - Factors added to graph");
268 factor_graph_time = rclcpp::Clock().now();
269 RCLCPP_DEBUG(rclcpp::get_logger("slam"), "add_observations - Mutex unlocked - Factors added");
270
271 // Optimize the graph if optimization is synchronous
272 if (this->_params_.slam_optimization_mode_ == "sync-parallel") {
274 } else if (this->_params_.slam_optimization_mode_ == "sync") {
275 RCLCPP_DEBUG(rclcpp::get_logger("slam"), "add_observations - Mutex locked - optimizing graph");
276 std::unique_lock uniq_lock(this->_mutex_);
277 this->_graph_slam_instance_->optimize();
278 optimization_time = rclcpp::Clock().now();
279 this->_pose_updater_->update_pose(gtsam_pose_to_eigen(this->_graph_slam_instance_->get_pose()));
280 RCLCPP_DEBUG(rclcpp::get_logger("slam"), "add_observations - Mutex unlocked - graph optimized");
281 }
282 RCLCPP_INFO(rclcpp::get_logger("slam"), "add_observations - Graph optimized if needed");
283
284 // Timekeeping
285 if (this->_execution_times_ == nullptr) {
286 return;
287 }
288 this->_execution_times_->at(3) = (covariance_time - initialization_time).seconds() * 1000.0;
289 this->_execution_times_->at(2) = (association_time - covariance_time).seconds() * 1000.0;
290 this->_execution_times_->at(4) = (factor_graph_time - association_time).seconds() * 1000.0;
291 if (this->_params_.slam_optimization_mode_ == "sync") {
292 this->_execution_times_->at(5) = (optimization_time - factor_graph_time).seconds() * 1000.0;
293 }
294}
295
296void GraphSLAMSolver::load_initial_state(const Eigen::VectorXd& map, const Eigen::Vector3d& pose) {
297 this->_graph_slam_instance_->load_initial_state(map, pose, this->_params_.preloaded_map_noise_);
298 this->_pose_updater_->update_pose(pose); // Update the pose in the pose updater
299}
300
302 rclcpp::Time start_time = rclcpp::Clock().now();
303
304 // Copy data to optimize
305 std::shared_ptr<GraphSLAMInstance> graph_slam_instance_copy;
306 std::shared_ptr<PoseUpdater> pose_updater_copy;
307 {
308 const std::shared_lock lock(this->_mutex_);
309 RCLCPP_DEBUG(rclcpp::get_logger("slam"),
310 "_asynchronous_optimization_routine - Shared mutex accessed");
311 if (!this->_graph_slam_instance_->new_observation_factors()) {
312 return;
313 }
314 graph_slam_instance_copy = this->_graph_slam_instance_->clone();
315 pose_updater_copy = this->_pose_updater_->clone();
316 }
317 {
318 std::unique_lock lock(this->_mutex_);
319 this->_optimization_under_way_ = true;
320 }
321 rclcpp::Time initialization_time = rclcpp::Clock().now();
322
323 // Optimize the graph
324 RCLCPP_DEBUG(rclcpp::get_logger("slam"),
325 "_asynchronous_optimization_routine - Starting optimization");
326 graph_slam_instance_copy->optimize();
327 pose_updater_copy->update_pose(gtsam_pose_to_eigen(graph_slam_instance_copy->get_pose()));
328 RCLCPP_DEBUG(rclcpp::get_logger("slam"), "_asynchronous_optimization_routine - Graph optimized");
329 rclcpp::Time optimization_time = rclcpp::Clock().now();
330
331 // Rebuild the graph with the missed data
332 {
333 std::unique_lock lock(this->_mutex_);
334 this->_optimization_under_way_ = false;
335 RCLCPP_DEBUG(rclcpp::get_logger("slam"), "_asynchronous_optimization_routine - Mutex locked");
336 while (this->_motion_data_queue_.size() > 0 || this->_observation_data_queue_.size() > 0) {
337 RCLCPP_DEBUG(rclcpp::get_logger("slam"),
338 "_asynchronous_optimization_routine - Rebuilding graph, motion data queue size: "
339 "%ld, observation data queue size: %ld",
340 this->_motion_data_queue_.size(), this->_observation_data_queue_.size());
341 bool process_pose = this->_observation_data_queue_.size() <= 0 ||
342 (this->_motion_data_queue_.size() > 0 &&
343 this->_motion_data_queue_.front().timestamp_ <=
344 this->_observation_data_queue_.front().timestamp_);
345 if (process_pose) {
346 std::shared_ptr<V2PMotionModel> motion_model_ptr =
348 ? this->_motion_model_
349 : this->_odometry_model;
350 pose_updater_copy->predict_pose(this->_motion_data_queue_.front(),
351 motion_model_ptr); // Predict the pose
352 this->_add_motion_data_to_graph(pose_updater_copy, graph_slam_instance_copy);
353 this->_motion_data_queue_.pop();
354 } else {
356 pose_updater_copy,
357 graph_slam_instance_copy); // To update graph pose before connecting factors
358 graph_slam_instance_copy->process_observations(this->_observation_data_queue_.front());
359 this->_observation_data_queue_.pop();
360 }
361 }
362 this->_graph_slam_instance_ = graph_slam_instance_copy;
363 this->_pose_updater_ = pose_updater_copy;
364 }
365 rclcpp::Time end_time = rclcpp::Clock().now();
366 if (this->_execution_times_ != nullptr) {
367 this->_execution_times_->at(5) =
368 (optimization_time - initialization_time).seconds() * 1000.0; // Optimization time
369 this->_execution_times_->at(6) =
370 (initialization_time - start_time).seconds() * 1000.0; // Initialization time
371 this->_execution_times_->at(7) =
372 (end_time - optimization_time).seconds() * 1000.0; // Graph update time
373 this->_execution_times_->at(8) =
374 (end_time - start_time).seconds() * 1000.0; // Optimization time
375 }
376 RCLCPP_DEBUG(rclcpp::get_logger("slam"),
377 "_asynchronous_optimization_routine - Mutex unlocked - Graph updated");
378}
379
380std::vector<common_lib::structures::Cone>
381GraphSLAMSolver::get_map_estimate() { // TODO: include the map updates in observation to save
382 // time
383 const std::shared_lock lock(this->_mutex_);
384 rclcpp::Time current_time = rclcpp::Clock().now();
385 const gtsam::Values& graph_values = this->_graph_slam_instance_->get_graph_values_reference();
386 std::vector<common_lib::structures::Cone> map_estimate;
387 map_estimate.reserve(this->_graph_slam_instance_->get_landmark_counter());
388 // const gtsam::Marginals marginals(this->_factor_graph_, this->_graph_values_);
389 for (auto it = graph_values.begin(); it != graph_values.end(); ++it) {
390 // Iterate through the landmarks in the _graph_values_
391 if (gtsam::Symbol(it->key).chr() == 'l') {
392 // Get landmarks covariance
393 // const gtsam::Matrix covariance = marginals.marginalCovariance(it->key); // TODO:
394 // covariances are slow af
395 gtsam::Point2 landmark = it->value.cast<gtsam::Point2>();
396 common_lib::structures::Position landmark_position(landmark.x(), landmark.y(), 0.0, 0.0,
397 current_time);
398
399 map_estimate.push_back(common_lib::structures::Cone(
400 landmark_position, common_lib::competition_logic::Color::UNKNOWN, 1.0,
401 current_time)); // TODO: vary cone confidence
402 }
403 }
404 rclcpp::Time end_time = rclcpp::Clock().now();
405 RCLCPP_DEBUG(rclcpp::get_logger("slam"), "get_map_estimate - Time: %f ms",
406 (end_time - current_time).seconds() * 1000.0);
407 return map_estimate;
408}
409
411 // const gtsam::Marginals marginals(this->_factor_graph_, this->_graph_values_);
412 // const gtsam::Key key = gtsam::Symbol('x', this->_pose_counter_);
413 // const gtsam::Matrix covariance = marginals.marginalCovariance(key);
414 const std::shared_lock lock(this->_mutex_);
415 Eigen::Vector3d pose_vector = this->_pose_updater_->get_last_pose();
416
417 return common_lib::structures::Pose(pose_vector(0), pose_vector(1), pose_vector(2), 0.0, 0.0, 0.0,
418 this->_pose_updater_->get_last_pose_update());
419}
420
421std::vector<common_lib::structures::Pose> GraphSLAMSolver::get_trajectory_estimate() {
422 const std::shared_lock lock(this->_mutex_);
423 std::vector<common_lib::structures::Pose> trajectory;
424 const gtsam::Values& graph_values = this->_graph_slam_instance_->get_graph_values_reference();
425 trajectory.reserve(this->_graph_slam_instance_->get_pose_counter());
426 for (auto it = graph_values.begin(); it != graph_values.end(); ++it) {
427 // Iterate through the poses in the _graph_values_
428 if (gtsam::Symbol(it->key).chr() == 'x') {
429 gtsam::Pose2 pose = it->value.cast<gtsam::Pose2>();
430 trajectory.push_back(common_lib::structures::Pose(pose.x(), pose.y(), pose.theta()));
431 }
432 }
433 return trajectory;
434}
435
437 const std::shared_lock lock(this->_mutex_);
438 return this->_graph_slam_instance_->get_covariance_matrix();
439}
440
441Eigen::VectorXi GraphSLAMSolver::get_associations() const {
442 const std::shared_lock lock(this->_mutex_);
443 return this->_associations_;
444}
445
447 const std::shared_lock lock(this->_mutex_);
448 return this->_observations_global_;
449}
450
452 const std::shared_lock lock(this->_mutex_);
453 return this->_map_coordinates_;
454}
std::shared_mutex _mutex_
Eigen::VectorXd get_observations_global() const override
Eigen::VectorXd _observations_global_
std::shared_ptr< GraphSLAMInstance > _graph_slam_instance_
void add_odometry(const common_lib::structures::Pose &pose_difference) override
Add odometry data to the solver (for prediction step)
void add_imu_data(const common_lib::sensor_data::ImuData &imu_data) override
Add IMU data to the solver.
void _asynchronous_optimization_routine()
Asynchronous optimization routine.
bool _add_motion_data_to_graph(const std::shared_ptr< PoseUpdater > pose_updater, const std::shared_ptr< GraphSLAMInstance > graph_slam_instance, bool force_update=false)
Adds motion data to the graph if the pose updater is ready.
void add_velocities(const common_lib::structures::Velocities &velocities) override
Process new velocities data (prediction step)
std::shared_ptr< OdometryModel > _odometry_model
void init(std::weak_ptr< rclcpp::Node > node) override
Initialize the SLAM solver.
rclcpp::CallbackGroup::SharedPtr _reentrant_group_
void add_observations(const std::vector< common_lib::structures::Cone > &cones, rclcpp::Time cones_timestamp) override
Add observations to the solver (correction step)
rclcpp::TimerBase::SharedPtr _optimization_timer_
std::vector< common_lib::structures::Cone > get_map_estimate() override
Get the map estimate object.
GraphSLAMSolver(const SLAMParameters &params, std::shared_ptr< DataAssociationModel > data_association, std::shared_ptr< V2PMotionModel > motion_model, std::shared_ptr< LandmarkFilter > landmark_filter, std::shared_ptr< std::vector< double > > execution_times, std::shared_ptr< LoopClosure > loop_closure)
Construct a new GraphSLAMSolver object.
void load_initial_state(const Eigen::VectorXd &map, const Eigen::Vector3d &pose) override
Initialize the graph SLAM solver with a previously saved map and pose.
common_lib::structures::Pose get_pose_estimate() override
Get the pose estimate object.
Eigen::VectorXi _associations_
Eigen::VectorXd get_map_coordinates() const override
std::queue< MotionData > _motion_data_queue_
std::shared_ptr< PoseUpdater > _pose_updater_
Eigen::MatrixXd get_covariance() override
Get the covariance matrix of the graph.
Eigen::VectorXd _map_coordinates_
std::queue< ObservationData > _observation_data_queue_
common_lib::sensor_data::ImuData _last_imu_data_
std::vector< common_lib::structures::Pose > get_trajectory_estimate() override
Get the trajectory estimate of the car (all poses)
Eigen::VectorXi get_associations() const override
Interface for SLAM solvers.
std::shared_ptr< std::vector< double > > _execution_times_
std::shared_ptr< LoopClosure > _loop_closure_
SLAMParameters _params_
std::shared_ptr< V2PMotionModel > _motion_model_
std::shared_ptr< DataAssociationModel > _data_association_
std::shared_ptr< LandmarkFilter > _landmark_filter_
@ VELOCITIES
Vehicle velocities.
Eigen::VectorXd local_to_global_coordinates(const Eigen::Vector3d &local_reference_frame, const Eigen::VectorXd &local_points)
Transform points from a local reference frame to a global reference frame.
const std::map< std::string, std::function< std::shared_ptr< BaseOptimizer >(const SLAMParameters &)>, std::less<> > graph_slam_optimizer_constructors_map
Definition map.hpp:18
const std::map< std::string, std::function< std::shared_ptr< PoseUpdater >(const SLAMParameters &)>, std::less<> > pose_updater_constructors_map
Definition map.hpp:16
Eigen::Vector3d pose_difference_eigen(const Eigen::Vector3d &pose1, const Eigen::Vector3d &pose2)
Definition utils.cpp:11
Eigen::Vector3d gtsam_pose_to_eigen(const gtsam::Pose2 &pose)
Definition utils.cpp:7
Result of loop closure detection.
Data structure to hold motion data.
rclcpp::Time timestamp_
std::shared_ptr< Eigen::VectorXd > motion_data_
std::shared_ptr< Eigen::VectorXd > motion_data_noise_
Struct containing observation data.
Parameters for the SLAM node.
float imu_acceleration_x_noise_
std::string slam_optimization_mode_
float angular_velocity_noise_
double slam_optimization_period_
double preloaded_map_noise_
std::string slam_optimization_type_
std::string pose_updater_name_
Struct for pose representation.
Definition pose.hpp:13
double orientation_noise
theta in radians
Definition pose.hpp:16