CTRE Phoenix 6 C++ 26.70.0-alpha-2
Loading...
Searching...
No Matches
SwerveModuleImpl.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
13#include <wpi/units/force.hpp>
14#include <wpi/units/torque.hpp>
15#include <array>
16
17namespace ctre {
18namespace phoenix6 {
19namespace swerve {
20namespace impl {
21
22/**
23 * \brief All possible control requests for the module steer motor.
24 */
25enum class SteerRequestType {
26 /**
27 * \brief Control the drive motor using a Motion Magic® Expo request.
28 * The control output type is determined by SwerveModuleConstants#SteerMotorClosedLoopOutput.
29 */
31 /**
32 * \brief Control the drive motor using an unprofiled position request.
33 * The control output type is determined by SwerveModuleConstants#SteerMotorClosedLoopOutput.
34 */
36};
37
38/**
39 * \brief All possible control requests for the module drive motor.
40 */
41enum class DriveRequestType {
42 /**
43 * \brief Control the drive motor using an open-loop voltage request.
44 */
46 /**
47 * \brief Control the drive motor using a velocity closed-loop request.
48 * The control output type is determined by SwerveModuleConstants#DriveMotorClosedLoopOutput.
49 */
51};
52
53/**
54 * \brief Swerve Module class that encapsulates a swerve module powered by
55 * CTR Electronics devices.
56 *
57 * This class handles the hardware devices but does not configure them for
58 * swerve module operation using the Phoenix 6 API. Users should create a
59 * high-level SwerveModule instead of using this directly.
60 */
62public:
63 /**
64 * \brief Contains everything the swerve module needs to apply a request.
65 */
67 /**
68 * \brief Unoptimized velocity the module should target.
69 */
70 SwerveModuleVelocity Velocity{};
71
72 /**
73 * \brief Robot-centric wheel force feedforward to apply in the
74 * X direction. X is defined as forward according to WPILib
75 * convention, so this determines the forward force to apply.
76 *
77 * This force should include friction applied to the ground.
78 */
79 wpi::units::newton_t WheelForceFeedforwardX = 0_N;
80 /**
81 * \brief Robot-centric wheel force feedforward to apply in the
82 * Y direction. Y is defined as to the left according to WPILib
83 * convention, so this determines the force to apply to the left.
84 *
85 * This force should include friction applied to the ground.
86 */
87 wpi::units::newton_t WheelForceFeedforwardY = 0_N;
88
89 /**
90 * \brief The type of control request to use for the drive motor.
91 */
93 /**
94 * \brief The type of control request to use for the steer motor.
95 */
97
98 /**
99 * \brief The update period of the module request. Setting this to
100 * a non-zero value adds a velocity feedforward to the steer motor.
101 */
102 wpi::units::second_t UpdatePeriod = 0_s;
103
104 /**
105 * \brief When using Voltage-based control, set to true (default) to use FOC
106 * commutation (requires Phoenix Pro), which increases peak power by ~15%. Set to
107 * false to use trapezoidal commutation. This is ignored when using Torque-based
108 * control, which always uses FOC.
109 *
110 * FOC improves motor performance by leveraging torque (current) control.
111 * However, this may be inconvenient for applications that require specifying
112 * duty cycle or voltage. CTR-Electronics has developed a hybrid method that
113 * combines the performances gains of FOC while still allowing applications to
114 * provide duty cycle or voltage demand. This not to be confused with simple
115 * sinusoidal control or phase voltage control which lacks the performance
116 * gains.
117 */
118 bool EnableFOC = true;
119
120 /**
121 * \brief Modifies the Velocity parameter and returns itself.
122 *
123 * Unoptimized velocity the module should target.
124 *
125 * \param newVelocity Parameter to modify
126 * \returns Itself
127 */
128 ModuleRequest &WithVelocity(SwerveModuleVelocity newVelocity)
129 {
130 this->Velocity = std::move(newVelocity);
131 return *this;
132 }
133
134 /**
135 * \brief Modifies the WheelForceFeedforwardX parameter and returns itself.
136 *
137 * Robot-centric wheel force feedforward to apply in the
138 * X direction. X is defined as forward according to WPILib
139 * convention, so this determines the forward force to apply.
140 *
141 * This force should include friction.
142 *
143 * \param newWheelForceFeedforwardX Parameter to modify
144 * \returns Itself
145 */
146 ModuleRequest &WithWheelForceFeedforwardX(wpi::units::newton_t newWheelForceFeedforwardX)
147 {
148 this->WheelForceFeedforwardX = newWheelForceFeedforwardX;
149 return *this;
150 }
151 /**
152 * \brief Modifies the WheelForceFeedforwardY parameter and returns itself.
153 *
154 * Robot-centric wheel force feedforward to apply in the
155 * Y direction. Y is defined as to the left according to WPILib
156 * convention, so this determines the force to apply to the left.
157 *
158 * This force should include friction.
159 *
160 * \param newWheelForceFeedforwardY Parameter to modify
161 * \returns Itself
162 */
163 ModuleRequest &WithWheelForceFeedforwardY(wpi::units::newton_t newWheelForceFeedforwardY)
164 {
165 this->WheelForceFeedforwardY = newWheelForceFeedforwardY;
166 return *this;
167 }
168
169 /**
170 * \brief Modifies the DriveRequest parameter and returns itself.
171 *
172 * The type of control request to use for the drive motor.
173 *
174 * \param newDriveRequest Parameter to modify
175 * \returns Itself
176 */
178 {
179 this->DriveRequest = newDriveRequest;
180 return *this;
181 }
182 /**
183 * \brief Modifies the SteerRequest parameter and returns itself.
184 *
185 * The type of control request to use for the steer motor.
186 *
187 * \param newSteerRequest Parameter to modify
188 * \returns Itself
189 */
191 {
192 this->SteerRequest = newSteerRequest;
193 return *this;
194 }
195
196 /**
197 * \brief Modifies the UpdatePeriod parameter and returns itself.
198 *
199 * The update period of the module request. Setting this to a
200 * non-zero value adds a velocity feedforward to the steer motor.
201 *
202 * \param newUpdatePeriod Parameter to modify
203 * \returns Itself
204 */
205 ModuleRequest &WithUpdatePeriod(wpi::units::second_t newUpdatePeriod)
206 {
207 this->UpdatePeriod = newUpdatePeriod;
208 return *this;
209 }
210
211 /**
212 * \brief Modifies the EnableFOC parameter and returns itself.
213 *
214 * When using Voltage-based control, set to true (default) to use FOC commutation
215 * (requires Phoenix Pro), which increases peak power by ~15%. Set to false to
216 * use trapezoidal commutation. This is ignored when using Torque-based control,
217 * which always uses FOC.
218 *
219 * FOC improves motor performance by leveraging torque (current) control.
220 * However, this may be inconvenient for applications that require specifying
221 * duty cycle or voltage. CTR-Electronics has developed a hybrid method that
222 * combines the performances gains of FOC while still allowing applications to
223 * provide duty cycle or voltage demand. This not to be confused with simple
224 * sinusoidal control or phase voltage control which lacks the performance
225 * gains.
226 *
227 * \param newEnableFOC Parameter to modify
228 * \returns Itself
229 */
230 ModuleRequest &WithEnableFOC(bool newEnableFOC)
231 {
232 this->EnableFOC = newEnableFOC;
233 return *this;
234 }
235 };
236
237private:
238 std::unique_ptr<hardware::traits::CommonTalon> _driveMotor;
239 std::unique_ptr<hardware::traits::CommonTalon> _steerMotor;
240 hardware::traits::CommonTalonWithFOC *_driveMotorFOC{};
241 hardware::traits::CommonTalonWithFOC *_steerMotorFOC{};
242
247 StatusSignal<wpi::units::turn_t> _encoderPosition;
248
250 mutable StatusSignal<wpi::units::ampere_t> _driveMotorStallCurrent;
251
252 struct ModuleSupplem;
253 mutable std::unique_ptr<ModuleSupplem> _moduleSupplem;
254
255 ClosedLoopOutputType kDriveClosedLoopOutput;
256 ClosedLoopOutputType kSteerClosedLoopOutput;
257
258 using turns_per_meter = wpi::units::compound_unit<wpi::units::turns, wpi::units::inverse<wpi::units::meters>>;
259 using turns_per_meter_t = wpi::units::unit_t<turns_per_meter>;
260
261 turns_per_meter_t kDriveRotationsPerMeter;
262 wpi::units::meter_t kDriveNmPerWheelN;
263 wpi::units::scalar_t kCouplingRatioDriveRotorToEncoder;
264 wpi::units::meters_per_second_t kSpeedAt12Volts;
265
266 SwerveModulePosition _currentPosition;
267 SwerveModuleVelocity _targetVelocity;
268
269public:
270 /**
271 * \brief Construct a SwerveModuleImpl with the specified constants.
272 *
273 * \param constants Constants used to construct the module
274 * \param canbus The CAN bus this module is on
275 */
276 template <
277 std::derived_from<configs::ParentConfiguration> DriveMotorConfigsT,
278 std::derived_from<configs::ParentConfiguration> SteerMotorConfigsT,
279 std::derived_from<configs::ParentConfiguration> EncoderConfigsT
280 >
283 CANBus canbus
284 );
285
287
288 /**
289 * \brief Applies the desired ModuleRequest to this module.
290 *
291 * \param moduleRequest The request to apply to this module
292 */
293 void Apply(ModuleRequest const &moduleRequest);
294
295 /**
296 * \brief Controls this module using the specified drive and steer control requests.
297 *
298 * This is intended only to be used for characterization of the robot; do not use this for normal use.
299 *
300 * \param driveRequest The control request to apply to the drive motor
301 * \param steerRequest The control request to apply to the steer motor
302 */
303 template <
304 std::derived_from<controls::ControlRequest> DriveReq,
305 std::derived_from<controls::ControlRequest> SteerReq
306 >
307 void Apply(DriveReq &&driveRequest, SteerReq &&steerRequest)
308 {
310
311 if (_driveMotorFOC) {
312 _driveMotorFOC->SetControl(driveRequest.WithUpdateFreqHz(0_Hz));
313 } else {
314 _driveMotor->SetControl(driveRequest.WithUpdateFreqHz(0_Hz));
315 }
316
317 if (_steerMotorFOC) {
318 _steerMotorFOC->SetControl(steerRequest.WithUpdateFreqHz(0_Hz));
319 } else {
320 _steerMotor->SetControl(steerRequest.WithUpdateFreqHz(0_Hz));
321 }
322 }
323
324 /**
325 * \brief Configures the neutral mode to use for the module's drive motor.
326 *
327 * \param neutralMode The drive motor neutral mode
328 * \param timeoutSeconds Maximum amount of time to wait when performing configuration
329 * \returns Status code response of the request
330 */
331 ctre::phoenix::StatusCode ConfigNeutralMode(signals::NeutralModeValue neutralMode, wpi::units::second_t timeoutSeconds);
332
333 /**
334 * \brief Gets the state of this module and passes it back as a
335 * SwerveModulePosition object with latency compensated values.
336 *
337 * This function is blocking when it performs a refresh.
338 *
339 * \param refresh True if the signals should be refreshed
340 * \returns SwerveModulePosition containing this module's state.
341 */
342 SwerveModulePosition GetPosition(bool refresh);
343
344 /**
345 * \brief Gets the last cached swerve module position.
346 * This differs from #GetPosition in that it will not
347 * perform any latency compensation or refresh the signals.
348 *
349 * \returns Last cached SwerveModulePosition
350 */
351 SwerveModulePosition GetCachedPosition() const { return _currentPosition; }
352
353 /**
354 * \brief Get the current velocity of the module.
355 *
356 * This is typically used for telemetry, as the SwerveModulePosition
357 * is used for odometry.
358 *
359 * \returns Current velocity of the module
360 */
361 SwerveModuleVelocity GetCurrentVelocity() const
362 {
363 return SwerveModuleVelocity{_driveVelocity.GetValue() / kDriveRotationsPerMeter, {_steerPosition.GetValue()}};
364 }
365
366 /**
367 * \brief Get the target velocity of the module.
368 *
369 * This is typically used for telemetry.
370 *
371 * \returns Target velocity of the module
372 */
373 SwerveModuleVelocity GetTargetVelocity() const { return _targetVelocity; }
374
375 /**
376 * \brief Resets the cached target velocity to 0 m/s at the current module angle.
377 *
378 * This should not be called by users, as this is called automatically when running
379 * a SwerveRequest that directly applies ControlRequest instances to the motors.
380 */
381 void ResetTargetVelocity() { _targetVelocity = {0_mps, _currentPosition.angle}; }
382
383 /**
384 * \brief Resets this module's drive motor position to 0 rotations.
385 */
387 {
388 /* Only touch drive pos, not steer */
389 _driveMotor->SetPosition(0_tr);
390 }
391
392 /**
393 * \brief Gets the closed-loop output type to use for the drive motor.
394 *
395 * \returns Drive motor closed-loop output type
396 */
398 {
399 return kDriveClosedLoopOutput;
400 }
401
402 /**
403 * \brief Gets the closed-loop output type to use for the steer motor.
404 *
405 * \returns Steer motor closed-loop output type
406 */
408 {
409 return kSteerClosedLoopOutput;
410 }
411
412private:
413 /**
414 * \brief Collection of all possible torque feedforward outputs that
415 * can be applied to the motor for a given wheel force feedforward.
416 */
417 struct MotorTorqueFeedforwards {
418 wpi::units::newton_meter_t torque;
419 wpi::units::ampere_t torqueCurrent;
420 wpi::units::volt_t voltage;
421 };
422
423 wpi::units::turns_per_second_t ApplyVelocityCorrections(wpi::units::turns_per_second_t velocity, wpi::units::turn_t targetAngle) const;
424 MotorTorqueFeedforwards CalculateMotorTorqueFeedforwards(
425 wpi::units::newton_t wheelForceFeedforwardX,
426 wpi::units::newton_t wheelForceFeedforwardY
427 ) const;
428
430
431 std::array<BaseStatusSignal *, 4> GetSignals()
432 {
433 return std::array<BaseStatusSignal *, 4>{&_drivePosition, &_driveVelocity, &_steerPosition, &_steerVelocity};
434 }
435 StatusSignal<wpi::units::turn_t> &GetEncoderPositionSignal()
436 {
437 return _encoderPosition;
438 }
439};
440
441}
442}
443}
444}
Class for getting information about an available CAN bus.
Definition CANBus.hpp:142
Represents a status signal with data of type T, and operations available to retrieve information abou...
Definition StatusSignal.hpp:523
Contains everything common between Talon motor controllers that support FOC (requires Phoenix Pro).
Definition CommonTalonWithFOC.hpp:28
ctre::phoenix::StatusCode ConfigNeutralMode(signals::NeutralModeValue neutralMode, wpi::units::second_t timeoutSeconds)
Configures the neutral mode to use for the module's drive motor.
void ResetTargetVelocity()
Resets the cached target velocity to 0 m/s at the current module angle.
Definition SwerveModuleImpl.hpp:381
SwerveModuleImpl(SwerveModuleConstants< DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT > const &constants, CANBus canbus)
Construct a SwerveModuleImpl with the specified constants.
ClosedLoopOutputType GetSteerClosedLoopOutputType() const
Gets the closed-loop output type to use for the steer motor.
Definition SwerveModuleImpl.hpp:407
friend class SwerveDrivetrainImpl
Definition SwerveModuleImpl.hpp:429
SwerveModuleVelocity GetTargetVelocity() const
Get the target velocity of the module.
Definition SwerveModuleImpl.hpp:373
void Apply(ModuleRequest const &moduleRequest)
Applies the desired ModuleRequest to this module.
SwerveModuleVelocity GetCurrentVelocity() const
Get the current velocity of the module.
Definition SwerveModuleImpl.hpp:361
void Apply(DriveReq &&driveRequest, SteerReq &&steerRequest)
Controls this module using the specified drive and steer control requests.
Definition SwerveModuleImpl.hpp:307
ClosedLoopOutputType GetDriveClosedLoopOutputType() const
Gets the closed-loop output type to use for the drive motor.
Definition SwerveModuleImpl.hpp:397
SwerveModulePosition GetPosition(bool refresh)
Gets the state of this module and passes it back as a SwerveModulePosition object with latency compen...
void ResetPosition()
Resets this module's drive motor position to 0 rotations.
Definition SwerveModuleImpl.hpp:386
SwerveModulePosition GetCachedPosition() const
Gets the last cached swerve module position.
Definition SwerveModuleImpl.hpp:351
Status codes reported by APIs, including OK, warnings, and errors.
Definition StatusCodes.h:28
Definition SwerveDrivetrainImpl.hpp:21
SteerRequestType
All possible control requests for the module steer motor.
Definition SwerveModuleImpl.hpp:25
@ MotionMagicExpo
Control the drive motor using a Motion Magic® Expo request.
Definition SwerveModuleImpl.hpp:30
@ Position
Control the drive motor using an unprofiled position request.
Definition SwerveModuleImpl.hpp:35
DriveRequestType
All possible control requests for the module drive motor.
Definition SwerveModuleImpl.hpp:41
@ Velocity
Control the drive motor using a velocity closed-loop request.
Definition SwerveModuleImpl.hpp:50
@ OpenLoopVoltage
Control the drive motor using an open-loop voltage request.
Definition SwerveModuleImpl.hpp:45
Definition SwerveModule.hpp:28
ClosedLoopOutputType
Supported closed-loop output types.
Definition SwerveModuleConstants.hpp:22
Definition ExternalFeedbackConfigs.hpp:16
Definition motor_constants.h:14
The state of the motor controller bridge when output is neutral or disabled.
Definition SpnEnums.hpp:1499
All constants for a swerve module.
Definition SwerveModuleConstants.hpp:152
Contains everything the swerve module needs to apply a request.
Definition SwerveModuleImpl.hpp:66
ModuleRequest & WithSteerRequest(SteerRequestType newSteerRequest)
Modifies the SteerRequest parameter and returns itself.
Definition SwerveModuleImpl.hpp:190
DriveRequestType DriveRequest
The type of control request to use for the drive motor.
Definition SwerveModuleImpl.hpp:92
wpi::units::newton_t WheelForceFeedforwardX
Robot-centric wheel force feedforward to apply in the X direction.
Definition SwerveModuleImpl.hpp:79
ModuleRequest & WithEnableFOC(bool newEnableFOC)
Modifies the EnableFOC parameter and returns itself.
Definition SwerveModuleImpl.hpp:230
ModuleRequest & WithWheelForceFeedforwardX(wpi::units::newton_t newWheelForceFeedforwardX)
Modifies the WheelForceFeedforwardX parameter and returns itself.
Definition SwerveModuleImpl.hpp:146
ModuleRequest & WithVelocity(SwerveModuleVelocity newVelocity)
Modifies the Velocity parameter and returns itself.
Definition SwerveModuleImpl.hpp:128
SwerveModuleVelocity Velocity
Unoptimized velocity the module should target.
Definition SwerveModuleImpl.hpp:70
ModuleRequest & WithWheelForceFeedforwardY(wpi::units::newton_t newWheelForceFeedforwardY)
Modifies the WheelForceFeedforwardY parameter and returns itself.
Definition SwerveModuleImpl.hpp:163
SteerRequestType SteerRequest
The type of control request to use for the steer motor.
Definition SwerveModuleImpl.hpp:96
ModuleRequest & WithDriveRequest(DriveRequestType newDriveRequest)
Modifies the DriveRequest parameter and returns itself.
Definition SwerveModuleImpl.hpp:177
bool EnableFOC
When using Voltage-based control, set to true (default) to use FOC commutation (requires Phoenix Pro)...
Definition SwerveModuleImpl.hpp:118
ModuleRequest & WithUpdatePeriod(wpi::units::second_t newUpdatePeriod)
Modifies the UpdatePeriod parameter and returns itself.
Definition SwerveModuleImpl.hpp:205
wpi::units::second_t UpdatePeriod
The update period of the module request.
Definition SwerveModuleImpl.hpp:102
wpi::units::newton_t WheelForceFeedforwardY
Robot-centric wheel force feedforward to apply in the Y direction.
Definition SwerveModuleImpl.hpp:87