Si vous avez lu le premier article sur la présentation du Lidar X4 (vous pouvez retrouver l’article ici), alors voici la suite.
Dans cet article, nous allons nous pencher sur la partie logicielle et en particulier sur la récupération de données Lidar via Python et l’affichage sous un format exploitable en utilisant la librairie PyGame. Voici ci-dessous un séquençage de notre objectif du jour:
Objectifs
- Connecter le Lidar à un PC et être en mesure de récupérer des données
- Développer une interface en Python/pygame pour visualiser les données
- Afficher les données sur cette interface
Commençons donc tout d’abord par voir comment connecter le Lidar et récupérer les données.
Récupération des trames de données Lidar via USB
Dans un premier temps, nous allons devoir installer le driver permettant de communiquer avec la carte d’acquisiton de données fournies avec le lidar. Cette carte se base sur une puce CP2102 pour initier le lien UART/USB. On doit donc installer le driver correspondant que l’on pourra trouver sur le site de YDLidar à l’adresse suivante: https://www.ydlidar.com/dowfile.html?id=97
Sous Linux, vous n’aurez même pas à installer de driver, la connexion devrait directement être fonctionnelle. Pour la suite du projet, puisque nous travaillerons sous Python, nous allons devoir installer la librairie « PyLidar3 » via pip:
pip install PyLidar3
Si l’installation se déroule correctement, vous serez prêt à développer et à récupérer des trames de données. Vérifions cela rapidement grâce au script suivant:
from PyLidar3 import YdLidarX4
lidar = YdLidarX4("COM3")
print(lidar.Connect())
print(lidar.StartScanning())
En remplaçant « COM3 » par le port sur lequel votre Lidar est connecté. Vous pouvez retrouver cette information en effectuant un clic droit sur « Ce PC » dans l’explorateur de fichier, en sélectionnant « Gérer » puis « Gestionnaire de périphériques »
Si vous n’avez pas d’erreur dans la console et que vous recevez la sortie suivante:
True
<generator object YdLidarX4.StartScanning at 0x00000253F60A3580>
C’est que votre Lidar et la communication est fonctionnelle.
Il nous reste à développer un utilitaire de visualisation et à y intégrer les données.
Développement de l’utilitaire de visualisation
Dans un premier temps, nous allons installer pygame de la même manière dont nous avons installé PyLidar3:
pip install pygame
PyGame est une librairie Python avec un ensemble d’outil pour la manipulation d’éléments graphiques, sonores, input, etc… Bref, tout ce qu’il faut pour un petit jeu en Python. Pour notre part, cela permettra d’utiliser rapidement des éléments graphiques pour générer notre fenêtre.
Il faut voir un programme vidéo comme une succession de fonctions élémentaires:
- Création de la fenêtre
- Gestion de la boucle d’évènements
- Gestion des inputs utilisateur (clavier, souris, etc…)
On va donc prendre ces étapes une à une.
Création de la fenêtre
On commence par importer pygame:
import pygame
On initialise ensuite pygame, on définie la hauteur/largeur de la fenêtre et son titre:
WIDTH = 720
HEIGHT = 480
pygame.init()
pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("LIDAR")
Gestion de la boucle d’évènements
On crée ensuite la boucle d’évènements:
screen = pygame.display.get_surface()
running = True
while running:
screen.fill((33, 33, 33))
pygame.display.update()
Ici, on récupère la surface de la fenêtre pour pouvoir « dessiner » dessus, on crée une boucle while dans laquelle on vient effacer toute la fenêtre à chaque itération. Cela nous permet par la suite de pouvoir afficher nos données comme on le souhaite.
Gestion des inputs utilisateur
On va ajouter une entrée souris pour quitter proprement le logiciel lors du clic sur la croix en haut à droite:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
Puis en sortie de la boucle while:
pygame.quit()
Au total, on a le script suivant:
import pygame
WIDTH = 720
HEIGHT = 480
pygame.init()
pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("LIDAR")
screen = pygame.display.get_surface()
running = True
while running:
screen.fill((33, 33, 33))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.update()
pygame.quit()
Et vous devriez obtenir votre première fenêtre à l’exécution
Affichage des données sur l’interface
On commence par reprendre les briques de tests qui nous ont permis de tester le fonctionnement de la liaison au Lidar et on les intègre à notre outil de visualisation:
import pygame
from PyLidar3 import YdLidarX4
from math import cos, sin, pi
import sys
lidar = YdLidarX4("COM3")
if not lidar.Connect():
sys.exit(1)
WIDTH = 720
HEIGHT = 480
pygame.init()
pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("LIDAR")
scan = lidar.StartScanning()
screen = pygame.display.get_surface()
running = True
while running:
screen.fill((33, 33, 33))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.update()
pygame.quit()
Puis on crée une nouvelle surface qu’on appellera « scope » sur laquelle on vient tracer les données du Lidar, tout cela sera intégré dans la boucle d’évènements:
scope = pygame.Surface((WIDTH, HEIGHT))
scope.fill((33, 33, 33))
data = next(scan)
maxKey = max(data, key=data.get)
maxValue = data[maxKey]
for angle in data.keys():
distRelative = data[angle] / maxValue
dist = (HEIGHT / 2) * distRelative
angleRad = angle * pi / 180
pygame.draw.line(scope, (255, 0, 0), (round(WIDTH/2), round(HEIGHT/2)), (round(WIDTH/2 + dist*cos(angleRad)), round(HEIGHT / 2 + dist*sin(angleRad))), 3)
Discutons de ces quelques lignes. Dans un premier temps, on crée une surface, de la taille de l’écran, que l’on vient remplir de gris pour la nettoyer. On lit ensuite les nouvelles données du scan, on récupère la clé de la valeur maximale et sa valeur (cela permettra de faire une mise à l’échelle).
On parcours ensuite toutes les données en fonction des position angulaire et on vient tracer une ligne d’un longueur relative à la mesure effectuer. On travaille en coordonnées cylindriques, c’est à dire qu’un point est défini par un angle et une longueur, d’où les cos et sin.
On intègre tout cela dans la boucle d’évènements:
import pygame
from PyLidar3 import YdLidarX4
from math import cos, sin, pi
import sys
lidar = YdLidarX4("COM3")
if not lidar.Connect():
sys.exit(1)
WIDTH = 720
HEIGHT = 480
pygame.init()
pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("LIDAR")
scan = lidar.StartScanning()
screen = pygame.display.get_surface()
running = True
while running:
screen.fill((33, 33, 33))
scope = pygame.Surface((WIDTH, HEIGHT))
scope.fill((33, 33, 33))
data = next(scan)
maxKey = max(data, key=data.get)
maxValue = data[maxKey]
for angle in data.keys():
distRelative = data[angle] / maxValue
dist = (HEIGHT / 2) * distRelative
angleRad = angle * pi / 180
pygame.draw.line(scope, (255, 0, 0), (round(WIDTH/2), round(HEIGHT/2)), (round(WIDTH/2 + dist*cos(angleRad)), round(HEIGHT / 2 + dist*sin(angleRad))), 3)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.blit(scope, (0, 0)) # Cet appel permet d'afficher la surface scope sur la surface screen et donc sur la fenêtre
pygame.display.update()
pygame.quit()
Et vous devriez obtenir le résultat suivant:
Conclusion
Dans cet article, nous avons vu comment créer un utilitaire de visualisation de nos données. Il est évidemment améliorable et vous en trouverez des versions améliorées sur norte dépôt github:
https://github.com/SimpleDuino/Lidar-examples
avec notamment une version en orienté objet, bien plus simple à manier par la suite.
Nous aurons l’occasion de réutiliser cet utilitaire lorsqu’il s’agira d’entrainer un réseau de neurones à identifier des menaces ou des objets dans son environnement proche.
En tous les cas, mesurez le chemin parcouru. Vous avez été en mesure de développer un petit logiciel en fenêtre pour visualiser un flux de données à priori complexe.
Si vous souhaitez aller plus loin, vous pouvez chercher à implémenter par vous même les améliorations que nous avons réalisé:
- Possibilité de personnaliser l’angle de mesure (et donc l’angle d’affichage)
- Affichage de cercles à des distances connues pour mettre en place une échelle et donc mieux lire les données
- Travailler en orienté objet, avec un objet Lidar