123 bool FalconConfig(ctre::phoenix6::hardware::TalonFX& motorController,
units::millisecond_t configTimeout) {
124 ctre::phoenix6::configs::TalonFXConfiguration config;
127 config.MotorOutput.Inverted = T::inverted;
130 config.MotorOutput.NeutralMode = T::neutralMode;
133 config.MotorOutput.DutyCycleNeutralDeadband = T::dutyCycleNeutralDeadband;
137 T::selectedSensor != ctre::phoenix6::signals::FeedbackSensorSourceValue::RotorSensor,
138 "Remote sensor required when address provided");
139 static_assert(T::selectedSensor_addr.address >= 0,
"Remote sensor address must be non-negative");
140 config.Feedback.FeedbackRemoteSensorID = T::selectedSensor_addr.address;
143 config.MotorOutput.PeakForwardDutyCycle = T::peakOutputForward;
146 config.MotorOutput.PeakReverseDutyCycle = T::peakOutputReverse;
149 config.OpenLoopRamps.VoltageOpenLoopRampPeriod =
150 std::clamp<units::second_t>(T::voltageOpenLoopRampPeriod, 0_s, 1_s);
153 config.OpenLoopRamps.DutyCycleOpenLoopRampPeriod =
154 std::clamp<units::second_t>(T::dutyCycleOpenLoopRampPeriod, 0_s, 1_s);
157 config.Feedback.FeedbackSensorSource = T::selectedSensor;
158 if constexpr (T::selectedSensor == ctre::phoenix6::signals::FeedbackSensorSourceValue::FusedCANcoder) {
161 static_assert(T::sensorToMechanismRatio > 0,
"sensorToMechanismRatio must be a positive value");
162 static_assert(T::rotorToSensorRatio > 0,
"rotorToSensorRatio must be a positive value");
163 config.Feedback.SensorToMechanismRatio = T::sensorToMechanismRatio;
164 config.Feedback.RotorToSensorRatio = T::rotorToSensorRatio;
168 config.Slot0.kP = T::pid0_kP;
171 config.Slot0.kI = T::pid0_kI;
174 config.Slot0.kD = T::pid0_kD;
177 config.Slot0.kS = T::pid0_kS;
180 config.Slot0.kV = T::pid0_kV;
183 config.Slot0.kA = T::pid0_kA;
186 config.Slot0.kG = T::pid0_kG;
187 config.Slot0.GravityType = T::pid0_gravityType;
190 config.Slot1.kP = T::pid1_kP;
193 config.Slot1.kI = T::pid1_kI;
196 config.Slot1.kD = T::pid1_kD;
199 config.Slot1.kS = T::pid1_kS;
202 config.Slot1.kV = T::pid1_kV;
205 config.Slot1.kA = T::pid1_kA;
208 config.Slot1.kG = T::pid1_kG;
209 config.Slot1.GravityType = T::pid1_gravityType;
212 config.MotionMagic.MotionMagicCruiseVelocity = T::motionMagic_cruiseVelocity;
215 config.MotionMagic.MotionMagicAcceleration = T::motionMagic_acceleration;
218 config.MotionMagic.MotionMagicJerk = T::motionMagic_jerk;
221 config.MotionMagic.MotionMagicExpo_kV = T::motionMagic_expo_kV;
224 config.MotionMagic.MotionMagicExpo_kA = T::motionMagic_expo_kA;
228 config.CurrentLimits.SupplyCurrentLimitEnable =
true;
230 constexpr units::ampere_t currentLimit = T::supplyCurrentLimit;
231 static_assert(currentLimit.to<
double>() > 0,
"Supply current limit must be positive");
232 config.CurrentLimits.SupplyCurrentLimit = currentLimit.to<
double>();
235 constexpr units::ampere_t currentThreshold = T::supplyCurrentLowerLimit;
236 static_assert(currentThreshold.to<
double>() > 0,
"Supply current threshold must be positive");
237 config.CurrentLimits.SupplyCurrentLowerLimit = currentThreshold.to<
double>();
240 constexpr units::second_t currentThresholdTime = T::supplyCurrentLowerTime;
241 static_assert(currentThresholdTime.to<
double>() >= 0,
"Supply current threshold time must be non-negative");
242 static_assert(currentThresholdTime.to<
double>() <= 1.275,
"Current duration must be less than 1.275");
243 config.CurrentLimits.SupplyCurrentLowerTime = currentThresholdTime.to<
double>();
247 config.CurrentLimits.StatorCurrentLimitEnable =
true;
248 constexpr units::ampere_t currentLimit = T::statorCurrentLimit;
249 static_assert(currentLimit.to<
double>() > 0,
"Stator current limit must be positive");
250 config.CurrentLimits.StatorCurrentLimit = currentLimit;
255 constexpr ctre::phoenix6::signals::ForwardLimitSourceValue source = T::forwardLimit_source;
256 if constexpr (source != ctre::phoenix6::signals::ForwardLimitSourceValue::Disabled &&
257 source != ctre::phoenix6::signals::ForwardLimitSourceValue::LimitSwitchPin) {
260 if constexpr (source != ctre::phoenix6::signals::ForwardLimitSourceValue::Disabled) {
262 "Forward limit switch configuration requires both source and normal state");
263 config.HardwareLimitSwitch.ForwardLimitEnable =
true;
265 config.HardwareLimitSwitch.ForwardLimitSource = T::forwardLimit_source;
269 T::forwardLimit_source != ctre::phoenix6::signals::ForwardLimitSourceValue::Disabled &&
270 T::forwardLimit_source != ctre::phoenix6::signals::ForwardLimitSourceValue::LimitSwitchPin,
271 "Forward limit switch device ID has no effect when limit source is not remote");
272 config.HardwareLimitSwitch.ForwardLimitRemoteSensorID = T::forwardLimit_deviceID;
275 if constexpr (T::forwardLimit_normalState != ctre::phoenix6::signals::ForwardLimitSourceValue::Disabled) {
278 config.HardwareLimitSwitch.ForwardLimitType = T::forwardLimit_normalState;
281 config.HardwareLimitSwitch.ForwardLimitEnable =
false;
286 constexpr ctre::phoenix6::signals::ReverseLimitSourceValue source = T::reverseLimit_source;
287 if constexpr (source != ctre::phoenix6::signals::ReverseLimitSourceValue::Disabled &&
288 source != ctre::phoenix6::signals::ReverseLimitSourceValue::LimitSwitchPin) {
291 if constexpr (source != ctre::phoenix6::signals::ReverseLimitSourceValue::Disabled) {
293 "Reverse limit switch configuration requires both source and normal state");
294 config.HardwareLimitSwitch.ReverseLimitEnable =
true;
296 config.HardwareLimitSwitch.ReverseLimitSource = T::reverseLimit_source;
300 T::reverseLimit_source != ctre::phoenix6::signals::ReverseLimitSourceValue::Disabled &&
301 T::reverseLimit_source != ctre::phoenix6::signals::ReverseLimitSourceValue::LimitSwitchPin,
302 "Reverse limit switch device ID has no effect when limit source is not remote");
303 config.HardwareLimitSwitch.ReverseLimitRemoteSensorID = T::reverseLimit_deviceID;
306 if constexpr (T::reverseLimit_normalState != ctre::phoenix6::signals::ReverseLimitSourceValue::Disabled) {
309 config.HardwareLimitSwitch.ReverseLimitType = T::reverseLimit_normalState;
312 config.HardwareLimitSwitch.ReverseLimitEnable =
false;
315 static_assert(T::neutralDeadband >= 0.001,
"Neutral deadband must be greater than 0.001 (0.1%)");
316 static_assert(T::neutralDeadband <= 0.25,
"Neutral deadband must be less than 0.25 (25%)");
317 config.MotorOutput.DutyCycleNeutralDeadband = T::neutralDeadband;
324 auto retVal = motorController.GetConfigurator().Apply(config, configTimeout);
326 std::cout <<
"Error code (" << motorController.GetDeviceID() <<
"): " << retVal <<
'\n';