banner
Hogar / Blog / Cómo usar Lidar con Raspberry Pi
Blog

Cómo usar Lidar con Raspberry Pi

Nov 29, 2023Nov 29, 2023

La capacidad de medir de manera económica pero precisa la distancia entre un vehículo o robot autónomo y los objetos cercanos es un problema desafiante para los piratas informáticos. Conocer la distancia es clave para evitar obstáculos. Chocarse con algo con un robot pequeño puede ser un problema trivial, pero podría ser mortal con uno grande como un vehículo autónomo.

Mi interés en la medición de distancias para evitar obstáculos surge de mi participación en el Concurso de Robots de Retorno de Muestras (SRR) de la NASA de 2013. Usé una cámara web para el procesamiento de la visión e intenté varias técnicas visuales para realizar mediciones, sin mucho éxito. En la competencia, dos participantes usaron lidars de escaneo que despertaron mi interés en ellos.

Un lidar es un dispositivo de medición de alcance láser. El nombre es una combinación de los términos LUZ y RADAR y no, como comúnmente se sugiere, un acrónimo derivado de manera similar a su predecesor, "Radio Detection And Ranging". El término se utilizó por primera vez en 1963 según Merriam-Webster. Algunos de los primeros usos de lidar fueron medir las nubes y la superficie de la luna por parte del Apolo 13. A medida que los láseres se reducían de tamaño, se encontraron otros usos, incluso como telémetro para fines militares.

Un solo rayo láser solo puede proporcionar el rango a un solo objeto. Así como el radar de control de aeronaves hace girar un rayo a través del cielo, un lidar de exploración barre el láser. La aplicación de lidar para dispositivos móviles autónomos requiere escanear un área amplia tanto vertical como horizontalmente para proporcionar una nube de puntos de mediciones de distancia. Se podría hacer algo similar con un sensor de infrarrojos, como hemos visto anteriormente, pero la precisión no es tan buena como con un láser.

La medición de la distancia se puede realizar de múltiples maneras, pero se utilizan dos principales. Uno mide el tiempo de vuelo de un pulso láser mientras que el otro usa el ángulo de desviación del rayo láser.

Está familiarizado con el funcionamiento básico del radar y la sonda: envíe un pulso y mida el tiempo que tarda en recibir la señal de retorno. El tiempo dividido por la velocidad de la luz o el sonido te da la distancia que la señal recorrió de ida y vuelta. Divida eso por dos para obtener la distancia al objeto. Esa es la medición del tiempo de vuelo (ToF).

Como puede sospechar, las cosas se complican dada la velocidad de la luz. Pionera en computadoras, la contralmirante Grace "Amazing Grace" Hopper entregaba piezas de alambre de 11,80" para demostrar la distancia que recorre la luz en un nanosegundo en el vacío. Con los robots, esa es la magnitud de la distancia que nos interesa medir. Es difícil de medir menos que un metro enviando solo un pulso y cronometrando la señal de retorno porque la señal regresa en aproximadamente 7 nanosegundos.

Una técnica en torno a esto es modular continuamente la señal por amplitud o frecuencia. La diferencia de fase entre las señales transmitidas y recibidas es proporcional a la distancia al objeto. Un lidar que usa modulación puede medir hasta centímetros.

Hay una serie de proveedores comerciales de lidars de escaneo basados ​​en ToF, pero el precio es un poco más alto de lo que gastaría la mayoría de los aficionados. Un participante relativamente nuevo, PulsedLight, ofreció un lidar ToF de un solo haz dentro del rango de precios de los piratas informáticos, pero todos sus proveedores están atrasados.

El lidar de triangulación utiliza la misma técnica que los sensores de medición de distancia por infrarrojos de Sharp que los piratas informáticos han estado utilizando durante años. El transmisor es una fuente única, pero el receptor es una matriz de receptores de 1 o 2 dimensiones. El desplazamiento de los elementos del receptor del transmisor crea la línea de base de un triángulo. La señal de salida y de retorno son los otros dos lados del triángulo. La trigonometría simple proporciona la distancia desde la línea de base hasta el objeto.

La Sociedad Óptica describe estas y otras técnicas utilizadas para medir la distancia.

Lo que no sabía cuando competí en el SRR de la NASA de 2013 es que Neato Robotics lanzó una aspiradora en 2010 usando un lidar de escaneo para detectar los alrededores de la aspiradora. Esto permite que el robot evite los obstáculos en lugar de chocar con ellos como lo hacían los robots aspiradores anteriores.

Sparkfun hizo un desmontaje de la aspiradora e investigó el lidar. Se produjo una larga discusión que comenzó en noviembre de 2010 en el foro Trossen Robotic cuando los piratas informáticos diseccionaron el vacío con mucha atención al lidar. Incluso se ofrecieron pequeños premios por piratear el lidar.

Desafortunadamente, varios de los enlaces en ese hilo ya no existen, pero vale la pena leerlo, ya que muchos detalles se presentan en los mensajes. Algunos otros hilos en el foro tienen información adicional. Un hallazgo especialmente interesante es un trabajo de investigación que precedió al lidar de Neato pero que sirvió como base para el diseño final. Describió los detalles necesarios para que Neato creara un producto de ingeniería.

