Formula Student Autonomous Systems
The code for the main driverless system
Loading...
Searching...
No Matches
motion_model_test.cpp
Go to the documentation of this file.
1#include <memory>
2#include <rclcpp/rclcpp.hpp>
3
4#include "gtest/gtest.h"
7
8/* ---------------------- Motion Model -------------------------------------*/
9
10TEST(MOTION_MODEL, NOISE_MATRIX_SHAPE_TEST) {
11 Eigen::MatrixXf r_matrix = Eigen::MatrixXf::Zero(6, 6);
12 r_matrix(0, 0) = static_cast<float>(0.1);
13 r_matrix(1, 1) = static_cast<float>(0.1);
14 r_matrix(2, 2) = static_cast<float>(0.1);
15 r_matrix(3, 3) = static_cast<float>(0.1);
16 r_matrix(4, 4) = static_cast<float>(0.1);
17 r_matrix(5, 5) = static_cast<float>(0.1);
18
19 std::shared_ptr<MotionModel> motion_model = std::make_shared<NormalVelocityModel>(r_matrix);
20 Eigen::MatrixXf noise_matrix = motion_model->get_process_noise_covariance_matrix(10);
21 EXPECT_EQ(noise_matrix.rows(), 10);
22 EXPECT_EQ(noise_matrix.cols(), 10);
23 EXPECT_NEAR(noise_matrix(0, 0), 0.1, 0.0001);
24 EXPECT_NEAR(noise_matrix(1, 1), 0.1, 0.0001);
25 EXPECT_NEAR(noise_matrix(2, 2), 0.1, 0.0001);
26 EXPECT_NEAR(noise_matrix(3, 3), 0.1, 0.0001);
27 EXPECT_NEAR(noise_matrix(4, 4), 0.1, 0.0001);
28}
29
30/* ---------------------- Normal Velocity Model ---------------------------*/
31
32TEST(NORMAL_VELOCITY_MODEL, STANDING_STILL_TEST) {
33 Eigen::MatrixXf r_matrix = Eigen::MatrixXf::Zero(5, 5);
34 NormalVelocityModel motion_model = NormalVelocityModel(r_matrix);
35 MotionUpdate prediction_data = {0, 0, 0, 0, 0, rclcpp::Clock().now()};
36 Eigen::VectorXf new_state =
37 motion_model.predict_expected_state(Eigen::VectorXf::Zero(10), prediction_data, 1.0);
38 Eigen::MatrixXf g_matrix =
39 motion_model.get_motion_to_state_matrix(Eigen::VectorXf::Zero(10), prediction_data, 1.0);
40 Eigen::MatrixXf new_covariance = g_matrix * Eigen::MatrixXf::Zero(10, 10) * g_matrix.transpose();
41 EXPECT_DOUBLE_EQ(new_state(0), 0.0);
42 EXPECT_DOUBLE_EQ(new_state(1), 0.0);
43 EXPECT_DOUBLE_EQ(new_state(2), 0.0);
44 for (int i = 0; i < 10; i++) {
45 for (int j = 0; j < 10; j++) {
46 EXPECT_DOUBLE_EQ(new_covariance(i, j), 0.0);
47 }
48 }
49}
50
51TEST(NORMAL_VELOCITY_MODEL, LINEAR_FORWARD_MOVEMENT_TEST) {
52 Eigen::MatrixXf r_matrix = Eigen::MatrixXf::Zero(6, 6);
53 NormalVelocityModel motion_model = NormalVelocityModel(r_matrix);
54 MotionUpdate prediction_data = {1, 0, 0, 0, 0, rclcpp::Clock().now()};
55 Eigen::VectorXf new_state =
56 motion_model.predict_expected_state(Eigen::VectorXf::Zero(10), prediction_data, 1.0);
57 Eigen::MatrixXf g_matrix =
58 motion_model.get_motion_to_state_matrix(Eigen::VectorXf::Zero(10), prediction_data, 1.0);
59
60 Eigen::MatrixXf new_covariance =
61 g_matrix * Eigen::MatrixXf::Ones(10, 10) *
62 g_matrix.transpose(); // Covariance with ones to check if it is modified
63 EXPECT_DOUBLE_EQ(new_state(0), 1.0); // x
64 EXPECT_DOUBLE_EQ(new_state(1), 0.0); // y
65 EXPECT_DOUBLE_EQ(new_state(2), 0.0); // theta
66 for (int i = 0; i < 10; i++) { // Covariance
67 for (int j = 0; j < 10; j++) {
68 if (i == 1 || j == 1) {
69 EXPECT_NE(new_covariance(i, j), 1.0);
70 } // Only y is affected because of the Jacobian
71 }
72 }
73}
74
75TEST(NORMAL_VELOCITY_MODEL, LINEAR_VELOCITY_CURVE_TEST) {
76 Eigen::MatrixXf r_matrix = Eigen::MatrixXf::Zero(5, 5);
77 NormalVelocityModel motion_model = NormalVelocityModel(r_matrix);
78
79 // Moving in a curve with linear acceleration
80 MotionUpdate prediction_data = {1, 0, 0, M_PI / 180, 0, rclcpp::Clock().now()};
81 Eigen::VectorXf new_state =
82 motion_model.predict_expected_state(Eigen::VectorXf::Zero(10), prediction_data, 1.0);
83 Eigen::MatrixXf g_matrix =
84 motion_model.get_motion_to_state_matrix(Eigen::VectorXf::Zero(10), prediction_data, 1.0);
85 Eigen::MatrixXf new_covariance =
86 g_matrix * Eigen::MatrixXf::Ones(10, 10) *
87 g_matrix.transpose(); // Covariance with ones to check if it is modified
88 EXPECT_NEAR(new_state(0), 0.99, 0.05); // x
89 EXPECT_NEAR(new_state(1), 0.01, 0.05); // y
90 EXPECT_NEAR(new_state(2), M_PI / 180, 0.00001); // theta
91}
92
93TEST(NORMAL_VELOCITY_MODEL, AUTONOMOUS_DEMO_TEST) {
94 Eigen::MatrixXf r_matrix = Eigen::MatrixXf::Zero(6, 6);
95 Eigen::VectorXf temp_state = Eigen::VectorXf::Zero(6);
96 NormalVelocityModel motion_model = NormalVelocityModel(r_matrix);
97 MotionUpdate prediction_data = {2.5, 0, 0, 0.001, 0, rclcpp::Clock().now()};
98 for (unsigned int i = 0; i < 4; i++) {
99 temp_state = motion_model.predict_expected_state(temp_state, prediction_data, 1);
100 EXPECT_NEAR(temp_state(0), 2.5 * (i + 1), 0.01 * (i + 1));
101 }
102 prediction_data = {0, 0, 0, 0.001, 0, rclcpp::Clock().now()};
103 for (unsigned int i = 0; i < 4; i++) {
104 temp_state = motion_model.predict_expected_state(temp_state, prediction_data, 1);
105 EXPECT_NEAR(temp_state(0), 10, 0.05);
106 }
107 prediction_data = {2.5, 0, 0, 0.001, 0, rclcpp::Clock().now()};
108 for (unsigned int i = 0; i < 4; i++) {
109 temp_state = motion_model.predict_expected_state(temp_state, prediction_data, 1);
110 EXPECT_NEAR(temp_state(0), 10 + 2.5 * (i + 1), 0.01 * (i + 1));
111 }
112}
113
114TEST(NORMAL_VELOCITY_MODEL, CIRCULAR_MOVEMENT_TEST) {
115 Eigen::MatrixXf r_matrix = Eigen::MatrixXf::Zero(6, 6);
116 NormalVelocityModel motion_model = NormalVelocityModel(r_matrix);
117 MotionUpdate prediction_data = {0, 0, 0, 0, 0, rclcpp::Clock().now()};
118 Eigen::VectorXf temp_state;
119 Eigen::VectorXf new_state = Eigen::VectorXf::Zero(10);
120 float radius = static_cast<float>(12.7324);
121 new_state(0) = 0;
122 new_state(1) = -radius; // Radius of the circle
123 Eigen::MatrixXf g_matrix =
124 motion_model.get_motion_to_state_matrix(Eigen::VectorXf::Zero(10), prediction_data, 1.0);
125 Eigen::MatrixXf new_covariance = Eigen::MatrixXf::Ones(10, 10);
126 for (int i = 0; i < 1000; i++) {
127 prediction_data.translational_velocity = 10;
128 prediction_data.rotational_velocity = M_PI / 4;
129 temp_state = new_state;
130 new_state = motion_model.predict_expected_state(new_state, prediction_data, 0.1);
131 g_matrix = motion_model.get_motion_to_state_matrix(new_state, prediction_data, 0.1);
132 new_covariance = g_matrix * new_covariance * g_matrix.transpose();
133 // Max 0.01 percent calculation error
134 EXPECT_LT(new_state(0), radius + 0.1); // x
135 EXPECT_LT(new_state(1), radius + 0.1); // y
136 EXPECT_NEAR(new_state(0) * new_state(0) + new_state(1) * new_state(1), radius * radius,
137 0.0001 * radius * radius); // Radius
138 EXPECT_LT(new_state(2), 2 * M_PI); // theta
139 }
140}
141
142/* ----------------------- IMU VELOCITY MODEL -------------------------*/
143
144TEST(IMU_VELOCITY_MODEL, STANDING_STILL_TEST) {
145 Eigen::MatrixXf r_matrix = Eigen::MatrixXf::Zero(6, 6);
146 ImuVelocityModel motion_model = ImuVelocityModel(r_matrix);
147 MotionUpdate prediction_data = {0, 0, 0, 0, 0, rclcpp::Clock().now()};
148 Eigen::VectorXf new_state =
149 motion_model.predict_expected_state(Eigen::VectorXf::Zero(10), prediction_data, 1.0);
150 Eigen::MatrixXf g_matrix =
151 motion_model.get_motion_to_state_matrix(Eigen::VectorXf::Zero(10), prediction_data, 1.0);
152 Eigen::MatrixXf new_covariance = g_matrix * Eigen::MatrixXf::Zero(10, 10) * g_matrix.transpose();
153 EXPECT_DOUBLE_EQ(new_state(0), 0.0);
154 EXPECT_DOUBLE_EQ(new_state(1), 0.0);
155 EXPECT_DOUBLE_EQ(new_state(2), 0.0);
156 for (int i = 0; i < 10; i++) {
157 for (int j = 0; j < 10; j++) {
158 EXPECT_DOUBLE_EQ(new_covariance(i, j), 0.0);
159 }
160 }
161}
162
163TEST(IMU_VELOCITY_MODEL, LINEAR_FORWARD_MOVEMENT_TEST) {
164 Eigen::MatrixXf r_matrix = Eigen::MatrixXf::Zero(6, 6);
165 ImuVelocityModel motion_model = ImuVelocityModel(r_matrix);
166 MotionUpdate prediction_data = {0, 1, 0, 0, 0, rclcpp::Clock().now()};
167 Eigen::VectorXf new_state =
168 motion_model.predict_expected_state(Eigen::VectorXf::Zero(10), prediction_data, 1.0);
169 Eigen::MatrixXf g_matrix =
170 motion_model.get_motion_to_state_matrix(Eigen::VectorXf::Zero(10), prediction_data, 1.0);
171 Eigen::MatrixXf new_covariance = g_matrix * Eigen::MatrixXf::Ones(10, 10) * g_matrix.transpose();
172 EXPECT_DOUBLE_EQ(new_state(0), 0.5); // x
173 EXPECT_DOUBLE_EQ(new_state(1), 0.0); // y
174 EXPECT_DOUBLE_EQ(new_state(2), 0.0); // theta
175}
176
177TEST(IMU_VELOCITY_MODEL, LINEAR_VELOCITY_CURVE_TEST) {
178 Eigen::MatrixXf r_matrix = Eigen::MatrixXf::Zero(6, 6);
179 ImuVelocityModel motion_model = ImuVelocityModel(r_matrix);
180 MotionUpdate prediction_data = {0, 5, 10, M_PI / 16, 0, rclcpp::Clock().now()};
181 Eigen::VectorXf new_state =
182 motion_model.predict_expected_state(Eigen::VectorXf::Zero(10), prediction_data, 0.1);
183 Eigen::MatrixXf g_matrix =
184 motion_model.get_motion_to_state_matrix(Eigen::VectorXf::Zero(10), prediction_data, 1.0);
185 Eigen::MatrixXf new_covariance =
186 g_matrix * Eigen::MatrixXf::Ones(10, 10) *
187 g_matrix.transpose(); // Covariance with ones to check if it is modified
188 EXPECT_NEAR(new_state(0), 0.025, 0.0001); // x
189 EXPECT_NEAR(new_state(1), 0.05, 0.001); // y
190 EXPECT_NEAR(new_state(2), M_PI / 160, 0.1); // theta
191 EXPECT_NEAR(new_state(3), 0.5, 0.001); // Vx
192 EXPECT_NEAR(new_state(4), 1, 0.001); // Vy
193 EXPECT_NEAR(new_state(5), M_PI / 16, 0.001); // rot vel
194}
195
196TEST(IMU_VELOCITY_MODEL, COMPLEX_MOVEMENT_TEST) {
197 Eigen::MatrixXf r_matrix = Eigen::MatrixXf::Zero(6, 6);
198 ImuVelocityModel motion_model = ImuVelocityModel(r_matrix);
199 MotionUpdate prediction_data = {0, 0, 0, 0, 0, rclcpp::Clock().now()};
200 Eigen::VectorXf temp_state;
201 Eigen::VectorXf new_state = Eigen::VectorXf::Zero(10);
202 double radius = 12.7324;
203 new_state(0) = 0;
204 new_state(1) = static_cast<float>(-radius); // Radius of the circle
205 Eigen::MatrixXf g_matrix =
206 motion_model.get_motion_to_state_matrix(Eigen::VectorXf::Zero(10), prediction_data, 1.0);
207 Eigen::MatrixXf new_covariance = Eigen::MatrixXf::Ones(10, 10);
208
209 for (int i = 0; i < 1000; i++) {
210 prediction_data.rotational_velocity = M_PI / 4;
211 temp_state = new_state;
212 new_state = motion_model.predict_expected_state(new_state, prediction_data, 0.1);
213 g_matrix = motion_model.get_motion_to_state_matrix(new_state, prediction_data, 0.1);
214 new_covariance = g_matrix * new_covariance * g_matrix.transpose();
215
216 EXPECT_LT(new_state(0), radius + 0.1); // x
217 EXPECT_LT(new_state(1), radius + 0.1); // y
218 EXPECT_NEAR(new_state(0) * new_state(0) + new_state(1) * new_state(1), radius * radius,
219 0.0001 * radius * radius); // Radius
220 EXPECT_LT(new_state(2), 2 * M_PI); // theta
221 }
222}
Motion estimation that uses the specific values of the x and y axis accelerations,...
Eigen::MatrixXf get_motion_to_state_matrix(const Eigen::VectorXf &expected_state, const MotionUpdate &motion_prediction_data, const double time_interval) const override
Calculate state covariance matrix from velocity model using IMU data and linear functions Uses transl...
Eigen::VectorXf predict_expected_state(const Eigen::VectorXf &expected_state, const MotionUpdate &motion_prediction_data, const double time_interval) const override
Calculate expected state vector from velocity model using IMU data and linear functions Uses translat...
Motion estimation that uses the module of the velocity and the rotational velocity.
Eigen::VectorXf predict_expected_state(const Eigen::VectorXf &expected_state, const MotionUpdate &motion_prediction_data, const double time_interval) const override
Calculate expected state vector from velocity model using normal motion data Uses translation velocit...
Eigen::MatrixXf get_motion_to_state_matrix(const Eigen::VectorXf &expected_state, const MotionUpdate &motion_prediction_data, const double time_interval) const override
Calculate state covariance matrix from velocity model using normal motion data Uses translation veloc...
TEST(MOTION_MODEL, NOISE_MATRIX_SHAPE_TEST)
Struct for data retrieved by the IMU.
double rotational_velocity
Degrees per sec.
double translational_velocity
Meters per sec.