ALGORITMO ODOMÉTRICO LOAM INNOVADO DESDE C++ SIN ROBOT OPERATIVE SYSTEM
Víctor
Joel Pinargote Bravo1
vpinargote@espam.edu.ec
Alfonso
Tomás Loor Vera1
aloor@espam.edu.ec
Edwin Wellington Moreira Santos1
edwinmoreira97@espam.edu.ec
Luisa
Anabel Palacios López2
luisa.palacios@unesum.edu.ec
1Escuela
Superior Politécnica Agropecuaria de Manabí Manuel Félix López, ESPAM MFL.
Carrera de Computación. Calceta, Ecuador.
2Universidad
Estatal del Sur de Manabí, UNESUM. Carrera de Ingeniería Ambiental. Jipijapa,
Ecuador.
DOI: https://doi.org/10.56124/encriptar.v7i14.006
Resumen
La
odometría desempeña un papel crucial en la estimación de la posición relativa
de un robot móvil, lo que motiva este artículo a implementar el método
utilizado en el algoritmo LOAM, desarrollado dentro del marco de ROS (Robot
Operating System). El enfoque de este trabajo se centra en el análisis del
algoritmo LOAM y su posterior implementación en C++ sin la dependencia de ROS,
empleando bibliotecas como PCL (Point Cloud Library), Eigen 3.0, y algunas
funcionalidades adaptadas para su uso en C++, como ROS::tf. Para llevar a cabo
el análisis del algoritmo LOAM, se aplicó un proceso de ingeniería inversa y se
revisó la literatura existente, basándose en los artículos publicados por los
autores del algoritmo mencionado anteriormente. Asimismo, se examinaron los
métodos de Visual SLAM (Simultaneous Localization and Mapping) con el fin de
compararlos y proponer posibles mejoras y observaciones en el algoritmo
estudiado y posteriormente implementado. Se demostró que el algoritmo LOAM
presenta una mayor eficiencia en tramos rectos en comparación con las curvas,
debido a la ausencia de un sensor de medida inercial que sea capaz de compensar
la rotación del láser en las curvas. Por lo tanto, se recomienda realizar un
análisis segmentado en escenarios con diversos tipos de recorridos para mejorar
los resultados y reducir el error total del experimento.
Palabras
clave: odometría, algoritmo
LOAM, robot móvil.
LOAM ODOMETRIC ALGORITHM INNOVATED FROM C++ WITHOUT ROBOT OPERATIVE
SYSTEM
ABSTRACT
Odometry
plays a crucial role in estimating the relative position of a mobile robot,
which motivates this article to implement the method used in the LOAM
algorithm, developed within the ROS (Robot Operating System) framework. The
focus of this work is on the analysis of the LOAM algorithm and its subsequent
implementation in C++ without dependency on ROS, using libraries such as PCL
(Point Cloud Library), Eigen 3.0, and some functionalities adapted for use in
C++, such as ROS. ::tf. To carry out the analysis of the LOAM algorithm, a
reverse engineering process was applied and the existing literature was
reviewed, based on the articles published by the authors of the aforementioned
algorithm. Likewise, Visual SLAM (Simultaneous Localization and Mapping) methods
were examined in order to compare them and propose
possible improvements and observations in the algorithm studied and
subsequently implemented. It was shown that the LOAM algorithm has greater
efficiency in straight sections compared to curves, due to the absence of an
inertial measurement sensor that is capable of compensating for the rotation of
the laser in curves. Therefore, it is recommended to perform a segmented
analysis in scenarios with various types of paths to improve the results and
reduce the total error of the experiment.
Keywords:
odometry, LOAM algorithm, mobile robot.
1. Introducción
En la actualidad el
área de la robótica y la conducción autónoma convergen, debido a que algunos de
los algoritmos más eficientes de conducción independiente se implementan en
ROS; siendo este el punto de partida para múltiples proyectos e
investigaciones, lo que representa una problemática para ciertos grupos de
desarrolladores e investigadores, debido a que muchos tienen la necesidad de
empezar a investigar en esa área de la tecnología sin usar el denominado Robot
Operative System (Pinargote, 2017).
La solución que aquí se
presenta proporciona un cálculo de Odometría Lidar en tiempo real con el uso de
elementos computacionales de última generación, ese algoritmo de cálculo puede
ser utilizado como un sensor independiente sin la necesidad de añadir otro,
aunque también integra funciones para usar un IMU (Inertial Measurement Unit);
por lo expuesto se enuncia como objetivo del presente artículo el de argumentar
la implementación del algoritmo de Odometría del LOAM en C++ sin usar ROS para
obtener un array que almacene la ruta desplazada por el sensor (Zhang y Singh,
2014).
Este artículo proviene
de una investigación previa titulada “Implementación del algoritmo de odometría
LOAM con C++ en Linux” el cual se enmarca en el ámbito de la robótica móvil y
la conducción autónoma, dado que surge de la necesidad de conseguir una localización
sin depender de los Sistemas de Posicionamiento Global (GPS). Esto se debe a
que existen entornos, como túneles y otros espacios subterráneos, donde los GPS
no tienen cobertura o su señal es deficiente (Pinargote, 2017).
No obstante, si bien
hoy existen múltiples algoritmos que tratan la problemática del SLAM
(Simultaneous Localization and Mapping), tales como los de Odometría Visual o
Lidar, entre otros, la visual es el proceso mediante el que se hace una
estimación del movimiento realizado por un robot móvil o por un vehículo a
partir de los datos obtenidos por el sistema de visión del mismo, mientras que
la Odometría Lidar, aunque posee el mismo objetivo, parte de los datos
capturados por un sistema de scanner láser 3D o 2D de manera indistinta.
Hoy, la mayoría de los
algoritmos de odometría visual propuestos no funcionan en tiempo real, sino que
sus resultados se obtienen principalmente de manera off-line, ya que las
imágenes se capturan y luego se procesan. Otros algoritmos operan a una frecuencia
de captura de imágenes muy baja, lo que exige un movimiento muy lento del
robot. Esto se debe a que los algoritmos de odometría visual actuales requieren
cálculos muy complejos y una alta carga computacional, lo cual implica que,
para ejecutarse correctamente, a menudo se necesitan equipos informáticos y
sistemas de visión avanzados, lo que incrementa significativamente los costos.
Por esta razón, se optó por utilizar el algoritmo V-LOAM, ya que es uno de los
más confiables en este campo según el ranking de KITTI Vision Benchmark Suite.
2. Metodología (Materiales y métodos)
La metodología seguida
durante el desarrollo de la investigación de este artículo es una estructura
planeada previamente a la realización del trabajo y se basó en los principios
científicos necesarios para un trabajo de este tipo. Primero, se realizó una
revisión en profundidad de la literatura actualizada sobre la temática, con un
foco de atención en el estudio de los diversos trabajos de localización basados
en el cálculo de la Odometría Visual y Odometría Lidar; de lo que fueron
estudiadas las ventajas e inconvenientes de cada una de las propuestas que,
hasta el momento se han realizado y tienen su fundamento en lo anteriormente
abordado.
Posteriormente, se optó
por un método de odometría Lidar que se consideró apropiado debido a su
robustez conceptual y procedimental. Se llevó a cabo un estudio detallado de
cada uno de los componentes y etapas del algoritmo. Una vez que se tuvo un
algoritmo de cálculo de odometría Lidar disponible, se procedió a su
implementación en C++, haciendo uso de bibliotecas como PCL, Eigen3 y otras
como ROSS::tf. Cabe destacar que esta última se adaptó para su uso sin ROS, lo
cual se explicará más adelante.
2.1. Herramientas de software utilizadas
En primer lugar, a lo
largo de este proyecto se consideró útil trabajar con la biblioteca de gran
escala Point Cloud Library (PCL), la cual se distribuye bajo una licencia de
Berkeley Software Distribution (BSD) y es un software de código abierto multi-plataforma,
que funciona con Linux, Android, Windows, iOs y MacOS.
Para simplificar, el
desarrollo PCL está compartimentado en una serie de bibliotecas de menor tamaño
que pueden ser compiladas cada una por su parte. Esta modularidad es importante
para su distribución en plataformas con restricciones de tamaño o cómputo
(Tombari, 2013). De ella, los módulos más importantes a tomar en cuenta
fueron:
• Filters: Limpia las
nubes de puntos 3D al eliminar el ruido y los puntos aislados para mejorar la
calidad de los datos.
• Features: Analiza y
calcula las características tridimensionales de una nube de puntos para
identificar patrones o elementos de interés en el entorno.
• Keypoints: Identifica
y marca los puntos de interés significativos en una imagen o nube de puntos que
pueden ser útiles para el análisis o la toma de decisiones.
• Registration: Fusiona
múltiples conjuntos de datos en un único modelo global para obtener una visión
más completa del entorno tridimensional.
• Kd-tree: Utiliza una
estructura de árbol kd para encontrar de manera eficiente los puntos más
cercanos en una nube de puntos, facilitando operaciones de búsqueda.
• Octree: Genera un
árbol jerárquico a partir de una nube de puntos, permitiendo la organización
espacial, la reducción de la resolución y la realización de operaciones de
búsqueda de manera eficiente.
• Segmentation: Agrupa
los puntos de una nube en clusters para identificar objetos individuales o
regiones de interés.
• Sample_consensus: Utiliza algoritmos como
RANSAC y modelos geométricos para estimar relaciones espaciales entre puntos y
ajustar modelos como planos y cilindros.
• Surface: Reconstruye
las superficies originales a partir de los datos de escaneo 3D para obtener una
representación detallada del entorno.
• Range_image: Analiza
y opera con imágenes de profundidad para representar la distancia entre objetos
en un entorno tridimensional.
• Io: Lee y guarda
nubes de puntos desde archivos en formato PCD para facilitar el almacenamiento
y el intercambio de datos 3D.
• Display: Muestra de
manera visual los resultados obtenidos a partir de las nubes de datos 3D para
facilitar la interpretación y el análisis de los datos (PCL, 2023).
En segundo lugar, se
utilizó Eigen, una biblioteca de C++ de alto nivel basada en plantillas para
álgebra lineal, operaciones con matrices y vectores, transformaciones
geométricas, solucionadores numéricos y algoritmos relacionados. Esta
biblioteca es de código abierto y está licenciada bajo MPL2 desde la versión
3.1.1; se implementa utilizando la técnica de meta programación de plantillas
de expresión, lo que significa que genera árboles de expresión en tiempo de
compilación y concibe un código personalizado para evaluarlos. Con el uso de
plantillas de expresión y un modelo de coste de operaciones en coma flotante,
la biblioteca realiza su propio desenrollado y vectorización de bucle (Eigen,
2016).
Finalmente, se empleó
el paquete Tf, que posibilita al usuario rastrear múltiples marcos de
coordenadas a lo largo del tiempo. Este paquete mantiene la relación entre los
marcos de coordenadas en una estructura de árbol temporal y permite al usuario
transformar puntos, vectores y otros elementos entre dos marcos de coordenadas
en cualquier momento deseado. Aunque este paquete forma parte de ROS, puede ser
adaptado e implementado sin necesidad de utilizar ROS, dado que está escrito en
C++ y sus dependencias son fácilmente accesibles (ROS, 2021).
2.2. Herramientas hardware utilizadas
Sobre este particular,
el nuevo sensor PUCK ™ (VLP-16) de Velodyne es el producto más pequeño, nuevo y
avanzado de la gama de productos 3D Lidar de Velodyne. Es mucho más rentable
que otros de similar precio; además que conserva las características claves de
los avances de Velodyne en Lidar; esto es, tiempo real, distancia 360°, 3D y
mediciones de reflectividad calibrada (PUCK, 2023). Tiene las siguientes especificaciones: un
peso máximo de 830 gramos, un alcance máximo de 100 metros, una precisión de ±2
centímetros, una capacidad para capturar 300,000 puntos por segundo, un campo
de visión horizontal de 360 grados, un campo de visión vertical de ±15 grados,
16 haces (canales) y una tasa de rotación que varía entre 5 y 20 hercios.
3. Resultados
(análisis e interpretación de los resultados)
Al analizar el algoritmo, se revela que la estimación del movimiento y la cartografía utilizando la nube de puntos de un escáner láser giratorio puede ser complicada debido a la necesidad de recuperar el movimiento y corregir la distorsión del mismo en la nube Lidar. La solución propuesta aborda este desafío al dividirlo y resolverlo a través de dos algoritmos que funcionan simultáneamente: la odometría Lidar se encarga del procesamiento más elaborado para estimar la velocidad a una frecuencia más alta, en contraste y el mapeo Lidar ejecuta un procesamiento menos complejo para crear mapas a una frecuencia más baja. La colaboración entre estos dos algoritmos permite una estimación precisa del movimiento y la generación de mapas en tiempo real.
Al implementar ese algoritmo en otro sistema operativo se obtienen resultados muy parecidos al original puesto que se identifican con éxito los puntos claves en la fase de ScanRegistration como se muestra (Figura 1) y en la fase de detección de puntos clave (Figura 2), lo cual concluye en un buena odometría (Figura 3); no obstante, en cuanto al coste computacional no se obtuvieron buenos resultados, puesto que el algoritmo fue diseñado para ejecutar cuatro procesos en paralelo y enviar mensajes por cada frame, lo que resulta complicado en C++, puesto que es necesario utilizar hilos para lograr ese objetivo; y esto concluye en un aumento en la carga de ejecución y, consecuentemente, una ralentización de la ejecución del programa.
Figura 1. Fase de Scan Registration
Figura 2. Puntos con forma de Esquinas detectadas
La fase de ScanRegistration incluye varias funciones, destacándose entre ellas laserCloudHandler, la cual recibe los puntos capturados por el escáner en el formato “pcl::PointCloud<PointType>”. La constante PointType equivale a pcl::PointXYZI, dependiendo del modelo del sensor Lidar utilizado.
Figura 3. Función principal de ScanRegistration
Una de las
funcionalidades principales es almacenar y filtrar ciertos puntos utilizando la
función PCL removeNaNFromPointCloud. Esta función
elimina los puntos con valores x, y o z iguales a NaN
(not-a-number). La función
solo calcula la correlación entre los puntos en la nube de entrada y la nube
resultante después del filtrado, emitiéndola ya filtrada.
En la fase de LaserOdometry se calcula la trayectoria, la cual se mejora
posteriormente en la fase de LaserMapping. Una de las
funciones principales en la fase de odometría es pointAssociateToMap, que asocia los puntos clave
identificados en la fase de ScanRegistration con el
mapa obtenido, tal como se ilustra en la Figura 4.
Figura 4. Función de LaserOdometry
En esta función, se ingresan dos conjuntos de datos: uno contiene puntos con forma de esquinas y el otro contiene puntos planos del barrido actual, los cuales se asocian al mapa. Es relevante señalar que, en esta etapa, el algoritmo ya puede calcular la trayectoria del vehículo, aunque esta estimación todavía está en una fase inicial.
Además, en la etapa de LaserMapping se emplea una función denominada transformAssociateToMap, la cual expande la capacidad de pointAssociateToMap. Esta función utiliza los datos obtenidos de pointAssociateToMap y los transforma en puntos en los ejes x y z, tal como se ilustra en la Figura 5.
Figura 5. Función del Apartado de
LaserMapping
Esta fase de mapeo también contribuye al cálculo matemático de la trayectoria, ya que en ella se corrige y ajusta el mapa de la trayectoria obtenido en la fase de odometría. Esto se lleva a cabo en la función laserOdometryHandler, como se ilustra en la Figura 6.
Figura 6. Función de la fase de mapeo
Este procedimiento emplea una
biblioteca encontrada en la investigación bibliográfica denominada tf::Quaternion, que ejecuta rotaciones de álgebra lineal en
combinación con Matrix3x3 para calcular la posición, considerando la rotación
del sensor. Esta biblioteca se desarrolló en C++, a diferencia del algoritmo
original que se implementaba en C++ en conjunto con ROS.
El algoritmo hasta aquí argumentado, resulta muy eficiente, puesto que sin usar un
sensor inercial se obtienen resultados válidos en cuanto al posicionamiento.
Para dicha comparación fueron utilizados los datos de un GPS y se cotejaron con
la ruta calculada por el algoritmo. A partir de ello, se obtuvo una similitud
aceptable (Figuras 7 y 8). Ahora bien,
para un análisis más profundo se calculará el error total del posicionamiento y
de ciertos puntos.
Figura 7. Ruta obtenida con el algoritmo implementado
Figura 8. Ruta obtenida con el GPS
Para el respectivo análisis se definen Δx, Δy; como los errores entre la posición estimada (datos del GPS), la medida de precisión Ep se define para representar el promedio del error de posicionamiento donde N representa el alcance del escaneo, que en este experimento específico es de 1700 unidades, resultando en un error de posicionamiento total del experimento de Ep = 3.5527 metros. Además, se llevó a cabo un análisis muestral en el que se seleccionaron 6 puntos, incluyendo 3 puntos situados en una línea recta y 3 puntos en curva, como se muestra en la Tabla 1.
Tabla 1. Puntos en rectas y curvas
Entorno |
Punto 1 |
Punto 2 |
Punto 3 |
||||
Distancia |
Error |
Distancia |
Error |
Distancia |
Error |
||
Rectas |
0,25 m |
0,00014706 |
0,7 m |
0,00041176 |
1,2 m |
0,00070588 |
|
Curvas |
1,50 m |
0,00088235 |
3,2 m |
0,00188235 |
5,6 m |
0,00329412 |
|
Los puntos amarillos equivalen
a las curvas y los puntos blancos a las rectas (Figura 9), donde es factible
observar que el error en las curvas es más alto que en las rectas; ello se debe
con toda probabilidad a la falta de un dispositivo de medida inercial en el
sistema.
Figura 9. Comparativa de las trayectorias obtenidas por el algoritmo y el GPS
Después de examinar la trayectoria por segmentos y transformar los datos del GPS al formato X, Y, se nota que los puntos de la trayectoria generada por el algoritmo implementado no se alinean perfectamente con los datos del GPS. Por consiguiente, resulta fundamental llevar a cabo una estimación y análisis por segmentos. Esto implica extraer segmentos específicos de la trayectoria y compararlos individualmente con la trayectoria real, con el propósito de minimizar el error.
En cuanto al análisis de los segmentos curvos, se aplicó el mismo criterio de medición de error mencionado anteriormente. Para ello, se dividió el conjunto de datos mediante la extracción de la trayectoria curva, como se muestra en la Figura 10, y se comparó con el segmento obtenido del GPS. Se obtuvo una trayectoria con un total de 898 puntos extraídos y un error Epc de 1,2 metros.
Figura 10.
Trayectoria GPS versus Lidar en curvas
Se seleccionaron tres puntos para observar que, al realizar este tipo de análisis por segmentos, el error disminuye en comparación con el análisis previo, como se muestra en la Tabla 2.
Tabla 2. Puntos de
segmento curvos
Entorno |
Punto 1 |
Punto 2 |
Punto 3 |
||||
Distancia |
Error |
Distancia |
Error |
Distancia |
Error |
||
Curvas |
1 m |
0,00111359 |
1,5 m |
0,00244989 |
8,6 m |
0,00957684 |
|
El error de distancia es más alto en el último punto comparado debido a que, al tratarse de una ruta algo extensa, el sistema acumula el error a lo largo del recorrido, lo que se refleja en los extremos finales del trayecto.
Respecto al análisis de los segmentos rectos, fue utilizado el criterio de medida de error antes mencionado, para lo cual se fraccionó el conjunto de datos, extrayendo la trayectoria curva (Figura 11) y se comparó frente al segmento obtenido del GPS; lográndose una trayectoria con un total de 866 puntos extraídos y un Error Epr= 0,43 m.
Figura 11. Trayectoria GPS vs LIDAR en
curvas
En este sentido, se seleccionaron tres puntos para observar que, al realizar este tipo de análisis por segmentos, se logró una considerable reducción del error en comparación con el análisis previo, como se muestra en los datos de la Tabla 3.
Tabla 3. Puntos de muestra de trayectoria rectas
Entorno |
Punto 1 |
Punto 2 |
Punto 3 |
||||
Distancia |
Error |
Distancia |
Error |
Distancia |
Error |
||
Rectas |
0,15 |
0,00017321 |
0,35 |
0,00040416 |
0,62 |
0,00071594 |
|
4. Conclusiones
El empleo de
bibliotecas como Eigen y tf simplifica y resuelve la necesidad de prescindir de
utilizar ROS en la realización de este proyecto, ya que el algoritmo requiere
el uso de ciertas bibliotecas y paquetes diseñados específicamente para ROS,
las herramientas mencionadas en el texto posibilitan la implementación de las
funcionalidades de dichos paquetes y bibliotecas en C++.
En la etapa de
LaserOdometry, se obtiene una estimación preliminar del posicionamiento del
sensor, la cual es de baja precisión. Sin embargo, en la fase de LaserMapping,
se realiza una corrección y se obtiene una estimación de la posición más
precisa y certera.
El algoritmo
implementado muestra mayor eficiencia en tramos rectos en comparación con las
curvas debido a la falta de un sensor de medida inercial. Este sensor compensa
la rotación del láser en las curvas. Por esta razón, en situaciones con
diversos tipos de recorrido, se recomienda realizar un análisis por segmentos
para mejorar los resultados y reducir el error total del experimento.
En general, este
algoritmo demuestra ser muy útil como complemento de un GPS en ciertos
contextos. Sin embargo, se podría obtener información aún más precisa y
detallada al incorporar un sensor IMU.
Aunque los desafíos
surgieron debido a la interacción entre el entorno del recorrido y la velocidad
de desplazamiento del vehículo, se sugirió realizar un conjunto más amplio de
pruebas, las cuales estarían debidamente documentadas. Estas pruebas surgirían
de una exhaustiva observación de todos los procesos asociados, con el objetivo
de establecer una relación más precisa entre el error de la trayectoria, el
tipo de entorno, la velocidad de desplazamiento del vehículo y la frecuencia de
muestreo del sensor láser.
El análisis realizado
puso en evidencia que la ausencia de un dispositivo de este tipo, afectaba la
precisión del algoritmo; por tal razón, fue un propósito implementar el
algoritmo usando ese tipo de sensor, para realizar un tipo de fusión sensorial
y para mejorar la precisión.
Entre las ventajas que
se ponen de manifiesto en este artículo, como resultado de un proceso
investigativo llevado a cabo durante un grupo de años, se encuentra la
disponibilidad de la nube de puntos; por lo que, es hipotéticamente posible
lograr la implementación de un algoritmo de detección de objetos y tracking.
5. Referencias
Eigen. (2016). Eigen is a C++ Template Library for Linear Algebra: Matrices, Vectors,
Numerical Solvers, and Related Algorithms. http://eigen.tuxfamily.org/index.php?title=Main_Page
PCL. (2023). About. What is PCL. https://pointclouds.org/about/
Pinargote, V. (2017). Implementación del algoritmo de odometría LOAM con C++ en Linux
[Tesis de Maestría, Universidad Politécnica de Madrid].
https://oa.upm.es/48115/3/TFM_VICTOR_PINARGOTE_BRAVO.pdf
PUCK. (2023). PUCK ™ (VLP-16).
http://velodynelidar.com/vlp-16.html
ROS (Robot Operating System).
(2021). About ROS.
https://www.ros.org/
Tombari, F. (2013). Keypoints and Features for 2D/3D Image
Processing and Recognition [Archivo PDF].
https://courses.cs.washington.edu/courses/cse455/09wi/Lects/lect6.pdf
Zhang, J. y Singh, S. (2014). LOAM:
Lidar Odometry and Mapping in Realtime. Robotics:
Science and Systems Conference (RSS), p. 9.
https://www.ri.cmu.edu/pub_files/2014/7/Ji_LidarMapping_RSS2014_v8.pdf