Skip to content

Commit 0814577

Browse files
authored
fix(voxel_based_compare_map): temporary fix pointcloud transform lookup (#10299)
* fix(voxel_based_compare_map): temporary fix pointcloud transform lookup_time Signed-off-by: badai-nguyen <dai.nguyen@tier4.jp> * pre-commit Signed-off-by: badai-nguyen <dai.nguyen@tier4.jp> * chore: reduce timeout Signed-off-by: badai-nguyen <dai.nguyen@tier4.jp> * fix: misalignment when tranform back output Signed-off-by: badai-nguyen <dai.nguyen@tier4.jp> * fix: typo Signed-off-by: badai-nguyen <dai.nguyen@tier4.jp> --------- Signed-off-by: badai-nguyen <dai.nguyen@tier4.jp>
1 parent 059181c commit 0814577

File tree

3 files changed

+135
-8
lines changed
  • perception/autoware_compare_map_segmentation/src/voxel_based_compare_map_filter
  • sensing/autoware_pointcloud_preprocessor/include/autoware/pointcloud_preprocessor

3 files changed

+135
-8
lines changed

perception/autoware_compare_map_segmentation/src/voxel_based_compare_map_filter/node.cpp

+117-2
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,26 @@
2020
#include <pcl/kdtree/kdtree_flann.h>
2121
#include <pcl/search/kdtree.h>
2222
#include <pcl/segmentation/segment_differences.h>
23-
23+
#ifdef ROS_DISTRO_GALACTIC
24+
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>
25+
#include <tf2_sensor_msgs/tf2_sensor_msgs.h>
26+
#else
27+
#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
28+
#include <tf2_sensor_msgs/tf2_sensor_msgs.hpp>
29+
#endif
2430
#include <memory>
2531
#include <string>
32+
#include <utility>
33+
#include <vector>
2634

2735
namespace autoware::compare_map_segmentation
2836
{
2937

3038
VoxelBasedCompareMapFilterComponent::VoxelBasedCompareMapFilterComponent(
3139
const rclcpp::NodeOptions & options)
32-
: Filter("VoxelBasedCompareMapFilter", options)
40+
: Filter("VoxelBasedCompareMapFilter", options),
41+
tf_buffer_(this->get_clock()),
42+
tf_listener_(tf_buffer_)
3343
{
3444
// initialize debug tool
3545
{
@@ -62,6 +72,111 @@ VoxelBasedCompareMapFilterComponent::VoxelBasedCompareMapFilterComponent(
6272
RCLCPP_INFO(this->get_logger(), "tf_map_input_frame: %s", tf_input_frame_.c_str());
6373
}
6474

75+
// TODO(badai-nguyen): Temporary Implementation of input_indices_callback and convert_output_costly
76+
// functions; Delete this override function when autoware_utils refactor
77+
// (https://github.com/autowarefoundation/autoware_utils/pull/50) or new ManagedTransformBuffer lib
78+
// is deployed for autoware
79+
void VoxelBasedCompareMapFilterComponent::input_indices_callback(
80+
const sensor_msgs::msg::PointCloud2::ConstSharedPtr cloud, const PointIndicesConstPtr indices)
81+
{
82+
// If cloud is given, check if it's valid
83+
if (!isValid(cloud)) {
84+
RCLCPP_ERROR(this->get_logger(), "[input_indices_callback] Invalid input!");
85+
return;
86+
}
87+
// If indices are given, check if they are valid
88+
if (indices && !isValid(indices)) {
89+
RCLCPP_ERROR(this->get_logger(), "[input_indices_callback] Invalid indices!");
90+
return;
91+
}
92+
93+
// Check whether the user has given a different input TF frame
94+
tf_input_orig_frame_ = cloud->header.frame_id;
95+
PointCloud2ConstPtr cloud_tf;
96+
if (cloud->header.frame_id != tf_input_frame_) {
97+
RCLCPP_DEBUG(
98+
this->get_logger(), "[input_indices_callback] Transforming input dataset from %s to %s.",
99+
cloud->header.frame_id.c_str(), tf_input_frame_.c_str());
100+
// Save the original frame ID
101+
// Convert the cloud into the different frame
102+
PointCloud2 cloud_transformed;
103+
104+
try {
105+
// Lookup the transform from input frame to "map"
106+
geometry_msgs::msg::TransformStamped transform_stamped = tf_buffer_.lookupTransform(
107+
tf_input_frame_, tf_input_orig_frame_, rclcpp::Time(cloud->header.stamp),
108+
rclcpp::Duration::from_seconds(0.0));
109+
110+
// Transform the point cloud
111+
tf2::doTransform(*cloud, cloud_transformed, transform_stamped);
112+
cloud_tf = std::make_shared<PointCloud2>(cloud_transformed);
113+
} catch (tf2::TransformException & ex) {
114+
RCLCPP_WARN_THROTTLE(
115+
this->get_logger(), *this->get_clock(), 5000, "Could not transform pointcloud: %s",
116+
ex.what());
117+
cloud_tf = cloud; // Fallback to original data
118+
}
119+
} else {
120+
cloud_tf = cloud;
121+
}
122+
// Need setInputCloud () here because we have to extract x/y/z
123+
IndicesPtr vindices;
124+
if (indices) {
125+
vindices.reset(new std::vector<int>(indices->indices));
126+
}
127+
128+
computePublish(cloud_tf, vindices);
129+
}
130+
131+
bool VoxelBasedCompareMapFilterComponent::convert_output_costly(
132+
std::unique_ptr<PointCloud2> & output)
133+
{
134+
if (!output || output->data.empty() || output->fields.empty()) {
135+
RCLCPP_ERROR(this->get_logger(), "Invalid output point cloud!");
136+
return false;
137+
}
138+
if (
139+
pcl::getFieldIndex(*output, "x") == -1 || pcl::getFieldIndex(*output, "y") == -1 ||
140+
pcl::getFieldIndex(*output, "z") == -1) {
141+
RCLCPP_ERROR(this->get_logger(), "Input pointcloud does not have xyz fields");
142+
return false;
143+
}
144+
if (!tf_output_frame_.empty() && output->header.frame_id != tf_output_frame_) {
145+
auto cloud_transformed = std::make_unique<PointCloud2>();
146+
try {
147+
geometry_msgs::msg::TransformStamped transform_stamped = tf_buffer_.lookupTransform(
148+
tf_output_frame_, output->header.frame_id, rclcpp::Time(output->header.stamp),
149+
rclcpp::Duration::from_seconds(0.0));
150+
tf2::doTransform(*output, *cloud_transformed, transform_stamped);
151+
cloud_transformed->header.frame_id = tf_output_frame_;
152+
output = std::move(cloud_transformed);
153+
} catch (tf2::TransformException & e) {
154+
RCLCPP_WARN_THROTTLE(
155+
this->get_logger(), *this->get_clock(), 5000, "Could not transform pointcloud: %s",
156+
e.what());
157+
return false;
158+
}
159+
}
160+
161+
if (tf_output_frame_.empty() && output->header.frame_id != tf_input_orig_frame_) {
162+
auto cloud_transformed = std::make_unique<PointCloud2>();
163+
try {
164+
geometry_msgs::msg::TransformStamped transform_stamped = tf_buffer_.lookupTransform(
165+
tf_input_orig_frame_, output->header.frame_id, rclcpp::Time(output->header.stamp),
166+
rclcpp::Duration::from_seconds(0.0));
167+
tf2::doTransform(*output, *cloud_transformed, transform_stamped);
168+
cloud_transformed->header.frame_id = tf_input_orig_frame_;
169+
output = std::move(cloud_transformed);
170+
} catch (tf2::TransformException & e) {
171+
RCLCPP_WARN_THROTTLE(
172+
this->get_logger(), *this->get_clock(), 5000, "Could not transform pointcloud: %s",
173+
e.what());
174+
return false;
175+
}
176+
}
177+
return true;
178+
}
179+
65180
void VoxelBasedCompareMapFilterComponent::filter(
66181
const PointCloud2ConstPtr & input, [[maybe_unused]] const IndicesPtr & indices,
67182
PointCloud2 & output)

perception/autoware_compare_map_segmentation/src/voxel_based_compare_map_filter/node.hpp

+13
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,29 @@ namespace autoware::compare_map_segmentation
2727
{
2828
class VoxelBasedCompareMapFilterComponent : public autoware::pointcloud_preprocessor::Filter
2929
{
30+
using PointCloud2 = sensor_msgs::msg::PointCloud2;
31+
using PointCloud2ConstPtr = sensor_msgs::msg::PointCloud2::ConstSharedPtr;
32+
33+
using PointIndices = pcl_msgs::msg::PointIndices;
34+
using PointIndicesPtr = PointIndices::SharedPtr;
35+
using PointIndicesConstPtr = PointIndices::ConstSharedPtr;
36+
3037
protected:
3138
void filter(
3239
const PointCloud2ConstPtr & input, const IndicesPtr & indices, PointCloud2 & output) override;
40+
void input_indices_callback(
41+
const PointCloud2ConstPtr cloud, const PointIndicesConstPtr indices) override;
42+
43+
bool convert_output_costly(std::unique_ptr<PointCloud2> & output) override;
3344

3445
private:
3546
// pcl::SegmentDifferences<pcl::PointXYZ> impl_;
3647
std::unique_ptr<VoxelGridMapLoader> voxel_grid_map_loader_;
3748
rclcpp::Subscription<PointCloud2>::SharedPtr sub_map_;
3849
double distance_threshold_;
3950
bool set_map_in_voxel_grid_;
51+
tf2_ros::Buffer tf_buffer_;
52+
tf2_ros::TransformListener tf_listener_;
4053

4154
public:
4255
PCL_MAKE_ALIGNED_OPERATOR_NEW

sensing/autoware_pointcloud_preprocessor/include/autoware/pointcloud_preprocessor/filter.hpp

+5-6
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,11 @@ class Filter : public rclcpp::Node
206206
* \param input the input point cloud dataset.
207207
* \param indices a pointer to the vector of point indices to use.
208208
*/
209-
void computePublish(const PointCloud2ConstPtr & input, const IndicesPtr & indices);
209+
virtual void computePublish(const PointCloud2ConstPtr & input, const IndicesPtr & indices);
210+
/** \brief PointCloud2 + Indices data callback. */
211+
virtual void input_indices_callback(
212+
const PointCloud2ConstPtr cloud, const PointIndicesConstPtr indices);
213+
virtual bool convert_output_costly(std::unique_ptr<PointCloud2> & output);
210214

211215
//////////////////////
212216
// from PCLNodelet //
@@ -279,16 +283,11 @@ class Filter : public rclcpp::Node
279283
std::shared_ptr<ExactTimeSyncPolicy> sync_input_indices_e_;
280284
std::shared_ptr<ApproximateTimeSyncPolicy> sync_input_indices_a_;
281285

282-
/** \brief PointCloud2 + Indices data callback. */
283-
void input_indices_callback(const PointCloud2ConstPtr cloud, const PointIndicesConstPtr indices);
284-
285286
/** \brief Get a matrix for conversion from the original frame to the target frame */
286287
bool calculate_transform_matrix(
287288
const std::string & target_frame, const sensor_msgs::msg::PointCloud2 & from,
288289
TransformInfo & transform_info /*output*/);
289290

290-
bool convert_output_costly(std::unique_ptr<PointCloud2> & output);
291-
292291
// TODO(sykwer): Temporary Implementation: Remove this interface when all the filter nodes conform
293292
// to new API.
294293
void faster_input_indices_callback(

0 commit comments

Comments
 (0)