Поскольку LiDAR может получить информацию о локальном облаке точек только за одно сканирование,,Чтобы получить глобальную информацию об облаке точек (например, о комнате, трехмерном объекте),это нужно выполнитьНесколько последовательных сканирований,и продолжайтеРегистрация облака точек。Поскольку облако точек, полученное при каждом сканировании, имеет независимую систему координат,поэтому Регистрация облака точекбыть выполненоПреобразование координат(вращать、Кастрюля),Интегрируйте облака точек в нескольких кадрах разных систем координат в одну систему координат.
Регистрация облака точекиметь Грубая регистрацияи Штрафная регистрациядва этапа,Грубая регистрацияРечь идет о регистрации, когда относительное положение облака точек совершенно неизвестно.,Найдите матрицу преобразования вращения и перемещения, которая сделает два облака точек относительно похожими.,Затем преобразуйте облако точек для регистрации в единую систему координат.,может быть Штрафная регистрация Обеспечьте хорошие начальные значения;иШтрафная регистрацияотносится к Грубая регистрацияна основе,Минимизируйте различия в пространственном положении между облаками точек.,Получите более точную матрицу преобразования вращения и перемещения.
общий Штрафная регистрация方法иметьICPИтерация до ближайшей точкиалгоритм(Iterative Cloest Point)иNDTПреобразование нормального распределенияалгоритм(Normal Distributions Трансформировать). Цель регистрации – получение параметров преобразования координат. **R( матрица вращения)** и Т (вектор перевода),Чтобы трехмерные данные, измеренные под разными углами обзора, можно было измерить с помощью Преобразования. Расстояние после координаты минимально, чтобы получить полную модель данных.
Конкретные этапы реализации регистрации облака точек следующие:
Самым важным во всем процессе регистрации является извлечение ключевых точек и описание функций ключевых точек, чтобы обеспечить точность и эффективность соответствующей оценки, чтобы обеспечить точность оценки матрицы преобразования твердого тела в последующем. процесс.
Преобразование твердого тела между двумя большими облаками точек (оба превышают 100 000 точек) можно определить с помощью алгоритма преобразования нормального распределения. (Чтобы проложить путь для алгоритмов картографирования и позиционирования Autoware NDT.)
Далее NDT используется для обработки регистрации данных облака точек двух помещений. Код выглядит следующим образом:
/*
Эксперименты с использованием преобразования нормального распределения для регистрации . Среди них room_scan1.pcd room_scan2.pcd Эти облака точек содержат 360 сканов одной и той же комнаты с разных точек зрения.
*/
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <boost/thread/thread.hpp>
#define BOOST_TYPEOF_EMULATION //Решение: в библиотеке облака точек pcl есть ошибка в typeof_impl.hpp
#include <pcl/registration/ndt.h> //Файл заголовка класса регистрации NDT (нормальное распределение)
#include <pcl/filters/approximate_voxel_grid.h> //Заголовочный файл класса фильтра (Эффект от использования фильтра сетки вокселей лучше)
#include <pcl/visualization/pcl_visualizer.h>
int main(int argc, char** argv)
{
// Загрузите первое облако точек сканирования данных комнаты в качестве цели.
pcl::PointCloud<pcl::PointXYZ>::Ptr target_cloud(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile<pcl::PointXYZ>("data/room_scan1.pcd", *target_cloud) == -1)
{
PCL_ERROR("Couldn't read file room_scan1.pcd \n");
return (-1);
}
std::cout << "Loaded " << target_cloud->size() << " data points from room_scan1.pcd" << std::endl;
// Загрузите данные второго облака точек сканирования, полученные с новой точки зрения, в качестве исходного облака точек.
pcl::PointCloud<pcl::PointXYZ>::Ptr input_cloud(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile<pcl::PointXYZ>("data/room_scan2.pcd", *input_cloud) == -1)
{
PCL_ERROR("Couldn't read file room_scan2.pcd \n");
return (-1);
}
std::cout << "Loaded " << input_cloud->size() << " data points from room_scan2.pcd" << std::endl;
//Приведенный выше код загружает два файла PCD для получения общего указателя. Последующая регистрация предназначена для завершения оценки матрицы преобразования опорной системы координат из исходного облака точек в целевое облако точек и получения преобразования второго набора. облаков точек в первый набор точек Матрица преобразования в облачную систему координат.
// Отфильтруйте входное отсканированное облако точек до 10 % от исходного размера, чтобы увеличить скорость сопоставления. Фильтруется только исходное облако точек, чтобы уменьшить его объем, а целевое облако точек не требует фильтрации.
//Потому что в NDTалгоритме статистический расчет структуры данных сетки вокселей, соответствующей целевому облаку точек, не использует одну точку, а использует статистические данные точек, содержащихся в каждой ячейке вокселя
pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::ApproximateVoxelGrid<pcl::PointXYZ> approximate_voxel_filter;
approximate_voxel_filter.setLeafSize(0.2, 0.2, 0.2);
approximate_voxel_filter.setInputCloud(input_cloud);
approximate_voxel_filter.filter(*filtered_cloud);
std::cout << "Filtered cloud contains " << filtered_cloud->size()
<< " data points from room_scan2.pcd" << std::endl;
// Инициализируйте объект нормального распределения (NDT)
pcl::NormalDistributionsTransform<pcl::PointXYZ, pcl::PointXYZ> ndt;
// Установите параметры, связанные с неразрушающим контролем, в соответствии с масштабом входных данных.
ndt.setTransformationEpsilon(0.01); //Устанавливаем минимальную разницу конвертации для условия завершения
ndt.setStepSize(0.1); //Устанавливаем максимальный размер шага для более тщательного поиска строк
ndt.setResolution(1.0); //Устанавливаем разрешение структуры сетки NDT (voxelgridcovariance)
//Вышеуказанные параметры работают лучше при использовании соотношения размеров комнаты, но если вам нужно обрабатывать более мелкие объекты, такие как скан чашки, вам необходимо уменьшить параметры.
//Установите максимальное количество совпадающих итераций. Этот параметр управляет максимальным количеством итераций, которые выполняет программа. Вообще говоря, программа оптимизации завершится при пороге преобразования эпсилон до этого предельного значения.
//Добавление максимального предела итераций может повысить надежность программы и предотвратить ее слишком долгое выполнение в неправильном направлении.
ndt.setMaximumIterations(35);
ndt.setInputSource(filtered_cloud); //Исходное облако точек
// Setting point cloud to be aligned to.
ndt.setInputTarget(target_cloud); //Целевое облако точек
// Установите грубые исходные результаты матрицы преобразования, полученные с помощью одометрии робота.
Eigen::AngleAxisf init_rotation(0.6931, Eigen::Vector3f::UnitZ());
Eigen::Translation3f init_translation(1.79387, 0.720047, 0);
Eigen::Matrix4f init_guess = (init_translation * init_rotation).matrix();
// Рассчитайте преобразование твердого тела, необходимое для сопоставления исходного облака точек с целевым облаком точек.
pcl::PointCloud<pcl::PointXYZ>::Ptr output_cloud(new pcl::PointCloud<pcl::PointXYZ>);
ndt.align(*output_cloud, init_guess);
//Выходное_облако в этом месте нельзя использовать в качестве окончательного преобразования исходного облака точек, поскольку облако точек фильтруется выше.
std::cout << "Normal Distributions Transform has converged:" << ndt.hasConverged()
<< " score: " << ndt.getFitnessScore() << std::endl;
// Преобразуйте входное облако точек для фильтрации с помощью созданного преобразования.
pcl::transformPointCloud(*input_cloud, *output_cloud, ndt.getFinalTransformation());
// Сохраните преобразованное исходное облако точек в качестве окончательного результата преобразования.
pcl::io::savePCDFileASCII("room_scan2_transformed.pcd", *output_cloud);
// Инициализация облака точек объекта предварительного просмотра
boost::shared_ptr<pcl::visualization::PCLVisualizer>
viewer_final(new pcl::visualization::PCLVisualizer("3D Viewer"));
viewer_final->setBackgroundColor(0, 0, 0); //Установим черный цвет фона
// Раскрасить целевое облако точек Предварительный просмотр (red).
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>
target_color(target_cloud, 255, 0, 0);
viewer_final->addPointCloud<pcl::PointXYZ>(target_cloud, target_color, "target cloud");
viewer_final->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,1, "target cloud");
// Раскрасьте преобразованное исходное облако точек. (green)Визуализация.
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>
output_color(output_cloud, 0, 255, 0);
viewer_final->addPointCloud<pcl::PointXYZ>(output_cloud, output_color, "output cloud");
viewer_final->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE,1, "output cloud");
// запускать Визуализация
viewer_final->addCoordinateSystem(1.0, "global"); //Отображение оси индикатора XYZ
viewer_final->initCameraParameters(); //Инициализируем параметры камеры
// Подождите, пока окно предварительного просмотра не закроется.
while (!viewer_final->wasStopped())
{
viewer_final->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
return (0);
}
Результаты бега следующие: