mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-05 03:21:42 +00:00
[wpimath] Add minLinearAccel parameter to DifferentialDriveAccelerationLimiter (#4422)
This commit is contained in:
@@ -4,7 +4,9 @@
|
||||
|
||||
package edu.wpi.first.math.controller;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import edu.wpi.first.math.MatBuilder;
|
||||
@@ -204,4 +206,98 @@ class DifferentialDriveAccelerationLimiterTest {
|
||||
assertEquals(x.get(1, 0), xAccelLimiter.get(1, 0), 1e-5);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSeperateMinMaxLowLimits() {
|
||||
final double trackwidth = 0.9;
|
||||
final double dt = 0.005;
|
||||
final double minA = -1.0;
|
||||
final double maxA = 2.0;
|
||||
final double maxAlpha = 2.0;
|
||||
|
||||
var plant = LinearSystemId.identifyDrivetrainSystem(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
var accelLimiter =
|
||||
new DifferentialDriveAccelerationLimiter(plant, trackwidth, minA, maxA, maxAlpha);
|
||||
|
||||
var x = new MatBuilder<>(Nat.N2(), Nat.N1()).fill(0.0, 0.0);
|
||||
var xAccelLimiter = new MatBuilder<>(Nat.N2(), Nat.N1()).fill(0.0, 0.0);
|
||||
|
||||
// Ensure voltage exceeds acceleration before limiting
|
||||
{
|
||||
final var accels =
|
||||
plant
|
||||
.getA()
|
||||
.times(xAccelLimiter)
|
||||
.plus(plant.getB().times(new MatBuilder<>(Nat.N2(), Nat.N1()).fill(12.0, 12.0)));
|
||||
final double a = (accels.get(0, 0) + accels.get(1, 0)) / 2.0;
|
||||
System.out.println(a);
|
||||
assertTrue(Math.abs(a) > maxA);
|
||||
assertTrue(Math.abs(a) > -minA);
|
||||
}
|
||||
|
||||
// a should always be within [minA, maxA]
|
||||
// Forward
|
||||
var u = new MatBuilder<>(Nat.N2(), Nat.N1()).fill(12.0, 12.0);
|
||||
for (double t = 0.0; t < 3.0; t += dt) {
|
||||
x = plant.calculateX(x, u, dt);
|
||||
final var voltages =
|
||||
accelLimiter.calculate(
|
||||
xAccelLimiter.get(0, 0), xAccelLimiter.get(1, 0), u.get(0, 0), u.get(1, 0));
|
||||
xAccelLimiter =
|
||||
plant.calculateX(
|
||||
xAccelLimiter,
|
||||
new MatBuilder<>(Nat.N2(), Nat.N1()).fill(voltages.left, voltages.right),
|
||||
dt);
|
||||
|
||||
final var accels =
|
||||
plant
|
||||
.getA()
|
||||
.times(xAccelLimiter)
|
||||
.plus(
|
||||
plant
|
||||
.getB()
|
||||
.times(
|
||||
new MatBuilder<>(Nat.N2(), Nat.N1())
|
||||
.fill(voltages.left, voltages.right)));
|
||||
final double a = (accels.get(0, 0) + accels.get(1, 0)) / 2.0;
|
||||
assertTrue(minA <= a && a <= maxA);
|
||||
}
|
||||
|
||||
// Backward
|
||||
u = new MatBuilder<>(Nat.N2(), Nat.N1()).fill(-12.0, -12.0);
|
||||
for (double t = 0.0; t < 3.0; t += dt) {
|
||||
x = plant.calculateX(x, u, dt);
|
||||
final var voltages =
|
||||
accelLimiter.calculate(
|
||||
xAccelLimiter.get(0, 0), xAccelLimiter.get(1, 0), u.get(0, 0), u.get(1, 0));
|
||||
xAccelLimiter =
|
||||
plant.calculateX(
|
||||
xAccelLimiter,
|
||||
new MatBuilder<>(Nat.N2(), Nat.N1()).fill(voltages.left, voltages.right),
|
||||
dt);
|
||||
|
||||
final var accels =
|
||||
plant
|
||||
.getA()
|
||||
.times(xAccelLimiter)
|
||||
.plus(
|
||||
plant
|
||||
.getB()
|
||||
.times(
|
||||
new MatBuilder<>(Nat.N2(), Nat.N1())
|
||||
.fill(voltages.left, voltages.right)));
|
||||
final double a = (accels.get(0, 0) + accels.get(1, 0)) / 2.0;
|
||||
assertTrue(minA <= a && a <= maxA);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMinAccelGreaterThanMaxAccel() {
|
||||
var plant = LinearSystemId.identifyDrivetrainSystem(1.0, 1.0, 1.0, 1.0);
|
||||
assertDoesNotThrow(() -> new DifferentialDriveAccelerationLimiter(plant, 1, -1, 1, 1e3));
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> new DifferentialDriveAccelerationLimiter(plant, 1, 1, -1, 1e3));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,4 +171,87 @@ TEST(DifferentialDriveAccelerationLimiterTest, HighLimits) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DifferentialDriveAccelerationLimiterTest, SeperateMinMaxLowLimits) {
|
||||
constexpr auto trackwidth = 0.9_m;
|
||||
constexpr auto dt = 5_ms;
|
||||
constexpr auto minA = -1_mps_sq;
|
||||
constexpr auto maxA = 2_mps_sq;
|
||||
constexpr auto maxAlpha = 2_rad_per_s_sq;
|
||||
|
||||
using Kv_t = decltype(1_V / 1_mps);
|
||||
using Ka_t = decltype(1_V / 1_mps_sq);
|
||||
auto plant = LinearSystemId::IdentifyDrivetrainSystem(Kv_t{1.0}, Ka_t{1.0},
|
||||
Kv_t{1.0}, Ka_t{1.0});
|
||||
|
||||
DifferentialDriveAccelerationLimiter accelLimiter{plant, trackwidth, minA,
|
||||
maxA, maxAlpha};
|
||||
|
||||
Vectord<2> x{0.0, 0.0};
|
||||
Vectord<2> xAccelLimiter{0.0, 0.0};
|
||||
|
||||
// Ensure voltage exceeds acceleration before limiting
|
||||
{
|
||||
Vectord<2> accels =
|
||||
plant.A() * xAccelLimiter + plant.B() * Vectord<2>{12.0, 12.0};
|
||||
units::meters_per_second_squared_t a{(accels(0) + accels(1)) / 2.0};
|
||||
EXPECT_GT(units::math::abs(a), maxA);
|
||||
EXPECT_GT(units::math::abs(a), -minA);
|
||||
}
|
||||
|
||||
// a should always be within [minA, maxA]
|
||||
// Forward
|
||||
Vectord<2> u{12.0, 12.0};
|
||||
for (auto t = 0_s; t < 3_s; t += dt) {
|
||||
x = plant.CalculateX(x, u, dt);
|
||||
auto [left, right] =
|
||||
accelLimiter.Calculate(units::meters_per_second_t{xAccelLimiter(0)},
|
||||
units::meters_per_second_t{xAccelLimiter(1)},
|
||||
units::volt_t{u(0)}, units::volt_t{u(1)});
|
||||
xAccelLimiter =
|
||||
plant.CalculateX(xAccelLimiter, Vectord<2>{left, right}, dt);
|
||||
|
||||
Vectord<2> accels =
|
||||
plant.A() * xAccelLimiter + plant.B() * Vectord<2>{left, right};
|
||||
units::meters_per_second_squared_t a{(accels(0) + accels(1)) / 2.0};
|
||||
EXPECT_GE(a, minA);
|
||||
EXPECT_LE(a, maxA);
|
||||
}
|
||||
|
||||
// Backward
|
||||
u = Vectord<2>{-12.0, -12.0};
|
||||
for (auto t = 0_s; t < 3_s; t += dt) {
|
||||
x = plant.CalculateX(x, u, dt);
|
||||
auto [left, right] =
|
||||
accelLimiter.Calculate(units::meters_per_second_t{xAccelLimiter(0)},
|
||||
units::meters_per_second_t{xAccelLimiter(1)},
|
||||
units::volt_t{u(0)}, units::volt_t{u(1)});
|
||||
xAccelLimiter =
|
||||
plant.CalculateX(xAccelLimiter, Vectord<2>{left, right}, dt);
|
||||
|
||||
Vectord<2> accels =
|
||||
plant.A() * xAccelLimiter + plant.B() * Vectord<2>{left, right};
|
||||
units::meters_per_second_squared_t a{(accels(0) + accels(1)) / 2.0};
|
||||
EXPECT_GE(a, minA);
|
||||
EXPECT_LE(a, maxA);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DifferentialDriveAccelerationLimiterTest, MinAccelGreaterThanMaxAccel) {
|
||||
using Kv_t = decltype(1_V / 1_mps);
|
||||
using Ka_t = decltype(1_V / 1_mps_sq);
|
||||
auto plant = LinearSystemId::IdentifyDrivetrainSystem(Kv_t{1.0}, Ka_t{1.0},
|
||||
Kv_t{1.0}, Ka_t{1.0});
|
||||
EXPECT_NO_THROW({
|
||||
DifferentialDriveAccelerationLimiter accelLimiter(plant, 1_m, 1_mps_sq,
|
||||
1_rad_per_s_sq);
|
||||
});
|
||||
|
||||
EXPECT_THROW(
|
||||
{
|
||||
DifferentialDriveAccelerationLimiter accelLimiter(
|
||||
plant, 1_m, 1_mps_sq, -1_mps_sq, 1_rad_per_s_sq);
|
||||
},
|
||||
std::invalid_argument);
|
||||
}
|
||||
|
||||
} // namespace frc
|
||||
|
||||
Reference in New Issue
Block a user