107 bool FalconConfig(ctre::phoenix6::hardware::TalonFX& motorController,
units::millisecond_t configTimeout) {
108 ctre::phoenix6::configs::TalonFXConfiguration config;
111 config.MotorOutput.Inverted = T::inverted;
114 config.MotorOutput.NeutralMode = T::neutralMode;
118 T::selectedSensor != ctre::phoenix6::signals::FeedbackSensorSourceValue::RotorSensor,
119 "Remote sensor required when address provided");
120 static_assert(T::selectedSensor_addr.address >= 0,
"Remote sensor address must be non-negative");
121 config.Feedback.FeedbackRemoteSensorID = T::selectedSensor_addr.address;
124 config.MotorOutput.PeakForwardDutyCycle = T::peakOutputForward;
127 config.MotorOutput.PeakReverseDutyCycle = T::peakOutputReverse;
130 config.Feedback.FeedbackSensorSource = T::selectedSensor;
131 if constexpr (T::selectedSensor == ctre::phoenix6::signals::FeedbackSensorSourceValue::FusedCANcoder) {
134 static_assert(T::sensorToMechanismRatio > 0,
"sensorToMechanismRatio must be a positive value");
135 static_assert(T::rotorToSensorRatio > 0,
"rotorToSensorRatio must be a positive value");
136 config.Feedback.SensorToMechanismRatio = T::sensorToMechanismRatio;
137 config.Feedback.RotorToSensorRatio = T::rotorToSensorRatio;
141 config.Slot0.kP = T::pid0_kP;
144 config.Slot0.kI = T::pid0_kI;
147 config.Slot0.kD = T::pid0_kD;
150 config.Slot0.kS = T::pid0_kS;
153 config.Slot0.kV = T::pid0_kV;
156 config.Slot0.kA = T::pid0_kA;
159 config.Slot0.kG = T::pid0_kG;
160 config.Slot0.GravityType = T::pid0_gravityType;
163 config.Slot1.kP = T::pid1_kP;
166 config.Slot1.kI = T::pid1_kI;
169 config.Slot1.kD = T::pid1_kD;
172 config.Slot1.kS = T::pid1_kS;
175 config.Slot1.kV = T::pid1_kV;
178 config.Slot1.kA = T::pid1_kA;
181 config.Slot1.kG = T::pid1_kG;
182 config.Slot1.GravityType = T::pid1_gravityType;
186 config.CurrentLimits.SupplyCurrentLimitEnable =
true;
188 constexpr units::ampere_t currentLimit = T::supplyCurrentLimit;
189 static_assert(currentLimit.to<
double>() > 0,
"Supply current limit must be positive");
190 config.CurrentLimits.SupplyCurrentLimit = currentLimit.to<
double>();
193 constexpr units::ampere_t currentThreshold = T::supplyCurrentThreshold;
194 static_assert(currentThreshold.to<
double>() > 0,
"Supply current threshold must be positive");
195 config.CurrentLimits.SupplyCurrentThreshold = currentThreshold.to<
double>();
198 constexpr units::second_t currentThresholdTime = T::supplyCurrentThresholdTime;
199 static_assert(currentThresholdTime.to<
double>() >= 0,
"Supply current threshold time must be non-negative");
200 static_assert(currentThresholdTime.to<
double>() <= 1.275,
"Current duration must be less than 1.275");
201 config.CurrentLimits.SupplyTimeThreshold = currentThresholdTime.to<
double>();
205 config.CurrentLimits.StatorCurrentLimitEnable =
true;
206 constexpr units::ampere_t currentLimit = T::statorCurrentLimit;
207 static_assert(currentLimit.to<
double>() > 0,
"Stator current limit must be positive");
208 config.CurrentLimits.StatorCurrentLimit = currentLimit.to<
double>();
213 constexpr ctre::phoenix6::signals::ForwardLimitSourceValue source = T::forwardLimit_source;
214 if constexpr (source != ctre::phoenix6::signals::ForwardLimitSourceValue::Disabled &&
215 source != ctre::phoenix6::signals::ForwardLimitSourceValue::LimitSwitchPin) {
218 if constexpr (source != ctre::phoenix6::signals::ForwardLimitSourceValue::Disabled) {
220 "Forward limit switch configuration requires both source and normal state");
221 config.HardwareLimitSwitch.ForwardLimitEnable =
true;
223 config.HardwareLimitSwitch.ForwardLimitSource = T::forwardLimit_source;
227 T::forwardLimit_source != ctre::phoenix6::signals::ForwardLimitSourceValue::Disabled &&
228 T::forwardLimit_source != ctre::phoenix6::signals::ForwardLimitSourceValue::LimitSwitchPin,
229 "Forward limit switch device ID has no effect when limit source is not remote");
230 config.HardwareLimitSwitch.ForwardLimitRemoteSensorID = T::forwardLimit_deviceID;
233 if constexpr (T::forwardLimit_normalState != ctre::phoenix6::signals::ForwardLimitSourceValue::Disabled) {
236 config.HardwareLimitSwitch.ForwardLimitType = T::forwardLimit_normalState;
239 config.HardwareLimitSwitch.ForwardLimitEnable =
false;
244 constexpr ctre::phoenix6::signals::ReverseLimitSourceValue source = T::reverseLimit_source;
245 if constexpr (source != ctre::phoenix6::signals::ReverseLimitSourceValue::Disabled &&
246 source != ctre::phoenix6::signals::ReverseLimitSourceValue::LimitSwitchPin) {
249 if constexpr (source != ctre::phoenix6::signals::ReverseLimitSourceValue::Disabled) {
251 "Reverse limit switch configuration requires both source and normal state");
252 config.HardwareLimitSwitch.ReverseLimitEnable =
true;
254 config.HardwareLimitSwitch.ReverseLimitSource = T::reverseLimit_source;
258 T::reverseLimit_source != ctre::phoenix6::signals::ReverseLimitSourceValue::Disabled &&
259 T::reverseLimit_source != ctre::phoenix6::signals::ReverseLimitSourceValue::LimitSwitchPin,
260 "Reverse limit switch device ID has no effect when limit source is not remote");
261 config.HardwareLimitSwitch.ReverseLimitRemoteSensorID = T::reverseLimit_deviceID;
264 if constexpr (T::reverseLimit_normalState != ctre::phoenix6::signals::ReverseLimitSourceValue::Disabled) {
267 config.HardwareLimitSwitch.ReverseLimitType = T::reverseLimit_normalState;
270 config.HardwareLimitSwitch.ReverseLimitEnable =
false;
273 static_assert(T::neutralDeadband >= 0.001,
"Neutral deadband must be greater than 0.001 (0.1%)");
274 static_assert(T::neutralDeadband <= 0.25,
"Neutral deadband must be less than 0.25 (25%)");
275 config.MotorOutput.DutyCycleNeutralDeadband = T::neutralDeadband;
282 auto retVal = motorController.GetConfigurator().Apply(config, configTimeout);
284 std::cout <<
"Error code (" << motorController.GetDeviceID() <<
"): " << retVal <<
'\n';