Robots suiveurs 3 - Capteurs
Le logiciel Webots dispose d'une large collection de capteurs déjà configurés disposant de méthodes associées. Le robot E-puck que nous utilisons dans ce projet dispose de différents capteurs prépositionnés :
- 8 capteurs de distance infrarouge
- Camera couleur VGA
- Accéléromètre 3D (non utilisé)
- Émetteur-récepteur ZigBee
Nous allons donc détailler dans cette partie le fonctionnement des capteurs utilisés.
Capteur de distance
Afin de détecter des obstacles, nous utilisons des capteurs de distance qu'on modélise grâce au node DistanceSensor. Nous allons décrire ici son fonctionnement.
Champs du node DistanceSensor
les champs du capteur de mouvement sont composés d'une table servant a définir sa fonction de transfert et de caractéristiques du laser (son nombre de rayons, son ouverture, etc).
| Nom | Type | Valeurs possibles |
| lookupTable | SFVec3f | lookup table |
| type | SFString | {"generic", "infra-red", "sonar", "laser"} |
| numberOfRays | Int32 | [1, inf) |
| aperture | SFFloat | [0, 2*pi] |
| gaussianWidth | SFFloat | [0, inf) |
| resolution | SFFloat | {-1, [0, inf)} |
LookUpTable
La LookUpTable est un tableau à 2 dimensions servant à faire la correspondance entre la distance en mètre mesurée par le capteur et la valeur de sortie du capteur. Cette table consiste en une liste de coordonnées de points qui, une fois reliés, nous donne la fonction de transfert du capteur. A chaque point est associé une valeur d'écart type pour son bruit associé.
Les valeurs de la table sont pré-configurés pour correspondre à un capteur précis. On peut voir sur le graphique que plus la distance est faible, plus la valeur de sortie augmente vite. Afin d'éviter précisément des obstacles, et de simplifier la mesure des distance, nous pouvons modifier la table. En ne positionnant que deux points aux extrémités des intervalles, nous obtenons une droite affine. Nous avons donc une précision constante en fonction de la distance et les conversions distance/code sont plus simples. Il serait possible par la suite d'étudier l'influence du bruit sur les performances du robot. Nous pourrons aussi questionner la pertinence de ces modifications qui changent peut-être trop le fonctionnement des capteurs pour correspondre à la réalité.
Méthodes utilisées
| Méthode | Paramètres | Description |
| void wb_distance_sensor_enable(WbDeviceTag tag) | WbDeviceTag tag : tag du capteur afin de le cibler | Active le capteur de distance ciblé. |
| double wb_distance_sensor_get_value(WbDeviceTag tag) | WbDeviceTag tag : tag du capteur afin de le cibler | Renvoie la valeur associée à la distance mesurée du capteur ciblé. |
Caméra
Pour modéliser une caméra, nous utilisons une caméra embarquée classique, modélisée grâce au node Caméra, et en donnant une couleur rouge à l'objet à suivre, comme ci celui-ci était une source de chaleur. L'image résultante peut être affichée sur la fenêtre 3D et nous permet de visualiser l'image en RGB dans notre cas.
Champ du node Camera
| Nom | Type | Valeur par défaut | Valeurs possibles |
| fieldOfView | SFFloat | 0.7854 | [0, pi] |
| width | SFInt32 | 64 | [0, inf) |
| height | SFInt32 | 64 | [0, inf) |
| spherical | SFBool | FALSE | {TRUE, FALSE} |
| near | SFFloat | 0.01 | [0, inf) |
| far | SFFloat | 0.0 | [0, inf) |
| antiAliasing | SFBool | FALSE | {TRUE, FALSE} |
| ambientOcclusionRadius | SFFloat | 0 | [0, inf) |
| bloomThreshold | SFFloat | -1.0 | [-1, inf) |
| motionBlur | SFFloat | 0.0 | [0, inf) |
| noise | SFFloat | 0.0 | [0, 1] |
| noiseMaskUrl | SFString | "" | any string |
| lens | SFNode | NULL | {Lens, PROTO} |
| focus | SFNode | NULL | {Focus, PROTO} |
| zoom | SFNode | NULL | {Zoom, PROTO} |
| recognition | SFNode | NULL | {Recognition, PROTO} |
| lensFlare | SFNode | NULL | {LensFlare, PROTO} |
Fonctions utiles (en C++)
| Fonction | Utilité |
| virtual void enable(int samplingPeriod); | Activation de la caméra |
| virtual void disable(); | Désactivation de la caméra |
| int getWidth() const; | Récupération de la largeur de l'image en pixels |
| int getHeight() const; | Récupération de la hauteur de l'image en pixels |
| const unsigned char *getImage() const; | Lecture de la dernière image saisie par l'appareil photo. L'image est codée comme une séquence de trois octets représentant les niveaux rouge, vert et bleu d'un pixel. Les pixels sont stockés sur des lignes horizontales allant du côté supérieur gauche de l'image jusqu'au coin inférieur droit. |
| static unsigned char imageGetRed(const unsigned char *image, int width, int x, int y); | Accès au niveau de rouge d'un pixel RGB à partir de ses coordonnées |
| static unsigned char imageGetGreen(const unsigned char *image, int width, int x, int y); | Accès au niveau de vert d'un pixel RGB à partir de ses coordonnées |
| static unsigned char imageGetBlue(const unsigned char *image, int width, int x, int y); | Accès au niveau de bleu d'un pixel RGB à partir de ses coordonnées |
Utilisation de l'image
L'image de la caméra est affichée en temps réel, en haut de la fenêtre 3D par défaut. La résolution de la caméra peut être modifiée dans les caractéristiques de celle-ci.
Afin d'exploiter l'image issue de la caméra, il suffit d'analyser tout ou partie des pixels qui la composent. Une comparaison entre les nombres de pixels rouges, verts et bleus permet par exemple de détecter la présence d'un objet de couleur.
Émetteur-récepteur
Afin de faire communiquer des robots, nous utilisons des émetteurs et récepteurs, qu'on modélise grâce aux nodes Emitter et Receiver, respectivement. Nous allons décrire ici les bases de son fonctionnement. Pour plus d'information, veuillez accéder aux liens des nodes (vers le site de cyberbotics).
Champs des nodes Emitter et Receiver
Emitter
| Nom | Type | Valeur par défaut | Valeurs possibles |
| type | SFString | "radio" | {"radio", "serial", "infra-red"} |
| range | SFFloat | -1 | {-1, [0, inf)} |
| maxRange | SFFloat | -1 | {-1, [0, inf)} |
| aperture | SFFloat | -1 | {-1 ,[0, 2*pi]} |
| channel | SFInt32 | 0 | [0, inf) |
| baudRate | SFInt32 | -1 | {-1, [0, inf)} |
| byteSize | SFInt32 | 8 | [8, inf) |
| bufferSize | SFInt32 | -1 | {-1, [0, inf)} |
Receiver
| Nom | Type | Valeur par défaut | Valeurs possibles |
| type | SFString | "radio" | {"radio", "serial", "infra-red"} |
| aperture | SFFloat | -1 | {-1 ,[0, 2*pi]} |
| channel | SFInt32 | 0 | [0, inf) |
| baudRate | SFInt32 | -1 | {-1, [0, inf)} |
| byteSize | SFInt32 | 8 | [8, inf) |
| bufferSize | SFInt32 | -1 | {-1, [0, inf)} |
| signalStrengthNoise | SFFloat | 0 | [0, inf) |
| directionNoise | SFFloat | 0 | [0, inf) |
Description des champs
Emitter
- type : type de signaux: "radio", "serial" ou "infra-red". Les signaux de type "radio" (par défaut) et "serial" sont transmis sans tenir compte des obstacles. Cependant, les signaux de type "infra-red" tiennent compte des obstacles potentiels entre l'émetteur et le récepteur. Tout objet solide (solide, robots, etc ...) avec un objet englobant défini est un obstacle potentiel à une communication "infra-red". La structure du robot émetteur ou récepteur lui-même ne bloquera pas une transmission "infra-red". Actuellement, il n'y a pas de différence d'implémentation entre les types "radio" et "serial".
- range : rayon de la sphère d'émission (en mètres). Un récepteur ne peut recevoir un message que s'il se trouve dans la sphère d'émission. Une valeur de -1 (par défaut) pour la plage est considérée comme une plage infinie.
- maxRange : définit la valeur maximale autorisée pour la plage. Ce champ définit la valeur maximale pouvant être définie à l'aide de la fonction wb_emitter_set_range. Une valeur de -1 (par défaut) pour maxRange est considérée comme infinie.
- aperture : angle d'ouverture du cône d'émission (en radians); pour "infra-red" uniquement. L'apex du cône est situé à l'origine ([0 0 0]) du système de coordonnées de l'émetteur et l'axe du cône coïncide avec l'axe z du système de coordonnées de l'émetteur. Un émetteur "infra-red" ne peut envoyer des données qu'aux récepteurs actuellement situés dans son cône d'émission. Une ouverture de -1 (valeur par défaut) est considérée comme infinie, ce qui signifie que les signaux émis sont omnidirectionnels. Pour les émetteurs "radio" et "serial", ce champ est ignoré.
- channel : canal de transmission. Il s'agit d'un numéro d'identification pour un émetteur "infra-red" ou d'une fréquence pour un émetteur "radio". Normalement, un récepteur doit utiliser le même canal qu'un émetteur pour recevoir les données émises. Cependant, le canal spécial -1 permet de diffuser des messages sur tous les canaux. Le canal 0 (par défaut) est réservé pour communiquer avec un plugin physique. Pour la communication inter-robots, veuillez utiliser des numéros de canaux positifs.
- baudRate : le débit en bauds est la vitesse de communication exprimée en nombre de bits par seconde. Un baudRate de -1 (par défaut) est considéré comme infini et entraîne la transmission immédiate des données (dans un pas de temps de base) de l'émetteur au récepteur.
- byteSize : la taille d'octet est le nombre de bits requis pour transmettre un octet d'information. Il s'agit généralement de 8 (valeur par défaut), mais peut être supérieur si des bits de contrôle sont utilisés.
- bufferSize : spécifie la taille (en octets) du buffer de transmission. Le nombre total d'octets dans les paquets mis en file d'attente dans l'émetteur ne peut pas dépasser ce nombre. Un bufferSize de -1 (par défaut) est considéré comme une taille de buffer illimitée.
Receiver
- type : idem que pour l'émetteur.
- aperture : angle d'ouverture du cône de réception (en radians); pour "infra-red" uniquement. Le récepteur ne peut recevoir que des messages d'émetteurs situés actuellement dans son cône de réception. L'apex du cône est situé à l'origine ([0 0 0]) du système de coordonnées du récepteur et l'axe du cône coïncide avec l'axe z du système de coordonnées du récepteur. Une ouverture de -1 (valeur par défaut) est considérée comme infinie, ce qui signifie qu'un signal peut être reçu de n'importe quelle direction. Pour les récepteurs "radio", le champ d'ouverture est ignoré.
- channel : canal de réception. La valeur est un numéro d'identification pour un récepteur "infra-red" ou une fréquence pour un récepteur "radio". Normalement, l'émetteur et le récepteur doivent utiliser le même canal pour pouvoir communiquer. Cependant, le numéro de canal spécial -1 permet au récepteur d'écouter tous les canaux.
- baudRate : le débit en bauds est la vitesse de communication exprimée en bits par seconde. Elle doit être identique à la vitesse de l'émetteur. Actuellement, ce champ est ignoré.
- byteSize : la taille en octets est le nombre de bits utilisés pour représenter un octet de données transmises (généralement 8, mais peut être supérieur si des bits de contrôle sont utilisés). Il doit être de la même taille que la taille des octets de l'émetteur. Actuellement, ce champ est ignoré.
- bufferSize : taille (en octets) du buffer de réception. La taille des données reçues ne doit à aucun moment dépasser la taille de la mémoire buffer, sinon les données peuvent être perdues. Un bufferSize de -1 (par défaut) est considéré comme une taille de buffer illimitée. Si les données précédentes n'ont pas été lues lors de la réception de nouvelles données, les données précédentes sont perdues.
- signalStrengthNoise : écart-type du bruit gaussien ajouté à la force du signal renvoyé par wb_receiver_get_signal_strength (ou getSignalStrength() en C++). Le bruit est proportionnel à la force du signal, par exemple, un signalStrengthNoise de 0,1 ajoutera un bruit avec un écart-type de 0,1 pour une force de signal de 1 et 0,2 pour une force de signal de 2.
- directionNoise : écart-type du bruit gaussien ajouté à chacune des composantes de la direction retournée par wb_receiver_get_emitter_direction (ou getEmitterDirection() en C++). Le bruit ne dépend pas de la distance entre l'émetteur-récepteur.
Fonctions Disponibles (en C++)
Emitter
| Fonction | Utilité |
| virtual int send(const void *data, int size); | Ajoute à la file d'attente de l'émetteur un paquet d'octets de taille situé à l'adresse indiquée par "data". |
| virtual void setChannel(int channel); | Permet au contrôleur de changer le canal de transmission. |
| int getChannel() const; | Renvoie le numéro de canal actuel de l'émetteur. |
| virtual void setRange(double range); | Permet au contrôleur de modifier la plage de transmission au moment de l'exécution. |
| double getRange() const; | Renvoie la plage actuelle de l'émetteur. |
| int getBufferSize() const; | Renvoie la taille (en octets) du buffer de transmission. |
Receiver
| Fonction | Utilité |
| virtual void enable(int samplingPeriod); | Démarre le récepteur à l'écoute des paquets de données entrants. |
| virtual void disable(); | Arrête l'écoute en arrière-plan. |
| int getSamplingPeriod() const; | Renvoie la période donnée dans la fonction enable, ou 0 si le périphérique est désactivé. |
| int getQueueLength() const; | Renvoie le nombre de paquets de données actuellement présents dans la file d'attente du récepteur. |
| virtual void nextPacket(); | Supprime le paquet de tête. Le paquet suivant dans la file d'attente, le cas échéant, devient le nouveau paquet principal. |
| const void *getData() const; | Renvoie les données du paquet en tête de la file d'attente de réception. |
| int getDataSize() const; | Renvoie le nombre d'octets de données présents dans le paquet de tête de la file d'attente de réception. |
| double getSignalStrength() const; | Renvoie la force du signal simulé au moment où le paquet a été transmis. |
| const double *getEmitterDirection() const; | Renvoie un vecteur normalisé (longueur = 1) qui indique la direction de l'émetteur par rapport au système de coordonnées du récepteur. |
| virtual void setChannel(int channel); | Permet à un récepteur de changer de canal de réception. |
| int getChannel() const; | Renvoie le numéro de canal actuel du récepteur. |
