3#include <tf2/LinearMath/Quaternion.h>
6#include <geometry_msgs/msg/transform_stamped.hpp>
23 RCLCPP_INFO_STREAM(this->get_logger(),
"SLAM Node parameters:" << params);
26 std::shared_ptr<DataAssociationModel> data_association =
31 std::shared_ptr<LandmarkFilter> landmark_filter =
38 std::shared_ptr<LoopClosure> loop_closure = std::make_shared<LapCounter>(15, 20, 10, 2);
47 _track_map_ = std::vector<common_lib::structures::Cone>();
54 this->create_callback_group(rclcpp::CallbackGroupType::Reentrant);
55 rclcpp::SubscriptionOptions parallel_opts;
58 this->create_subscription<custom_interfaces::msg::PerceptionOutput>(
59 "/perception/cones", 1,
64 rclcpp::CallbackGroupType::MutuallyExclusive);
66 this->create_subscription<custom_interfaces::msg::PerceptionOutput>(
67 "/perception/cones", 1,
72 rclcpp::SubscriptionOptions subscription_options;
75 "/state_estimation/velocities", 50,
77 subscription_options);
82 this->create_publisher<custom_interfaces::msg::ConeArray>(
"/state_estimation/map", 10);
84 this->create_publisher<custom_interfaces::msg::Pose>(
"/state_estimation/vehicle_pose", 10);
86 this->create_publisher<visualization_msgs::msg::MarkerArray>(
87 "/state_estimation/visualization_map", 10);
89 this->create_publisher<visualization_msgs::msg::MarkerArray>(
90 "/state_estimation/visualization_associations", 10);
92 this->create_publisher<visualization_msgs::msg::Marker>(
93 "/state_estimation/visualization/position", 10);
95 this->create_publisher<visualization_msgs::msg::MarkerArray>(
96 "/state_estimation/visualization/trajectory", 10);
98 "/state_estimation/slam_execution_time", 10);
100 "/state_estimation/slam_covariance", 10);
102 this->create_publisher<std_msgs::msg::Float64>(
"/state_estimation/lap_counter", 10);
103 this->
_tf_broadcaster_ = std::make_shared<tf2_ros::TransformBroadcaster>(
this);
105 RCLCPP_INFO(this->get_logger(),
"SLAM Node has been initialized using %s solver.",
110 if (
auto solver_ptr = std::dynamic_pointer_cast<NodeControllerTrait>(this->
_slam_solver_)) {
111 solver_ptr->init(this->weak_from_this());
118 const custom_interfaces::msg::PerceptionOutput &msg) {
119 RCLCPP_INFO(this->get_logger(),
"SLAMNode::_perception_subscription_callback called");
120 auto const &cone_array = msg.cones.cone_array;
121 double perception_exec_time = msg.exec_time;
123 RCLCPP_DEBUG(this->get_logger(),
"SUB - Perception: %ld cones. Mission: %d", cone_array.size(),
124 static_cast<int>(this->_mission_));
127 std::unique_lock lock(this->
mutex_);
128 if (!this->
_go_ || this->
_mission_ == common_lib::competition_logic::Mission::NONE) {
133 rclcpp::Time start_time = this->get_clock()->now();
134 rclcpp::Time
const cones_time =
136 ? rclcpp::Time(msg.header.stamp)
137 : start_time - rclcpp::Duration::from_seconds(perception_exec_time);
144 Eigen::Vector3d velocities;
146 std::unique_lock lock(this->
mutex_);
148 this->_vehicle_state_velocities_.velocity_y,
149 this->_vehicle_state_velocities_.rotational_velocity);
152 double theta = -velocities(2) * perception_exec_time;
153 double cos_theta = std::cos(theta);
154 double sin_theta = std::sin(theta);
155 for (
auto &cone : cone_array) {
156 double x_linear_compensated = cone.position.x - velocities(0) * perception_exec_time;
157 double y_linear_compensated = cone.position.y - velocities(1) * perception_exec_time;
158 double x_compensated = cos_theta * x_linear_compensated - sin_theta * y_linear_compensated;
159 double y_compensated = sin_theta * x_linear_compensated + cos_theta * y_linear_compensated;
161 x_compensated, y_compensated, cone.color, cone.confidence, msg.header.stamp));
164 for (
auto &cone : cone_array) {
166 cone.position.x, cone.position.y, cone.color, cone.confidence, msg.header.stamp));
169 RCLCPP_INFO(this->get_logger(),
"ATTR - Perception map size: %ld",
_perception_map_.size());
172 RCLCPP_WARN(this->get_logger(),
"ATTR - Slam Solver object is null");
177 RCLCPP_INFO(this->get_logger(),
"ATTR - Observations added to SLAM solver");
179 std::vector<common_lib::structures::Cone> track_map;
184 std::unique_lock lock(this->
mutex_);
198 RCLCPP_INFO(this->get_logger(),
"ATTR - Mission finished check done");
209 rclcpp::Time end_time = this->get_clock()->now();
210 std_msgs::msg::Float64MultiArray execution_time_msg;
212 std::unique_lock lock(this->
mutex_);
217 RCLCPP_INFO(this->get_logger(),
"ATTR - Perception callback finished");
221 if (this->
_mission_ == common_lib::competition_logic::Mission::NONE) {
225 rclcpp::Time start_time = this->get_clock()->now();
227 rclcpp::Time
const velocities_time =
229 if (
auto solver_ptr = std::dynamic_pointer_cast<VelocitiesIntegratorTrait>(this->
_slam_solver_)) {
231 msg.velocity_x, msg.velocity_y, msg.angular_velocity, msg.covariance[0], msg.covariance[4],
232 msg.covariance[8], velocities_time);
236 std::unique_lock lock(this->
mutex_);
239 solver_ptr->add_velocities(velocities);
244 std::unique_lock lock(this->
mutex_);
251 rclcpp::Time end_time = this->get_clock()->now();
252 std_msgs::msg::Float64MultiArray execution_time_msg;
254 std::unique_lock lock(this->
mutex_);
262 if (this->
_mission_ == common_lib::competition_logic::Mission::NONE) {
265 RCLCPP_DEBUG(this->get_logger(),
"SUB - IMU data received");
266 if (
auto solver_ptr = std::dynamic_pointer_cast<ImuIntegratorTrait>(this->
_slam_solver_)) {
268 msg.angular_velocity.z, msg.linear_acceleration.x, msg.linear_acceleration.y,
269 msg.header.stamp, msg.angular_velocity_covariance[8], msg.linear_acceleration_covariance[0],
270 msg.linear_acceleration_covariance[4]);
272 imu_data.timestamp_ = this->get_clock()->now();
274 solver_ptr->add_imu_data(imu_data);
281 auto message = custom_interfaces::msg::Pose();
282 auto tf_message = geometry_msgs::msg::TransformStamped();
284 std::unique_lock lock(this->
mutex_);
290 message.header.stamp = this->get_clock()->now();
292 RCLCPP_DEBUG(this->get_logger(),
"PUB - Pose: (%f, %f, %f)", message.x, message.y, message.theta);
296 tf_message.header.stamp = message.header.stamp;
297 tf_message.header.frame_id =
"map";
301 q.setRPY(0.0, 0.0, message.theta);
302 tf_message.transform.translation.x = message.x;
303 tf_message.transform.translation.y = message.y;
304 tf_message.transform.translation.z = 0.0;
305 tf_message.transform.rotation.x = q.x();
306 tf_message.transform.rotation.y = q.y();
307 tf_message.transform.rotation.z = q.z();
308 tf_message.transform.rotation.w = q.w();
313 if (
auto solver_ptr = std::dynamic_pointer_cast<TrajectoryCalculator>(this->
_slam_solver_)) {
314 std::vector<common_lib::structures::Pose> trajectory = solver_ptr->get_trajectory_estimate();
315 auto marker_array_msg = visualization_msgs::msg::MarkerArray();
317 trajectory,
"vehicle_trajectory",
"map",
"blue",
"sphere");
328 auto cone_array_msg = custom_interfaces::msg::ConeArray();
329 auto marker_array_msg = visualization_msgs::msg::MarkerArray();
330 auto marker_array_msg_perception = visualization_msgs::msg::MarkerArray();
331 std::vector<common_lib::structures::Cone> track_map;
333 std::unique_lock lock(this->
mutex_);
337 auto cone_message = custom_interfaces::msg::Cone();
338 cone_message.position.x = cone.position.x;
339 cone_message.position.y = cone.position.y;
342 cone_array_msg.cone_array.push_back(cone_message);
347 cone_array_msg.header.stamp = this->get_clock()->now();
356 std_msgs::msg::Float64MultiArray covariance_msg;
357 covariance_msg.layout = std_msgs::msg::MultiArrayLayout();
358 covariance_msg.layout.dim.push_back(std_msgs::msg::MultiArrayDimension());
359 covariance_msg.layout.dim[0].size = this->
_slam_solver_->get_covariance().rows();
360 covariance_msg.layout.dim[0].stride =
362 covariance_msg.layout.dim[0].label =
"rows";
363 covariance_msg.layout.dim.push_back(std_msgs::msg::MultiArrayDimension());
364 covariance_msg.layout.dim[1].size = this->
_slam_solver_->get_covariance().cols();
365 covariance_msg.layout.dim[1].stride = this->
_slam_solver_->get_covariance().cols();
366 covariance_msg.layout.dim[1].label =
"cols";
367 Eigen::MatrixXd covariance_matrix = this->
_slam_solver_->get_covariance();
368 for (
unsigned int i = 0; i < covariance_matrix.rows(); i++) {
369 for (
unsigned int j = 0; j < covariance_matrix.cols(); j++) {
370 covariance_msg.data.push_back(covariance_matrix(i, j));
377 std_msgs::msg::Float64 lap_counter_msg;
378 lap_counter_msg.data = this->
_slam_solver_->get_lap_counter();
383 auto marker_array_msg = visualization_msgs::msg::MarkerArray();
384 RCLCPP_DEBUG(this->get_logger(),
"PUB - Associations %ld", this->
_associations_.size());
386 visualization_msgs::msg::Marker clear_marker;
387 clear_marker.header.frame_id =
"map";
388 clear_marker.header.stamp = this->now();
389 clear_marker.ns =
"associations";
391 clear_marker.action = visualization_msgs::msg::Marker::DELETEALL;
392 marker_array_msg.markers.push_back(clear_marker);
401 visualization_msgs::msg::Marker marker;
402 marker.header.frame_id =
"map";
403 marker.header.stamp = this->now();
404 marker.ns =
"associations";
406 marker.type = visualization_msgs::msg::Marker::ARROW;
407 marker.action = visualization_msgs::msg::Marker::ADD;
409 geometry_msgs::msg::Point start, end;
410 start.x = observation_x;
411 start.y = observation_y;
417 marker.points.push_back(start);
418 marker.points.push_back(end);
420 marker.scale.x = 0.15;
421 marker.scale.y = 0.04;
422 marker.scale.z = 0.01;
424 marker.color.r = 1.0;
425 marker.color.g = 1.0;
426 marker.color.b = 1.0;
427 marker.color.a = 1.0;
429 marker_array_msg.markers.push_back(marker);
438 std::unique_lock lock(this->
mutex_);
440 this->_vehicle_state_velocities_.velocity_y > 0.1 ||
441 this->_vehicle_state_velocities_.rotational_velocity > 0.05) {
445 if (this->
_mission_ == common_lib::competition_logic::Mission::ACCELERATION &&
449 if (this->
_mission_ == common_lib::competition_logic::Mission::SKIDPAD &&
454 if (this->
_mission_ == common_lib::competition_logic::Mission::AUTOCROSS &&
458 if (this->
_mission_ == common_lib::competition_logic::Mission::TRACKDRIVE &&
rclcpp::Publisher< visualization_msgs::msg::MarkerArray >::SharedPtr _visualization_map_publisher_
Eigen::VectorXd _map_coordinates_
Coordinates of the cones in the map.
common_lib::structures::Velocities _vehicle_state_velocities_
std::vector< common_lib::structures::Cone > _perception_map_
rclcpp::Subscription< custom_interfaces::msg::PerceptionOutput >::SharedPtr _perception_subscription_
std::string _vehicle_frame_id_
Frame id of the vehicle for the transform.
rclcpp::CallbackGroup::SharedPtr _callback_group_
Callback group for subscriptions, used to control if they are concurrent or not.
std::shared_ptr< std::vector< double > > _execution_times_
void _publish_lap_counter()
publishes the lap counter
rclcpp::Subscription< custom_interfaces::msg::Velocities >::SharedPtr _velocities_subscription_
virtual void finish()=0
Finish the mission.
rclcpp::Publisher< visualization_msgs::msg::MarkerArray >::SharedPtr _trajectory_visualization_publisher_
Publishes full vehicle trajectory.
std::shared_ptr< tf2_ros::TransformBroadcaster > _tf_broadcaster_
rclcpp::Publisher< visualization_msgs::msg::Marker >::SharedPtr _position_visualization_publisher_
Publishes the vehicle position.
void _publish_vehicle_pose()
publishes the localization ('vehicle_pose') to the topic vehicle_pose
common_lib::competition_logic::Mission _mission_
void _velocities_subscription_callback(const custom_interfaces::msg::Velocities &msg)
Callback that updates everytime information is received from velocity estimation node.
rclcpp::Publisher< custom_interfaces::msg::Pose >::SharedPtr _vehicle_pose_publisher_
void _publish_covariance()
publishes the covariance of the state
Eigen::VectorXd _observations_global_
Global observations of the cones.
Eigen::VectorXi _associations_
SLAMNode(const SLAMParameters ¶ms)
Constructor that uses the parameters structure.
rclcpp::CallbackGroup::SharedPtr _parallel_callback_group_
void _publish_associations()
Publishes the visualization of the associations by data association.
rclcpp::Publisher< std_msgs::msg::Float64MultiArray >::SharedPtr _covariance_publisher_
Publishes the covariance of the pose.
void _publish_map()
publishes the map ('track_map') to the topic track_map
void _perception_subscription_callback(const custom_interfaces::msg::PerceptionOutput &msg)
Callback that updates everytime information is received from the perception module.
rclcpp::Publisher< std_msgs::msg::Float64MultiArray >::SharedPtr _execution_time_publisher_
rclcpp::Publisher< std_msgs::msg::Float64 >::SharedPtr _lap_counter_publisher_
common_lib::structures::Pose _vehicle_pose_
rclcpp::Publisher< custom_interfaces::msg::ConeArray >::SharedPtr _map_publisher_
bool _is_mission_finished()
Checks if the mission is finished.
void _imu_subscription_callback(const sensor_msgs::msg::Imu &msg)
Callback that updates everytime information is received from the IMU.
std::vector< common_lib::structures::Cone > _track_map_
std::shared_ptr< SLAMSolver > _slam_solver_
SLAM solver object.
rclcpp::Publisher< visualization_msgs::msg::MarkerArray >::SharedPtr _associations_visualization_publisher_
void init()
Initialize functions @description This method is used to initialize things that require the construct...
const std::map< std::string, std::function< std::shared_ptr< V2PMotionModel >()>, std::less<> > v2p_models_map
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.
visualization_msgs::msg::Marker marker_from_position(const common_lib::structures::Position &position, const std::string &name_space, const int id, const std::string &color="red", float scale=0.5, const std::string &frame_id="map", const std::string &shape="sphere", int action=visualization_msgs::msg::Marker::ADD)
Converts a position to a marker.
std::string get_color_string(int color)
const std::map< std::string, std::function< std::shared_ptr< DataAssociationModel >(const DataAssociationParameters &)>, std::less<> > data_association_models_map
Map of data association models, with the key being the name of the data association model and the val...
const std::map< std::string, std::function< std::shared_ptr< LandmarkFilter >(const LandmarkFilterParameters &, std::shared_ptr< DataAssociationModel >)>, std::less<> > landmark_filters_map
Map of landmark filters, with the key being the name of the landmark filter and the value being a lam...
const std::map< std::string, std::function< std::shared_ptr< SLAMSolver >(const SLAMParameters &, std::shared_ptr< DataAssociationModel >, std::shared_ptr< V2PMotionModel >, std::shared_ptr< LandmarkFilter >, std::shared_ptr< std::vector< double > >, std::shared_ptr< LoopClosure >)>, std::less<> > slam_solver_constructors_map
Parameters for the SLAM node.
double data_association_gate_
double minimum_frequency_of_detections_
int minimum_observation_count_
float data_association_limit_distance_
float observation_y_noise_
bool use_simulated_perception_
bool synchronized_timestamps
std::string motion_model_name_
std::string slam_optimization_mode_
std::string slam_solver_name_
bool use_simulated_velocities_
std::string landmark_filter_name_
float observation_x_noise_
double new_landmark_confidence_gate_
std::string data_association_model_name_
Struct for pose representation.