Le contrôleur PID¶
Contrôler un mécanisme¶
Maintenant que nous savons contrôler les moteurs et lire les informations des capteurs, il faut les utiliser ensemble pour contrôler intelligemment et efficacement vos mécanismes. Voici quelques termes qui seront utiles pour la suite :
Setpoint¶
Le setpoint est l’objectif que le mécanisme doit atteindre. Pour un élévateur, le setpoint est la hauteur désirée. Pour un pivot, c’est un angle. On peut aussi imaginer un shooter dont le setpoint serait la vitesse de rotation adéquate pour lancer l’objet à la bonne distance.
Erreur¶
L’erreur est la différence entre le setpoint et l’état (position, vitesse) du mécanisme à un instant donné. Pour un élévateur, c’est la distance (positive ou négative) qu’il reste à parcourir pour atteindre le setpoint.
Output¶
L’output est la correction exercé sur le mécanisme pour le rapprocher du setpoint. Il peut être exprimé sur une échelle de -1 à 1 représentant la puissance donnée au moteur ou bien en volts.
PID, ça veut dire quoi ?¶
Le PID est une méthode pour contrôler les mécanismes efficacement. C’est la boucle de contrôle la plus utilisée dans l’industrie car elle peut s’appliquer à de nombreuses situations (thermostat, régulateur de position, de vitesse). C’est un acronyme signifiant : Proportionnel, Intégral, Dérivé, les 3 termes qui composent le PID.
L’équation d’un contrôleur PID est la somme de ces 3 termes :
Proportionnel¶
Le terme proportionnel est égal au produit d’un coefficient constant (kP ou P gain) et de l’erreur. Ce terme est ainsi élevé quand l’erreur est élevé (au début) et diminue lorsque le mécanisme se rapproche du setpoint. Plus le coefficient est élevé, plus la réponse du système sera rapide mais plus le mécanisme risquera d’osciller.
Intégral¶
En utilisant seulement le terme proportionnel, le mécanisme peut osciller (kP trop élevé) ou bien rester en dessous du setpoint (kP trop faible). Pour cela, on peut utiliser le terme intégral. Celui-ci est égal à la somme de toutes les erreurs depuis le début. Ce terme va ainsi augmenter de plus en plus si le mécanisme reste en dessous du setpoint trop longtemps.
Dérivé¶
Le terme dérivé est égal à la variation de l’erreur sur la variation du temps. C’est la « pente » de l’erreur. Dans le code du robot, le delta temps sera toujours le même entre 2 itérations. On peut donc résumer le terme dérivé en la variation de l’erreur entre 2 itérations soit la différence entre l’erreur actuelle et l’erreur précédente.
Le coefficient kD est souvent négatif afin de réguler « l’accélération » du mécanisme. Si l’accélération est trop élevée, le terme dérivé sera alors d’autant plus important et ralentira le mécanisme.
Feed-Forward¶
Au PID on peut ajouter un 4ème terme, le terme F pour feed forward. Il peut être calculé en connaissant les caractéristiques du mécanisme :
Élévateur : Pour contrer la gravité exercée sur un élévateur, le voltage nécessaire peut être calculé en fonction de la masse de l’élévateur, du torque du moteur et du ratio de la gearbox.
Pivot : Pour contrer la gravité exercée sur le bras du pivot, le terme F peut être calculé en fonction de l’angle du bras :
Il existe d’autres cas comme les bases roulantes où le terme F peut être utile pour contrer les forces de frottement ou d’accélération.
Coder un PID¶
Le Code¶
Maintenant que nous avons appris la théorie du PID, utilisons le pour déplacer
notre élévateur de façon autonome. Pour l’exemple, un dira que l’unique moteur
de l’élévateur sera contrôlé par un VictorSP
et que la position de
l’élévateur nous sera donnée par un Encoder
. A vous de jouer.
Correction
Normalement, votre programme sera séparé en 2 fichiers différents : Robot.h et Robot.cpp. Ici, le programme est dans un seul fichier pour plus de simplicité :
#include <frc/TimedRobot.h>
#include <frc/VictorSP.h>
#include <frc/Encoder.h>
class Robot : public frc::TimedRobot
{
public:
void RobotInit() override
{
// Le sens de rotation du moteur
m_Moteur.SetInverted(false);
// Le sens dans lequel compte l'encodeur
m_Encodeur.SetReverseDirection(false);
// Conversion ticks -> mètres
m_Encodeur.SetDistancePerPulse(m_DistanceParTick);
m_Setpoint = 0.0;
m_Erreur = 0.0;
m_ErreurPrecedente = 0.0;
m_SommeErreurs = 0.0;
m_Derivee = 0.0;
}
void RobotPeriodic () override
{
position = m_Encodeur.GetDistance();
m_Erreur = m_Setpoint - position;
m_SommeErreurs += m_Erreur;
m_Derivee = m_Erreur - m_ErreurPrecedente;
double output = m_P * m_Erreur + m_I * m_SommeErreurs + m_D * m_Derivee + m_F;
m_Moteur.Set(output);
m_ErreurPrecedente = m_Erreur;
}
void TeleopPeriodic() override
{
// En fonction des actions du pilote :
// Utiliser la fonction SetSetpoint pour déplacer l'élévateur
}
void SetSetpoint(double setpoint)
{
if(setpoint < m_MinSetpoint)
{
m_Setpoint = m_MinSetpoint;
}
else if(setpoint > m_MaxSetpoint)
{
m_Setpoint = m_MaxSetpoint:
}
else
{
m_Setpoint = setpoint;
}
}
private:
// Moteurs et Capteurs
frc::VictorSP m_Moteur(0);
frc::Encoder m_Encodeur(0, 1);
// Facteur de conversion des ticks vers une distance en mètre
const double m_DistanceParTick = 0.05;
// Variables du PID
double m_Setpoint;
double m_Erreur;
double m_ErreurPrecedente;
double m_SommeErreurs;
double m_Derivee;
// Valeurs déterminées scientifiquement
const double m_P = 0.8;
const double m_I = 0.01;
const double m_D = - 0.2;
const double m_F = 0.15;
// L'élévateur peut aller de 0 m jusqu'à 1.5 m de hauteur
const double m_MinSetpoint = 0.0;
const double m_MaxSetpoint = 1.5;
};
Le Réglage¶
L’étape de tuning (de réglage) du PID consiste à trouver les bonnes valeurs pour les 3 coefficients P, I et D. Il faut commencer avec I et D à zéro et en réglant seulement P. C’est le coefficient P qui va determiner la « vitesse de réaction » du mécanisme. Ensuite, si il y a besoin, on peut ajuster les 2 autres coefficients afin d’améliorer le PID.
Le réglage d’un PID se fait souvent de façon empirique (au talent) Il existe cependant différentes méthodes censées faciliter cette étape mais souvent régler le PID à l’instinct suffit.
Attention
Régler un PID peu s’avérer très dangereux si des précautions ne sont pas prises. Pensez, au tout début, à calculer l’ordre de grandeur de vos coefficients en fonction des valeurs de l’erreur.
Par exemple, pour un élévateur dont l’erreur sera au maximum égale à 1,5 (m), on veut commencer avec un output maximum inférieur à 0,1.
On peut donc commencer avec un coefficient P aux alentours de 0.06666 sans prendre trop de risques. En revanche, si la distance parcourue par l’élévateur était exprimée en cm, un coefficient de 0.06666 serait beaucoup trop élevé et dangereux ( !!!).