前馈与PID控制相结合

备注

本文介绍了结合前馈/ PID控制和WPILib提供的库类的代码内实现。以及详细描述所涉及概念的文档。

前馈和反馈控制器可以单独使用,但组合在一起时最有效。值得庆幸的是,将这两种控制方法结合起来*非常*简单明了-只需将它们的输出相加即可。

将前馈与PIDController一起使用

Users may add any feedforward they like to the output of the controller before sending it to their motors:

// 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)

此外,前馈是与反馈完全独立的功能,因此没有理由在同一控制器对象中进行处理,因为这违反了关注点分离。 WPILib带有多个帮助程序类,可以为常见的FRC | reg |计算准确的前馈电压。机制-有关更多信息,请参阅:ref:docs/software/advanced-controls/controllers/feedforward:Feedforward Control in WPILib.

通过PID使用前馈组件

备注

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.

前馈/ PID组合控制的更完整示例是什么样子?考虑前馈页面上的驱动器示例<docs / software / advanced-controls / controllers / feedforward:将前馈用于控制机制>。我们可以很容易地修改它以包括反馈控制(带有“ 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)
    )

其他机制类型也可以类似地处理。