Commande prédictive ou par anticipation en WPILib

N.D.T. le terme anglais Feedforward sera utilisé quelquefois pour alléger le texte. Jusqu’à présent, nous avons utilisé le contrôle de rétroaction pour le suivi des références (faire en sorte que la sortie d’un système suive le signal de référence souhaité). Bien que cela soit efficace, c’est une mesure réactionnaire; le système ne commencera pas à appliquer l’effort de contrôle tant que le système n’a pas pris un certain retard. Si nous pouvions informer le contrôleur du mouvement souhaité et de l’entrée requise à l’avance, le système pourrait réagir plus rapidement et le contrôleur de rétroaction pourrait faire moins de travail. Un contrôleur qui transmet des informations à l’Usine comme celle-ci est appelé contrôleur par anticipation (Feedforward).

Un contrôleur par anticipation injecte des informations sur la dynamique du système (comme le fait un modèle mathématique) ou le mouvement prévu. La composante calculée par anticipation donne le mouvement désiré et la meilleure façon d’atteindre le point de contrôle, et la rétroaction du système compense pour ce que nous ignorons, ou les variations du comportement du système au moment de l’exécution.

Il existe deux types de contrôleurs par anticipation: Feedforward basé sur un modèle et Feedforward pour une dynamique sans modèle. Le premier résout un modèle mathématique du système pour les entrées nécessaires pour répondre aux vitesses et accélérations souhaitées. Le second compense directement les forces ou les comportements non modélisés afin que le contrôleur de rétroaction n’ait pas à le faire. Les deux types peuvent faciliter des contrôleurs de rétroaction plus simples. Nous couvrirons plusieurs exemples ci-dessous.

Les classes FeedForward WPILib

WPILib fournit un certain nombre de classes pour aider les utilisateurs à implémenter une commande feedforward pour leurs mécanismes. À bien des égards, un feedforward précis est plus important que la rétroaction au contrôle efficace d’un mécanisme. Comme la plupart des mécanismes en FRC® obéissent étroitement aux équations bien comprises du système, en commençant par un feedforward précis est à la fois facile et extrêmement bénéfique pour le contrôle précis et robuste du mécanisme

Les classes d’anticipation WPILib correspondent étroitement aux outils de caractérisation des mécanismes disponibles dans la suite d’outils SysId. La suite d’outils d’identification du système peut être utilisée pour déterminer rapidement et efficacement les gains corrects pour chaque type d’anticipation. Si vous n’êtes pas en mesure de caractériser empiriquement votre mécanisme (en raison de contraintes d’espace et/ou de temps), des estimations raisonnables de kG, kV et kA peuvent être obtenues par un calcul assez simple, et sont également disponibles sur ReCalc. kS est presque impossible à modéliser et doit être mesuré de manière empirique.

WPILib fournit actuellement les trois classes suivantes pour le contrôle Feedforward

La classe « SimpleMotorFeedforward »

Note

En C ++, la classe SimpleMotorFeedforward est basée sur le type d’unité utilisé pour les mesures de distance, qui peut être angulaire ou linéaire. Les gains transmis doivent avoir des unités cohérentes avec les unités de distance, sinon une erreur de compilation sera générée. kS doit avoir des unités de volts, kV doit avoir des unités de volts * secondes / distance et kA doit avoir des unités de volts * secondes^2 / distance. Pour plus d’informations sur les unités C ++, voir La librairie d’unités C++.

Note

Les composants Java Feedforward calculent les sorties en unités déterminées par les unités des gains Feedforward fournis par l’utilisateur. Les utilisateurs doivent maintenir la cohérence des unités, car WPILibJ ne dispose pas d’un système d’unités de type sécurisé.

La classe SimpleMotorFeedforward calcule les valeurs de Feedforward pour les mécanismes qui se composent de moteurs à courant continu à aimant permanent (comme le CIM, Bag, 775…) sans charge externe autre que le frottement et l’inertie, tels que les volants d’inertie et les entraînements de robots.

Pour créer un SimpleMotorFeedforward, il suffit de le construire avec les gains requis:

Note

Le gain kA peut être omis, et s’il l’est, sera par défaut à une valeur de zéro. Pour de nombreux mécanismes, en particulier ceux avec peu d’inertie, ce n’est pas nécessaire.

// Create a new SimpleMotorFeedforward with gains kS, kV, and kA
SimpleMotorFeedforward feedforward = new SimpleMotorFeedforward(kS, kV, kA);

Pour calculer le feedforward, il suffit d’appeler la méthode calculate() avec la vitesse et l’accélération désirées du moteur:

Note

L’argument d’accélération peut être omis de l’appel calculate(), et si c’est le cas, sa valeur par défaut sera zéro. Cela doit être fait chaque fois qu’il n’y a pas de point de consigne d’accélération clairement défini.

// Calculates the feedforward for a velocity of 10 units/second and an acceleration of 20 units/second^2
// Units are determined by the units of the gains passed in at construction.
feedforward.calculate(10, 20);

La classe ArmFeedforward

Note

