Formula Student Autonomous Systems
The code for the main driverless system
Loading...
Searching...
No Matches
se_node.cpp
Go to the documentation of this file.
2
3#include <yaml-cpp/yaml.h>
4
5#include <fstream>
6
16#include "geometry_msgs/msg/pose_with_covariance.hpp"
17#include "rclcpp/rclcpp.hpp"
18#include "visualization_msgs/msg/marker.hpp"
19#include "utils/utils.hpp"
20/*---------------------- Constructor --------------------*/
21
22double last_wss = 0.0;
23
24SENode::SENode() : Node("ekf_state_est") {
25 auto global_config_path =
26 common_lib::config_load::get_config_yaml_path("ekf_state_est", "global", "global_config");
27 auto global_config = YAML::LoadFile(global_config_path);
28
29 _use_simulated_perception_ = global_config["global"]["use_simulated_perception"].as<bool>();
30 _adapter_name_ = global_config["global"]["adapter"].as<std::string>();
31
33 "ekf_state_est", "ekf_state_est", _adapter_name_);
34
35 auto se_config = YAML::LoadFile(se_config_path)["ekf_state_est"];
36 RCLCPP_DEBUG(rclcpp::get_logger("ekf_state_est"), "SE config contents: %s",
37 YAML::Dump(se_config).c_str());
38
39 _use_odometry_ = se_config["use_odometry"].as<bool>();
40 std::string motion_model_name = se_config["motion_model"].as<std::string>();
41 std::string data_assocation_model_name = se_config["data_association_model"].as<std::string>();
42
43 float wss_noise = 0.0f;
44 float imu_noise = 0.0f; // Declare the 'imu_noise' variable
45 if (data_assocation_model_name == "max_likelihood") {
46 wss_noise = se_config["wss_noise"].as<float>();
47 imu_noise = se_config["imu_noise"].as<float>();
48 }
49 float data_association_limit_distance = se_config["data_association_limit_distance"].as<float>();
50 float observation_noise = se_config["observation_noise"].as<float>();
51
52 std::shared_ptr<MotionModel> motion_model_wss = motion_model_constructors.at(
53 "normal_velocity_model")(MotionModel::create_process_noise_covariance_matrix(wss_noise));
54 std::shared_ptr<MotionModel> motion_model_imu = motion_model_constructors.at(motion_model_name)(
56
57 std::shared_ptr<ObservationModel> observation_model = std::make_shared<ObservationModel>(
59 std::shared_ptr<DataAssociationModel> data_association_model =
60 data_association_model_constructors.at(data_assocation_model_name)(
61 data_association_limit_distance);
62 _ekf_ = std::make_shared<ExtendedKalmanFilter>(observation_model, data_association_model);
63 _ekf_->add_motion_model("wheel_speed_sensor", motion_model_wss);
64 _ekf_->add_motion_model("imu", motion_model_imu);
65 _perception_map_ = std::make_shared<std::vector<common_lib::structures::Cone>>();
66 _motion_update_ = std::make_shared<MotionUpdate>();
67 _track_map_ = std::make_shared<std::vector<common_lib::structures::Cone>>();
68 _vehicle_state_ = std::make_shared<common_lib::structures::VehicleState>();
69 _motion_update_->last_update = this->get_clock()->now();
70
72 this->_perception_subscription_ = this->create_subscription<custom_interfaces::msg::ConeArray>(
73 "/perception/cones", 1,
74 std::bind(&SENode::_perception_subscription_callback, this, std::placeholders::_1));
75 }
76 this->_vehicle_state_publisher_ = this->create_publisher<custom_interfaces::msg::VehicleState>(
77 "/state_estimation/vehicle_state", 10);
79 this->create_publisher<custom_interfaces::msg::VehicleState>(
80 "/state_estimation/vehicle_state/wss", 10);
82 this->create_publisher<custom_interfaces::msg::VehicleState>(
83 "/state_estimation/vehicle_state/imu", 10);
84 this->_map_publisher_ =
85 this->create_publisher<custom_interfaces::msg::ConeArray>("/state_estimation/map", 10);
87 this->create_publisher<visualization_msgs::msg::MarkerArray>(
88 "/state_estimation/visualization_map", 10);
89 this->_correction_execution_time_publisher_ = this->create_publisher<std_msgs::msg::Float64>(
90 "/state_estimation/execution_time/correction_step", 10);
91 this->_prediction_execution_time_publisher_ = this->create_publisher<std_msgs::msg::Float64>(
92 "/state_estimation/execution_time/prediction_step", 10);
93 _adapter_ = adapter_map.at(_adapter_name_)(std::shared_ptr<SENode>(this));
94
95 this->_position_publisher_ = this->create_publisher<visualization_msgs::msg::Marker>(
96 "/state_estimation/visualization/position", 10);
97 this->_car_model_publisher_ = this->create_publisher<visualization_msgs::msg::Marker>(
98 "/state_estimation/visualization/car_model", 10);
99}
100
101/*---------------------- Subscriptions --------------------*/
102
103void SENode::_perception_subscription_callback(const custom_interfaces::msg::ConeArray &msg) {
104 auto const &cone_array = msg.cone_array;
105 if (this->_perception_map_ == nullptr) {
106 RCLCPP_WARN(this->get_logger(), "SUB - Perception map is null");
107 return;
108 }
109
110 if (!this->_go_) {
111 return;
112 }
113
114 rclcpp::Time start_time = this->get_clock()->now();
115
116 this->_perception_map_->clear();
117
118 for (auto &cone : cone_array) {
119 this->_perception_map_->push_back(common_lib::structures::Cone(cone.position.x, cone.position.y,
120 cone.color, cone.confidence));
121 }
122
123 if (this->_ekf_ == nullptr) {
124 RCLCPP_WARN(this->get_logger(), "ATTR - EKF object is null");
125 return;
126 }
127 // RCLCPP_DEBUG(this->get_logger(), "CORRECTION STEP END\n---------------------------\n");
128 this->_ekf_->correction_step(*(this->_perception_map_));
129 this->_ekf_->update(this->_vehicle_state_, this->_track_map_);
130
131 rclcpp::Time end_time = this->get_clock()->now();
132
133 // Execution Time calculation
134 std_msgs::msg::Float64 correction_execution_time;
135 correction_execution_time.data = (end_time - start_time).seconds() * 1000.0;
136 this->_correction_execution_time_publisher_->publish(correction_execution_time);
137 // this->_publish_vehicle_state();
138 this->_publish_map();
139}
140
141void SENode::_imu_subscription_callback(const sensor_msgs::msg::Imu &imu_msg) {
142 if (this->_use_odometry_) {
143 return;
144 }
145
146 if (!this->_go_) {
147 return;
148 }
149
150 rclcpp::Time start_time = this->get_clock()->now();
151
152 double ax = imu_msg.linear_acceleration.x;
153 // double ay = imu_msg.linear_acceleration.y;
154
155 double v_rot = imu_msg.angular_velocity.z;
156
157 double angle = this->_ekf_->get_state()(2);
158
159 double ax_map = ax * cos(angle) /* - ay * sin(angle)*/;
160 double ay_map = ax * sin(angle) /* + ay * cos(angle) */;
161
162 MotionUpdate motion_prediction_data;
163 motion_prediction_data.acceleration_x = ax_map;
164 motion_prediction_data.acceleration_y = ay_map;
165 motion_prediction_data.rotational_velocity = v_rot;
166 this->_motion_update_->acceleration_x = motion_prediction_data.acceleration_x;
167 this->_motion_update_->acceleration_y = motion_prediction_data.acceleration_y;
168 this->_motion_update_->rotational_velocity = motion_prediction_data.rotational_velocity;
169 this->_motion_update_->last_update = imu_msg.header.stamp;
170 if (this->_ekf_ == nullptr) {
171 RCLCPP_ERROR(this->get_logger(), "ATTR - EKF object is null");
172 return;
173 }
174 MotionUpdate temp_update = *(this->_motion_update_);
175 this->_ekf_->prediction_step(temp_update, "imu");
176 this->_ekf_->update(this->_vehicle_state_, this->_track_map_);
177
178 // Execution Time calculation
179 rclcpp::Time end_time = this->get_clock()->now();
180 std_msgs::msg::Float64 prediction_execution_time;
181 prediction_execution_time.data = (end_time - start_time).seconds() * 1000.0;
182 this->_prediction_execution_time_publisher_->publish(prediction_execution_time);
183
185 this->_publish_map();
186}
187
188double rl_before = 0.0, rr_before = 0.0, fl_before = 0.0, fr_before = 0.0;
189double difference = 10;
190
191void SENode::_wheel_speeds_subscription_callback(double rl_speed, double rr_speed, double fl_speed,
192 double fr_speed, double steering_angle,
193 const rclcpp::Time &timestamp) {
194 if (!this->_go_) {
195 return;
196 }
197
198 bool change = false;
199
200 if (abs(rl_before - rl_speed) >= difference) change = true;
201 if (abs(rr_before - rr_speed) >= difference) change = true;
202 if (abs(fl_before - fl_speed) >= difference) change = true;
203 if (abs(fr_before - fr_speed) >= difference) change = true;
204
205 rl_before = rl_speed;
206 rr_before = rr_speed;
207 fl_before = fl_speed;
208 fr_before = fr_speed;
209 if (change) return;
210
211 RCLCPP_INFO(this->get_logger(), "Rear Left: %f\n Rear Right: %f", rl_speed, rr_speed);
212 rclcpp::Time start_time = this->get_clock()->now();
213
214 auto [linear_velocity, angular_velocity] =
215 wheels_velocities_to_cg(this->_car_parameters_, rl_speed, fl_speed, rr_speed, fr_speed, steering_angle);
216
217 RCLCPP_INFO(this->get_logger(), "Linear Velocity: %f\nAngular Velocity: %f", linear_velocity,
218 angular_velocity);
219 MotionUpdate motion_prediction_data;
220 motion_prediction_data.translational_velocity = linear_velocity;
221 motion_prediction_data.rotational_velocity = angular_velocity;
222 this->_motion_update_->translational_velocity = motion_prediction_data.translational_velocity;
223 this->_motion_update_->rotational_velocity = motion_prediction_data.rotational_velocity;
224 this->_motion_update_->steering_angle = steering_angle;
225 this->_motion_update_->last_update = timestamp;
226
227 last_wss = linear_velocity;
228
229 if (this->_ekf_ == nullptr) {
230 RCLCPP_ERROR(this->get_logger(), "ATTR - EKF object is null");
231 return;
232 }
233 MotionUpdate temp_update = *(this->_motion_update_);
234
235 RCLCPP_INFO(this->get_logger(), "Motion update Translational Velocity: %f",
236 this->_motion_update_->translational_velocity);
237
238 this->_ekf_->prediction_step(temp_update, "wheel_speed_sensor");
239 this->_ekf_->update(this->_vehicle_state_, this->_track_map_);
240
241 // Execution Time calculation
242 rclcpp::Time end_time = this->get_clock()->now();
243 std_msgs::msg::Float64 prediction_execution_time;
244 prediction_execution_time.data = (end_time - start_time).seconds() * 1000.0;
245 this->_prediction_execution_time_publisher_->publish(prediction_execution_time);
246
248 this->_publish_map();
249}
250/*---------------------- Publications --------------------*/
251
253 if (this->_vehicle_state_ == nullptr) {
254 RCLCPP_WARN(this->get_logger(), "PUB - Vehicle state object is null");
255 return;
256 }
257 // if (!this->_go_){
258 // return;
259 // }
260
261 auto message = custom_interfaces::msg::VehicleState();
262 message.position.x = this->_vehicle_state_->pose.position.x;
263 message.position.y = this->_vehicle_state_->pose.position.y;
264 message.theta = this->_vehicle_state_->pose.orientation;
265 double velocity_x = this->_vehicle_state_->velocity_x;
266 double velocity_y = this->_vehicle_state_->velocity_y;
267 message.linear_velocity = std::sqrt(velocity_x * velocity_x + velocity_y * velocity_y);
268 message.angular_velocity = this->_vehicle_state_->rotational_velocity;
269 message.header.stamp = this->get_clock()->now();
270
271 RCLCPP_DEBUG(this->get_logger(), "PUB - Pose: (%f, %f, %f); Velocities: (%f, %f)",
272 message.position.x, message.position.y, message.theta, message.linear_velocity,
273 message.angular_velocity);
274 this->_vehicle_state_publisher_->publish(message);
275}
276
278 if (this->_vehicle_state_ == nullptr) {
279 RCLCPP_WARN(this->get_logger(), "PUB - Vehicle state object is null");
280 return;
281 }
282 auto message = custom_interfaces::msg::VehicleState();
283 message.position.x = this->_vehicle_state_->pose.position.x;
284 message.position.y = this->_vehicle_state_->pose.position.y;
285 message.theta = this->_vehicle_state_->pose.orientation;
286 double velocity_x = this->_vehicle_state_->velocity_x;
287 double velocity_y = this->_vehicle_state_->velocity_y;
288 message.linear_velocity = std::sqrt(velocity_x * velocity_x + velocity_y * velocity_y);
289 message.angular_velocity = this->_vehicle_state_->rotational_velocity;
290 message.header.stamp = this->get_clock()->now();
291
292 RCLCPP_DEBUG(this->get_logger(), "PUB - Pose: (%f, %f, %f); Velocities: (%f, %f)",
293 message.position.x, message.position.y, message.theta, message.linear_velocity,
294 message.angular_velocity);
295 this->_vehicle_state_publisher_->publish(message);
296
297 auto marker = visualization_msgs::msg::Marker();
298 marker.header.frame_id = "map"; // Use an appropriate frame
299 marker.header.stamp = this->get_clock()->now();
300 marker.ns = "vehicle_state";
301 marker.id = 0;
302 marker.type = visualization_msgs::msg::Marker::SPHERE;
303 marker.action = visualization_msgs::msg::Marker::ADD;
304 marker.pose.position.x = this->_vehicle_state_->pose.position.x;
305 marker.pose.position.y = this->_vehicle_state_->pose.position.y;
306 marker.pose.position.z = 0.0;
307 marker.pose.orientation.w = 1.0;
308 marker.scale.x = 0.5;
309 marker.scale.y = 0.5;
310 marker.scale.z = 0.5;
311 marker.color.r = 0.0;
312 marker.color.g = 1.0;
313 marker.color.b = 0.0;
314 marker.color.a = 1.0;
315
316 RCLCPP_DEBUG(this->get_logger(), "PUB - Marker at position: (%f, %f)", marker.pose.position.x,
317 marker.pose.position.y);
318 this->_position_publisher_->publish(marker);
319
320 // Calculate front and rear axle positions
321 double lr = 0.791;
322 double lf = 1.6;
323 double theta = this->_vehicle_state_->pose.orientation;
324 double cos_theta = std::cos(theta);
325 double sin_theta = std::sin(theta);
326
327 geometry_msgs::msg::Point rear_axis;
328 rear_axis.x = message.position.x - lr * cos_theta;
329 rear_axis.y = message.position.y - lr * sin_theta;
330
331 geometry_msgs::msg::Point front_axis;
332 front_axis.x = message.position.x + lf * cos_theta;
333 front_axis.y = message.position.y + lf * sin_theta;
334
335 // Create a marker array to draw the line between front and rear axis
336 visualization_msgs::msg::Marker line_marker;
337 line_marker.header.frame_id = "map";
338 line_marker.header.stamp = this->get_clock()->now();
339 line_marker.ns = "vehicle_state";
340 line_marker.id = 1;
341 line_marker.type = visualization_msgs::msg::Marker::LINE_STRIP;
342 line_marker.action = visualization_msgs::msg::Marker::ADD;
343 line_marker.scale.x = 0.1; // Line width
344 line_marker.color.r = 1.0;
345 line_marker.color.g = 1.0;
346 line_marker.color.b = 0.0;
347 line_marker.color.a = 1.0;
348
349 // Add points to the line marker
350 line_marker.points.push_back(rear_axis);
351 line_marker.points.push_back(front_axis);
352
353 // Publish the line marker
354 this->_car_model_publisher_->publish(line_marker);
355}
356
358 if (this->_vehicle_state_ == nullptr) {
359 RCLCPP_WARN(this->get_logger(), "PUB - Vehicle state object is null");
360 return;
361 }
362 auto message = custom_interfaces::msg::VehicleState();
363 message.position.x = this->_vehicle_state_->pose.position.x;
364 message.position.y = this->_vehicle_state_->pose.position.y;
365 message.theta = this->_vehicle_state_->pose.orientation;
366 double velocity_x = this->_vehicle_state_->velocity_x;
367 double velocity_y = this->_vehicle_state_->velocity_y;
368 message.linear_velocity = std::sqrt(velocity_x * velocity_x + velocity_y * velocity_y);
369 message.angular_velocity = this->_vehicle_state_->rotational_velocity;
370 message.header.stamp = this->get_clock()->now();
371
372 RCLCPP_DEBUG(this->get_logger(), "PUB - Pose: (%f, %f, %f); Velocities: (%f, %f)",
373 message.position.x, message.position.y, message.theta, message.linear_velocity,
374 message.angular_velocity);
375 this->_vehicle_state_publisher_->publish(message);
376}
377
379 auto cone_array_msg = custom_interfaces::msg::ConeArray();
380 auto marker_array_msg = visualization_msgs::msg::MarkerArray();
381 RCLCPP_DEBUG(this->get_logger(), "PUB - cone map:");
382 RCLCPP_DEBUG(this->get_logger(), "--------------------------------------");
383 for (common_lib::structures::Cone const &cone : *this->_track_map_) {
384 auto cone_message = custom_interfaces::msg::Cone();
385 cone_message.position.x = cone.position.x;
386 cone_message.position.y = cone.position.y;
387 cone_message.color = common_lib::competition_logic::get_color_string(cone.color);
388 cone_array_msg.cone_array.push_back(cone_message);
389 RCLCPP_DEBUG(this->get_logger(), "(%f\t%f)\t%s", cone_message.position.x,
390 cone_message.position.y, cone_message.color.c_str());
391 }
392 RCLCPP_DEBUG(this->get_logger(), "--------------------------------------");
393 cone_array_msg.header.stamp = this->get_clock()->now();
395 *this->_track_map_, "map_cones", _adapter_name_ == "eufs" ? "base_footprint" : "map");
396 this->_map_publisher_->publish(cone_array_msg);
397 this->_visualization_map_publisher_->publish(marker_array_msg);
398}
399
400/*---------------------- Others --------------------*/
401
402// Not utilized
404 if (this->_ekf_ == nullptr) {
405 RCLCPP_WARN(this->get_logger(), "PUB - EKF object is null");
406 return;
407 }
408 MotionUpdate temp_update = *(this->_motion_update_);
409 this->_ekf_->prediction_step(temp_update, "wheel_speed_sensor");
410 this->_ekf_->correction_step(*(this->_perception_map_));
411 this->_ekf_->update(this->_vehicle_state_, this->_track_map_);
412 RCLCPP_DEBUG(this->get_logger(), "EKF - EFK Step");
413}
414
415void SENode::_update_and_publish() { // Currently unused, as correction step
416 // and prediction step are carried out
417 // separately
418 this->_ekf_step();
420 this->_publish_map();
421}
static Eigen::MatrixXf create_process_noise_covariance_matrix(float process_noise)
static Eigen::MatrixXf create_observation_noise_covariance_matrix(float noise_value)
Create a Q matrix from a given noise value.
bool _use_simulated_perception_
Definition se_node.hpp:53
rclcpp::Subscription< custom_interfaces::msg::ConeArray >::SharedPtr _perception_subscription_
Definition se_node.hpp:34
void _publish_vehicle_state_wss()
publishes the localization ('vehicle_localization') to the topic vehicle_location
Definition se_node.cpp:277
rclcpp::Publisher< visualization_msgs::msg::Marker >::SharedPtr _car_model_publisher_
Definition se_node.hpp:50
std::shared_ptr< common_lib::car_parameters::CarParameters > _car_parameters_
Mutex used to lock EKF access.
Definition se_node.hpp:57
std::shared_ptr< ExtendedKalmanFilter > _ekf_
SLAM EKF object.
Definition se_node.hpp:43
std::shared_ptr< std::vector< common_lib::structures::Cone > > _perception_map_
Definition se_node.hpp:44
rclcpp::Publisher< visualization_msgs::msg::MarkerArray >::SharedPtr _visualization_map_publisher_
Definition se_node.hpp:39
std::shared_ptr< std::vector< common_lib::structures::Cone > > _track_map_
Definition se_node.hpp:46
void _ekf_step()
executes the prediction step of the EKF
Definition se_node.cpp:403
std::string _adapter_name_
Definition se_node.hpp:54
rclcpp::Publisher< custom_interfaces::msg::VehicleState >::SharedPtr _vehicle_state_publisher_wss_
Definition se_node.hpp:36
void _wheel_speeds_subscription_callback(double rl_speed, double rr_speed, double fl_speed, double fr_speed, double steering_angle, const rclcpp::Time &timestamp)
Function to be called everytime information is received from the wheel encoders.
Definition se_node.cpp:191
SENode()
Constructor of the main node, most things are received by launch parameter.
Definition se_node.cpp:24
rclcpp::Publisher< std_msgs::msg::Float64 >::SharedPtr _prediction_execution_time_publisher_
Definition se_node.hpp:41
rclcpp::Publisher< custom_interfaces::msg::ConeArray >::SharedPtr _map_publisher_
Definition se_node.hpp:38
void _imu_subscription_callback(const sensor_msgs::msg::Imu &imu_msg)
Function to be called everytime information is received from the IMU.
Definition se_node.cpp:141
void _publish_map()
publishes the map ('track_map') to the topic track_map
Definition se_node.cpp:378
void _publish_vehicle_state_imu()
publishes the localization ('vehicle_localization') to the topic vehicle_location
Definition se_node.cpp:357
std::shared_ptr< MotionUpdate > _motion_update_
Definition se_node.hpp:45
void _update_and_publish()
Executes:
Definition se_node.cpp:415
void _publish_vehicle_state()
publishes the localization ('vehicle_localization') to the topic vehicle_location
Definition se_node.cpp:252
std::shared_ptr< Adapter > _adapter_
Definition se_node.hpp:55
rclcpp::Publisher< custom_interfaces::msg::VehicleState >::SharedPtr _vehicle_state_publisher_
Definition se_node.hpp:35
rclcpp::Publisher< visualization_msgs::msg::Marker >::SharedPtr _position_publisher_
Definition se_node.hpp:49
std::shared_ptr< common_lib::structures::VehicleState > _vehicle_state_
Definition se_node.hpp:47
bool _go_
Definition se_node.hpp:51
rclcpp::Publisher< std_msgs::msg::Float64 >::SharedPtr _correction_execution_time_publisher_
Definition se_node.hpp:40
void _perception_subscription_callback(const custom_interfaces::msg::ConeArray &msg)
Callback that updates everytime information is received from the perception module.
Definition se_node.cpp:103
rclcpp::Publisher< custom_interfaces::msg::VehicleState >::SharedPtr _vehicle_state_publisher_imu_
Definition se_node.hpp:37
bool _use_odometry_
flag to start the mission
Definition se_node.hpp:52
const std::map< std::string, std::function< std::shared_ptr< ControlNode >(const ControlParameters &)>, std::less<> > adapter_map
Definition map.hpp:18
const std::map< std::string, std::function< std::shared_ptr< DataAssociationModel >(float max_landmark_distance)>, std::less<> > data_association_model_constructors
std::pair< double, double > wheels_velocities_to_cg(std::shared_ptr< common_lib::car_parameters::CarParameters > car_parameters, double rl_rpm, double fl_rpm, double rr_rpm, double fr_rpm, double steering_angle)
Calculates the translational and rotational velocities of the vehicle from wheel rotations and steeri...
Definition utils.cpp:3
const std::map< std::string, std::function< std::shared_ptr< MotionModel >(const Eigen::MatrixXf &)>, std::less<> > motion_model_constructors
Map object to map strings from launch file parameter to constructor.
visualization_msgs::msg::MarkerArray marker_array_from_structure_array(const std::vector< T > &structure_array, const std::string &name_space, const std::string &frame_id, const std::string &color="red", const std::string &shape="cylinder", float scale=0.5, int action=visualization_msgs::msg::Marker::MODIFY)
Converts a vector of cones to a marker array.
Definition marker.hpp:79
std::string get_color_string(int color)
Definition color.cpp:16
std::string get_config_yaml_path(const std::string &package_name, const std::string &dir, const std::string &filename)
double rl_before
Definition se_node.cpp:188
double last_wss
Definition se_node.cpp:22
double fr_before
Definition se_node.cpp:188
double difference
Definition se_node.cpp:189
double rr_before
Definition se_node.cpp:188
double fl_before
Definition se_node.cpp:188
Struct for data retrieved by the IMU.
double rotational_velocity
Degrees per sec.
double translational_velocity
Meters per sec.
double acceleration_x
Meters per sec.
double acceleration_y
Meters per sec.