Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(autoware_pointcloud_preprocessor): distortion corrector node update azimuth and distance #8380

Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
b7ea57d
feat: add option for updating distance and azimuth value
vividf Aug 6, 2024
1bd37c4
chore: clean code
vividf Aug 6, 2024
336f709
chore: remove space
vividf Aug 6, 2024
c8378ac
chore: add documentation
vividf Aug 6, 2024
3081d66
chore: fix docs
vividf Aug 6, 2024
f6394b2
Merge branch 'main' into feature/distortion_corrector_node_update_azi…
vividf Aug 6, 2024
94551b6
feat: conversion formula implementation for degree, still need to cha…
vividf Aug 9, 2024
9ac2689
chore: fix tests for AzimuthConversionExists function
vividf Aug 13, 2024
0990c02
feat: add fastatan to utils
vividf Aug 14, 2024
6796341
feat: remove seperate sin, cos and use sin_and_cos function
vividf Aug 14, 2024
afd0fda
chore: fix readme
vividf Aug 14, 2024
9809a4b
chore: fix some grammar errors
vividf Aug 14, 2024
64bfbc5
Merge branch 'main' into feature/distortion_corrector_node_update_azi…
vividf Aug 14, 2024
9aeac77
chore: fix spell error
vividf Aug 14, 2024
8a37932
Merge branch 'feature/distortion_corrector_node_update_azimuth_and_di…
vividf Aug 14, 2024
b5dfa85
chore: set debug mode to false
vividf Aug 14, 2024
d55db4b
Merge branch 'main' into feature/distortion_corrector_node_update_azi…
vividf Aug 19, 2024
d57f751
chore: set update_azimuth_and_distance default value to false
vividf Aug 19, 2024
8703a23
chore: update readme
vividf Aug 19, 2024
5390055
Merge branch 'main' into feature/distortion_corrector_node_update_azi…
vividf Sep 4, 2024
f509d7d
chore: remove cout
vividf Sep 4, 2024
62434fa
chore: add opencv license
vividf Sep 4, 2024
a3c977b
chore: fix grammar error
vividf Sep 4, 2024
ee1b169
Merge branch 'main' into feature/distortion_corrector_node_update_azi…
vividf Sep 9, 2024
7288042
style(pre-commit): autofix
pre-commit-ci[bot] Sep 9, 2024
7e1f510
chore: add runtime error when azimuth conversion failed
vividf Sep 9, 2024
b156fb5
chore: change default pointcloud
vividf Sep 9, 2024
0a1f4c9
chore: change function name
vividf Sep 9, 2024
f11e529
chore: move variables to structure
vividf Sep 9, 2024
f0609f5
chore: add random seed
vividf Sep 9, 2024
ec4172e
chore: rewrite get conversion function
vividf Sep 9, 2024
e797752
Merge branch 'main' into feature/distortion_corrector_node_update_azi…
vividf Sep 10, 2024
be9d8c9
Merge branch 'feature/distortion_corrector_node_update_azimuth_and_di…
vividf Sep 10, 2024
427a0ce
chore: fix opencv fast atan2 function
vividf Sep 10, 2024
25253c3
chore: fix schema description
vividf Sep 10, 2024
ed3efee
Update sensing/autoware_pointcloud_preprocessor/test/test_distortion_…
vividf Sep 10, 2024
031bc2c
Update sensing/autoware_pointcloud_preprocessor/test/test_distortion_…
vividf Sep 10, 2024
a1f076c
chore: move code to function for readability
vividf Sep 10, 2024
71b1917
chore: simplify code
vividf Sep 10, 2024
80ad8e2
chore: fix sentence, angle conversion
vividf Sep 10, 2024
11b88bd
chore: add more invalid condition
vividf Sep 11, 2024
53f4162
chore: fix the string name to enum
vividf Sep 11, 2024
a65a2bf
chore: remove runtime error
vividf Sep 11, 2024
8a24a79
chore: use optional for AngleConversion structure
vividf Sep 11, 2024
f6c5dab
chore: fix bug and clean code
vividf Sep 11, 2024
4342dca
chore: refactor the logic of calculating conversion
vividf Sep 11, 2024
242ab45
chore: refactor function in unit test
vividf Sep 12, 2024
1d5ccdb
chore: RCLCPP_WARN_STREAM logging when failed to get angle conversion
vividf Sep 12, 2024
5e55d01
chore: improve normalize angle algorithm
vividf Sep 12, 2024
02beb86
chore: improve multiple_of_90_degrees logic
vividf Sep 12, 2024
29f4b96
chore: add opencv license
vividf Sep 12, 2024
b9a5c56
style(pre-commit): autofix
pre-commit-ci[bot] Sep 12, 2024
13d981f
chore: clean code
vividf Sep 12, 2024
96bafef
Merge branch 'feature/distortion_corrector_node_update_azimuth_and_di…
vividf Sep 12, 2024
02b1217
chore: fix sentence
vividf Sep 12, 2024
cdb88ae
style(pre-commit): autofix
pre-commit-ci[bot] Sep 12, 2024
4e3d70a
Merge branch 'feature/distortion_corrector_node_update_azimuth_and_di…
vividf Sep 12, 2024
a853293
chore: add 0 0 0 points in test case
vividf Sep 12, 2024
cd066c4
chore: fix spell error
vividf Sep 12, 2024
5560c1d
Update common/autoware_universe_utils/NOTICE
vividf Sep 13, 2024
4c521c0
Update sensing/autoware_pointcloud_preprocessor/src/distortion_correc…
vividf Sep 13, 2024
8e26988
Update sensing/autoware_pointcloud_preprocessor/src/distortion_correc…
vividf Sep 13, 2024
41f086a
chore: use constexpr for threshold
vividf Sep 13, 2024
8428321
Merge branch 'feature/distortion_corrector_node_update_azimuth_and_di…
vividf Sep 13, 2024
a3e5cd8
chore: fix the path of license
vividf Sep 13, 2024
550a646
chore: explanation for failures
vividf Sep 13, 2024
03354c8
chore: use throttle
vividf Sep 13, 2024
320e961
chore: fix empty pointcloud function
vividf Sep 13, 2024
f6be637
refactor: change camel to snake case
vividf Sep 17, 2024
8d4bcd7
Update sensing/autoware_pointcloud_preprocessor/include/autoware/poin…
vividf Sep 19, 2024
4d58839
Update sensing/autoware_pointcloud_preprocessor/include/autoware/poin…
vividf Sep 19, 2024
1f144d3
style(pre-commit): autofix
pre-commit-ci[bot] Sep 19, 2024
f58307d
Update sensing/autoware_pointcloud_preprocessor/test/test_distortion_…
vividf Sep 19, 2024
896d843
refactor: refactor virtual function in base class
vividf Sep 19, 2024
3027ec1
chore: fix test naming error
vividf Sep 19, 2024
3c74303
chore: fix clang error
vividf Sep 19, 2024
2439956
chore: fix error
vividf Sep 20, 2024
f40d081
Merge branch 'autowarefoundation:main' into feature/distortion_correc…
vividf Sep 25, 2024
4e0b8bf
Merge branch 'main' into feature/distortion_corrector_node_update_azi…
vividf Sep 30, 2024
cf27e42
Merge branch 'main' into feature/distortion_corrector_node_update_azi…
vividf Sep 30, 2024
783219f
chore: fix clangd
vividf Sep 30, 2024
caafd52
Merge branch 'feature/distortion_corrector_node_update_azimuth_and_di…
vividf Sep 30, 2024
72f5bb2
chore: add runtime error if the setting is wrong
vividf Oct 3, 2024
9663eaa
chore: clean code
vividf Oct 3, 2024
a06ad31
Update sensing/autoware_pointcloud_preprocessor/src/distortion_correc…
vividf Oct 3, 2024
20ffc99
style(pre-commit): autofix
pre-commit-ci[bot] Oct 3, 2024
7f31139
chore: fix unit test for runtime error
vividf Oct 3, 2024
9d1bef7
Update sensing/autoware_pointcloud_preprocessor/docs/distortion-corre…
vividf Oct 8, 2024
bbbc501
chore: fix offset_rad_threshold
vividf Oct 8, 2024
2594e76
chore: change pointer to reference
vividf Oct 8, 2024
9d0aa59
chore: snake_case for unit test
vividf Oct 8, 2024
cfddc0d
chore: fix refactor process twist and imu
vividf Oct 8, 2024
b1ffa5e
chore: fix abs and return type of matrix to tf2
vividf Oct 8, 2024
57824ef
chore: fix grammar error
vividf Oct 8, 2024
9680027
chore: fix readme description
vividf Oct 9, 2024
4bc0df1
chore: remove runtime error
vividf Oct 9, 2024
384abe8
Merge branch 'main' into feature/distortion_corrector_node_update_azi…
vividf Oct 24, 2024
a4a693e
Merge branch 'main' into feature/distortion_corrector_node_update_azi…
vividf Oct 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
base_frame: base_link
use_imu: true
use_3d_distortion_correction: false
sensor_azimuth_coordinate: ""
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,20 @@ ros2 launch autoware_pointcloud_preprocessor distortion_corrector.launch.xml

