YAMS
Yet Another Mechanism System
Loading...
Searching...
No Matches
SmartMotorController.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 <functional>
7#include <memory>
8#include <optional>
9#include <string>
10#include <vector>
11#include <wpi/math/controller/ArmFeedforward.hpp>
12#include <wpi/math/controller/ElevatorFeedforward.hpp>
13#include <wpi/math/controller/PIDController.hpp>
14#include <wpi/math/controller/SimpleMotorFeedforward.hpp>
15#include <wpi/math/system/DCMotor.hpp>
16#include <wpi/math/trajectory/ExponentialProfile.hpp>
17#include <wpi/math/trajectory/TrapezoidProfile.hpp>
18#include <wpi/nt/NetworkTable.hpp>
19#include <wpi/system/Notifier.hpp>
20#include <wpi/units/acceleration.hpp>
21#include <wpi/units/angle.hpp>
22#include <wpi/units/angular_acceleration.hpp>
23#include <wpi/units/angular_jerk.hpp>
24#include <wpi/units/angular_velocity.hpp>
25#include <wpi/units/current.hpp>
26#include <wpi/units/force.hpp>
27#include <wpi/units/length.hpp>
28#include <wpi/units/temperature.hpp>
29#include <wpi/units/time.hpp>
30#include <wpi/units/velocity.hpp>
31#include <wpi/units/voltage.hpp>
32
33#include "SimSupplier.hpp"
38
39namespace yams::motorcontrollers {
40
49 public:
53
56
57 // ---- Configuration ------------------------------------------------------
58
65 virtual bool ApplyConfig(const SmartMotorControllerConfig& config) = 0;
66
67 // ---- Simulation ---------------------------------------------------------
68
70 virtual void SetupSimulation() = 0;
71
73 virtual void SimIterate() = 0;
74
82 void SetSimSupplier(std::shared_ptr<SimSupplier> supplier);
83
90
91 // ---- Encoder sync -------------------------------------------------------
92
94 virtual void SeedRelativeEncoder() = 0;
95
97 virtual void SynchronizeRelativeEncoder() = 0;
98
99 // ---- Open-loop outputs --------------------------------------------------
100
106 virtual void SetDutyCycle(double dutyCycle) = 0;
107
113 virtual double GetDutyCycle() = 0;
114
120 virtual void SetVoltage(wpi::units::volt_t voltage) = 0;
121
127 virtual wpi::units::volt_t GetVoltage() = 0;
128
129 // ---- Closed-loop setpoints ----------------------------------------------
130
136 virtual void SetPosition(wpi::units::turn_t angle) = 0;
137
143 virtual void SetPosition(wpi::units::meter_t distance) = 0;
144
150 virtual void SetVelocity(wpi::units::turns_per_second_t velocity) = 0;
151
157 virtual void SetVelocity(wpi::units::meters_per_second_t velocity) = 0;
158
169 virtual void SetVelocity(wpi::units::turns_per_second_t velocity,
170 wpi::units::newton_t feedforwardForce);
171
181 void SetVelocity(wpi::units::meters_per_second_t velocity, wpi::units::newton_t feedforwardForce);
182
183 // ---- Encoder writes -----------------------------------------------------
184
190 virtual void SetEncoderPosition(wpi::units::turn_t angle) = 0;
191
197 virtual void SetEncoderPosition(wpi::units::meter_t distance) = 0;
198
204 virtual void SetEncoderVelocity(wpi::units::turns_per_second_t velocity) = 0;
205
211 virtual void SetEncoderVelocity(wpi::units::meters_per_second_t velocity) = 0;
212
213 // ---- Encoder reads ------------------------------------------------------
214
222 virtual wpi::units::turn_t GetMechanismPosition() = 0;
223
231 virtual wpi::units::turns_per_second_t GetMechanismVelocity() = 0;
232
239 virtual wpi::units::turn_t GetRelativeMechanismPosition() = 0;
240
247 virtual wpi::units::turns_per_second_t GetRelativeMechanismVelocity() = 0;
248
254 virtual wpi::units::turns_per_second_squared_t GetMechanismAcceleration() = 0;
255
261 virtual wpi::units::turn_t GetRotorPosition() = 0;
262
268 virtual wpi::units::turns_per_second_t GetRotorVelocity() = 0;
269
275 virtual wpi::units::meter_t GetMeasurementPosition() = 0;
276
282 virtual wpi::units::meters_per_second_t GetMeasurementVelocity() = 0;
283
289 virtual wpi::units::meters_per_second_squared_t GetMeasurementAcceleration() = 0;
290
297 virtual std::optional<wpi::units::turn_t> GetExternalEncoderMechanismPosition() = 0;
298
306 virtual std::optional<wpi::units::turns_per_second_t> GetExternalEncoderMechanismVelocity() = 0;
307
308 // ---- Motor status -------------------------------------------------------
309
315 virtual std::optional<wpi::units::ampere_t> GetSupplyCurrent() = 0;
316
322 virtual wpi::units::ampere_t GetStatorCurrent() = 0;
323
329 virtual wpi::units::celsius_t GetTemperature() = 0;
330
336 virtual wpi::math::DCMotor GetDCMotor() = 0;
337
338 // ---- Configuration setters (live tuning) --------------------------------
339
345 virtual void SetZeroPower(MotorMode mode) = 0;
346
352 virtual void SetMotorInverted(bool inverted) = 0;
353
359 virtual void SetEncoderInverted(bool inverted) = 0;
360
366 virtual void SetKp(double kP) = 0;
367
373 virtual void SetKi(double kI) = 0;
374
380 virtual void SetKd(double kD) = 0;
381
389 virtual void SetFeedback(double kP, double kI, double kD) = 0;
390
396 virtual void SetKs(double kS) = 0;
397
403 virtual void SetKv(double kV) = 0;
404
410 virtual void SetKa(double kA) = 0;
411
417 virtual void SetKg(double kG) = 0;
418
427 virtual void SetFeedforward(double kS, double kV, double kA, double kG) = 0;
428
434 virtual void SetStatorCurrentLimit(wpi::units::ampere_t currentLimit) = 0;
435
441 virtual void SetSupplyCurrentLimit(wpi::units::ampere_t currentLimit) = 0;
442
448 virtual void SetClosedLoopRampRate(wpi::units::second_t rampRate) = 0;
449
455 virtual void SetOpenLoopRampRate(wpi::units::second_t rampRate) = 0;
456
462 virtual void SetMechanismUpperLimit(wpi::units::turn_t upperLimit) = 0;
463
469 virtual void SetMechanismLowerLimit(wpi::units::turn_t lowerLimit) = 0;
470
477 virtual void SetMechanismLimits(wpi::units::turn_t lower, wpi::units::turn_t upper) = 0;
478
484 virtual void SetMechanismLimitsEnabled(bool enabled) = 0;
485
491 virtual void SetMeasurementUpperLimit(wpi::units::meter_t upperLimit) = 0;
492
498 virtual void SetMeasurementLowerLimit(wpi::units::meter_t lowerLimit) = 0;
499
505 virtual void SetMotionProfileMaxVelocity(wpi::units::turns_per_second_t maxVelocity) = 0;
506
512 virtual void SetMotionProfileMaxVelocity(wpi::units::meters_per_second_t maxVelocity) = 0;
513
519 virtual void SetMotionProfileMaxAcceleration(wpi::units::turns_per_second_squared_t maxAcc) = 0;
520
526 virtual void SetMotionProfileMaxAcceleration(wpi::units::meters_per_second_squared_t maxAcc) = 0;
527
534 wpi::units::angular_jerk::turns_per_second_cubed_t maxJerk) = 0;
535
543 virtual void SetExponentialProfile(std::optional<double> kV, std::optional<double> kA,
544 std::optional<wpi::units::volt_t> maxInput) = 0;
545
552
561 virtual void SetMechanismGearing(const gearing::MechanismGearing& gearing);
562
571 virtual void SetMechanismCircumference(wpi::units::meter_t circumference);
572
573 // ---- Closed-loop controller thread --------------------------------------
574
583 wpi::units::second_t GetClosedLoopControllerPeriod() const;
584
593 virtual std::optional<wpi::units::second_t> GetVelocityMeasurementDelay() const;
594
597
603
606
607 // ---- Telemetry ----------------------------------------------------------
608
615 void SetupTelemetry(std::shared_ptr<wpi::nt::NetworkTable> dataTable,
616 std::shared_ptr<wpi::nt::NetworkTable> tuningTable);
617
620
627
636
642 bool TuningEnabled() const;
643
650
656
663 const std::vector<SmartMotorController*>& GetLooselyCoupledFollowers() const {
664 return m_looseFollowers;
665 }
666
673 void AddCloseHook(std::function<void()> hook);
674
685
695
702
703 // ---- Misc ---------------------------------------------------------------
704
710 std::optional<wpi::units::turn_t> GetMechanismPositionSetpoint() const;
711
717 std::optional<wpi::units::turns_per_second_t> GetMechanismSetpointVelocity() const;
718
726 std::optional<wpi::units::meter_t> GetMeasurementPositionSetpoint() const;
727
735 std::optional<wpi::units::meters_per_second_t> GetMeasurementSetpointVelocity() const;
736
742 std::optional<wpi::units::newton_t> GetSetpointFeedforwardForce() const;
743
750
756 virtual void* GetMotorController() = 0;
757
763 virtual void* GetMotorControllerConfig() = 0;
764
770 std::string GetName() const;
771
779 bool IsMotor(const wpi::math::DCMotor& a, const wpi::math::DCMotor& b) const;
780
783
789 void Close();
790
791 protected:
797 ClosedLoopControllerSlot m_slot{ClosedLoopControllerSlot::SLOT_0};
798 std::shared_ptr<SimSupplier> m_simSupplier;
799
801 std::vector<SmartMotorController*> m_looseFollowers;
802
808
817
822 void ForwardPositionToFollowers(wpi::units::turn_t pos);
823
828 void ForwardPositionToFollowers(wpi::units::meter_t dist);
829
834 void ForwardVelocityToFollowers(wpi::units::turns_per_second_t vel);
835
840 void ForwardVelocityToFollowers(wpi::units::meters_per_second_t vel);
841
842 std::optional<wpi::math::PIDController> m_pid;
843 std::optional<math::LQRController> m_lqr;
844
845 // Angular motion profile state
846 std::optional<wpi::math::TrapezoidProfile<wpi::units::turns>::State> m_trapState;
847 std::optional<wpi::math::ExponentialProfile<wpi::units::turns, wpi::units::volts>::State>
849
850 // Linear motion profile state
851 std::optional<wpi::math::TrapezoidProfile<wpi::units::meters>::State> m_linearTrapState;
852 std::optional<wpi::math::ExponentialProfile<wpi::units::meters, wpi::units::volts>::State>
854
859 std::optional<wpi::units::turn_t> m_lastClosedLoopMechanismPosition;
860
861 std::optional<wpi::units::turn_t> m_setpointPosition;
862 std::optional<wpi::units::turns_per_second_t> m_setpointVelocity;
864 std::optional<wpi::units::newton_t> m_setpointFeedforwardForce;
865
867 std::vector<std::function<void()>> m_closeHooks;
868
875 const void* BatterySimKey() const { return this; }
876
877 std::unique_ptr<wpi::Notifier> m_closedLoopControllerThread;
879
880 std::shared_ptr<wpi::nt::NetworkTable> m_parentTable;
881 std::shared_ptr<wpi::nt::NetworkTable> m_telemetryTable;
882 std::shared_ptr<wpi::nt::NetworkTable> m_tuningTable;
883
888 std::shared_ptr<telemetry::SmartMotorControllerTelemetryConfig> m_specifiedTelemetryConfig;
890 bool m_closed{false};
891
892 private:
894 void ResetProfileStates();
895};
896
897} // namespace yams::motorcontrollers
Definition MechanismGearing.hpp:19
Definition SimSupplier.hpp:22
Definition SmartMotorControllerConfig.hpp:65
ControlMode
Definition SmartMotorControllerConfig.hpp:68
ClosedLoopControllerSlot
Definition SmartMotorControllerConfig.hpp:74
MotorMode
Definition SmartMotorControllerConfig.hpp:70
Definition SmartMotorController.hpp:48
ClosedLoopControllerSlot m_slot
Definition SmartMotorController.hpp:797
std::optional< wpi::units::turn_t > m_lastClosedLoopMechanismPosition
Definition SmartMotorController.hpp:859
virtual wpi::units::celsius_t GetTemperature()=0
virtual void SetMeasurementUpperLimit(wpi::units::meter_t upperLimit)=0
virtual wpi::units::meters_per_second_t GetMeasurementVelocity()=0
virtual void SetMeasurementLowerLimit(wpi::units::meter_t lowerLimit)=0
std::optional< wpi::math::PIDController > m_pid
Definition SmartMotorController.hpp:842
std::optional< wpi::units::turns_per_second_t > m_setpointVelocity
Definition SmartMotorController.hpp:862
virtual void SetClosedLoopSlot(ClosedLoopControllerSlot slot)=0
std::shared_ptr< wpi::nt::NetworkTable > m_tuningTable
Definition SmartMotorController.hpp:882
virtual void SetMechanismLimits(wpi::units::turn_t lower, wpi::units::turn_t upper)=0
void SetupTelemetry(std::shared_ptr< wpi::nt::NetworkTable > dataTable, std::shared_ptr< wpi::nt::NetworkTable > tuningTable)
std::optional< wpi::math::ExponentialProfile< wpi::units::turns, wpi::units::volts >::State > m_expoState
Definition SmartMotorController.hpp:848
virtual wpi::units::turn_t GetRotorPosition()=0
virtual void SetOpenLoopRampRate(wpi::units::second_t rampRate)=0
SmartMotorControllerConfig * m_config
Definition SmartMotorController.hpp:796
virtual void SetVoltage(wpi::units::volt_t voltage)=0
std::shared_ptr< wpi::nt::NetworkTable > m_telemetryTable
Definition SmartMotorController.hpp:881
virtual wpi::units::turns_per_second_t GetRotorVelocity()=0
void ConfigureSoftwarePID(const SmartMotorControllerConfig &config)
bool IsMotor(const wpi::math::DCMotor &a, const wpi::math::DCMotor &b) const
virtual SmartMotorControllerConfig & GetConfig()=0
std::shared_ptr< wpi::nt::NetworkTable > m_parentTable
Definition SmartMotorController.hpp:880
SmartMotorController & WithTelemetry(telemetry::SmartMotorControllerTelemetryConfig config)
virtual void SetMechanismGearing(const gearing::MechanismGearing &gearing)
virtual void SetSupplyCurrentLimit(wpi::units::ampere_t currentLimit)=0
bool m_telemetryConfigExplicit
Definition SmartMotorController.hpp:886
void ForwardVelocityToFollowers(wpi::units::turns_per_second_t vel)
virtual wpi::units::turns_per_second_squared_t GetMechanismAcceleration()=0
virtual wpi::units::ampere_t GetStatorCurrent()=0
void AddCloseHook(std::function< void()> hook)
virtual void SetMotionProfileMaxAcceleration(wpi::units::turns_per_second_squared_t maxAcc)=0
virtual telemetry::UnsupportedTelemetryFields GetUnsupportedTelemetryFields()
std::optional< wpi::math::TrapezoidProfile< wpi::units::turns >::State > m_trapState
Definition SmartMotorController.hpp:846
virtual void SetClosedLoopRampRate(wpi::units::second_t rampRate)=0
std::optional< wpi::units::newton_t > m_setpointFeedforwardForce
Definition SmartMotorController.hpp:864
virtual void SetEncoderVelocity(wpi::units::meters_per_second_t velocity)=0
bool m_closed
Definition SmartMotorController.hpp:890
bool m_liveTuningRegistered
Definition SmartMotorController.hpp:889
virtual wpi::units::meters_per_second_squared_t GetMeasurementAcceleration()=0
virtual wpi::units::volt_t GetVoltage()=0
telemetry::SmartMotorControllerTelemetry m_telemetry
Definition SmartMotorController.hpp:884
virtual void SetMotionProfileMaxVelocity(wpi::units::meters_per_second_t maxVelocity)=0
void SetVelocity(wpi::units::meters_per_second_t velocity, wpi::units::newton_t feedforwardForce)
virtual void SetEncoderPosition(wpi::units::meter_t distance)=0
virtual void SetMechanismLowerLimit(wpi::units::turn_t lowerLimit)=0
virtual std::optional< wpi::units::turn_t > GetExternalEncoderMechanismPosition()=0
std::optional< wpi::math::TrapezoidProfile< wpi::units::meters >::State > m_linearTrapState
Definition SmartMotorController.hpp:851
virtual std::optional< wpi::units::second_t > GetVelocityMeasurementDelay() const
virtual void SetMechanismLimitsEnabled(bool enabled)=0
virtual std::optional< wpi::units::ampere_t > GetSupplyCurrent()=0
virtual void SetZeroPower(MotorMode mode)=0
virtual wpi::units::turns_per_second_t GetRelativeMechanismVelocity()=0
virtual void SetMotionProfileMaxJerk(wpi::units::angular_jerk::turns_per_second_cubed_t maxJerk)=0
virtual void SetEncoderVelocity(wpi::units::turns_per_second_t velocity)=0
void ForwardVelocityToFollowers(wpi::units::meters_per_second_t vel)
virtual void SetMotionProfileMaxAcceleration(wpi::units::meters_per_second_squared_t maxAcc)=0
virtual void SetVelocity(wpi::units::turns_per_second_t velocity, wpi::units::newton_t feedforwardForce)
virtual void SetMechanismUpperLimit(wpi::units::turn_t upperLimit)=0
ClosedLoopControllerSlot GetClosedLoopControllerSlot() const
bool m_closedLoopControllerRunning
Definition SmartMotorController.hpp:878
std::optional< wpi::units::newton_t > GetSetpointFeedforwardForce() const
const std::vector< SmartMotorController * > & GetLooselyCoupledFollowers() const
Definition SmartMotorController.hpp:663
virtual void SetVelocity(wpi::units::turns_per_second_t velocity)=0
virtual wpi::units::meter_t GetMeasurementPosition()=0
std::optional< wpi::units::meters_per_second_t > GetMeasurementSetpointVelocity() const
virtual wpi::units::turns_per_second_t GetMechanismVelocity()=0
virtual void SetMotionProfileMaxVelocity(wpi::units::turns_per_second_t maxVelocity)=0
virtual void SetPosition(wpi::units::turn_t angle)=0
std::optional< wpi::units::turn_t > GetMechanismPositionSetpoint() const
virtual void SetMechanismCircumference(wpi::units::meter_t circumference)
std::vector< std::function< void()> > m_closeHooks
Definition SmartMotorController.hpp:867
virtual void SetExponentialProfile(std::optional< double > kV, std::optional< double > kA, std::optional< wpi::units::volt_t > maxInput)=0
void ForwardPositionToFollowers(wpi::units::meter_t dist)
std::optional< wpi::units::turn_t > m_setpointPosition
Definition SmartMotorController.hpp:861
std::vector< SmartMotorController * > m_looseFollowers
Definition SmartMotorController.hpp:801
virtual void SetEncoderPosition(wpi::units::turn_t angle)=0
virtual void SetDutyCycle(double dutyCycle)=0
virtual void SetStatorCurrentLimit(wpi::units::ampere_t currentLimit)=0
virtual wpi::units::turn_t GetMechanismPosition()=0
virtual wpi::units::turn_t GetRelativeMechanismPosition()=0
std::optional< wpi::math::ExponentialProfile< wpi::units::meters, wpi::units::volts >::State > m_linearExpoState
Definition SmartMotorController.hpp:853
virtual bool ApplyConfig(const SmartMotorControllerConfig &config)=0
void ForwardPositionToFollowers(wpi::units::turn_t pos)
virtual wpi::math::DCMotor GetDCMotor()=0
std::optional< wpi::units::turns_per_second_t > GetMechanismSetpointVelocity() const
virtual void SetMotorInverted(bool inverted)=0
wpi::units::second_t GetClosedLoopControllerPeriod() const
virtual void SetEncoderInverted(bool inverted)=0
void SetSimSupplier(std::shared_ptr< SimSupplier > supplier)
const void * BatterySimKey() const
Definition SmartMotorController.hpp:875
std::shared_ptr< telemetry::SmartMotorControllerTelemetryConfig > m_specifiedTelemetryConfig
Definition SmartMotorController.hpp:888
std::optional< math::LQRController > m_lqr
Definition SmartMotorController.hpp:843
virtual void SetVelocity(wpi::units::meters_per_second_t velocity)=0
virtual std::optional< wpi::units::turns_per_second_t > GetExternalEncoderMechanismVelocity()=0
std::shared_ptr< SimSupplier > m_simSupplier
Definition SmartMotorController.hpp:798
std::unique_ptr< wpi::Notifier > m_closedLoopControllerThread
Definition SmartMotorController.hpp:877
virtual void SetPosition(wpi::units::meter_t distance)=0
std::optional< wpi::units::meter_t > GetMeasurementPositionSetpoint() const
virtual void SetFeedforward(double kS, double kV, double kA, double kG)=0
virtual void SetFeedback(double kP, double kI, double kD)=0
telemetry::SmartMotorControllerTelemetryConfig m_telemetryConfig
Definition SmartMotorController.hpp:885
Definition SmartMotorControllerTelemetryConfig.hpp:63
Definition SmartMotorControllerTelemetry.hpp:543
Definition SimSensorConfig.hpp:15
Definition SmartMotorControllerTelemetry.hpp:107