CTRE Phoenix 6 C++ 26.50.0-alpha-1
Loading...
Searching...
No Matches
SwerveDriveKinematics.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) Cross The Road Electronics.  All rights reserved.
3 * License information can be found in CTRE_LICENSE.txt
4 * For support and suggestions contact support@ctr-electronics.com or file
5 * an issue tracker at https://github.com/CrossTheRoadElec/Phoenix-Releases
6 */
7#pragma once
8
10#include <memory>
11#include <span>
12#include <vector>
13
14namespace ctre {
15namespace phoenix6 {
16namespace swerve {
17namespace impl {
18
19/**
20 * \brief Class that converts a chassis velocity (dx, dy, and dtheta components)
21 * into individual module states (velocity and angle).
22 *
23 * The inverse kinematics (converting from a desired chassis velocity to
24 * individual module states) uses the relative locations of the modules with
25 * respect to the center of rotation. The center of rotation for inverse
26 * kinematics is also variable. This means that you can set your set your center
27 * of rotation in a corner of the robot to perform special evasion maneuvers.
28 *
29 * Forward kinematics (converting an array of module states into the overall
30 * chassis motion) is performs the exact opposite of what inverse kinematics
31 * does. Since this is an overdetermined system (more equations than variables),
32 * we use a least-squares approximation.
33 *
34 * The inverse kinematics: [moduleVelocities] = [moduleLocations] * [chassisVelocities]
35 * We take the Moore-Penrose pseudoinverse of [moduleLocations] and then
36 * multiply by [moduleVelocities] to get our chassis velocities.
37 *
38 * Forward kinematics is also used for odometry -- determining the position of
39 * the robot on the field using encoders and a gyro.
40 */
42 std::vector<Translation2d> m_modules;
43
44 struct KinematicsMatrices;
45 std::unique_ptr<KinematicsMatrices> m_matrices;
46
47 mutable std::vector<Rotation2d> m_moduleHeadings;
48 mutable Translation2d m_previousCoR{};
49
50public:
51 using WheelPositions = std::vector<SwerveModulePosition>;
52 using WheelVelocities = std::vector<SwerveModuleVelocity>;
53 using WheelAccelerations = std::vector<SwerveModuleAcceleration>;
54
55 /**
56 * \brief Constructs a swerve drive kinematics object. This takes in a variable
57 * number of module locations as Translation2ds. The order in which you pass
58 * in the module locations is the same order that you will receive the module
59 * states when performing inverse kinematics. It is also expected that you
60 * pass in the module states in the same order when calling the forward
61 * kinematics methods.
62 *
63 * \param moduleLocations The locations of the modules relative to the
64 * physical center of the robot.
65 */
66 SwerveDriveKinematics(std::vector<Translation2d> moduleLocations);
67
71
74
75 /**
76 * \brief Reset the internal swerve module headings.
77 *
78 * \param moduleHeadings The swerve module headings. The order of the module
79 * headings should be same as passed into the constructor of this class.
80 */
81 void ResetHeadings(std::span<Rotation2d const> moduleHeadings)
82 {
83 for (size_t i = 0; i < m_modules.size() && i < moduleHeadings.size(); ++i) {
84 m_moduleHeadings[i] = moduleHeadings[i];
85 }
86 }
87
88 /**
89 * \brief Performs inverse kinematics to return the module states from a desired
90 * chassis velocity. This method is often used to convert joystick values into
91 * module velocities and angles.
92 *
93 * This function also supports variable centers of rotation. During normal
94 * operations, the center of rotation is usually the same as the physical
95 * center of the robot; therefore, the argument is defaulted to that use case.
96 * However, if you wish to change the center of rotation for evasive
97 * maneuvers, vision alignment, or for any other use case, you can do so.
98 *
99 * In the case that the desired chassis velocities are zero (i.e. the robot
100 * will be stationary), the previously calculated module angle will be
101 * maintained.
102 *
103 * \param chassisVelocities The desired chassis velocity.
104 * \param centerOfRotation The center of rotation. For example, if you set the
105 * center of rotation at one corner of the robot and provide a chassis velocity
106 * that only has a dtheta component, the robot will rotate around that corner.
107 *
108 * \returns A vector containing the module velocities. Use caution because these
109 * module velocities are not normalized. Sometimes, a user input may cause one of
110 * the module velocities to go above the attainable max velocity. Use the
111 * DesaturateWheelVelocities(WheelVelocities const &, wpi::units::meters_per_second_t)
112 * function to rectify this issue.
113 */
114 WheelVelocities ToSwerveModuleVelocities(ChassisVelocities const &chassisVelocities, Translation2d const &centerOfRotation = Translation2d{}) const;
115
116 /**
117 * \brief Performs inverse kinematics to return the wheel velocities from a desired
118 * chassis velocity. This method is often used to convert joystick values into
119 * wheel velocities.
120 *
121 * \param chassisVelocities The desired chassis velocity.
122 * \returns The wheel velocities.
123 */
124 WheelVelocities ToWheelVelocities(ChassisVelocities const &chassisVelocities) const
125 {
126 return ToSwerveModuleVelocities(chassisVelocities);
127 }
128
129 /**
130 * \brief Performs forward kinematics to return the resulting chassis state from
131 * the given module states. This method is often used for odometry -- determining
132 * the robot's position on the field using data from the real-world velocity
133 * and angle of each module on the robot.
134 *
135 * \param moduleVelocities The state of the modules as a std::vector of type
136 * SwerveModuleVelocity, as measured from respective encoders and gyros. The
137 * order of the swerve module states should be same as passed into the
138 * constructor of this class.
139 *
140 * \returns The resulting chassis velocity.
141 */
142 ChassisVelocities ToChassisVelocities(WheelVelocities const &moduleVelocities) const;
143
144 /**
145 * \brief Performs inverse kinematics to return the module accelerations from a
146 * desired chassis acceleration. This method is often used for dynamics
147 * calculations -- converting desired robot accelerations into individual
148 * module accelerations.
149 *
150 * This function also supports variable centers of rotation. During normal
151 * operations, the center of rotation is usually the same as the physical
152 * center of the robot; therefore, the argument is defaulted to that use case.
153 * However, if you wish to change the center of rotation for evasive
154 * maneuvers, vision alignment, or for any other use case, you can do so.
155 *
156 * \param chassisAccelerations The desired chassis accelerations.
157 * \param angularVelocity The desired robot angular velocity.
158 * \param centerOfRotation The center of rotation. For example, if you set the
159 * center of rotation at one corner of the robot and provide a chassis
160 * acceleration that only has a dtheta component, the robot will rotate
161 * around that corner.
162 * \returns A vector containing the module accelerations.
163 */
165 ChassisAccelerations const &chassisAccelerations,
166 wpi::units::radians_per_second_t const angularVelocity = 0.0_rad_per_s,
167 Translation2d const &centerOfRotation = Translation2d{}
168 ) const;
169
170 /**
171 * \brief Performs inverse kinematics to return the wheel accelerations from a
172 * desired chassis acceleration. This method is often used for dynamics
173 * calculations -- converting desired robot accelerations into individual
174 * wheel accelerations.
175 *
176 * \param chassisAccelerations The desired chassis accelerations.
177 * \returns The wheel accelerations.
178 */
179 WheelAccelerations ToWheelAccelerations(ChassisAccelerations const &chassisAccelerations) const
180 {
181 return ToSwerveModuleAccelerations(chassisAccelerations);
182 }
183
184 /**
185 * \brief Performs forward kinematics to return the resulting chassis accelerations
186 * from the given module accelerations. This method is often used for dynamics
187 * calculations -- determining the robot's acceleration on the field using
188 * data from the real-world acceleration of each module on the robot.
189 *
190 * \param moduleAccelerations The accelerations of the modules as measured
191 * from respective encoders and gyros. The order of the swerve module
192 * accelerations should be same as passed into the constructor of this class.
193 * \returns The resulting chassis accelerations.
194 */
195 ChassisAccelerations ToChassisAccelerations(WheelAccelerations const &moduleAccelerations) const;
196
197 /**
198 * \brief Performs forward kinematics to return the resulting Twist2d from the
199 * given module position deltas. This method is often used for odometry --
200 * determining the robot's position on the field using data from the
201 * real-world position delta and angle of each module on the robot.
202 *
203 * \param moduleDeltas The latest change in position of the modules (as a
204 * SwerveModulePosition type) as measured from respective encoders and gyros.
205 * The order of the swerve module states should be same as passed into the
206 * constructor of this class.
207 *
208 * \returns The resulting Twist2d.
209 */
210 Twist2d ToTwist2d(WheelPositions const &moduleDeltas) const;
211
212 /**
213 * \brief Performs forward kinematics to return the resulting Twist2d from the given
214 * change in wheel positions. This method is often used for odometry --
215 * determining the robot's position on the field using changes in the distance
216 * driven by each wheel on the robot.
217 *
218 * \param start The starting distances driven by the wheels.
219 * \param end The ending distances driven by the wheels.
220 *
221 * \returns The resulting Twist2d in the robot's movement.
222 */
223 Twist2d ToTwist2d(WheelPositions const &start, WheelPositions const &end) const
224 {
225 WheelPositions result(m_modules.size());
226 for (size_t i = 0; i < m_modules.size() && i < std::min(start.size(), end.size()); ++i) {
227 result[i] = {end[i].distance - start[i].distance, end[i].angle};
228 }
229 return ToTwist2d(result);
230 }
231
232 /**
233 * \brief Performs interpolation between two values.
234 *
235 * \param start The value to start at.
236 * \param end The value to end at.
237 * \param t How far between the two values to interpolate. This should be
238 * bounded to [0, 1].
239 * \returns The interpolated value.
240 */
241 WheelPositions Interpolate(WheelPositions const &start, WheelPositions const &end, double t) const
242 {
243 WheelPositions result(m_modules.size());
244 for (size_t i = 0; i < m_modules.size() && i < std::min(start.size(), end.size()); ++i) {
245 result[i] = start[i].Interpolate(end[i], t);
246 }
247 return result;
248 }
249
250 std::vector<Translation2d> const &GetModules() const { return m_modules; }
251
252 /**
253 * \brief Renormalizes the wheel velocities if any individual velocity is above the
254 * specified maximum.
255 *
256 * Sometimes, after inverse kinematics, the requested velocity
257 * from one or more modules may be above the max attainable velocity for the
258 * driving motor on that module. To fix this issue, one can reduce all the
259 * wheel velocities to make sure that all requested module speeds are
260 * at-or-below the absolute threshold, while maintaining the ratio of
261 * velocities between modules.
262 *
263 * \param moduleVelocities The vector of module velocities.
264 * \param attainableMaxVelocity The absolute max velocity that a module can reach.
265 * \returns The vector of desaturated module velocities.
266 */
267 [[nodiscard]]
268 static WheelVelocities DesaturateWheelVelocities(WheelVelocities const &moduleVelocities, wpi::units::meters_per_second_t attainableMaxVelocity);
269
270 /**
271 * \brief Renormalizes the wheel velocities if any individual velocity is above the
272 * specified maximum, as well as getting rid of joystick saturation at edges of
273 * joystick.
274 *
275 * Sometimes, after inverse kinematics, the requested velocity
276 * from one or more modules may be above the max attainable velocity for the
277 * driving motor on that module. To fix this issue, one can reduce all the
278 * wheel velocities to make sure that all requested module velocities are
279 * at-or-below the absolute threshold, while maintaining the ratio of
280 * velocities between modules.
281 *
282 * Scaling down the module velocities rotates the direction of net motion in
283 * the opposite direction of rotational velocity, which makes discretizing the
284 * chassis velocities inaccurate because the discretization did not account
285 * for this translational skew.
286 *
287 * \param moduleVelocities The vector of module velocities.
288 * \param desiredChassisVelocity The desired velocity of the robot
289 * \param attainableMaxModuleVelocity The absolute max velocity a module can reach
290 * \param attainableMaxRobotTranslationVelocity The absolute max velocity the
291 * robot can reach while translating
292 * \param attainableMaxRobotRotationVelocity The absolute max velocity the
293 * robot can reach while rotating
294 * \returns The vector of desaturated module velocities
295 */
297 WheelVelocities const &moduleVelocities,
298 ChassisVelocities const &desiredChassisVelocity,
299 wpi::units::meters_per_second_t attainableMaxModuleVelocity,
300 wpi::units::meters_per_second_t attainableMaxRobotTranslationVelocity,
301 wpi::units::radians_per_second_t attainableMaxRobotRotationVelocity
302 );
303
304private:
305 void SetInverseKinematics(Translation2d const &centerOfRotation) const;
306};
307
308}
309}
310}
311}
std::vector< SwerveModuleVelocity > WheelVelocities
Definition SwerveDriveKinematics.hpp:52
WheelVelocities ToSwerveModuleVelocities(ChassisVelocities const &chassisVelocities, Translation2d const &centerOfRotation=Translation2d{}) const
Performs inverse kinematics to return the module states from a desired chassis velocity.
ChassisVelocities ToChassisVelocities(WheelVelocities const &moduleVelocities) const
Performs forward kinematics to return the resulting chassis state from the given module states.
SwerveDriveKinematics(std::vector< Translation2d > moduleLocations)
Constructs a swerve drive kinematics object.
Twist2d ToTwist2d(WheelPositions const &start, WheelPositions const &end) const
Performs forward kinematics to return the resulting Twist2d from the given change in wheel positions.
Definition SwerveDriveKinematics.hpp:223
std::vector< SwerveModulePosition > WheelPositions
Definition SwerveDriveKinematics.hpp:51
SwerveDriveKinematics & operator=(SwerveDriveKinematics const &)
static WheelVelocities DesaturateWheelVelocities(WheelVelocities const &moduleVelocities, ChassisVelocities const &desiredChassisVelocity, wpi::units::meters_per_second_t attainableMaxModuleVelocity, wpi::units::meters_per_second_t attainableMaxRobotTranslationVelocity, wpi::units::radians_per_second_t attainableMaxRobotRotationVelocity)
Renormalizes the wheel velocities if any individual velocity is above the specified maximum,...
std::vector< Translation2d > const & GetModules() const
Definition SwerveDriveKinematics.hpp:250
WheelAccelerations ToSwerveModuleAccelerations(ChassisAccelerations const &chassisAccelerations, wpi::units::radians_per_second_t const angularVelocity=0.0_rad_per_s, Translation2d const &centerOfRotation=Translation2d{}) const
Performs inverse kinematics to return the module accelerations from a desired chassis acceleration.
WheelPositions Interpolate(WheelPositions const &start, WheelPositions const &end, double t) const
Performs interpolation between two values.
Definition SwerveDriveKinematics.hpp:241
void ResetHeadings(std::span< Rotation2d const > moduleHeadings)
Reset the internal swerve module headings.
Definition SwerveDriveKinematics.hpp:81
SwerveDriveKinematics(SwerveDriveKinematics const &)
SwerveDriveKinematics & operator=(SwerveDriveKinematics &&)
ChassisAccelerations ToChassisAccelerations(WheelAccelerations const &moduleAccelerations) const
Performs forward kinematics to return the resulting chassis accelerations from the given module accel...
static WheelVelocities DesaturateWheelVelocities(WheelVelocities const &moduleVelocities, wpi::units::meters_per_second_t attainableMaxVelocity)
Renormalizes the wheel velocities if any individual velocity is above the specified maximum.
Twist2d ToTwist2d(WheelPositions const &moduleDeltas) const
Performs forward kinematics to return the resulting Twist2d from the given module position deltas.
std::vector< SwerveModuleAcceleration > WheelAccelerations
Definition SwerveDriveKinematics.hpp:53
WheelAccelerations ToWheelAccelerations(ChassisAccelerations const &chassisAccelerations) const
Performs inverse kinematics to return the wheel accelerations from a desired chassis acceleration.
Definition SwerveDriveKinematics.hpp:179
WheelVelocities ToWheelVelocities(ChassisVelocities const &chassisVelocities) const
Performs inverse kinematics to return the wheel velocities from a desired chassis velocity.
Definition SwerveDriveKinematics.hpp:124
Definition SwerveDrivetrainImpl.hpp:21
Definition SwerveModule.hpp:28
Definition ExternalFeedbackConfigs.hpp:16
Definition motor_constants.h:14