From bc745d6e3637213100bccb36b5b7df733b02874e Mon Sep 17 00:00:00 2001 From: Berkay Karaman Date: Thu, 1 Feb 2024 11:28:14 +0300 Subject: [PATCH] feat(pointcloud_preprocessor): add pipeline latency time debug information for pointcloud pipeline (#6056) --- sensing/pointcloud_preprocessor/README.md | 40 +++++++++++++++++- .../pointcloud_preprocess_pipeline.drawio.png | Bin 0 -> 60904 bytes .../concatenate_and_time_sync_nodelet.cpp | 14 ++++++ .../crop_box_filter_nodelet.cpp | 10 ++++- .../distortion_corrector.cpp | 10 +++++ .../ring_outlier_filter_nodelet.cpp | 8 ++++ 6 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 sensing/pointcloud_preprocessor/docs/image/pointcloud_preprocess_pipeline.drawio.png diff --git a/sensing/pointcloud_preprocessor/README.md b/sensing/pointcloud_preprocessor/README.md index 91ef34f4cae72..5c6402efdf23d 100644 --- a/sensing/pointcloud_preprocessor/README.md +++ b/sensing/pointcloud_preprocessor/README.md @@ -56,7 +56,45 @@ Detail description of each filter's algorithm is in the following links. ## Assumptions / Known limits -`pointcloud_preprocessor::Filter` is implemented based on pcl_perception [1] because of [this issue](https://github.com/ros-perception/perception_pcl/issues/9). +`pointcloud_preprocessor::Filter` is implemented based on pcl_perception [1] because +of [this issue](https://github.com/ros-perception/perception_pcl/issues/9). + +## Measuring the performance + +In Autoware, point cloud data from each LiDAR sensor undergoes preprocessing in the sensing pipeline before being input +into the perception pipeline. The preprocessing stages are illustrated in the diagram below: + +![pointcloud_preprocess_pipeline.drawio.png](docs%2Fimage%2Fpointcloud_preprocess_pipeline.drawio.png) + +Each stage in the pipeline incurs a processing delay. Mostly, we've used `ros2 topic delay /topic_name` to measure +the time between the message header and the current time. This approach works well for small-sized messages. However, +when dealing with large point cloud messages, this method introduces an additional delay. This is primarily because +accessing these large point cloud messages externally impacts the pipeline's performance. + +Our sensing/perception nodes are designed to run within composable node containers, leveraging intra-process +communication. External subscriptions to these messages (like using ros2 topic delay or rviz2) impose extra delays and +can even slow down the pipeline by subscribing externally. Therefore, these measurements will not be accurate. + +To mitigate this issue, we've adopted a method where each node in the pipeline reports its pipeline latency time. +This approach ensures the integrity of intra-process communication and provides a more accurate measure of delays in the +pipeline. + +### Benchmarking The Pipeline + +The nodes within the pipeline report the pipeline latency time, indicating the duration from the sensor driver's pointcloud +output to the node's output. This data is crucial for assessing the pipeline's health and efficiency. + +When running Autoware, you can monitor the pipeline latency times for each node in the pipeline by subscribing to the +following ROS 2 topics: + +- `/sensing/lidar/LidarX/crop_box_filter_self/debug/pipeline_latency_ms` +- `/sensing/lidar/LidarX/crop_box_filter_mirror/debug/pipeline_latency_ms` +- `/sensing/lidar/LidarX/distortion_corrector/debug/pipeline_latency_ms` +- `/sensing/lidar/LidarX/ring_outlier_filter/debug/pipeline_latency_ms` +- `/sensing/lidar/concatenate_data_synchronizer/debug/sensing/lidar/LidarX/pointcloud/pipeline_latency_ms` + +These topics provide the pipeline latency times, giving insights into the delays at various stages of the pipeline +from the sensor output of LidarX to each subsequent node. ## (Optional) Error detection and handling diff --git a/sensing/pointcloud_preprocessor/docs/image/pointcloud_preprocess_pipeline.drawio.png b/sensing/pointcloud_preprocessor/docs/image/pointcloud_preprocess_pipeline.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..e690d0179afa643889a3a994630022f3e0c60f52 GIT binary patch literal 60904 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 jO!ch%!7~|@h052YwEJ?U9&d{}WWYt( + std::chrono::nanoseconds( + (this->get_clock()->now() - e.second->header.stamp).nanoseconds())) + .count(); + debug_publisher_->publish( + "debug" + e.first + "/pipeline_latency_ms", pipeline_latency_ms); + } + } + } + // publish concatenated pointcloud if (concat_cloud_ptr) { auto output = std::make_unique(*concat_cloud_ptr); diff --git a/sensing/pointcloud_preprocessor/src/crop_box_filter/crop_box_filter_nodelet.cpp b/sensing/pointcloud_preprocessor/src/crop_box_filter/crop_box_filter_nodelet.cpp index 20d1f5c8b3d6d..cfbeffee9982c 100644 --- a/sensing/pointcloud_preprocessor/src/crop_box_filter/crop_box_filter_nodelet.cpp +++ b/sensing/pointcloud_preprocessor/src/crop_box_filter/crop_box_filter_nodelet.cpp @@ -65,7 +65,7 @@ CropBoxFilterComponent::CropBoxFilterComponent(const rclcpp::NodeOptions & optio using tier4_autoware_utils::DebugPublisher; using tier4_autoware_utils::StopWatch; stop_watch_ptr_ = std::make_unique>(); - debug_publisher_ = std::make_unique(this, "crop_box_filter"); + debug_publisher_ = std::make_unique(this, this->get_name()); stop_watch_ptr_->tic("cyclic_time"); stop_watch_ptr_->tic("processing_time"); } @@ -195,6 +195,14 @@ void CropBoxFilterComponent::faster_filter( "debug/cyclic_time_ms", cyclic_time_ms); debug_publisher_->publish( "debug/processing_time_ms", processing_time_ms); + + auto pipeline_latency_ms = + std::chrono::duration( + std::chrono::nanoseconds((this->get_clock()->now() - input->header.stamp).nanoseconds())) + .count(); + + debug_publisher_->publish( + "debug/pipeline_latency_ms", pipeline_latency_ms); } } diff --git a/sensing/pointcloud_preprocessor/src/distortion_corrector/distortion_corrector.cpp b/sensing/pointcloud_preprocessor/src/distortion_corrector/distortion_corrector.cpp index dd38b85a2b56d..d1d91ed7ec439 100644 --- a/sensing/pointcloud_preprocessor/src/distortion_corrector/distortion_corrector.cpp +++ b/sensing/pointcloud_preprocessor/src/distortion_corrector/distortion_corrector.cpp @@ -128,6 +128,16 @@ void DistortionCorrectorComponent::onPointCloud(PointCloud2::UniquePtr points_ms undistortPointCloud(tf2_base_link_to_sensor, *points_msg); + if (debug_publisher_) { + auto pipeline_latency_ms = + std::chrono::duration( + std::chrono::nanoseconds( + (this->get_clock()->now() - points_msg->header.stamp).nanoseconds())) + .count(); + debug_publisher_->publish( + "debug/pipeline_latency_ms", pipeline_latency_ms); + } + undistorted_points_pub_->publish(std::move(points_msg)); // add processing time for debug diff --git a/sensing/pointcloud_preprocessor/src/outlier_filter/ring_outlier_filter_nodelet.cpp b/sensing/pointcloud_preprocessor/src/outlier_filter/ring_outlier_filter_nodelet.cpp index d2570b9c4d786..d968b06a0dc61 100644 --- a/sensing/pointcloud_preprocessor/src/outlier_filter/ring_outlier_filter_nodelet.cpp +++ b/sensing/pointcloud_preprocessor/src/outlier_filter/ring_outlier_filter_nodelet.cpp @@ -204,6 +204,14 @@ void RingOutlierFilterComponent::faster_filter( "debug/cyclic_time_ms", cyclic_time_ms); debug_publisher_->publish( "debug/processing_time_ms", processing_time_ms); + + auto pipeline_latency_ms = + std::chrono::duration( + std::chrono::nanoseconds((this->get_clock()->now() - input->header.stamp).nanoseconds())) + .count(); + + debug_publisher_->publish( + "debug/pipeline_latency_ms", pipeline_latency_ms); } }