CTRE Phoenix 6 C++ 24.3.0
SimpleDifferentialMechanism.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 <atomic>
14#include <optional>
15
16namespace ctre {
17namespace phoenix6 {
18namespace mechanisms {
19
20/**
21 * \brief Manages control of a simple two-axis differential mechanism.
22 *
23 * This mechanism provides limited differential functionality. Pro users
24 * on a CAN FD bus can use the \c DifferentialMechanism class instead
25 * for full functionality.
26 */
28public:
29 /**
30 * \brief Sensor sources for a differential Pigeon 2.
31 */
33 Yaw,
34 Pitch,
35 Roll
36 };
37
38 /**
39 * \brief Possible reasons for the mechanism to disable.
40 */
41 enum class DisabledReason {
42 /**
43 * \brief No reason given.
44 */
45 None,
46 /**
47 * \brief A remote sensor is not present on CAN Bus.
48 */
49 MissingRemoteSensor,
50 /**
51 * \brief The remote Talon FX used for differential
52 * control is not present on CAN Bus.
53 */
54 MissingDifferentialFX,
55 /**
56 * \brief A remote sensor position has overflowed. Because of the
57 * nature of remote sensors, it is possible for a remote sensor
58 * position to overflow beyond what is supported by the status signal
59 * frame. However, this is rare and cannot occur over the course of an
60 * FRC match under normal use.
61 */
62 RemoteSensorPosOverflow,
63 /**
64 * \brief A device or remote sensor has reset.
65 */
66 DeviceHasReset,
67 };
68
69 /**
70 * \brief Possible reasons for the mechanism to require
71 * user action to resume control.
72 */
73 enum class RequiresUserReason {
74 /**
75 * \brief No reason given.
76 */
77 None,
78 /**
79 * \brief A remote sensor position has overflowed. Because of the
80 * nature of remote sensors, it is possible for a remote sensor
81 * position to overflow beyond what is supported by the status signal
82 * frame. However, this is rare and cannot occur over the course of an
83 * FRC match under normal use.
84 */
85 RemoteSensorPosOverflow,
86 /**
87 * \brief A device or remote sensor has reset.
88 */
89 DeviceHasReset,
90 };
91
92private:
93 hardware::TalonFX *_diffAddFX;
94 hardware::TalonFX *_diffSubFX;
95 std::optional<hardware::Pigeon2 *> _pigeon2;
96 DifferentialPigeon2Source _pigeonSource;
97 std::optional<hardware::CANcoder *> _cancoder;
98
100
101 controls::NeutralOut _neutral{};
102 controls::CoastOut _coast{};
103 controls::StaticBrake _brake{};
104
105 std::function<bool()> _diffAddFXResetChecker;
106 std::function<bool()> _diffSubFXResetChecker;
107 std::optional<std::function<bool()>> _pigeon2ResetChecker;
108 std::optional<std::function<bool()>> _cancoderResetChecker;
109
110 bool _hasAppliedConfigs{false};
111 ctre::phoenix::StatusCode BeforeControl();
112
113 std::atomic<bool> _mechanismDisabled{false};
114 std::atomic<bool> _requiresUserAction{false};
115
116 DisabledReason _disabledReason{DisabledReason::None};
117 RequiresUserReason _requiresUserReason{RequiresUserReason::None};
118
119public:
120 /**
121 * \brief The default number of retries for config applies.
122 */
123 static constexpr int kDefaultConfigRetries = 5;
124
125 /**
126 * \brief Creates a new simple differential mechanism using the given two hardware#TalonFX devices.
127 * The mechanism will use the average of the two Talon FX sensors on the primary axis,
128 * and the difference between the two Talon FX sensors on the differential axis.
129 *
130 * This mechanism provides limited differential functionality. Pro users on a CAN FD
131 * bus can use the \c DifferentialMechanism class instead for full functionality.
132 *
133 * \param differentialAddFX The Talon FX that will have the differential output added to its regular output.
134 * \param differentialSubFX The Talon FX that will have the differential output subtracted from its regular output.
135 * \param motorDirectionsAlign Whether the differential motors' directions are aligned.
136 */
137 SimpleDifferentialMechanism(hardware::TalonFX &differentialAddFX, hardware::TalonFX &differentialSubFX, bool motorDirectionsAlign) :
138 _diffAddFX{&differentialAddFX},
139 _diffSubFX{&differentialSubFX},
140 _pigeon2{std::nullopt},
141 _pigeonSource{},
142 _cancoder{std::nullopt},
143 _diffFollow{_diffAddFX->GetDeviceID(), !motorDirectionsAlign},
144 _diffAddFXResetChecker{_diffAddFX->GetResetOccurredChecker()},
145 _diffSubFXResetChecker{_diffSubFX->GetResetOccurredChecker()},
146 _pigeon2ResetChecker{std::nullopt},
147 _cancoderResetChecker{std::nullopt}
148 {}
149
150 /**
151 * \brief Creates a new simple differential mechanism using the given two hardware#TalonFX devices and
152 * a hardware#Pigeon2. The mechanism will use the average of the two Talon FX sensors on the primary
153 * axis, and the selected Pigeon 2 sensor source on the differential axis.
154 *
155 * This mechanism provides limited differential functionality. Pro users on a CAN FD
156 * bus can use the \c DifferentialMechanism class instead for full functionality.
157 *
158 * \param differentialAddFX The Talon FX that will have the differential output added to its regular output.
159 * \param differentialSubFX The Talon FX that will have the differential output subtracted from its regular output.
160 * \param motorDirectionsAlign Whether the differential motors' directions are aligned.
161 * \param pigeon2 The Pigeon 2 to use for the differential axis.
162 * \param pigeonSource The sensor source to use for the Pigeon 2 (Yaw, Pitch, or Roll).
163 */
164 SimpleDifferentialMechanism(hardware::TalonFX &differentialAddFX, hardware::TalonFX &differentialSubFX, bool motorDirectionsAlign, hardware::Pigeon2 &pigeon2, DifferentialPigeon2Source pigeonSource) :
165 _diffAddFX{&differentialAddFX},
166 _diffSubFX{&differentialSubFX},
167 _pigeon2{&pigeon2},
168 _pigeonSource{pigeonSource},
169 _cancoder{std::nullopt},
170 _diffFollow{_diffAddFX->GetDeviceID(), !motorDirectionsAlign},
171 _diffAddFXResetChecker{_diffAddFX->GetResetOccurredChecker()},
172 _diffSubFXResetChecker{_diffSubFX->GetResetOccurredChecker()},
173 _pigeon2ResetChecker{(*_pigeon2)->GetResetOccurredChecker()},
174 _cancoderResetChecker{std::nullopt}
175 {}
176
177 /**
178 * \brief Creates a new simple differential mechanism using the given two hardware#TalonFX devices and
179 * a hardware#CANcoder. The mechanism will use the average of the two Talon FX sensors on the primary
180 * axis, and the CANcoder position/velocity on the differential axis.
181 *
182 * This mechanism provides limited differential functionality. Pro users on a CAN FD
183 * bus can use the \c DifferentialMechanism class instead for full functionality.
184 *
185 * \param differentialAddFX The Talon FX that will have the differential output added to its regular output.
186 * \param differentialSubFX The Talon FX that will have the differential output subtracted from its regular output.
187 * \param motorDirectionsAlign Whether the differential motors' directions are aligned.
188 * \param cancoder The CANcoder to use for the differential axis.
189 */
190 SimpleDifferentialMechanism(hardware::TalonFX &differentialAddFX, hardware::TalonFX &differentialSubFX, bool motorDirectionsAlign, hardware::CANcoder &cancoder) :
191 _diffAddFX{&differentialAddFX},
192 _diffSubFX{&differentialSubFX},
193 _pigeon2{std::nullopt},
194 _pigeonSource{},
195 _cancoder{&cancoder},
196 _diffFollow{_diffAddFX->GetDeviceID(), !motorDirectionsAlign},
197 _diffAddFXResetChecker{_diffAddFX->GetResetOccurredChecker()},
198 _diffSubFXResetChecker{_diffSubFX->GetResetOccurredChecker()},
199 _pigeon2ResetChecker{std::nullopt},
200 _cancoderResetChecker{(*_cancoder)->GetResetOccurredChecker()}
201 {}
202
203 /**
204 * \brief Get the Talon FX that is differential leader. The differential
205 * leader calculates the output for the differential follower. The differential
206 * leader is also used for fault detection, and it reports status signals for
207 * the differential controller.
208 *
209 * \returns Differential leader Talon FX
210 */
212 {
213 return *_diffAddFX;
214 }
215 /**
216 * \brief Get the Talon FX that is differential leader. The differential
217 * leader calculates the output for the differential follower. The differential
218 * leader is also useful for fault detection, and it reports status signals for
219 * the differential controller.
220 *
221 * \returns Differential leader Talon FX
222 */
224 {
225 return *_diffAddFX;
226 }
227
228 /**
229 * \brief Get the Talon FX that is differential follower. The differential
230 * follower's position and velocity are used by the differential leader
231 * for the differential controller.
232 *
233 * \returns Differential follower Talon FX
234 */
236 {
237 return *_diffSubFX;
238 }
239 /**
240 * \brief Get the Talon FX that is differential follower. The differential
241 * follower's position and velocity are used by the differential leader
242 * for the differential controller.
243 *
244 * \returns Differential follower Talon FX
245 */
247 {
248 return *_diffSubFX;
249 }
250
251 /**
252 * \brief Apply the mechanism configs to the devices. This should be
253 * called after applying all other configs to the devices.
254 *
255 * \details If the user does not call this function by the time SetControl
256 * is called, SetControl will apply the configs once.
257 *
258 * \param numRetries Number of retries when applying the configs
259 * \returns Status Code of the config applies.
260 */
261 ctre::phoenix::StatusCode ApplyConfigs(int numRetries = kDefaultConfigRetries);
262
263 /**
264 * \brief Call this method periodically to keep the mechanism state updated.
265 */
266 void Periodic();
267
268 /**
269 * \brief Get whether the mechanism is currently disabled due to an issue.
270 *
271 * \returns true if the mechanism is temporarily disabled
272 */
273 bool IsDisabled() const
274 {
275 return _mechanismDisabled.load(std::memory_order_acquire);
276 }
277
278 /**
279 * \brief Get whether the mechanism is currently disabled and requires
280 * user action to re-enable mechanism control.
281 *
282 * \returns true if the mechanism is disabled and the user must manually
283 * perform an action
284 */
286 {
287 return _requiresUserAction.load(std::memory_order_acquire);
288 }
289
290 /**
291 * \brief Gets the state of the mechanism.
292 *
293 * \returns MechanismState representing the state of the mechanism
294 */
296 {
297 if (RequiresUserAction()) {
299 } else if (IsDisabled()) {
301 } else {
302 return MechanismState::OK;
303 }
304 }
305
306 /**
307 * \brief Indicate to the mechanism that the user has performed the required
308 * action to resume mechanism control.
309 */
311
312 /**
313 * \returns The reason for the mechanism being disabled
314 */
316 {
317 return _disabledReason;
318 }
319 /**
320 * \returns The reason for the mechanism requiring user
321 * action to resume control
322 */
324 {
325 return _requiresUserReason;
326 }
327
328 /**
329 * \brief Request neutral output of mechanism. The applied brake type
330 * is determined by the NeutralMode configuration of each device.
331 *
332 * \details Since the NeutralMode configuration of devices may not align, users
333 * may prefer to use the \c SetCoastOut() or \c SetStaticBrake() method.
334 *
335 * \returns Status Code of the request.
336 */
337 ctre::phoenix::StatusCode SetNeutralOut();
338
339 /**
340 * \brief Request coast neutral output of mechanism. The bridge is
341 * disabled and the rotor is allowed to coast.
342 *
343 * \returns Status Code of the request.
344 */
345 ctre::phoenix::StatusCode SetCoastOut();
346
347 /**
348 * \brief Applies full neutral-brake on the mechanism by shorting
349 * motor leads together.
350 *
351 * \returns Status Code of the request.
352 */
353 ctre::phoenix::StatusCode SetStaticBrake();
354
355
356private:
357
358
359public:
360 /**
361 * \brief Sets the control request for this mechanism.
362 *
363 * \param _diffAddFXRequest Request a specified motor duty cycle with a
364 * differential position closed-loop.
365 * \returns Status Code of the request.
366 */
367 ctre::phoenix::StatusCode SetControl(controls::DifferentialDutyCycle _diffAddFXRequest);
368 /**
369 * \brief Sets the control request for this mechanism.
370 *
371 * \param _diffAddFXRequest Request a specified voltage with a differential
372 * position closed-loop.
373 * \returns Status Code of the request.
374 */
375 ctre::phoenix::StatusCode SetControl(controls::DifferentialVoltage _diffAddFXRequest);
376 /**
377 * \brief Sets the control request for this mechanism.
378 *
379 * \param _diffAddFXRequest Request PID to target position with a
380 * differential position setpoint.
381 * \returns Status Code of the request.
382 */
383 ctre::phoenix::StatusCode SetControl(controls::DifferentialPositionDutyCycle _diffAddFXRequest);
384 /**
385 * \brief Sets the control request for this mechanism.
386 *
387 * \param _diffAddFXRequest Request PID to target position with a
388 * differential position setpoint
389 * \returns Status Code of the request.
390 */
391 ctre::phoenix::StatusCode SetControl(controls::DifferentialPositionVoltage _diffAddFXRequest);
392 /**
393 * \brief Sets the control request for this mechanism.
394 *
395 * \param _diffAddFXRequest Request PID to target velocity with a
396 * differential position setpoint.
397 * \returns Status Code of the request.
398 */
399 ctre::phoenix::StatusCode SetControl(controls::DifferentialVelocityDutyCycle _diffAddFXRequest);
400 /**
401 * \brief Sets the control request for this mechanism.
402 *
403 * \param _diffAddFXRequest Request PID to target velocity with a
404 * differential position setpoint.
405 * \returns Status Code of the request.
406 */
407 ctre::phoenix::StatusCode SetControl(controls::DifferentialVelocityVoltage _diffAddFXRequest);
408 /**
409 * \brief Sets the control request for this mechanism.
410 *
411 * \param _diffAddFXRequest Requests Motion Magic® to target a final position
412 * using a motion profile, and PID to a differential
413 * position setpoint.
414 * \returns Status Code of the request.
415 */
416 ctre::phoenix::StatusCode SetControl(controls::DifferentialMotionMagicDutyCycle _diffAddFXRequest);
417 /**
418 * \brief Sets the control request for this mechanism.
419 *
420 * \param _diffAddFXRequest Requests Motion Magic® to target a final position
421 * using a motion profile, and PID to a differential
422 * position setpoint.
423 * \returns Status Code of the request.
424 */
425 ctre::phoenix::StatusCode SetControl(controls::DifferentialMotionMagicVoltage _diffAddFXRequest);
426};
427
428}
429}
430}
Request coast neutral output of actuator.
Definition: CoastOut.hpp:27
Request a specified motor duty cycle with a differential position closed-loop.
Definition: DifferentialDutyCycle.hpp:31
Follow the differential motor output of another Talon.
Definition: DifferentialFollower.hpp:30
Requests Motion Magic® to target a final position using a motion profile, and PID to a differential p...
Definition: DifferentialMotionMagicDutyCycle.hpp:33
Requests Motion Magic® to target a final position using a motion profile, and PID to a differential p...
Definition: DifferentialMotionMagicVoltage.hpp:33
Request PID to target position with a differential position setpoint.
Definition: DifferentialPositionDutyCycle.hpp:29
Request PID to target position with a differential position setpoint.
Definition: DifferentialPositionVoltage.hpp:29
Request PID to target velocity with a differential position setpoint.
Definition: DifferentialVelocityDutyCycle.hpp:30
Request PID to target velocity with a differential position setpoint.
Definition: DifferentialVelocityVoltage.hpp:30
Request a specified voltage with a differential position closed-loop.
Definition: DifferentialVoltage.hpp:31
Request neutral output of actuator.
Definition: NeutralOut.hpp:27
Class for CANcoder, a CAN based magnetic encoder that provides absolute and relative position along w...
Definition: CANcoder.hpp:27
Class description for the Pigeon 2 IMU sensor that measures orientation.
Definition: Pigeon2.hpp:29
Class description for the Talon FX integrated motor controller.
Definition: TalonFX.hpp:32
Manages control of a simple two-axis differential mechanism.
Definition: SimpleDifferentialMechanism.hpp:27
hardware::TalonFX const & GetDifferentialLeader() const
Get the Talon FX that is differential leader.
Definition: SimpleDifferentialMechanism.hpp:223
ctre::phoenix::StatusCode SetControl(controls::DifferentialPositionVoltage _diffAddFXRequest)
Sets the control request for this mechanism.
ctre::phoenix::StatusCode SetControl(controls::DifferentialPositionDutyCycle _diffAddFXRequest)
Sets the control request for this mechanism.
ctre::phoenix::StatusCode SetCoastOut()
Request coast neutral output of mechanism.
hardware::TalonFX const & GetDifferentialFollower() const
Get the Talon FX that is differential follower.
Definition: SimpleDifferentialMechanism.hpp:246
hardware::TalonFX & GetDifferentialFollower()
Get the Talon FX that is differential follower.
Definition: SimpleDifferentialMechanism.hpp:235
void ClearUserRequirement()
Indicate to the mechanism that the user has performed the required action to resume mechanism control...
ctre::phoenix::StatusCode SetStaticBrake()
Applies full neutral-brake on the mechanism by shorting motor leads together.
bool IsDisabled() const
Get whether the mechanism is currently disabled due to an issue.
Definition: SimpleDifferentialMechanism.hpp:273
ctre::phoenix::StatusCode SetControl(controls::DifferentialVoltage _diffAddFXRequest)
Sets the control request for this mechanism.
ctre::phoenix::StatusCode SetNeutralOut()
Request neutral output of mechanism.
static constexpr int kDefaultConfigRetries
The default number of retries for config applies.
Definition: SimpleDifferentialMechanism.hpp:123
ctre::phoenix::StatusCode SetControl(controls::DifferentialMotionMagicDutyCycle _diffAddFXRequest)
Sets the control request for this mechanism.
ctre::phoenix::StatusCode SetControl(controls::DifferentialVelocityVoltage _diffAddFXRequest)
Sets the control request for this mechanism.
SimpleDifferentialMechanism(hardware::TalonFX &differentialAddFX, hardware::TalonFX &differentialSubFX, bool motorDirectionsAlign, hardware::CANcoder &cancoder)
Creates a new simple differential mechanism using the given two hardware::TalonFX devices and a hardw...
Definition: SimpleDifferentialMechanism.hpp:190
DisabledReason GetDisabledReason() const
Definition: SimpleDifferentialMechanism.hpp:315
MechanismState GetMechanismState() const
Gets the state of the mechanism.
Definition: SimpleDifferentialMechanism.hpp:295
ctre::phoenix::StatusCode SetControl(controls::DifferentialMotionMagicVoltage _diffAddFXRequest)
Sets the control request for this mechanism.
RequiresUserReason GetRequiresUserReason() const
Definition: SimpleDifferentialMechanism.hpp:323
void Periodic()
Call this method periodically to keep the mechanism state updated.
bool RequiresUserAction() const
Get whether the mechanism is currently disabled and requires user action to re-enable mechanism contr...
Definition: SimpleDifferentialMechanism.hpp:285
DisabledReason
Possible reasons for the mechanism to disable.
Definition: SimpleDifferentialMechanism.hpp:41
SimpleDifferentialMechanism(hardware::TalonFX &differentialAddFX, hardware::TalonFX &differentialSubFX, bool motorDirectionsAlign)
Creates a new simple differential mechanism using the given two hardware::TalonFX devices.
Definition: SimpleDifferentialMechanism.hpp:137
SimpleDifferentialMechanism(hardware::TalonFX &differentialAddFX, hardware::TalonFX &differentialSubFX, bool motorDirectionsAlign, hardware::Pigeon2 &pigeon2, DifferentialPigeon2Source pigeonSource)
Creates a new simple differential mechanism using the given two hardware::TalonFX devices and a hardw...
Definition: SimpleDifferentialMechanism.hpp:164
hardware::TalonFX & GetDifferentialLeader()
Get the Talon FX that is differential leader.
Definition: SimpleDifferentialMechanism.hpp:211
ctre::phoenix::StatusCode SetControl(controls::DifferentialDutyCycle _diffAddFXRequest)
Sets the control request for this mechanism.
ctre::phoenix::StatusCode ApplyConfigs(int numRetries=kDefaultConfigRetries)
Apply the mechanism configs to the devices.
ctre::phoenix::StatusCode SetControl(controls::DifferentialVelocityDutyCycle _diffAddFXRequest)
Sets the control request for this mechanism.
RequiresUserReason
Possible reasons for the mechanism to require user action to resume control.
Definition: SimpleDifferentialMechanism.hpp:73
DifferentialPigeon2Source
Sensor sources for a differential Pigeon 2.
Definition: SimpleDifferentialMechanism.hpp:32
MechanismState
Possible states of a mechanism.
Definition: MechanismState.hpp:15
@ RequiresUserAction
The mechanism is disabled and requires user action.
@ Disabled
The mechanism is temporarily disabled due to an issue.
@ OK
The mechanism is running normally.
Definition: string_util.hpp:15