Construyendo un mapa local de campo a través del robot

Hola Habr!

En esta publicación, me gustaría hablar sobre cómo construí un mapa local de campo a través para el robot. Esta tarea fue necesaria tanto para aumentar las habilidades en la programación y el dominio de los sensores, como para la posterior implementación de nuestros propios algoritmos en la operación de robots reales en pruebas robóticas como Robocross y Robofest.

Este artículo está dirigido a aquellos que recién ingresan al mundo de la robótica o intentan descubrir cómo construir un mapa de campo a través. Traté de explicar todo en el lenguaje más simple y más comprensible que es comprensible para la mayoría de las personas.

¿Qué es un mapa local de campo a través?


Entonces, un mapa local de campo a través es lo que el robot ve en un momento dado en el tiempo.
Esta es la información que proviene de los "ojos" del robot y posteriormente se procesa y se muestra de una forma conveniente para nosotros.

Si el robot se detiene, su mapa local en condiciones ambientales constantes permanece constante.

Si el robot se mueve, entonces, en cada momento, su entorno es diferente, respectivamente, el mapa local también cambia.

El mapa local generalmente tiene tamaños constantes. El tamaño se calcula en función de la longitud máxima de los rayos emitidos por el telémetro. En mi caso, esta longitud es de 6 metros.

Para simplificar la tarea, se decidió hacer el mapa cuadrado. También se decidió que condicionalmente el buscador de rango estaría exactamente en el centro del mapa (este lugar será el punto donde x = y = 0). El centro se eligió de esta manera porque el telémetro que utilizo emite rayos en el plano más de 180 ° (emite rayos a 240 °, pero más sobre eso más adelante), es decir, algunos rayos ciertamente irán detrás del escáner y Si elige el centro equivocado, puede perderlos. Con una elección adecuada del centro, todos los rayos se mostrarán correctamente. En base a esto, hice el tamaño del mapa 2 veces más grande que la longitud máxima de los rayos emitidos.
El tamaño de mi tarjeta es de 12 * 12 metros.

imagen

El sensor que usé


De hecho, para resolver este tipo de problema, puede usar cualquier buscador de rango.
El telémetro es un dispositivo para determinar la distancia a algo (en mi caso, a un obstáculo potencial).

En robótica, se utilizan principalmente 2 tipos de telémetros: ultrasónico y láser.
Los telémetros ultrasónicos son mucho más baratos, pero los rayos ultrasónicos son lo suficientemente anchos y no son adecuados para mediciones precisas.

Los telémetros láser son más caros, pero más precisamente, ya que sus rayos están enfocados de manera más estrecha.

Para resolver mi problema, utilicé un escáner láser Hokuyo URG-04LX-UG01. Este sensor es capaz de emitir rayos a 240 ° y proporciona información bastante precisa sobre los obstáculos que se han interpuesto en el camino de los rayos. Su alcance máximo es de 5-6 metros. Vale la pena señalar que este telémetro emite rayos solo en el plano 2D. Este hecho le obliga a colocar el sensor en el robot en un lugar determinado, generalmente frente a la parte inferior del robot, para obtener una imagen más precisa. Una vez más, puede usar escáneres 3D, que proporcionan información mucho más precisa y completa sobre el entorno, pero también cuestan mucho más.

Creo que este escáner en particular es perfecto para entrenar en la relación calidad-precio.

imagen
Hokuyo URG-04LX-UG01

Brevemente sobre el principio del escáner láser:
El telémetro emite rayos a lo largo del plano. Un rayo que ha encontrado un obstáculo en su camino se refleja y regresa. Por la diferencia de fase entre las señales enviadas y recibidas, uno puede juzgar qué tan lejos se encuentra el obstáculo.

En consecuencia, si el rayo emitido no regresó, entonces a 5 - 6 metros a lo largo de la línea recta de emisión no hay obstáculos o el rayo no puede reflejarse correctamente.

imagen

Los siguientes datos se pueden obtener de un escáner láser:

Por cada rayo emitido:

  • Distancia a un obstáculo
  • Ángulo de emisión

* Cada uno de los parámetros se almacena en una matriz separada y corresponde a los datos de uno de los rayos.

Sobre la construcción de mapas


Para construir el mapa y dibujarlo, utilicé las herramientas ROS (Robot Operating System), a saber: el programa Rviz y el tipo de datos nav_msgs :: OccupancyGrid. Creé un editor del mapa local con el tipo de mensaje nav_msgs :: OccupancyGrid bajo el tema correspondiente local_map. En Rviz, suscribiéndose a este tema, recibió datos sobre el mapa y los mostró en forma de tipo Mapa.

De acuerdo con dicho algoritmo, era necesario configurar mediante programación el procesamiento de datos desde un escáner láser y registrarlos en el formato requerido para la transmisión. En OccupancyGrid, un mapa se almacena y se transmite en una matriz unidimensional.

¿Qué está pasando aquí?
Para aquellos que se enfrentan a este tipo de datos ROS por primera vez: esto es inusual, ya que el mapa se representa convencionalmente como una matriz bidimensional con un cierto número de columnas y filas.

