Formula Student Autonomous Systems
The code for the main driverless system
Loading...
Searching...
No Matches
data_association_test.cpp
Go to the documentation of this file.
2
3#include <gtest/gtest.h>
4
5#include <cmath>
6
9
13TEST(DATA_ASSOCIATION_MODEL, NEW_LANDMARK) {
14 // Arrange
15 float max_landmark_distance = 15.0f;
16 MaxLikelihood data_association_model(max_landmark_distance);
17
18 Eigen::VectorXf state_vector(8);
19 state_vector << 0, 0, 0, 0, 0, 0, 1, 1; // Initial state with one landmark at (5, 5)
20
21 Eigen::MatrixXf covariance_matrix = Eigen::MatrixXf::Identity(8, 8);
22
23 std::vector<common_lib::structures::Cone> perception_map = {
24 {common_lib::structures::Cone{{10, 10}, common_lib::competition_logic::Color::BLUE, 1.0}}};
25
26 std::vector<int> matched_ids;
27 std::vector<Eigen::Vector2f> matched_cone_positions;
28 std::vector<Eigen::Vector2f> new_features;
29
30 Eigen::MatrixXf observation_noise_covariance_matrix = Eigen::MatrixXf::Identity(2, 2);
31 ObservationModel observation_model(observation_noise_covariance_matrix);
32
33 // Act
34 data_association_model.associate_n_filter(perception_map, state_vector, covariance_matrix,
35 matched_ids, matched_cone_positions, new_features,
36 &observation_model);
37 // Assert
38 ASSERT_EQ(new_features.size(), 1);
39 ASSERT_EQ(new_features[0](0), 10);
40 ASSERT_EQ(new_features[0](1), 10);
41}
42
46TEST(DATA_ASSOCIATION_MODEL, PERFECT_MATCH) {
47 // Arrange
48 float max_landmark_distance = 15.0f;
49 MaxLikelihood data_association_model(max_landmark_distance);
50
51 Eigen::VectorXf state_vector(8);
52 state_vector << 0, 0, 0, 0, 0, 0, 3, 4; // State vector with one landmark at (3, 4)
53
54 Eigen::MatrixXf covariance_matrix = Eigen::MatrixXf::Identity(8, 8);
55
56 std::vector<common_lib::structures::Cone> perception_map = {
57 {common_lib::structures::Cone{{3.0, 4.0}, common_lib::competition_logic::Color::BLUE, 1.0}}};
58
59 std::vector<int> matched_ids;
60 std::vector<Eigen::Vector2f> matched_cone_positions;
61 std::vector<Eigen::Vector2f> new_features;
62
63 Eigen::MatrixXf observation_noise_covariance_matrix = Eigen::MatrixXf::Identity(2, 2);
64 ObservationModel observation_model(observation_noise_covariance_matrix);
65
66 // Act
67 data_association_model.associate_n_filter(perception_map, state_vector, covariance_matrix,
68 matched_ids, matched_cone_positions, new_features,
69 &observation_model);
70
71 // Assert
72 ASSERT_EQ(matched_ids.size(), 1);
73 ASSERT_EQ(matched_cone_positions.size(), 1);
74 ASSERT_EQ(new_features.size(), 0);
75
76 ASSERT_EQ(matched_ids[0],
77 6); // Assuming the first landmark in the state vector is the perfect match
78 ASSERT_FLOAT_EQ(matched_cone_positions[0](0), 3.0);
79 ASSERT_FLOAT_EQ(matched_cone_positions[0](1), 4.0);
80}
81
85TEST(DATA_ASSOCIATION_MODEL, NEAR_MATCH) {
86 // Arrange
87 float max_landmark_distance = 15.0f;
88 MaxLikelihood data_association_model(max_landmark_distance);
89
90 Eigen::VectorXf state_vector(8);
91 state_vector << 0, 0, 0, 0, 0, 0, 3.1, 4.1; // State vector with one landmark at (3, 4)
92
93 Eigen::MatrixXf covariance_matrix = Eigen::MatrixXf::Identity(8, 8);
94
95 std::vector<common_lib::structures::Cone> perception_map = {
96 {common_lib::structures::Cone{{3.0, 4.0}, common_lib::competition_logic::Color::BLUE, 1.0}}};
97
98 std::vector<int> matched_ids;
99 std::vector<Eigen::Vector2f> matched_cone_positions;
100 std::vector<Eigen::Vector2f> new_features;
101
102 Eigen::MatrixXf observation_noise_covariance_matrix = Eigen::MatrixXf::Identity(2, 2);
103 ObservationModel observation_model(observation_noise_covariance_matrix);
104
105 // Act
106 data_association_model.associate_n_filter(perception_map, state_vector, covariance_matrix,
107 matched_ids, matched_cone_positions, new_features,
108 &observation_model);
109
110 // Assert
111 ASSERT_EQ(matched_ids.size(), 1);
112 ASSERT_EQ(matched_cone_positions.size(), 1);
113 ASSERT_EQ(new_features.size(), 0);
114
115 ASSERT_EQ(matched_ids[0],
116 6); // Assuming the first landmark in the state vector is the perfect match
117 ASSERT_NEAR(matched_cone_positions[0](0), 3.0, 0.1);
118 ASSERT_NEAR(matched_cone_positions[0](1), 4.0, 0.1);
119}
120
124TEST(DATA_ASSOCIATION_MODEL, MISMATCH_NOT_NEW) {
125 // Arrange
126 float max_landmark_distance = 15.0f;
127 MaxLikelihood data_association_model(max_landmark_distance);
128
129 Eigen::VectorXf state_vector(8);
130 state_vector << 0, 0, 0, 0, 0, 0, 7, 8; // State vector with one landmark at (3, 4)
131
132 Eigen::MatrixXf covariance_matrix = Eigen::MatrixXf::Identity(8, 8);
133
134 std::vector<common_lib::structures::Cone> perception_map = {
135 {common_lib::structures::Cone{{3.0, 4.0}, common_lib::competition_logic::Color::BLUE, 1.0}}};
136
137 std::vector<int> matched_ids;
138 std::vector<Eigen::Vector2f> matched_cone_positions;
139 std::vector<Eigen::Vector2f> new_features;
140
141 Eigen::MatrixXf observation_noise_covariance_matrix = Eigen::MatrixXf::Identity(2, 2);
142 ObservationModel observation_model(observation_noise_covariance_matrix);
143
144 // Act
145 data_association_model.associate_n_filter(perception_map, state_vector, covariance_matrix,
146 matched_ids, matched_cone_positions, new_features,
147 &observation_model);
148
149 // Assert
150
151 ASSERT_EQ(matched_ids.size(), 0);
152 ASSERT_EQ(matched_cone_positions.size(), 0);
153 ASSERT_EQ(new_features.size(), 0);
154}
158TEST(DATA_ASSOCIATION_MODEL, VALID_MATCH_ZERO_DELTA) {
159 // Arrange
160 float max_landmark_distance = 15.0f;
161 MaxLikelihood data_association_model(max_landmark_distance);
162
163 Eigen::VectorXf state_vector(8);
164 state_vector << 0, 0, 0, 0, 0, 0, 3, 4; // State vector with one landmark at (3, 4)
165
166 Eigen::MatrixXf covariance_matrix = Eigen::MatrixXf::Identity(8, 8);
167
168 std::vector<common_lib::structures::Cone> perception_map = {
169 {common_lib::structures::Cone{{3.0, 4.0}, common_lib::competition_logic::Color::BLUE, 1.0}}};
170
171 std::vector<int> matched_ids;
172 std::vector<Eigen::Vector2f> matched_cone_positions;
173 std::vector<Eigen::Vector2f> new_features;
174
175 // Zero noise covariance matrix
176 Eigen::MatrixXf observation_noise_covariance_matrix = Eigen::MatrixXf::Zero(2, 2);
177 ObservationModel observation_model(observation_noise_covariance_matrix);
178
179 // Act
180 data_association_model.associate_n_filter(perception_map, state_vector, covariance_matrix,
181 matched_ids, matched_cone_positions, new_features,
182 &observation_model);
183
184 // Assert
185 ASSERT_EQ(matched_ids.size(), 1);
186 ASSERT_EQ(matched_cone_positions.size(), 1);
187 ASSERT_EQ(new_features.size(), 0);
188
189 ASSERT_EQ(matched_ids[0],
190 6); // Assuming the first landmark in the state vector is the perfect match
191 ASSERT_FLOAT_EQ(matched_cone_positions[0](0), 3.0);
192 ASSERT_FLOAT_EQ(matched_cone_positions[0](1), 4.0);
193}
194
198TEST(DATA_ASSOCIATION_MODEL, VALID_MATCH_MODERATE_NOISE) {
199 // Arrange
200 float max_landmark_distance = 15.0f;
201 MaxLikelihood data_association_model(max_landmark_distance);
202
203 Eigen::VectorXf state_vector(8);
204 state_vector << 0, 0, 0, 0, 0, 0, 3, 4; // State vector with one landmark at (3, 4)
205
206 Eigen::MatrixXf covariance_matrix = Eigen::MatrixXf::Identity(8, 8);
207
208 std::vector<common_lib::structures::Cone> perception_map = {
209 {common_lib::structures::Cone{{3.1, 4.1}, common_lib::competition_logic::Color::BLUE, 1.0}}};
210
211 std::vector<int> matched_ids;
212 std::vector<Eigen::Vector2f> matched_cone_positions;
213 std::vector<Eigen::Vector2f> new_features;
214
215 // Moderate noise covariance matrix
216 Eigen::MatrixXf observation_noise_covariance_matrix = 0.1 * Eigen::MatrixXf::Identity(2, 2);
217 ObservationModel observation_model(observation_noise_covariance_matrix);
218
219 // Act
220 data_association_model.associate_n_filter(perception_map, state_vector, covariance_matrix,
221 matched_ids, matched_cone_positions, new_features,
222 &observation_model);
223
224 // Assert
225 ASSERT_EQ(matched_ids.size(), 1);
226 ASSERT_EQ(matched_cone_positions.size(), 1);
227 ASSERT_EQ(new_features.size(), 0);
228
229 ASSERT_EQ(matched_ids[0],
230 6); // Assuming the first landmark in the state vector is the perfect match
231 ASSERT_NEAR(matched_cone_positions[0](0), 3.1, 0.1);
232 ASSERT_NEAR(matched_cone_positions[0](1), 4.1, 0.1);
233}
237TEST(DATA_ASSOCIATION_MODEL, VALID_MATCH_INCREASING_NOISE) {
238 // Arrange
239 float max_landmark_distance = 15.0f;
240 MaxLikelihood data_association_model(max_landmark_distance);
241
242 Eigen::VectorXf state_vector(8);
243 state_vector << 0, 0, 0, 0, 0, 0, 3, 4; // State vector with one landmark at (3, 4)
244
245 Eigen::MatrixXf covariance_matrix = Eigen::MatrixXf::Identity(8, 8);
246
247 std::vector<common_lib::structures::Cone> perception_map = {
248 {common_lib::structures::Cone{{5.5, 6.5}, common_lib::competition_logic::Color::BLUE, 1.0}}};
249
250 std::vector<int> matched_ids;
251 std::vector<Eigen::Vector2f> matched_cone_positions;
252 std::vector<Eigen::Vector2f> new_features;
253
254 // Low noise covariance matrix
255 Eigen::MatrixXf low_noise_covariance_matrix = 0.1 * Eigen::MatrixXf::Identity(2, 2);
256 ObservationModel low_noise_model(low_noise_covariance_matrix);
257
258 // Act with low noise
259 data_association_model.associate_n_filter(perception_map, state_vector, covariance_matrix,
260 matched_ids, matched_cone_positions, new_features,
261 &low_noise_model);
262
263 // Assert no match due to low noise
264 ASSERT_EQ(matched_ids.size(), 0);
265 ASSERT_EQ(matched_cone_positions.size(), 0);
266
267 // Clear previous results
268 matched_ids.clear();
269 matched_cone_positions.clear();
270 new_features.clear();
271
272 // High noise covariance matrix
273 Eigen::MatrixXf high_noise_covariance_matrix = 10.0 * Eigen::MatrixXf::Identity(2, 2);
274 ObservationModel high_noise_model(high_noise_covariance_matrix);
275
276 // Act with high noise
277 data_association_model.associate_n_filter(perception_map, state_vector, covariance_matrix,
278 matched_ids, matched_cone_positions, new_features,
279 &high_noise_model);
280
281 // Assert match due to high noise
282 ASSERT_EQ(matched_ids.size(), 1);
283 ASSERT_EQ(matched_cone_positions.size(), 1);
284
285 ASSERT_EQ(matched_ids[0], 6);
286}
290TEST(DATA_ASSOCIATION_MODEL, INVALID_PARAMETERS) {
291 // Arrange
292 float invalid_max_landmark_distance = 0.5f; // Less than 1
293 float valid_max_landmark_distance = 15.0f;
294 float invalid_association_gate = -1.0f; // Negative value
295 float invalid_new_landmark_gate = -1.0f; // Negative value
296
297 // Act & Assert
298 // Test invalid max_landmark_distance
299 EXPECT_THROW({ MaxLikelihood data_association_model(invalid_max_landmark_distance); },
300 std::invalid_argument);
301
302 // Test invalid association_gate_
303 MaxLikelihood::association_gate_ = invalid_association_gate;
304 EXPECT_THROW({ MaxLikelihood data_association_model(valid_max_landmark_distance); },
305 std::invalid_argument);
306
308
309 MaxLikelihood::new_landmark_gate_ = invalid_new_landmark_gate;
310 EXPECT_THROW({ MaxLikelihood data_association_model(valid_max_landmark_distance); },
311 std::invalid_argument);
312
314}
Maximum Likelihood Method class, used to match observations to landmarks in the map with maximum like...
int associate_n_filter(const std::vector< common_lib::structures::Cone > &perception_map, Eigen::VectorXf &_x_vector_, Eigen::MatrixXf &_p_matrix_, std::vector< int > &matched_ids, std::vector< Eigen::Vector2f > &matched_cone_positions, std::vector< Eigen::Vector2f > &new_features, ObservationModel *observation_model) const override
normalized distance gate (closest unmatched landmark)
static float new_landmark_gate_
normalized innovation squared gate
static float association_gate_
Observation Model class compiled of functions for observation model.
TEST(DATA_ASSOCIATION_MODEL, NEW_LANDMARK)
Test case for when a landmark is not in the state yet.