Création d'une carte locale du pays du robot

Bonjour, Habr!

Dans cette publication, je voudrais expliquer comment j'ai construit une carte de ski de fond locale pour le robot. Cette tâche était nécessaire à la fois pour accroître les compétences en programmation et en maîtrise des capteurs, et pour la mise en œuvre ultérieure de nos propres algorithmes dans le fonctionnement de robots réels sur des tests robotiques tels que Robocross et Robofest.

Cet article est destiné à ceux qui viennent d'entrer dans le monde de la robotique ou qui essaient de comprendre comment construire une carte de ski de fond. J'ai essayé de tout expliquer dans le langage le plus simple et le plus compréhensible qui soit compréhensible pour la plupart des gens.

Qu'est-ce qu'une carte de ski de fond locale


Ainsi, une carte de ski de fond locale est ce que le robot voit à un moment donné.
Il s'agit des informations qui proviennent des "yeux" du robot et sont ensuite traitées et affichées sous une forme qui nous convient.

Si le robot reste immobile, sa carte locale dans des conditions environnementales constantes reste constante.

Si le robot se déplace, à chaque instant, son environnement est différent, respectivement, la carte locale change également.

La carte locale a généralement des tailles constantes. La taille est calculée en fonction de la longueur maximale des rayons émis par le télémètre. Dans mon cas, cette longueur est de 6 mètres.

Pour simplifier la tâche, il a été décidé de faire le carré de la carte. Il a également été décidé que le télémètre conditionnellement serait exactement au centre de la carte (cet endroit sera le point où x = y = 0). Le centre a été choisi de cette façon parce que le télémètre que j'utilise émet des rayons dans l'avion à plus de 180 ° (il émet des rayons à 240 °, mais plus tard), c'est-à-dire que certains rayons iront certainement derrière le scanner et si vous choisissez le mauvais centre, vous pouvez les perdre. Avec un bon choix du centre, tous les rayons seront correctement affichés. Sur cette base, j'ai fait la taille de la carte 2 fois plus grande que la longueur maximale des rayons émis.
La taille de ma carte est de 12 * 12 mètres.

image

Le capteur que j'ai utilisé


En fait, pour résoudre ce genre de problème, vous pouvez utiliser n'importe quel télémètre.
Le télémètre est un appareil pour déterminer la distance à quelque chose (dans mon cas, à un obstacle potentiel).

En robotique, on utilise principalement 2 types de télémètres: ultrasons et laser.
Les télémètres à ultrasons sont beaucoup moins chers, mais les rayons ultrasoniques sont suffisamment larges et ne conviennent pas pour des mesures précises.

Les télémètres laser sont plus chers, mais plus précisément, car leurs rayons sont étroitement focalisés.

Pour résoudre mon problème, j'ai utilisé un scanner laser Hokuyo URG-04LX-UG01. Ce capteur est capable d'émettre des rayons à 240 ° et fournit des informations assez précises sur les obstacles qui se sont opposés aux rayons. Sa portée maximale est de 5-6 mètres. Il est à noter que ce télémètre n'émet des rayons que dans le plan 2D. Ce fait vous oblige à placer le capteur sur le robot à un certain endroit, généralement devant le fond du robot, pour obtenir une image plus précise. Encore une fois, vous pouvez utiliser des scanners 3D, qui fournissent des informations beaucoup plus précises et complètes sur l'environnement, mais ils coûtent également beaucoup plus cher.

Je crois que ce scanner particulier est parfait pour s'entraîner au rapport qualité-prix.

image
Hokuyo URG-04LX-UG01

En bref sur le principe du scanner laser:
Le télémètre émet des rayons le long de l'avion. Un faisceau qui a rencontré un obstacle sur son chemin en est réfléchi et revient. Par la différence de phase entre les signaux émis et reçus, on peut juger de la distance de l'obstacle.

En conséquence, si le faisceau émis n'est pas revenu, à 5 - 6 mètres le long de la ligne droite de son émission, il n'y a pas d'obstacles ou le faisceau ne peut pas se refléter correctement.

image

Les données suivantes peuvent être obtenues à partir d'un scanner laser:

Pour chaque rayon émis:

  • Distance à un obstacle
  • Angle d'émission

* Chacun des paramètres est stocké dans un tableau séparé et correspond aux données pour l'un des rayons.

À propos de la création de cartes


Pour construire la carte et la dessiner, j'ai utilisé les outils ROS (Robot Operating System), à savoir: le programme Rviz et le type de données nav_msgs :: OccupancyGrid. J'ai créé un éditeur de la carte locale avec le type de message nav_msgs :: OccupancyGrid sous la rubrique locale_map correspondante. Dans Rviz, en vous abonnant à ce sujet, vous avez reçu des données sur la carte et les avez affichées sous la forme de type Carte.

Conformément à un tel algorithme, il était nécessaire de configurer par programme le traitement des données d'un scanner laser et de les enregistrer dans le format requis pour la transmission. Dans OccupancyGrid, une carte est stockée et transmise dans un tableau unidimensionnel.

Que se passe-t-il ici?
Pour ceux qui sont confrontés à ce type de données ROS pour la première fois: cela est inhabituel, car la carte est conventionnellement représentée comme un tableau bidimensionnel avec un certain nombre de colonnes et de lignes.

C'était donc avec moi. Je stocke la carte basée sur les données du scanner dans un tableau bidimensionnel et lors de la composition d'un message à envoyer à Rviz, je convertis le tableau bidimensionnel en le tableau unidimensionnel nécessaire à OccupancyGrid.

