IMA4 2016/2017 P39
Sommaire
Cahier des charges
Présentation générale du projet
Contexte
Le laser est une technologie largement utilisé de nos jours dans de diverses applications. En effet, on retrouve cette technologie dans le domaine médical notamment pour la chirurgie oculaire ou encore dans industrie avec la découpe laser ou la soudure au laser.
Le laser est une émission de photons produit par excitation d'un milieu amplificateur (ex : CO2), le rayonnement produit est unidirectionnel et monochromatique. Ce sont ces propriétés que nous allons exploiter afin réaliser un projecteur laser qui mis en mouvement est capable de dessiner des formes sur une surface à l'instar de systèmes existants utilisés pour des effets lumineux lors de festivités.
Objectif du projet
L'objectif du projet est de créer un système de projection laser à plusieurs couleurs (au minimum deux) avec une application web pour programmer les formes à dessiner afin d'agrémenter des compétitions de gymnastique rythmique.
Description du projet
Le projet consiste à réaliser avec des lasers des figures géométriques par l'intermédiaire d'un système galvanométrique.
Notre premier travail sera de concevoir la partie projection. Pour cela, nous devrons aligner les lasers et les galvanomètres. En effet, ces derniers posséderont des miroirs à l'extrémité, ainsi les miroirs changeront d'inclinaison suivant le courant traversant les galvanomètres (similaire à l'image ci-contre). Il nous faudra également créer un système d'alimentation qui à partir d'une même source (réseau 230 V) sera capable d'alimenter les lasers et les galvanomètres ainsi qu'une Arduino et une Raspberry Pi.
Ensuite nous nous intéresserons à l'utilisation d'un système embarqué pour contrôler les galvanomètres et donc dessiner avec les lasers sur un plan 2D. En effet, le laser restera toujours fixe, seuls les galvanomètres, et donc les miroirs bougeront. Les galvanomètres étant contrôlés en courant il faudra réaliser une interface électronique pour convertir une commande en tension en commande de courant. La commande en tension sera assuré par une carte Arduino. Nous n'utiliserons qu'une seule paire de galvanomètres pour les deux laser. Il faudra donc multiplexer les deux faisceaux. La programmation des formes à effectuer, se fera par l'intermédiaire d'une application web PHP hébergée sur une RaspberryPi qui permettra de récupérer une image, d'y appliquer divers traitements et filtres afin d'en extraire les contours, et de calculer les commandes pour positionner les galvanomètres. Un serveur WebSocket également hébergé sur la RaspberryPi servira d'interface entre l'application web et L'arduino qui sera connecté via une liaison série sur la raspberryPI.
Comme animation de test, nous dessinerons le contour d'une gymnaste avec une couleur et son ballon d'une autre couleur. La gymnaste devra lancer son ballon, réaliser quelques difficultés et récupérer son ballon.
Choix techniques : matériel et logiciel
Nous utiliserons comme matériels :
- Deux lasers de différentes couleurs
- Une paire de galvanomètres à miroir
- Arduino
- Raspberry Pi3
- Alimentation 230V/5V 1A [1]
- Drivers galvanomètres x2
- Alimentation laser
- Lunette de sécurité x2 [2]
- Boitier ABS [3]
- DAC 4 canaux, avec interface I²C [4]
- Connecteur C14 [5]
- Câble secteur
Logiciel :
- Serveur web : Apache2, HTML5, PHP5, CSS
- Base de donnée : MySQL
- Serveur WebSocket : JQuerry, websocket
- Arduino : IDE Arduino
Calendrier prévisionnel
Liste des tâches à effectuer
Les différentes tâches à effectuer sont :
- Partie préliminaire : étude de fonctionnement des galvanomètres
- Déterminer comment est effectuée la commande des galvanomètres (protocole, tension...)
- Effectuer des tests avec l'Arduino ou la Raspberry Pi
- Effectuer des tests avec une LED à la place du laser
- Partie projection
- Fixer les lasers
- Aligner les lasers et les galvanomètres
- Créer le système d'alimentation
- Création d'un boitier
- Partie système embarqué
- Asservissement des galvanomètres avec l'Arduino
- Système électronique de commande en courant pour les galvanomètres
- Interface Web
- Installation et configuration Apache2
- Création d'une interface graphique simple
- Implémentation d'algorithmes de traitement d'image
- Mise en forme avec des CSS
- Sytème d'authentification avec mot de passe
- Utilisation d'une base de données pour enregistrer toutes les images déjà utilisés afin de les réutiliser
- Serveur Web Socket
- Récupération des données de l'interface web
- Mise en place de la liaison série avec l'Arduino
Calendrier
Répartition du temps consacré au projet (240h) :
- Partie projection : 80h
- Partie système embarqué : 40h
- Partie interface web et websocket: 120h
Feuille d'heures
Tâche | Prélude | Heures S1 | Heures S2 | Heures S3 | Heures S4 | Heures S5 | Heures S6 | Heures S7 | Heures S8 | Heures S9 | Heures S10 | Total |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Définition cahier des charges | 8 | 8 | 8 | 14 | 38 |
Avancement du Projet
Semaine 1
- Finalisation du cahier des charges avec les responsables
- Acquisition de matériels :
- Projecteur Laser
- Galvanomètres
- Alimentation des galvanomètres
- Listage du matériels à acquérir :
- Lunettes de sécurité
- DAC
- Alimentation 230V/5V 1A
- Boitier ABS
- ...
Semaine 2
- Obtention de l'arduino et de la raspberryPI
- Démontage du projecteur laser
- Deux lasers de classe 3b (vert et rouge)
- Circuit d'alimentation des deux lasers
- Initialisation du port série de la raspberryPI
- Modification du fichier config.txt dans la partition boot
- Ajout d'une ligne autorisant la communication série (enable_uart=1)
Semaine 3
- Installation du serveur apache sur la raspberryPI
- Modification du fichier /etc/network/interfaces (Static, Address, Netmask, Gateway)
- Modification du fichier /etc/resolv.conf (Adresse du serveur)
- Utilisation d'un proxy pour la récupération outils de programmation (Apache2, Php5)
- Mise en place du point d’accès wifi de la raspberryPI
- Récupération des logiciels nécessaires (dnsmasq, hostapd)
- Mise en place d'une adresse IP statique pour le point d'accès par l'intermédiaire du fichier /etc/dhcpcd.conf
- Désactivation de la négociation automatique de bail dans le fichier /etc/network/interfaces
- Configuration du logiciel hostapd /etc/hostapd/hostapd.conf
- Activation du démarrage automatique du point d'accès /etc/default/hostapd
- Configuration du serveur DNS par /etc/dnsmasq.conf
- Instauration de la page d'accueil de l'interface web à l'adresse 192.168.3.1
- Téléversement de fichiers images sur la page web et affichage de celle-ci
- Voyant de confirmation du bon fonctionnement du serveur web
- Développement du serveur websocket
Le développement du serveur websocket, initialement prévu en C (il était prévu de reprendre les sources utilisées l'année précédente dans le cadre des projet IMA3 SC), a finalement été réalisé en JAVA pour plusieurs raisons. Premièrement, un seul programme met en œuvre le serveur websocket, les divers traitements d'image, ainsi que les contrôles des galvanomètres (par l'intermédiaire des DAC) via la liaison I²C de la Raspberry Pi. Le langage JAVA fournit nativement des bibliothèques d'objets pour manipuler assez simplement des images, il existe également des librairies pour contrôler le port GPIO de la Raspberry et il était également intéressant de travailler avec un langage de plus haut niveau que le C. En outre, la totale portabilité de ce langage nous permet de travailler sur n'importe quelle machine et ensuite transférer notre programme sur la Raspberry Pi et l’exécuter sans même repasser par une phase de compilation. Et finalement, c'est le langage que nous étudions actuellement en cours de programmation orientée objet, ce qui permet de nous perfectionner.
Serveur WebSocket
N'ayant pas trouvé d'API WebSocket en Java satisfaisante (qui ne nécessitent pas l'installation et la configuration de nombreux outils additionnels), j'ai estimé plus commode et plus formateur de développer notre propre serveur WebSocket en se basant sur les librairies sockets de Java avec l'aide d'une documentation assez exhaustive [6].
Les WebSockets désignent à la fois un protocole réseau qui étend le protocole TCP ainsi qu'une API du World Wide Web. Nous nous en servons afin d'établir une communication asynchrone et bidirectionnelle entre un navigateur web et le serveur, notamment pour envoyer l'image à projeter. L’implémentation du serveur repose sur plusieurs étapes.
1) Connexion d'un client
2) Handshake : permet de faire le lien entre le protocole HTTP et WS. Le client envoie une requête HTTP demandant un upgrade de la connexion en protocole WS et le serveur répond en configurant la connexion (détail dans la documentation [7]).
3) Réception et décodage des messages : le serveurs reçoit des trames brutes, on extrait donc la taille du message ainsi que le message. De plus, les données son encodées (cryptage XOR) par un masque qui doit également être extrait.
4) Fermeture de la communication.
Le serveur supporte le multi-client il est donc nécessaire qu'il effectue ces étapes en "parallèle". Nous utilisons donc les threads ou fils d’exécution. Un thread est donc responsable d'attendre qu'un nouveau client se connecte et effectue le "handshake", il crée ensuite un thread associé à ce client afin d'établir un canal de communication. Il y a donc au moins un thread par client. Par la suite il faudra également implémenter une déconnexion automatique d'un client notamment après un timeout.
Exemple d’exécution du serveur avec deux clients qui se connectent et envoient un message :
Les clients sont des navigateurs web. Pour les tests nous avons repris les exemples utilisés dans le cadre das projets IMA3 SC avec le titre de la page HTML qui se colore en vert lorsque le client est connecté, et un champ de saisie pour envoyer des messages au serveur :
Semaine 4
- Mise en place d’algorithmes de traitement d'image
Détection de contour
L'objectif de notre projet est de pouvoir projeter n'importe quelle image envoyé grâce à l'application web. Pour cela nous allons tracer à une vitesse élevée les contours de l'image sur par exemple un mur grâce au laser. Il est donc nécessaire de détecter les contours de l'image grâce à plusieurs traitements.
Conversion en niveau de gris
Une des étapes préliminaires pour effectuer la détection de contour est de convertir l'image couleur en niveau de gris. Pour cela l'algorithme est simple : il suffit pour chaque pixel de l'image d'effectuer la moyenne des composantes rouge, verte, bleu de chaque pixel. En effet, si l'on considère une image matricielle (l'image est considérée comme un tableau à deux dimensions avec chaque case qui contient la couleur du pixel), chaque pixel contient les composantes RGB codées sur un octet. La couleur gris correspond aux composantes RGB égales. Le niveau de gris est donc codé de 0 à 255, avec 0 donnant du noir et 255 du blanc.
Filtre de Prewit et Sobel
Un contour est défini par un changement brutal d'intensité lumineuse, il s'agit donc de détecter selon plusieurs directions (au moins 2) ces changements. Il existe de nombreuses techniques afin de détecter les contours d'une image (gradient, Laplacien). L'une des techniques avec un rapport efficacité/temps d'exécution correct repose sur les algorithmes de Prewit ou Sobel. L'algorithme repose sur la convolution de matrices. Cela consiste à appliquer sur chaque pixel de l'image la matrice de Prewit définie comme
- ainsi que sa transposée :
Convoluer ces deux filtres sur l'image permet de détecter respectivement les contours verticaux et horizontaux.
D'après wikipedia [8], on obtient de meilleurs résultats en appliquant un filtre triangulaire, on introduit donc la matrice de Sobel :
On obtient le résultat suivant :
Pré-traitement : Flou Gaussien
Afin de réduire significativement le nombre de contours, il est nécessaire d'effectuer un pré-traitement avant la détection de contours. On utilise généralement un flou Gaussien afin de réduire les transitions lumineuses et ainsi réduire le nombre de contours. L’algorithme de flou Gaussien repose également sur la convolution de matrice sauf qu'ici la matrice filtre est générée grâce à une fonction gaussienne paramétrée par Sigma qui va directement impacter le niveau de flou. Plus la matrice de filtrage est grande plus la qualité du résultat est meilleure, mais le temps d’exécution devient également plus grand.
Voici la fonction de génération du filtre : où x et y correspondent au indices de la cellule de la matrice.
On obtient ce résultat :
On note un bien meilleur résultat. Cependant on remarque que les composantes horizontales ne sont pas correctement détectées il subsiste un problème avec le filtrage vertical que je n'ai pas réussi à identifier. De plus, il s'agit par sa suite d'éliminer les contours parasites ainsi que d'affiner le trait pour n'avoir plus qu'un pixel d'épaisseur.
Fichiers Rendus
Bibliographie
https://icn.fenelonlille.org/mediawiki/index.php/Projet_ICN_commun_2016/2017
https://www.g33k-zone.org/post/2016/05/11/Configurer-le-Raspberry-Pi-en-point-d-acc%C3%A8s-Wifi
http://stackoverflow.com/questions/22087076/how-to-make-a-simple-image-upload-using-javascript-html
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_a_WebSocket_server_in_Java
export http_proxy=http://proxy.polytech-lille.fr:3128