- The node requires time synchronization between the topics from lidars, twist, and IMU.
- If you want to use a 3D distortion corrector without IMU, please check that the linear and angular velocity fields of your twist message are not empty.
- The node updates the per-point azimuth and distance values based on the undistorted XYZ coordinates when the input point cloud is in the sensor frame and the `sensor_azimuth_coordinate` parameter is set to either `velodyne` or `hesai`. The azimuth values are calculated using the `cv::fastAtan2` function. Please note that updating the azimuth and distance fields increases the execution time by approximately 13%. Additionally, due to the `cv::fastAtan2` algorithm's accuracy of about 0.3 degrees, there is a **possibility of changing beam order for high azimuth resolution LiDAR**.
- Currently, `sensor_azimuth_coordinate` only supports `velodyne` and `hesai`. The `velodyne` and `hesai` coordinates are illustrated below. If a LiDAR uses the same coordinates as `velodyne` or `hesai`, users can use them as well.

<table>
<tr>
<td><img src="./image/velodyne.drawio.png" alt="velodyne azimuth coordinate"></td>
<td><img src="./image/hesai.drawio.png" alt="hesai azimuth coordinate"></td>
</tr>
<tr>
<td><p style="text-align: center;">Velodyne azimuth coordinate.</p></td>
<td><p style="text-align: center;">Hesai azimuth coordinate</p></td>
</tr>
</table>