En fait, une carte dans OccupancyGrid n'est stockée et transmise que dans un tableau unidimensionnel. Lors du décryptage de ses données, il se transformera automatiquement en une carte carrée à deux dimensions.
Mais pour que cela se produise correctement, vous devez écrire ce tableau unidimensionnel d'une certaine manière.

À savoir: ligne par ligne à partir du stockage bidimensionnel pour écrire sur une seule ligne.

Voila! C'est tout le secret.

Un appel à n'importe quel élément d'un tel tableau unidimensionnel se produit comme suit:

localMap[mapSizej+i]


mapSize - taille de la carte locale
j est le numéro de colonne
i - numéro de ligne

Les cellules de la carte (toujours selon le type de données de l'OccupancyGrid) doivent avoir des valeurs comprises entre 0 et 100. Plus la valeur est basse, plus la probabilité que la cellule soit passable et vice versa est grande.

Pour simplifier la tâche, j'ai sélectionné 3 couleurs primaires pour colorer les cellules.

  • Blanc - Zone Passable = 0
  • Noir - Zone infranchissable = 100
  • Gris - zone inconnue = 50

Un point important!

Avant l'arrivée des données du scanner, la carte est complètement inconnue (valeurs de toutes les cellules = 50) et chaque fois après le dessin, elle est mise à jour à nouveau dans un état inconnu. Ceci est fait pour que la carte ne superpose pas les valeurs précédentes superflues. Après tout, une carte locale ne reflète l'état de l'environnement qu'à un moment donné.

image
Carte inconnue

Les rayons sont construits en utilisant une transformation à partir du système de coordonnées polaires (SCU)
au système de coordonnées cartésiennes (DSC).

$$ afficher $$ \ gauche \ {\ commencer {rassembler} x = r * cos φ \\ y = r * sin φ \ terminer {rassembler} \ droite. $$ afficher $$


x, y - nouvelles coordonnées dans DSC
r est la distance à l'obstacle
φ est l'angle auquel le faisceau a été lâché
r, φ - anciennes coordonnées dans le SCU

Algorithme de traitement des données du capteur:


Nous parcourons complètement les tableaux de distances r et d'angles φ des rayons (données UCS). Pour chaque élément, procédez comme suit:

  1. Nous transformons les coordonnées de UCS en DSC pour r et φ finis. Peignez la cellule résultante en noir. Ceci est un obstacle.
  2. On passe en ligne droite de l'emplacement du scanner à la cellule avec un obstacle à un certain pas, dans le cas le plus simple égal à la taille de la cellule.
  3. Encore une fois, nous convertissons les données de l'UCS en DSC et peignons la nouvelle cellule en blanc. Ceci est une zone piétonnière

image
L'exemple le plus simple de la façon de construire un chemin piétonnier vers un obstacle

Mais que faire si le faisceau émis ne revient pas?
Si cela arrivait, cela pourrait signifier ce qui suit:

  • Le rayon est "perdu", c'est-à-dire qu'il n'est pas entièrement réfléchi ou réfléchi dans l'autre sens
  • Il n'y avait aucun obstacle sur le chemin du faisceau et à cause de cela, il n'avait tout simplement rien à réfléchir

* Un rayon peut "se perdre" généralement parce qu'il n'a pas été réfléchi à un angle de 180 ° (c'est-à-dire sous tout ce qui ne remonte pas), car l'obstacle pourrait se tenir perpendiculairement au rayon. Et comme vous le savez de la physique: l'angle d'incidence est égal à l'angle de réflexion.

image

Ou parce que l'obstacle était trop noir et absorbait la majeure partie de l'énergie du faisceau et que le faisceau n'avait pas assez d'énergie pour revenir en arrière.

Ainsi, il est impossible d'être complètement sûr de ce qui s'est passé si le faisceau n'est pas revenu.

Que faire dans de telles situations?

Nous faisons ce qui suit:

  1. Nous considérons la distance à l'obstacle d'un tel faisceau comme possible pour le scanner (dans notre cas c'est 6 mètres)
  2. Nous considérons toutes les cellules en ligne droite à l'obstacle comme semi-passables et leur attribuons un nombre intermédiaire de 25. Ce sont des cellules passables, mais nous n'en sommes pas complètement sûrs.

Nous ne perdons rien si les rayons n'ont vraiment pas rencontré d'obstacles, et si une sorte d'obstacle a néanmoins échappé aux «yeux» du robot, alors il sera certainement détecté très rapidement.

Résolution de la carte


Enfin, la touche finale!

Chaque carte a la permission. Autrement dit, c'est le nombre de cellules qui peuvent tenir dans 1 cellule.

Par exemple
S'il y a 1 cellule dans 1 cellule (le cas le plus simple), alors résolution 1.
S'il y a 5 cellules dans 1 cellule, la résolution est de 0,2.

La résolution de ma carte est de 0,04. Autrement dit, dans chaque cellule, il y a 25 cellules. Ainsi, mon pas minimum est de 4 cm et 1 cellule est de 1 m.

image
Cellule et différence de cellule sur ma carte

Quel est le résultat?


image
Un exemple de construction d'une carte de ski de fond locale
* La couleur jaune indique les couleurs des cellules

Je crois qu'en général, le travail que j'ai fait a été réussi, mais je comprends que l'algorithme est imparfait et nécessite un raffinement et un raffinement.

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


All Articles