|
20 | 20 | #include <pcl/kdtree/kdtree_flann.h>
|
21 | 21 | #include <pcl/search/kdtree.h>
|
22 | 22 | #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 |
24 | 30 | #include <memory>
|
25 | 31 | #include <string>
|
| 32 | +#include <utility> |
| 33 | +#include <vector> |
26 | 34 |
|
27 | 35 | namespace autoware::compare_map_segmentation
|
28 | 36 | {
|
29 | 37 |
|
30 | 38 | VoxelBasedCompareMapFilterComponent::VoxelBasedCompareMapFilterComponent(
|
31 | 39 | const rclcpp::NodeOptions & options)
|
32 |
| -: Filter("VoxelBasedCompareMapFilter", options) |
| 40 | +: Filter("VoxelBasedCompareMapFilter", options), |
| 41 | + tf_buffer_(this->get_clock()), |
| 42 | + tf_listener_(tf_buffer_) |
33 | 43 | {
|
34 | 44 | // initialize debug tool
|
35 | 45 | {
|
@@ -62,6 +72,111 @@ VoxelBasedCompareMapFilterComponent::VoxelBasedCompareMapFilterComponent(
|
62 | 72 | RCLCPP_INFO(this->get_logger(), "tf_map_input_frame: %s", tf_input_frame_.c_str());
|
63 | 73 | }
|
64 | 74 |
|
| 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 | + |
65 | 180 | void VoxelBasedCompareMapFilterComponent::filter(
|
66 | 181 | const PointCloud2ConstPtr & input, [[maybe_unused]] const IndicesPtr & indices,
|
67 | 182 | PointCloud2 & output)
|
|
0 commit comments