15 const std::string global_config_path =
17 RCLCPP_DEBUG(rclcpp::get_logger(
"perception"),
"Loading global config from: %s",
18 global_config_path.c_str());
19 const YAML::Node global_config = YAML::LoadFile(global_config_path);
21 params.
adapter_ = global_config[
"global"][
"adapter"].as<std::string>();
22 params.
vehicle_frame_id_ = global_config[
"global"][
"vehicle_frame_id"].as<std::string>();
28 const std::string perception_path =
30 RCLCPP_DEBUG(rclcpp::get_logger(
"perception"),
"Loading perception config from: %s",
31 perception_path.c_str());
32 const YAML::Node perception = YAML::LoadFile(perception_path);
34 const auto perception_config = perception[
"perception"];
35 RCLCPP_DEBUG(rclcpp::get_logger(
"perception"),
"Perception config contents: %s",
36 YAML::Dump(perception_config).c_str());
38 const auto default_mission_str = perception_config[
"default_mission"].as<std::string>();
45 perception_config[
"publish_ground_removed_cloud"].as<
bool>();
50 trim_params.
min_range = perception_config[
"min_range"].as<
double>();
51 trim_params.max_height = perception_config[
"max_height"].as<
double>();
52 trim_params.max_range = perception_config[
"max_range"].as<
double>();
53 trim_params.acc_max_range = perception_config[
"acc_max_range"].as<
double>();
54 trim_params.acc_max_y = perception_config[
"acc_max_y"].as<
double>();
55 trim_params.skid_max_range = perception_config[
"skid_max_range"].as<
double>();
56 trim_params.lidar_height = perception_config[
"lidar_height"].as<
double>();
57 trim_params.lidar_horizontal_resolution =
58 perception_config[
"lidar_horizontal_resolution"].as<
double>();
59 trim_params.lidar_vertical_resolution =
60 perception_config[
"lidar_vertical_resolution"].as<
double>();
61 trim_params.apply_rotation = perception_config[
"apply_rotation"].as<
bool>();
62 trim_params.rotation = perception_config[
"rotation"].as<
double>();
63 trim_params.apply_fov_trimming = perception_config[
"apply_fov_trimming"].as<
bool>();
64 trim_params.fov = perception_config[
"fov"].as<
double>();
65 trim_params.is_raining = perception_config[
"is_raining"].as<
bool>();
66 trim_params.minimum_intensity = perception_config[
"minimum_intensity"].as<
float>();
68 auto acceleration_trimming = std::make_shared<AccelerationTrimming>(trim_params);
69 auto skidpad_trimming = std::make_shared<SkidpadTrimming>(trim_params);
70 auto cut_trimming = std::make_shared<CutTrimming>(trim_params);
72 auto temp_fov_trim_map = std::unordered_map<int16_t, std::shared_ptr<FovTrimming>>{
73 {
static_cast<int16_t
>(Mission::MANUAL), cut_trimming},
74 {
static_cast<int16_t
>(Mission::ACCELERATION), acceleration_trimming},
75 {
static_cast<int16_t
>(Mission::SKIDPAD), skidpad_trimming},
76 {
static_cast<int16_t
>(Mission::TRACKDRIVE), cut_trimming},
77 {
static_cast<int16_t
>(Mission::AUTOCROSS), cut_trimming},
78 {
static_cast<int16_t
>(Mission::INSPECTION), cut_trimming},
79 {
static_cast<int16_t
>(Mission::EBS_TEST), acceleration_trimming},
80 {
static_cast<int16_t
>(Mission::MANUAL), cut_trimming},
81 {
static_cast<int16_t
>(Mission::NONE), cut_trimming}};
84 std::make_shared<std::unordered_map<int16_t, std::shared_ptr<FovTrimming>>>(
88 double ground_grid_range = perception_config[
"ground_grid_range"].as<
double>();
89 double ground_grid_angle = perception_config[
"ground_grid_angle"].as<
double>();
90 double ground_grid_radius = perception_config[
"ground_grid_radius"].as<
double>();
91 double ground_grid_start_augmentation =
92 perception_config[
"ground_grid_start_augmentation"].as<
double>();
93 double ground_grid_radius_augmentation =
94 perception_config[
"ground_grid_radius_augmentation"].as<
double>();
96 ground_grid_range, ground_grid_angle, ground_grid_radius, ground_grid_start_augmentation,
97 ground_grid_radius_augmentation, trim_params.fov);
100 std::string ground_removal_algorithm = perception_config[
"ground_removal"].as<std::string>();
101 double ransac_epsilon = perception_config[
"ransac_epsilon"].as<
double>();
102 int ransac_iterations = perception_config[
"ransac_iterations"].as<
int>();
103 double himmelsbach_grid_angle = perception_config[
"himmelsbach_grid_angle"].as<
double>();
104 double himmelsbach_max_slope = perception_config[
"himmelsbach_max_slope"].as<
double>();
105 double himmelsbach_alpha = perception_config[
"himmelsbach_initial_alpha"].as<
double>();
106 double himmelsbach_alpha_augmentation_m =
107 perception_config[
"himmelsbach_alpha_augmentation_m"].as<
double>();
108 double himmelsbach_start_augmentation =
109 perception_config[
"himmelsbach_start_augmentation"].as<
double>();
111 if (ground_removal_algorithm ==
"ransac") {
112 params.
ground_removal_ = std::make_shared<RANSAC>(ransac_epsilon, ransac_iterations);
113 }
else if (ground_removal_algorithm ==
"himmelsbach") {
115 himmelsbach_grid_angle, himmelsbach_max_slope, himmelsbach_alpha,
116 himmelsbach_alpha_augmentation_m, himmelsbach_start_augmentation, trim_params);
118 RCLCPP_ERROR(rclcpp::get_logger(
"perception"),
119 "Ground removal algorithm not recognized: %s, using RANSAC as default",
120 ground_removal_algorithm.c_str());
121 params.
ground_removal_ = std::make_shared<RANSAC>(ransac_epsilon, ransac_iterations);
125 double wall_removal_grid_angle = perception_config[
"wall_removal_grid_angle"].as<
double>();
126 double wall_removal_grid_radius = perception_config[
"wall_removal_grid_radius"].as<
double>();
127 double wall_removal_start_augmentation =
128 perception_config[
"wall_removal_start_augmentation"].as<
double>();
129 double wall_removal_radius_augmentation =
130 perception_config[
"wall_removal_radius_augmentation"].as<
double>();
131 int wall_removal_max_points_per_cluster =
132 perception_config[
"wall_removal_max_points_per_cluster"].as<
int>();
134 wall_removal_grid_angle, wall_removal_grid_radius, wall_removal_start_augmentation,
135 wall_removal_radius_augmentation, trim_params.fov, wall_removal_max_points_per_cluster);
138 std::string clustering_algorithm = perception_config[
"clustering"].as<std::string>();
139 int DBSCAN_clustering_n_neighbours = perception_config[
"DBSCAN_n_neighbours"].as<
int>();
140 double DBSCAN_clustering_epsilon = perception_config[
"DBSCAN_clustering_epsilon"].as<
double>();
141 double grid_clustering_grid_angle = perception_config[
"grid_clustering_grid_angle"].as<
double>();
142 double grid_clustering_grid_radius =
143 perception_config[
"grid_clustering_grid_radius"].as<
double>();
144 double grid_clustering_start_augmentation =
145 perception_config[
"grid_clustering_start_augmentation"].as<
double>();
146 double grid_clustering_radius_augmentation =
147 perception_config[
"grid_clustering_radius_augmentation"].as<
double>();
149 if (clustering_algorithm ==
"DBSCAN") {
151 std::make_shared<DBSCAN>(DBSCAN_clustering_n_neighbours, DBSCAN_clustering_epsilon);
152 }
else if (clustering_algorithm ==
"GridClustering") {
153 params.
clustering_ = std::make_shared<GridClustering>(
154 grid_clustering_grid_angle, grid_clustering_grid_radius, grid_clustering_start_augmentation,
155 grid_clustering_radius_augmentation, trim_params.fov);
157 RCLCPP_ERROR(rclcpp::get_logger(
"perception"),
158 "Clustering algorithm not recognized: %s, using DBSCAN as default",
159 clustering_algorithm.c_str());
161 std::make_shared<DBSCAN>(DBSCAN_clustering_n_neighbours, DBSCAN_clustering_epsilon);
165 auto eval_params = std::make_shared<EvaluatorParameters>();
166 eval_params->small_cone_width = perception_config[
"small_cone_width"].as<
double>();
167 eval_params->large_cone_width = perception_config[
"large_cone_width"].as<
double>();
168 eval_params->small_cone_height = perception_config[
"small_cone_height"].as<
double>();
169 eval_params->large_cone_height = perception_config[
"large_cone_height"].as<
double>();
170 eval_params->n_out_points_ratio = perception_config[
"n_out_points_ratio"].as<
double>();
171 eval_params->max_distance_from_ground_min =
172 perception_config[
"max_distance_from_ground_min"].as<
double>();
173 eval_params->max_distance_from_ground_max =
174 perception_config[
"max_distance_from_ground_max"].as<
double>();
175 eval_params->n_points_intial_max = perception_config[
"n_points_intial_max"].as<
double>();
176 eval_params->n_points_intial_min = perception_config[
"n_points_intial_min"].as<
double>();
177 eval_params->n_points_max_distance_reduction =
178 perception_config[
"n_points_max_distance_reduction"].as<
double>();
179 eval_params->n_points_min_distance_reduction =
180 perception_config[
"n_points_min_distance_reduction"].as<
double>();
187 : Node(
"perception"),
188 _vehicle_frame_id_(params.vehicle_frame_id_),
189 _mission_type_(params.default_mission_),
190 _publish_fov_trimmed_cloud_(params.publish_fov_trimmed_cloud),
191 _publish_ground_removed_cloud_(params.publish_ground_removed_cloud),
192 _publish_wall_removed_cloud_(params.publish_wall_removed_cloud),
193 _fov_trim_map_(params.fov_trim_map_),
194 _ground_grid_(params.ground_grid_),
195 _ground_removal_(params.ground_removal_),
196 _wall_removal_(params.wall_removal_),
197 _clustering_(params.clustering_),
198 _cone_differentiator_(params.cone_differentiator_),
199 _cone_evaluator_(params.cone_evaluator_) {
201 this->create_publisher<custom_interfaces::msg::PerceptionOutput>(
"/perception/cones", 10);
204 this->create_publisher<sensor_msgs::msg::PointCloud2>(
"/perception/fov_trimmed_cloud", 10);
207 this->create_publisher<sensor_msgs::msg::PointCloud2>(
"/perception/ground_removed_cloud", 10);
210 this->create_publisher<sensor_msgs::msg::PointCloud2>(
"/perception/wall_removed_cloud", 10);
213 this->create_publisher<std_msgs::msg::Float64MultiArray>(
"/perception/execution_time", 10);
217 this->create_subscription<custom_interfaces::msg::OperationalStatus>(
218 "/vehicle/operational_status", rclcpp::QoS(10),
219 [
this](
const custom_interfaces::msg::OperationalStatus::SharedPtr msg) {
224 std::unordered_map<std::string, std::tuple<std::string, rclcpp::QoS>> adapter_topic_map = {
225 {
"vehicle", {
"/lidar_points", rclcpp::QoS(10)}},
227 {
"/velodyne_points", rclcpp::QoS(1).reliability(RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT)}},
228 {
"fsds", {
"/lidar/Lidar1", rclcpp::QoS(10)}},
229 {
"vehicle_preprocessed", {
"/rslidar_points/pre_processed", rclcpp::QoS(10)}},
230 {
"fst", {
"/hesai/pandar", rclcpp::QoS(10)}}};
234 std::get<0>(adapter_topic_map.at(params.
adapter_)),
235 std::get<1>(adapter_topic_map.at(params.
adapter_)),
236 [
this](
const sensor_msgs::msg::PointCloud2::SharedPtr msg) {
237 this->point_cloud_callback(msg);
239 }
catch (
const std::out_of_range& e) {
240 RCLCPP_ERROR(this->get_logger(),
"Adapter not recognized: %s", params.
adapter_.c_str());
244 "/state_estimation/velocities", rclcpp::QoS(10),
247 "/perception/visualization/cones", 10);
252 emergency_client_ = this->create_client<std_srvs::srv::Trigger>(
"/as_srv/emergency");
254 RCLCPP_INFO(this->get_logger(),
"Perception Node created with adapter: %s",
261 rclcpp::Time pcl_time = this->now();
267 rclcpp::Time start_time = this->now();
268 rclcpp::Time time1, time2, time3, time4, time5, time6;
271 auto trimmed_cloud = std::make_shared<sensor_msgs::msg::PointCloud2>();
281 auto ground_removed_cloud = std::make_shared<sensor_msgs::msg::PointCloud2>();
291 auto wall_removed_cloud = std::make_shared<sensor_msgs::msg::PointCloud2>();
292 _wall_removal_->remove_walls(ground_removed_cloud, wall_removed_cloud);
305 std::vector<Cluster> clusters;
306 _clustering_->clustering(wall_removed_cloud, &clusters);
310 std::vector<Cluster> filtered_clusters;
312 for (
auto& cluster : clusters) {
314 filtered_clusters.push_back(cluster);
319 double perception_execution_time_seconds = (time6 - start_time).seconds();
327 std_msgs::msg::Float64MultiArray exec_time_msg;
331 publish_cones(&filtered_clusters, perception_execution_time_seconds, start_time);