La buena noticia es que existe un wiki con un resumen de información sobre la aspiradora y el lidar. Uno de los participantes activos de piratería, [Nicolas "Xevel" Saugnier] creó una pequeña placa de interfaz USB para alimentar el lidar y conectarse a su interfaz serial. En el verano de 2014 obtuve un par de unidades lidar y las placas mientras buscaba ingresar al SRR de la NASA de 2015. Conseguí que las unidades lidar funcionaran utilizando el software Python [de Xevel] y los paquetes disponibles en el sistema operativo Robot.

El lidar de escaneo permitió a Neato Robotics implementar la localización y el mapeo simultáneos (SLAM) utilizando los datos de medición de distancia. Esto permite que el robot planifique la ruta de limpieza en lugar de usar los golpes anteriores y los movimientos aleatorios, un paseo de borracho, de las aspiradoras anteriores. Esto permite que Neato cubra completamente una habitación más rápidamente. Observe en este video de una demostración de Neato cómo el robot construye un mapa de dónde ha estado y los obstáculos que encuentra. Tenga en cuenta especialmente cómo utiliza los datos LIDAR para rodear cuidadosamente el único obstáculo.

Todavía estoy muy interesado en los robots, aunque me he dado por vencido en el concurso SRR. Los lidars han estado sentados en el estante atrayéndome como sirenas míticas. Finalmente sucumbí a su llamada cuando me di cuenta de que la interfaz serial lidar era una combinación perfecta para una Raspberry Pi, ya que ambas funcionan a niveles de 3V3. Esto eliminaría la interfaz USB. Un esfuerzo similar es el de [Thomas Jesperson] en 2014, quien usó una placa STM32F429 y produjo un video del lidar en acción.

El lidar es una unidad sellada con un motor que cuelga de un extremo. El motor impulsa una torreta que gira a unas 300 rpm. La torreta contiene el láser y el sensor de recepción y, al girar, proporciona un escaneo de 360 ​​grados del área circundante. El láser y el sensor de recepción tienen dos puertos ópticos fuera de la torreta. Hay dos cables cortos con conectores JST provenientes del lidar. Un conector de dos pines proporciona energía al motor. Un conector de cuatro clavijas proporciona alimentación de 5 V a los circuitos de control y la interfaz serial 3V3. Los pines son:

En el vacío, el motor recibe alimentación de una fuente de 12 V que utiliza PWM con un ciclo de trabajo de alrededor del 25 %. Esto significa que el motor necesita alrededor de 3 V para funcionar a la velocidad correcta y las pruebas posteriores realizadas por los piratas informáticos demostraron que esto es cierto. La placa de interfaz USB ejecuta el lidar desde la entrada de 5 V del conector USB mediante PWM controlado por un bucle PID (diferencial integral proporcional) para mantener la velocidad del motor. ¿Por qué usar PWM y PID? Para mantener RPM constantes para la torreta giratoria a medida que se desgasta y acumula suciedad, polvo y otros desechos. En mis pruebas noté que el motor girará la torreta en cualquier dirección dependiendo de la conexión positiva y negativa. La interfaz aún funciona bien, pero la secuencia de los puntos de datos se invertirá. Normalmente, la torreta gira en sentido contrario a las agujas del reloj.

Una palabra de precaución: en algunas unidades anteriores, la interfaz usaba 3V3, por lo que conectarlas a 5V puede destruir la interfaz.

Mi conexión original entre la Pi y el lidar fue rápida y sucia. Conecté el motor a la salida 3V3 de Pi y funcionó. La salida del Pi 3V3 está limitada a 50 mA por las especificaciones y el lidar Wiki dice que el motor consumiría 64 mA. Medí el mío y dibujó considerablemente más. También conecté el pin TX de la interfaz al RX de Pi (pin 10). Usando CuteCom bajo Raspbian Jessie, pude leer los datos cuando la torreta se giraba manualmente. Con esas pruebas básicas fuera del camino, era hora de ponerse un poco más serio.

Elegí usar una matriz de transistores Darlington ULN2803A que encontré en mi gabinete de piezas para impulsar el motor. Este IC maneja fácilmente la corriente necesaria para impulsar el motor e incluye los diodos de protección necesarios para impulsar una carga inductiva. No tenía la intención de hacer PWM del motor, pero quería apagarlo y encenderlo. Conecté los 5V de Pi en el pin 2 al cable rojo en el conector del motor. El cable negro conectado al ULN2803A a través de una resistencia de 15 ohmios para bajar el voltaje. Esta configuración de configuración de lado bajo para controlar el motor. El cable de interfaz está conectado a los pines de 5V, tierra y RX en el Pi.

Para probar el control del motor, utilicé la asignación de los pines GPIO al directorio del sistema de archivos /sys/class/gpio. Cada GPIO se puede controlar aquí una vez que se exporta el pin. Los comandos pueden establecer la dirección de los pines y encender y apagar el pin. Los comandos que usé controlaban GPIO 18 (pin 12):

