Ce projet avait pour but de déterminer un objectif à atteindre dans une image afin de permettre à un robot de naviguer en toute autonomie et en évitant les obstacles. En effet, il est possible pour un robot de naviguer dans une map connue grâce au SLAM (Simultaneous Location And Mapping). Le SLAM nécessite de connaître l'environnement à travers une map réalisée au préalable.
L'objectif ici était de permettre la navigation sans avoir de cartographie de l'environnement et en évitant les obstalces. Pour cela l'idée était de faire reconnaître la route à un robot via une caméra et lui faire suivre le point le plus haut de la route dans l'image.
Pour reconnaître la route, je me suis appuyé sur un modèle de Fully Convolutional Networks. Ce modèle a été pré-entraîné par Nvidia et est nommé Segnet. Il a été choisi afin d'utiliser l'algorithme sur des routes extérieures mais aussi dans des couloirs de bâtiments. Puisque seule la classe de la route est utilisée, il est possible de déterminer le chemin sans tenir compte des obstacles sur celle-ci.
Ce projet a été développé sur une Jetson Nano de la marque Nvidia et pouvait fonctionner à plus de 60 FPS comme le montre l'image animée ci-contre. Une fois l'objectif fixé (point en rouge sur le GIF), il était possible de déterminer le chemin pour y accéder.
Récupération de la route dans le mask produit par Segnet.
Le mask a été récupéré seul afin d'améliorer les performances de l'algorithme.
Conversion de l'image en graphe de nœuds (ici les nœuds sont des cases et les liens entre les cases sont leur adjacence).
Une fois le graphe obtenu, un premier Breadth-First Search (parcours en largeur) est effectué et sert de filtre. Ce parcours en largeur a été inspiré du jeu Number of Islands et permet de garder la zone du graphe comportant le plus de nœuds et de supprimer le bruit (ici représenté par des cases détachées du graphe, voir image de l'étape 3).
Recherche du chemin sur la portion de la route grâce à un Breadth-First Search en partant du centre bas de l'image vers l'objectif.
L'objectif était placé sur la case la plus haute du graphe. Pour ce qui est de sa coordonnée x, cette dernière était calculée en faisant la moyenne des coordonnées x des cases les plus hautes du graphe.
Avant d'implémenter un parcours en largeur, mon idée était de déterminer l'angle séparant l'objectif dans l'image et le centre bas de l'image puis de faire suivre cette trajectoire à un robot en adaptatant son orientation grâce à un IMU.
Breadth-First Search
A-STAR (A*)
Le choix s'est porté sur un parcours en largeur plutôt que l'algorithme A*, car suite à certains tests il a été déterminé que le BFS est plus efficace dans certaines situations comme le montrent les images ci-dessus.
On peut lire 0,30 seconde pour le parcours en largeur et 0,94 pour le A* étant donné qu'il a fallu calculer l'heuristique pour un grand nombre de cases.
Ce projet n'a pas donné de résultats très convaincants. En effet, le modèle Segnet a été entrainé pour reconnaître de nombreuses classes et n'est pas spécialement conçu pour reconnaître précisement une route, ce qui entraînait malheuresement trop de bruits et d'imprécisions. Il aurait fallu se concentrer soit sur la navigation intérieur ou la navigation extérieure. Une possibilité aurait été d'entraîner un modèle spécifique pour reconnaître les routes extérieures ou utiliser un modèle entraîné sur un datatset comme Cityscapes.
Cependant, ce projet laisse entrevoir la possibilité d'inclure un évitement d'obstacles sur la trajectoire d'un robot. En effet, si un robot possède une cartographie globale, il pourra donc se déplacer d'un point A vers un point B. De ce fait, ce projet pourrait permettre au robot de déterminer un chemin dans sa local map (partie visible grâce à sa caméra), et adapter sa trajectoire en fonction de cette dernière sans trop s'éloigner de la trajectoire dictée dans la global map.
Les librairies ROS et OpenCV ont été utilisées afin de récupérer grâce à un subscriber la segmentation d'images de segnet, publiée sur un rostopic par le node ros_deep_learning.
Ce projet a été réalisé en Python en utilisant les librairies : OpenCV, Numpy, Pygame, Collections (pour le pathfinding) et Time.
Pygame a permis la conversion des pixels de l'image en grille de case pour y implémenter l'algorithme de pathfinding.