WPILib中的前馈控制

备注

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.

The WPILib Feedforward Classes

WPILib提供了许多类来帮助用户实现对其机制的精确前馈控制。在许多方面,准确的前馈比反馈对机制的有效控制更为重要。由于大多数FRC | reg |机构严格遵循易于理解的系统方程式,从准确的前馈开始既容易又对精确且鲁棒的机构控制非常有利。

The WPILib feedforward classes closely match the available mechanism characterization tools available in the SysId toolsuite. The system identification toolsuite can be used to quickly and effectively determine the correct gains for each type of feedforward. If you are unable to empirically characterize your mechanism (due to space and/or time constraints), reasonable estimates of kG, kV, and kA can be obtained by fairly simple computation, and are also available from ReCalc. kS is nearly impossible to model, and must be measured empirically.

WPILib当前提供以下三个帮助程序类用于前馈控制:

SimpleMotor前馈

备注

在C ++中,``SimpleMotorFeedforward’’类以用于距离测量的单位类型为模板,可以是角度或线性的。传递的增益*必须*具有与距离单位一致的单位,否则将引发编译时错误。 ``kS’’的单位应为``伏特’’,``kV’’的单位应为``伏特*秒/距离’’,``kA’’的单位应为``伏特*秒/秒^ 2 /距离。有关C ++单元的更多信息,请参见:docs / software / basic-programming / cpp-units:C ++单元库。

备注

Java前馈组件将以由用户提供的前馈增益的单位确定的单位来计算输出。用户*必须*务必保持单元一致,因为WPILibJ没有类型安全的单元系统。

备注

The API documentation for Python feedforward components indicate which unit is being used as wpimath.units.NAME. Users must take care to use correct units, as Python does not have a type-safe unit system.

``SimpleMotorFeedforward’’类计算由永磁直流电机组成的机构的前馈,这些电机除了摩擦和惯性外没有其他负载,例如飞轮和机器人驱动器。

要创建``SimpleMotorFeedforward’’,只需使用所需的增益即可构造它:

备注

可以省略``kA’’增益,如果是,则默认为零。对于许多机构,尤其是惯性很小的机构,没有必要。

// 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);
from wpimath.controller import SimpleMotorFeedforwardMeters

# Create a new SimpleMotorFeedforward with gains kS, kV, and kA
# Distance is measured in meters
feedforward = SimpleMotorFeedforwardMeters(kS, kV, kA)

要计算前馈,只需使用所需的电动机速度和加速度调用calculate()方法即可:

备注

可以在calculate()调用中省略加速度参数,如果是,则默认为零。如果没有明确定义的加速度设定值,则应执行此操作。

// 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);
# 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, 20)

臂前馈

备注

In C++, the ArmFeedforward class assumes distances are angular, not linear. The passed-in gains must have units consistent with the angular unit, or a compile-time error will be thrown. kS and kG should have units of volts, kV should have units of volts * seconds / radians, and kA should have units of volts * seconds^2 / radians. For more information on C++ units, see C++ 单位库.

备注

Java前馈组件将以由用户提供的前馈增益的单位确定的单位来计算输出。用户*必须*务必保持单元一致,因为WPILibJ没有类型安全的单元系统。

备注

The API documentation for Python feedforward components indicate which unit is being used as wpimath.units.NAME. Users must take care to use correct units, as Python does not have a type-safe unit system.

``ArmFeedforward’’类可计算由永磁直流电动机直接控制的臂的前馈,并具有外部的摩擦力,惯性和质量。这是FRC中大多数武器的准确模型。

要创建一个``ArmFeedforward``,只需使用所需的增益构造它即可:

备注

可以省略``kA’’增益,如果是,则默认为零。对于许多机构,尤其是惯性很小的机构,没有必要。

// 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);
from wpimath.controller import ArmFeedforward

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

要计算前馈,只需使用所需的手臂位置,速度和加速度调用calculate()方法即可:

备注

可以在calculate()调用中省略加速度参数,如果是,则默认为零。如果没有明确定义的加速度设定值,则应执行此操作。

// 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));
# 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, 2, 3)

抬升架前馈

备注

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 C++ 单位库.

备注

Java前馈组件将以由用户提供的前馈增益的单位确定的单位来计算输出。用户*必须*务必保持单元一致,因为WPILibJ没有类型安全的单元系统。

备注

The API documentation for Python feedforward components indicate which unit is being used as wpimath.units.NAME. Users must take care to use correct units, as Python does not have a type-safe unit system.

``ElevatorFeedforward’’类可为电梯计算前馈,该电梯由永磁直流电动机组成,该电动机由电梯的摩擦力,惯性和质量加载。这是FRC中大多数电梯的准确模型。

要创建``ElevatorFeedforward’’,只需使用所需的增益构造它即可:

备注

可以省略``kA’’增益,如果是,则默认为零。对于许多机构,尤其是惯性很小的机构,没有必要。

// 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);
from wpimath.controller import ElevatorFeedforward

# Create a new ElevatorFeedforward with gains kS, kV, and kA
# Distance is measured in meters
feedforward = ElevatorFeedforward(kS, kG, kV, kA)

要计算前馈,只需使用所需的电动机速度和加速度调用calculate()方法即可:

备注

可以在calculate()调用中省略加速度参数,如果是,则默认为零。如果没有明确定义的加速度设定值,则应执行此操作。

// 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);
# 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, 30)

使用前馈控制机制

备注

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.

前馈控制可以完全单独使用,而无需反馈控制器。这就是所谓的“开环”控制,对于许多机构(尤其是机器人驱动器),都可以令人满意。可以使用``SimpleMotorFeedforward’’来控制机器人驱动器,如下所示:

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));
}
def tankDriveWithFeedforward(self, leftVelocity: float, rightVelocity: float):
    self.leftMotor.setVoltage(feedForward.calculate(leftVelocity))
    self.rightMotor.setVoltage(feedForward.calculate(rightVelocity))