GroundCTRL




 * UE/Module: Projet innovant de RICM4 option CM
 * Enseignant: Didier Donsez (avec le support gracieux de TagSys)
 * Élèves: 3 RICM4 	L. Dauvergne, F. Levêque, R. Ngouala. Voir la page de suivi ici

Description
L'idée de GroundCTRL est de projeter sur le sol d'un hall d'accueil de bâtiment des informations contextuelles au pied des personnes qui entrent dans le bâtiment. Les informations affichées seront l'emploi du temps du jour avec les emails de la personne ainsi qu'un flux de type Twitter. Par défaut, un message de bienvenue s'affiche sans que l'utilisateur soit authentifié.

Pour s'authentifier, une personne a besoin de s'enregistrer dans une base de données. Elle pourra ensuite s'identifier grâces aux technologies suivantes: RFID UHF, NFC, QRCode.



Une fois authentifiée, la personne accédera à ses informations pendant un certain temps (20-30 secondes). Ensuite, le système retournera dans son état initial et une nouvelle personne pourra s'authentifier.

Ce projet a été réalisé dans un esprit de modularité et compatibilité du système conçu avec de futures extensions (du point de vue logiciel ou matériel).

Cœur du système
Au départ, le cœur du projet devait être développé en Java. Pour des raisons de flexibilité dans le développement et l'utilisation de notre logiciel, nous avons progressivement opté pour réaliser notre programme principal à base d'un script PHP avec l'aide de Javascript et Ajax.

/* A COMPLETER */

Méthodes d'authentification
Dans un but de simplicité et d'évolution du système, nous avons opté pour un système d'authentification flexible. D'un côté nous attendons sur un port et de l'autre, différents programmes écrits dans différents langages envoient les données qu'ils récupèrent (les identifiants des utilisateurs) sur le port correspondant. L'application principale peut ainsi afficher une information personnalisée à l'utilisateur.



QrCode
Le module QrCode permet la détection et le décodage de QR code grâce à un flux vidéo venant d’une caméra.

Pour l'authentification par QrCode, nous avons choisi d'utiliser une variante en Python du programme Zbar. Zbar nous a permit, contrairement à d'autres lecteurs de QrCode que nous avons essayé, de bénéficier des avantages suivants:

