
Si usa ROS cuando crea robots, probablemente sepa que tiene soporte para trabajar con cámaras estéreo. Puede construir, por ejemplo, un mapa de profundidad de la parte visible del espacio o una nube de puntos. Y me preguntaba qué fácil sería usar una cámara estéreo StereoPi basada en frambuesa en ROS. Anteriormente, ya estaba convencido de que el mapa de profundidad está perfectamente construido por OpenCV, pero nunca he tratado con ROS. Y decidí probarlo. Quiero hablar sobre mis aventuras para encontrar una solución.
1. ¿Hay alguna ROS en la Raspberry Pi?
Al principio, decidí averiguar si era posible construir ROS para Raspberry Pi. Lo primero que me dijo Google fue una lista de instrucciones para instalar diferentes versiones de ROS en la Raspberry Pi, es decir, esta página
wiki de ROSBueno, ¡ya hay algo por donde empezar! Recuerdo bien cuánto tiempo llevó construir OpenCV en Raspberry (aproximadamente ocho horas), así que decidí buscar imágenes ya preparadas de tarjetas MicroSD para ahorrar tiempo.
2. ¿Hay imágenes de tarjetas microSD listas para usar con ROS para Raspberry?
Resultó que este problema ya ha sido resuelto por varios equipos de desarrollo. Si no toma compilaciones únicas de entusiastas, entonces se destacaron un par de imágenes que se actualizan constantemente con el lanzamiento de nuevas versiones del sistema operativo y ROS.
La primera opción es ROS instalada en el sistema operativo Raspbian nativo del equipo de ROSbots, aquí hay una página con un enlace de imagen actualizado:
ready-to-use-image-raspbian-stretch-ros-opencvEl segundo son las
imágenes de Ubiquiti Robotics en ubuntu .
Bueno, la segunda pregunta también se cerró lo suficientemente rápido. Es hora de sumergirse más profundo.
3. ¿Cómo funciona ROS con la cámara Raspberry Pi?
¿Y qué cámaras estéreo generalmente son compatibles con ROS? Miré la página con cámaras estéreo, para la cual se declaró la disponibilidad de controladores listos para ROS, esta:
wiki.ros.org/SensorsHabía dos secciones:
2.3 Sensores 3D (telémetros y cámaras RGB-D)
2.5 cámarasResultó que en la primera sección, no solo se enumeran las cámaras estéreo, sino también los sensores TOF y los lidares de escaneo, en general, todo lo que puede proporcionar información en 3D de inmediato. Y en el segundo ya hay cámaras estéreo. Intentar ver los controladores de varias cámaras estéreo no fue un placer para mí, ya que insinuó una inmersión seria en el código.
Bien, retrocede un paso. ¿Cómo funciona con una sola cámara Raspberry Pi en ROS?
Aquí me esperaban tres sorpresas agradables:
- Resulta que para ROS hay un nodo especial raspicam_node solo para trabajar con la cámara Raspberry Pi
- Los tipos de nodo se encuentran en el github, el código se mantiene activamente y está bien documentado: github.com/UbiquityRobotics/raspicam_node
- El autor del nodo Rohan Agrawal ( @Rohbotics ) trabaja para una empresa que respalda activamente una de las imágenes preparadas para Raspberry Pi
Miré el repositorio de github raspicam_node y miré los problemas. Allí encontré un problema abierto con el nombre espacioso "modo estéreo" hace casi siete meses, sin respuestas ni comentarios. En realidad, en él todos los eventos se desarrollaron aún más.
4. Hardcore o no?
Para no hacer preguntas de los niños a los autores, decidí mirar el código fuente y evaluar qué amenaza la incorporación del modo estéreo. Estaba más interesado en la parte del sistema aquí:
github.com/UbiquityRobotics/raspicam_node/tree/kinetic/srcBueno, los muchachos escribieron al conductor hundiéndose en el nivel MMAL. También recordé que el código fuente de las frambuesas en modo estéreo también está abierto (la evolución se puede rastrear
aquí en el foro de frambuesas ), y la tarea de escribir un controlador estéreo completo es solucionable, pero a gran escala. Al observar la descripción de los controladores de otras cámaras, me di cuenta de que era necesario publicar no solo las imágenes izquierda y derecha, sino también dar los parámetros de ambas cámaras, aplicar los resultados de calibración a cada una y hacer muchas otras cosas. Esto atrajo experimentos de un mes o dos de largo. Por lo tanto, decidí paralelizar el enfoque, a saber: escribirle al autor una pregunta sobre el soporte estéreo y buscar una solución más simple pero que funcione.
5. Diálogos con el autor.
En el hilo sobre el modo estéreo en el github, le hice una pregunta al autor, mencionando que el estéreo ha sido respaldado por frambuesas desde 2014, y sugerí, si es necesario, enviarle una placa de depuración para experimentos. Permíteme recordarte que todavía dudaba que en esta distribución el estéreo funcionará como en el Raspbian nativo.
Rohan respondió sorprendentemente rápido, diciendo que su distribución usa un núcleo de frambuesa y que todo debería funcionar. Y pidió que lo revisen en una de sus asambleas.
Núcleo de frambuesa! ¡Hurra! ¡Teóricamente, se debe capturar una imagen estéreo sin bailar con una pandereta!
Descargué e implementé su última imagen
usando un enlace de Rohan y ejecuté un simple script de Python para capturar un par estéreo. Funcionó!

