mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-03 03:01:44 +00:00
[wpimath] Make swerve and differential kinematics functions immutable (#8274)
Originally started with just swerve, but expanded to diff and mecanum (docs only) for parity across the drivetrains. Return value checks are applied when possible to make migration easier and to error loudly if people forget. --------- Co-authored-by: Joseph Eng <91924258+KangarooKoala@users.noreply.github.com>
This commit is contained in:
@@ -272,7 +272,7 @@ TEST_F(SwerveDriveKinematicsTest, Desaturate) {
|
||||
SwerveModuleVelocity state4{7.0_mps, 0_deg};
|
||||
|
||||
wpi::util::array<SwerveModuleVelocity, 4> arr{state1, state2, state3, state4};
|
||||
SwerveDriveKinematics<4>::DesaturateWheelVelocities(&arr, 5.5_mps);
|
||||
arr = SwerveDriveKinematics<4>::DesaturateWheelVelocities(arr, 5.5_mps);
|
||||
|
||||
double kFactor = 5.5 / 7.0;
|
||||
|
||||
@@ -289,8 +289,8 @@ TEST_F(SwerveDriveKinematicsTest, DesaturateSmooth) {
|
||||
SwerveModuleVelocity state4{7.0_mps, 0_deg};
|
||||
|
||||
wpi::util::array<SwerveModuleVelocity, 4> arr{state1, state2, state3, state4};
|
||||
SwerveDriveKinematics<4>::DesaturateWheelVelocities(
|
||||
&arr, m_kinematics.ToChassisVelocities(arr), 5.5_mps, 5.5_mps,
|
||||
arr = SwerveDriveKinematics<4>::DesaturateWheelVelocities(
|
||||
arr, m_kinematics.ToChassisVelocities(arr), 5.5_mps, 5.5_mps,
|
||||
3.5_rad_per_s);
|
||||
|
||||
double kFactor = 5.5 / 7.0;
|
||||
@@ -308,7 +308,7 @@ TEST_F(SwerveDriveKinematicsTest, DesaturateNegativeVelocity) {
|
||||
SwerveModuleVelocity state4{-2.0_mps, 0_deg};
|
||||
|
||||
wpi::util::array<SwerveModuleVelocity, 4> arr{state1, state2, state3, state4};
|
||||
SwerveDriveKinematics<4>::DesaturateWheelVelocities(&arr, 1.0_mps);
|
||||
arr = SwerveDriveKinematics<4>::DesaturateWheelVelocities(arr, 1.0_mps);
|
||||
|
||||
EXPECT_NEAR(arr[0].velocity.value(), 0.5, kEpsilon);
|
||||
EXPECT_NEAR(arr[1].velocity.value(), 0.5, kEpsilon);
|
||||
|
||||
@@ -13,119 +13,119 @@ static constexpr double kEpsilon = 1E-9;
|
||||
TEST(SwerveModuleVelocityTest, Optimize) {
|
||||
wpi::math::Rotation2d angleA{45_deg};
|
||||
wpi::math::SwerveModuleVelocity refA{-2_mps, 180_deg};
|
||||
refA.Optimize(angleA);
|
||||
auto optimizedA = refA.Optimize(angleA);
|
||||
|
||||
EXPECT_NEAR(refA.velocity.value(), 2.0, kEpsilon);
|
||||
EXPECT_NEAR(refA.angle.Degrees().value(), 0.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedA.velocity.value(), 2.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedA.angle.Degrees().value(), 0.0, kEpsilon);
|
||||
|
||||
wpi::math::Rotation2d angleB{-50_deg};
|
||||
wpi::math::SwerveModuleVelocity refB{4.7_mps, 41_deg};
|
||||
refB.Optimize(angleB);
|
||||
auto optimizedB = refB.Optimize(angleB);
|
||||
|
||||
EXPECT_NEAR(refB.velocity.value(), -4.7, kEpsilon);
|
||||
EXPECT_NEAR(refB.angle.Degrees().value(), -139.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedB.velocity.value(), -4.7, kEpsilon);
|
||||
EXPECT_NEAR(optimizedB.angle.Degrees().value(), -139.0, kEpsilon);
|
||||
}
|
||||
|
||||
TEST(SwerveModuleVelocityTest, NoOptimize) {
|
||||
wpi::math::Rotation2d angleA{0_deg};
|
||||
wpi::math::SwerveModuleVelocity refA{2_mps, 89_deg};
|
||||
refA.Optimize(angleA);
|
||||
auto optimizedA = refA.Optimize(angleA);
|
||||
|
||||
EXPECT_NEAR(refA.velocity.value(), 2.0, kEpsilon);
|
||||
EXPECT_NEAR(refA.angle.Degrees().value(), 89.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedA.velocity.value(), 2.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedA.angle.Degrees().value(), 89.0, kEpsilon);
|
||||
|
||||
wpi::math::Rotation2d angleB{0_deg};
|
||||
wpi::math::SwerveModuleVelocity refB{-2_mps, -2_deg};
|
||||
refB.Optimize(angleB);
|
||||
auto optimizedB = refB.Optimize(angleB);
|
||||
|
||||
EXPECT_NEAR(refB.velocity.value(), -2.0, kEpsilon);
|
||||
EXPECT_NEAR(refB.angle.Degrees().value(), -2.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedB.velocity.value(), -2.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedB.angle.Degrees().value(), -2.0, kEpsilon);
|
||||
}
|
||||
|
||||
TEST(SwerveModuleVelocityTest, CosineScaling) {
|
||||
wpi::math::Rotation2d angleA{0_deg};
|
||||
wpi::math::SwerveModuleVelocity refA{2_mps, 45_deg};
|
||||
refA.CosineScale(angleA);
|
||||
auto optimizedA = refA.CosineScale(angleA);
|
||||
|
||||
EXPECT_NEAR(refA.velocity.value(), std::sqrt(2.0), kEpsilon);
|
||||
EXPECT_NEAR(refA.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedA.velocity.value(), std::sqrt(2.0), kEpsilon);
|
||||
EXPECT_NEAR(optimizedA.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
|
||||
wpi::math::Rotation2d angleB{45_deg};
|
||||
wpi::math::SwerveModuleVelocity refB{2_mps, 45_deg};
|
||||
refB.CosineScale(angleB);
|
||||
auto optimizedB = refB.CosineScale(angleB);
|
||||
|
||||
EXPECT_NEAR(refB.velocity.value(), 2.0, kEpsilon);
|
||||
EXPECT_NEAR(refB.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedB.velocity.value(), 2.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedB.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
|
||||
wpi::math::Rotation2d angleC{-45_deg};
|
||||
wpi::math::SwerveModuleVelocity refC{2_mps, 45_deg};
|
||||
refC.CosineScale(angleC);
|
||||
auto optimizedC = refC.CosineScale(angleC);
|
||||
|
||||
EXPECT_NEAR(refC.velocity.value(), 0.0, kEpsilon);
|
||||
EXPECT_NEAR(refC.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedC.velocity.value(), 0.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedC.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
|
||||
wpi::math::Rotation2d angleD{135_deg};
|
||||
wpi::math::SwerveModuleVelocity refD{2_mps, 45_deg};
|
||||
refD.CosineScale(angleD);
|
||||
auto optimizedD = refD.CosineScale(angleD);
|
||||
|
||||
EXPECT_NEAR(refD.velocity.value(), 0.0, kEpsilon);
|
||||
EXPECT_NEAR(refD.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedD.velocity.value(), 0.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedD.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
|
||||
wpi::math::Rotation2d angleE{-135_deg};
|
||||
wpi::math::SwerveModuleVelocity refE{2_mps, 45_deg};
|
||||
refE.CosineScale(angleE);
|
||||
auto optimizedE = refE.CosineScale(angleE);
|
||||
|
||||
EXPECT_NEAR(refE.velocity.value(), -2.0, kEpsilon);
|
||||
EXPECT_NEAR(refE.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedE.velocity.value(), -2.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedE.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
|
||||
wpi::math::Rotation2d angleF{180_deg};
|
||||
wpi::math::SwerveModuleVelocity refF{2_mps, 45_deg};
|
||||
refF.CosineScale(angleF);
|
||||
auto optimizedF = refF.CosineScale(angleF);
|
||||
|
||||
EXPECT_NEAR(refF.velocity.value(), -std::sqrt(2.0), kEpsilon);
|
||||
EXPECT_NEAR(refF.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedF.velocity.value(), -std::sqrt(2.0), kEpsilon);
|
||||
EXPECT_NEAR(optimizedF.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
|
||||
wpi::math::Rotation2d angleG{0_deg};
|
||||
wpi::math::SwerveModuleVelocity refG{-2_mps, 45_deg};
|
||||
refG.CosineScale(angleG);
|
||||
auto optimizedG = refG.CosineScale(angleG);
|
||||
|
||||
EXPECT_NEAR(refG.velocity.value(), -std::sqrt(2.0), kEpsilon);
|
||||
EXPECT_NEAR(refG.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedG.velocity.value(), -std::sqrt(2.0), kEpsilon);
|
||||
EXPECT_NEAR(optimizedG.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
|
||||
wpi::math::Rotation2d angleH{45_deg};
|
||||
wpi::math::SwerveModuleVelocity refH{-2_mps, 45_deg};
|
||||
refH.CosineScale(angleH);
|
||||
auto optimizedH = refH.CosineScale(angleH);
|
||||
|
||||
EXPECT_NEAR(refH.velocity.value(), -2.0, kEpsilon);
|
||||
EXPECT_NEAR(refH.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedH.velocity.value(), -2.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedH.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
|
||||
wpi::math::Rotation2d angleI{-45_deg};
|
||||
wpi::math::SwerveModuleVelocity refI{-2_mps, 45_deg};
|
||||
refI.CosineScale(angleI);
|
||||
auto optimizedI = refI.CosineScale(angleI);
|
||||
|
||||
EXPECT_NEAR(refI.velocity.value(), 0.0, kEpsilon);
|
||||
EXPECT_NEAR(refI.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedI.velocity.value(), 0.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedI.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
|
||||
wpi::math::Rotation2d angleJ{135_deg};
|
||||
wpi::math::SwerveModuleVelocity refJ{-2_mps, 45_deg};
|
||||
refJ.CosineScale(angleJ);
|
||||
auto optimizedJ = refJ.CosineScale(angleJ);
|
||||
|
||||
EXPECT_NEAR(refJ.velocity.value(), 0.0, kEpsilon);
|
||||
EXPECT_NEAR(refJ.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedJ.velocity.value(), 0.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedJ.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
|
||||
wpi::math::Rotation2d angleK{-135_deg};
|
||||
wpi::math::SwerveModuleVelocity refK{-2_mps, 45_deg};
|
||||
refK.CosineScale(angleK);
|
||||
auto optimizedK = refK.CosineScale(angleK);
|
||||
|
||||
EXPECT_NEAR(refK.velocity.value(), 2.0, kEpsilon);
|
||||
EXPECT_NEAR(refK.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedK.velocity.value(), 2.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedK.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
|
||||
wpi::math::Rotation2d angleL{180_deg};
|
||||
wpi::math::SwerveModuleVelocity refL{-2_mps, 45_deg};
|
||||
refL.CosineScale(angleL);
|
||||
auto optimizedL = refL.CosineScale(angleL);
|
||||
|
||||
EXPECT_NEAR(refL.velocity.value(), std::sqrt(2.0), kEpsilon);
|
||||
EXPECT_NEAR(refL.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
EXPECT_NEAR(optimizedL.velocity.value(), std::sqrt(2.0), kEpsilon);
|
||||
EXPECT_NEAR(optimizedL.angle.Degrees().value(), 45.0, kEpsilon);
|
||||
}
|
||||
|
||||
TEST(SwerveModuleVelocityTest, Equality) {
|
||||
|
||||
Reference in New Issue
Block a user