- Multiplateforme (utilisé sous linux mais disponible pour Windows

- Performant (scan des QrCodes instantanément, même ceux qui sont peu visibles)

- Flexible (scan aussi bien des codes-barres que des QrCode)

Pour nous permettre de pouvoir renvoyer les QrCode sur un port, nous avons dû implémenter un script qui effectue le travail. Voici un extrait du script ci dessous:

Il est basé sur l’algorithme suivant :

-	Détection du QrCode et de son sens dans une image -	Reconnaitre le format et différencier les bits 1 ou 0 -	Découvrir la région à décoder -	Récupération des données et du code correcteur -	Correction des erreurs (si erreurs) -	Décodage du code





La détection se fait grâce au format spécifique d’un QR Code. En effet, il possède des carrés sur 3 de ces côtés. Il est alors possible détecter le code dans tous les sens.

Grâce à ces carrés, il est aussi possible de récupérer la structure (taille des motifs,…) du QR code. Le carré noir extérieur permet de définir la taille des motifs dans le code.

Dès lors, il est possible de récupérer des informations du code. Sur la figure 1, nous voyons les différentes parties du code.

Il faut tout d’abord lire les données sur le format et la version du message. Ces informations vont permettre de connaitre la dimension du symbole ainsi que le niveau du code de correction (4 niveaux qui permettent de définir le pourcentage maximum du message qui peut être perdu sans endommager le décodage) et le mode d’encodage.

Lorsque le QR code est déformé (code incliné,…), les motifs d’alignements permettent de corriger la distorsion formée (utilisé pour des QR code de grande taille). En effet, il suffit de calculer la variation entre la position estimée du centre du motif et la position réelle du centre permet d’avoir un rapport pour corriger le symbole.

Pour les petits symboles qui n’ont pas de motifs d’alignements, il est possible d’utiliser les « timing pattern » pour reformer le motif linéaire

Sur la figure 2, nous voyons le découpage des données utiles et du code correcteurs pour permettre la lecture. Les données sont découpées selon le mode d’encodage défini (par exemple 8 bits par caractères pour le codage d’octet). Il suffit donc de découper les données en blocs (de 8 motifs) et de récupérer la valeur.

Nous avions tout d’abord essayé de réaliser notre décodeur, cependant nous étions bloqués lors de la lecture des caractères. La détection nécessitait d’avoir une image très proche et non déformée (ce qui est contraignant dans notre projet).

Nous avons donc décidé d’utiliser une librairie open-source Python nommé zbar qui réalise la détection et la correction du motif (si distorsion). Notre choix c’est porté sur cette librairie car lors de la lecture du flux vidéo, il y a un traitement de l’image qui permet un décodage à la volé très rapide.

NFC
Pour les Tag NFC, nous avons utilisé le matériel prêté par Mr Donsez. Il s'agit d'un capteur Tikitag (maintenant connu sous le nom de Touchatag), fabriqué à partir d'un capteur ACR 122U (fabriqué par ACS, voir ici).

Pour l'utiliser, nous avons adapté un programme Java réalisé par Mr Donsez. Ce dernier nous permet maintenant de récupérer l'identifiant du tag NFC et de le renvoyer sur le port associé au programme.

La reconnaissance des tags NFC se fait très rapidement et ne pose aucun souci.

Il faut néanmoins faire attention aux librairies utilisées sous Ubuntu. Notre lecteur RFID n'arrivait pas à être reconnu sous Ubuntu. Nous avons longtemps cherché avant de trouver la solution ci-dessous qui consistait à manuellement pointer les librairies que nous utilisons "pcsc_tools". Ceci est dû au fait que par défaut, l'API Java cherche libpcsclite.so dans les dossiers /usr/lib:/usr/lib64:/usr/local/lib:/usr/local/lib64. Cependant, sous Ubuntu, elle se situe dans le dossier /lib.

Nous avons donc pu résoudre notre problème en choisissant l'une des commandes suivantes:

-Déplacer la librairie: sudo ln -s /lib/libpcsclite.so.1 /usr/local/lib64/libpcsclite.so

-Définir la librairie à l’exécution du programme: java -Dsun.security.smartcardio.library=/usr/local/lib/libpcsclite.so TestSmartCardIO

-Rechercher le fichier dans /lib dans le code: File libPcscLite = new File("/lib/libpcsclite.so.1"); if (libPcscLite.exists) { System.setProperty("sun.security.smartcardio.library", libPcscLite.getAbsolutePath); }

Il va de soi que la troisième solution est la moins adaptée car elle n'est pas robuste en cas de changement de plate-forme.

RFID
/* A completer par Rolly */

Interface
/* A Completer par Rolly */

Contrôle de l'image
Pour pouvoir orienter l'image vers l'utilisateur, nous avons opté pour un système de redirection d'un flux provenant d'un vidéoprojecteur. Au départ, une lentille correctrice devait servir à concentrer le flux devait nous être fournie mais elle ne le fût pas. Nous avons pu obtenir de l'IMAG un vidéoprojecteur suffisamment performant pour effectuer nos expérimentations.

Pour permet une aisance dans nos expérimentations, le système se devait d'être facilement démontable. Nous avons donc fabriqué un bras "fait maison" en y intégrant les servomoteurs fournis par Mr Donsez.

Bras articulé


Nous étions partis sur l'idée un bras fixe mais dès que nous avons appris que notre système ne sera pas définitif nous nous sommes rapidement orientés vers un bras facilement démontable et adaptable à tout type de scénario.

Nous avons donc choisi de réaliser un bras à partir d'un pied de lampe de bureau en adaptant le bout de celle-ci avec des équerres, elles-mêmes fabriquées sur mesure à partir d'aluminium brut. Une première version de ce bras fût fabriquée mais l'équerre utilisé était trop souple et générait trop de mouvement dans le bras. Une deuxième version fût donc construite pour remédier à un maximum de problèmes.

La deuxième version est donc beaucoup plus satisfaisante, elle est suffisamment souple pour s'adapter à tous les scénarios et fourni des performances acceptables. Nous regrettons néanmoins le fait que l'image à tendance à trembler un peu, ceci pourrait être réglé en réalisant une installation fixe du vidéoprojecteur et de ce système de déviation d'image.



Pour permettre un maximum de mouvement de l'image, le bras peut se déplacer en avant et en arrière (sa base est pivotante). Le miroir peut quant à lui bouger de 180° dans les deux axes de rotation.

Voici un schéma de présentation du bras:



Néanmoins, dans le cadre de ce projet, le miroir bouge seulement d'une dizaine de degrés sur chaque axe. Le reste nous servant de marge pour positionner l'image idéalement pour l'utilisateur.

La première expérimentation avec le système de servomoteurs est disponible ici : http://vimeo.com/37984555

Voici une présentation effectuée après calibrage: http://vimeo.com/40961428

Arduino
Pour contrôler les servomoteurs du bras, notre choix s'est immédiatement porté sur la solution Arduino. En effet, un membre du groupe avait déjà travaillé avec (a des fins personnelles), la prise en main fût donc rapide.

Au fil du développement, nous avons retenu deux types de programmes: un programme pour permettre de contrôler pas à pas les servomoteurs et un autre programme pour envoyer une inclinaison directement à l'un des deux servos.

Le contrôle des servomoteurs par notre programme se fait par l'intermediaire de la librairie libserial (5.2 ou supérieur). Il est nécessaire d'ajouter l'argument « -lserial » lors de la compilation pour que gcc puisse prendre en compte le code relatif à libserial.

L'ajout de la liaison série avec l'Arduino au sein d'un programme CPP se fait de la façon suivante : using namespace std; using namespace LibSerial; SerialStream ardu; void open{ ardu.Open(PORT); ardu.SetBaudRate(SerialStreamBuf::BAUD_9600); ardu.SetCharSize(SerialStreamBuf::CHAR_SIZE_8); }
 * 1) include 
 * 2) define PORT "/dev/ttyACM0"