Después de eso, Rohan escribió que miraría el código del controlador para el modo estéreo, y escribió un par de preguntas. Por ejemplo, nuestro modo estéreo produce una imagen pegada, y tendríamos que cortarla en dos: izquierda y derecha. Y la segunda pregunta sobre los parámetros de calibración de cada cámara es cómo manejarla.
Dije que como primer paso, puedes tomar fotos de las cámaras de forma independiente. Sí, no se sincronizarán en el tiempo de captura y la configuración (como el balance de brillo, contraste y blanco), pero como primer paso, esto podría reducirse.
Rohan
lanzó rápidamente
un parche que le permite especificar directamente desde ROS de qué cámara tomar fotos. Lo comprobé: elegir una cámara funciona, ya es un excelente resultado.
6. Ayuda inesperada
Y luego aparece un comentario del usuario de Wezzoid en el hilo. Dijo que estaba haciendo un proyecto basado en una cámara estéreo en un Pi Compute 3 usando paneles de frambuesa. Su robot ambulante de cuatro patas rastreó la posición del objeto en el espacio, cambió la posición de las cámaras y mantuvo la distancia especificada (el proyecto se publica en hackaday.io
aquí ).

Y compartió el código en el que tomó la imagen, la cortó por la mitad con python y lo compartió como nodos de las cámaras izquierda y derecha.
Python no es un amigo muy rápido en estos asuntos, por lo que utilizó una resolución baja de 320x240 y un buen truco de vida. Si capturamos una imagen estéreo lado a lado (una cámara a la izquierda de la imagen estéreo, la segunda a la derecha), entonces la pitón debería cortar cada una de las 240 líneas por la mitad. Pero si hace una imagen de arriba a abajo (la cámara izquierda es la mitad superior del cuadro, la derecha es la parte inferior), entonces la pitón corta la matriz por la mitad en una sola operación. Lo cual fue realizado con éxito por el usuario Wezzoid.
Además, publicó su código de Python en Pastebin, que realizó esta operación. Aquí esta:
Código Wezzoid para publicar nodos de dos cámaras desde un par estéreo 7. Comience a publicar los nodos de las cámaras izquierda y derecha
Al principio, el código maldijo que no había acceso a los archivos YML con los parámetros de la cámara. Utilicé cámaras V2 de color frambuesa y recordé que los archivos listos para
usar con resultados de calibración para diferentes modelos de cámaras llegaron al
raspicam_node en el github:
github.com/UbiquityRobotics/raspicam_node/tree/kinetic/camera_infoTomé uno de ellos, hice dos copias y lo guardé con los nombres left.yml y right.yml, escribiendo en ellos la resolución de la cámara del guión del autor. Esto es lo que sucedió con la cámara izquierda:
left.yml image_width: 320 image_height: 240 camera_name: left camera_matrix: rows: 3 cols: 3 data: [1276.704618338571, 0, 634.8876509199106, 0, 1274.342831275509, 379.8318028940378, 0, 0, 1] distortion_model: plumb_bob distortion_coefficients: rows: 1 cols: 5 data: [0.1465167016954302, -0.2847343180128725, 0.00134017721235817, -0.004309553450829512, 0] rectification_matrix: rows: 3 cols: 3 data: [1, 0, 0, 0, 1, 0, 0, 0, 1] projection_matrix: rows: 3 cols: 4 data: [1300.127197265625, 0, 630.215390285608, 0, 0, 1300.670166015625, 380.1702884455881, 0, 0, 0, 1, 0]
A la derecha, el nombre de la cámara se reemplaza por right, y el archivo en sí se llama right.yml. El resto del archivo es idéntico.
Como no planeaba hacer un proyecto complejo, no repetí las largas rutas del autor con subcarpetas y solo puse los archivos en la raíz de la carpeta de inicio junto al script de Python. El código se inició correctamente y muestra mensajes de estado en la consola.

