Combinaison des contrôles Feedforward ou Prédictif et PID

Note

N.D.T Le terme Feedforward sera quelquefois utilisé pour alléger le texte. Cet article couvre l’implémentation dans le code du contrôle Feedforward/PID combiné avec les librairies de classes fournies par WPILib. Une documentation décrivant ces concepts de façon plus détaillée est à venir.

Les contrôleurs de commande par anticipation et de rétroaction peuvent être utilisé séparément, cependant ils sont plus efficaces lorsqu’ils sont combinés ensemble. La combinaison de ces deux méthodes de contrôle est d’une simplicité enfantine - on ajoute simplement leurs sorties respectives…

L’utilisation d’un Feedforward avec un PIDController

Les utilisateurs peuvent ajouter n’importe quelle information de leur choix à la sortie du contrôleur avant de l’envoyer à leurs moteurs :

// Adds a feedforward to the loop output before sending it to the motor
motor.setVoltage(pid.calculate(encoder.getDistance(), setpoint) + feedforward);
// Adds a feedforward to the loop output before sending it to the motor
motor.SetVoltage(pid.Calculate(encoder.GetDistance(), setpoint) + feedforward);
# Adds a feedforward to the loop output before sending it to the motor
motor.setVoltage(pid.calculate(encoder.getDistance(), setpoint) + feedforward)

En outre, la prédiction est une fonctionnalité entièrement distincte de la rétroaction, et n’a donc aucune raison d’être traitée dans le même objet contrôleur, car cela viole la séparation des préoccupations. WPILib est livré avec plusieurs classes d’aide pour calculer des tensions de prédiction précises pour des mécanismes communs en FRC® - pour plus d’informations, consulter Commande prédictive ou par anticipation en WPILib.

L’utilisation des composants Feedforward avec PID

Note

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

À quoi pourrait ressembler un exemple plus complet de contrôle Feedforward/PID combiné? Considerez l’exemple de conduite de la section de contôle anticipé (Feedforward). Nous pouvons facilement modifier les exemples pour ajouter de la rétroaction (avec une composante SimpleMotorFeedforward):

public void tankDriveWithFeedforwardPID(double leftVelocitySetpoint, double rightVelocitySetpoint) {
  leftMotor.setVoltage(feedforward.calculate(leftVelocitySetpoint)
      + leftPID.calculate(leftEncoder.getRate(), leftVelocitySetpoint));
  rightMotor.setVoltage(feedForward.calculate(rightVelocitySetpoint)
      + rightPID.calculate(rightEncoder.getRate(), rightVelocitySetpoint));
}
void TankDriveWithFeedforwardPID(units::meters_per_second_t leftVelocitySetpoint,
                                 units::meters_per_second_t rightVelocitySetpoint) {
  leftMotor.SetVoltage(feedforward.Calculate(leftVelocitySetpoint)
      + leftPID.Calculate(leftEncoder.getRate(), leftVelocitySetpoint.value()));
  rightMotor.SetVoltage(feedforward.Calculate(rightVelocitySetpoint)
      + rightPID.Calculate(rightEncoder.getRate(), rightVelocitySetpoint.value()));
}
def tank_drive_with_feedforward_PID(
    left_velocity_setpoint: float,
    right_velocity_setpoint: float,
) -> None:
    leftMotor.setVoltage(
        feedforward.calculate(left_velocity_setpoint)
        + leftPID.calculate(leftEncoder.getRate(), left_velocity_setpoint)
    )
    rightMotor.setVoltage(
        feedforward.calculate(right_velocity_setpoint)
        + rightPID.calculate(rightEncoder.getRate(), right_velocity_setpoint)
    )

D’autre types de mécanismes peut être traité de la même façon.