Attention, la ligne "/dev/ttyACM0" dépend entièrement de votre configuration locale, il va de soit que cela peut changer selon la machine ou le port USB sur lequel vous branchez le périphérique.

Le premier programme développé est disponible [/*HERE*/ ici], il permet le contrôle pas à pas des servomoteurs.

Le deuxième programme est disponible [/*HERE*/ ici]. Il nous permet de rentrer directement l'inclinaison des miroirs dans notre programme OpenCV avec le code suivant:

ardu<<finalx; ardu<<"a"; ardu<<finaly; ardu<<"b";

Dans ce code, nous envoyons d'abord l'angle souhaité et ensuite le code du servomoteur associé.

OpenCV
OpenCV est une librairie de fonction pour le traitement d'images, c'est cette librairie qui a été utilisé au sein de ce projet. /* IMAGE A INSERER ICI */

Installation
Concernant Opencv, nous avons choisi d'utiliser ce dernier avec Linux. Nous avons utilisé la version 2.2.1 de OpenCV ainsi que la version 2.3.1.

Pour l'installation, nous avons suivi différent tutoriels disponibles sur internet (les liens sont disponibles dans la rubrique liens). Néanmoins, celui qui nous a permit d'installer correctement OpenCV en corrigeant les erreurs associés est celui-ci(Google traduction vous sera utile si vous ne parlez pas encore couramment le russe).

Nous avons testé OpenCV 2.3.1 avec Ubuntu 10.04 sous machine virtuelle dans un premier temps. Ensuite, il a été installé sur Kubuntu(Ubuntu marcherait tout aussi bien) 12.04 pour des raisons de faibles performances de la machine virtuelle.

Nous sommes contraints d'utiliser la distribution 12.04 de Kubuntu pour des raison de compatibilité entre zbar et Opencv, en effet, les deux utilisent une seule et même librairie mais dans différentes versions.

Seul un Ubuntu en version > 11 nous apportait une compatibilité avec zbar et Opencv installés en même temps. Nous n'avons pas effectué de tests sur un autre distribution de Linux.

Utilisation
Nous avons ensuite cherché et adapté des modules pour la détection des personnes. Nous avons effectués beaucoup de tests sur cette partie car suivant les différents scripts et codes, les résultats variaient énormément.

Notre choix final se porte sur un script de reconnaissance "fullbody"(inclut dans OpenCV) avec un programme CPP qui permet de faire le lien entre l'image capturée et les servomoteurs en calculant le déplacement nécéssaire de ces derniers. Le programme CPP, calibré pour notre expérimentation est disponible dans l'archive fournie en bas de page.

