YAMS
Yet Another Mechanism System
Loading...
Searching...
No Matches
TalonFXSWrapper.hpp
Go to the documentation of this file.
1// Copyright (c) 2026 Yet Another Software Suite
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
4#pragma once
5
6#include <any>
7#include <ctre/phoenix6/CANcoder.hpp>
8#include <ctre/phoenix6/CANdi.hpp>
9#include <ctre/phoenix6/TalonFXS.hpp>
10#include <ctre/phoenix6/controls/DutyCycleOut.hpp>
11#include <ctre/phoenix6/controls/Follower.hpp>
12#include <ctre/phoenix6/controls/MotionMagicDutyCycle.hpp>
13#include <ctre/phoenix6/controls/MotionMagicExpoDutyCycle.hpp>
14#include <ctre/phoenix6/controls/MotionMagicExpoVoltage.hpp>
15#include <ctre/phoenix6/controls/MotionMagicTorqueCurrentFOC.hpp>
16#include <ctre/phoenix6/controls/MotionMagicVelocityDutyCycle.hpp>
17#include <ctre/phoenix6/controls/MotionMagicVelocityTorqueCurrentFOC.hpp>
18#include <ctre/phoenix6/controls/MotionMagicVelocityVoltage.hpp>
19#include <ctre/phoenix6/controls/MotionMagicVoltage.hpp>
20#include <ctre/phoenix6/controls/PositionDutyCycle.hpp>
21#include <ctre/phoenix6/controls/PositionTorqueCurrentFOC.hpp>
22#include <ctre/phoenix6/controls/PositionVoltage.hpp>
23#include <ctre/phoenix6/controls/VelocityDutyCycle.hpp>
24#include <ctre/phoenix6/controls/VelocityTorqueCurrentFOC.hpp>
25#include <ctre/phoenix6/controls/VelocityVoltage.hpp>
26#include <ctre/phoenix6/controls/VoltageOut.hpp>
27#include <functional>
28#include <memory>
29#include <optional>
30#include <string>
31#include <variant>
32#include <wpi/simulation/DCMotorSim.hpp>
33#include <wpi/units/frequency.hpp>
34#include <wpi/util/Alert.hpp>
35
37
39
76 public:
77 // Expose SetVelocity(velocity, feedforwardForce) from the base class alongside the overrides.
79
82
91 TalonFXSWrapper(ctre::phoenix6::hardware::TalonFXS* talon, wpi::math::DCMotor dcMotor,
93
107 TalonFXSWrapper(ctre::phoenix6::hardware::TalonFXS* talon, wpi::math::DCMotor dcMotor,
108 MotorArrangement arrangement, SmartMotorControllerConfig* config);
109
112
113 // ---- TalonFXS specific ---------------------------------------------------
138 bool UseCANdiPWM1() const;
146 bool UseCANdiPWM2() const;
152 void SetUpdateFrequency(wpi::units::hertz_t frequency);
158 ctre::phoenix::StatusCode ForceConfigApply();
159
160 // ---- Telemetry ----------------------------------------------------------
163
164 // ---- Configuration ------------------------------------------------------
166 bool ApplyConfig(const SmartMotorControllerConfig& config) override;
167
168 // ---- Simulation ---------------------------------------------------------
170 void SetupSimulation() override;
172 void SimIterate() override;
173
174 // ---- Encoder sync -------------------------------------------------------
176 void SeedRelativeEncoder() override;
179
180 // ---- Open-loop outputs --------------------------------------------------
182 void SetDutyCycle(double dutyCycle) override;
184 double GetDutyCycle() override;
186 void SetVoltage(wpi::units::volt_t voltage) override;
188 wpi::units::volt_t GetVoltage() override;
196 std::optional<wpi::units::second_t> GetVelocityMeasurementDelay() const override;
197
198 // ---- Closed-loop setpoints ----------------------------------------------
200 void SetPosition(wpi::units::turn_t angle) override;
207 void SetPosition(wpi::units::meter_t distance) override;
209 void SetVelocity(wpi::units::turns_per_second_t velocity) override;
216 void SetVelocity(wpi::units::meters_per_second_t velocity) override;
227 void SetVelocity(wpi::units::turns_per_second_t velocity,
228 wpi::units::newton_t feedforwardForce) override;
229
230 // ---- Encoder writes -----------------------------------------------------
232 void SetEncoderPosition(wpi::units::turn_t angle) override;
239 void SetEncoderPosition(wpi::units::meter_t distance) override;
241 void SetEncoderVelocity(wpi::units::turns_per_second_t velocity) override;
243 void SetEncoderVelocity(wpi::units::meters_per_second_t velocity) override;
244
245 // ---- Encoder reads ------------------------------------------------------
247 wpi::units::turn_t GetMechanismPosition() override;
249 wpi::units::turns_per_second_t GetMechanismVelocity() override;
251 wpi::units::turn_t GetRelativeMechanismPosition() override;
253 wpi::units::turns_per_second_t GetRelativeMechanismVelocity() override;
255 wpi::units::turns_per_second_squared_t GetMechanismAcceleration() override;
257 wpi::units::turn_t GetRotorPosition() override;
259 wpi::units::turns_per_second_t GetRotorVelocity() override;
261 wpi::units::meter_t GetMeasurementPosition() override;
263 wpi::units::meters_per_second_t GetMeasurementVelocity() override;
265 wpi::units::meters_per_second_squared_t GetMeasurementAcceleration() override;
267 std::optional<wpi::units::turn_t> GetExternalEncoderMechanismPosition() override;
269 std::optional<wpi::units::turns_per_second_t> GetExternalEncoderMechanismVelocity() override;
270
271 // ---- Motor status -------------------------------------------------------
273 std::optional<wpi::units::ampere_t> GetSupplyCurrent() override;
275 wpi::units::ampere_t GetStatorCurrent() override;
277 wpi::units::celsius_t GetTemperature() override;
279 wpi::math::DCMotor GetDCMotor() override;
280
281 // ---- Configuration setters (live tuning) --------------------------------
283 void SetZeroPower(MotorMode mode) override;
285 void SetMotorInverted(bool inverted) override;
287 void SetEncoderInverted(bool inverted) override;
289 void SetKp(double kP) override;
291 void SetKi(double kI) override;
293 void SetKd(double kD) override;
295 void SetFeedback(double kP, double kI, double kD) override;
297 void SetKs(double kS) override;
299 void SetKv(double kV) override;
301 void SetKa(double kA) override;
303 void SetKg(double kG) override;
305 void SetFeedforward(double kS, double kV, double kA, double kG) override;
307 void SetStatorCurrentLimit(wpi::units::ampere_t currentLimit) override;
309 void SetSupplyCurrentLimit(wpi::units::ampere_t currentLimit) override;
311 void SetClosedLoopRampRate(wpi::units::second_t rampRate) override;
313 void SetOpenLoopRampRate(wpi::units::second_t rampRate) override;
315 void SetMechanismUpperLimit(wpi::units::turn_t upperLimit) override;
317 void SetMechanismLowerLimit(wpi::units::turn_t lowerLimit) override;
319 void SetMechanismLimits(wpi::units::turn_t lower, wpi::units::turn_t upper) override;
321 void SetMechanismLimitsEnabled(bool enabled) override;
328 void SetMeasurementUpperLimit(wpi::units::meter_t upperLimit) override;
335 void SetMeasurementLowerLimit(wpi::units::meter_t lowerLimit) override;
337 void SetMotionProfileMaxVelocity(wpi::units::turns_per_second_t maxVelocity) override;
344 void SetMotionProfileMaxVelocity(wpi::units::meters_per_second_t maxVelocity) override;
348 void SetMotionProfileMaxAcceleration(wpi::units::turns_per_second_squared_t maxAcc) override;
356 void SetMotionProfileMaxAcceleration(wpi::units::meters_per_second_squared_t maxAcc) override;
358 void SetMotionProfileMaxJerk(wpi::units::angular_jerk::turns_per_second_cubed_t maxJerk) override;
360 void SetExponentialProfile(std::optional<double> kV, std::optional<double> kA,
361 std::optional<wpi::units::volt_t> maxInput) override;
374 void SetMechanismGearing(const gearing::MechanismGearing& gearing) override;
381 void SetMechanismCircumference(wpi::units::meter_t circumference) override;
382
390 void* GetMotorController() override;
396 void* GetMotorControllerConfig() override;
397
398 private:
399 ctre::phoenix6::hardware::TalonFXS* m_talon;
400 wpi::math::DCMotor m_dcMotor;
401 MotorArrangement m_arrangement;
403 ctre::phoenix6::signals::MotorArrangementValue m_motorArrangement{
404 ctre::phoenix6::signals::MotorArrangementValue::Disabled};
405 ctre::phoenix6::signals::AdvancedHallSupportValue m_advancedHallSupport{
406 ctre::phoenix6::signals::AdvancedHallSupportValue::Disabled};
407 // Whether StatusSignal refreshes should report errors; false in simulation, where status
408 // signals are not always updated before they are read.
409 const bool m_reportStatusSignalErrors;
410 ctre::phoenix6::configs::TalonFXSConfiguration m_talonConfig;
411
412 // Active closed-loop control requests variant selects the active request type
413 using PositionControlRequest = std::variant<
414 ctre::phoenix6::controls::PositionVoltage, ctre::phoenix6::controls::PositionDutyCycle,
415 ctre::phoenix6::controls::PositionTorqueCurrentFOC,
416 ctre::phoenix6::controls::MotionMagicVoltage, ctre::phoenix6::controls::MotionMagicDutyCycle,
417 ctre::phoenix6::controls::MotionMagicExpoVoltage,
418 ctre::phoenix6::controls::MotionMagicExpoDutyCycle,
419 ctre::phoenix6::controls::MotionMagicTorqueCurrentFOC>;
420 using VelocityControlRequest =
421 std::variant<ctre::phoenix6::controls::VelocityVoltage,
422 ctre::phoenix6::controls::VelocityDutyCycle,
423 ctre::phoenix6::controls::VelocityTorqueCurrentFOC,
424 ctre::phoenix6::controls::MotionMagicVelocityVoltage,
425 ctre::phoenix6::controls::MotionMagicVelocityDutyCycle,
426 ctre::phoenix6::controls::MotionMagicVelocityTorqueCurrentFOC>;
427
428 PositionControlRequest m_positionReq{ctre::phoenix6::controls::PositionVoltage{0_tr}};
429 VelocityControlRequest m_velocityReq{ctre::phoenix6::controls::VelocityVoltage{0_tps}};
430 ctre::phoenix6::controls::VoltageOut m_voltageReq{0_V};
431 ctre::phoenix6::controls::DutyCycleOut m_dutyCycleReq{0.0};
432
433 // External sensors
434 ctre::phoenix6::hardware::CANcoder* m_cancoder{nullptr};
435 ctre::phoenix6::hardware::CANdi* m_candi{nullptr};
436
437 // Simulation
438 std::optional<wpi::sim::DCMotorSim> m_motorSim;
439
441 std::optional<wpi::util::Alert> m_rioControllerAlert;
443 std::optional<wpi::util::Alert> m_startingPositionExternalEncoderAlert;
445 std::optional<wpi::util::Alert> m_zeroOffsetNoExternalEncoderAlert;
447 std::optional<wpi::util::Alert> m_discontinuityPointNoExternalEncoderAlert;
448
450 static MotorArrangement ArrangementForMotor(ctre::phoenix6::hardware::TalonFXS* talon,
451 const wpi::math::DCMotor& motor);
453 std::string AlertId(const std::string& alertType) const;
455 void EnsureRequest(const std::function<ctre::phoenix::StatusCode()>& request);
457 template <typename Group>
458 ctre::phoenix::StatusCode ApplyGroup(const Group& group);
460 void SetFOC(bool foc);
462 double PositionGainUnitsPerRotation() const;
464 double VelocityGainUnitsPerRotation() const;
466 double AccelerationGainUnitsPerRotation() const;
468 void WriteSlotPID(ClosedLoopControllerSlot slot, double kP, double kI, double kD);
470 void WriteSlotGains(const SmartMotorControllerConfig& config);
472 void WriteMotionMagic(const SmartMotorControllerConfig& config);
474 void WriteSensorRatios(const SmartMotorControllerConfig& config);
476 void ApplyExternalEncoder(const SmartMotorControllerConfig& config);
478 std::optional<wpi::units::turn_t> GetExternalEncoderSensorPosition();
480 std::optional<wpi::units::turns_per_second_t> GetExternalEncoderSensorVelocity();
482 void ApplyFollowers(const SmartMotorControllerConfig& config);
484 void ApplyVendorControlRequest(const SmartMotorControllerConfig& config);
485};
486
487} // namespace yams::motorcontrollers::remote
Definition MechanismGearing.hpp:19
Definition SmartMotorControllerConfig.hpp:65
ClosedLoopControllerSlot
Definition SmartMotorControllerConfig.hpp:74
MotorMode
Definition SmartMotorControllerConfig.hpp:70
Definition SmartMotorController.hpp:48
SmartMotorControllerConfig::ClosedLoopControllerSlot ClosedLoopControllerSlot
Definition SmartMotorController.hpp:50
virtual void SetVelocity(wpi::units::turns_per_second_t velocity)=0
Definition TalonFXSWrapper.hpp:75
void SetPosition(wpi::units::meter_t distance) override
void SetMeasurementUpperLimit(wpi::units::meter_t upperLimit) override
void SetEncoderInverted(bool inverted) override
wpi::units::ampere_t GetStatorCurrent() override
void SetVoltage(wpi::units::volt_t voltage) override
std::optional< wpi::units::ampere_t > GetSupplyCurrent() override
SmartMotorControllerConfig & GetConfig() override
void SetMechanismUpperLimit(wpi::units::turn_t upperLimit) override
wpi::units::celsius_t GetTemperature() override
wpi::units::volt_t GetVoltage() override
ctre::phoenix::StatusCode ForceConfigApply()
void SetMechanismCircumference(wpi::units::meter_t circumference) override
void SetMechanismLowerLimit(wpi::units::turn_t lowerLimit) override
void SetEncoderPosition(wpi::units::turn_t angle) override
TalonFXSWrapper(ctre::phoenix6::hardware::TalonFXS *talon, wpi::math::DCMotor dcMotor, SmartMotorControllerConfig *config)
MotorArrangement
Definition TalonFXSWrapper.hpp:81
void SetMechanismLimits(wpi::units::turn_t lower, wpi::units::turn_t upper) override
void SetVelocity(wpi::units::meters_per_second_t velocity) override
void SetEncoderVelocity(wpi::units::meters_per_second_t velocity) override
void SetClosedLoopRampRate(wpi::units::second_t rampRate) override
void SetClosedLoopSlot(ClosedLoopControllerSlot slot) override
void SetMotionProfileMaxAcceleration(wpi::units::meters_per_second_squared_t maxAcc) override
void SetMechanismGearing(const gearing::MechanismGearing &gearing) override
wpi::units::turns_per_second_t GetMechanismVelocity() override
wpi::units::turns_per_second_squared_t GetMechanismAcceleration() override
void SetFeedback(double kP, double kI, double kD) override
void SetUpdateFrequency(wpi::units::hertz_t frequency)
std::optional< wpi::units::turns_per_second_t > GetExternalEncoderMechanismVelocity() override
TalonFXSWrapper(ctre::phoenix6::hardware::TalonFXS *talon, wpi::math::DCMotor dcMotor, MotorArrangement arrangement, SmartMotorControllerConfig *config)
wpi::units::meters_per_second_squared_t GetMeasurementAcceleration() override
void SetSupplyCurrentLimit(wpi::units::ampere_t currentLimit) override
void SetPosition(wpi::units::turn_t angle) override
void SetStatorCurrentLimit(wpi::units::ampere_t currentLimit) override
void SetMeasurementLowerLimit(wpi::units::meter_t lowerLimit) override
telemetry::UnsupportedTelemetryFields GetUnsupportedTelemetryFields() override
void SetMotionProfileMaxAcceleration(wpi::units::turns_per_second_squared_t maxAcc) override
void SetMotionProfileMaxJerk(wpi::units::angular_jerk::turns_per_second_cubed_t maxJerk) override
void SetMechanismLimitsEnabled(bool enabled) override
std::optional< wpi::units::second_t > GetVelocityMeasurementDelay() const override
void SetExponentialProfile(std::optional< double > kV, std::optional< double > kA, std::optional< wpi::units::volt_t > maxInput) override
std::optional< wpi::units::turn_t > GetExternalEncoderMechanismPosition() override
wpi::math::DCMotor GetDCMotor() override
void SetOpenLoopRampRate(wpi::units::second_t rampRate) override
wpi::units::turns_per_second_t GetRotorVelocity() override
void SetMotionProfileMaxVelocity(wpi::units::meters_per_second_t maxVelocity) override
wpi::units::turn_t GetRelativeMechanismPosition() override
void SetDutyCycle(double dutyCycle) override
wpi::units::meter_t GetMeasurementPosition() override
wpi::units::meters_per_second_t GetMeasurementVelocity() override
wpi::units::turn_t GetMechanismPosition() override
void SetVelocity(wpi::units::turns_per_second_t velocity, wpi::units::newton_t feedforwardForce) override
void SetEncoderPosition(wpi::units::meter_t distance) override
bool ApplyConfig(const SmartMotorControllerConfig &config) override
wpi::units::turn_t GetRotorPosition() override
void SetMotionProfileMaxVelocity(wpi::units::turns_per_second_t maxVelocity) override
void SetZeroPower(MotorMode mode) override
void SetMotorInverted(bool inverted) override
wpi::units::turns_per_second_t GetRelativeMechanismVelocity() override
void SetEncoderVelocity(wpi::units::turns_per_second_t velocity) override
void SetVelocity(wpi::units::turns_per_second_t velocity) override
void SetFeedforward(double kS, double kV, double kA, double kG) override
Definition TalonFXSWrapper.hpp:38
Definition SmartMotorControllerTelemetry.hpp:107