Skip to content

Commit 18843b2

Browse files
authored
Merge pull request #1074 from tier4/fix/ndt_scan_matcher/delete_diagnostics_thread
fix(ndt scan matcher): delete diagnostics thread
2 parents f74b33d + a606563 commit 18843b2

File tree

4 files changed

+70
-79
lines changed

4 files changed

+70
-79
lines changed

localization/ndt_scan_matcher/include/ndt_scan_matcher/map_update_module.hpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ class MapUpdateModule
5151
rclcpp::Node * node, std::mutex * ndt_ptr_mutex,
5252
std::shared_ptr<NormalDistributionsTransform> ndt_ptr,
5353
std::shared_ptr<Tf2ListenerModule> tf2_listener_module, std::string map_frame,
54-
rclcpp::CallbackGroup::SharedPtr main_callback_group,
55-
std::shared_ptr<std::map<std::string, std::string>> state_ptr);
54+
rclcpp::CallbackGroup::SharedPtr main_callback_group);
5655

5756
private:
5857
friend class NDTScanMatcher;
@@ -82,7 +81,6 @@ class MapUpdateModule
8281
rclcpp::Logger logger_;
8382
rclcpp::Clock::SharedPtr clock_;
8483
std::shared_ptr<Tf2ListenerModule> tf2_listener_module_;
85-
std::shared_ptr<std::map<std::string, std::string>> state_ptr_;
8684

8785
std::optional<geometry_msgs::msg::Point> last_update_position_ = std::nullopt;
8886
std::optional<geometry_msgs::msg::Point> current_position_ = std::nullopt;

localization/ndt_scan_matcher/include/ndt_scan_matcher/ndt_scan_matcher_core.hpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ class NDTScanMatcher : public rclcpp::Node
127127
const rclcpp::Time & sensor_ros_time);
128128
void add_regularization_pose(const rclcpp::Time & sensor_ros_time);
129129

130-
void timer_diagnostic();
130+
void publish_diagnostic();
131131

132132
rclcpp::Subscription<geometry_msgs::msg::PoseWithCovarianceStamped>::SharedPtr initial_pose_sub_;
133133
rclcpp::Subscription<sensor_msgs::msg::PointCloud2>::SharedPtr sensor_points_sub_;
@@ -190,8 +190,6 @@ class NDTScanMatcher : public rclcpp::Node
190190
std::mutex ndt_ptr_mtx_;
191191
std::mutex initial_pose_array_mtx_;
192192

193-
std::thread diagnostic_thread_;
194-
195193
// variables for regularization
196194
const bool regularization_enabled_;
197195
std::deque<geometry_msgs::msg::PoseWithCovarianceStamped::ConstSharedPtr>

localization/ndt_scan_matcher/src/map_update_module.cpp

