4 std::shared_ptr<DataAssociationModel> data_association,
5 std::shared_ptr<V2PMotionModel> motion_model,
6 std::shared_ptr<LandmarkFilter> landmark_filter,
7 std::shared_ptr<std::vector<double>> execution_times,
8 std::shared_ptr<LoopClosure> loop_closure)
9 :
SLAMSolver(params, data_association, motion_model, landmark_filter, execution_times,
11 slam_parameters_(params) {
24 Eigen::MatrixXd observation_noise_matrix =
25 Eigen::MatrixXd::Zero(num_landmarks * 2, num_landmarks * 2);
26 for (
int i = 0; i < num_landmarks; i++) {
30 return observation_noise_matrix;
36 std::unique_lock lock(this->
mutex_);
43 std::unique_lock lock(this->
mutex_);
48 [[maybe_unused]] rclcpp::Time cones_time) {
49 int num_observations =
static_cast<int>(cones.size());
50 std::vector<int> matched_landmarks_indices;
51 Eigen::VectorXd matched_observations(0);
52 Eigen::VectorXd observations(2 * num_observations);
53 Eigen::VectorXd observation_confidences(num_observations);
55 Eigen::VectorXd state;
56 Eigen::MatrixXd covariance;
58 std::unique_lock lock(this->
mutex_);
64 Eigen::VectorXd global_observations =
67 state.segment(3, state.size() - 3), global_observations,
68 covariance.block(3, 3, state.size() - 3, state.size() - 3), observation_confidences);
70 Eigen::VectorXd filtered_landmarks =
71 this->
_landmark_filter_->filter(global_observations, observation_confidences, associations);
74 for (
int i = 0; i < num_observations; i++) {
75 if (associations(i) >= 0) {
77 matched_landmarks_indices.push_back(associations(i) + 3);
78 matched_observations.conservativeResize(matched_observations.size() + 2);
79 matched_observations(matched_observations.size() - 2) = observations(2 * i);
80 matched_observations(matched_observations.size() - 1) = observations(2 * i + 1);
84 if (!matched_landmarks_indices.empty()) {
85 this->
correct(state, covariance, matched_landmarks_indices, matched_observations);
87 if (this->
_mission_ != common_lib::competition_logic::Mission::NONE &&
89 (this->_mission_ == common_lib::competition_logic::Mission::SKIDPAD ||
90 this->_mission_ == common_lib::competition_logic::Mission::ACCELERATION)) &&
91 this->lap_counter_ == 0) {
96 std::unique_lock lock(this->
mutex_);
98 this->
state_.segment(0, 3) +=
105 state.segment(0, 3), state.segment(3, state.size() - 3), associations, observations);
106 if (result.detected) {
112 const Eigen::MatrixXd& process_noise_matrix,
113 const rclcpp::Time last_update,
115 auto time_interval = velocities.
timestamp_.seconds() - last_update.seconds();
117 Eigen::Vector3d previous_pose = state.segment(0, 3);
121 Eigen::MatrixXd pose_jacobian =
122 this->
_motion_model_->get_jacobian_pose(previous_pose, temp_velocities, time_interval);
123 Eigen::MatrixXd updated_covariance_block =
124 pose_jacobian * covariance.block(0, 0, 3, 3) * pose_jacobian.transpose() +
125 process_noise_matrix;
127 Eigen::Vector3d next_pose =
128 this->
_motion_model_->get_next_pose(previous_pose, temp_velocities, time_interval);
134 state.segment(0, 3) = next_pose;
135 covariance.block(0, 0, 3, 3) = updated_covariance_block;
139 const std::vector<int>& matched_landmarks_indices,
140 const Eigen::VectorXd& matched_observations) {
141 Eigen::VectorXd predicted_observations =
143 Eigen::MatrixXd jacobian =
144 this->
observation_model_->observation_model_jacobian(state, matched_landmarks_indices);
145 Eigen::MatrixXd observation_noise_matrix =
147 Eigen::MatrixXd kalman_gain =
148 covariance * jacobian.transpose() *
149 (jacobian * covariance * jacobian.transpose() + observation_noise_matrix).inverse();
150 state += kalman_gain * (matched_observations - predicted_observations);
152 (Eigen::MatrixXd::Identity(state.size(), state.size()) - kalman_gain * jacobian) * covariance;
156 const Eigen::VectorXd& new_landmarks_coordinates) {
158 int num_new_entries =
static_cast<int>(new_landmarks_coordinates.size());
159 int covariance_size =
static_cast<int>(covariance.rows());
161 covariance.conservativeResizeLike(
162 Eigen::MatrixXd::Zero(covariance_size + num_new_entries, covariance_size + num_new_entries));
163 for (
int i = 0; i < num_new_entries / 2; i++) {
164 covariance(2 * i + covariance_size, 2 * i + covariance_size) =
166 covariance(2 * i + 1 + covariance_size, 2 * i + 1 + covariance_size) =
170 int original_state_size =
static_cast<int>(state.size());
171 state.conservativeResizeLike(Eigen::VectorXd::Zero(original_state_size + num_new_entries));
172 state.segment(original_state_size, num_new_entries) = new_landmarks_coordinates;
176 if (map.size() % 2 != 0 || pose.size() != 3) {
177 throw std::runtime_error(
"Invalid map or pose size");
179 std::unique_lock lock(this->
mutex_);
180 this->
state_ = Eigen::VectorXd::Zero(3 + map.size());
181 this->
state_.segment(0, 3) = pose;
182 this->
state_.segment(3, map.size()) = map;
183 this->
covariance_ = Eigen::MatrixXd::Identity(this->
state_.size(), this->state_.size()) *
185 this->
covariance_.block(0, 0, 3, 3) = Eigen::MatrixXd::Zero(3, 3);
192 std::vector<common_lib::structures::Cone> map;
193 Eigen::VectorXd state;
194 rclcpp::Time last_update;
196 std::unique_lock lock(this->
mutex_);
200 for (
int i = 3; i < state.size(); i += 2) {
208 std::unique_lock lock(this->
mutex_);
Eigen::MatrixXd get_observation_noise_matrix(int num_landmarks) const
Get the observation noise matrix object used in the correction step of the EKF with the right dimensi...
EKFSLAMSolver(const SLAMParameters ¶ms, 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)
void add_velocities(const common_lib::structures::Velocities &velocities) override
Executed to deal with new velocity data.
void load_initial_state(const Eigen::VectorXd &map, const Eigen::Vector3d &pose) override
Initialize the EKF SLAM solver with a previously saved map and pose.
Eigen::MatrixXd covariance_
void correct(Eigen::VectorXd &state, Eigen::MatrixXd &covariance, const std::vector< int > &observed_landmarks_indices, const Eigen::VectorXd &matched_observations)
correction step of the EKF that updates the state and covariance based on the observed landmarks
common_lib::structures::Pose get_pose_estimate() override
Get the pose estimate object.
bool correction_step_ongoing_
bool velocities_received_
Eigen::Vector3d pose_difference_
std::shared_ptr< SLAMObservationModel > observation_model_
SLAMParameters slam_parameters_
rclcpp::Time last_update_
void predict(Eigen::VectorXd &state, Eigen::MatrixXd &covariance, const Eigen::MatrixXd &process_noise_matrix, const rclcpp::Time last_update, const common_lib::structures::Velocities &velocities)
executed when velocity data is received.
void state_augmentation(Eigen::VectorXd &state, Eigen::MatrixXd &covariance, const Eigen::VectorXd &new_landmarks)
add new landmarks to the state vector and covariance matrix
std::vector< common_lib::structures::Cone > get_map_estimate() override
Get the map estimate object.
void add_observations(const std::vector< common_lib::structures::Cone > &positions, rclcpp::Time cones_timestamp) override
process obervations of landmarks
Eigen::MatrixXd process_noise_matrix_
Interface for SLAM solvers.
common_lib::competition_logic::Mission _mission_
std::shared_ptr< LoopClosure > _loop_closure_
std::shared_ptr< V2PMotionModel > _motion_model_
std::shared_ptr< DataAssociationModel > _data_association_
std::shared_ptr< LandmarkFilter > _landmark_filter_
void cone_vector_to_eigen(const std::vector< common_lib::structures::Cone > &cones, Eigen::VectorXd &positions, Eigen::VectorXd &confidences)
Convert vector of the struct common_lib::structures::Cone to Eigen vectors.
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.
Result of loop closure detection.
Parameters for the SLAM node.
float observation_y_noise_
bool using_preloaded_map_
double pose_x_initial_noise_
float angular_velocity_noise_
double pose_y_initial_noise_
float observation_x_noise_
double pose_theta_initial_noise_
double preloaded_map_noise_
Struct for pose representation.
double rotational_velocity