## References/External links

<https://docs.opencv.org/3.4/db/de0/group__core__utils.html#ga7b356498dd314380a0c386b059852270>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
#endif

#include <opencv2/opencv.hpp>

#include <tf2_ros/buffer.h>
#include <tf2_ros/buffer_interface.h>
#include <tf2_ros/transform_listener.h>
Expand All @@ -50,8 +52,8 @@ namespace autoware::pointcloud_preprocessor
class DistortionCorrectorBase
{
public:
virtual bool pointcloud_transform_exists() = 0;
virtual bool pointcloud_transform_needed() = 0;
virtual bool pointcloudTransformExists() = 0;
virtual bool pointcloudTransformNeeded() = 0;
virtual std::deque<geometry_msgs::msg::TwistStamped> get_twist_queue() = 0;
virtual std::deque<geometry_msgs::msg::Vector3Stamped> get_angular_velocity_queue() = 0;

Expand All @@ -62,7 +64,9 @@ class DistortionCorrectorBase
virtual void setPointCloudTransform(
const std::string & base_frame, const std::string & lidar_frame) = 0;
virtual void initialize() = 0;
virtual void undistortPointCloud(bool use_imu, sensor_msgs::msg::PointCloud2 & pointcloud) = 0;
virtual void undistortPointCloud(
bool use_imu, std::string sensor_azimuth_coordinate,
sensor_msgs::msg::PointCloud2 & pointcloud) = 0;
};

template <class T>
Expand Down Expand Up @@ -103,16 +107,18 @@ class DistortionCorrector : public DistortionCorrectorBase
{
static_tf_buffer_ = std::make_unique<autoware::universe_utils::StaticTransformBuffer>();
}
bool pointcloud_transform_exists();
bool pointcloud_transform_needed();
bool pointcloudTransformExists();
bool pointcloudTransformNeeded();
std::deque<geometry_msgs::msg::TwistStamped> get_twist_queue();
std::deque<geometry_msgs::msg::Vector3Stamped> get_angular_velocity_queue();
void processTwistMessage(
const geometry_msgs::msg::TwistWithCovarianceStamped::ConstSharedPtr twist_msg) override;