En C++, la classe ArmFeedforward suppose que les distances sont angulaires et non linéaires. Les gains transmis doivent avoir des unités cohérentes avec l’unité angulaire, sinon une erreur de compilation sera générée. kS et kG doivent avoir des unités de volts, kV doivent avoir des unités de volts * secondes / radians, et kA doivent avoir des unités de volts * secondes^2 / radians. Pour plus d’informations sur les unités C++, consultez La librairie d’unités C++.

Note

Les composants Java Feedforward calculent les sorties en unités déterminées par les unités des gains Feedforward fournis par l’utilisateur. Les utilisateurs doivent maintenir la cohérence des unités, car WPILibJ ne dispose pas d’un système d’unités de type sécurisé.

La classe ArmFeedforward calcule les valeurs de Feedforward pour les bras de levier qui sont contrôlés directement par un moteur à courant continu à aimant permanent, avec une charge externe de frottement, d’inertie et de masse du bras. Il s’agit d’un modèle précis qui simule la plupart des bras de levier utilisés en FRC.

Pour créer un ArmFeedforward, il suffit de le construire avec les gains requis:

Note

Le gain kA peut être omis, et s’il l’est, sera par défaut à une valeur de zéro. Pour de nombreux mécanismes, en particulier ceux avec peu d’inertie, ce n’est pas nécessaire.

// Create a new ArmFeedforward with gains kS, kG, kV, and kA
ArmFeedforward feedforward = new ArmFeedforward(kS, kG, kV, kA);

Pour calculer le Feedforward, il suffit d’appeler la méthode calculate() avec la position, la vitesse et l’accélération souhaitées du bras de levier:

Note

L’argument d’accélération peut être omis de l’appel calculate(), et si c’est le cas, sa valeur par défaut sera zéro. Cela doit être fait chaque fois qu’il n’y a pas de point de consigne d’accélération clairement défini.

// Calculates the feedforward for a position of 1 units, a velocity of 2 units/second, and
// an acceleration of 3 units/second^2
// Units are determined by the units of the gains passed in at construction.
feedforward.calculate(1, 2, 3);

La classe ElevatorFeedforward

Note

En C++, la classe ElevatorFeedforward est basée sur le type d’unité utilisé pour les mesures de distance, qui peut être angulaire ou linéaire. Les gains transmis doivent avoir des unités cohérentes avec les unités de distance, sinon une erreur de compilation sera levée. kS et kG doivent avoir des unités de volts, kV doivent avoir des unités de volts * secondes / distance et kA doivent avoir des unités de volts * secondes ^ 2 / distance. Pour plus d’informations sur les unités C ++, voir La librairie d’unités C++.

Note

Les composants Java Feedforward calculent les sorties en unités déterminées par les unités des gains Feedforward fournis par l’utilisateur. Les utilisateurs doivent maintenir la cohérence des unités, car WPILibJ ne dispose pas d’un système d’unités de type sécurisé.

La classe ElevatorFeedforward calcule les feed-back pour un mécanisme de type ascenseur qui se composent de moteurs à courant continu à aimant permanent chargés par le frottement, l’inertie et la masse de charge déplacée par l’ascenseur. Il s’agit d’un modèle précis de la plupart des mécanismes d’ascenseurs en FRC.

Pour créer un ElevatorFeedforward, il suffit de le construire avec les gains requis:

Note

Le gain kA peut être omis, et s’il l’est, sera par défaut à une valeur de zéro. Pour de nombreux mécanismes, en particulier ceux avec peu d’inertie, ce n’est pas nécessaire.

// Create a new ElevatorFeedforward with gains kS, kG, kV, and kA
ElevatorFeedforward feedforward = new ElevatorFeedforward(kS, kG, kV, kA);

Pour calculer le feedforward, il suffit d’appeler la méthode calculate() avec la vitesse et l’accélération désirées du moteur:

Note

L’argument d’accélération peut être omis de l’appel calculate(), et si c’est le cas, sa valeur par défaut sera zéro. Cela doit être fait chaque fois qu’il n’y a pas de point de consigne d’accélération clairement défini.

// Calculates the feedforward for a velocity of 20 units/second
// and an acceleration of 30 units/second^2
// Units are determined by the units of the gains passed in at construction.
feedforward.calculate(20, 30);

Utilisation de Feedforward pour contrôler les mécanismes

Note

Étant donné que les tensions de contrôle d’anticipation (feedforward) sont physiquement significatives, il est préférable d’utiliser la méthode setVoltage() (Java, C++) lors de leur application sur des moteurs pour compenser « l’affaissement de la tension » de la batterie.

Le contrôle par anticipation (Feedforward) peut être utilisé à lui seul, sans contrôleur de rétroaction. Ceci est connu sous le nom de contrôle « en boucle ouverte », et pour de nombreux mécanismes (en particulier les moteurs qui font avancer le robot) peuvent être parfaitement satisfaisants. Un SimpleMotorFeedforward peut être utilisé pour contrôler un entraînement de robot comme suit:

public void tankDriveWithFeedforward(double leftVelocity, double rightVelocity) {
  leftMotor.setVoltage(feedforward.calculate(leftVelocity));
  rightMotor.setVoltage(feedForward.calculate(rightVelocity));
}