Formula Student Autonomous Systems
The code for the main driverless system
Loading...
Searching...
No Matches
sliding_window_levenberg_optimizer_test.cpp
Go to the documentation of this file.
2
3#include <gmock/gmock.h>
4#include <gtest/gtest.h>
5#include <gtsam/geometry/Pose2.h>
6#include <gtsam/inference/Symbol.h>
7#include <gtsam/sam/BearingRangeFactor.h>
8#include <gtsam/slam/BetweenFactor.h>
9#include <yaml-cpp/yaml.h>
10
11#include <iostream>
12
16class SlidingWindowLevenbergOptimizerTest : public testing::Test {
17public:
19
20protected:
21 gtsam::NonlinearFactorGraph factor_graph;
22 gtsam::Values graph_values;
24 std::shared_ptr<SlidingWindowLevenbergOptimizer> optimizer;
25
26 void SetUp() override {
27 // Set up any necessary data or state before each test
28 factor_graph = gtsam::NonlinearFactorGraph();
29 graph_values = gtsam::Values();
31 }
32
33 void TearDown() override {
34 // Clean up any resources or state after each test
35 factor_graph.resize(0);
36 graph_values.clear();
37 }
38
51 void test_sliding_window(unsigned int num_poses, unsigned int num_landmarks,
52 unsigned int window_size) {
53 // ARRANGE
54 params.sliding_window_size_ = window_size; // Set sliding window size to 5
55 optimizer = std::make_shared<SlidingWindowLevenbergOptimizer>(params);
56
57 // Add some pose values to the graph
58 for (unsigned int i = 1; i <= num_poses; i++) {
59 gtsam::Key key = gtsam::Symbol('x', i);
60 graph_values.insert(key, gtsam::Pose2(i * 5, i * 5, 0));
61 }
62
63 // Add some landmark values to the graph
64 for (unsigned int j = 1; j <= num_landmarks; j++) {
65 gtsam::Key key = gtsam::Symbol('l', j);
66 graph_values.insert(key, gtsam::Point2(j * 5 + 5, 0));
67 }
68
69 // Add between factors
70 for (unsigned int i = 1; i <= num_poses; i++) {
71 gtsam::Key key = gtsam::Symbol('x', i);
72 gtsam::Key key2 = gtsam::Symbol('x', i + 1);
73 factor_graph.add(gtsam::BetweenFactor<gtsam::Pose2>(
74 key, key2, gtsam::Pose2(3, 1, 0),
75 gtsam::noiseModel::Diagonal::Sigmas(gtsam::Vector3(0.2, 0.2, 0.2))));
76 }
77
78 // Add bearing range factors
79 for (unsigned int landmark_index = 1; landmark_index <= num_landmarks; landmark_index++) {
80 gtsam::Key key = gtsam::Symbol('l', landmark_index);
81 for (unsigned int pose_index = 1; pose_index <= num_poses; ++pose_index) {
82 factor_graph.add(gtsam::BearingRangeFactor<gtsam::Pose2, gtsam::Point2>(
83 gtsam::Symbol('x', pose_index), key, gtsam::Rot2(0), 1,
84 gtsam::noiseModel::Diagonal::Sigmas(gtsam::Vector2(0.1, 0.1))));
85 }
86 }
87
88 // ACT
89 gtsam::Values optimized_values;
90 gtsam::Values old_values = graph_values;
91 EXPECT_NO_THROW(optimized_values =
92 optimizer->optimize(factor_graph, graph_values, num_poses, num_landmarks));
93
94 // ASSERT
95 EXPECT_EQ(optimized_values.size(), num_poses + num_landmarks);
96 for (unsigned int i = 1; i <= num_poses; i++) {
97 EXPECT_TRUE(optimized_values.exists(gtsam::Symbol('x', i)));
98 }
99 for (unsigned int j = 1; j <= num_landmarks; j++) {
100 EXPECT_TRUE(optimized_values.exists(gtsam::Symbol('l', j)));
101 }
102
103 // Assert that only the last 5 poses are optimized
104 for (int i = 1; i <= static_cast<int>(num_poses - window_size); i++) {
105 gtsam::Pose2 optimized_pose = optimized_values.at<gtsam::Pose2>(gtsam::Symbol('x', i));
106 gtsam::Pose2 old_pose = old_values.at<gtsam::Pose2>(gtsam::Symbol('x', i));
107 EXPECT_TRUE(optimized_pose.equals(old_pose));
108 }
109
110 // Assert that the optimized values are close to the expected values, but not equal
111 for (unsigned int i = num_poses - window_size + 1; i <= num_poses; i++) {
112 gtsam::Pose2 optimized_pose = optimized_values.at<gtsam::Pose2>(gtsam::Symbol('x', i));
113 gtsam::Pose2 old_pose = old_values.at<gtsam::Pose2>(gtsam::Symbol('x', i));
114 EXPECT_FALSE(optimized_pose.equals(old_pose) && num_landmarks != 0);
115 }
116
117 for (unsigned int landmark_index = 1; landmark_index <= num_landmarks; landmark_index++) {
118 gtsam::Point2 optimized_landmark =
119 optimized_values.at<gtsam::Point2>(gtsam::Symbol('l', landmark_index));
120 gtsam::Point2 old_landmark = old_values.at<gtsam::Point2>(gtsam::Symbol('l', landmark_index));
121 EXPECT_FALSE(optimized_landmark.x() == old_landmark.x() && num_poses != 0);
122 EXPECT_FALSE(optimized_landmark.y() == old_landmark.y() && num_poses != 0);
123 }
124 }
125};
126
132TEST_F(SlidingWindowLevenbergOptimizerTest, LessPosesThanSlidingWindowJustPoses) {
133 test_sliding_window(3, 0, 5);
134}
135
141TEST_F(SlidingWindowLevenbergOptimizerTest, EmptyValuesAndGraph) { test_sliding_window(0, 0, 5); }
142
148TEST_F(SlidingWindowLevenbergOptimizerTest, JustLandmarks) { test_sliding_window(0, 3, 5); }
149
155TEST_F(SlidingWindowLevenbergOptimizerTest, LessPosesThanSlidingWindow) {
156 test_sliding_window(3, 3, 5);
157}
158
164TEST_F(SlidingWindowLevenbergOptimizerTest, SamePosesThanSlidingWindow) {
165 test_sliding_window(5, 3, 5);
166}
167
173TEST_F(SlidingWindowLevenbergOptimizerTest, MorePosesThanSlidingWindow) {
174 test_sliding_window(10, 3, 5);
175}
Whitebox unit test for the SlidingWindowLevenbergOptimizer.
void test_sliding_window(unsigned int num_poses, unsigned int num_landmarks, unsigned int window_size)
Test the SlidingWindowLevenbergOptimizer.
std::shared_ptr< SlidingWindowLevenbergOptimizer > optimizer
TEST_F(SlidingWindowLevenbergOptimizerTest, LessPosesThanSlidingWindowJustPoses)
Test the SlidingWindowLevenbergOptimizer.
Parameters for the SLAM node.
unsigned int sliding_window_size_