void processIMUMessage(
const std::string & base_frame, const sensor_msgs::msg::Imu::ConstSharedPtr imu_msg) override;
void undistortPointCloud(bool use_imu, sensor_msgs::msg::PointCloud2 & pointcloud) override;
void undistortPointCloud(
bool use_imu, std::string sensor_azimuth_coordinate,
sensor_msgs::msg::PointCloud2 & pointcloud) override;
bool isInputValid(sensor_msgs::msg::PointCloud2 & pointcloud);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class DistortionCorrectorComponent : public rclcpp::Node
std::string base_frame_;
bool use_imu_;
bool use_3d_distortion_correction_;
std::string sensor_azimuth_coordinate_;

std::unique_ptr<DistortionCorrectorBase> distortion_corrector_;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,19 @@
"type": "boolean",
"description": "Use 3d distortion correction algorithm, otherwise, use 2d distortion correction algorithm.",
"default": "false"
},
"sensor_azimuth_coordinate": {
"type": "string",
"description": "The azimuth coordinate of sensor. Currently support Hesai and Velodyne.",
"default": ""
}
},
"required": ["base_frame", "use_imu", "use_3d_distortion_correction"]
"required": [
"base_frame",
"use_imu",
"use_3d_distortion_correction",
"sensor_azimuth_coordinate"
]
}
},
"properties": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2024 TIER IV, Inc.

Check notice on line 1 in sensing/autoware_pointcloud_preprocessor/src/distortion_corrector/distortion_corrector.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

ℹ Getting worse: Primitive Obsession

