51template <
size_t NumModules>
53 :
public Kinematics<wpi::array<SwerveModuleState, NumModules>,
54 wpi::array<SwerveModulePosition, NumModules>> {
67 template <std::convertible_to<Translation2d>... ModuleTranslations>
68 requires(
sizeof...(ModuleTranslations) == NumModules)
71 for (
size_t i = 0; i < NumModules; i++) {
73 m_inverseKinematics.template block<2, 3>(i * 2, 0) <<
74 1, 0, (-m_modules[i].Y()).value(),
75 0, 1, (+m_modules[i].X()).value();
79 m_forwardKinematics = m_inverseKinematics.householderQr();
87 : m_modules{modules}, m_moduleHeadings(
wpi::empty_array) {
88 for (
size_t i = 0; i < NumModules; i++) {
90 m_inverseKinematics.template block<2, 3>(i * 2, 0) <<
91 1, 0, (-m_modules[i].Y()).value(),
92 0, 1, (+m_modules[i].X()).value();
96 m_forwardKinematics = m_inverseKinematics.householderQr();
109 template <std::convertible_to<Rotation2d>... ModuleHeadings>
110 requires(
sizeof...(ModuleHeadings) == NumModules)
122 for (
size_t i = 0; i < NumModules; i++) {
123 m_moduleHeadings[i] = moduleHeadings[i];
163 if (chassisSpeeds.
vx == 0_mps && chassisSpeeds.
vy == 0_mps &&
164 chassisSpeeds.
omega == 0_rad_per_s) {
165 for (
size_t i = 0; i < NumModules; i++) {
166 moduleStates[i] = {0_mps, m_moduleHeadings[i]};
173 if (centerOfRotation != m_previousCoR) {
174 for (
size_t i = 0; i < NumModules; i++) {
176 m_inverseKinematics.template block<2, 3>(i * 2, 0) =
178 {1, 0, (-m_modules[i].Y() + centerOfRotation.Y()).value()},
179 {0, 1, (+m_modules[i].X() - centerOfRotation.X()).value()}};
182 m_previousCoR = centerOfRotation;
185 Eigen::Vector3d chassisSpeedsVector{chassisSpeeds.
vx.value(),
186 chassisSpeeds.
vy.value(),
187 chassisSpeeds.
omega.value()};
190 m_inverseKinematics * chassisSpeedsVector;
192 for (
size_t i = 0; i < NumModules; i++) {
193 units::meters_per_second_t x{moduleStateMatrix(i * 2, 0)};
194 units::meters_per_second_t y{moduleStateMatrix(i * 2 + 1, 0)};
197 auto rotation = speed > 1e-6_mps ? Rotation2d{x.value(), y.value()}
198 : m_moduleHeadings[i];
200 moduleStates[i] = {speed, rotation};
201 m_moduleHeadings[i] = rotation;
224 template <std::convertible_to<SwerveModuleState>... ModuleStates>
225 requires(
sizeof...(ModuleStates) == NumModules)
245 moduleStates)
const override {
248 for (
size_t i = 0; i < NumModules; ++i) {
250 moduleStateMatrix(i * 2, 0) =
module.speed.value() * module.angle.Cos();
251 moduleStateMatrix(i * 2 + 1, 0) =
252 module.speed.value() * module.angle.Sin();
255 Eigen::Vector3d chassisSpeedsVector =
256 m_forwardKinematics.solve(moduleStateMatrix);
258 return {units::meters_per_second_t{chassisSpeedsVector(0)},
259 units::meters_per_second_t{chassisSpeedsVector(1)},
260 units::radians_per_second_t{chassisSpeedsVector(2)}};
276 template <std::convertible_to<SwerveModulePosition>... ModuleDeltas>
277 requires(
sizeof...(ModuleDeltas) == NumModules)
300 for (
size_t i = 0; i < NumModules; ++i) {
302 moduleDeltaMatrix(i * 2, 0) =
303 module.distance.value() * module.angle.Cos();
304 moduleDeltaMatrix(i * 2 + 1, 0) =
305 module.distance.value() * module.angle.Sin();
308 Eigen::Vector3d chassisDeltaVector =
309 m_forwardKinematics.solve(moduleDeltaMatrix);
311 return {units::meter_t{chassisDeltaVector(0)},
312 units::meter_t{chassisDeltaVector(1)},
313 units::radian_t{chassisDeltaVector(2)}};
321 for (
size_t i = 0; i < NumModules; i++) {
322 result[i] = {end[i].distance - start[i].distance, end[i].angle};
344 units::meters_per_second_t attainableMaxSpeed) {
345 auto& states = *moduleStates;
348 [](
const auto& a,
const auto& b) {
349 return units::math::abs(a.speed) <
350 units::math::abs(b.speed);
354 if (realMaxSpeed > attainableMaxSpeed) {
355 for (
auto& module : states) {
356 module.speed = module.speed / realMaxSpeed * attainableMaxSpeed;
385 units::meters_per_second_t attainableMaxModuleSpeed,
386 units::meters_per_second_t attainableMaxRobotTranslationSpeed,
387 units::radians_per_second_t attainableMaxRobotRotationSpeed) {
388 auto& states = *moduleStates;
392 [](
const auto& a,
const auto& b) {
393 return units::math::abs(a.speed) <
394 units::math::abs(b.speed);
398 if (attainableMaxRobotTranslationSpeed == 0_mps ||
399 attainableMaxRobotRotationSpeed == 0_rad_per_s ||
400 realMaxSpeed == 0_mps) {
404 auto translationalK =
406 attainableMaxRobotTranslationSpeed;
409 attainableMaxRobotRotationSpeed;
415 for (
auto& module : states) {
416 module.speed = module.speed * scale;
423 double t)
const override {
426 for (
size_t i = 0; i < NumModules; ++i) {
427 result[i] = start[i].Interpolate(end[i], t);
439 Eigen::HouseholderQR<Matrixd<NumModules * 2, 3>> m_forwardKinematics;
445template <
typename ModuleTranslation,
typename... ModuleTranslations>
#define WPILIB_DLLEXPORT
Definition SymbolExports.h:36
#define EXPORT_TEMPLATE_DECLARE(export)
Definition SymbolExports.hpp:92
Helper class that converts a chassis velocity (dx, dy, and dtheta components) into individual wheel s...
Definition Kinematics.h:25
Helper class that converts a chassis velocity (dx, dy, and dtheta components) into individual module ...
Definition SwerveDriveKinematics.h:54
wpi::array< SwerveModuleState, NumModules > ToSwerveModuleStates(const ChassisSpeeds &chassisSpeeds, const Translation2d ¢erOfRotation=Translation2d{}) const
Performs inverse kinematics to return the module states from a desired chassis velocity.
Definition SwerveDriveKinematics.h:158
wpi::array< SwerveModulePosition, NumModules > Interpolate(const wpi::array< SwerveModulePosition, NumModules > &start, const wpi::array< SwerveModulePosition, NumModules > &end, double t) const override
Performs interpolation between two values.
Definition SwerveDriveKinematics.h:420
const wpi::array< Translation2d, NumModules > & GetModules() const
Definition SwerveDriveKinematics.h:432
SwerveDriveKinematics(const SwerveDriveKinematics &)=default
void ResetHeadings(ModuleHeadings &&... moduleHeadings)
Reset the internal swerve module headings.
Definition SwerveDriveKinematics.h:111
void ResetHeadings(wpi::array< Rotation2d, NumModules > moduleHeadings)
Reset the internal swerve module headings.
Definition SwerveDriveKinematics.h:121
ChassisSpeeds ToChassisSpeeds(const wpi::array< SwerveModuleState, NumModules > &moduleStates) const override
Performs forward kinematics to return the resulting chassis state from the given module states.
Definition SwerveDriveKinematics.h:244
static void DesaturateWheelSpeeds(wpi::array< SwerveModuleState, NumModules > *moduleStates, units::meters_per_second_t attainableMaxSpeed)
Renormalizes the wheel speeds if any individual speed is above the specified maximum.
Definition SwerveDriveKinematics.h:342
SwerveDriveKinematics(ModuleTranslations &&... moduleTranslations)
Constructs a swerve drive kinematics object.
Definition SwerveDriveKinematics.h:69
Twist2d ToTwist2d(ModuleDeltas &&... moduleDeltas) const
Performs forward kinematics to return the resulting Twist2d from the given module position deltas.
Definition SwerveDriveKinematics.h:278
SwerveDriveKinematics(const wpi::array< Translation2d, NumModules > &modules)
Definition SwerveDriveKinematics.h:85
wpi::array< SwerveModuleState, NumModules > ToWheelSpeeds(const ChassisSpeeds &chassisSpeeds) const override
Performs inverse kinematics to return the wheel speeds from a desired chassis velocity.
Definition SwerveDriveKinematics.h:207
static void DesaturateWheelSpeeds(wpi::array< SwerveModuleState, NumModules > *moduleStates, ChassisSpeeds desiredChassisSpeed, units::meters_per_second_t attainableMaxModuleSpeed, units::meters_per_second_t attainableMaxRobotTranslationSpeed, units::radians_per_second_t attainableMaxRobotRotationSpeed)
Renormalizes the wheel speeds if any individual speed is above the specified maximum,...
Definition SwerveDriveKinematics.h:382
ChassisSpeeds ToChassisSpeeds(ModuleStates &&... moduleStates) const
Performs forward kinematics to return the resulting chassis state from the given module states.
Definition SwerveDriveKinematics.h:226
Twist2d ToTwist2d(wpi::array< SwerveModulePosition, NumModules > moduleDeltas) const
Performs forward kinematics to return the resulting Twist2d from the given module position deltas.
Definition SwerveDriveKinematics.h:296
Twist2d ToTwist2d(const wpi::array< SwerveModulePosition, NumModules > &start, const wpi::array< SwerveModulePosition, NumModules > &end) const override
Performs forward kinematics to return the resulting Twist2d from the given change in wheel positions.
Definition SwerveDriveKinematics.h:316
Represents a translation in 2D space.
Definition Translation2d.h:29
Container for values which represent quantities of a given unit.
Definition base.h:1930
This class is a wrapper around std::array that does compile time size checking.
Definition array.h:26
static void ReportUsage(MathUsageId id, int count)
Definition MathShared.h:75
constexpr UnitType abs(const UnitType x) noexcept
Compute absolute value.
Definition math.h:726
constexpr UnitTypeLhs hypot(const UnitTypeLhs &x, const UnitTypeRhs &y)
Computes the square root of the sum-of-squares of x and y.
Definition math.h:508
Eigen::Matrix< double, Rows, Cols, Options, MaxRows, MaxCols > Matrixd
Definition EigenCore.h:21
SwerveDriveKinematics(ModuleTranslation, ModuleTranslations...) -> SwerveDriveKinematics< 1+sizeof...(ModuleTranslations)>
constexpr UnitTypeLhs max(const UnitTypeLhs &lhs, const UnitTypeRhs &rhs)
Definition base.h:3422
constexpr UnitTypeLhs min(const UnitTypeLhs &lhs, const UnitTypeRhs &rhs)
Definition base.h:3414
@ kKinematics_SwerveDrive
Foonathan namespace.
Definition ntcore_cpp.h:26
constexpr empty_array_t empty_array
Definition array.h:16
Represents the speed of a robot chassis.
Definition ChassisSpeeds.h:25
units::meters_per_second_t vx
Velocity along the x-axis.
Definition ChassisSpeeds.h:29
units::meters_per_second_t vy
Velocity along the y-axis.
Definition ChassisSpeeds.h:34
units::radians_per_second_t omega
Represents the angular velocity of the robot frame.
Definition ChassisSpeeds.h:39
Represents the position of one swerve module.
Definition SwerveModulePosition.h:18
Represents the state of one swerve module.
Definition SwerveModuleState.h:18
A change in distance along a 2D arc since the last pose update.
Definition Twist2d.h:22