Pointcloud란?
- ROS 에서 다루는 다양한 메시지 타입 중 점들의 집합에 대한 정보를 담고 있는 메시지
- 주로 Pointcloud2 를 통해 이 데이터를 얻어내고, 이것을 처리하기가 조금 어렵다는 게 지난 포스트 내용
- 그걸 다루는 라이브러리에 대해 알아보자.
1) PCL library 설치하기
- Pointcloud 정보를 다루기 위해서 필요한 라이브러리이다.
- 설치 명령 (Ubuntu 20.04 / ROS noetic 기준)
sudo apt-get install libpcl-dev
sudo apt-get install ros-noetic-pcl-conversions ros-noetic-pcl-ros
2) PCL library 활용하기
- 데이터를 받아서 활용할 방안은 무궁무진하지만, 단순한 예시를 보여주고자 한다.
- Pointcloud2 에서 얻어진 점의 위치를 알아내고, 이를 Down sampling 하고, Markersetarray 에 담아서 보여준다.
Code 설명
1) pcl_conversion 을 통해 받은 msg (pointcloud2) 를 cloud 로 치환한다.
2) Voxel Grid Filter 를 통해 Pointcloud 데이터를 다운샘플링한다. (Leaf size : 0.1 --> 0.1 m^3 안에 점이 여러 개 있으면 그 것들의 평균지점을 하나만 남긴다)
3) 다시 Pointcloud2 output 으로 옮기고, 좌표를 알아내기 위해 Pointcloud output_dust 로 옮긴다.
4) 옮긴 데이터를 marker 형태로 표현하고, markersetarray 에 넣어준다.
5) 이전에 받은 데이터가 남아있지 않도록, 이전에 받은 cloud 정보량이 더 많으면 더 많은 만큼은 그 marker를 삭제해준다.
이 코드를 다른 package 의 src 폴더에 넣고, compile 해야 한다. 주의할 점은 아래와 같이 CMakeList 도 수정을 해줘야 한다. pcl_conversions, pcl_ros 를 find_package 에 넣어줘야 함. (add_executable 설명은 따로 하지 않았음)
#include <ros/ros.h>
#include <iostream>
#include <math.h>
#include <sensor_msgs/PointCloud2.h>
#include <visualization_msgs/Marker.h>
#include <visualization_msgs/MarkerArray.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/filters/voxel_grid.h>
#include <tf/transform_listener.h>
#include <tf/tf.h>
#include <vector>
using namespace std;
pcl::PointCloud<pcl::PointXYZ> output_dust;
ros::Publisher marker_pub;
int former_sz = 0;
void cloud_cb(const sensor_msgs::PointCloud2ConstPtr& msg)
{
const sensor_msgs::PointCloud2 cloud_in, cloud_out;
tf::TransformListener listener;
// Container for original & filtered data
pcl::PCLPointCloud2* cloud = new pcl::PCLPointCloud2;
pcl::PCLPointCloud2ConstPtr cloudPtr(cloud);
pcl::PCLPointCloud2 cloud_filtered;
// Convert to PCL data type
pcl_conversions::toPCL(*msg, *cloud);
// Perform the actual filtering
pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
sor.setInputCloud (cloudPtr);
sor.setLeafSize (0.1, 0.1, 0.1); // unit : m
sor.filter (cloud_filtered);
// Convert to ROS data type
sensor_msgs::PointCloud2 output;
pcl_conversions::fromPCL(cloud_filtered, output);
pcl::fromROSMsg(output, output_dust);
// Publish Markersetarray
int sz;
visualization_msgs::MarkerArray markers_bbox;
visualization_msgs::Marker marker;
uint32_t shape = visualization_msgs::Marker::CUBE;
if (former_sz > output_dust.size()){
sz = former_sz;
}
else{
sz = output_dust.size();
}
for (int i = 0; i < sz; i++){
marker.ns = "basic_shapes";
marker.id = i;
marker.type = shape;
if ( i > output_dust.size())
marker.action = visualization_msgs::Marker::DELETE;
else
marker.action = visualization_msgs::Marker::ADD;
marker.pose.position.x = output_dust[i].x;
marker.pose.position.y = output_dust[i].y;
marker.pose.position.z = output_dust[i].z;
marker.pose.orientation.x = 0.0;
marker.pose.orientation.y = 0.0;
marker.pose.orientation.z = 0.0;
marker.pose.orientation.w = 1.0;
marker.scale.x = 0.1;
marker.scale.y = 0.1;
marker.scale.z = 0.1;
marker.color.r = 0.0f;
marker.color.g = 1.0f;
marker.color.b = 0.0f;
marker.color.a = 1.0;
marker.header.frame_id = "camera_depth_optical_center_link";
markers_bbox.markers.push_back(marker);
}
marker_pub.publish(markers_bbox);
former_sz = output_dust.size();
}
int main (int argc, char** argv)
{
// Initialize ROS
ros::init (argc, argv, "my_pcl_tutorial");
ros::NodeHandle nh;
// Create a ROS subscriber for the input point cloud
ros::Subscriber sub = nh.subscribe ("/firefly/vi_sensor/camera_depth/depth/points", 1, cloud_cb);
marker_pub = nh.advertise<visualization_msgs::MarkerArray> ("out",1);
// Spin
ros::spin();
}
3) 실행 화면
총 4개의 코드를 실행해야 한다.
roslaunch rotors_gazebo mav_hovering_example_with_vi_sensor.launch
rosrun beginner_tutorials marker_array_node // 위에서 설명한 새로 추가한 코드
rosrun tf2_ros static_transform_publisher 0 0 0 0 0 0 1 /firefly/vi_sensor/camera_depth_optical_center_link camera_depth_optical_center_link
rviz
- RVIZ 에서 topic 을 추가하고, global fixed frame 은 world 로 수정한다.
- 아래와 같이 보인다. 복잡한 과정을 거친 것 같지만 그냥 Pointcloud 를 cube 모양으로 바꾼 것 뿐이다.
- 데이터를 활용해서 뭔가 하기 위한 준비 단계 수준~
끝~
'ROS' 카테고리의 다른 글
[ros 설치 오류] Could NOT find random_numbers (0) | 2023.07.18 |
---|---|
ROS 강의 - (9) Octomap에 대해 알아보기 (0) | 2023.05.13 |
ROS 강의 - (7) Pointcloud, Pointcloud2에 대해 알아보기 (1) (0) | 2023.05.07 |
ROS 강의 - (6) TF 에 대해 알아보기 (0) | 2023.05.04 |
ROS 강의 - (5) RotorS 사용해보기 (0) | 2023.04.15 |