Nous allons aborder ici un aspect particulier du contrôle des robots, notamment la relation entre capteurs et moteurs, c'est-à-dire la manière dont ils interagissent les uns sur les autres.
PID désigne un dispositif, un organe de contrôle informatisé utilisé dans l'industrie pour une grande variété de machines incluant les véhicules, les robots et même les engins balistiques.
Donner ici une définition mathématique du PID est assez difficile pour ceux qui ne disposent pas de connaissances suffisantes et ne maîtrisent pas les calculs, mais une bonne compréhension du dispositif est nécessaire pour utiliser efficacement un PID.
Cette leçon décrit la façon de créer un PID destiné aux robots Lego Mindstorms NXT programmés en NXT-G version 1.1..
Elle est inspirée d'un article rédigé par James Sluka et publié le 29 septembre 2009 sur le blog NXT STEP
http://thenxtstep.blogspot.com/2009_09_01_archive.html
CHAPITRE 1
Le plus simple est de prendre un exemple, et dans notre cas, ce sera un Robot suiveur d'un tracé.
Une fois créé, le même PID peut-être employé moyennant quelques modifications mineures, pour n'importe quelle autre action, comme se diriger d'une manière rectiligne, ou grimper une rampe, ou encore se balancer en utilisant seulement 2 roues en contact avec le sol.
Pour éviter de se lancer dans des notions trop compliquées de calculs, et pour que cette approche soit à la portée de tous, je partirai d'un concept simple faisant appel aux mathématiques d'une manière très limitée.
Un PID est un outil assez simple, et sa description est facilement comprise par tous ceux qui calculent sans trop de difficultés.
Commençons par fixer les éléments de base d'un robot suiveur de tracé.
fig.1
![Image](http://img641.imageshack.us/img641/2205/basicbot1.jpg)
Ce robot schématiquement représenté, dispose de 2 roues arrières A et C entraînées chacune par un moteur.
à l'avant une roue folle. Ce dispositif permet une direction différentielle en jouant sur la vitesse des 2 moteurs. Egalement à l'avant, un capteur photosensible pointant vers le bas, de telle sorte qu'il ne "voit" que le support sur lequel il est posé. La flèche indique le sens de déplacement du robot.
L'objectif recherché est de contraindre le robot à suivre un tracé matérialisé sur le support par une large bande noire.
Ce robot, "suiveur de tracé" peut-être construit avec un capteur photosensible ou plusieurs si vous en disposez. Plus vous installerez de capteurs et meilleure sera cette conduite.
Dans notre cas nous nous limiterons à un seul capteur, car même équipé de la sorte, notre robot pourra suivre le tracé avec précision, quelle que soit sa forme, courbes comprises. La seule chose que vous perdrez, c'est la vitesse de déplacement.
La première astuce que nous utiliserons, et qui est sans rapport avec un PID, sera de suivre non pas le tracé, mais le bord du tracé. Pourquoi?
Parce que, si nous suivons le tracé lui-même (bande noire) alors que le robot s'écarte de la ligne et que le capteur "voit blanc", nous ne savons pas de quel côté du tracé nous nous trouvons. Sommes nous à droite ou à gauche? Mais si nous suivons le bord du tracé, alors nous pouvons savoir de quel côté nous nous trouvons quand le robot dévie. Si le capteur "voit blanc" alors nous savons qu'il s'agit du bord gauche. Et s'il "voit noir" nous savons qu'il se trouve à droite du bord. On appelle cela un "suiveur de tracé gauche" (left hand line follower).
Nous avons maintenant besoin de connaître les valeurs fournies par le capteur quand il "voit blanc" et quand il "voit noir". D'ordinaire, un Capteur Photosensible (non calibré) donne une valeur de 50 pour un "blanc" et 40 pour un "noir" (échelle de 0 à 100).
Si on représente ces valeurs sur une ligne graduée, on pourrait résumer les lectures de la manière suivante:
fig.2
![Image](http://img200.imageshack.us/img200/9507/lecturecapteur2.jpg)
Bien, on a donc coupé la plage de valeurs en 2 tranches égales, et on peut dire que si la valeur relevée est inférieure à 45, le robot tournera à gauche, et si elle est supérieure à 45, il tournera à droite.
Pour l'instant la manière de virer ne sera pas abordée. Disons que sur une ligne plutôt rectiligne les virages seront mieux maîtrisés. Pour un tracé présentant de nombreuses courbes, il faudra tenir compte des virages plus serrés. Dans le cas d'une trajectoire rectiligne, on prévoira un niveau de puissance égal à 50% pour la roue rapide, et 20% pour la roue lente. Pour des virages plus serrés sur une trajectoire courbe, on choisira un niveau de 30% pour la roue rapide et un freinage pour la roue lente. Quels que soient les niveaux de puissance, il seront identiques pour les 2 virages (droite et gauche); il faudra seulement inverser les valeurs des 2 moteurs.
Cette manière de suivre un tracé manque d'élégance. Elle peut paraître suffisante pour des trajectoires à peu près rectilignes, mais quand il s'agit de trajectoires sinueuses, il faut demander au robot de "serpenter" le long du tracé puisqu'il ne sait faire que 2 choses: tourner à gauche ou à droite. De plus, ce dispositif ralenti le temps de parcours et offre un spectacle désolant.
Dans cette approche le robot ne suit jamais une trajectoire rectiligne, même s'il est parfaitement aligné sur le bord du tracé. Cela ne paraît pas très efficient, n'est-ce pas?
Procédons autrement. Au lieu de diviser la ligne graduée (fig.2) en 2 parties, divisons la en 3.
fig.3
![Image](http://img69.imageshack.us/img69/9803/lecturecapteur3.jpg)
A présent, si le niveau lumineux est inférieur à 43, nous voulons que le robot tourne à gauche. Si le niveau est entre 44 et 47, le robot doit aller tout droit. Enfin si le niveau est supérieur à 47, le robot doit tourner à droite. Cette relation peut-être facilement établie en programmation NXT-G à l'aide de 2 commutateurs imbriqués (2 tests à faire et non 3).
Cette approche fonctionne mieux que la précédente. Nous savons maintenant que le robot peut avancer quelquefois en ligne droite.
Si le partage de la ligne des valeurs en 3 régions donne de meilleurs résultats qu' en 2 régions, qu'en est-il si on augmente ce nombre découpage?
C'est ici qu'on aborde le PID.
1 - Le "P" dans PID: P pour Proportionnel
Que se passe-t-il donc si on augmente le nombre de divisions dans la ligne de valeurs?
Il faut d'abord s'interroger sur le sens à donner au mot "Tourne" lorsque le nombre de régions dépasse 3. Dans la première approche, le robot ne pouvait faire que 2 choses; tourner à droite ou tourner à gauche. Les virages sont strictement identiques, mais de sens opposé. Dans la 2ème approche, on a ajouté "tout droit" aux deux précédents. Mais si nous dépassons 3 régions, il nous faut plus de "sortes" de 'Tourne', je dirai de Virages.
Fig.4
![Image](http://img64.imageshack.us/img64/442/3rgions4.jpg)
Dans le cas suivant, nous sommes en présence de ce que nous appellerons une ligne Proportionnelle. C'est à quoi ressemblerait la ligne bleu en escalier, lorsque le nombre de régions (gradins) augmenterait indéfiniment. Dans ce cas, les virages se produisent avec douceur entre ces deux limites. Si la lecture du capteur dit que l'on est proche de la ligne, alors on exécute un petit virage. Si l'on se trouve à une plus grande distance de cette ligne, alors le virage sera plus important.
Fig.5
![Image](http://img521.imageshack.us/img521/575/ligneproportionnelle5.jpg)
Proportionnel signifie qu'il existe une relation linéaire entre 2 variables.
Pour comprendre ces "plus de sortes"de 'Tourne', nous allons utiliser une représentation graphique dans un système d'axes en X et Y. L'axe horizontal (axe des X) supporte les valeurs lues du niveau de luminosité tel qu'il est représenté. L'axe Vertical (Axe des Y) sera celui des Virages.
Pour simplifier, nous dirons que proportionnel signifie qu'il existe une relation entre ces 2 variables, dont la représentation graphique est une ligne droite.
Vous devez sans doute savoir que l'équation algébrique d'une ligne droite se présente sous la forme :
y = mx + b
Où y est la valeur verticale (positive ou négative) sur l'axe des Y, et x la valeur correspondante sur l'axe des X. La constante m est la pente de cette droite et b est la valeur de Y quand cette droite coupe l'axe des Y, c'est-à-dire quand x est égal à zéro.
La pente se définit comme une valeur résultant de la division de l'écart y (variation de y) par l'écart x (variation de x) correspondante, de 2 points rapprochés pris sur cette droite.
Si vous ne savez pas grand choses sur les droites (ou si vous avez oublié), je ferai donc un petit rappel en simplifiant le graphique et l'équation. D'abord, nous remettrons le centre de notre droite de valeurs lues (l'Axe des X) au zéro. C'est facile à faire. Aux valeurs extrêmes 40 et 50 du niveau lumineux, nous soustrairons juste 45 (qui est la moyenne de 40 et 50, soit (40+50)/2) de toutes les valeurs relevées. Nous appellerons ce résultat l'erreur. Ainsi, si la valeur est 47 nous soustrairons 45 et obtiendrons une erreur = 2.
L'erreur nous donne la valeur séparant notre position jusqu'au bord du tracé . Si le capteur est exactement sur la ligne notre erreur est égale à zéro puisque nous soustrayons 45 de toutes nos lectures. Si le capteur est entièrement dans le blanc notre erreur est égale à + 5, et entièrement dans le noir égale à - 5.
Fig.6
![Image](http://img297.imageshack.us/img297/4124/ligneerreur6.jpg)
Dans ce graphique, on a remplacé les valeurs de niveau lumineux de l'axe des X par une nouvelle échelle qui est celle des erreurs. Et comme cette droite coupe l'axe des Y à l'origine c'est-à-dire au point zéro; l'équation se simplifie et devient:
y = mx
Et si on adopte une expression plus générale, on peut écrire:
Virage = m * erreur
Mais, nous n'avons pas encore défini la signification de l'axe des virages. Aussi pour l'instant contentons-nous de dire que la plage des valeurs se situe entre -1 ( virage franc à droite) et +1 (virage franc à gauche); le zéro signifiant tout droit. La pente de cette droite peut-être calculée en utilisant les coordonnées des 2 points rouge situés aux extrémités de la droite:
pente = m = (écart des y) / (écart des x) = ( 1 - (-1)) / (-5 -(5) = - 2/10 = - 0,2 soit 0,20 en valeur absolue.
La pente est une contante proportionnelle qui est le facteur multiplicateur à appliquer à l'erreur (valeur de x) pour obtenir celle du virage (valeur de y).
Dans le vocabulaire adopté pour exprimer le PID, cette constante est appelée " K " (peut-être pour rappeler la notion de constante). On peut l'assimiler à un facteur de conversion qui, à partir d'un niveau de luminosité ou d'une erreur dans notre cas, produit une autre valeur comme celle d'un virage. Très simple et très puissant!
Donc, en utilisant ces nouvelles conventions, on peut écrire l'équation de cette droite ainsi:
Virage = K * (erreur)
La valeur Virage est considérée comme une sortie de notre Contrôleur P, et désignée par le terme P.
Vous avez remarqué que dans le dernier graphique, la ligne erreur est dans la plage -5 et +5. En dehors de cette plage, il n'est plus possible de déterminer l'éloignement du capteur par rapport au tracé. Tous les "blanc" sont identiques si le capteur n'est pas en mesure de détecter un "noir". Souvenez-vous que cette plage est arbitraire, car elle est déterminée par les caractéristiques du capteur photosensible, les couleurs des supports, etc…. Dès que le capteur s'éloigne trop du tracé, il relève des valeurs constantes ; cela signifie que les lectures ne sont plus proportionnelles à l'erreur.
La déviation par rapport au tracé ne peut être appréciée que si le capteur est assez proche de ce tracé. C'est à l'intérieur de cette plage que les valeurs lues sont proportionnelles à la distance. A l'extérieur de cette plage, il nous indique la bonne direction, mais l'ampleur est faussée. La lecture des valeurs, ou l'erreur, est plus petite qu'elle ne l'est en réalité, et ne fournit donc pas une réponse satisfaisante.
Dans la définition du PID, la plage qui nous intéresse et qui donne une réponse proportionnelle est appelée "Plage Proportionnelle". Ce concept est très important dans la notion du PID.
Pour revenir à notre suivi de tracé, la Plage Proportionnelle pour le Capteur Photosensible se situe entre 40 et 50, et pour l'erreur elle est comprise entre -5 et +5. On peut également noter que les servomoteurs ont eux aussi une plage proportionnelle, de -100 (pleine puissance arrière) à +100 (pleine puissance avant).
Deux remarques importantes sur la Plage Proportionnelle:
(1) Vous souhaitez une plage proportionnelle aussi grande que possible.
La plage proportionnelle du Capteur Photosensible est assez petite, cela signifie que le Capteur doit être assez près du bord du tracé pour obtenir des valeurs proportionnelles. Plus exactement, la grandeur de la plage dépend essentiellement de la hauteur du capteur par rapport au plan du tracé. Si le capteur est très proche du plan, disons 2 mm environ, il émet un très petit cercle lumineux. Un petit déplacement du capteur produira une variation de l'erreur de -5 à +5, correspondant à notre plage proportionnelle.
Vous pourriez dire que le capteur a "des vues étroites" et il peut seulement voir une très petite partie du plan. Le capteur doit être très près du bord du tracé pour obtenir une lecture qui n'est pas "blanc" ou "noir". Si le capteur est positionné plus haut, la tache lumineuse s'étale en un plus grand cercle sur le plan. À une hauteur de 12 mm environ, le capteur émet une tache lumineuse de même dimension. A cette hauteur, la plage proportionnelle est trop grande, le capteur devant se maintenir entre +/- 12 mm de part et d'autre du bord du tracé pour obtenir un résultat proportionnel satisfaisant.
Malheureusement, il y a deux inconvénient pour une position trop élevée du capteur. D'abord le capteur "voit" et réagit à l'éclairage ambiant beaucoup plus que s'il se trouve en position basse. Ensuite, il discerne moins bien les nuances entre le noir et le blanc. A une certaine distance, il donnera une même lecture au noir et au blanc.
(2) À l'extérieur de la plage proportionnelle le contrôleur provoquera un déplacement dans une direction correcte mais sous-évaluée. La réponse proportionnelle du contrôleur est limitée par la plage proportionnelle.
2 - De P à niveaux de puissance réelle du moteur.
Comment pouvons-nous mettre en oeuvre les virages ? Quel doit être le niveau de puissance des moteurs ?
Une façon d'envisager les virages consiste à définir "un Niveau de Puissance Cible", que nous appellerons "Tp". Tp est le niveau de puissance des deux moteurs quand on suppose que le robot se déplace tout droit, ce qu'il fait quand l'erreur = 0.
Quand l'erreur n'est pas nulle nous utilisons l'équation virage = K * (l'erreur) pour calculer le changement des niveaux de puissance des deux moteurs. Un moteur obtiendra un niveau de puissance égal Tp+Virage, l'autre moteur obtiendra un niveau de puissance égal à Tp-Virage.
A noter que notre erreur est comprise entre -5 à +5, ce qui signifie que le Virage peut être positif ou négatif c'est-à-dire, correspondant aux virages dans des sens opposés. Il se trouve que c'est exactement ce que nous recherchons puisqu'il mettra automatiquement un moteur en accélération et l'autre en ralentissement.
Un moteur (nous supposerons que c'est le moteur gauche du robot raccordé au port A) obtiendra toujours la valeur de Tp+Virage comme niveau de puissance. L'autre moteur (le droit raccordé au port C) obtiendra toujours la Tp-Virage comme c'est le niveau de puissance. Si l'erreur est positive, alors Virage est positif et Tp+Virage est plus grand que Tp; la vitesse du moteur gauche augmentera alors que celle du moteur droit diminuera.
Si l'erreur change de signe et devient négative (signifiant qu'on a franchi le bord du tracé et voit l'autre couleur), alors Tp+Virage est maintenant plus petit que Tp, la vitesse du moteur gauche augmente et celle du moteur droit diminue, puisque Tp-Virage est plus grand que Tp (rappelez-vous que le produit de 2 valeurs négatives donne une valeur positive). Simple, non?
Poursuivons.
3 - Pseudo Code pour un Contrôleur P
D'abord nous devons évaluer les valeurs lues par le capteur de lumière pour le blanc et le noir. De ces deux valeurs nous pouvons calculer la moyenne, c'est-à-dire quelle valeur soustraire à celle d'une lumière brute lue pour convertir l'ensemble en valeur d'erreur. La moyenne est la demi-somme des lectures "blanc" et "noir". Pour la simplicité on supposera que cette moyenne a déjà été mesurée et stockée dans une variable appelée moyenne. (Une démarche intéressante consisterait à faire calculer la moyenne par le robot à partir des mesures lues niveaux blanc et noir).
Nous aurons aussi besoin d'un emplacement de stockage pour la constante K, nous l'appellerons Kp (de constant pour le contrôleur proportionnel). Ainsi qu'une valeur de défaut pour Kp.
Il y a plusieurs façons pour l'obtenir, par tâtonnement puis corrections successives de l'erreur. Ou alors, vous pouvez essayer d'évaluer une valeur basée sur les caractéristiques du capteur et du robot.
Nous appliquerons cette dernière méthode. Nous utiliserons un Tp (niveau de puissance cible) de 50: quand l'erreur est égale à zéro les deux moteurs fonctionneront au niveau 50. La plage d'erreur se situe entre -5 à +5. Nous supposerons que la puissance variera de 50 à 0 quand l'erreur passera de 0 à -5. Cela signifie que Kp (la pente souvenez-vous, la variation de y divisée par la variation de x correspondante) est:
Kp = (0 - 50) / (-5 -0) = 10
Nous utiliserons la valeur 10 pour Kp, afin de convertir une valeur erreur en valeur Virage. En d'autres termes: une variation de 1 de l'erreur, se traduira par une augmentation de 10 de la puissance d'un moteur. L'autre moteur verra sa puissance diminuer de 10.
Aussi, en pseudo-code, c'est-à-dire, sous forme d'énumérations logiques d'actions, indépendamment du langage de programmation utilisé ( NXT-G ou autre), nous pourrions écrire:
Kp = 10 ! Initialisation de trois variables
moyenne = 45
Tp = 50
Loop forever ! Début de Boucle pour toujours
LightValue = valeurlueducapteur ! Quelle est la valeur lue courante du capteur?
erreur = LightValue - moyenne ! calcul de l'erreur par soustraction de la moyenne.
Virage = Kp * erreur ! le terme "P", de combien veut-on modifier la puissance du moteur
powerA = Tp + Virage ! niveau de puissance pour le moteur A
powerC = Tp - Virage ! niveau de puissance pour le moteur C
MOTOR A direction=forward power=powerA ! transmet la commande avec la nouvelle valeur de puissance dans un bloc MOTEUR.
MOTOR C direction=forward power=powerC ! Commande identique à l'autre moteur mais en utilisant l'autre valeur de puissance.
end loop forever ! fin de boucle, retour au début de boucle et recommencer à nouveau.
Bien, nous y voilà presque. Il y a cependant un problème subtil qui devrait être corrigé. Mais laissez de toute manière une chance à votre robot. S'il semble s'écarter du bord du tracé, au lieu de s'en rapprocher, la cause la plus probable est que vous avez inversé les sens des Virages. Corrigez Kp à -10 et vérifiez le résultat Si cela rectifie les sens de Virage alors revenez à Kp en conservant +10 et changent les signes dans les deux lignes de la manière suivante;
powerA = Tp - Virage
powerC = Tp + Virage
Il y a deux "paramètres variables" et une constante dans ce contrôleur P. La constante est la valeur moyenne (la moyenne des lectures du capteur photosensible pour le blanc et le noir). Vous devrez donc écrire un court programme pour évaluer les niveaux lumineux sur votre surface d'évolution de votre robot. Vous avez besoin de déterminer une valeur "noir" et une valeur "blanc". Calculez la moyenne et placez-la dans le programme du contrôleur P (dans la variable Moyenne).
La plupart des lignes qui vont suivre supposent que vous avez réalisé ce petit programme exécuté par le robot.
La valeur de Kp et la puissance cible Tp sont des paramètres variables. Un paramètre variable doit être choisi par tâtonnements et approximations successives. Kp contrôlera la vitesse du contrôleur dans ses mouvements de retour au bord du tracé quand il s'en est éloigné. Tp contrôlera la vitesse du robot dans son déplacement le long du tracé.
Si la ligne est pratiquement rectiligne, vous pouvez utiliser une grande valeur pour Tp afin de déplacer le robot à grande vitesse, et une petite valeur pour Kp pour rendre les virages plus doux.
Si le tracé présente des courbes serrées, La valeur maximum Tp sera la meilleure. Si Tp est supérieur à ce maximum, la valeur de Kp importe peu, et le robot ratera son virage car il se déplace trop rapidement. Si Tp est faible, la plupart des valeurs de Kp seront acceptables compte tenu du lent déplacement du robot. L'objectif est d'avoir un déplacement le plus rapide possible sans perdre la capacité de suivre le tracé.
Nous avions supposé une valeur de départ pour Kp de 10. Pour Tp vous pourriez choisir une valeur plus faible que celle suggérée ci-dessus, peut-être 15 (le robot se déplace assez lentement). Essayez et vérifiez le résultat. Si vous ratez le tracé parce que le robot semble virer trop lentement, alors augmentez Kp et essayez à nouveau. Si vous ratez le tracé parce que le robot semble trop réactif dans la recherche du tracé dans les deux sens diminuez alors Kp. Si le robot semble suivre le tracé correctement, augmentez Tp et assurez-vous de pouvoir suivre le tracé à une vitesse plus rapide. Pour chaque nouvelle valeur de Tp vous devrez déterminer une nouvelle valeur correspondante de Kp, sachant que Kp présente d'habitude peu de variation.
Suivre un tracé rectiligne est d'ordinaire assez facile. Suivre un tracé comportant des courbes douces est un peu plus délicat. Suivre enfin un tracé comportant des courbes serrées est nettement plus dur.
Si le robot se déplace assez lentement, presque n'importe quel tracé peut être suivi, même avec un contrôleur rudimentaire. Nous recherchons un bon suivi de tracé, avec une vitesse convenable et la capacité d'aborder avec succès les virages doux. (Les tracés avec virages serrés suivent généralement des trajectoires de tracés plus spécialisées).
Il est évident que le meilleur contrôleur P est spécifique à chaque type de tracé (largeur, rayons des courbes, éclairage, etc.) et à chaque robot. En d'autres termes, un contrôleur P (ou un contrôleur PID en la matière) est conçu pour une seule sorte de tracé et de robot et ne fonctionnera pas convenablement pour d'autres tracés ou robots. Il faudra donc adapter les paramètres Kp et Tp selon les circonstances.
Une idée intéressante consisterait à noter sous forme de tableau, toutes les tests avec les valeurs modifiées des différents paramètres. Chaque test pouvant être commenté en termes simples pour faire ressortir les valeurs qui conviennent le mieux.
Avant d'aller plus loin, Je vous propose deux exercices dont l'utilité se retrouvera par la suite.
Premier exercice:
Utiliser le tapis d'évolution (test pad) fourni dans le kit # 8527.
Ecrire un programme NXT-G capable de lire les valeurs fournies par le capteur photosensible pour le 'blanc' et le 'noir' à partir du tracé ovale du tapis d'évolution. Puis calculer la moyenne et la stocker dans une variable (cette moyenne permettra de calculer par la suite l'erreur).
Pour accomplir ce travail, placer le robot, le nez sur le tracé du tapis.
Au début du programme, le robot doit accomplir un balayage en pivotant sur lui-même. Pendant ce balayage (demi-rotation du moteur A), capter les valeurs et les stocker dans des variables. Arrêt du robot. Une fois ces valeurs captées, faire revenir le nez du robot à proximité du tracé. Arrêt du robot et affichage de la valeur moyenne sur le petit écran.
Deuxième exercice:
Transformer le programme précédent en un 'Mon bloc' en utilisant la palette 'Perso.' Ce 'Mon Bloc' est une routine qui sera utilisée pour l'écriture du programme futur du contrôleur P. Ce bloc est aussi très utile et peut-être réutilisé pour l'écriture d'autres programmes faisant appel aux valeurs lues du capteur.
Dans un prochain chapitre, nous verrons comment écrire un PID en NXT-G dans un cas simple utilisant le bloc DEPLACER.
![;) ;)](./images/smilies/;).gif)
edit :
suite (1) de la leçon : post53474.html#p53474
suite (2) de la leçon : post56827.html#p56827
suite (3) de la leçon : post58022.html#p58022
suite (4) de la leçon : post58757.html#p58757