Dans le programme, il convient de choisir correctement le périphérique d'entrée ainsi que la résolution associée. Voici les lignes à modifier : CvCapture* capture = cvCaptureFromCAM(0);; cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 320); cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 240);

La première sert à choisir le périphérique de capture vidéo, les deux suivantes permettent de choisir la résolution. Attention: Avec notre PC de démonstration (core i3), toute résolution supérieure à 320*240 provoquait de grosses saccades dans traitement. Nous nous sommes donc limité à cette dernière.

Vous pouvez voir un aperçu du résultat dans la vidéo disponible ici.

Nous estimons que les résultats sont satisfaisants. Nous pourrions arriver à un meilleur résultat avec une installation fixe et définitive, car cela aurait permit un meilleur calibrage.

Récupération des informations
/* A COMPLETER */

Emplois du temps
/* A COMPLETER */

Mails
/* A COMPLETER */

Twitter&Co
/* A COMPLETER */

Code
Nous mettons à disposition le code que nous avons écrit pour le projet dans l'archive suivante. /* A COMPLETER */

Méthode de travail
Pour mener à bien notre projet, nous avons utilisé le logiciel Kunagi, qui permet de mettre en place facilement et rapidement la méthode de travail Scrum, ceci nous a permet de nous rappeler les différentes tâches qu'il restait à faire tout au long du projet.

Ce logiciel est entièrement Open-Source, ce qui est très positif face aux logiciels qui coûtent plusieurs milliers d'euros et dont nous n'avons pas l’utilité.

Matériel & Budget
Ce projet n'a bénéficié d'aucun budget.

La majeur partie du matériel nous a été prêté et sera donc rendu à la fin du projet. Nous remercions toutes les personnes nous ayant prêté du matériel: la société TagSys(pour le lecteur RFID), Gérard Forestier du service informatique de l'IMAG, Didier Donsez, Jean-Yves Mayvial(pour le bras de lampe, les bouts d'aluminium, ses vis et son atelier).

Prété par Polytech
/* A CORRIGER */
 * 1 Mac mini (Non utilisé)


 * 1 Webcam PS3


 * 1 projecteur longue focale (Toujours en attente au 06/03/2012, emprunté le 20/04/2012 au responsable des services informatiques de l'IMAG)


 * 1 lecteur NFC Tikitag


 * 4 Mirroirs IKEA


 * 1 lecteur RFID UHF longue distance (lecteur Impinj R420 prété par TagSys) - Géré par Rolly


 * Quelques tags NFC


 * Arduino + 2 servomoteurs rapides et puissants + miroir + pan/tilt servo bracket pour diriger le faiseau (si intensité lumineuse trop faible) ** voir Face Tracking with a Pan/Tilt Servo Bracket

Prêté par les étudiants

 * 1 Bras articulé avec fixation pour pouvoir utiliser les servo-moteurs convenablement mais avec une forte contrainte de portabilité du système - Géré par Léopold

Logiciels & Technologies utilisées

 * OpenCV


 * Arduino


 * Eclipse


 * Ajax


 * Javascript


 * PHP

Liens externes
/* A COMPLETER */

Partie Coeur
/* A COMPLETER */

Partie OpenCV
[http://robocraft.ru/blog/computervision/435.html OpenCV шаг за шагом. Установка OpenCV под OC Linux]

Sony PlayStation Eye driver install instructions

How to install OpenCV 2.3.1 in Ubuntu 11.10 Oneiric Ocelot with Python support

New entry to Debian bug: libcv-dev: error: 'ptrdiff_t' does not name a type

Circle recognition using openCV

Face Detection using OpenCV

Suivi de balle par une tourelle pan (1 servomoteur) à partir d'une interface Processing - version 2 - avec GSVideo - plus rapide !

OpenCV + Java + Linux

openframeworks

Arduino + Servo + openCV Tutorial openFrameworks

Partie Arduino
Interfacing Arduino with C++ and libSerial. undefined reference to `LibSerial::SerialStreamBuf::showmanyc' LibSerial Documentation Controlling two servos through serial

Partie NFC
Présentation de la technologie NFC par Nokia

Support MeeGo by creating your own Meegon

QrCodes
python-zbar (0.10+doc-4)

Open Source QR Code Library

Processing QRCode Library

Yawcam

Cambozola V0.92