Simulateur

Présentation générale

Le simulateur du drone a pour objectif final de reproduire exactement les mouvements du drone afin de le tester dans un environnement virtuel, ce qui réduit les risques de destructions inopinées.

Le drone, dans l'espace de simulation, peut-être contrôlé de deux manières : par le clavier, ou par un appareil sous Android dont on reçoit les consignes via Wi-Fi.

Nous sommes donc partis d'un existant, et nous sommes appuyés sur le wiki de Raydium disponible sur internet, contenant les descriptions des fonctions, ainsi que des exemples.

Les principaux outils utilisés pour développer le simulateur sont :

- Raydium :

Raydium est une bibliothèque regroupant plusieurs bibliothèques plus bas niveau ayant toutes une application dans le domaine du jeu vidéo 3D. De plus, Raydium propose une API composée de fonctions haut-niveau ayant pour but de faciliter l'écriture de morceaux de code communs à tous les jeux vidéo. Raydium dispose donc de moteurs pour gérer tout ce qui est relatif aux jeux vidéo, des graphismes au son, en passant par la physique et le réseau. Dans le cadre du simulateur, nous nous sommes surtout attachés aux moteurs qui gèrent la physique et les graphismes, respectivement ODE et OpenGL.

Figure 31 : Logo de Raydium

- Code::Blocks :

Code::Blocks est l'environnement de développement intégré au SDK de Raydium. Il nous a donc fallu apprendre à l'utiliser, vu qu'il est nécessaire. C'est un IDE assez facile à prendre en main grâce à son compilateur intégré et son interface modifiable à souhait.

Particularités d'un programme incluant Raydium

Raydium étant codé en C, une fonction main est nécessaire à tout programme l'incluant. De plus, Raydium a besoin d'une fonction d'affichage, et nous avons utilisé une autre fonction propre à Raydium (plus précisément à ODE), destinée à être appelée de façon très régulière : step().
main : la fonction main servira à initialiser des paramètres propres à Raydium concernant l'application, notamment la résolution de la fenêtre, le filtre des textures, le champ de vision, la (non-)activation des ombres, tout ce qui est relatif à la lumière, les « .tri » à utiliser, la gravité, ainsi qu'à définir quelles fonctions correspondront à la fonction d'affichage et la fonction appelée de façon récurrente.

affichage : tâche effectuée par la fonction display(), dans le cas de notre simulateur. Sert à rafraîchir la caméra ainsi que les différents viewports, elle se doit donc d'être appelée souvent. On appelle aussi la fonction servant à la gestion du clavier dans display(). De par sa nature gourmande en CPU (à cause des traitements graphiques réguliers et nombreux), sa fréquence d'appel dépend directement du processeur.

step : fonction censée être appelée très régulièrement. Elle provient d'ODE, il convient donc de lui faire effectuer tout ce qui tient de la physique.

Figure 32 : Fonctionnement d’un programme Raydium

Déroulement du projet

- Analyse de l'existant:

Etant partis d'un existant suffisamment conséquent, il nous incombait d'analyser sa structure, son fonctionnement, ainsi que de comprendre la raison d'être de chacun des appels de fonctions de Raydium. Cette partie nous a pris du temps car il fallait non-seulement comprendre le but de chaque partie du code, mais aussi maitriser les concepts propres à Raydium, tels que, notamment, celui des viewports, et ce qui, plus généralement, concerne le fonctionnement d'une application avec des animations en 3D.

Cette analyse nous a permis de repérer ce qui n'allait pas dans l'agencement des différentes parties du code du simulateur. Ainsi, nous avons remarqué que la gestion du clavier était mise dans step(), qui est censée contenir uniquement ce qui concerne la physique et les asservissements. En effet, step() est une fonction appelée beaucoup plus souvent que display() (Ceci étant dû au fait que display() est une fonction faisant du traitement graphique, qui ne nécessite donc pas d'être appelée plus de 25 fois par seconde environ (le minimum nécessaire pour que l'être humain voit une action fluide)). De plus, il nous semblait inutile et coûteux d'effectuer une scrutation du clavier plus de 25 fois par seconde (la fréquence d'appel de step(), qui était la fonction contenant le code de gestion du clavier, est de 200Hz, ce qui est beaucoup plus que nécessaire pour faire une gestion du clavier réactive).

Nous avons aussi pu constater que l'ébauche de physique présente sur l'existant n'était pas vraiment cohérente. Notamment une tentative pour gérer le déplacement du drone avec une variable speed, ce qui n'a pas vraiment de sens vu que la vitesse du drone dépend de son inclinaison par rapport à l'horizontale (en effet, d'un point de vue physique, le drone ne peut produire qu'une force vers le bas. Or, plus il est penché en avant, plus la force produite est dirigée vers l'arrière, plus la vitesse du drone augmente). De plus, les valeurs possibles de la variable speed donnaient au drone un comportement tout sauf réaliste.

