From 8e2465f8a0c23386ab76846e4a217234c51d1a10 Mon Sep 17 00:00:00 2001 From: Gold856 <117957790+Gold856@users.noreply.github.com> Date: Thu, 31 Aug 2023 14:57:24 -0400 Subject: [PATCH] [wpimath] Add arithmetic functions to wheel speeds classes (#5465) --- .../first/math/kinematics/ChassisSpeeds.java | 6 +- .../DifferentialDriveWheelSpeeds.java | 71 ++++++++++++++++ .../kinematics/MecanumDriveWheelSpeeds.java | 83 +++++++++++++++++++ .../include/frc/kinematics/ChassisSpeeds.h | 8 +- .../kinematics/DifferentialDriveWheelSpeeds.h | 74 +++++++++++++++++ .../frc/kinematics/MecanumDriveWheelSpeeds.h | 72 ++++++++++++++++ .../DifferentialDriveWheelSpeedsTest.java | 63 ++++++++++++++ .../MecanumDriveWheelSpeedsTest.java | 73 ++++++++++++++++ .../DifferentialDriveWheelSpeedsTest.cpp | 54 ++++++++++++ .../MecanumDriveWheelSpeedsTest.cpp | 64 ++++++++++++++ 10 files changed, 561 insertions(+), 7 deletions(-) create mode 100644 wpimath/src/test/java/edu/wpi/first/math/kinematics/DifferentialDriveWheelSpeedsTest.java create mode 100644 wpimath/src/test/java/edu/wpi/first/math/kinematics/MecanumDriveWheelSpeedsTest.java create mode 100644 wpimath/src/test/native/cpp/kinematics/DifferentialDriveWheelSpeedsTest.cpp create mode 100644 wpimath/src/test/native/cpp/kinematics/MecanumDriveWheelSpeedsTest.cpp diff --git a/wpimath/src/main/java/edu/wpi/first/math/kinematics/ChassisSpeeds.java b/wpimath/src/main/java/edu/wpi/first/math/kinematics/ChassisSpeeds.java index c0370cea0b5..2c6bde27f6a 100644 --- a/wpimath/src/main/java/edu/wpi/first/math/kinematics/ChassisSpeeds.java +++ b/wpimath/src/main/java/edu/wpi/first/math/kinematics/ChassisSpeeds.java @@ -154,7 +154,7 @@ public ChassisSpeeds plus(ChassisSpeeds other) { } /** - * Subtracts the other ChassisSpeeds from the other ChassisSpeeds and returns the difference. + * Subtracts the other ChassisSpeeds from the current ChassisSpeeds and returns the difference. * *
For example, ChassisSpeeds{5.0, 4.0, 2.0} - ChassisSpeeds{1.0, 2.0, 1.0} = * ChassisSpeeds{4.0, 2.0, 1.0} @@ -197,8 +197,8 @@ public ChassisSpeeds times(double scalar) { * *
For example, ChassisSpeeds{2.0, 2.5, 1.0} / 2 = ChassisSpeeds{1.0, 1.25, 0.5} * - * @param scalar The scalar to multiply by. - * @return The reference to the new mutated object. + * @param scalar The scalar to divide by. + * @return The scaled ChassisSpeeds. */ public ChassisSpeeds div(double scalar) { return new ChassisSpeeds( diff --git a/wpimath/src/main/java/edu/wpi/first/math/kinematics/DifferentialDriveWheelSpeeds.java b/wpimath/src/main/java/edu/wpi/first/math/kinematics/DifferentialDriveWheelSpeeds.java index d4b235ea9c3..ec874b65f33 100644 --- a/wpimath/src/main/java/edu/wpi/first/math/kinematics/DifferentialDriveWheelSpeeds.java +++ b/wpimath/src/main/java/edu/wpi/first/math/kinematics/DifferentialDriveWheelSpeeds.java @@ -46,6 +46,77 @@ public void desaturate(double attainableMaxSpeedMetersPerSecond) { } } + /** + * Adds two DifferentialDriveWheelSpeeds and returns the sum. + * + *
For example, DifferentialDriveWheelSpeeds{1.0, 0.5} + DifferentialDriveWheelSpeeds{2.0, 1.5} + * = DifferentialDriveWheelSpeeds{3.0, 2.0} + * + * @param other The DifferentialDriveWheelSpeeds to add. + * @return The sum of the DifferentialDriveWheelSpeeds. + */ + public DifferentialDriveWheelSpeeds plus(DifferentialDriveWheelSpeeds other) { + return new DifferentialDriveWheelSpeeds( + leftMetersPerSecond + other.leftMetersPerSecond, + rightMetersPerSecond + other.rightMetersPerSecond); + } + + /** + * Subtracts the other DifferentialDriveWheelSpeeds from the current DifferentialDriveWheelSpeeds + * and returns the difference. + * + *
For example, DifferentialDriveWheelSpeeds{5.0, 4.0} - DifferentialDriveWheelSpeeds{1.0, 2.0} + * = DifferentialDriveWheelSpeeds{4.0, 2.0} + * + * @param other The DifferentialDriveWheelSpeeds to subtract. + * @return The difference between the two DifferentialDriveWheelSpeeds. + */ + public DifferentialDriveWheelSpeeds minus(DifferentialDriveWheelSpeeds other) { + return new DifferentialDriveWheelSpeeds( + leftMetersPerSecond - other.leftMetersPerSecond, + rightMetersPerSecond - other.rightMetersPerSecond); + } + + /** + * Returns the inverse of the current DifferentialDriveWheelSpeeds. This is equivalent to negating + * all components of the DifferentialDriveWheelSpeeds. + * + * @return The inverse of the current DifferentialDriveWheelSpeeds. + */ + public DifferentialDriveWheelSpeeds unaryMinus() { + return new DifferentialDriveWheelSpeeds(-leftMetersPerSecond, -rightMetersPerSecond); + } + + /** + * Multiplies the DifferentialDriveWheelSpeeds by a scalar and returns the new + * DifferentialDriveWheelSpeeds. + * + *
For example, DifferentialDriveWheelSpeeds{2.0, 2.5} * 2 = DifferentialDriveWheelSpeeds{4.0, + * 5.0} + * + * @param scalar The scalar to multiply by. + * @return The scaled DifferentialDriveWheelSpeeds. + */ + public DifferentialDriveWheelSpeeds times(double scalar) { + return new DifferentialDriveWheelSpeeds( + leftMetersPerSecond * scalar, rightMetersPerSecond * scalar); + } + + /** + * Divides the DifferentialDriveWheelSpeeds by a scalar and returns the new + * DifferentialDriveWheelSpeeds. + * + *
For example, DifferentialDriveWheelSpeeds{2.0, 2.5} / 2 = DifferentialDriveWheelSpeeds{1.0, + * 1.25} + * + * @param scalar The scalar to divide by. + * @return The scaled DifferentialDriveWheelSpeeds. + */ + public DifferentialDriveWheelSpeeds div(double scalar) { + return new DifferentialDriveWheelSpeeds( + leftMetersPerSecond / scalar, rightMetersPerSecond / scalar); + } + @Override public String toString() { return String.format( diff --git a/wpimath/src/main/java/edu/wpi/first/math/kinematics/MecanumDriveWheelSpeeds.java b/wpimath/src/main/java/edu/wpi/first/math/kinematics/MecanumDriveWheelSpeeds.java index 1dcfc8551cd..63cef1838f0 100644 --- a/wpimath/src/main/java/edu/wpi/first/math/kinematics/MecanumDriveWheelSpeeds.java +++ b/wpimath/src/main/java/edu/wpi/first/math/kinematics/MecanumDriveWheelSpeeds.java @@ -73,6 +73,89 @@ public void desaturate(double attainableMaxSpeedMetersPerSecond) { } } + /** + * Adds two MecanumDriveWheelSpeeds and returns the sum. + * + *
For example, MecanumDriveWheelSpeeds{1.0, 0.5, 2.0, 1.5} + MecanumDriveWheelSpeeds{2.0, 1.5, + * 0.5, 1.0} = MecanumDriveWheelSpeeds{3.0, 2.0, 2.5, 2.5} + * + * @param other The MecanumDriveWheelSpeeds to add. + * @return The sum of the MecanumDriveWheelSpeeds. + */ + public MecanumDriveWheelSpeeds plus(MecanumDriveWheelSpeeds other) { + return new MecanumDriveWheelSpeeds( + frontLeftMetersPerSecond + other.frontLeftMetersPerSecond, + frontRightMetersPerSecond + other.frontRightMetersPerSecond, + rearLeftMetersPerSecond + other.rearLeftMetersPerSecond, + rearRightMetersPerSecond + other.rearRightMetersPerSecond); + } + + /** + * Subtracts the other MecanumDriveWheelSpeeds from the current MecanumDriveWheelSpeeds and + * returns the difference. + * + *
For example, MecanumDriveWheelSpeeds{5.0, 4.0, 6.0, 2.5} - MecanumDriveWheelSpeeds{1.0, 2.0, + * 3.0, 0.5} = MecanumDriveWheelSpeeds{4.0, 2.0, 3.0, 2.0} + * + * @param other The MecanumDriveWheelSpeeds to subtract. + * @return The difference between the two MecanumDriveWheelSpeeds. + */ + public MecanumDriveWheelSpeeds minus(MecanumDriveWheelSpeeds other) { + return new MecanumDriveWheelSpeeds( + frontLeftMetersPerSecond - other.frontLeftMetersPerSecond, + frontRightMetersPerSecond - other.frontRightMetersPerSecond, + rearLeftMetersPerSecond - other.rearLeftMetersPerSecond, + rearRightMetersPerSecond - other.rearRightMetersPerSecond); + } + + /** + * Returns the inverse of the current MecanumDriveWheelSpeeds. This is equivalent to negating all + * components of the MecanumDriveWheelSpeeds. + * + * @return The inverse of the current MecanumDriveWheelSpeeds. + */ + public MecanumDriveWheelSpeeds unaryMinus() { + return new MecanumDriveWheelSpeeds( + -frontLeftMetersPerSecond, + -frontRightMetersPerSecond, + -rearLeftMetersPerSecond, + -rearRightMetersPerSecond); + } + + /** + * Multiplies the MecanumDriveWheelSpeeds by a scalar and returns the new MecanumDriveWheelSpeeds. + * + *
For example, MecanumDriveWheelSpeeds{2.0, 2.5, 3.0, 3.5} * 2 = MecanumDriveWheelSpeeds{4.0, + * 5.0, 6.0, 7.0} + * + * @param scalar The scalar to multiply by. + * @return The scaled MecanumDriveWheelSpeeds. + */ + public MecanumDriveWheelSpeeds times(double scalar) { + return new MecanumDriveWheelSpeeds( + frontLeftMetersPerSecond * scalar, + frontRightMetersPerSecond * scalar, + rearLeftMetersPerSecond * scalar, + rearRightMetersPerSecond * scalar); + } + + /** + * Divides the MecanumDriveWheelSpeeds by a scalar and returns the new MecanumDriveWheelSpeeds. + * + *
For example, MecanumDriveWheelSpeeds{2.0, 2.5, 1.5, 1.0} / 2 = MecanumDriveWheelSpeeds{1.0, + * 1.25, 0.75, 0.5} + * + * @param scalar The scalar to divide by. + * @return The scaled MecanumDriveWheelSpeeds. + */ + public MecanumDriveWheelSpeeds div(double scalar) { + return new MecanumDriveWheelSpeeds( + frontLeftMetersPerSecond / scalar, + frontRightMetersPerSecond / scalar, + rearLeftMetersPerSecond / scalar, + rearRightMetersPerSecond / scalar); + } + @Override public String toString() { return String.format( diff --git a/wpimath/src/main/native/include/frc/kinematics/ChassisSpeeds.h b/wpimath/src/main/native/include/frc/kinematics/ChassisSpeeds.h index b388d5cec85..8b65eb52af7 100644 --- a/wpimath/src/main/native/include/frc/kinematics/ChassisSpeeds.h +++ b/wpimath/src/main/native/include/frc/kinematics/ChassisSpeeds.h @@ -146,8 +146,8 @@ struct WPILIB_DLLEXPORT ChassisSpeeds { } /** - * Subtracts the other ChassisSpeeds from the other ChassisSpeeds and returns - * the difference. + * Subtracts the other ChassisSpeeds from the current ChassisSpeeds and + * returns the difference. * *
For example, ChassisSpeeds{5.0, 4.0, 2.0} - ChassisSpeeds{1.0, 2.0, 1.0} * = ChassisSpeeds{4.0, 2.0, 1.0} @@ -188,9 +188,9 @@ struct WPILIB_DLLEXPORT ChassisSpeeds { *
For example, ChassisSpeeds{2.0, 2.5, 1.0} / 2 * = ChassisSpeeds{1.0, 1.25, 0.5} * - * @param scalar The scalar to multiply by. + * @param scalar The scalar to divide by. * - * @return The reference to the new mutated object. + * @return The scaled ChassisSpeeds. */ constexpr ChassisSpeeds operator/(double scalar) const { return operator*(1.0 / scalar); diff --git a/wpimath/src/main/native/include/frc/kinematics/DifferentialDriveWheelSpeeds.h b/wpimath/src/main/native/include/frc/kinematics/DifferentialDriveWheelSpeeds.h index fce2b9688ad..9d9e705772d 100644 --- a/wpimath/src/main/native/include/frc/kinematics/DifferentialDriveWheelSpeeds.h +++ b/wpimath/src/main/native/include/frc/kinematics/DifferentialDriveWheelSpeeds.h @@ -36,5 +36,79 @@ struct WPILIB_DLLEXPORT DifferentialDriveWheelSpeeds { * @param attainableMaxSpeed The absolute max speed that a wheel can reach. */ void Desaturate(units::meters_per_second_t attainableMaxSpeed); + + /** + * Adds two DifferentialDriveWheelSpeeds and returns the sum. + * + *
For example, DifferentialDriveWheelSpeeds{1.0, 0.5} + + * DifferentialDriveWheelSpeeds{2.0, 1.5} = + * DifferentialDriveWheelSpeeds{3.0, 2.0} + * + * @param other The DifferentialDriveWheelSpeeds to add. + * + * @return The sum of the DifferentialDriveWheelSpeeds. + */ + constexpr DifferentialDriveWheelSpeeds operator+( + const DifferentialDriveWheelSpeeds& other) const { + return {left + other.left, right + other.right}; + } + + /** + * Subtracts the other DifferentialDriveWheelSpeeds from the current + * DifferentialDriveWheelSpeeds and returns the difference. + * + *
For example, DifferentialDriveWheelSpeeds{5.0, 4.0} - + * DifferentialDriveWheelSpeeds{1.0, 2.0} = + * DifferentialDriveWheelSpeeds{4.0, 2.0} + * + * @param other The DifferentialDriveWheelSpeeds to subtract. + * + * @return The difference between the two DifferentialDriveWheelSpeeds. + */ + constexpr DifferentialDriveWheelSpeeds operator-( + const DifferentialDriveWheelSpeeds& other) const { + return *this + -other; + } + + /** + * Returns the inverse of the current DifferentialDriveWheelSpeeds. + * This is equivalent to negating all components of the + * DifferentialDriveWheelSpeeds. + * + * @return The inverse of the current DifferentialDriveWheelSpeeds. + */ + constexpr DifferentialDriveWheelSpeeds operator-() const { + return {-left, -right}; + } + + /** + * Multiplies the DifferentialDriveWheelSpeeds by a scalar and returns the new + * DifferentialDriveWheelSpeeds. + * + *
For example, DifferentialDriveWheelSpeeds{2.0, 2.5} * 2 + * = DifferentialDriveWheelSpeeds{4.0, 5.0} + * + * @param scalar The scalar to multiply by. + * + * @return The scaled DifferentialDriveWheelSpeeds. + */ + constexpr DifferentialDriveWheelSpeeds operator*(double scalar) const { + return {scalar * left, scalar * right}; + } + + /** + * Divides the DifferentialDriveWheelSpeeds by a scalar and returns the new + * DifferentialDriveWheelSpeeds. + * + *
For example, DifferentialDriveWheelSpeeds{2.0, 2.5} / 2 + * = DifferentialDriveWheelSpeeds{1.0, 1.25} + * + * @param scalar The scalar to divide by. + * + * @return The scaled DifferentialDriveWheelSpeeds. + */ + constexpr DifferentialDriveWheelSpeeds operator/(double scalar) const { + return operator*(1.0 / scalar); + } }; } // namespace frc diff --git a/wpimath/src/main/native/include/frc/kinematics/MecanumDriveWheelSpeeds.h b/wpimath/src/main/native/include/frc/kinematics/MecanumDriveWheelSpeeds.h index e698c5f110d..80e84607ed7 100644 --- a/wpimath/src/main/native/include/frc/kinematics/MecanumDriveWheelSpeeds.h +++ b/wpimath/src/main/native/include/frc/kinematics/MecanumDriveWheelSpeeds.h @@ -46,5 +46,77 @@ struct WPILIB_DLLEXPORT MecanumDriveWheelSpeeds { * @param attainableMaxSpeed The absolute max speed that a wheel can reach. */ void Desaturate(units::meters_per_second_t attainableMaxSpeed); + + /** + * Adds two MecanumDriveWheelSpeeds and returns the sum. + * + *
For example, MecanumDriveWheelSpeeds{1.0, 0.5, 2.0, 1.5} + + * MecanumDriveWheelSpeeds{2.0, 1.5, 0.5, 1.0} = + * MecanumDriveWheelSpeeds{3.0, 2.0, 2.5, 2.5} + * + * @param other The MecanumDriveWheelSpeeds to add. + * @return The sum of the MecanumDriveWheelSpeeds. + */ + constexpr MecanumDriveWheelSpeeds operator+( + const MecanumDriveWheelSpeeds& other) const { + return {frontLeft + other.frontLeft, frontRight + other.frontRight, + rearLeft + other.rearLeft, rearRight + other.rearRight}; + } + + /** + * Subtracts the other MecanumDriveWheelSpeeds from the current + * MecanumDriveWheelSpeeds and returns the difference. + * + *
For example, MecanumDriveWheelSpeeds{5.0, 4.0, 6.0, 2.5} - + * MecanumDriveWheelSpeeds{1.0, 2.0, 3.0, 0.5} = + * MecanumDriveWheelSpeeds{4.0, 2.0, 3.0, 2.0} + * + * @param other The MecanumDriveWheelSpeeds to subtract. + * @return The difference between the two MecanumDriveWheelSpeeds. + */ + constexpr MecanumDriveWheelSpeeds operator-( + const MecanumDriveWheelSpeeds& other) const { + return *this + -other; + } + + /** + * Returns the inverse of the current MecanumDriveWheelSpeeds. + * This is equivalent to negating all components of the + * MecanumDriveWheelSpeeds. + * + * @return The inverse of the current MecanumDriveWheelSpeeds. + */ + constexpr MecanumDriveWheelSpeeds operator-() const { + return {-frontLeft, -frontRight, -rearLeft, -rearRight}; + } + + /** + * Multiplies the MecanumDriveWheelSpeeds by a scalar and returns the new + * MecanumDriveWheelSpeeds. + * + *
For example, MecanumDriveWheelSpeeds{2.0, 2.5, 3.0, 3.5} * 2 = + * MecanumDriveWheelSpeeds{4.0, 5.0, 6.0, 7.0} + * + * @param scalar The scalar to multiply by. + * @return The scaled MecanumDriveWheelSpeeds. + */ + constexpr MecanumDriveWheelSpeeds operator*(double scalar) const { + return {scalar * frontLeft, scalar * frontRight, scalar * rearLeft, + scalar * rearRight}; + } + + /** + * Divides the MecanumDriveWheelSpeeds by a scalar and returns the new + * MecanumDriveWheelSpeeds. + * + *
For example, MecanumDriveWheelSpeeds{2.0, 2.5, 1.5, 1.0} / 2 =
+ * MecanumDriveWheelSpeeds{1.0, 1.25, 0.75, 0.5}
+ *
+ * @param scalar The scalar to divide by.
+ * @return The scaled MecanumDriveWheelSpeeds.
+ */
+ constexpr MecanumDriveWheelSpeeds operator/(double scalar) const {
+ return operator*(1.0 / scalar);
+ }
};
} // namespace frc
diff --git a/wpimath/src/test/java/edu/wpi/first/math/kinematics/DifferentialDriveWheelSpeedsTest.java b/wpimath/src/test/java/edu/wpi/first/math/kinematics/DifferentialDriveWheelSpeedsTest.java
new file mode 100644
index 00000000000..7f2618012df
--- /dev/null
+++ b/wpimath/src/test/java/edu/wpi/first/math/kinematics/DifferentialDriveWheelSpeedsTest.java
@@ -0,0 +1,63 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+package edu.wpi.first.math.kinematics;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+class DifferentialDriveWheelSpeedsTest {
+ @Test
+ void testPlus() {
+ final var left = new DifferentialDriveWheelSpeeds(1.0, 0.5);
+ final var right = new DifferentialDriveWheelSpeeds(2.0, 1.5);
+
+ final var wheelSpeeds = left.plus(right);
+
+ assertAll(
+ () -> assertEquals(3.0, wheelSpeeds.leftMetersPerSecond),
+ () -> assertEquals(2.0, wheelSpeeds.rightMetersPerSecond));
+ }
+
+ @Test
+ void testMinus() {
+ final var left = new DifferentialDriveWheelSpeeds(1.0, 0.5);
+ final var right = new DifferentialDriveWheelSpeeds(2.0, 0.5);
+
+ final var wheelSpeeds = left.minus(right);
+
+ assertAll(
+ () -> assertEquals(-1.0, wheelSpeeds.leftMetersPerSecond),
+ () -> assertEquals(0.0, wheelSpeeds.rightMetersPerSecond));
+ }
+
+ @Test
+ void testUnaryMinus() {
+ final var wheelSpeeds = new DifferentialDriveWheelSpeeds(1.0, 0.5).unaryMinus();
+
+ assertAll(
+ () -> assertEquals(-1.0, wheelSpeeds.leftMetersPerSecond),
+ () -> assertEquals(-0.5, wheelSpeeds.rightMetersPerSecond));
+ }
+
+ @Test
+ void testMultiplication() {
+ final var wheelSpeeds = new DifferentialDriveWheelSpeeds(1.0, 0.5).times(2.0);
+
+ assertAll(
+ () -> assertEquals(2.0, wheelSpeeds.leftMetersPerSecond),
+ () -> assertEquals(1.0, wheelSpeeds.rightMetersPerSecond));
+ }
+
+ @Test
+ void testDivision() {
+ final var wheelSpeeds = new DifferentialDriveWheelSpeeds(1.0, 0.5).div(2.0);
+
+ assertAll(
+ () -> assertEquals(0.5, wheelSpeeds.leftMetersPerSecond),
+ () -> assertEquals(0.25, wheelSpeeds.rightMetersPerSecond));
+ }
+}
diff --git a/wpimath/src/test/java/edu/wpi/first/math/kinematics/MecanumDriveWheelSpeedsTest.java b/wpimath/src/test/java/edu/wpi/first/math/kinematics/MecanumDriveWheelSpeedsTest.java
new file mode 100644
index 00000000000..22efb44332f
--- /dev/null
+++ b/wpimath/src/test/java/edu/wpi/first/math/kinematics/MecanumDriveWheelSpeedsTest.java
@@ -0,0 +1,73 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+package edu.wpi.first.math.kinematics;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+class MecanumDriveWheelSpeedsTest {
+ @Test
+ void testPlus() {
+ final var left = new MecanumDriveWheelSpeeds(1.0, 0.5, 2.0, 1.5);
+ final var right = new MecanumDriveWheelSpeeds(2.0, 1.5, 0.5, 1.0);
+
+ final var wheelSpeeds = left.plus(right);
+
+ assertAll(
+ () -> assertEquals(3.0, wheelSpeeds.frontLeftMetersPerSecond),
+ () -> assertEquals(2.0, wheelSpeeds.frontRightMetersPerSecond),
+ () -> assertEquals(2.5, wheelSpeeds.rearLeftMetersPerSecond),
+ () -> assertEquals(2.5, wheelSpeeds.rearRightMetersPerSecond));
+ }
+
+ @Test
+ void testMinus() {
+ final var left = new MecanumDriveWheelSpeeds(1.0, 0.5, 2.0, 1.5);
+ final var right = new MecanumDriveWheelSpeeds(2.0, 0.5, 0.5, 1.0);
+
+ final var wheelSpeeds = left.minus(right);
+
+ assertAll(
+ () -> assertEquals(-1.0, wheelSpeeds.frontLeftMetersPerSecond),
+ () -> assertEquals(0.0, wheelSpeeds.frontRightMetersPerSecond),
+ () -> assertEquals(1.5, wheelSpeeds.rearLeftMetersPerSecond),
+ () -> assertEquals(0.5, wheelSpeeds.rearRightMetersPerSecond));
+ }
+
+ @Test
+ void testUnaryMinus() {
+ final var wheelSpeeds = new MecanumDriveWheelSpeeds(1.0, 0.5, 2.0, 1.5).unaryMinus();
+
+ assertAll(
+ () -> assertEquals(-1.0, wheelSpeeds.frontLeftMetersPerSecond),
+ () -> assertEquals(-0.5, wheelSpeeds.frontRightMetersPerSecond),
+ () -> assertEquals(-2.0, wheelSpeeds.rearLeftMetersPerSecond),
+ () -> assertEquals(-1.5, wheelSpeeds.rearRightMetersPerSecond));
+ }
+
+ @Test
+ void testMultiplication() {
+ final var wheelSpeeds = new MecanumDriveWheelSpeeds(1.0, 0.5, 2.0, 1.5).times(2.0);
+
+ assertAll(
+ () -> assertEquals(2.0, wheelSpeeds.frontLeftMetersPerSecond),
+ () -> assertEquals(1.0, wheelSpeeds.frontRightMetersPerSecond),
+ () -> assertEquals(4.0, wheelSpeeds.rearLeftMetersPerSecond),
+ () -> assertEquals(3.0, wheelSpeeds.rearRightMetersPerSecond));
+ }
+
+ @Test
+ void testDivision() {
+ final var wheelSpeeds = new MecanumDriveWheelSpeeds(1.0, 0.5, 2.0, 1.5).div(2.0);
+
+ assertAll(
+ () -> assertEquals(0.5, wheelSpeeds.frontLeftMetersPerSecond),
+ () -> assertEquals(0.25, wheelSpeeds.frontRightMetersPerSecond),
+ () -> assertEquals(1.0, wheelSpeeds.rearLeftMetersPerSecond),
+ () -> assertEquals(0.75, wheelSpeeds.rearRightMetersPerSecond));
+ }
+}
diff --git a/wpimath/src/test/native/cpp/kinematics/DifferentialDriveWheelSpeedsTest.cpp b/wpimath/src/test/native/cpp/kinematics/DifferentialDriveWheelSpeedsTest.cpp
new file mode 100644
index 00000000000..92cc583644c
--- /dev/null
+++ b/wpimath/src/test/native/cpp/kinematics/DifferentialDriveWheelSpeedsTest.cpp
@@ -0,0 +1,54 @@
+// Copyright (c) FIRST and other WPILib contributors.
+// Open Source Software; you can modify and/or share it under the terms of
+// the WPILib BSD license file in the root directory of this project.
+
+#include