• Aucun résultat trouvé

CHAPITRE 7 CONCLUSION GÉNÉRALE

B.2. Commande plate-forme

Le deuxième travail que j’ai du réalisé était le contrôle de la plate-forme MOOG 2000E du simulateur SAAM. En effet, ce type de plate-forme n’avait jamais été utilisé jusqu’alors avec le logiciel SCANeR©. J’ai donc développé une DLL calquée sur celles permettant de piloter d’autres types de plate-forme.

La communication avec la MOOG 2000E se fait en UDP. Le contrôleur envoie un message de 8 mots de 4 bits chacun (soit 32 bits en tout) : un mot de commande, 6 mots pour la position à atteindre selon les 6 degrés de liberté, et le 8ème mot n’est pas utilisé (spare). La plate-forme répond alors par un message de 10 mots de 4 bits chacun (soit 40 bits en tout) : 3 mots contenant les informations d’état de la plate-forme, 6 mots pour la position de la plate-forme selon les 6 degrés de liberté, et le 10ème mot n’est pas utilisé (spare).

La figure suivante donne le diagramme UML (très) simplifié du code développé pour piloter la plate-forme.

Lors de l’initialisation (« connectToMotion() »), la DLL crée un socket (« mySocket ») de communication avec la plate-forme. Puis, lors du fonctionnement « normal », à chaque boucle de temps :

 les données calculées par la stratégie de commande (« myDataToMotion ») sont mises à jour ;

 ces données sont formatées pour pouvoir être envoyées à la plate-forme (fonction « setCommand() » de « myMsgToMotion ») ;

 les données sont envoyées à la plate-forme (fonction « sendMessage() » qui fait appel à la fonction « send() » de « mySocket ») ;

 les données renvoyées par la plate-forme sont récupérées (fonction « receiveMessage() » qui fait appel à la fonction « receive() » de « mySocket ») ;  ces données sont alors retranscrites (fonction « getStatus () » de

« myMsgFromMotion »)…

 … et mises à jour (« myDataFromMotion ») pour pouvoir être récupérées par le reste du programme.

147

Annexe C Shader de correction

d’image

Voici le code du shader utilisé sur le simulateur SAAM pour déformer l’image en fonction du point de vue. Ce shader est donné en HLSL (High Level Shader Language).

Les commentaires apparaissent en vert et aident à la compréhension du shader. Toutefois, pour plus d’informations, se référer à la partie 6.3.

/*

// Déclaration de la structure pour le vertex shader */

struct VSOut {

float4 pos : POSITION;

float2 tex0 : TEXCOORD0; };

/*

// vertex shader

// Rien de particulier n’est fait */

VSOut Transform2d(

float3 Pos : POSITION,

float2 Tex0 : TEXCOORD0

) {

VSOut output = (VSOut)0; output.pos = float4(Pos, 1); output.tex0 = Tex0;

return output; }

/*

// Récupération et « sampling » de l’image de la caméra */

texture2D image : TEXTURE0;

sampler g_samSrcColor = sampler_state

{ Texture = <image>; MinFilter = LINEAR; MagFilter = LINEAR; AddressU = CLAMP; AddressV = CLAMP; }; /*

// Déclaration des points E_ref et E_pos, correspondants respectivement // au point de vue de référence pour la déformation statique, et au point // de vue courant

// Les valeurs de E_ref et E_pos sont des données d’entrée du shader. */

float3 E_ref = float3(0.0,0.0,0.0);

float3 E_pos = float3(0.0,0.0,0.0);

/*

// Déclaration de la variable face, indiquant sur quelle face de l’écran on est. // 1 => face de gauche

// 2 => face du milieu // 3 => face de droite

// La valeur de face est une donnée d’entrée du shader. */

int face = 0;

// Déclaration et définition de la variable R, correspondant à la valeur en mètres // du rayon de l’écran cylindrique

*/

static float R = 1.9;

/*

// Définition du Pixel Shader pour la déformation de l’image */

float4 WarpingShader( float2 Tex : TEXCOORD0 ) : COLOR0

