Предисловие
В этой статье мы покажем, как использовать CUDA-PCL для обработки облаков точек для достижения максимальной производительности. Поскольку PCL не может полностью использовать CUDA в Jetson, NVIDIA разработала несколько библиотек на основе CUDA с теми же функциями, что и PCL. Адрес кода: https://github.com/NVIDIA-AI-IOT/cuPCL.git (только динамические библиотеки и заголовочные файлы, автор сообщил, что исходный код в будущем будет открытым).
cuPCL содержит библиотеки для обработки облаков точек с использованием CUDA, а также примеры их использования. В проекте есть несколько подпапок, каждая из которых содержит: библиотеку, реализованную с помощью CUDA, и пример кода, который использует библиотеку и проверяет производительность и точность путем сравнения ее результатов с выводами PCL. Библиотека поддерживает Xavier, Orin. и Линукс х86.
Представление автора
Лэй Фан — старший инженер-программист CUDA в NVIDIA. В настоящее время он работает с китайской командой инженеров технической поддержки NVIDIA над разработкой решений для оптимизации производительности программного обеспечения с помощью CUDA.
Лили Ли, работает по связям с разработчиками в команде NVIDIA по робототехнике. В настоящее время она работает над разработкой робототехнических решений в экосистеме Jetson, помогая создавать лучшие практики.
Основное содержание
Многие пользователи Jetson выбирают LiDAR в качестве основного датчика для позиционирования и восприятия. LiDAR описывает пространственную среду вокруг автомобиля как набор трехмерных точек, называемых облаком точек. Облака точек сканируют поверхности окружающих объектов и имеют дальний радиус действия. Возможности высокой четкости. Характеристики точности делают его очень подходящим для расширенного восприятия препятствий, создания карт, алгоритмов позиционирования и планирования.
В этой статье представлена CUDA-PCL 1.0. Здесь мы в основном представляем три библиотеки PCL с ускорением CUDA:
1.CUDA-ICP
2.CUDA-Segmentation
3.CUDA-Filter
CUDA-ICP
В итеративной ближайшей точке (ICP) целевое облако точек или облако опорных точек фиксируется, а исходные точки преобразуются для наилучшего соответствия опорной точке. Алгоритм итеративно вычисляет необходимую матрицу преобразования, чтобы минимизировать метрику ошибки, которая обычно представляет собой расстояние от исходной точки до облака опорных точек, например сумму квадратов разностей между совпадающими парами координат. ICP — один из широко используемых алгоритмов для выравнивания 3D-моделей с учетом исходной предполагаемой позы, необходимой для жесткого преобразования. Преимущества ICP включают результаты сопоставления с высокой точностью, высокую устойчивость к различным инициализациям и т. д. Однако он потребляет много вычислительных ресурсов. Чтобы улучшить производительность ICP на Jetson, NVIDIA выпустила ICP на основе CUDA, который может заменить исходную версию ICP в библиотеке облаков точек (PCL). Следующие примеры кода являются примерами CUDA-ICP. Этот класс может быть создан и cudaICP.icp() выполнен напрямую.
cudaICP icpTest(nPCountM, nQCountM, stream);
icpTest.icp(cloud_source, nPCount,
float *cloud_target, int nQCount,
int Maxiterate, double threshold,
Eigen::Matrix4f &transformation_matrix, stream);
ICP вычисляет матрицу преобразования между двумя облаками точек:
source(P)* transformation =target(Q)
Поскольку лидар предоставляет облако точек с фиксированным числом, мы можем получить максимальное количество точек. И nPCountM, и nQCountM используются для выделения кэша для ICP.
class cudaICP
{
public:
/* nPCountM and nQCountM are the maximum of count for input clouds.
They are used to pre-allocate memory.
*/
cudaICP(int nPCountM, int nQCountM, cudaStream_t stream = 0);
~cudaICP(void);
/*
cloud_target = transformation_matrix *cloud_source
When the Epsilon of the transformation_matrix is less than threshold,
the function returns transformation_matrix.
Input:
cloud_source, cloud_target: Data pointer for the point cloud.
nPCount: Point number of the cloud_source.
nQCount: Point number of the cloud_target.
Maxiterate: Threshold for iterations.
threshold: When the Epsilon of the transformation_matrix is less than
threshold, the function returns transformation_matrix.
Output:
transformation_matrix
*/
void icp(float *cloud_source, int nPCount,
float *cloud_target, int nQCount,
int Maxiterate, double threshold,
Eigen::Matrix4f &transformation_matrix,
cudaStream_t stream = 0);
void *m_handle = NULL;
};
В таблице 2 показаны результаты сравнения производительности CUDA-ICP и PCL-ICP.
Состояние облака точек за два кадра до ICP
Состояние облака точек через два кадра после ICP
CUDA-Segmentation
Карта облака точек содержит множество наземных точек, что не только делает всю карту беспорядочной, но и усложняет классификацию, идентификацию и отслеживание последующих облаков точек препятствий, поэтому их необходимо сначала удалить. Удаление грунта может быть достигнуто посредством сегментации облака точек. Библиотека достигает этого с помощью подгонки консенсуса случайной выборки (Ransac) и нелинейной оптимизации. Ниже приведен пример кода для CUDA-сегментации. Сначала создайте экземпляр класса, инициализируйте параметры, а затем напрямую вызовите cudaSeg.segment, чтобы выполнить удаление грунта.
//Now Just support: SAC_RANSAC + SACMODEL_PLANE
std::vectorindexV;
cudaSegmentation cudaSeg(SACMODEL_PLANE, SAC_RANSAC, stream);
segParam_t setP;
setP.distanceThreshold = 0.01;
setP.maxIterations = 50;
setP.probability = 0.99;
setP.optimizeCoefficients = true;
cudaSeg.set(setP);
cudaSeg.segment(input, nCount, index, modelCoefficients);
for(int i = 0; i < nCount; i++)
{
if(index[i] == 1)
indexV.push_back(i);
}
CUDA-Segmentation сегментирует входные данные с помощью точек nCount с использованием некоторых параметров, index — это индекс входных данных, представляющий целевую плоскость, а modelCoefficients — группа коэффициентов плоскости.
typedef struct {
double distanceThreshold;
int maxIterations;
double probability;
bool optimizeCoefficients;
} segParam_t;
class cudaSegmentation
{
public:
//Now Just support: SAC_RANSAC + SACMODEL_PLANE
cudaSegmentation(int ModelType, int MethodType, cudaStream_t stream = 0);
~cudaSegmentation(void);
/*
Input:
cloud_in: Data pointer for point cloud
nCount: Count of points in cloud_in
Output:
Index: Data pointer that has the index of points in a plane from input
modelCoefficients: Data pointer that has the group of coefficients of the plane
*/
int set(segParam_t param);
void segment(float *cloud_in, int nCount,
int *index, float *modelCoefficients);
private:
void *m_handle = NULL;
};
В таблице 3 показано сравнение производительности CUDA-сегментации и PCL-сегментации.
На рисунках 3 и 4 показаны необработанные данные облака точек, за которыми следует обработанная версия, в которой сохраняются только облака точек, связанные с препятствиями. Этот пример типичен для обработки облаков точек, включая удаление грунта, удаление некоторых облаков точек и извлечение объектов, а также кластеризацию некоторых облаков точек.
Рисунок 3. Исходное облако точек CUDA-сегментации.
Рисунок 4. Облако точек, обработанное с помощью CUDA-сегментации.
CUDA-Filter
Фильтрация — одна из наиболее важных операций предварительной обработки перед обработкой облаков точек для сегментации, обнаружения и распознавания. Ограничения координат облака точек могут быть достигнуты посредством фильтрации, прямой фильтрации осей X, Y и Z облака точек. Фильтрация облака точек может ограничивать только ось Z или три оси координат X, Y и Z. CUDA-Filter в настоящее время поддерживает только PassThrough, но в будущем будет поддерживаться больше методов. Ниже приведен пример кода для примера CUDA-Filter, который создает экземпляр класса, инициализирует параметры, а затем напрямую вызывает функцию cudaFilter.filter.
cudaFilter filterTest(stream);
FilterParam_t setP;
FilterType_t type = PASSTHROUGH;
setP.type = type;
setP.dim = 2;
setP.upFilterLimits = 1.0;
setP.downFilterLimits = 0.0;
setP.limitsNegative = false;
filterTest.set(setP);
filterTest.filter(output, &countLeft, input, nCount);
CUDA-Filter использует параметры для фильтрации входных точек nCount, а затем после фильтрации с помощью CUDA выводит результаты с точками countLeft.
typedef struct {
FilterType_t type;
//0=x,1=y,2=z
int dim;
float upFilterLimits;
float downFilterLimits;
bool limitsNegative;
} FilterParam_t;
class cudaFilter
{
public:
cudaFilter(cudaStream_t stream = 0);
~cudaFilter(void);
int set(FilterParam_t param);
/*
Input:
source: data pointer for point cloud
nCount: count of points in cloud_in
Output:
output: data pointer which has points filtered by CUDA
countLeft: count of points in output
*/
int filter(void *output, unsigned int *countLeft, void *source, unsigned int nCount);
void *m_handle = NULL;
};
В Таблице 4 показано сравнение производительности CUDA-Filter и PCL-Filter.
На рисунках 5 и 6 показаны примеры фильтров PassThrough с ограничениями по оси X.
Рисунок 6. Исходное облако точек.
Рисунок 6. Облако точек, отфильтрованное ограничениями по оси X.
Сравнение других модулей
VoxelGrid
cuOctree
cuCluster
cuNDT
Ссылки по теме
https://github.com/NVIDIA-AI-IOT/cuPCL.git
https://developer.nvidia.com/blog/accelerating-lidar-for-robotics-with-cuda-based-pcl/
https://developer.nvidia.com/blog/detecting-objects-in-point-clouds-with-cuda-pointpillars/
ресурс
Совместное использование автономного вождения и позиционирования
Обнаружение движущихся объектов на основе оптического потока при автономном вождении
Калибровка внешних параметров камеры на основе семантической сегментации
Обзор методов автономного позиционирования транспортных средств в условиях высоких скоростей
Patchwork++: быстрый и надежный метод сегментации земли на основе облака точек.
PaGO-LOAM: наземная оптимизированная лидарная одометрия
Мультимодальный метод обнаружения и фильтрации края дороги
Платформа для одновременной калибровки, позиционирования и картографирования нескольких лидаров.
Извлечение, картографирование и долгосрочное позиционирование стержней в динамичной городской среде.
Коррекция искажений движения непериодического сканирующего лидара
Быстрая и тесно связанная разреженная прямая радиолокационная инерционно-визуальная одометрия
3D-обнаружение транспортных средств на основе камер и лидара низкого разрешения
Базовое введение в начало работы с ROS2
Автоматическая калибровка твердотельных лидаров и систем камер
Решение для позиционирования датчика с помощью лидара + GPS + IMU + спидометра на колесах
Больше статей можно посмотреть:Краткое изложение статей по истории обучения облакам точек
Обмен, связанный с SLAM и AR
Введение в принципы TOF-камеры
Введение в времяпролетную камеру глубины TOF
Оптимизированное решение F-LOAM с открытым исходным кодом: на основе оптимизированного SC-F-LOAM.
[Быстрое чтение статьи] AVP-SLAM: Семантический SLAM в автоматических парковочных системах
[Краткое чтение статей об облаках точек] StructSLAM: SLAM структурированных линейных объектов
Часто используемые 3D-камеры глубины
Обзор и оценка алгоритма монокулярной визуальной инерциальной навигации SLAM для AR-оборудования
Обзор SLAM (4) Laser and Vision Fusion SLAM
Система Semantic SLAM для реконструкции в реальном времени от Kimera