点群のダウンサンプリングの実装をご紹介します。
【ROS+PCL】点群のダウンサンプリング(VoxelGrid)
点群データを扱う際に、点の数を間引くこと(ダウンサンプリング)がよくあります。その理由は主に、計算負荷を減らすためです。
この記事では、点群のダウンサンプリングを、ROSとPCLで実装してみます。
目次
仕様
Subscribeした点群に対して、ダウンサンプリングを適用してPublishする仕様とします。
ダウンサンプリングのアルゴリズムには、VoxelGridフィルターを採用します。このアルゴリズムでは、入力点群を3次元のグリッドに区切って、各グリッドの重心点を出力します。複雑そうに聞こえますが、PCLを使えば簡単に実装することができます。
以下に、実装における、入出力とパラメータを記載します。
入力(Subscribe)
- sensor_msgs::PointCloud2:入力点群
出力(Publish)
- sensor_msgs::PointCloud2:ダウンサンプリングされた点群
パラメータ
- double:ボクセルの1辺の長さ [m]
環境構築
今回のプログラムを動かすためには、以下をインストールする必要があります。
- ROS
- PCL
(Dockerを使う場合)
Dockerを使う場合は、以下のDockerfileを例として参考にしてください。
########## Pull ########## FROM ros:noetic ########## ROS setup ########## RUN mkdir -p ~/catkin_ws/src && \ cd ~/catkin_ws && \ /bin/bash -c "source /opt/ros/noetic/setup.bash; catkin_make" && \ echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc && \ echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc && \ echo "export ROS_WORKSPACE=~/catkin_ws" >> ~/.bashrc ########## Requirements ########## RUN apt-get update && \ apt-get install -y \ libpcl-dev \ ros-noetic-pcl-conversions \ ros-noetic-rviz
実装
ディレクトリ構造
~/catkin_ws/src/pc_voxelgrid_filter/
┣ src/
┃ ┗ pc_voxelgrid_filter.cpp
┣ launch/
┃ ┗ pc_voxelgrid_filter.launch
┗ CMakeLists.txt
CMakeLists.txt
cmake_minimum_required(VERSION 3.0.2)
project(pc_downsampling)
add_compile_options(-std=c++14 -O2 -g -Wall)
find_package(catkin REQUIRED
roscpp
)
find_package(PCL)
catkin_package(
)
include_directories(
${catkin_INCLUDE_DIRS}
${PCL_INCLUDE_DIRS}
)
add_executable(pc_voxelgrid_filter src/pc_voxelgrid_filter.cpp)
target_link_libraries(pc_voxelgrid_filter
${catkin_LIBRARIES}
${PCL_LIBRARIES}
)
pc_voxelgrid_filter.cpp
#include <ros/ros.h>
#include <sensor_msgs/PointCloud2.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl/filters/voxel_grid.h>
class PcVoxelgridFilter{
private:
/*node handle*/
ros::NodeHandle nh_;
ros::NodeHandle nh_private_;
/*subscriber*/
ros::Subscriber sub_;
/*publisher*/
ros::Publisher pub_;
/*tool*/
pcl::VoxelGrid<pcl::PointXYZI> vg_;
/*buffer*/
pcl::PointCloud<pcl::PointXYZI>::Ptr pc_ {new pcl::PointCloud<pcl::PointXYZI>};
/*parameter*/
double leafsize_;
public:
PcVoxelgridFilter();
void callback(const sensor_msgs::PointCloud2ConstPtr& msg);
void filter(void);
void publication(std_msgs::Header header);
};
PcVoxelgridFilter::PcVoxelgridFilter()
: nh_private_("~")
{
std::cout << "----- pc_voxelgrid_filter -----" << std::endl;
/*parameter*/
nh_private_.param("leafsize", leafsize_, 0.5);
std::cout << "leafsize_ = " << leafsize_ << std::endl;
/*subscriber*/
sub_ = nh_.subscribe("/point_cloud", 1, &PcVoxelgridFilter::callback, this);
/*publisher*/
pub_ = nh_.advertise<sensor_msgs::PointCloud2>("/point_cloud/downsampled", 1);
}
void PcVoxelgridFilter::callback(const sensor_msgs::PointCloud2ConstPtr &msg)
{
pcl::fromROSMsg(*msg, *pc_);
filter();
publication(msg->header);
}
void PcVoxelgridFilter::filter(void)
{
vg_.setInputCloud(pc_);
vg_.setLeafSize(leafsize_, leafsize_, leafsize_);
vg_.filter(*pc_);
}
void PcVoxelgridFilter::publication(std_msgs::Header header)
{
if(!pc_->points.empty()){
sensor_msgs::PointCloud2 ros_pc;
pcl::toROSMsg(*pc_, ros_pc);
ros_pc.header = header;
pub_.publish(ros_pc);
}
}
int main(int argc, char** argv)
{
ros::init(argc, argv, "pc_voxelgrid_filter");
PcVoxelgridFilter pc_voxelgrid_filter;
ros::spin();
}
pc_voxelgrid_filter.launch
<launch> <!-- global rosparam --> <param name="use_sim_time" value="true"/> <!-- rosbag --> <node pkg="rosbag" type="play" name="player" args="--clock $(env HOME)/rosbag/demo.bag"/> <!-- rviz --> <node pkg="rviz" type="rviz" name="rviz" args="-d $(find pc_downsampling)/rviz_config/demo.rviz"/> <!-- main --> <node pkg="pc_downsampling" type="pc_voxelgrid_filter" name="pc_voxelgrid_filter" output="screen"> <remap from="/point_cloud" to="/demo_points"/> <remap from="/point_cloud/downsampled" to="/demo_points/downsampled"/> <param name="leafsize" type="double" value="0.1"/> </node> </launch>
使い方
ビルド
cd ~/catkin_ws catkin_make
実行
roslaunch pc_downsampling pc_voxelgrid_filter.launch
さいごに
ROSとPCLを使って、3次元点群のダウンサンプリングを実装してみました。
参考になれば幸いです。
Ad.
コメント