Así fue conmigo. Almaceno el mapa en función de los datos del escáner en una matriz bidimensional, y cuando redacto un mensaje para enviarlo a Rviz, convertiré la matriz bidimensional en la unidimensional necesaria para OccupancyGrid.

De hecho, un mapa en OccupancyGrid solo se almacena y transmite en una matriz unidimensional. Al descifrar sus datos, se convertirá automáticamente en un mapa bidimensional cuadrado.
Pero para que esto suceda correctamente, debe escribir esta matriz unidimensional de cierta manera.

A saber: línea por línea desde el almacenamiento bidimensional para escribir en una línea.

Voila! Este es todo el secreto.

Una apelación a cualquier elemento de dicha matriz unidimensional se produce de la siguiente manera:

localMap[mapSizej+i]


mapSize - tamaño del mapa local
j es el número de columna
i - número de línea

Las celdas del mapa (de nuevo según el tipo de datos de OccupancyGrid) deben tener valores de 0 a 100. Cuanto menor sea el valor, mayor será la probabilidad de que la celda sea transitable y viceversa.

Para simplificar la tarea, he seleccionado 3 colores primarios para colorear celdas.

  • Blanco - Área transitable = 0
  • Negro: área infranqueable = 100
  • Gris: zona desconocida = 50

Un punto importante!

Antes de que lleguen los datos del escáner, el mapa es completamente desconocido (valores de todas las celdas = 50) y cada vez que se dibuja se actualiza nuevamente a un estado desconocido. Esto se hace para que la tarjeta no se superponga a valores anteriores superfluos. Después de todo, un mapa local refleja el estado del medio ambiente solo en un momento dado en el tiempo.

imagen
Tarjeta desconocida

Los rayos se construyen usando una transformación del sistema de coordenadas polares (UCS)
al sistema de coordenadas cartesianas (DSC).

$$ display $$ \ left \ {\ begin {collect} x = r * cos φ \\ y = r * sin φ \ end {collect} \ right. $$ display $$


x, y - nuevas coordenadas en DSC
r es la distancia al obstáculo
φ es el ángulo en el que se dejó caer el haz
r, φ - coordenadas antiguas en UCS

Algoritmo de procesamiento de datos del sensor:


Atravesamos completamente los conjuntos de distancias r y ángulos φ de los rayos (datos UCS). Para cada artículo, haga lo siguiente:

  1. Transformamos las coordenadas de UCS a DSC para r y ite finitos. Pinte la celda resultante de negro. Este es un obstáculo.
  2. Pasamos en línea recta desde la ubicación del escáner a la celda con un obstáculo con cierto paso, en el caso más simple igual al tamaño de la celda.
  3. Una vez más, convertimos los datos del UCS al DSC y pintamos la nueva celda en blanco. Esta es un área transitable.

imagen
El ejemplo más simple de cómo construir un camino transitable hacia un obstáculo.

Pero, ¿qué pasa si el haz emitido no regresa?
Si esto sucediera, podría significar lo siguiente:

  • El rayo está "perdido", es decir, no está completamente reflejado o reflejado en la otra dirección
  • No había obstáculos en el camino de la viga y debido a esto, simplemente no tenía nada para reflexionar

* Un rayo puede "perderse" generalmente porque no se reflejó en un ángulo de 180 ° (es decir, debajo de cualquiera que no llegue hacia atrás), ya que el obstáculo podría estar perpendicular al rayo. Y como saben por la física: el ángulo de incidencia es igual al ángulo de reflexión.

imagen

O porque el obstáculo era demasiado negro y absorbía la mayor parte de la energía del rayo y el rayo no tenía suficiente energía para regresar.

Por lo tanto, es imposible estar completamente seguro de lo que sucedió si el rayo no regresó.

¿Qué hacer en tales situaciones?

Hacemos lo siguiente:

  1. Consideramos la distancia al obstáculo de tal haz como sea posible para el escáner (en nuestro caso es de 6 metros)
  2. Consideramos todas las celdas en línea recta al obstáculo como semi-transitables y les asignamos un número intermedio de 25. Estas son celdas transitables, pero no estamos completamente seguros de ellas.

No perdemos nada si los rayos realmente no se encontraron con los obstáculos, y si algún obstáculo escapó de los "ojos" del robot, entonces se detectará muy rápidamente.

Resolución de la tarjeta


Finalmente, los toques finales!

Cada tarjeta tiene permiso. En pocas palabras, este es el número de celdas que pueden caber en 1 celda.

Por ejemplo
Si hay 1 celda en 1 celda (el caso más simple), entonces la resolución 1.
Si hay 5 celdas en 1 celda, entonces la resolución es 0.2.

La resolución de mi tarjeta es 0.04. Es decir, en cada celda hay 25 celdas. Por lo tanto, mi paso mínimo es de 4 cm. Y 1 celda es de 1 m.

imagen
Celda y diferencia celular en mi mapa

Cual es el resultado?


imagen
Un ejemplo de construcción de un mapa local de campo a través
* El color amarillo indica los colores de las celdas.

Creo que, en general, el trabajo que he realizado fue exitoso, pero entiendo que el algoritmo es imperfecto y requiere refinamiento y refinamiento.

Source: https://habr.com/ru/post/es418585/


All Articles