Skip to content

Commit 96999f0

Browse files
committed
feat: refactored the concat into a templated design to allow cuda implementations and extend it to radars
Signed-off-by: Kenzo Lobos-Tsunekawa <kenzo.lobos@tier4.jp>
1 parent 660ae1a commit 96999f0

18 files changed

+1303
-951
lines changed

sensing/autoware_pointcloud_preprocessor/CMakeLists.txt

+29-1
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,32 @@ ament_target_dependencies(faster_voxel_grid_downsample_filter
6363
sensor_msgs
6464
)
6565

66-
ament_auto_add_library(pointcloud_preprocessor_filter SHARED
66+
add_library(concatenate_data SHARED
6767
src/concatenate_data/concatenate_and_time_sync_node.cpp
6868
src/concatenate_data/combine_cloud_handler.cpp
6969
src/concatenate_data/cloud_collector.cpp
7070
src/concatenate_data/collector_matching_strategy.cpp
7171
src/concatenate_data/concatenate_pointclouds.cpp
72+
)
73+
74+
target_include_directories(concatenate_data PUBLIC
75+
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
76+
"$<INSTALL_INTERFACE:include/${PROJECT_NAME}>"
77+
)
78+
79+
ament_target_dependencies(concatenate_data
80+
SYSTEM
81+
pcl_conversions
82+
rclcpp
83+
sensor_msgs
84+
tf2_ros
85+
autoware_utils
86+
pcl_ros
87+
autoware_point_types
88+
)
89+
90+
ament_auto_add_library(pointcloud_preprocessor_filter SHARED
91+
7292
src/crop_box_filter/crop_box_filter_node.cpp
7393
src/time_synchronizer/time_synchronizer_node.cpp
7494
src/downsample_filter/voxel_grid_downsample_filter_node.cpp
@@ -95,6 +115,7 @@ ament_auto_add_library(pointcloud_preprocessor_filter SHARED
95115
target_link_libraries(pointcloud_preprocessor_filter
96116
pointcloud_preprocessor_filter_base
97117
faster_voxel_grid_downsample_filter
118+
concatenate_data
98119
${Boost_LIBRARIES}
99120
${OpenCV_LIBRARIES}
100121
${Sophus_LIBRARIES}
@@ -220,6 +241,13 @@ install(
220241
RUNTIME DESTINATION bin
221242
)
222243

244+
install(
245+
TARGETS concatenate_data EXPORT export_${PROJECT_NAME}
246+
ARCHIVE DESTINATION lib
247+
LIBRARY DESTINATION lib
248+
RUNTIME DESTINATION bin
249+
)
250+
223251
install(
224252
DIRECTORY include/
225253
DESTINATION include/${PROJECT_NAME}

sensing/autoware_pointcloud_preprocessor/include/autoware/pointcloud_preprocessor/concatenate_data/cloud_collector.hpp

+22-13
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@
2323
namespace autoware::pointcloud_preprocessor
2424
{
2525

26-
class PointCloudConcatenateDataSynchronizerComponent;
26+
template <typename MsgTraits>
27+
class PointCloudConcatenateDataSynchronizerComponentTemplated;
28+
29+
template <typename MsgTraits>
2730
class CombineCloudHandler;
2831

2932
struct CollectorInfoBase
@@ -50,23 +53,25 @@ struct AdvancedCollectorInfo : public CollectorInfoBase
5053
};
5154

5255
enum class CollectorStatus { Idle, Processing, Finished };
53-
56+
template <typename MsgTraits>
5457
class CloudCollector
5558
{
5659
public:
5760
CloudCollector(
58-
std::shared_ptr<PointCloudConcatenateDataSynchronizerComponent> && ros2_parent_node,
59-
std::shared_ptr<CombineCloudHandler> & combine_cloud_handler, int num_of_clouds,
61+
std::shared_ptr<PointCloudConcatenateDataSynchronizerComponentTemplated<MsgTraits>> &&
62+
ros2_parent_node,
63+
std::shared_ptr<CombineCloudHandler<MsgTraits>> & combine_cloud_handler, int num_of_clouds,
6064
double timeout_sec, bool debug_mode);
6165
bool topic_exists(const std::string & topic_name);
62-
void process_pointcloud(
63-
const std::string & topic_name, sensor_msgs::msg::PointCloud2::SharedPtr cloud);
66+
bool process_pointcloud(
67+
const std::string & topic_name, typename MsgTraits::PointCloudMessage::ConstSharedPtr cloud);
6468
void concatenate_callback();
6569

66-
ConcatenatedCloudResult concatenate_pointclouds(
67-
std::unordered_map<std::string, sensor_msgs::msg::PointCloud2::SharedPtr> topic_to_cloud_map);
70+
ConcatenatedCloudResult<MsgTraits> concatenate_pointclouds(
71+
std::unordered_map<std::string, typename MsgTraits::PointCloudMessage::ConstSharedPtr>
72+
topic_to_cloud_map);
6873

69-
std::unordered_map<std::string, sensor_msgs::msg::PointCloud2::SharedPtr>
74+
std::unordered_map<std::string, typename MsgTraits::PointCloudMessage::ConstSharedPtr>
7075
get_topic_to_cloud_map();
7176

7277
[[nodiscard]] CollectorStatus get_status() const;
@@ -77,15 +82,19 @@ class CloudCollector
7782
void reset();
7883

7984
private:
80-
std::shared_ptr<PointCloudConcatenateDataSynchronizerComponent> ros2_parent_node_;
81-
std::shared_ptr<CombineCloudHandler> combine_cloud_handler_;
85+
std::shared_ptr<PointCloudConcatenateDataSynchronizerComponentTemplated<MsgTraits>>
86+
ros2_parent_node_;
87+
std::shared_ptr<CombineCloudHandler<MsgTraits>> combine_cloud_handler_;
8288
rclcpp::TimerBase::SharedPtr timer_;
83-
std::unordered_map<std::string, sensor_msgs::msg::PointCloud2::SharedPtr> topic_to_cloud_map_;
89+
std::unordered_map<std::string, typename MsgTraits::PointCloudMessage::ConstSharedPtr>
90+
topic_to_cloud_map_;
8491
uint64_t num_of_clouds_;
8592
double timeout_sec_;
86-
bool debug_mode_;
8793
std::shared_ptr<CollectorInfoBase> collector_info_;
8894
CollectorStatus status_;
95+
bool debug_mode_;
8996
};
9097

9198
} // namespace autoware::pointcloud_preprocessor
99+
100+
#include "autoware/pointcloud_preprocessor/concatenate_data/cloud_collector.ipp"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
// Copyright 2024 TIER IV, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "autoware/pointcloud_preprocessor/concatenate_data/combine_cloud_handler.hpp"
16+
#include "autoware/pointcloud_preprocessor/concatenate_data/concatenate_and_time_sync_node.hpp"
17+
#include "autoware/pointcloud_preprocessor/concatenate_data/traits.hpp"
18+
19+
#include <rclcpp/rclcpp.hpp>
20+
21+
#include <memory>
22+
#include <string>
23+
#include <unordered_map>
24+
#include <utility>
25+
26+
namespace autoware::pointcloud_preprocessor
27+
{
28+
29+
template <typename MsgTraits>
30+
CloudCollector<MsgTraits>::CloudCollector(
31+
std::shared_ptr<PointCloudConcatenateDataSynchronizerComponentTemplated<MsgTraits>> &&
32+
ros2_parent_node,
33+
std::shared_ptr<CombineCloudHandler<MsgTraits>> & combine_cloud_handler, int num_of_clouds,
34+
double timeout_sec, bool debug_mode)
35+
: ros2_parent_node_(std::move(ros2_parent_node)),
36+
combine_cloud_handler_(combine_cloud_handler),
37+
num_of_clouds_(num_of_clouds),
38+
timeout_sec_(timeout_sec),
39+
status_(CollectorStatus::Idle),
40+
debug_mode_(debug_mode)
41+
{
42+
const auto period_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
43+
std::chrono::duration<double>(timeout_sec_));
44+
45+
timer_ =
46+
rclcpp::create_timer(ros2_parent_node_, ros2_parent_node_->get_clock(), period_ns, [this]() {
47+
if (status_ == CollectorStatus::Finished) return;
48+
concatenate_callback();
49+
});
50+
51+
timer_->cancel();
52+
}
53+
54+
template <typename MsgTraits>
55+
void CloudCollector<MsgTraits>::set_info(std::shared_ptr<CollectorInfoBase> collector_info)
56+
{
57+
collector_info_ = std::move(collector_info);
58+
}
59+
60+
template <typename MsgTraits>
61+
std::shared_ptr<CollectorInfoBase> CloudCollector<MsgTraits>::get_info() const
62+
{
63+
return collector_info_;
64+
}
65+
66+
template <typename MsgTraits>
67+
bool CloudCollector<MsgTraits>::topic_exists(const std::string & topic_name)
68+
{
69+
return topic_to_cloud_map_.find(topic_name) != topic_to_cloud_map_.end();
70+
}
71+
72+
template <typename MsgTraits>
73+
bool CloudCollector<MsgTraits>::process_pointcloud(
74+
const std::string & topic_name, typename MsgTraits::PointCloudMessage::ConstSharedPtr cloud)
75+
{
76+
if (status_ == CollectorStatus::Finished) {
77+
return false;
78+
}
79+
80+
if (status_ == CollectorStatus::Idle) {
81+
// Add first pointcloud to the collector, restart the timer
82+
status_ = CollectorStatus::Processing;
83+
timer_->reset();
84+
} else if (status_ == CollectorStatus::Processing) {
85+
// Check if the map already contains an entry for the same topic. This shouldn't happen if the
86+
// parameter 'lidar_timestamp_noise_window' is set correctly.
87+
if (topic_to_cloud_map_.find(topic_name) != topic_to_cloud_map_.end()) {
88+
RCLCPP_WARN_STREAM_THROTTLE(
89+
ros2_parent_node_->get_logger(), *ros2_parent_node_->get_clock(),
90+
std::chrono::milliseconds(10000).count(),
91+
"Topic '" << topic_name
92+
<< "' already exists in the collector. Check the timestamp of the pointcloud.");
93+
}
94+
}
95+
96+
// Check if the map already contains an entry for the same topic. This shouldn't happen if the
97+
// parameter 'lidar_timestamp_noise_window' is set correctly.
98+
if (topic_to_cloud_map_.find(topic_name) != topic_to_cloud_map_.end()) {
99+
RCLCPP_WARN_STREAM_THROTTLE(
100+
ros2_parent_node_->get_logger(), *ros2_parent_node_->get_clock(),
101+
std::chrono::milliseconds(10000).count(),
102+
"Topic '" << topic_name
103+
<< "' already exists in the collector. Check the timestamp of the pointcloud.");
104+
}
105+
topic_to_cloud_map_[topic_name] = cloud;
106+
if (topic_to_cloud_map_.size() == num_of_clouds_) {
107+
concatenate_callback();
108+
}
109+
110+
return true;
111+
}
112+
113+
template <typename MsgTraits>
114+
CollectorStatus CloudCollector<MsgTraits>::get_status() const
115+
{
116+
return status_;
117+
}
118+
119+
template <typename MsgTraits>
120+
void CloudCollector<MsgTraits>::concatenate_callback()
121+
{
122+
if (debug_mode_) {
123+
show_debug_message();
124+
}
125+
126+
// All pointclouds are received or the timer has timed out, cancel the timer and concatenate the
127+
// pointclouds in the collector.
128+
timer_->cancel();
129+
130+
auto concatenated_cloud_result = concatenate_pointclouds(topic_to_cloud_map_);
131+
132+
ros2_parent_node_->publish_clouds(std::move(concatenated_cloud_result), collector_info_);
133+
134+
combine_cloud_handler_->allocate_pointclouds();
135+
136+
status_ = CollectorStatus::Finished;
137+
}
138+
139+
template <typename MsgTraits>
140+
ConcatenatedCloudResult<MsgTraits> CloudCollector<MsgTraits>::concatenate_pointclouds(
141+
std::unordered_map<std::string, typename MsgTraits::PointCloudMessage::ConstSharedPtr>
142+
topic_to_cloud_map)
143+
{
144+
return combine_cloud_handler_->combine_pointclouds(topic_to_cloud_map);
145+
}
146+
147+
template <typename MsgTraits>
148+
std::unordered_map<std::string, typename MsgTraits::PointCloudMessage::ConstSharedPtr>
149+
CloudCollector<MsgTraits>::get_topic_to_cloud_map()
150+
{
151+
return topic_to_cloud_map_;
152+
}
153+
154+
template <typename MsgTraits>
155+
void CloudCollector<MsgTraits>::show_debug_message()
156+
{
157+
RCLCPP_WARN(ros2_parent_node_->get_logger(), "start show_debug_message timer with timeout=%f", timeout_sec_);
158+
auto time_until_trigger = timer_->time_until_trigger();
159+
std::stringstream log_stream;
160+
log_stream << std::fixed << std::setprecision(6);
161+
log_stream << "Collector's concatenate callback time: "
162+
<< ros2_parent_node_->get_clock()->now().seconds() << " seconds\n";
163+
164+
if (auto advanced_info = std::dynamic_pointer_cast<AdvancedCollectorInfo>(collector_info_)) {
165+
log_stream << "Advanced strategy:\n Collector's reference time min: "
166+
<< advanced_info->timestamp - advanced_info->noise_window
167+
<< " to max: " << advanced_info->timestamp + advanced_info->noise_window
168+
<< " seconds\n";
169+
} else if (auto naive_info = std::dynamic_pointer_cast<NaiveCollectorInfo>(collector_info_)) {
170+
log_stream << "Naive strategy:\n Collector's timestamp: " << naive_info->timestamp
171+
<< " seconds\n";
172+
}
173+
174+
log_stream << "Time until trigger: " << (time_until_trigger.count() / 1e9) << " seconds\n";
175+
176+
log_stream << "Pointclouds: [";
177+
std::string separator = "";
178+
for (const auto & [topic, cloud] : topic_to_cloud_map_) {
179+
log_stream << separator;
180+
log_stream << "[" << topic << ", " << rclcpp::Time(cloud->header.stamp).seconds() << "]";
181+
separator = ", ";
182+
}
183+
184+
log_stream << "]\n";
185+
186+
RCLCPP_WARN(ros2_parent_node_->get_logger(), "end show_debug_message timer with timeout=%f", timeout_sec_);
187+
RCLCPP_INFO(ros2_parent_node_->get_logger(), "%s", log_stream.str().c_str());
188+
}
189+
190+
template <typename MsgTraits>
191+
void CloudCollector<MsgTraits>::reset()
192+
{
193+
status_ = CollectorStatus::Idle; // Reset status to Idle
194+
topic_to_cloud_map_.clear();
195+
collector_info_ = nullptr;
196+
197+
if (timer_ && !timer_->is_canceled()) {
198+
timer_->cancel();
199+
}
200+
}
201+
202+
} // namespace autoware::pointcloud_preprocessor

0 commit comments

Comments
 (0)