Valkyrie 2026
Loading...
Searching...
No Matches
BaseController.h
1#pragma once
2
3#include <memory>
4#include <string>
5
6#include <ctre/phoenix6/CANBus.hpp>
7#include <ctre/phoenix6/CANcoder.hpp>
8#include <ctre/phoenix6/TalonFX.hpp>
9#include <frc/simulation/DCMotorSim.h>
10#include <frc/simulation/FlywheelSim.h>
11#include <frc/simulation/SingleJointedArmSim.h>
12#include <frc/smartdashboard/SmartDashboard.h>
13#include <frc/system/plant/DCMotor.h>
14#include <networktables/NetworkTable.h>
15#include <networktables/NetworkTableEntry.h>
16#include <networktables/NetworkTableInstance.h>
17#include <units/angle.h>
18#include <units/angular_velocity.h>
19#include <units/base.h>
20#include <units/current.h>
21#include <units/velocity.h>
22#include <units/voltage.h>
23#include <valkyrie/Loggable.h>
24#include <valkyrie/controllers/PIDF.h>
25
26#include "frc/smartdashboard/SendableChooser.h"
27#include "wpi/sendable/SendableRegistry.h"
28
29namespace valor {
30
34enum NeutralMode { Brake, Coast };
35
58 public:
59 using Output = std::variant<units::volt_t, units::ampere_t, units::scalar_t>;
60
61 template <typename T>
62 class Signal {
63 public:
64 constexpr Signal(T value, units::second_t timestamp) : value{value}, timestamp{timestamp} {}
65
66 inline const T* operator->() const { return &value; }
67
68 inline const T& operator*() const { return value; }
69
70 constexpr units::second_t GetTimestamp() const { return timestamp; }
71
72 private:
73 T value;
74 units::second_t timestamp;
75 };
76
77 enum class OperationalMode {
78 NON_OPERATIONAL,
79 TUNING,
80 OPERATIONAL,
81 };
82
83 // Should match the order in BaseController::Output
84 enum class ControlMode {
85 VOLTAGE,
86 CURRENT,
87 DUTY_CYCLE,
88 SPEED,
89 POSITION,
90 };
91
95 explicit BaseController(frc::DCMotor _motorSpec)
96 : motorSpec{_motorSpec}, rotorToSensor(1), sensorToMech(1), voltageCompensation(units::volt_t{12.0}) {
97 tuningModeChooser.SetDefaultOption(magic_enum::enum_name(ControlMode::VOLTAGE), ControlMode::VOLTAGE);
98 for (ControlMode mode : magic_enum::enum_values<ControlMode>())
99 tuningModeChooser.AddOption(magic_enum::enum_name(mode), mode);
100
101 opModeChooser.SetDefaultOption(magic_enum::enum_name(OperationalMode::OPERATIONAL), OperationalMode::OPERATIONAL);
102 for (OperationalMode mode : magic_enum::enum_values<OperationalMode>())
103 opModeChooser.AddOption(magic_enum::enum_name(mode), mode);
104
105 LogChild("Tuning Mode", &tuningModeChooser);
106 LogChild("Operational Mode", &opModeChooser);
107 }
108
109 void OnLoggingStart() override { WriteLog("Setpoint", 0.0); }
110
111 virtual void ApplyConfig() = 0;
112
119 constexpr units::turns_per_second_t GetMaxMechanismSpeed() { return motorSpec.freeSpeed / GetGearRatio(); }
120
121 constexpr double GetGearRatio() const { return rotorToSensor * sensorToMech; }
122
127 constexpr void SetVoltageCompensation(units::volt_t _voltageCompensation) { voltageCompensation = _voltageCompensation; }
128
129 constexpr units::volt_t GetVoltageCompensation() const { return voltageCompensation; }
130
141 virtual constexpr void Reset() {}
142
151
160
161 virtual Signal<units::volt_t> GetVoltage() const = 0;
162
171
172 virtual Signal<units::turns_per_second_squared_t> GetAcceleration() const = 0;
173
174 virtual void SetEncoderPosition(units::turn_t position) = 0;
175
176 void SetPosition(units::turn_t position, Output feedforward = 0, int slot = 0) {
177 if (opModeChooser.GetSelected() == OperationalMode::OPERATIONAL) {
178 setpoint = position.value();
179 controlMode = ControlMode::POSITION;
180 PositionSetter(position, feedforward, slot);
181 } else if (opModeChooser.GetSelected() == OperationalMode::TUNING)
182 HandleTuningMode();
183 else
184 PowerSetter(0_V);
185 }
186
187 void SetSpeed(units::turns_per_second_t speed, Output feedforward = 0, int slot = 0) {
188 if (opModeChooser.GetSelected() == OperationalMode::OPERATIONAL) {
189 setpoint = speed.value();
190 controlMode = ControlMode::SPEED;
191 SpeedSetter(speed, feedforward, slot);
192 } else if (opModeChooser.GetSelected() == OperationalMode::TUNING)
193 HandleTuningMode();
194 else
195 PowerSetter(0_V);
196 }
197
198 void SetPower(Output power) {
199 if (opModeChooser.GetSelected() == OperationalMode::OPERATIONAL) {
200 std::visit([this](auto&& power) { setpoint = power.value(); }, power);
201 controlMode = static_cast<ControlMode>(power.index());
202 PowerSetter(power);
203 } else if (opModeChooser.GetSelected() == OperationalMode::TUNING)
204 HandleTuningMode();
205 else
206 PowerSetter(0_V);
207 }
208
221 virtual void SetupFollower(int canID, bool followerInverted = false) = 0;
222
234 virtual void SetPIDF(valor::PIDF<> pidf, int slot = 0, bool saveImmediately = false) = 0;
235
248 void SetLimits(units::turn_t reverse, units::turn_t forward, bool saveImmediately = false) {
249 SetForwardLimit(forward, saveImmediately);
250 SetReverseLimit(reverse, saveImmediately);
251 }
252
261 virtual void SetForwardLimit(units::turn_t forward, bool saveImmediately = false) = 0;
262
271 virtual void SetReverseLimit(units::turn_t reverse, bool saveImmediately = false) = 0;
272
279 virtual void SetNeutralMode(valor::NeutralMode mode, bool saveImmediately = false) = 0;
280
296 virtual void SetGearRatios(double rotorToSensor, double sensorToMech, bool saveImmediately = false) = 0;
297
298 virtual void SetOpenLoopRamp(units::second_t time, bool saveImmediately = false) = 0;
299
300 virtual units::turn_t GetAbsoluteEncoderPosition() const = 0;
301
302 virtual units::volt_t CalculateAppliedVoltage() = 0;
303 virtual void SetSimState(units::turn_t pos, units::turns_per_second_t vel, units::turns_per_second_squared_t accel) = 0;
304
305 virtual inline void SetSimState(frc::sim::DCMotorSim& sim) {
306 SetSimState(sim.GetAngularPosition(), sim.GetAngularVelocity(), sim.GetAngularAcceleration());
307 }
308
309 virtual inline void SetSimState(frc::sim::FlywheelSim& sim) {
310 SetSimState(0_tr, sim.GetAngularVelocity(), sim.GetAngularAcceleration());
311 }
312
313 virtual inline void SetSimState(frc::sim::SingleJointedArmSim& sim) { SetSimState(sim.GetAngle(), sim.GetVelocity(), 0_tr_per_s_sq); }
314
315 void LoggablePeriodic() override {
316 WriteLog("Control Mode", controlMode);
317 if (opModeChooser.GetSelected() == OperationalMode::TUNING)
318 setpoint = ReadLog("Setpoint", setpoint);
319 else
320 WriteLog("Setpoint", setpoint);
321 }
322
323 frc::DCMotor motorSpec;
324
325 protected:
338 virtual void PositionSetter(units::turn_t position, Output feedforward = 0, int slot = 0) = 0;
339
352 virtual void SpeedSetter(units::turns_per_second_t speed, Output feedforward = 0, int slot = 0) = 0;
353
354 virtual void PowerSetter(Output out) = 0;
355
356 double rotorToSensor;
357 double sensorToMech;
358 units::volt_t voltageCompensation;
359
360 private:
361 void HandleTuningMode() {
362 controlMode = tuningModeChooser.GetSelected();
363 switch (tuningModeChooser.GetSelected()) {
364 case ControlMode::VOLTAGE:
365 return PowerSetter(units::volt_t{setpoint});
366 case ControlMode::CURRENT:
367 return PowerSetter(units::ampere_t{setpoint});
368 case ControlMode::DUTY_CYCLE:
369 return PowerSetter(setpoint);
370 case ControlMode::SPEED:
371 return SpeedSetter(units::turns_per_second_t{setpoint});
372 case ControlMode::POSITION:
373 return PositionSetter(units::turn_t{setpoint});
374 }
375 }
376
377 frc::SendableChooser<ControlMode> tuningModeChooser;
378 frc::SendableChooser<OperationalMode> opModeChooser;
379 ControlMode controlMode = ControlMode::DUTY_CYCLE;
380 double setpoint = 0.0;
381};
382} // namespace valor
Definition BaseController.h:62
virtual void SetNeutralMode(valor::NeutralMode mode, bool saveImmediately=false)=0
Set the neutral mode of the motor.
virtual void SetForwardLimit(units::turn_t forward, bool saveImmediately=false)=0
Set the forward soft limit for the motor.
void SetLimits(units::turn_t reverse, units::turn_t forward, bool saveImmediately=false)
Set both soft limits for the motor.
Definition BaseController.h:248
virtual Signal< units::turn_t > GetPosition() const =0
Get the motors position.
virtual void SpeedSetter(units::turns_per_second_t speed, Output feedforward=0, int slot=0)=0
Send the motor to a specific speed.
virtual void SetPIDF(valor::PIDF<> pidf, int slot=0, bool saveImmediately=false)=0
Change the PIDF values for the motor.
virtual Signal< units::ampere_t > GetCurrent() const =0
Get the motors output current.
constexpr units::turns_per_second_t GetMaxMechanismSpeed()
Get the mechanisms's maximum speed.
Definition BaseController.h:119
virtual void SetReverseLimit(units::turn_t reverse, bool saveImmediately=false)=0
Set the reverse soft limit for the motor.
BaseController(frc::DCMotor _motorSpec)
Construct a new Valor Controller object.
Definition BaseController.h:95
virtual void SetupFollower(int canID, bool followerInverted=false)=0
If a motor is paired with another motor, setup that other motor as a follower.
virtual void PositionSetter(units::turn_t position, Output feedforward=0, int slot=0)=0
Send the motor to a specific position.
virtual Signal< units::turns_per_second_t > GetSpeed() const =0
Get the motors speed.
virtual void SetGearRatios(double rotorToSensor, double sensorToMech, bool saveImmediately=false)=0
Set the gear ratios for the motor.
void LoggablePeriodic() override
Periodic callback for logging updates.
Definition BaseController.h:315
constexpr void SetVoltageCompensation(units::volt_t _voltageCompensation)
Setup the voltage compensation for the motor.
Definition BaseController.h:127
virtual constexpr void Reset()
Resets the motor and any state.
Definition BaseController.h:141
void OnLoggingStart() override
Hook invoked when logging is started for this object.
Definition BaseController.h:109
Base helper for publishing and subscribing values to NetworkTables.
Definition Loggable.h:53
void LogChild(std::string_view name, Loggable *child)
Register a child Loggable under a named subtree.
Container to hold PID and feed forward values for the motor controller.
Definition PIDF.h:26