前馈与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)
)
其他机制类型也可以类似地处理。