Skip to content

Commit

Permalink
feat: move the polygon removing function to util and use it
Browse files Browse the repository at this point in the history
Signed-off-by: Tomohito Ando <tomohito.ando@tier4.jp>
  • Loading branch information
TomohitoAndo committed Aug 24, 2022
1 parent e503429 commit dd61182
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 65 deletions.
1 change: 1 addition & 0 deletions sensing/pointcloud_preprocessor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ include_directories(

ament_auto_add_library(pointcloud_preprocessor_filter SHARED
src/filter.cpp
src/utility/utilities.cpp
src/concatenate_data/concatenate_data_nodelet.cpp
src/crop_box_filter/crop_box_filter_nodelet.cpp
src/downsample_filter/voxel_grid_downsample_filter_nodelet.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define POINTCLOUD_PREPROCESSOR__NO_DETECTION_AREA_FILTER__NO_DETECTION_AREA_FILTER_HPP_

#include "pointcloud_preprocessor/filter.hpp"
#include "pointcloud_preprocessor/utility/utilities.hpp"

#include <lanelet2_extension/utility/message_conversion.hpp>
#include <lanelet2_extension/utility/query.hpp>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define POINTCLOUD_PREPROCESSOR__POLYGON_REMOVER__POLYGON_REMOVER_HPP_

#include "pointcloud_preprocessor/filter.hpp"
#include "pointcloud_preprocessor/utility/utilities.hpp"

#include <geometry_msgs/msg/polygon_stamped.hpp>
#include <sensor_msgs/point_cloud2_iterator.hpp>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2022 Tier IV, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef POINTCLOUD_PREPROCESSOR__UTILITY__UTILITIES_HPP_
#define POINTCLOUD_PREPROCESSOR__UTILITY__UTILITIES_HPP_

#include <geometry_msgs/msg/polygon.hpp>
#include <sensor_msgs/msg/point_cloud2.hpp>
#include <sensor_msgs/point_cloud2_iterator.hpp>

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polygon_2_algorithms.h>
#include <lanelet2_core/geometry/Polygon.h>
#include <pcl/pcl_base.h>
#include <pcl/point_types.h>
#include <pcl_conversions/pcl_conversions.h>

#include <vector>

using K = CGAL::Exact_predicates_inexact_constructions_kernel;
using PointCgal = K::Point_2;

namespace pointcloud_preprocessor::utils
{
/**
* @brief convert ROS polygon to CGAL polygon
*/
std::vector<PointCgal> to_cgal_polygon(
const geometry_msgs::msg::Polygon::ConstSharedPtr & polygon_in);

/**
* @brief convert lanelet polygon to CGAL polygon
*/
std::vector<PointCgal> to_cgal_polygon(const lanelet::BasicPolygon2d & polygon_in);

/**
* @brief remove points in the given polygon
*/
sensor_msgs::msg::PointCloud2 remove_polygon_cgal_from_cloud(
const sensor_msgs::msg::PointCloud2::ConstSharedPtr & cloud_in_ptr,
const std::vector<PointCgal> & polyline_polygon);

/**
* @brief remove points in the given polygon
*/
pcl::PointCloud<pcl::PointXYZ> remove_polygon_cgal_from_cloud(
const pcl::PointCloud<pcl::PointXYZ> & cloud_in, const std::vector<PointCgal> & polyline_polygon);

} // namespace pointcloud_preprocessor::utils

#endif // POINTCLOUD_PREPROCESSOR__UTILITY__UTILITIES_HPP_
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,6 @@

namespace
{
bool pointWithinLanelets(const Point2d & point, const lanelet::ConstPolygons3d & lanelets)
{
for (const auto & lanelet : lanelets) {
if (boost::geometry::within(point, lanelet::utils::to2D(lanelet).basicPolygon())) {
return true;
}
}

return false;
}

tier4_autoware_utils::Box2d calcBoundingBox(
const pcl::PointCloud<pcl::PointXYZ>::ConstPtr & input_cloud)
{
Expand All @@ -53,17 +42,15 @@ lanelet::ConstPolygons3d calcIntersectedPolygons(
}

pcl::PointCloud<pcl::PointXYZ> removePointsWithinPolygons(
const lanelet::ConstPolygons3d & polygons, const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud)
const pcl::PointCloud<pcl::PointXYZ>::Ptr & cloud_in, const lanelet::ConstPolygons3d & polygons)
{
pcl::PointCloud<pcl::PointXYZ> filtered_cloud;
filtered_cloud.header = cloud->header;

for (const auto & p : cloud->points) {
if (pointWithinLanelets(Point2d(p.x, p.y), polygons)) {
continue;
}
pcl::PointCloud<pcl::PointXYZ> filtered_cloud = *cloud_in;

filtered_cloud.points.push_back(p);
for (const auto & polygon : polygons) {
const auto lanelet_poly = lanelet::utils::to2D(polygon).basicPolygon();
const auto cgal_poly = pointcloud_preprocessor::utils::to_cgal_polygon(lanelet_poly);
filtered_cloud =
pointcloud_preprocessor::utils::remove_polygon_cgal_from_cloud(filtered_cloud, cgal_poly);
}

return filtered_cloud;
Expand Down Expand Up @@ -108,7 +95,7 @@ void NoDetectionAreaFilterComponent::filter(
calcIntersectedPolygons(bounding_box, no_detection_area_lanelets_);

// filter pointcloud by lanelet
const auto filtered_pc = removePointsWithinPolygons(intersected_lanelets, pc_input);
const auto filtered_pc = removePointsWithinPolygons(pc_input, intersected_lanelets);

// convert to ROS message
pcl::toROSMsg(filtered_pc, output);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ void PolygonRemoverComponent::filter(
void PolygonRemoverComponent::update_polygon(
const geometry_msgs::msg::Polygon::ConstSharedPtr & polygon_in)
{
polygon_cgal_ = polygon_geometry_to_cgal(polygon_in);
polygon_cgal_ = pointcloud_preprocessor::utils::to_cgal_polygon(polygon_in);
if (will_visualize_) {
marker_.ns = "";
marker_.id = 0;
Expand Down Expand Up @@ -131,49 +131,7 @@ sensor_msgs::msg::PointCloud2 PolygonRemoverComponent::remove_updated_polygon_fr
throw std::runtime_error("Polygon is not initialized. Please use `update_polygon` first.");
}

return remove_polygon_cgal_from_cloud(cloud_in, polygon_cgal_);
}

sensor_msgs::msg::PointCloud2 PolygonRemoverComponent::remove_polygon_cgal_from_cloud(
const sensor_msgs::msg::PointCloud2::ConstSharedPtr & cloud_in_ptr,
const std::vector<PointCgal> & polyline_polygon)
{
sensor_msgs::msg::PointCloud2 output;
pcl::PointCloud<pcl::PointXYZ> pcl_output;

sensor_msgs::msg::PointCloud2 transformed_cluster = *cloud_in_ptr;

for (sensor_msgs::PointCloud2ConstIterator<float> iter_x(transformed_cluster, "x"),
iter_y(transformed_cluster, "y"), iter_z(transformed_cluster, "z");
iter_x != iter_x.end(); ++iter_x, ++iter_y, ++iter_z) {
if (
CGAL::bounded_side_2(
polyline_polygon.begin(), polyline_polygon.end(), PointCgal(*iter_x, *iter_y), K()) ==
CGAL::ON_UNBOUNDED_SIDE) {
pcl::PointXYZ p;
p.x = *iter_x;
p.y = *iter_y;
p.z = *iter_z;
pcl_output.emplace_back(p);
}
}
pcl::toROSMsg(pcl_output, output);
output.header = cloud_in_ptr->header;
return output;
}
std::vector<PointCgal> PolygonRemoverComponent::polygon_geometry_to_cgal(
const geometry_msgs::msg::Polygon::ConstSharedPtr & polygon_in)
{
std::vector<PointCgal> polyline_polygon;
if (polygon_in->points.size() < 3) {
throw std::length_error("Polygon vertex count should be larger than 2.");
}
const auto & vertices_in = polygon_in->points;
polyline_polygon.resize(vertices_in.size());
std::transform(
polygon_in->points.begin(), polygon_in->points.end(), polyline_polygon.begin(),
[](const geometry_msgs::msg::Point32 & p_in) { return PointCgal(p_in.x, p_in.y); });
return polyline_polygon;
return pointcloud_preprocessor::utils::remove_polygon_cgal_from_cloud(cloud_in, polygon_cgal_);
}
} // namespace pointcloud_preprocessor

Expand Down
97 changes: 97 additions & 0 deletions sensing/pointcloud_preprocessor/src/utility/utilities.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright 2022 Tier IV, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "pointcloud_preprocessor/utility/utilities.hpp"

namespace pointcloud_preprocessor::utils
{
std::vector<PointCgal> to_cgal_polygon(
const geometry_msgs::msg::Polygon::ConstSharedPtr & polygon_in)
{
std::vector<PointCgal> polyline_polygon;
if (polygon_in->points.size() < 3) {
throw std::length_error("Polygon vertex count should be larger than 2.");
}

const auto & vertices_in = polygon_in->points;
polyline_polygon.resize(vertices_in.size());
std::transform(
polygon_in->points.begin(), polygon_in->points.end(), polyline_polygon.begin(),
[](const geometry_msgs::msg::Point32 & p_in) { return PointCgal(p_in.x, p_in.y); });
return polyline_polygon;
}

std::vector<PointCgal> to_cgal_polygon(const lanelet::BasicPolygon2d & polygon_in)
{
std::vector<PointCgal> polyline_polygon;
if (polygon_in.size() < 3) {
throw std::length_error("Polygon vertex count should be larger than 2.");
}

const auto & vertices_in = polygon_in;
polyline_polygon.resize(vertices_in.size());
std::transform(
polygon_in.cbegin(), polygon_in.cend(), polyline_polygon.begin(),
[](const Eigen::Matrix<double, 2, 1> & p_in) { return PointCgal(p_in.x(), p_in.y()); });
return polyline_polygon;
}

sensor_msgs::msg::PointCloud2 remove_polygon_cgal_from_cloud(
const sensor_msgs::msg::PointCloud2::ConstSharedPtr & cloud_in_ptr,
const std::vector<PointCgal> & polyline_polygon)
{
sensor_msgs::msg::PointCloud2 output;
pcl::PointCloud<pcl::PointXYZ> pcl_output;

sensor_msgs::msg::PointCloud2 transformed_cluster = *cloud_in_ptr;

for (sensor_msgs::PointCloud2ConstIterator<float> iter_x(transformed_cluster, "x"),
iter_y(transformed_cluster, "y"), iter_z(transformed_cluster, "z");
iter_x != iter_x.end(); ++iter_x, ++iter_y, ++iter_z) {
// check if the point is inside the polygon
if (
CGAL::bounded_side_2(
polyline_polygon.begin(), polyline_polygon.end(), PointCgal(*iter_x, *iter_y), K()) ==
CGAL::ON_UNBOUNDED_SIDE) {
pcl::PointXYZ p;
p.x = *iter_x;
p.y = *iter_y;
p.z = *iter_z;
pcl_output.emplace_back(p);
}
}
pcl::toROSMsg(pcl_output, output);
output.header = cloud_in_ptr->header;
return output;
}

pcl::PointCloud<pcl::PointXYZ> remove_polygon_cgal_from_cloud(
const pcl::PointCloud<pcl::PointXYZ> & cloud_in, const std::vector<PointCgal> & polyline_polygon)
{
pcl::PointCloud<pcl::PointXYZ> pcl_output;

for (const auto & p : cloud_in) {
// check if the point is inside the polygon
if (
CGAL::bounded_side_2(
polyline_polygon.begin(), polyline_polygon.end(), PointCgal(p.x, p.y), K()) ==
CGAL::ON_UNBOUNDED_SIDE) {
pcl_output.emplace_back(p);
}
}

return pcl_output;
} // namespace

} // namespace pointcloud_preprocessor::utils

0 comments on commit dd61182

Please sign in to comment.