\documentclass[a4, 9pt]{report} \usepackage[latin1]{inputenc} \usepackage[T1]{fontenc} \usepackage[francais]{babel} \parskip=5pt \usepackage{graphicx} \title{Rapport de Projet Individuel :\\ Logiciel de contrôle de robots Khepera II\\-\\Master 1 Informatique\\Université de Lille1} \date{\today} \author{Guillaume Libersat} \begin{document} \maketitle \tableofcontents \chapter*{Remerciements} Je tiens à remercier Monsieur \textsc{Philippe PREUX} de m'avoir permis de travailler sur ce sujet de stage ainsi. Je tiens aussi à le remercier de nouveau ainsi que Monsieur \textsc{Manuel LOTH} pour leur accueil et leur suivis tout au long du semestre. \chapter{Introduction} \section{Le projet} \subsection{Contexte} Le projet a été réalisé dans le cadre de l'unité d'enseignement « Projet Individuel » du second semestre de Master 1 d'informatique. Ce stage se déroule dans un laboratoire, habituellement au sein d'une équipe de recherche des Universités de Lille et est encadré par une personne de l'équipe en question. Le projet se déroule sur toute la période du semestre, c'est à dire de Février à Juin 2007. Les élèves sont mis en autonomies et doivent accomplir les tâches annoncées lors de la publication du sujet. \subsection{Présentation du sujet} Le sujet que j'ai choisi concerne la mise en place d'une interface logicielle de communication avec des robots de type Khepera II. Ce type de robots est un modèle construit par la société \textsc{K-Team Corporation} qui a pour but la création de robots spécifiques à la recherche et à l'éducation. Les robots de la \textsc{K-Team} sont internationalement reconnnus et sont utilisés par plus de 500 universités et industriels dans le monde entier. \subsection{Objectifs} Le premier objectif du projet est de \textbf{réaliser un interprêteur de commandes} permettant de donner des ordres aux robots (avancer, tourner, etc). Il doit aussi être possible de \textbf{récupérer les informations liées à leurs capteurs}. Le second objectif est de réaliser un logiciel qui permettra \textbf{l'accès à ces robots à travers le réseau}. Enfin, si le temps le permet, le sujet indique qu'il est envisageable d'expérimenter des applications du robot sur le terrain : localisation, cartographie, etc. \subsection{Contraintes et prérequis} Le sujet énonce clairement les contraintes suivantes : le travail doit être réalisé sous \textbf{GNU/Linux} et de préférence dans le \textbf{langage C}. Il est aussi précisé que toute la documentation disponible est en anglais et qu'il est donc nécessaire d'être capable de lire cette langue. \section{L'environnement} Le sujet a été proposé par Monsieur \textsc{Philippe PREUX} de l'équipe du \textsc{GRAPPA}. \textsc{GRAPPA} signifie \emph{Groupe de Recherche sur l'Apprentissage Automatique}. Elle est en majorité localisée à Lille3 mais aussi à Lille1 (Bâtiment M3). Cette équipe regroupe une quinzaine de personnes. L'équipe GRAPPA fait partie du LIFL (Laboratoire Informatique Fondamental de Lille1) qui est une UMR\footnote{Unité Mixte de Recherche} CNRS. De celle-ci sont nés deux projets INRIA : MOSTRARE (dont \textsc{Rémi GILLERON} est reponsable) et SEQUEL (dont \textsc{Philippe PREUX} est responsable). SEQUEL, maintenant située dans les locaux de l'\textsc{INRIA} au Parc de la Haute Borne à Lille1, est actuellement composée d'une quinzaine de personne. C'est dans cette équipe que j'ai réalisé mon stage. Le thème général de l'équipe est l'apprentissage automatique, c'est à dire l'élaboration d'algorithmes qui s'améliorent avec l'expérience. Quatre robots Khepera II ont été achetés par l'équipe dans le cadre d'expérimentations liées à l'apprentissage. C'est pourquoi, l'équipe nécessite une base applicative pour pouvoir mettre en \oe{}uvre ses expériences. \chapter{Mise en \oe{}uvre} \section{Découverte du robot} Avant de réaliser quoi que ce soit avec le Khepera, j'ai préféré tout d'abord lire la documentation fournie avec celui-ci. En effet, je n'avais jamais travaillé avec ce genre de matériel et n'avait aucune idée sur le fonctionnement ni les capacités de ce genre de périphériques. J'ai ainsi pu avoir un tour d'horizon des possiblités de la machine ainsi que les précautions à prendre pour l'utiliser. \subsection{Physiquement} Le robot Khepera II est un concentré de technologie contenu dans 70 mm de diamètre. Il se présente comme sur la figure \ref{fig:khepera}. \begin{figure}[!h] \centering \includegraphics[scale=0.3]{images/khepera.jpg} \caption{Le Khepera II} \label{fig:khepera} \end{figure} Il dispose de deux roues, à vitesse variable, pour se déplacer. Seize capteurs sont situés à intervalle régulier tout au long de sa circonférence. On distingue deux types de capteurs : \begin{enumerate} \item Les capteurs infrarouges de présence, qui réagissent à l'approche d'un objet ; \item Les capteurs de luminosité, sensibles à l'intensité de la lumière. \end{enumerate} \medskip \begin{figure}[!h] \centering \includegraphics[scale=0.7]{images/schem_khep.png} \caption{Anatomie d'un Khepera} \label{fig:schem_khep} \end{figure} On peut aussi lui associer des tourelles d'extension afin d'augmenter ses capacités (une pince, une caméra, etc). Ces éléments sont décrits sur la figure \ref{fig:schem_khep}. \subsection{Logiciellement} D'un point de vue fonctionnement, le Khepera II dispose de deux modes d'exécution : \begin{enumerate} \item \textbf{Autonome} : un programme interne, chargé dans sa mémoire dirige les composants. Ceci à l'avantage d'être plus efficace, mais il faut recharger le logiciel interne à chaque modification ; \item \textbf{Contrôle distant} : Un protocole simple, par liaison série, permet d'envoyer des commandes au robot. Il est possible d'exploiter quasiment toutes les fonctionnalités de cette manière. \end{enumerate} \subsection{Premiers tests} Une fois familiarisé avec le fonctionnement théorique du Khepera, j'ai alors décidé de configurer le périphérique sur mon système d'exploitation et d'effectuer plusieurs tests afin de confirmer ou non ma compréhension du fonctionnement. Une des questions que je me posais était de savoir si l'utilisation d'une tourelle sans-fil allait complexifier la méthode d'accès. En effet, chaque robot doit être contrôlé via une tourelle Bluetooth\footnote{Une technologie radio courte distance destinée à connecter les appareils électroniques entre eux - www.bluetooth.org.} et la documentation ne donnait pas d'informations à ce sujet. Suite à mes tests, je me suis rendu compte que le module est transparent et qu'il est possible de communiquer avec le robot comme sur la liaison série. Mieux encore, un port série est émulé au niveau du système d'exploitation. Une de mes interrogations était donc réglée : j'allais pouvoir programmer mes logiciels indépendamment de la méthode d'accès. Pour finir, en ce qui concerne l'utilisation même du robot, le manuel s'est avéré très clair et précis, je n'ai eu aucune surprise. La procédure de configuration du robot est décrite en annexe. \section{Etat de l'art} Avant de commencer la phase d'analyse, j'ai voulu tout d'abord prendre connaissance des projets se rapprochant du mien, voire similaires. En effet, je ne souhaitais pas réinventer la roue, et même si je me doutais que mon tuteur avait vérifié auparavant, je préférais être conscient de l'existant. \subsection{Logiciels officiels} Tout d'abord, j'ai analysé les solutions proposées par le distributeur du robot : deux méthodes d'accès étaient présentées. La première consiste à se connecter directement au robot avec un émulateur de modem et lui envoyer les commandes. Cette méthode n'est clairement pas pratique et ne peut dépasser le cadre du test rapide. La seconde quant à elle utilise le logiciel \textsc{Matlab}\footnote{MATLAB (raccourci de matrix laboratory, laboratoire matriciel) est un logiciel de calcul numérique édité par la société américaine \textsc{The MathWorks}.}. Son principal inconvénient est d'être justement dépendante de ce logiciel et de ne pas être facilement scriptable (quasiment tout doit se faire à la souris). De plus, \textsc{Matlab} ne prévoit rien de particulier pour interagir avec d'autres logiciels et n'est pas libre ; ce qui restreint beaucoup son utilisation. Aucune des solutions proposées par le fabricant n'était donc valable dans notre cas. \subsection{Logiciels tiers} Après de longues recherches, il s'est avéré qu'il existe beaucoup de logiciels concernant les Kheperas, principalement en logiciels libres. Seulement, la plupart d'entre eux sont des simulateurs ou sont écrits dans des langages de plus haut niveaux comme le \emph{Java}\footnote{http://java.sun.com} ou le \emph{Python}\footnote{http://www.python.org}. Un seul candidat est sorti du lot : \emph{kRobot}. Il s'agit d'une classe écrite en C++ qui permet de contrôler le robot. Cependant, la classe est devenue quasiment introuvable sur Internet et n'est pas vraiment exploitable (non maintenue, aucune documentation, etc). \subsection{Conclusion} Je me suis donc aperçu qu'aucun logiciel existant ne proposait ce dont nous avions réellement besoin. Je devais donc repartir de zéro et implémenter ce qui était demandé en langage C. \section{Analyse} Je décidais donc de rassembler les éléments afin de pouvoir évaluer précisément le besoin et de préparer la phase de programmation. J'ai tout d'abord interviewé les futurs utilisateurs de l'équipe afin de comprendre ce qu'ils attendaient réellement. J'ai ainsi pu clarifier certains points flous et m'assurer que je partais dans la bonne direction. Je me suis ensuite attaché aux points techniques afin de prévoir les difficultés et de proposer des logiciels maintenables, réutilisables et pratiques. Je décidais alors de programmer les éléments en couches afin d'être modulaire et de pouvoir aisément créer des applicatifs au long du stage selon l'évolution des demandes et des contraintes. La première étape serait donc de créer une bibliothèque de manière à permettre l'abstraction du protocole Khepera. Ainsi, grâce à ce composant, il serait facile de doter n'importe quel logiciel d'un contrôle sur un robot. Cela m'ouvrait donc les portes pour la suite : je savais que je pouvais écrire cette partie sans me soucier de la conception du serveur réseau. Ainsi, ceci me permettait donc de me mettre au travail rapidement et de façonner les parties suivantes au fil de mon avancement. Au final, l'architecture à laquelle je suis venue à ce moment est décrite sur la figure \ref{fig:arch_debut}. \begin{figure}[here] \centering \includegraphics[scale=0.7]{images/arch_debut.png} \caption{Une première idée d'architecture} \label{fig:arch_debut} \end{figure} Je décidais aussi d'utiliser un logiciel de gestion des révisions, \emph{Subversion}\footnote{http://subversion.tigris.org/}, afin de garder une trace de mon travail, de pouvoir revenir sur les modifications en cas d'erreurs et de pouvoir travailler depuis plusieurs postes. \section{La bibliothèque d'accès} \subsection{Mise en place} La bibliothèque d'accès a donc été la première brique logicielle à être programmée. N'ayant aucune expérience en ce qui concerne la programmation de liaison série, j'ai préféré suivre un didacticiel et de créer quelques exemples pour me faire la main. Une fois ceci terminé, j'ai alors catégorisé les possibilités du robot et en est venu à la conclusion suivante : \begin{itemize} \item Il existe deux grands types de commandes \item D'abord les « ordres » que répondent rien ; \item Ensuite les « requêtes » qui permettent d'obtenir une information. \end{itemize} J'avais donc à ce point tous les éléments nécessaires pour commencer à programmer. \subsection{Utilisation des autotools} Dans un soucis de maintenabilité, j'ai donc décidé d'utiliser les outils GNU \emph{Automake} et \emph{Autoconf} \footnote{Autoconf : http://www.gnu.org/software/autoconf/}, qui permettent de créer des bibliothèques aisément et aident au bon fonctionnement sur diverses architectures. Ainsi, cet ensemble de scripts fait que la bibliothèque pourra être compilée sur divers systèmes d'exploitation (GNU, Solaris, BSD, etc) et veillera au maximum à adapter la compilation pour le processeur de destination. Leur fonctionnement est synthétisé sur la figure \ref{fig:autotools}. \begin{figure}[here] \centering \includegraphics[scale=0.5]{images/autotools.png} \caption{Fonctionnement simplifiée des Autotools} \label{fig:autotools} \end{figure} Bien entendu, ces outils ne peuvent pas réaliser entièrement ces tâches à la place du programmeur, mais sont tout de même d'une grande aide. Revers de la médaille, cette suite n'est pas évidente à prendre en mains. L'ayant déjà utilisée auparavant, j'ai pu réinvestir mon expérience et ai réussi à la mettre en place assez rapidement avec l'appui de la documentation en ligne qui fournit de bonnes explications illustrées. \subsection{Premiers problèmes} J'ai ensuite écrit les fonctions permettant d'ouvrir un canal de communication avec le robot. Le robot réagissait comme prévu, je n'ai pas eu de problème. Suite à cela, j'ai donc écrit la partie commune aux deux classes de commandes : une partie logicielle qui s'occupera de transmettre les commandes de manière brute et d'en récupérer le résultat. Bien entendu, cette partie s'occupera aussi de transformer les informations en structures adaptées afin de rendre l'exploitation en C aisée. Aux premières commandes envoyées, je me suis rendu compte qu'il y avait un problème : elles ne s'exécutaient pas la première fois qu'on se connectait au robot. A la suite de nombreux tests, j'ai découvert qu'une bannière était émise lors de la première connexion et qu'elle génait la communication. Le problème peut paraître trivial, mais ça n'a pas été évident de le résoudre. Après plusieurs essais qui se sont soldés par un échec, j'ai décidé d'inspecter le code source de plusieurs programmes utilisant des ports séries. Le logiciel GPhoto\footnote{http://www.gphoto.org}, une bibliothèque d'accès aux appareils photographiques m'a été d'une grande assistance. Il s'est avéré qu'une fonction peu référencée permet de résoudre ce problème ; je l'ai donc utilisée et le problème semblait résolu. \subsection{Changement d'architecture} Au début du développement, j'ai commencé la programmation sur une machine de type \emph{Macintosh}. Au tiers du développement, j'ai acquis une nouvelle machine, et cette fois ci de type \emph{PC/Intel}. Comme je l'attendais, j'ai eu quelques problèmes de fonctionnement. Ceci à cause de deux facteurs : tout d'abord mon inaptitude à prévoir tous les cas de portabilité et surtout un fonctionnement légèrement différent des liaisons séries. En effet, les paramètres que j'appliquais sur la liaison venaient s'additionner à la configuration « de base » du port. Or, cette configuration « de base » différait selon le type de machine. J'ai alors du changer mon programmer afin d'écraser totalement la configuration du port afin de le mettre dans le mode requis par le Khepera. \subsection{Problèmes de synchronisation} Une fois l'écriture terminée des « ordres », je me décidais donc de passer à l'écriture des « requêtes », qui elles, nécessitent une réponse. J'ai donc réfléchi à des structures adaptées afin de recueillir les réponses du robot et ai commencé à programmer. Je me suis vite confronté à des problèmes de synchronisation. Par exemple, une réponse était lue partiellement et la suivante contenait une partie de la précédente. A la suite de nombreux tests, je n'avais toujours pas réussi à déterminer d'où cela venait. Il m'a fallu utiliser \emph{GDB}\footnote{Le débogeur GNU : http://sourceware.org/gdb/} afin d'arriver à un diagnostic précis. Il s'agissait d'un problème de mise en tampon au niveau du système d'exploitation, couplé avec des difficultés de transmission sur le Khepera. Je pouvais éventuellement rendre le système synchrone en désactivant la mise en tampon, mais cela allait impacter de manière critique sur les performances. Suite à de nombreuses recherches et tests, je suis parvenu à un système quasiment stable. Cela consiste à fonctionner en mode semi-synchrone et à se caler sur le temps d'un cycle d'exécution du Khepera. Cependant, le robot sature très rapidement et il arrive que suite à l'envoi de nombreuses commandes, il se mette à paniquer et redémarre inopinément. Cela reste encore un problème à ce jour et je ne pense pas réussir à faire mieux sur ce point. Le problème étant dû, je suppose, au logiciel interne du Khepera. \subsection{La documentation} Toujours dans un souci de maintenabilité, ajouté à la volonté de rendre l'utilisation pratique de ma bibliothèque, j'ai décidé d'intégrer un système de génération automatique de documentation. Mon choix s'est porté sur le logiciel \emph{Doxygen}\footnote{http://www.doxygen.org} qui est un programme éprouvé, fiable, complet et qui génère une documentation claire. Il suffit d'annoter les éléments dans le code source du programme pour qu'ils soient repris dans la documentation. Cela permet donc d'obtenir un manuel pour les développeurs très rapidement. De plus, plusieurs formats peuvent être générés (PDF, Html, texte, ...). Le fonctionnement de ce programme est illustré sur la figure \ref{fig:doxygen}. \begin{figure}[here] \centering \includegraphics[scale=0.5]{images/doxygen.png} \caption{Fonctionnement de Doxygen} \label{fig:doxygen} \end{figure} Cependant, comme évoqué précédemment, cet outil ne génère qu'une documentation pour les développeurs et ne remplacera pas un manuel. En somme, le travail le plus compliqué a été d'intégrer \emph{Doxygen} dans les \emph{Autotools}. Mais ce temps passé a été compensé par le temps gagné à la rédaction d'une documentation. \section{Le centre de tests} \subsection{Motivations} Au début du développement de la bibliothèque, je me suis dit qu'il fallait que j'effectue toute la phase de programmation par étapes, au rythme des tests. J'ai donc emprunté quelques idées aux méthodes d'\emph{Extreme Programming} \footnote{http://fr.wikipedia.org/wiki/Extreme\_programming} afin de ne valider mon code que lorsque les tests passaient avec succès. Je n'ai cependant pas réalisé une vraie suite de tests comme il est décrit dans cette méthode mais j'ai décidé de programmer une application qui utilise les fonctionnalités de la bibliothèque. Ainsi, dès lors qu'un dysfonctionnement apparaîtrait dans celle-ci, elle se répercuterait dans l'application et ce serait flagrant. Je décidais donc d'avancer étape par étape et seulement lorsqu'un test avait validé le travail que je venais d'effectuer. \subsection{Première version} La première version du centre de tests était un simple programme en ligne de commandes qui appelait fonction par fonction et testait la validité des résultats. Je me suis cependant vite aperçu que l'exécution de ces tests était très linéaire, quasi à intervalle régulier. De plus, ils ne représentaient pas ce qu'un Homme pourrait demander au robot. C'est pourquoi, au milieu de l'écriture de la bibliothèque, je décidais de réécrire ce code de test et d'en faire quelque chose de contrôlable par l'utilisateur. \subsection{Deuxième version} Cette nouvelle version donc, devait être capable de réagir aux interactions avec l'utilisateur et de l'informer en permanence sur l'état du robot. J'ai à ce moment hésité à écrire l'interpréteur de commandes. Cependant, le problème de l'interpréteur est qu'il aurait eu les mêmes défauts que le code de test : \begin{itemize} \item L'utilisateur ne pourrait pas stresser le robot (saisir les instructions est plus pour nous que les exécuter pour le robot) ; \item Utiliser une script reviendrait à écrire un test linéaire en C. \end{itemize} Il me paraissait donc logique d'éviter l'interpréteur qui n'apporterait rien pour cette phase de tests. Je choisissais donc de m'orienter vers une interface graphique qui permettrait la saisie très rapide des commandes et d'avoir un retour visuel direct. J'ai alors prototypé rapidement une interface et est arrivé au cahier des charges suivant : \begin{itemize} \item Appel des commandes sur simple pression d'une touche ; \item Affichage constant de l'état des capteurs ; \item Affichage constant de la vitesse du robot. \end{itemize} \subsubsection{L'interface graphique} Afin de construire l'interface graphique de mon application, il me fallait donc utiliser un toolkit\footnote{Un ensemble d'outils facilitant l'écriture de logiciels dans un domaine particulier.} graphique. J'ai alors envisagé plusieurs choix. Pour chacune de ces solutions, j'ai évalué le pour et le contre. Le résultat de cette analyse est regroupé dans le tableau \ref{tab:toolkits_gfx}. \begin{table}[here] \centering \begin{tabular}{|l|p{4cm}|p{4cm}|} \hline Nom & Avantages & Inconvénients \\ \hline \textbf{Xlib} & Très performant & Complexe, moyennement portable, laid \\ \hline \textbf{GTK}, \textbf{Qt}, ... & Portable, visuellement agréable, beaucoup de widgets\footnote{Un élément visuel faisant partie d'une interface.} disponibles & Evénements difficiles à capturer, temps de rafraichissement élevé\\ \hline \textbf{SDL}, \textbf{Allegro}, ... & Adapté à la réception d'évenements, rafraichissement très rapide, portable & Aucun widget, assez bas niveau\\ \hline \end{tabular} \caption{Comparaison des toolkits graphiques} \label{tab:toolkits_gfx} \end{table} Mon choix s'est alors porté sur la bibliothèque \textit{Simple Direct Layer}, ou \textit{SDL}\footnote{http://www.libsdl.org}, car c'était pour moi la plus adaptée. En effet, l'interface que je souhaitais réaliser s'apparentait plus, d'un point de vue technique, à un jeu qu'à une application graphique « classique ». Tout d'abord, j'avais besoin d'un rafraîchissement constant et paramètrable ; ensuite, je devais être capable d'utiliser divers périphériques d'entrée (l'équipe avait prononcé le souhait d'utiliser un joystick par exemple). Bien que la \textit{SDL} me laissait beaucoup plus de libertés et me permettait d'avoir exactement ce que je voulais, je ne disposais d'aucune assistance en ce qui concerne le rendu graphique. En effet, cette bibliothèque se contente d'afficher des pixels sur l'écran et ne connaît quasiment aucun primitive plus évoluée. Il me fallait donc soit créer une boite à outils pour afficher des formes ou m'intéresser à ce qui se faisait déjà. J'ai donc évidemment choisi de commencer par la deuxième solution, toujours dans le but d'éviter de réécrire quelque chose d'existant et de limiter les bogues. J'ai alors découvert la bibliothèque \textit{Cairo}, qui venait de faire son apparition en version stable. Cette bibliothèque permet de dessiner à l'écran en mode vectoriel et fournit toutes sortes de primitives pour manier les formes. Un des principaux avantages du vectoriel est qu'il s'adapte parfaitement à toutes les résolutions d'écrans sans sacrifier la qualité. L'utilisation de \textit{Cairo} en combinaison avec la \textit{SDL} m'a alors paru idéal, cette première me paraissant un bon compagnon pour la dernière. \subsubsection{Description} L'interface se présente donc, en version finale, comme illustré sur la figure \ref{fig:khepcc}. Au centre, on trouve un « pad » multidirectionnel qui indique quelle est la direction actuellement empruntée. Actuellement, il n'est possible de diriger le Khepera qu'avec les flèches du clavier, mais l'ajout d'un autre périphérique se révèle trivial grâce à la \textit{SDL}. Sous le « pad », se trouvent deux barres qui indiquent la résistance au sol. Elles sont calculées en effectuant la différence entre la vitesse demandée et la vitesse réelle. Enfin, de chaque côté, on trouve 8 barres qui correspondent à l'état des différents capteurs. Sur la gauche se trouvent les capteurs de présence, tandis que sur la droite sont représentés les capteurs de luminosité. \begin{figure}[here] \centering \includegraphics[scale=0.5]{images/khepcc.png} \caption{Le centre de contrôle} \label{fig:khepcc} \end{figure} \section{L'interpréteur de commandes} Une fois la bibliothèque suffisamment complète et stabilisée grâce à l'outil précédemment cité, je décidais donc de m'occuper de l'interprêteur de commandes. Comme demandé dans le sujet, il devait être possible de contrôler le robot au travers d'une invite de commande. Ayant déjà eu l'occasion de réaliser un interprêteur de commandes, j'ai voulu éviter de retomber dans le même piège. En effet, réaliser ce type de logiciel n'est pas évident du tout. Beaucoup de bogues sont à prévoirs et le logiciel doit être éprouvé sur une longue phase de déboguage pour être considéré stable. Il m'est alors venu l'idée d'utiliser un langage déjà existant possédant une interface en ligne de commande. Cela aurait deux avantages : \begin{enumerate} \item Tout d'abord, de disposer d'un interprêteur riche et convivial ; \item Ensuite d'utiliser un langage éprouvé et connu. \end{enumerate} Le candidat idéal m'a semblé être le langage \emph{Python}\footnote{Python : http://www.python.org} qui dispose des qualités requises sans aucun ajout de module externe. \subsection{Utilisation de Python} Pour utiliser \emph{Python}, je devais donc écrire un module qui permettrait de réaliser la cohésion entre la bibliothèque en langage \emph{C} et le langage \emph{Python}. En effet, ce dernier étant très divergeant du \emph{C}, il n'est pas possible d'utiliser automatiquement les bibliothèques écrites en \emph{C}. Elles doivent être soient écrites entièrement en python ou un module intermédiaire doit réaliser la conversion. Toujours dans un souci de maintenabilité, j'ai alors cherché un générateur de « bindings »\footnote{Un code qui sert de passerelle entre différents langages}. Ceci avait de nombreux avantages : \begin{itemize} \item Mise à jour synchronisée avec l'évolution de la bibliothèque \emph{C} ; \item Gain de temps considérable ; \item Compatibilité avec les dernières versions de \emph{Python} assurée ; \item Possibilité d'étendre les bindings vers d'autres langages (exemple: \emph{Caml}). \end{itemize} J'ai alors trouvé le logiciel \emph{SWIG}\footnote{Simplified Wrapper and Interface Generator : http://www.swig.org} qui m'a paru complet, abouti et bien maintenu. Cependant, il m'a aussi paru assez ardu à utiliser. Mon intuition ne m'avait pas menti. \subsection{SWIG} \emph{Swig} est un « générateur d'interfaces » qui permet de créer des bindings à partir de fichiers d'en-tête. Il est actuellement capable de générer des modules pour plus de quinze langages et ce, d'une manière quasiment uniforme. Le mécanisme de génération est représenté sur la figure \ref{fig:swig} \begin{figure}[here] \centering \includegraphics[scale=0.5]{images/swig.png} \caption{Mécanisme de génération de SWIG} \label{fig:swig} \end{figure} Son utilisation est en revanche non triviale. Fort heureusement, la documentation est assez exhaustive et permet, avec de l'investissement, d'y trouver ce que l'on souhaite. J'ai tout d'abord réalisé les bindings pour les commandes de type « ordre ». Ceci s'est passé sans problème. Lorsque j'ai commencé à faire générer les commandes de type « requête », le travail est devenu beaucoup moins trivial. Premièrement, \emph{SWIG} ne supportant pas la déclaration d'union\footnote{Une union est une zone mémoire qui peut accueillir plusieurs types, ceci de manière exclusive.} dans une structure, il ne réussisait donc pas à convertir le type de retour pour une requête. J'ai du alors l'adapter. Le plus gros problème allait suivre. Je me suis rendu compte qu'il ne comprenait pas les pointeurs, si ce n'est d'une manière abstraite. \emph{SWIG} fonctionne ainsi : il ne se préoccupe pas de connaître les détails et se base sur des hypothèses. Si un élément déclare un pointeur, il va se contenter d'en regarder le type et de générer les mécanismes pour accéder au contenu pointé. Il ne se préoccupera jamais de faire quelque chose d'intelligent en fonction du type. Ceci a donc posé problème pour les tableaux. En effet, \emph{SWIG}, suivant sa logique, permettait d'obtenir l'élément pointé par le « pointeur-tableau » et donc de n'accéder qu'au premier élément de celui-ci. Cela posait vraiment un problème pour lire les capteurs par exemple. J'ai donc du utiliser ce qu'on appelle un « typemap », qui permet d'automatiquement adopter un comportement en fonction d'un type rencontré. J'avais donc maintenant la possiblité d'indexer le pointeur comme un tableau normal. \subsection{Résultat} Une fois tous les problèmes réglés, j'ai intégré \emph{SWIG} aux \emph{Autotools} afin de rendre la génération des « bindings » automatique et paramètrable à l'aide des commandes classiques. Le résultat est un code \emph{Python} utilisable naturellement par une personne qui connaît la bibliothèque \emph{C}. Le grand avantage est donc que la documentation reste valide pour l'utilisation en python. Voici un exemple très succint d'une session : \bigskip >> from khepctrl import * >> h = khep\_open(``/dev/rfcomm0'', KHEP\_B115200) >> khep\_cmd\_set\_speed(h, 10, 10) >> khep\_close(h) \bigskip On obtient donc ce qui était demandé : il est possible d'exploiter tout le potentiel du robot à l'aide d'un interprêteur de commandes. J'ai ensuite apporté quelques améliorations aux « bindings » en fin de projet. Tout d'abord, les codes de retours dans le « style \emph{C} » (\emph{i.e.} des entiers) ont été remplacés par des exceptions \emph{Python}, ce qui permet d'avoir une gestion des erreurs moins lourde. Ensuite, j'ai commencé l'écriture d'une classe \emph{Python} afin d'accéder aux robots sous forme d'objets ; ce qui facilite l'exploitation et rend l'accès encore plus naturel. \section{Le serveur réseau} \subsection{Objectif initial} Le serveur réseau, comme décrit dans le sujet, devait être accessible par socket\footnote{Un canal de communication brut entre deux points.}. La procédure à suivre était donc d'ouvrir un socket distant puis d'y écrire les ordres en caractères ASCII. Comme on peut le remarquer, ceci présente de nombreux désavantages. En premier lieu, on effectue un pas en arrière comparé à la bibliothèque : l'abstraction qu'elle apporte vis à vis du protocole n'existe plus. Ensuite, ceci signifie donc que l'on n'a plus aucun contrôle de types, du nombre d'arguments, etc... L'intérêt qui était gagné est ici perdu et est une porte ouverte aux fautes d'inattention lors de la phase de programmation. Enfin, les sockets ne sont pas toujours évidents à gérer. Selon les langages, il est plus ou moins facile de les manipuler et sont parfois source d'erreurs. De plus, lorsqu'on écrit une application réseau, il est confortable de ne pas avoir à se soucier du transport des données. J'ai alors proposé une autre solution à mon tuteur de stage : \emph{Xml-RPC}. Après examen de celle-ci, il m'a conforté dans mon choix et m'a donné le feu vert pour l'exploiter. \subsection{Xml-RPC} \emph{Xml-RPC} est un protocole de haut niveau qui n'utilise que des standards bien établis du Web. Il permet une communication facile et homogène à travers le réseau. Tous les messages sont encodés en \emph{XML}\footnote{Un langage de description utilisant des balises} selon des règles bien établies et sont transportés sur le réseau en utilisant le protocole \emph{HTTP}\footnote{Le protocole utilisé pour transporter le « Web »}. Ceci permet de communiquer sans avoir à se préoccuper ni du langage source ni du langage cible. En effet, chaque bibliothèque respectant les mêmes normes, les données sont donc échangeables de manière transparente. Le premier grand intérêt est donc qu'il sera possible d'utiliser le serveur avec quasiment tous les langages disponibles. Ensuite, comme \emph{Xml-RPC} utilise le protocole \emph{HTTP}, n'importe quel serveur Web peut être utilisé pour gérer les connexions et le transport des données. Ceci apporte l'avantage de pouvoir se reposer sur des logiciels déjà existants, éprouvés et robustes. Un autre avantage de cette solution est qu'il est possible d'utiliser les mécanismes internes du serveur Web comme la redirection automatique vers un autre serveur (maintenance, équilibrage de charge, etc), l'authentification ou encore le chiffrement \emph{SSL}\footnote{La méthode utilisée sur le Web pour communiquer en chiffré}. Le seul point noir que l'on pourrait attribuer à l'utilisation d'\emph{Xml-RPC} est qu'il est nécessaire d'avoir une bibliothèque capable de comprendre ce langage à chaque point de communication. Cependant, comme dit précédemment, celles-ci existent pour la plupart des langages. Voici un schéma regroupant le fonctionnement d'\emph{Xml-RPC} (figure \ref{fig:xmlrpc}). \begin{figure}[here] \centering \includegraphics[scale=0.5]{images/xmlrpc.jpg} \caption{Fonctionnement global d'XML-RPC} \label{fig:xmlrpc} \end{figure} \subsection{Première version} La première version que j'ai développée était écrite en langage \emph{C}. J'avais choisi d'utiliser la bibliothèque « libxmlrpc »\footnote{LibXMLRPC : http://xmlrpc-c.sourceforge.net/} qui se décrit comme un moyen rapide et facile à mettre en \oe{}uvre tout en étant modulaire, portable et complet. Cette bibliothèque a aussi le gros avantage d'embarquer une copie d'un serveur Web très léger : \emph{Abyss}\footnote{Le serveur Web Abyss : http://abyss.sourceforge.net/}, ce qui permet d'avoir un composant autonome et facile à déployer. La documentation étant claire, fournie d'exemple, j'ai pu rapidement avoir un programme minimal fonctionnel. La bibliothèque semblait effectivement respecter ce qui était annoncé sur le site web. Je décidais donc d'intégrer ma bibliothèque Khepera avec celle ci. \subsubsection{Génération des fonctions} J'ai alors remarqué un point non négligeable : il n'est pas possible de générer les fonctions \emph{Xml-RPC} à partir des fichiers d'en-têtes. J'ai trouvé cela fort dommage pour deux raisons : \begin{enumerate} \item Il faudrait mettre à jour le serveur réseau à chaque changement de la bibliothèque ; \item Le processus de création de fonction \emph{Xml-RPC} est très linéaire et réberbatif, donc sûrement automatisable. \end{enumerate} J'ai donc écrit rapidement un outil qui, à partir d'un fichier d'en-tête et quelques informations, génère un fichier source \emph{C} contenant les fonctions \emph{Xml-RPC} correspondantes. \subsubsection{Problème significatif} A ce moment, j'avais donc un logiciel qui compilait, se lançait et était prêt à recevoir les requêtes \emph{Xml-RPC}. Je fus désagréablement surpris lors du premier test : j'obtenais comme erreur « \emph{descripteur de fichier non valide} »\footnote{Un descripteur de fichier est un numéro qui permet d'identifier un fichier ouvert afin d'effectuer des opérations sur celui-ci.} sur chacun de mes appels. Mes tests me montraient pourtant que les descripteurs de fichiers étaient bien attribués. Après de nombreuses tentatives diverses, j'ai enfin saisi le problème : le descripteur de fichier était bien ouvert à la demande, mais aussitôt fermé, donc inutilisable par les appels suivants. Je devais donc trouver la raison de cette fermeture soudaine. Ce problème m'a pris un temps considérable car j'ai dû explorer de nombreuses pistes. Peu à peu, je me suis rapproché du fonctionnement interne du serveur Web et j'ai alors trouvé le problème. En effet, la plupart des serveurs Web travaillent ainsi : lors de la réception d'une connexion, le programme est dupliqué en mémoire (un \emph{fork} ou un \emph{thread}), traite la demande puis se termine. Or, sur un système POSIX\footnote{Une famille très répandue de systèmes : http://fr.wikipedia.org/wiki/POSIX}, lorsqu'un programme quitte, tous les descripteurs de fichiers qui lui étaient associés sont fermés. Le problème est illustré sur la figure \ref{fig:fd_kill}. \begin{figure}[here] \centering \includegraphics[scale=0.7]{images/fd_kill.png} \caption{Mécanisme réalisé lors d'une requête d'ouverture d'un Khepera} \label{fig:fd_kill} \end{figure} J'avais donc trouvé mon problème et il n'était pas simple à résoudre. Il me fallait donc soit créer un serveur web spécifique ne fonctionnant qu'avec des threads pré-chargés, soit trouver un serveur web fonctionnant ainsi. \subsection{Version finale} J'ai alors pensé qu'il était peut être possible de tirer profit des bindings \emph{Python}. En effet, le langage \emph{Python} est basé sur une machine virtuelle qui utilise un pool\footnote{Un pool est un ensemble d'objets préchargés} de threads pour exécuter les tâches qui nécessitent un processus différent. L'utilisation de ce pool aurait l'avantage de ne pas fermer les descripteurs de fichiers lors de la fin de traitement et donc d'être utilisables pour le cas de figure recherché. De plus, \emph{Python} possédant naturellement de nombreux mécanismes d'introspection, j'avais l'intuition qu'il serait aisé de générer automatiquement les fonctions \emph{Xml-RPC}. Après m'être documenté sur les possibilités offertes par le module RPC de \emph{Python}, j'en ai donc conclu qu'il s'agissait du candidat idéal. La mise en pratique fût rapide et convaincante : quelques lignes de code ont suffit à la déduction automatique des fonctions exportées par la bibliothèque et les descripteurs de fichiers étaient bien gardés ouverts. J'avais donc atteint mon objectif : je disposais d'un serveur Web pouvant contrôler plusieurs robots, pouvant avoir plusieurs clients (même par robot), se mettant à jour automatiquement et gardant la même API que la bibliothèque (donc la même documentation). L'imbrication des composants est détaillée sur la figure \ref{fig:composants_net}. \begin{figure}[here] \centering \includegraphics[scale=0.7]{images/composants_net.png} \caption{Imbrication des composants} \label{fig:composants_net} \end{figure} \subsection{Problèmes finaux} Bien que le serveur fonctionnait parfaitement pour les commandes de type « ordre », il n'en était pas de même pour certaines commandes de type « requête ». En effet, \emph{SWIG} gérant les types d'une manière totalement générique, il crée ce qui est appelé un « proxy » permettant d'accéder à ces types. Le problème est que pour qu'un objet puisse passer à travers le réseau, il doit être sérialisable\footnote{Cela signifie qu'il est possible de créer une représentation textuelle d'un objet.}. Or, les proxies SWIG ne le sont pas. J'ai donc dû préciser à \emph{SWIG} comment les types non-natifs (\emph{i.e.} hormis entiers, chaînes de caractères, etc...) pouvait être représentés d'une manière sérialisable. Ce problème m'a pris beaucoup de temps car il m'a demandé d'utiliser des concepts avancés de \emph{SWIG} qui ne sont pas évidents à prendre en main. Une fois ce problème réglé, j'ai pu tester le serveur exhaustivement et d'une manière convaincante. \chapter{Conclusion} \section{Bilan} Pendant toute la durée du stage, j'ai pu enrichir mon expérience sur deux aspects. Tout d'abord, d'un point de vue technique, j'ai voulu mettre l'accent sur le côté génie logiciel car c'est, selon moi, un critère indispensable pour livrer un programme. En effet, le fait de savoir que d'autres programmeurs auront à maintenir le logiciel par la suite impose de nombreuses contraintes. Je me suis donc tenu à rechercher au maximum une maintenabilité aisée, une automatisation des procédés ainsi qu'une documentation la plus complète possible. Je pense avoir réussi sur ce point car tous les composants sont générés l'un après l'autre en prenant comme seul point de départ la bibliothèque \emph{C}. On comprend donc bien tout l'intêret : le fait de changer quelque chose dans celle ci se répercutera automatiquement dans toute la chaîne (module \emph{Python}, interprêteur de commandes, serveur \emph{Xml-RPC}, documentation). Ensuite, d'un point de vue personnel, j'ai pu découvrir le fonctionnement et l'ambiance de travail dans un laboratoire. Même s'il ne s'agissait pas d'un travail de recherche, je me suis intéressé et ai pu comprendre la nature des travaux de l'équipe. Ceci m'a d'ailleurs permis de faire mon choix pour mon orientation en Master 2. \section{Ouverture} Même si le travail réalisé est immédiatement exploitable, voici ce qui aurait pû être réalisé avec plus de temps : \begin{itemize} \item La gestion des tourelles des Khepera (Grippers, etc). Programmer ceci sous forme de greffons pourrait être une bonne idée ; \item Un logiciel de calibration du robot (ainsi que le support des profils dans la bibliothèque) permettant d'avoir une étalonnage fin selon ses préférences ; \item L'amélioration de la stabilité à l'aide de nombreux tests afin de stresser encore plus le robot ; \item Des bindings vers d'autres langages (\emph{Objective-Caml} par exemple). \emph{SWIG} supportant de nombreux langages, le travail le plus long serait sûrement l'intégration aux \emph{Autotools}. \item La possibilité de réserver un robot sur le serveur réseau selon ses capacités. Ceci avait été proposé par un membre de l'équipe. \end{itemize} \medskip Enfin, suite à la clarification de la licence (tous les logiciels sont couverts sous la licence \emph{GNU GPL}\footnote{http://www.gnu.org/licenses/licenses.html\#GPL}), des paquets \emph{Debian}\footnote{Système d'exploitation GNU/Linux, http://www.debian.org} sont en cours de création afin de faciliter l'installation des logiciels sur les machines de développement. \appendix \chapter{Configuration sous GNU/Linux} Afin d'utiliser la bibliothèque d'accès, la première étape consiste à configurer le Khepera II sur le système. Voici comment réaliser l'installation sous Debian GNU/Linux (cependant, ceci est facilement adaptable pour les autres distributions). Paquets nécessaires : \begin{itemize} \item bluetooth \item bluez-utils \item libbluetooth2 \end{itemize} Ils sont installables via la commande « \emph{apt-get install NOM\_PAQUET} ». Une fois ceux-ci installés, il faut relever le code MAC du robot. Pour ceci, une fois le robot sous tension, exécuter « \emph{hcitool scan} ». Enfin, il est nécessaire de renseigner le fichier « /etc/bluetooth/rfcomm.conf » avec les informations suivantes : \begin{verbatim} rfcomm0 { # Automatically bind the device at startup bind yes; # Bluetooth address of the device device 00:04:XX:XX:XX:XX; # RFCOMM channel for the connection channel 1; # Description of the connection comment "KheperaII robot#1"; } \end{verbatim} S'il y a plusieurs robots, il suffira de répéter l'opération autant de fois que nécessaire sans oublier d'incrémenter « rfcommX ». Une fois le fichier enregistré, un redémarrage de la pile bluetooth est nécessaire. Ceci s'effectue à l'aide de « \emph{/etc/init.d/bluetooth restart} ». \end{document}