Commande prédictive ou par anticipation en WPILib

Note

This article focuses on in-code implementation of feedforward control in WPILib. For a conceptual explanation of the feedforward equations used by WPILib, see Introduction to DC Motor Feedforward

You may have used feedback control (such as PID) for reference tracking (making a system’s output follow a desired reference signal). While this is effective, it’s a reactionary measure; the system won’t start applying control effort until the system is already behind. If we could tell the controller about the desired movement and required input beforehand, the system could react quicker and the feedback controller could do less work. A controller that feeds information forward into the plant like this is called a feedforward controller.

A feedforward controller injects information about the system’s dynamics (like a mathematical model does) or the intended movement. Feedforward handles parts of the control actions we already know must be applied to make a system track a reference, then feedback compensates for what we do not or cannot know about the system’s behavior at runtime.

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);
// Create a new SimpleMotorFeedforward with gains kS, kV, and kA
// Distance is measured in meters
frc::SimpleMotorFeedforward<units::meters> feedforward(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);
// Calculates the feedforward for a velocity of 10 meters/second and an acceleration of 20 meters/second^2
// Output is in volts
feedforward.Calculate(10_mps, 20_mps_sq);

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);
// Create a new ArmFeedforward with gains kS, kG, kV, and kA
frc::ArmFeedforward feedforward(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);
// Calculates the feedforward for a position of 1 radians, a velocity of 2 radians/second, and
// an acceleration of 3 radians/second^2
// Output is in volts
feedforward.Calculate(1_rad, 2_rad_per_s, 3_rad/(1_s * 1_s));

La classe ElevatorFeedforward

Note

In C++, the passed-in gains must have units consistent with the distance units, or a compile-time error will be thrown. kS and kG should have units of volts, kV should have units of volts * seconds / distance, and kA should have units of volts * seconds^2 / distance. For more information on C++ units, see 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);
// Create a new ElevatorFeedforward with gains kS, kV, and kA
// Distance is measured in meters
frc::ElevatorFeedforward feedforward(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);
// Calculates the feedforward for a velocity of 20 meters/second
// and an acceleration of 30 meters/second^2
// Output is in volts
feedforward.Calculate(20_mps, 30_mps_sq);

Utilisation de Feedforward pour contrôler les mécanismes

Note

Since feedforward voltages are physically meaningful, it is best to use the setVoltage() (Java, C++) method when applying them to motors to compensate for « voltage sag » from the battery.

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));
}
void TankDriveWithFeedforward(units::meters_per_second_t leftVelocity,
                              units::meters_per_second_t rightVelocity) {
  leftMotor.SetVoltage(feedforward.Calculate(leftVelocity));
  rightMotor.SetVoltage(feedforward.Calculate(rightVelocity));
}