YAMS
Yet Another Mechanism System
Loading...
Searching...
No Matches
TalonFXWrapper.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/TalonFX.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
90 TalonFXWrapper(ctre::phoenix6::hardware::TalonFX* talon, wpi::math::DCMotor dcMotor,
92
95
96 // ---- TalonFX specific ---------------------------------------------------
121 bool UseCANdiPWM1() const;
129 bool UseCANdiPWM2() const;
135 void SetUpdateFrequency(wpi::units::hertz_t frequency);
141 ctre::phoenix::StatusCode ForceConfigApply();
142
143 // ---- Telemetry ----------------------------------------------------------
146
147 // ---- Configuration ------------------------------------------------------
149 bool ApplyConfig(const SmartMotorControllerConfig& config) override;
150
151 // ---- Simulation ---------------------------------------------------------
153 void SetupSimulation() override;
155 void SimIterate() override;
156
157 // ---- Encoder sync -------------------------------------------------------
159 void SeedRelativeEncoder() override;
162
163 // ---- Open-loop outputs --------------------------------------------------
165 void SetDutyCycle(double dutyCycle) override;
167 double GetDutyCycle() override;
169 void SetVoltage(wpi::units::volt_t voltage) override;
171 wpi::units::volt_t GetVoltage() override;
179 std::optional<wpi::units::second_t> GetVelocityMeasurementDelay() const override;
180
181 // ---- Closed-loop setpoints ----------------------------------------------
183 void SetPosition(wpi::units::turn_t angle) override;
190 void SetPosition(wpi::units::meter_t distance) override;
192 void SetVelocity(wpi::units::turns_per_second_t velocity) override;
199 void SetVelocity(wpi::units::meters_per_second_t velocity) override;
210 void SetVelocity(wpi::units::turns_per_second_t velocity,
211 wpi::units::newton_t feedforwardForce) override;
212
213 // ---- Encoder writes -----------------------------------------------------
215 void SetEncoderPosition(wpi::units::turn_t angle) override;
222 void SetEncoderPosition(wpi::units::meter_t distance) override;
224 void SetEncoderVelocity(wpi::units::turns_per_second_t velocity) override;
226 void SetEncoderVelocity(wpi::units::meters_per_second_t velocity) override;
227
228 // ---- Encoder reads ------------------------------------------------------
230 wpi::units::turn_t GetMechanismPosition() override;
232 wpi::units::turns_per_second_t GetMechanismVelocity() override;
234 wpi::units::turn_t GetRelativeMechanismPosition() override;
236 wpi::units::turns_per_second_t GetRelativeMechanismVelocity() override;
238 wpi::units::turns_per_second_squared_t GetMechanismAcceleration() override;
240 wpi::units::turn_t GetRotorPosition() override;
242 wpi::units::turns_per_second_t GetRotorVelocity() override;
244 wpi::units::meter_t GetMeasurementPosition() override;
246 wpi::units::meters_per_second_t GetMeasurementVelocity() override;
248 wpi::units::meters_per_second_squared_t GetMeasurementAcceleration() override;
250 std::optional<wpi::units::turn_t> GetExternalEncoderMechanismPosition() override;
252 std::optional<wpi::units::turns_per_second_t> GetExternalEncoderMechanismVelocity() override;
253
254 // ---- Motor status -------------------------------------------------------
256 std::optional<wpi::units::ampere_t> GetSupplyCurrent() override;
258 wpi::units::ampere_t GetStatorCurrent() override;
260 wpi::units::celsius_t GetTemperature() override;
262 wpi::math::DCMotor GetDCMotor() override;
263
264 // ---- Configuration setters (live tuning) --------------------------------
266 void SetZeroPower(MotorMode mode) override;
268 void SetMotorInverted(bool inverted) override;
270 void SetEncoderInverted(bool inverted) override;
272 void SetKp(double kP) override;
274 void SetKi(double kI) override;
276 void SetKd(double kD) override;
278 void SetFeedback(double kP, double kI, double kD) override;
280 void SetKs(double kS) override;
282 void SetKv(double kV) override;
284 void SetKa(double kA) override;
286 void SetKg(double kG) override;
288 void SetFeedforward(double kS, double kV, double kA, double kG) override;
290 void SetStatorCurrentLimit(wpi::units::ampere_t currentLimit) override;
292 void SetSupplyCurrentLimit(wpi::units::ampere_t currentLimit) override;
294 void SetClosedLoopRampRate(wpi::units::second_t rampRate) override;
296 void SetOpenLoopRampRate(wpi::units::second_t rampRate) override;
298 void SetMechanismUpperLimit(wpi::units::turn_t upperLimit) override;
300 void SetMechanismLowerLimit(wpi::units::turn_t lowerLimit) override;
302 void SetMechanismLimits(wpi::units::turn_t lower, wpi::units::turn_t upper) override;
304 void SetMechanismLimitsEnabled(bool enabled) override;
311 void SetMeasurementUpperLimit(wpi::units::meter_t upperLimit) override;
318 void SetMeasurementLowerLimit(wpi::units::meter_t lowerLimit) override;
320 void SetMotionProfileMaxVelocity(wpi::units::turns_per_second_t maxVelocity) override;
327 void SetMotionProfileMaxVelocity(wpi::units::meters_per_second_t maxVelocity) override;
331 void SetMotionProfileMaxAcceleration(wpi::units::turns_per_second_squared_t maxAcc) override;
339 void SetMotionProfileMaxAcceleration(wpi::units::meters_per_second_squared_t maxAcc) override;
341 void SetMotionProfileMaxJerk(wpi::units::angular_jerk::turns_per_second_cubed_t maxJerk) override;
343 void SetExponentialProfile(std::optional<double> kV, std::optional<double> kA,
344 std::optional<wpi::units::volt_t> maxInput) override;
357 void SetMechanismGearing(const gearing::MechanismGearing& gearing) override;
364 void SetMechanismCircumference(wpi::units::meter_t circumference) override;
365
373 void* GetMotorController() override;
379 void* GetMotorControllerConfig() override;
380
381 private:
382 ctre::phoenix6::hardware::TalonFX* m_talon;
383 wpi::math::DCMotor m_dcMotor;
384 // Whether StatusSignal refreshes should report errors; false in simulation, where status
385 // signals are not always updated before they are read.
386 const bool m_reportStatusSignalErrors;
387 ctre::phoenix6::configs::TalonFXConfiguration m_talonConfig;
388
389 // Active closed-loop control requests variant selects the active request type
390 using PositionControlRequest = std::variant<
391 ctre::phoenix6::controls::PositionVoltage, ctre::phoenix6::controls::PositionDutyCycle,
392 ctre::phoenix6::controls::PositionTorqueCurrentFOC,
393 ctre::phoenix6::controls::MotionMagicVoltage, ctre::phoenix6::controls::MotionMagicDutyCycle,
394 ctre::phoenix6::controls::MotionMagicExpoVoltage,
395 ctre::phoenix6::controls::MotionMagicExpoDutyCycle,
396 ctre::phoenix6::controls::MotionMagicTorqueCurrentFOC>;
397 using VelocityControlRequest =
398 std::variant<ctre::phoenix6::controls::VelocityVoltage,
399 ctre::phoenix6::controls::VelocityDutyCycle,
400 ctre::phoenix6::controls::VelocityTorqueCurrentFOC,
401 ctre::phoenix6::controls::MotionMagicVelocityVoltage,
402 ctre::phoenix6::controls::MotionMagicVelocityDutyCycle,
403 ctre::phoenix6::controls::MotionMagicVelocityTorqueCurrentFOC>;
404
405 PositionControlRequest m_positionReq{ctre::phoenix6::controls::PositionVoltage{0_tr}};
406 VelocityControlRequest m_velocityReq{ctre::phoenix6::controls::VelocityVoltage{0_tps}};
407 ctre::phoenix6::controls::VoltageOut m_voltageReq{0_V};
408 ctre::phoenix6::controls::DutyCycleOut m_dutyCycleReq{0.0};
409
410 // External sensors
411 ctre::phoenix6::hardware::CANcoder* m_cancoder{nullptr};
412 ctre::phoenix6::hardware::CANdi* m_candi{nullptr};
413
414 // Simulation
415 std::optional<wpi::sim::DCMotorSim> m_motorSim;
416
418 std::optional<wpi::util::Alert> m_rioControllerAlert;
420 std::optional<wpi::util::Alert> m_startingPositionExternalEncoderAlert;
422 std::optional<wpi::util::Alert> m_zeroOffsetNoExternalEncoderAlert;
424 std::optional<wpi::util::Alert> m_feedbackNotAppliedAlert;
426 std::optional<wpi::util::Alert> m_feedforwardNotAppliedAlert;
428 std::optional<wpi::util::Alert> m_discontinuityPointNoExternalEncoderAlert;
429
431 std::string AlertId(const std::string& alertType) const;
433 void EnsureRequest(const std::function<ctre::phoenix::StatusCode()>& request);
435 template <typename Group>
436 ctre::phoenix::StatusCode ApplyGroup(const Group& group,
437 wpi::units::second_t retryFor = wpi::units::second_t{0.1});
439 void SetFOC(bool foc);
441 double PositionGainUnitsPerRotation() const;
443 double VelocityGainUnitsPerRotation() const;
445 double AccelerationGainUnitsPerRotation() const;
447 void WriteSlotPID(ClosedLoopControllerSlot slot, double kP, double kI, double kD);
449 void WriteSlotGains(const SmartMotorControllerConfig& config);
451 void WriteMotionMagic(const SmartMotorControllerConfig& config);
453 void WriteSensorRatios(const SmartMotorControllerConfig& config);
455 void ApplyExternalEncoder(const SmartMotorControllerConfig& config);
457 std::optional<wpi::units::turn_t> GetExternalEncoderSensorPosition();
459 std::optional<wpi::units::turns_per_second_t> GetExternalEncoderSensorVelocity();
461 void ApplyFollowers(const SmartMotorControllerConfig& config);
463 void ApplyVendorControlRequest(const SmartMotorControllerConfig& config);
464};
465
466} // 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 TalonFXWrapper.hpp:75
std::optional< wpi::units::turns_per_second_t > GetExternalEncoderMechanismVelocity() override
void SetMotionProfileMaxVelocity(wpi::units::meters_per_second_t maxVelocity) override
void SetMotionProfileMaxVelocity(wpi::units::turns_per_second_t maxVelocity) override
void SetMotionProfileMaxJerk(wpi::units::angular_jerk::turns_per_second_cubed_t maxJerk) override
void SetUpdateFrequency(wpi::units::hertz_t frequency)
void SetMechanismLowerLimit(wpi::units::turn_t lowerLimit) override
wpi::units::turn_t GetRotorPosition() override
TalonFXWrapper(ctre::phoenix6::hardware::TalonFX *talon, wpi::math::DCMotor dcMotor, SmartMotorControllerConfig *config)
SmartMotorControllerConfig & GetConfig() override
wpi::units::turns_per_second_t GetMechanismVelocity() override
void SetMotionProfileMaxAcceleration(wpi::units::meters_per_second_squared_t maxAcc) override
void SetExponentialProfile(std::optional< double > kV, std::optional< double > kA, std::optional< wpi::units::volt_t > maxInput) override
void SetEncoderInverted(bool inverted) override
void SetVelocity(wpi::units::meters_per_second_t velocity) override
void SetFeedback(double kP, double kI, double kD) override
wpi::units::turn_t GetMechanismPosition() override
wpi::units::celsius_t GetTemperature() override
ctre::phoenix::StatusCode ForceConfigApply()
wpi::units::meter_t GetMeasurementPosition() override
void SetMechanismUpperLimit(wpi::units::turn_t upperLimit) override
void SetOpenLoopRampRate(wpi::units::second_t rampRate) override
wpi::units::turns_per_second_t GetRotorVelocity() override
wpi::units::volt_t GetVoltage() override
void SetSupplyCurrentLimit(wpi::units::ampere_t currentLimit) override
void SetDutyCycle(double dutyCycle) override
void SetEncoderPosition(wpi::units::turn_t angle) override
void SetMechanismLimits(wpi::units::turn_t lower, wpi::units::turn_t upper) override
void SetZeroPower(MotorMode mode) override
void SetEncoderPosition(wpi::units::meter_t distance) override
wpi::units::meters_per_second_t GetMeasurementVelocity() override
wpi::units::meters_per_second_squared_t GetMeasurementAcceleration() override
void SetFeedforward(double kS, double kV, double kA, double kG) override
std::optional< wpi::units::second_t > GetVelocityMeasurementDelay() const override
void SetMechanismCircumference(wpi::units::meter_t circumference) override
void SetVoltage(wpi::units::volt_t voltage) override
void SetMotionProfileMaxAcceleration(wpi::units::turns_per_second_squared_t maxAcc) override
void SetMeasurementLowerLimit(wpi::units::meter_t lowerLimit) override
void SetPosition(wpi::units::turn_t angle) override
void SetEncoderVelocity(wpi::units::meters_per_second_t velocity) override
telemetry::UnsupportedTelemetryFields GetUnsupportedTelemetryFields() override
void SetVelocity(wpi::units::turns_per_second_t velocity, wpi::units::newton_t feedforwardForce) override
void SetClosedLoopSlot(ClosedLoopControllerSlot slot) override
void SetMechanismLimitsEnabled(bool enabled) override
void SetMechanismGearing(const gearing::MechanismGearing &gearing) override
void SetMeasurementUpperLimit(wpi::units::meter_t upperLimit) override
bool ApplyConfig(const SmartMotorControllerConfig &config) override
void SetClosedLoopRampRate(wpi::units::second_t rampRate) override
std::optional< wpi::units::turn_t > GetExternalEncoderMechanismPosition() override
void SetPosition(wpi::units::meter_t distance) override
void SetStatorCurrentLimit(wpi::units::ampere_t currentLimit) override
wpi::units::turns_per_second_t GetRelativeMechanismVelocity() override
void SetVelocity(wpi::units::turns_per_second_t velocity) override
std::optional< wpi::units::ampere_t > GetSupplyCurrent() override
void SetEncoderVelocity(wpi::units::turns_per_second_t velocity) override
wpi::units::ampere_t GetStatorCurrent() override
wpi::units::turns_per_second_squared_t GetMechanismAcceleration() override
wpi::math::DCMotor GetDCMotor() override
void SetMotorInverted(bool inverted) override
wpi::units::turn_t GetRelativeMechanismPosition() override
Definition TalonFXSWrapper.hpp:38
Definition SmartMotorControllerTelemetry.hpp:107