+17-18
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,13 @@ MapUpdateModule::MapUpdateModule(
2626
rclcpp::Node * node, std::mutex * ndt_ptr_mutex,
2727
std::shared_ptr<NormalDistributionsTransform> ndt_ptr,
2828
std::shared_ptr<Tf2ListenerModule> tf2_listener_module, std::string map_frame,
29-
rclcpp::CallbackGroup::SharedPtr main_callback_group,
30-
std::shared_ptr<std::map<std::string, std::string>> state_ptr)
29+
rclcpp::CallbackGroup::SharedPtr main_callback_group)
3130
: ndt_ptr_(std::move(ndt_ptr)),
3231
ndt_ptr_mutex_(ndt_ptr_mutex),
3332
map_frame_(std::move(map_frame)),
3433
logger_(node->get_logger()),
3534
clock_(node->get_clock()),
3635
tf2_listener_module_(std::move(tf2_listener_module)),
37-
state_ptr_(std::move(state_ptr)),
3836
dynamic_map_loading_update_distance_(
3937
node->declare_parameter<double>("dynamic_map_loading_update_distance")),
4038
dynamic_map_loading_map_radius_(
@@ -146,36 +144,37 @@ void MapUpdateModule::update_ndt(
146144
}
147145
const auto exe_start_time = std::chrono::system_clock::now();
148146

149-
NormalDistributionsTransform backup_ndt = *ndt_ptr_;
147+
const size_t add_size = maps_to_add.size();
148+
149+
// Perform heavy processing outside of the lock scope
150+
std::vector<pcl::shared_ptr<pcl::PointCloud<PointTarget>>> points_pcl(add_size);
151+
for (size_t i = 0; i < add_size; i++) {
152+
points_pcl[i] = pcl::make_shared<pcl::PointCloud<PointTarget>>();
153+
pcl::fromROSMsg(maps_to_add[i].pointcloud, *points_pcl[i]);
154+
}
155+
156+
(*ndt_ptr_mutex_).lock();
150157

151158
// Add pcd
152-
for (const auto & map_to_add : maps_to_add) {
153-
pcl::shared_ptr<pcl::PointCloud<PointTarget>> map_points_ptr(new pcl::PointCloud<PointTarget>);
154-
pcl::fromROSMsg(map_to_add.pointcloud, *map_points_ptr);
155-
backup_ndt.addTarget(map_points_ptr, map_to_add.cell_id);
159+
for (size_t i = 0; i < add_size; i++) {
160+
ndt_ptr_->addTarget(points_pcl[i], maps_to_add[i].cell_id);
156161
}
157162

158163
// Remove pcd
159164
for (const std::string & map_id_to_remove : map_ids_to_remove) {
160-
backup_ndt.removeTarget(map_id_to_remove);
165+
ndt_ptr_->removeTarget(map_id_to_remove);
161166
}
162167

163-
backup_ndt.createVoxelKdtree();
168+
ndt_ptr_->createVoxelKdtree();
169+
170+
(*ndt_ptr_mutex_).unlock();
164171

165172
const auto exe_end_time = std::chrono::system_clock::now();
166173
const auto duration_micro_sec =
167174
std::chrono::duration_cast<std::chrono::microseconds>(exe_end_time - exe_start_time).count();
168175
const auto exe_time = static_cast<double>(duration_micro_sec) / 1000.0;
169176
RCLCPP_INFO(logger_, "Time duration for creating new ndt_ptr: %lf [ms]", exe_time);
170177

171-
// swap
172-
(*ndt_ptr_mutex_).lock();
173-
// ToDo (kminoda): Here negligible NDT copy occurs during the new map loading phase, which should
174-
// ideally be avoided. But I will leave this for now since I cannot come up with a solution other
175-
// than using pointer of pointer.
176-
*ndt_ptr_ = backup_ndt;
177-
(*ndt_ptr_mutex_).unlock();
178-
179178
publish_partial_pcd_map();
180179
}
181180

localization/ndt_scan_matcher/src/ndt_scan_matcher_core.cpp

+51-55
Original file line numberDiff line numberDiff line change
@@ -232,70 +232,69 @@ NDTScanMatcher::NDTScanMatcher()
232232
&NDTScanMatcher::service_trigger_node, this, std::placeholders::_1, std::placeholders::_2),
233233
rclcpp::ServicesQoS().get_rmw_qos_profile(), main_callback_group);
234234

235-
diagnostic_thread_ = std::thread(&NDTScanMatcher::timer_diagnostic, this);
236-
diagnostic_thread_.detach();
237-
238235
tf2_listener_module_ = std::make_shared<Tf2ListenerModule>(this);
239236

240237
use_dynamic_map_loading_ = this->declare_parameter<bool>("use_dynamic_map_loading");
241238
if (use_dynamic_map_loading_) {
242239
map_update_module_ = std::make_unique<MapUpdateModule>(
243-
this, &ndt_ptr_mtx_, ndt_ptr_, tf2_listener_module_, map_frame_, main_callback_group,
244-
state_ptr_);
240+
this, &ndt_ptr_mtx_, ndt_ptr_, tf2_listener_module_, map_frame_, main_callback_group);
245241
} else {
246242
map_module_ = std::make_unique<MapModule>(this, &ndt_ptr_mtx_, ndt_ptr_, main_callback_group);
247243
}
248244
}
249245