The ratio of primitive types in function arguments increases from 48.65% to 50.00%, threshold = 30.0%. The functions in this file have too many primitive types (e.g. int, double, float) in their function argument lists. Using many primitive types lead to the code smell Primitive Obsession. Avoid adding more primitive arguments.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -25,13 +25,13 @@
{

template <class T>
bool DistortionCorrector<T>::pointcloud_transform_exists()
bool DistortionCorrector<T>::pointcloudTransformExists()
{
return pointcloud_transform_exists_;
}

template <class T>
bool DistortionCorrector<T>::pointcloud_transform_needed()
bool DistortionCorrector<T>::pointcloudTransformNeeded()
{
return pointcloud_transform_needed_;
}
Expand Down Expand Up @@ -189,75 +189,96 @@

template <class T>
void DistortionCorrector<T>::undistortPointCloud(
bool use_imu, sensor_msgs::msg::PointCloud2 & pointcloud)
bool use_imu, std::string sensor_azimuth_coordinate, sensor_msgs::msg::PointCloud2 & pointcloud)
{
if (!isInputValid(pointcloud)) return;

sensor_msgs::PointCloud2Iterator<float> it_x(pointcloud, "x");
sensor_msgs::PointCloud2Iterator<float> it_y(pointcloud, "y");
sensor_msgs::PointCloud2Iterator<float> it_z(pointcloud, "z");
sensor_msgs::PointCloud2Iterator<float> it_azimuth(pointcloud, "azimuth");
sensor_msgs::PointCloud2Iterator<float> it_distance(pointcloud, "distance");
sensor_msgs::PointCloud2ConstIterator<std::uint32_t> it_time_stamp(pointcloud, "time_stamp");

double prev_time_stamp_sec{
pointcloud.header.stamp.sec + 1e-9 * (pointcloud.header.stamp.nanosec + *it_time_stamp)};
const double first_point_time_stamp_sec{
pointcloud.header.stamp.sec + 1e-9 * (pointcloud.header.stamp.nanosec + *it_time_stamp)};

std::deque<geometry_msgs::msg::TwistStamped>::iterator it_twist;
std::deque<geometry_msgs::msg::Vector3Stamped>::iterator it_imu;
getTwistAndIMUIterator(use_imu, first_point_time_stamp_sec, it_twist, it_imu);

// For performance, do not instantiate `rclcpp::Time` inside of the for-loop
double twist_stamp = rclcpp::Time(it_twist->header.stamp).seconds();
double imu_stamp{0.0};
if (use_imu && !angular_velocity_queue_.empty()) {
imu_stamp = rclcpp::Time(it_imu->header.stamp).seconds();
}

// If there is a point in a pointcloud that cannot be associated, record it to issue a warning
bool is_twist_time_stamp_too_late = false;
bool is_imu_time_stamp_too_late = false;
bool is_twist_valid = true;
bool is_imu_valid = true;
double global_point_stamp;

for (; it_x != it_x.end(); ++it_x, ++it_y, ++it_z, ++it_time_stamp) {
is_twist_valid = true;
is_imu_valid = true;

global_point_stamp =
pointcloud.header.stamp.sec + 1e-9 * (pointcloud.header.stamp.nanosec + *it_time_stamp);

// Get closest twist information
while (it_twist != std::end(twist_queue_) - 1 && global_point_stamp > twist_stamp) {
++it_twist;
twist_stamp = rclcpp::Time(it_twist->header.stamp).seconds();
}
if (std::abs(global_point_stamp - twist_stamp) > 0.1) {
is_twist_time_stamp_too_late = true;
is_twist_valid = false;
}

// Get closest IMU information
if (use_imu && !angular_velocity_queue_.empty()) {
while (it_imu != std::end(angular_velocity_queue_) - 1 && global_point_stamp > imu_stamp) {
++it_imu;
imu_stamp = rclcpp::Time(it_imu->header.stamp).seconds();
}

if (std::abs(global_point_stamp - imu_stamp) > 0.1) {
is_imu_time_stamp_too_late = true;
is_imu_valid = false;
}
} else {
is_imu_valid = false;
}

float time_offset = static_cast<float>(global_point_stamp - prev_time_stamp_sec);

// Undistort a single point based on the strategy
undistortPoint(it_x, it_y, it_z, it_twist, it_imu, time_offset, is_twist_valid, is_imu_valid);

if (!sensor_azimuth_coordinate.empty() && pointcloudTransformNeeded()) {
// Input frame should be in the sensor frame.
*it_distance = sqrt(*it_x * *it_x + *it_y * *it_y + *it_z * *it_z);
float cartesian_coordinate_azimuth = cv::fastAtan2(*it_y, *it_x);
vividf marked this conversation as resolved.
Show resolved Hide resolved
if (sensor_azimuth_coordinate == "velodyne") {
*it_azimuth = (360 - cartesian_coordinate_azimuth) * M_PI / 180;
} else if (sensor_azimuth_coordinate == "hesai") {
*it_azimuth = (90 - cartesian_coordinate_azimuth) < 0
? (90 - cartesian_coordinate_azimuth + 360) * M_PI / 180
: (90 - cartesian_coordinate_azimuth) * M_PI / 180;
} else {
throw std::runtime_error(
sensor_azimuth_coordinate + " azimuth coordinate is not supported");
}
vividf marked this conversation as resolved.
Show resolved Hide resolved

++it_azimuth;
++it_distance;
}

Check warning on line 281 in sensing/autoware_pointcloud_preprocessor/src/distortion_corrector/distortion_corrector.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Method

undistortPointCloud increases in cyclomatic complexity from 13 to 19, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

Check notice on line 281 in sensing/autoware_pointcloud_preprocessor/src/distortion_corrector/distortion_corrector.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

ℹ Getting worse: Bumpy Road Ahead

undistortPointCloud increases from 2 to 3 logical blocks with deeply nested code, threshold is one single block per function. The Bumpy Road code smell is a function that contains multiple chunks of nested conditional logic. The deeper the nesting and the more bumps, the lower the code health.
prev_time_stamp_sec = global_point_stamp;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ DistortionCorrectorComponent::DistortionCorrectorComponent(const rclcpp::NodeOpt
base_frame_ = declare_parameter<std::string>("base_frame");
use_imu_ = declare_parameter<bool>("use_imu");
use_3d_distortion_correction_ = declare_parameter<bool>("use_3d_distortion_correction");
sensor_azimuth_coordinate_ = declare_parameter<std::string>("sensor_azimuth_coordinate");

// Publisher
{
Expand Down Expand Up @@ -91,9 +92,8 @@ void DistortionCorrectorComponent::onPointCloud(PointCloud2::UniquePtr pointclou
}

distortion_corrector_->setPointCloudTransform(base_frame_, pointcloud_msg->header.frame_id);

distortion_corrector_->initialize();
distortion_corrector_->undistortPointCloud(use_imu_, *pointcloud_msg);
distortion_corrector_->undistortPointCloud(use_imu_, sensor_azimuth_coordinate_, *pointcloud_msg);

if (debug_publisher_) {
auto pipeline_latency_ms =
Expand Down
Loading
Loading