El '0' y el '1' cuando se repiten apagan y encienden el pin, respectivamente. Esto funcionó y pude ver los datos usando CuteCom.

Un resultado interesante ocurre si está conectado al puerto serie y luego aplica energía a la interfaz. El lidar genera un mensaje de bienvenida:

Escáner de distancia láser Piccolo Copyright (c) 2009-2011 Neato Robotics, Inc. Todos los derechos reservados Loader\0x09V2.5.15295 CPU\0x09F2802x/c001 Serial\0x09KSH34313AA-0140854 LastCal\0x09[5371726C] Runtime\0x09V2.6.15295

Además, si gira manualmente la torreta, aparece un mensaje que dice "Girar" e informa que hay una capacidad de comando disponible enviando un descanso o tres caracteres esc. La información sobre los comandos está disponible en la Wiki.

Ahora a crear un software en bruto para ver cómo funciona todo esto. Por supuesto, utilicé C++, así que instalé la cadena de herramientas para Pi 2 y descubrí que la velocidad de compilación es suficiente para el desarrollo. Empecé a usar el editor de programación Geany y los makefiles; una configuración que aprendí mientras trabajaba con el código de Python para el lidar. Maneja múltiples lenguajes de programación y lo adopté como un editor de texto de uso general en Ubuntu y Raspian. Pero finalmente abandoné a Geany e instalé Eclipse CDT en la Pi cuando no formateó correctamente el código C++ después de editarlo. Eclipse funciona sorprendentemente bien en la Pi. De hecho, me decepcionó un poco el cambio, ya que con Geany estaba volviendo a aprender a trabajar con archivos MAKE, una habilidad que perdí al trabajar con Eclipse.

Mientras buscaba información sobre la programación del GPIO con C++, encontré la biblioteca WiringPi de [Gordon Henderson]. No solo es compatible con la programación GPIO sin formato, sino que es compatible con muchas placas secundarias Pi. Un atractivo adicional para mí es que tiene una interfaz de puerto serie, por lo que no tuve que entrar en detalles sobre eso en Linux, lo que habría sido nuevo para mí. Eventualmente, incluso usé su capacidad de subproceso simple para manejar una interfaz de usuario absurdamente mínima. [Gordon] también tiene una utilidad que debe consultar para controlar los pines desde la línea de comandos de manera más completa que escribir en los directorios como mostré anteriormente.

La pieza final que encontré en WiringPi es la capacidad de hacer hardware PWM en el único pin GPIO capaz de hacerlo en el Pi. Eso es GPIO 18. Originalmente usé GPIO 4 (pin 7) para controlar el motor, pero cambié cuando encontré esta capacidad. El código actualmente establece un valor constante para el PWM, pero eventualmente quiero agregar (y escribir un artículo sobre) un circuito de sistema de control PID (diferencial integral proporcional) para mantener una velocidad constante. Configurar WiringPi, un hilo y el PWM en GPIO 18 es fácil:

El hilo está ahí simplemente para detener el programa cuando se ingresa cualquier tecla y devolver el golpe. Cuando run se establece en falso, el subproceso principal que lee la entrada en serie se cierra y el programa sale después de apagar la torreta. El hilo real es muy simple:

Leer la entrada en serie es simple, solo leer caracteres, pero los datos en sí, si bien son sencillos, requieren un poco de golpes. Hay 360 muestras por revolución de la torreta, por lo que la cantidad de datos a 5 revoluciones por segundo es enorme. Hay 90 paquetes, cada uno de los cuales contiene cuatro puntos de datos. Cada punto está representado por cuatro bytes de datos: distancia, intensidad de la señal, bit de distancia no válida y bit de intensidad no válida. Además, cada paquete comienza con un byte de inicio, un byte de índice que es el número de paquete y dos bytes para la velocidad de rotación de la torreta. El paquete termina con dos bytes de suma de comprobación. Así es como mapeé esos datos en estructuras:

No me dediqué a almacenar los paquetes de datos, solo los informé para verificar que estaba viendo buenos datos y que mis cálculos se veían bien. Los datos de distancia son un número entero informado en milímetros que convertí a pulgadas. El código para la suma de comprobación está en Wiki pero aún no lo he implementado.

Este es solo el comienzo de trabajar con el lidar de Neato, pero es bueno. El hardware funciona bien y los conceptos básicos del software están a la mano. Puedo obtener los datos y ver que es válido. La biblioteca WiringPi es un buen hallazgo para continuar con mis esfuerzos con Pi.

Los siguientes pasos son hacer que la rutina de suma de verificación funcione, expandir la llamada interfaz de usuario para permitir el control de la operación de la torreta y agregar un bucle PID para mantener una velocidad de rotación constante. Dado que el chip UNL2803A está allí, lo usaré para controlar la alimentación de la interfaz. También quiero ver la compilación cruzada del código desde mi escritorio y hacer una depuración remota. Mientras hago esos cambios, organizaré el código en clases y veré cómo puedo usarlo en un robot.

Cable de interfaz de cable de motor