250-
void NDTScanMatcher::timer_diagnostic()
246+
void NDTScanMatcher::publish_diagnostic()
251247
{
252-
rclcpp::Rate rate(100);
253-
while (rclcpp::ok()) {
254-
diagnostic_msgs::msg::DiagnosticStatus diag_status_msg;
255-
diag_status_msg.name = "ndt_scan_matcher";
256-
diag_status_msg.hardware_id = "";
257-
258-
for (const auto & key_value : (*state_ptr_)) {
259-
diagnostic_msgs::msg::KeyValue key_value_msg;
260-
key_value_msg.key = key_value.first;
261-
key_value_msg.value = key_value.second;
262-
diag_status_msg.values.push_back(key_value_msg);
263-
}
248+
diagnostic_msgs::msg::DiagnosticStatus diag_status_msg;
249+
diag_status_msg.name = "ndt_scan_matcher";
250+
diag_status_msg.hardware_id = "";
251+
252+
for (const auto & key_value : (*state_ptr_)) {
253+
diagnostic_msgs::msg::KeyValue key_value_msg;
254+
key_value_msg.key = key_value.first;
255+
key_value_msg.value = key_value.second;
256+
diag_status_msg.values.push_back(key_value_msg);
257+
}
264258

259+
diag_status_msg.level = diagnostic_msgs::msg::DiagnosticStatus::OK;
260+
diag_status_msg.message = "";
261+
if (state_ptr_->count("state") && (*state_ptr_)["state"] == "Initializing") {
262+
diag_status_msg.level = diagnostic_msgs::msg::DiagnosticStatus::WARN;
263+
diag_status_msg.message += "Initializing State. ";
264+
}
265+
if (
266+
state_ptr_->count("skipping_publish_num") &&
267+
std::stoi((*state_ptr_)["skipping_publish_num"]) > 1 &&
268+
std::stoi((*state_ptr_)["skipping_publish_num"]) < 5) {
269+
diag_status_msg.level = diagnostic_msgs::msg::DiagnosticStatus::WARN;
270+
diag_status_msg.message += "skipping_publish_num > 1. ";
271+
}
272+
if (
273+
state_ptr_->count("skipping_publish_num") &&
274+
std::stoi((*state_ptr_)["skipping_publish_num"]) >= 5) {
275+
diag_status_msg.level = diagnostic_msgs::msg::DiagnosticStatus::ERROR;
276+
diag_status_msg.message += "skipping_publish_num exceed limit. ";
277+
}
278+
if (
279+
state_ptr_->count("nearest_voxel_transformation_likelihood") &&
280+
std::stod((*state_ptr_)["nearest_voxel_transformation_likelihood"]) <
281+
converged_param_nearest_voxel_transformation_likelihood_) {
282+
diag_status_msg.level = diagnostic_msgs::msg::DiagnosticStatus::WARN;
283+
diag_status_msg.message += "NDT score is unreliably low. ";
284+
}
285+
// Ignore local optimal solution
286+
if (
287+
state_ptr_->count("is_local_optimal_solution_oscillation") &&
288+
std::stoi((*state_ptr_)["is_local_optimal_solution_oscillation"])) {
265289
diag_status_msg.level = diagnostic_msgs::msg::DiagnosticStatus::OK;
266-
diag_status_msg.message = "";
267-
if (state_ptr_->count("state") && (*state_ptr_)["state"] == "Initializing") {
268-
diag_status_msg.level = diagnostic_msgs::msg::DiagnosticStatus::WARN;
269-
diag_status_msg.message += "Initializing State. ";
270-
}
271-
if (
272-
state_ptr_->count("skipping_publish_num") &&
273-
std::stoi((*state_ptr_)["skipping_publish_num"]) > 1) {
274-
diag_status_msg.level = diagnostic_msgs::msg::DiagnosticStatus::WARN;
275-
diag_status_msg.message += "skipping_publish_num > 1. ";
276-
}
277-
if (
278-
state_ptr_->count("skipping_publish_num") &&
279-
std::stoi((*state_ptr_)["skipping_publish_num"]) >= 5) {
280-
diag_status_msg.level = diagnostic_msgs::msg::DiagnosticStatus::ERROR;
281-
diag_status_msg.message += "skipping_publish_num exceed limit. ";
282-
}
283-
// Ignore local optimal solution
284-
if (
285-
state_ptr_->count("is_local_optimal_solution_oscillation") &&
286-
std::stoi((*state_ptr_)["is_local_optimal_solution_oscillation"])) {
287-
diag_status_msg.level = diagnostic_msgs::msg::DiagnosticStatus::OK;
288-
diag_status_msg.message = "local optimal solution oscillation occurred";
289-
}
290-
291-
diagnostic_msgs::msg::DiagnosticArray diag_msg;
292-
diag_msg.header.stamp = this->now();
293-
diag_msg.status.push_back(diag_status_msg);
290+
diag_status_msg.message = "local optimal solution oscillation occurred";
291+
}
294292

295-
diagnostics_pub_->publish(diag_msg);
293+
diagnostic_msgs::msg::DiagnosticArray diag_msg;
294+
diag_msg.header.stamp = this->now();
295+
diag_msg.status.push_back(diag_status_msg);
296296

297-
rate.sleep();
298-
}
297+
diagnostics_pub_->publish(diag_msg);
299298
}
300299

