Formula Student Autonomous Systems
The code for the main driverless system
Loading...
Searching...
No Matches
observation_models.cpp
Go to the documentation of this file.
2
3#include "rclcpp/rclcpp.hpp"
4
5ObservationModel::ObservationModel(const Eigen::MatrixXf &observation_noise_covariance_matrix)
6 : _observation_noise_covariance_matrix_(observation_noise_covariance_matrix) {}
7
9 const Eigen::VectorXf &expected_state, const ObservationData &observation_data) const {
10 RCLCPP_DEBUG(rclcpp::get_logger("ekf_state_est"),
11 "Observation Model - Expected State: %f %f %f %f %f", expected_state(0),
12 expected_state(1), expected_state(2), expected_state(3), expected_state(4));
13 RCLCPP_DEBUG(rclcpp::get_logger("ekf_state_est"), "Observation Model - Observation Data: (%f,%f)",
14 observation_data.position.x, observation_data.position.y);
15
16 Eigen::Matrix3f transformation_matrix = Eigen::Matrix3f::Identity();
17 transformation_matrix(0, 0) = cos(expected_state(2));
18 transformation_matrix(0, 1) = -sin(expected_state(2));
19 transformation_matrix(0, 2) = expected_state(0);
20 transformation_matrix(1, 0) = sin(expected_state(2));
21 transformation_matrix(1, 1) = cos(expected_state(2));
22 transformation_matrix(1, 2) = expected_state(1);
23
24 Eigen::Vector3f observation =
25 Eigen::Vector3f(observation_data.position.x, observation_data.position.y, 1);
26 Eigen::Vector3f observed_landmark_absolute_position = transformation_matrix * observation;
27
28 return Eigen::Vector2f(observed_landmark_absolute_position(0),
29 observed_landmark_absolute_position(1));
30}
31
32Eigen::MatrixXf ObservationModel::get_gv(const Eigen::VectorXf &expected_state,
33 const ObservationData &observation_data) const {
34 Eigen::MatrixXf gv(2, 3); // Initialize a 2x3 matrix
35
36 gv << 1, 0,
37 -observation_data.position.x * sin(expected_state(2)) -
38 observation_data.position.y * cos(expected_state(2)),
39 0, 1,
40 observation_data.position.x * cos(expected_state(2)) -
41 observation_data.position.y * sin(expected_state(2));
42
43 return gv;
44}
45
46Eigen::MatrixXf ObservationModel::get_gz(const Eigen::VectorXf &expected_state,
47 const ObservationData &observation_data) const {
48 Eigen::MatrixXf gz(2, 2); // Initialize a 2x2 matrix
49
50 gz << cos(expected_state(2)), -sin(expected_state(2)), sin(expected_state(2)),
51 cos(expected_state(2));
52
53 return gz;
54}
55
56Eigen::Vector2f ObservationModel::observation_model(const Eigen::VectorXf &expected_state,
57 const unsigned int landmark_index) const {
58 Eigen::Matrix3f transformation_matrix = Eigen::Matrix3f::Identity();
59 // transformation matrix is the matrix that transforms the landmark position from the world
60 // coordinate system to the robot coordinate system for future comparison with the observed
61 // landmark position
62
63 transformation_matrix(0, 0) = cos(-expected_state(2));
64 transformation_matrix(0, 1) = -sin(-expected_state(2));
65 transformation_matrix(0, 2) =
66 -expected_state(0) * cos(-expected_state(2)) + expected_state(1) * sin(-expected_state(2));
67 transformation_matrix(1, 0) = sin(-expected_state(2));
68 transformation_matrix(1, 1) = cos(-expected_state(2));
69 transformation_matrix(1, 2) =
70 -expected_state(0) * sin(-expected_state(2)) - expected_state(1) * cos(-expected_state(2));
71 Eigen::Vector3f observation =
72 transformation_matrix *
73 Eigen::Vector3f(static_cast<float>(expected_state(landmark_index)),
74 static_cast<float>(expected_state(landmark_index + 1)), 1);
75
76 return Eigen::Vector2f(observation(0), observation(1));
77}
78
80 const std::vector<Eigen::Vector2f> &observations) const {
81 Eigen::VectorXf formatted_observation(2 * observations.size());
82 for (int i = 0; i < static_cast<int>(observations.size()); i++) {
83 formatted_observation(2 * i) = observations[i](0);
84 formatted_observation(2 * i + 1) = observations[i](1);
85 }
86 return formatted_observation;
87}
88
90 const Eigen::VectorXf &current_state, const std::vector<int> &matched_ids) const {
91 auto number_of_landmarks = static_cast<int>(matched_ids.size());
92 Eigen::VectorXf expected_observation(2 * number_of_landmarks);
93 // transformation matrix is the matrix that transforms the landmark position from the world
94 // coordinate system to the robot coordinate system for future comparison with the observed
95 // landmark position
96
97 double cossine_minus_theta = cos(-current_state(2));
98 double sine_minus_theta = sin(-current_state(2));
99
100 double car_shift_x =
101 -current_state(0) * cossine_minus_theta + current_state(1) * sine_minus_theta;
102 double car_shift_y =
103 -current_state(0) * sine_minus_theta - current_state(1) * cossine_minus_theta;
104
105 unsigned int j = 0;
106 for (unsigned int i : matched_ids) {
107 expected_observation(2 * j) = cossine_minus_theta * current_state(i) -
108 sine_minus_theta * current_state(i + 1) + car_shift_x;
109 expected_observation(2 * j + 1) = sine_minus_theta * current_state(i) +
110 cossine_minus_theta * current_state(i + 1) + car_shift_y;
111 j++;
112 }
113
114 return expected_observation;
115}
116
118 const Eigen::VectorXf &current_state, const std::vector<int> &matched_ids) const {
119 int number_of_landmarks = matched_ids.size();
120 double cossine_minus_theta = cos(-current_state(2));
121 double sine_minus_theta = sin(-current_state(2));
122 Eigen::MatrixXf jacobian = Eigen::MatrixXf::Zero(number_of_landmarks * 2, current_state.size());
123 for (int i = 0; i < number_of_landmarks; i++) {
124 jacobian(2 * i, 0) = -cossine_minus_theta;
125 jacobian(2 * i + 1, 0) = -sine_minus_theta;
126 }
127 for (int i = 0; i < number_of_landmarks; i++) {
128 jacobian(2 * i, 1) = sine_minus_theta;
129 jacobian(2 * i + 1, 1) = -cossine_minus_theta;
130 }
131 for (int i = 0; i < number_of_landmarks; i++) {
132 jacobian(2 * i, 2) =
133 sine_minus_theta * (current_state(matched_ids[i]) - current_state(0)) +
134 cossine_minus_theta * (current_state(matched_ids[i] + 1) - current_state(1));
135 jacobian(2 * i + 1, 2) =
136 -cossine_minus_theta * (current_state(matched_ids[i]) - current_state(0)) +
137 sine_minus_theta * (current_state(matched_ids[i] + 1) - current_state(1));
138 }
139 for (int i = 0; i < number_of_landmarks; i++) {
140 jacobian(2 * i, matched_ids[i]) = cossine_minus_theta;
141 jacobian(2 * i, matched_ids[i] + 1) = -sine_minus_theta;
142 jacobian(2 * i + 1, matched_ids[i]) = sine_minus_theta;
143 jacobian(2 * i + 1, matched_ids[i] + 1) = cossine_minus_theta;
144 }
145 return jacobian;
146}
147
149 const Eigen::VectorXf &expected_state, const unsigned int landmark_index,
150 const unsigned int state_size) const {
151 // Old Implementation
152 Eigen::MatrixXf reformating_matrix = Eigen::MatrixXf::Zero(8, state_size);
153 reformating_matrix(0, 0) = 1;
154 reformating_matrix(1, 1) = 1;
155 reformating_matrix(2, 2) = 1;
156 reformating_matrix(3, 3) = 1;
157 reformating_matrix(4, 4) = 1;
158 reformating_matrix(5, 5) = 1;
159 reformating_matrix(6, landmark_index) = 1;
160 reformating_matrix(7, landmark_index + 1) = 1;
161
162 // partial derivative of h(x) or z_hat with respect to
163 // (x,y,theta,landmark_x,landmark_y)
164 Eigen::MatrixXf low_jacobian = Eigen::MatrixXf::Zero(2, 8);
165
166 // the function h that is derived is the observation model function which after the matrix
167 // multiplication becomes:
168 // expected_landmark_x = I * cos(t) + m * sin(t) - x * cos(t) - y * sin(t); -> FUNC_X
169 // expected_landmark_y = -I * sin(t) + m * cos(t) + x * sin(t) - y * cos(t); -> FUNC_Y
170 // and so the low_jacobian below is:
171 // FUNC_X partially derived in x, y, theta, vx, vy, omega, m, n
172 // FUNC_Y partially derived in x, y, theta, vx, vy, omega, m, n
173 // where x is the x coordinate of the robot, y is the y coordinate of the robot, theta is the
174 // orientation of the robot, m is the x coordinate of the landmark, n is the y coordinate of the
175 // landmark
176 low_jacobian(0, 0) = -cos(-expected_state(2));
177 low_jacobian(0, 1) = sin(-expected_state(2));
178 low_jacobian(0, 2) = -expected_state(landmark_index) * sin(expected_state(2)) +
179 expected_state(landmark_index + 1) * cos(-expected_state(2)) +
180 expected_state(0) * sin(expected_state(2)) -
181 expected_state(1) * cos(-expected_state(2));
182 low_jacobian(0, 3) = 0;
183 low_jacobian(0, 4) = 0;
184 low_jacobian(0, 5) = 0;
185 low_jacobian(0, 6) = cos(-expected_state(2));
186 low_jacobian(0, 7) = -sin(-expected_state(2));
187
188 low_jacobian(1, 0) = -sin(-expected_state(2));
189 low_jacobian(1, 1) = -cos(-expected_state(2));
190 low_jacobian(1, 2) = -expected_state(landmark_index) * cos(-expected_state(2)) -
191 expected_state(landmark_index + 1) * sin(expected_state(2)) +
192 expected_state(0) * cos(-expected_state(2)) +
193 expected_state(1) * sin(expected_state(2));
194 low_jacobian(1, 3) = 0;
195 low_jacobian(1, 4) = 0;
196 low_jacobian(1, 5) = 0;
197 low_jacobian(1, 6) = sin(-expected_state(2));
198 low_jacobian(1, 7) = cos(-expected_state(2));
199
200 Eigen::MatrixXf validation_jacobian = low_jacobian * reformating_matrix;
201
202 return validation_jacobian;
203}
204
208
210 const int observation_size) const {
211 double noise_value = this->get_observation_noise_covariance_matrix()(0, 0);
212 return Eigen::MatrixXf::Identity(observation_size, observation_size) * noise_value;
213}
214
216 return Eigen::MatrixXf::Identity(2, 2) * noise_value;
217}
Eigen::Vector2f observation_model(const Eigen::VectorXf &expected_state, const unsigned int landmark_index) const
Calculate expected observation from the state vector.
Eigen::MatrixXf get_full_observation_noise_covariance_matrix(const int observation_size) const
Eigen::Vector2f inverse_observation_model(const Eigen::VectorXf &expected_state, const ObservationData &observation_data) const
Calculate landmark position from observation.
Eigen::MatrixXf get_gv(const Eigen::VectorXf &expected_state, const ObservationData &observation_data) const
Eigen::MatrixXf _observation_noise_covariance_matrix_
H or C.
Eigen::VectorXf format_observation(const std::vector< Eigen::Vector2f > &observations) const
Eigen::MatrixXf get_observation_noise_covariance_matrix() const
Get the observation noise covariance matrix (C or H)
Eigen::MatrixXf get_state_to_observation_matrix(const Eigen::VectorXf &expected_state, const unsigned int landmark_index, const unsigned int state_size) const
Get the state to observation matrix of the observation model (H in LaTeX documentation)
Eigen::VectorXf observation_model_n_landmarks(const Eigen::VectorXf &current_state, const std::vector< int > &matched_ids) const
Eigen::MatrixXf get_gz(const Eigen::VectorXf &expected_state, const ObservationData &observation_data) const
static Eigen::MatrixXf create_observation_noise_covariance_matrix(float noise_value)
Create a Q matrix from a given noise value.
ObservationModel(const Eigen::MatrixXf &observation_noise_covariance_matrix)
Construct a new Observation Model object.
Eigen::MatrixXf get_jacobian_of_observation_model(const Eigen::VectorXf &current_state, const std::vector< int > &matched_ids) const
Struct containing observation data.
common_lib::structures::Position position