Slew Rate Limiting
Slew Rate Limiting is a simple numerical filter that constrains the rate of change of some value. This can be very useful in multiple situations to prevent unexpected sharp motions
SlewRateLimiter limit = new SlewRate(maxRatePerSecond)
// ...
var constrainedOutput = limit.calculate(unconstrainedInput)
By far the most helpful use case on everyday robots. This helps drivers get reliable, steady control of the robot, preventing sharp jerky motions. It also has the lowest risk of quirky side effects.
// Ordinary call with no ramping applied
drivetrain.arcadeDrive(forward, turn);
// Slew-rate limits the forward/backward input, limiting forward/backward acceleration
drivetrain.arcadeDrive(limit.calculate(forward), turn);
In some cases it can be helpful to contain motor outputs directly.
In fact, this use case is so common that Rev controllers have two variants of this built in
// Applies the slew rate on outputs generated by
// motor.set(...)
motorconfig.openLoopRampRate(rate);
// Applies the slew rate on outputs generated by
// motor.setReference(...)
motorconfig.closedLoopRampRate(rate);
The closedLoopRampRate
can help mitigate sharp oscillations around setpoints caused by imperfect PID tunings, and harsh transitions on setpoint changes. This can a lot of stability to simple systems, as well as make tuning easier.
The openLoopRampRate
is valuable for preventing harsh transitions between power levels, commonly encountered for simple button-actuated motions on rollers.
This application of slew rate limiting is most common earlier in your robotics career. Eventually, this simple method will be replaced with more advanced Motion Profiles.
Applying slew rate limits to PID setpoints can significantly improve ease of tuning and reduce many issues with setpoint jumps creating large error terms.
This application of slew-rates effectively creates a limited version of a Trapezoidal Motion Profile , but with some extra constraints and caveats.
A common surprise you might encounter with slew rate limiters is that they constrain limits in both up and down. This makes perfect mathematical sense, but the effect is that heavily rate-limited things may not stop when you expect them to. This can cause them to feel "unresponsive" or "floating". This is most common with things like buttons or joysticks; Stuff won't stop moving when you release, because it'll slowly coast down.
The internal implementation accounts for "change per time interval", with "time interval" being defined as the current and previous runs of the calculate()
method. If your system stops calculating for a time, the time interval is very large, which means the allowed change in the current iteration is also very large! This can permit the very problems you wanted to solve. If you're restarting a slew rate process, you'll need to reset it by creating a new instance of the SlewRate limiter and over-riding the old one.