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

fix(ndt_scan_matcher): make regularization process thread safe #5550

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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 @@ -204,9 +204,10 @@ class NDTScanMatcher : public rclcpp::Node
std::mutex initial_pose_array_mtx_;

// variables for regularization
const bool regularization_enabled_;
const bool regularization_enabled_; // whether to use longitudinal regularization
std::deque<geometry_msgs::msg::PoseWithCovarianceStamped::ConstSharedPtr>
regularization_pose_msg_ptr_array_;
regularization_pose_msg_ptr_array_; // queue for storing regularization base poses
std::mutex regularization_mutex_; // mutex for regularization_pose_msg_ptr_array_

bool is_activated_;
std::shared_ptr<Tf2ListenerModule> tf2_listener_module_;
Expand Down
52 changes: 38 additions & 14 deletions localization/ndt_scan_matcher/src/ndt_scan_matcher_core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,10 +219,21 @@
sensor_points_sub_ = this->create_subscription<sensor_msgs::msg::PointCloud2>(
"points_raw", rclcpp::SensorDataQoS().keep_last(points_queue_size),
std::bind(&NDTScanMatcher::callback_sensor_points, this, std::placeholders::_1), main_sub_opt);
regularization_pose_sub_ =
this->create_subscription<geometry_msgs::msg::PoseWithCovarianceStamped>(
"regularization_pose_with_covariance", 100,
std::bind(&NDTScanMatcher::callback_regularization_pose, this, std::placeholders::_1));

// Only if regularization is enabled, subscribe to the regularization base pose
if (regularization_enabled_) {
// NOTE: The reason that the regularization subscriber does not belong to the
// main_callback_group is to ensure that the regularization callback is called even if
// sensor_callback takes time to process.
// Also, initial_pose_callback_group is separated from main_callback_group because
// callback_initial_pose missed receiving data in the past. resulting in improper interpolation.
regularization_pose_sub_ =
this->create_subscription<geometry_msgs::msg::PoseWithCovarianceStamped>(
"regularization_pose_with_covariance", 10,
std::bind(

Check warning on line 233 in localization/ndt_scan_matcher/src/ndt_scan_matcher_core.cpp

View check run for this annotation

Codecov / codecov/patch

localization/ndt_scan_matcher/src/ndt_scan_matcher_core.cpp#L233

Added line #L233 was not covered by tests
&NDTScanMatcher::callback_regularization_pose, this,
std::placeholders::_1) /* Neither main_callback_group nor initial_pose_callback_group */);
kminoda marked this conversation as resolved.
Show resolved Hide resolved
}

sensor_aligned_pose_pub_ =
this->create_publisher<sensor_msgs::msg::PointCloud2>("points_aligned", 10);
Expand Down Expand Up @@ -397,7 +408,10 @@
void NDTScanMatcher::callback_regularization_pose(
geometry_msgs::msg::PoseWithCovarianceStamped::ConstSharedPtr pose_conv_msg_ptr)
{
// Get lock for regularization_pose_msg_ptr_array_
std::lock_guard<std::mutex> lock(regularization_mutex_);

Check warning on line 412 in localization/ndt_scan_matcher/src/ndt_scan_matcher_core.cpp

View check run for this annotation

Codecov / codecov/patch

localization/ndt_scan_matcher/src/ndt_scan_matcher_core.cpp#L412

Added line #L412 was not covered by tests
regularization_pose_msg_ptr_array_.push_back(pose_conv_msg_ptr);
// Release lock for regularization_pose_msg_ptr_array_
}

void NDTScanMatcher::callback_sensor_points(
Expand Down Expand Up @@ -459,7 +473,9 @@
initial_pose_array_lock.unlock();

// if regularization is enabled and available, set pose to NDT for regularization
if (regularization_enabled_) add_regularization_pose(sensor_ros_time);
if (regularization_enabled_) {
add_regularization_pose(sensor_ros_time);
}

Check warning on line 478 in localization/ndt_scan_matcher/src/ndt_scan_matcher_core.cpp

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Method

NDTScanMatcher::callback_sensor_points already has high cyclomatic complexity, and now it increases in Lines of Code from 138 to 140. 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.

if (ndt_ptr_->getInputTarget() == nullptr) {
RCLCPP_WARN_STREAM_THROTTLE(this->get_logger(), *this->get_clock(), 1, "No MAP!");
Expand Down Expand Up @@ -816,21 +832,29 @@
std::optional<Eigen::Matrix4f> NDTScanMatcher::interpolate_regularization_pose(
const rclcpp::Time & sensor_ros_time)
{
if (regularization_pose_msg_ptr_array_.empty()) {
return std::nullopt;
}
std::shared_ptr<PoseArrayInterpolator> interpolator = nullptr;
{
// Get lock for regularization_pose_msg_ptr_array_
std::lock_guard<std::mutex> lock(regularization_mutex_);

// synchronization
PoseArrayInterpolator interpolator(this, sensor_ros_time, regularization_pose_msg_ptr_array_);
if (regularization_pose_msg_ptr_array_.empty()) {
return std::nullopt;
}

interpolator = std::make_shared<PoseArrayInterpolator>(

Check warning on line 844 in localization/ndt_scan_matcher/src/ndt_scan_matcher_core.cpp

View check run for this annotation

Codecov / codecov/patch

localization/ndt_scan_matcher/src/ndt_scan_matcher_core.cpp#L844

Added line #L844 was not covered by tests
this, sensor_ros_time, regularization_pose_msg_ptr_array_);

pop_old_pose(regularization_pose_msg_ptr_array_, sensor_ros_time);
// Remove old pauses to make next interpolation more efficient
YamatoAndo marked this conversation as resolved.
Show resolved Hide resolved
pop_old_pose(regularization_pose_msg_ptr_array_, sensor_ros_time);

// Release lock for regularization_pose_msg_ptr_array_
}

// if the interpolate_pose fails, 0.0 is stored in the stamp
if (rclcpp::Time(interpolator.get_current_pose().header.stamp).seconds() == 0.0) {
if (!interpolator || !interpolator->is_success()) {
return std::nullopt;
}

return pose_to_matrix4f(interpolator.get_current_pose().pose.pose);
return pose_to_matrix4f(interpolator->get_current_pose().pose.pose);
}

void NDTScanMatcher::add_regularization_pose(const rclcpp::Time & sensor_ros_time)
Expand Down
Loading