Skip to content

Задача №3 Получение облака точек по RGBD данным

Облако точек — это набор данных в 3D-пространстве, где каждый объект или поверхность представлены множеством отдельных точек с координатами (X, Y, Z). Это основной формат для работы с 3D-данными в робототехнике, компьютерном зрении и дополненной реальности.

Разберем код детальнее, его можно найти по пути: /catkin_ws/src/applied_robotics-trackingcam3d_client_ros/src/convert_node.cpp

Основная его функция – преобразование карты глубины с модуля SVCAM в облако точек и публикует его в ROS.

  1. Подключение библиотек
#include <ros/ros.h\>

#include <cv_bridge/cv_bridge.h\> // для работы с изображениями OpenCV

#include <sensor_msgs/Image.h\> // для получения depth image

#include <sensor_msgs/CameraInfo.h\> // для параметров камеры

#include <sensor_msgs/PointCloud2.h\> // формат для 3D облака точек

#include <pcl_conversions/pcl_conversions.h\> // преобразование между
PCL и ROS

#include <pcl/point_types.h\>

#include <pcl/PCLPointCloud2.h\>

#include <pcl/conversions.h\>
  1. Глобальные переменные
ros::Publisher pub_point_cloud2; // публикатор облака точек

bool is_K_empty = 1; // флаг, что параметры камеры ещё не получены

double K[9]; // матрица внутренней калибровки камеры
  1. camera_info_callback()
void camera_info_callback(const sensor_msgs::CameraInfoConstPtr&camera_info_msg)

Подписан на топик camera_info.

Извлекает матрицу калибровки K:

[ fx 0 cx ]

[ 0 fy cy ]

[ 0 0 1 ]

Она нужна для восстановления 3D-координат из 2D.

  1. img_callback()
void img_callback(const sensor_msgs::ImageConstPtr &img_msg)

Подписан на топик с картой глубины image_rect.

Шаг 1: чтение глубины

unsigned short *depth_data = (unsigned short*)&img_msg->data[0];

глубина в формате 16UC1, единицы — миллиметры.

Шаг 2: преобразование в облако точек

z = depth / 1000.0; // перевод в метры

x = z * ((ux + width/2) - cx) / fx;

y = z * ((uy + height/2) - cy) / fy;

Цикл по пикселям:

(ux, uy) — координаты пикселя.

z — глубина.

x, y — пересчитанные координаты по формуле идеальной камеры-обскуры.

Шаг 3: публикация

pcl::toROSMsg(*cloud, point_cloud2);

point_cloud2.header.frame_id = "stereo_camera_first";

pub_point_cloud2.publish(point_cloud2);

Конвертация из PCL-облака в ROS-сообщение и публикация в /point_cloud.

  1. Функция main()
ros::Subscriber sub_img = n.subscribe(...);

ros::Subscriber sub_cmara_info = n.subscribe(...);

pub_point_cloud2 = n.advertise(...);

Подписка на:

/image_rect — карта глубины;

/camera_info — параметры камеры.

Публикация в:

/point_cloud — готовое облако точек.

Для запуска кейса необходимо остановить предыдущий и запустить новый с помощью команды:
rosrun trackingcam3d_client_ros convert_node

Чтобы увидеть данные необходимо в новом терминале прослушать топик «/point_cloud»

Для этого зайдем в Docker:

docker ps -a

docker exec –it <ID> /bin/bash

Далее требуется проинициализировать пространство:

cd

cd /catkin_ws

source devel/setup.bash

C помощью команды echо начнем прослушивать данные

rostopic echo /point_cloud

В терминале будут отображаться расстояние до каждого пикселя на изображении в байтах. В случае запуска данного кода на стационарном компьютере воспользуемся RViz для визуализации данных. В нем потребуется выставить параметры, как указано на рисунке 29.

Рис.29 Параметры в RViz для отображения облака точек

Также можно добавить видеопоток с камеры глубины и обычной камеры. В итоге при визуализации получим следующие результаты – рисунок 30.

Рис. 30 Облако точек совместно с видеопотоком камеры