Solo quedaba por ver lo que finalmente publicaron nuestras cámaras izquierda y derecha. Para hacer esto, lancé rqt_image_view. Los elementos / left / image_raw y / right / image_raw aparecieron en el menú desplegable. Cuando los seleccioné, vi imágenes de las cámaras izquierda y derecha.

Bueno, esto ha ganado! Ahora la parte divertida.
8. Observamos el mapa de las profundidades.
Para ver el mapa de profundidad, no se me ocurrió mi propio enfoque y
revisé el manual clásico de
ROS para configurar los parámetros estéreo .
A partir de ahí, descubrí que sería bueno publicar ambos nodos en un espacio de nombres específico, y no en la raíz como lo hizo Wezzoid. Como resultado, las viejas líneas de publicación del formulario
left_img_pub = rospy.Publisher('left/image_raw', Image, queue_size=1)
comenzó a verse así:
left_img_pub = rospy.Publisher('stereo/right/image_raw', Image, queue_size=1)
Después de eso, lanzamos el nodo de procesamiento del modo estéreo stereo_image_proc:
ROS_NAMESPACE=stereo rosrun stereo_image_proc stereo_ige_proc
Bueno, también queremos ver el resultado, así que comenzamos el observador:
rosrun image_view stereo_view stereo:=/stereo image:=image_rect_color
Y para configurar los parámetros del mapa de profundidad, ejecute la utilidad de configuración:
rosrun rqt_reconfigure rqt_reconfigure
Como resultado, vemos la imagen al comienzo del artículo. Aquí es un poco más grande:

Todos los archivos que publiqué en el github:
github.com/realizator/StereoPi-ROS-depth-map-test9. Planes inmediatos
Después de mi publicación del resultado en una discusión sobre el github, Rohan escribió "¡Genial! Tengo que ir a recoger mi StereoPi ". Le escribimos por correo, le envié una tarifa. Espero que con el hardware de trabajo en sus manos le sea más fácil terminar y depurar un controlador estéreo completo para ROS y Raspberry.
10. Resumen
Se puede obtener un mapa de profundidad de una imagen estéreo en frambuesas en ROS de varias maneras. La ruta elegida para la verificación rápida no es la más óptima en términos de rendimiento, pero puede usarse para fines de aplicación. La belleza de su simplicidad y la capacidad de comenzar inmediatamente los experimentos.
Bueno, por lo gracioso: después de recibir los resultados, noté que Wezzoid, quien propuso su solución, fue el autor de la pregunta sobre la publicación de dos imágenes estéreo. Se preguntó a sí mismo, decidió.