301300
void NDTScanMatcher::callback_initial_pose(
@@ -387,13 +386,11 @@ void NDTScanMatcher::callback_sensor_points(
387386
}
388387

389388
// perform ndt scan matching
390-
(*state_ptr_)["state"] = "Aligning";
391389
const Eigen::Matrix4f initial_pose_matrix =
392390
pose_to_matrix4f(interpolator.get_current_pose().pose.pose);
393391
auto output_cloud = std::make_shared<pcl::PointCloud<PointSource>>();
394392
ndt_ptr_->align(*output_cloud, initial_pose_matrix);
395393
const pclomp::NdtResult ndt_result = ndt_ptr_->getResult();
396-
(*state_ptr_)["state"] = "Sleeping";
397394

398395
const auto exe_end_time = std::chrono::system_clock::now();
399396
const auto duration_micro_sec =
@@ -488,6 +485,7 @@ void NDTScanMatcher::callback_sensor_points(
488485
make_float32_stamped(sensor_ros_time, no_ground_nearest_voxel_transformation_likelihood));
489486
}
490487

488+
(*state_ptr_)["state"] = "Aligned";
491489
(*state_ptr_)["transform_probability"] = std::to_string(ndt_result.transform_probability);
492490
(*state_ptr_)["nearest_voxel_transformation_likelihood"] =
493491
std::to_string(ndt_result.nearest_voxel_transformation_likelihood);
@@ -498,6 +496,8 @@ void NDTScanMatcher::callback_sensor_points(
498496
} else {
499497
(*state_ptr_)["is_local_optimal_solution_oscillation"] = "0";
500498
}
499+
500+
publish_diagnostic();
501501
}
502502

503503
void NDTScanMatcher::transform_sensor_measurement(
@@ -694,8 +694,6 @@ void NDTScanMatcher::service_trigger_node(
694694
if (is_activated_) {
695695
std::lock_guard<std::mutex> initial_pose_array_lock(initial_pose_array_mtx_);
696696
initial_pose_msg_ptr_array_.clear();
697-
} else {
698-
(*state_ptr_)["state"] = "Initializing";
699697
}
700698
res->success = true;
701699
}
@@ -731,9 +729,7 @@ void NDTScanMatcher::service_ndt_align(
731729
// mutex Map
732730
std::lock_guard<std::mutex> lock(ndt_ptr_mtx_);
733731

734-
(*state_ptr_)["state"] = "Aligning";
735732
res->pose_with_covariance = align_using_monte_carlo(ndt_ptr_, initial_pose_msg_in_map_frame);
736-
(*state_ptr_)["state"] = "Sleeping";
737733
res->success = true;
738734
res->pose_with_covariance.pose.covariance = req->pose_with_covariance.pose.covariance;
739735
}

0 commit comments

Comments
 (0)