De plus, les prototypes des fonctions prenaient en paramètres des pointeurs sur des variables qu'on ne modifiait, voire, n'utilisait pas. De plus, certaines fonctions, notamment celle concernant la régulation, avaient besoin de paramètres provenant de fonctions qui ne les appelaient pas. Il nous a donc fallu choisir un moyen de communication entre fonctions différent de la simple utilisation de paramètres et de codes de retour.

- Refonte du code :

Nous nous sommes donc attachés à reprendre le code dans son intégralité afin d’obtenir un résultat plus en adéquation avec nos attentes. Le déplacement du code de gestion du clavier dans une fonction différente nous a ainsi poussés à définir de quelle façon allaient communiquer nos différentes fonctions. Plusieurs options nous étaient proposées, notamment par structure, proposant ainsi de réunir toutes les consignes (l’angle en x, l’angle en y, et la consigne en altitude), par pointeur, ou par variable globale. Cette dernière option a été choisie pour des raisons de praticité. En effet, le choix de la structure nous aurait obligé à remplir tous les champs, ce qui implique l’envoi d’informations probablement redondantes, si jamais une consigne ne changeait pas d’une application des forces à l’autre. Et les pointeurs n’étaient pas envisageables car les fonctions ne s’appelaient pas entre elles. La variable globale présente, de plus, l’avantage d’être visible dans toutes les fonctions du fichier (voire plus, à l’aide du mot-clé « extern »).

Nous nous sommes ensuite occupés de nettoyer la partie physique du simulateur, et de poser les bases de ce qui nous semblait être une physique plus saine et plus réaliste. Cela passait par l’évincement de variables inutiles afin de garder ce qui allait vraiment être utile

par la suite. Toutes les occurrences à certaines variables ayant été enlevées, les prototypes des fonctions ont donc dû être modifiés en conséquence.

- Contrôles au clavier

Le drone simulé sur l’existant n’étant pas stable et sa gestion au clavier peu satisfaisante, il nous a fallu mener une réflexion pour définir, en coopération avec l’équipe chargée de la tablette Android, comment le drone allait être manipulé, afin de proposer des contrôles au clavier assez similaires à ce que fait la tablette Android. Nous avons donc opté de concert pour une manipulation séparant d’un côté le contrôle de l’altitude, se faisant via deux boutons, servant à monter ou descendre le drone par paliers d’une taille prédéfinie, et de l’autre, l’inclinaison du drone, contrôlée via un joystick (qui est, de base, émulé par les flèches directionnelles du clavier, mais Raydium gère très bien les vrais joysticks, ainsi que les manettes type XBox360).

- Mise au point de la physique et implémentation du code de l’asservissement

Une fois les contrôles faits, et des consignes cohérentes envoyées, nous devions faire en sorte que les consignes soient interprétées correctement afin que le drone soit stable et respecte les consignes sans oscillation, ce qui le rend incontrôlable. Pour cela, nous devions utiliser un asservissement utilisant la correction par PID. Néanmoins, n’étant pas à l’aise avec les calculs, nous avons dû nous en remettre à M. Laffont.

Une fois l’asservissement fait, nous avions donc un simulateur capable de prendre de l’altitude, et de se déplacer dans toutes les directions. Néanmoins, l’absence totale de frottements rendait le pilotage du drone simulé absurde : une fois le drone lancé avec une certaine vitesse, celui-ci dérive indéfiniment sans jamais ralentir ! Il fallait donc simuler des frottements de sorte que lorsque le drone se retrouve à l’horizontal, sa vitesse diminue petit à petit.

- Gestion de la camera

La caméra dans l’existant était en mode “freemove” : On pouvait se déplacer à volonté à travers les textures et les décors, et il fallait la contrôler manuellement pour qu’elle suive le drone dans ses déplacements, ce qui n’est pas acceptable. Il a donc fallu faire en sorte qu’elle suivre les mouvements du drone, afin d’en faciliter la manipulation. Cependant, la camera telle que nous l’avons codée reste fixe par rapport au drone.

Figure 33 : Fonctionnement de Raydium avec la bonne configuration de la caméra

radium.png (7.51 KB) Amaury Bendaoud-Joubert, 03/24/2012 12:46 PM

radium.png (7.51 KB) Amaury Bendaoud-Joubert, 03/24/2012 12:46 PM

sch2.png (15.5 KB) Amaury Bendaoud-Joubert, 03/24/2012 12:48 PM

drone.png (130 KB) Amaury Bendaoud-Joubert, 03/24/2012 12:50 PM