{

/*

// Déclaration et définition de x_0 et y_0, les coordonnées du point M */

float x_0 = Tex.x;

float y_0 = Tex.y;

/*

// Déclaration et définition de Q, Svector, Tvector et Uvector, définissant // le plan de projection de la caméra.

*/ float3 Q; float3 Svector; float3 Tvector; float3 Uvector; /*

// Les valeurs de Q, Svector, Tvector et Uvector dépendent de la face // sur laquelle on se trouve

*/

if (face == 1) // si on est sur la face de gauche

{

Q = float3 ( -1.834525, 2.28, 0.491 ); Svector = float3 ( 1.148895, 0.0, 1.280015 ); Tvector = float3 ( 0.0, -1.39, 0.0 );

Uvector = float3 ( Svector.y*Tvector.z - Svector.z*Tvector.y, Svector.z*Tvector.x - Svector.x*Tvector.z, Svector.x*Tvector.y - Svector.y*Tvector.x ); }

else

{

if (face == 3) // si on est sur la face de droite

{

Q = float3 ( 0.610889, 2.28, 1.7987 ); Svector = float3 ( 1.224086, 0.0, -1.3074 ); Tvector = float3 ( 0.0, -1.39, 0.0 );

Uvector = float3 ( Svector.y*Tvector.z - Svector.z*Tvector.y, Svector.z*Tvector.x - Svector.x*Tvector.z, Svector.x*Tvector.y - Svector.y*Tvector.x ); }

else // si on est sur la face du milieu (ou dans les autres cas)

{ Q = float3 ( -0.8175, 2.28, 1.715 ); Svector = float3 ( 1.635, 0.0, 0.0 ); Tvector = float3 ( 0.0, -1.39, 0.0 ); Uvector = float3 ( 0.0, 0.0, -1.0); } } /* // Calcul du point M */

float3 M = Q + x_0*Svector + y_0*Tvector;

/*

// Calcul du point N */

float3 ErefM = M - E_ref;

float A = ErefM.x / ErefM.z;

float B = (E_ref.x/R) - ((ErefM.x*E_ref.z)/(R*ErefM.z));

float cosTheta;

// cosTheta est solution d’une équation du second degré : // il y a donc 2 valeurs possibles : cosTheta1 et cosTheta2

float cosTheta1 = (- A*B + sqrt(A*A-B*B+1))/(A*A+1);

Annexe C 149 // On retiendra pour cosTheta la valeur positive.

if (cosTheta1 > 0) {

// Si cosTheta1 est positif, alors c’est la bonne solution

cosTheta = cosTheta1; }

else

{

// Sinon, c’est cosTheta2 la bonne solution

cosTheta = cosTheta2; }

float sinTheta = A*cosTheta + B;

float3 N = float3( R*sinTheta,

E_ref.y + (ErefM.y/ErefM.x)*(R*sinTheta - E_ref.x), R*cosTheta ); /* // Calcul du point P */ float3 QE = E_pos - Q; float3 EN = N - E_pos;

float uQE = (Uvector.x)*(QE.x) + (Uvector.y)*(QE.y) + (Uvector.z)*(QE.z);

float uEN = (Uvector.x)*(EN.x) + (Uvector.y)*(EN.y) + (Uvector.z)*(EN.z);

float k = - (uQE/uEN);

float3 QP = QE + k*EN;

float normS2 = (Svector.x)*(Svector.x) + (Svector.y)*(Svector.y) + (Svector.z)*(Svector.z);

float normT2 = (Tvector.x)*(Tvector.x) + (Tvector.y)*(Tvector.y) + (Tvector.z)*(Tvector.z);

float2 newTex;

// nexTex correspond aux coordonnées de texture du point P

newTex.x = ( (Svector.x) * (QP.x) + (Svector.y) * (QP.y) + (Svector.z) * (QP.z) ) / normS2 ; newTex.y = ( (Tvector.x) * (QP.x) + (Tvector.y) * (QP.y) + (Tvector.z) * (QP.z) ) / normT2 ;

/*

// Avant d’affecter au pixel courant la couleur du point P, on doit d’abord vérifier // que ce pixel P est bien dans l’image, c’est-à-dire que ses coordonnées de texture // sont bien comprises entre 0 et 1.

// Si le point P est en-dehors de l’image, alors on affectera la couleur errorColor // au pixel courant.

*/

float4 errorColor = float4 (0.0,1.0,0.0,1.0); // errorColor correspond à du vert /*

// Déclaration et définition de la variable isOut.

// isOut est instancié à false, c’est-à-dire qu’on fait l’hypothèse que P est dans l’image. */

bool isOut = false;

/*

// On teste la première coordonnée */ if (newTex.x > 1.0) { isOut = true; } else { if (newTex.x < 0.0) { isOut = true; } } /*

// On teste la deuxième coordonnée */ if (newTex.y > 1.0) { isOut = true; } else { if (newTex.y < 0.0) {

isOut = true; }

}

/*

// Si le point P n’est pas en-dehors de l’image, alors on affecte sa couleur // au pixel courant.

// Sinon, on affecte la couleur errorColor. */

if (isOut == false) {

return tex2D( g_samSrcColor, newTex.xy); } else { return errorColor ; } } /*

// On définit la technique « Warping », qui assemble le vertex shader // et le pixel shader qui ont été créés.

*/

technique Warping {

pass p1 {

VertexShader = compile vs_1_1 Transform2d(); PixelShader = compile ps_2_0 WarpingShader(); }