SubZero Common
Common library components for an FRC CommandRobot
Loading...
Searching...
No Matches
PidMotorController.h
Go to the documentation of this file.
1#pragma once
2
3#include <frc/controller/PIDController.h>
4#include <frc/smartdashboard/SmartDashboard.h>
5#include <rev/ClosedLoopSlot.h>
6#include <rev/SparkBase.h>
7#include <rev/SparkClosedLoopController.h>
8#include <rev/SparkFlex.h>
9#include <rev/SparkMax.h>
10#include <rev/config/SparkFlexConfig.h>
11#include <rev/config/SparkMaxConfig.h>
12#include <units/angle.h>
13#include <units/angular_velocity.h>
14
15#include <string>
16
19
20namespace subzero {
31template <typename TMotor, typename TController, typename TRelativeEncoder,
32 typename TAbsoluteEncoder, typename TPidConfig>
34public:
47
48 // TODO: make `absEncoder` an `std::optional<>` instead of a raw pointer
49 explicit PidMotorController(std::string name, TMotor &motor,
50 TRelativeEncoder &encoder,
51 TController &controller, PidSettings pidSettings,
52 TAbsoluteEncoder *absEncoder,
53 units::revolutions_per_minute_t maxRpm);
54
60 void Set(double percentage) override;
61
67 void Set(units::volt_t volts) override;
68
74 void SetPidTolerance(double tolerance) override;
75
80 void Update() override;
81
87 void RunWithVelocity(units::revolutions_per_minute_t rpm) override;
88
94 void RunWithVelocity(double percentage) override;
95
101 void RunToPosition(double position) override;
102
103 inline virtual void ResetEncoder() override {
104 m_encoder.SetPosition(0);
105 ConsoleWriter.logInfo(m_name + " PID Controller", "Reset encoder%s", "");
106 }
107
108 inline double GetEncoderPosition() override {
109 return m_encoder.GetPosition();
110 }
111
112 std::optional<double> GetAbsoluteEncoderPosition() override;
113
120 inline void SetEncoderConversionFactor(double factor) override {
121 m_config.encoder.PositionConversionFactor(factor);
122 m_config.encoder.VelocityConversionFactor(factor);
123
124 m_motor.Configure(m_config,
125 rev::spark::SparkBase::ResetMode::kNoResetSafeParameters,
126 rev::spark::SparkBase::PersistMode::kPersistParameters);
127 }
128
135 inline void SetAbsoluteEncoderConversionFactor(double factor) override {
136 if (m_absEncoder) {
137 m_config.absoluteEncoder.PositionConversionFactor(factor);
138 m_config.absoluteEncoder.VelocityConversionFactor(factor);
139
140 m_motor.Configure(
141 m_config, rev::spark::SparkBase::ResetMode::kNoResetSafeParameters,
142 rev::spark::SparkBase::PersistMode::kPersistParameters);
143 }
144 }
145
150 void Stop() override;
151
152 inline const PidSettings &GetPidSettings() override { return m_settings; }
153
155
156protected:
157 TMotor &m_motor;
158 TController &m_controller;
159 TRelativeEncoder &m_encoder;
160 TAbsoluteEncoder *m_absEncoder;
161 TPidConfig m_config;
163 frc::PIDController m_pidController;
166 const units::revolutions_per_minute_t m_maxRpm;
168};
169
170// TODO: Move to its own file and make it work with IPidMotorController
180template <typename TMotor, typename TController, typename TRelativeEncoder,
181 typename TAbsoluteEncoder, typename TPidConfig>
183public:
185 PidMotorController<TMotor, TController, TRelativeEncoder,
186 TAbsoluteEncoder, TPidConfig> &controller)
187 : m_controller{controller} {
188
189 frc::SmartDashboard::PutNumber(m_controller.m_name + " P Gain",
190 m_controller.GetPidSettings().p);
191 frc::SmartDashboard::PutNumber(m_controller.m_name + " I Gain",
192 m_controller.GetPidSettings().i);
193 frc::SmartDashboard::PutNumber(m_controller.m_name + " D Gain",
194 m_controller.GetPidSettings().d);
195 frc::SmartDashboard::PutNumber(m_controller.m_name + " IZone",
196 m_controller.GetPidSettings().iZone);
197 frc::SmartDashboard::PutNumber(m_controller.m_name + " Feed Forward",
198 m_controller.GetPidSettings().ff);
199 }
200
205
207 double tP = frc::SmartDashboard::GetNumber(m_controller.m_name + " P Gain",
208 m_controller.GetPidSettings().p);
209 double tI = frc::SmartDashboard::GetNumber(m_controller.m_name + " I Gain",
210 m_controller.GetPidSettings().i);
211 double tD = frc::SmartDashboard::GetNumber(m_controller.m_name + " D Gain",
212 m_controller.GetPidSettings().d);
213 double tIZone = frc::SmartDashboard::GetNumber(
214 m_controller.m_name + " IZone", m_controller.GetPidSettings().iZone);
215 double tFeedForward =
216 frc::SmartDashboard::GetNumber(m_controller.m_name + " Feed Forward",
217 m_controller.GetPidSettings().ff);
218
219 m_controller.UpdatePidSettings(
220 {.p = tP,
221 .i = tI,
222 .d = tD,
223 .iZone = tIZone,
224 .ff = tFeedForward,
225 .isIdleModeBrake = m_controller.GetPidSettings().isIdleModeBrake});
226 }
227
228private:
229 PidMotorController<TMotor, TController, TRelativeEncoder, TAbsoluteEncoder,
230 TPidConfig> &m_controller;
231};
232
234 : public PidMotorController<
235 rev::spark::SparkMax, rev::spark::SparkClosedLoopController,
236 rev::spark::SparkRelativeEncoder, rev::spark::SparkAbsoluteEncoder,
237 rev::spark::SparkMaxConfig> {};
238} // namespace subzero
#define ConsoleWriter
void UpdateFromShuffleboard()
Call this within the Periodic method of the encapsulating subsystem Note: You must enable submit butt...
PidMotorControllerTuner(PidMotorController< TMotor, TController, TRelativeEncoder, TAbsoluteEncoder, TPidConfig > &controller)
Combines a motor, motor drvier, relative encoder, and absolute encoder into a single wrapper; helpful...
void UpdatePidSettings(PidSettings settings)
void Set(units::volt_t volts) override
Set a motor to a voltage.
void Stop() override
Disable absolute positioning and stop the motor.
const PidSettings & GetPidSettings() override
void RunWithVelocity(double percentage) override
Set to a percentage of max RPM.
void RunWithVelocity(units::revolutions_per_minute_t rpm) override
Set to this velocity.
void Set(double percentage) override
Set the motor to a percentage of max voltage.
void SetAbsoluteEncoderConversionFactor(double factor) override
Sets the multiplier for going between encoder ticks and actual distance.
void SetEncoderConversionFactor(double factor) override
Sets the multiplier for going between encoder ticks and actual distance.
void RunToPosition(double position) override
Enables absolute positioning and sets the target to the position.
void SetPidTolerance(double tolerance) override
Absolute positioning is considered 'Done' when within this zone.
std::optional< double > GetAbsoluteEncoderPosition() override
const units::revolutions_per_minute_t m_maxRpm
virtual void ResetEncoder() override
void Update() override
! Call this every loop in Periodic !
PidMotorController(std::string name, TMotor &motor, TRelativeEncoder &encoder, TController &controller, PidSettings pidSettings, TAbsoluteEncoder *absEncoder, units::revolutions_per_minute_t maxRpm)
Construct a new PidMotorController.