YAMS
Yet Another Mechanism System
Loading...
Searching...
No Matches
SparkWrapper.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 <rev/DetachedEncoder.h>
7#include <rev/RelativeEncoder.h>
8#include <rev/SparkAbsoluteEncoder.h>
9#include <rev/SparkClosedLoopController.h>
10#include <rev/SparkFlex.h>
11#include <rev/SparkFlexExternalEncoder.h>
12#include <rev/SparkMax.h>
13#include <rev/SparkMaxAlternateEncoder.h>
14#include <rev/SparkRelativeEncoder.h>
15#include <rev/SparkSim.h>
16#include <rev/config/SparkFlexConfig.h>
17#include <rev/config/SparkMaxConfig.h>
18#include <rev/sim/SparkAbsoluteEncoderSim.h>
19#include <rev/sim/SparkExternalEncoderSim.h>
20#include <rev/sim/SparkMaxAlternateEncoderSim.h>
21#include <rev/sim/SparkRelativeEncoderSim.h>
22
23#include <functional>
24#include <memory>
25#include <optional>
26#include <string>
27#include <wpi/math/trajectory/TrapezoidProfile.hpp>
28#include <wpi/simulation/DCMotorSim.hpp>
29#include <wpi/util/Alert.hpp>
30
33
35
95 public:
96 // Expose SetVelocity(velocity, feedforwardForce) from the base class alongside the overrides.
98
106 SparkWrapper(rev::spark::SparkMax* spark, wpi::math::DCMotor motor,
108
116 SparkWrapper(rev::spark::SparkFlex* spark, wpi::math::DCMotor motor,
119
120 // ---- Telemetry ----------------------------------------------------------
123
124 // ---- Configuration ------------------------------------------------------
126 bool ApplyConfig(const SmartMotorControllerConfig& config) override;
127
128 // ---- Simulation ---------------------------------------------------------
130 void SetupSimulation() override;
132 void SimIterate() override;
133
134 // ---- Encoder sync -------------------------------------------------------
136 void SeedRelativeEncoder() override;
139
140 // ---- Open-loop outputs --------------------------------------------------
142 void SetDutyCycle(double dutyCycle) override;
144 double GetDutyCycle() override;
146 void SetVoltage(wpi::units::volt_t voltage) override;
148 wpi::units::volt_t GetVoltage() override;
154 std::optional<wpi::units::second_t> GetVelocityMeasurementDelay() const override;
155
156 // ---- Closed-loop setpoints ----------------------------------------------
158 void SetPosition(wpi::units::turn_t angle) override;
165 void SetPosition(wpi::units::meter_t distance) override;
167 void SetVelocity(wpi::units::turns_per_second_t velocity) override;
175 void SetVelocity(wpi::units::turns_per_second_t velocity,
176 wpi::units::newton_t feedforwardForce) override;
183 void SetVelocity(wpi::units::meters_per_second_t velocity) override;
184
185 // ---- Encoder writes -----------------------------------------------------
187 void SetEncoderPosition(wpi::units::turn_t angle) override;
194 void SetEncoderPosition(wpi::units::meter_t distance) override;
201 void SetEncoderVelocity(wpi::units::turns_per_second_t velocity) override;
208 void SetEncoderVelocity(wpi::units::meters_per_second_t velocity) override;
209
210 // ---- Encoder reads ------------------------------------------------------
212 wpi::units::turn_t GetMechanismPosition() override;
214 wpi::units::turns_per_second_t GetMechanismVelocity() override;
216 wpi::units::turn_t GetRelativeMechanismPosition() override;
218 wpi::units::turns_per_second_t GetRelativeMechanismVelocity() override;
220 wpi::units::turns_per_second_squared_t GetMechanismAcceleration() override;
222 wpi::units::turn_t GetRotorPosition() override;
224 wpi::units::turns_per_second_t GetRotorVelocity() override;
226 wpi::units::meter_t GetMeasurementPosition() override;
228 wpi::units::meters_per_second_t GetMeasurementVelocity() override;
230 wpi::units::meters_per_second_squared_t GetMeasurementAcceleration() override;
232 std::optional<wpi::units::turn_t> GetExternalEncoderMechanismPosition() override;
234 std::optional<wpi::units::turns_per_second_t> GetExternalEncoderMechanismVelocity() override;
235
236 // ---- Motor status -------------------------------------------------------
238 std::optional<wpi::units::ampere_t> GetSupplyCurrent() override;
240 wpi::units::ampere_t GetStatorCurrent() override;
242 wpi::units::celsius_t GetTemperature() override;
244 wpi::math::DCMotor GetDCMotor() override;
245
246 // ---- Configuration setters (live tuning) --------------------------------
248 void SetZeroPower(MotorMode mode) override;
250 void SetMotorInverted(bool inverted) override;
252 void SetEncoderInverted(bool inverted) override;
254 void SetKp(double kP) override;
256 void SetKi(double kI) override;
258 void SetKd(double kD) override;
260 void SetFeedback(double kP, double kI, double kD) override;
262 void SetKs(double kS) override;
264 void SetKv(double kV) override;
266 void SetKa(double kA) override;
275 void SetKg(double kG) override;
277 void SetFeedforward(double kS, double kV, double kA, double kG) override;
279 void SetStatorCurrentLimit(wpi::units::ampere_t currentLimit) override;
281 void SetSupplyCurrentLimit(wpi::units::ampere_t currentLimit) override;
283 void SetClosedLoopRampRate(wpi::units::second_t rampRate) override;
285 void SetOpenLoopRampRate(wpi::units::second_t rampRate) override;
287 void SetMechanismUpperLimit(wpi::units::turn_t upperLimit) override;
289 void SetMechanismLowerLimit(wpi::units::turn_t lowerLimit) override;
291 void SetMechanismLimits(wpi::units::turn_t lower, wpi::units::turn_t upper) override;
293 void SetMechanismLimitsEnabled(bool enabled) override;
303 void SetMeasurementUpperLimit(wpi::units::meter_t upperLimit) override;
313 void SetMeasurementLowerLimit(wpi::units::meter_t lowerLimit) override;
315 void SetMotionProfileMaxVelocity(wpi::units::turns_per_second_t maxVelocity) override;
322 void SetMotionProfileMaxVelocity(wpi::units::meters_per_second_t maxVelocity) override;
324 void SetMotionProfileMaxAcceleration(wpi::units::turns_per_second_squared_t maxAcc) override;
332 void SetMotionProfileMaxAcceleration(wpi::units::meters_per_second_squared_t maxAcc) override;
339 void SetMotionProfileMaxJerk(wpi::units::angular_jerk::turns_per_second_cubed_t maxJerk) override;
344 void SetExponentialProfile(std::optional<double> kV, std::optional<double> kA,
345 std::optional<wpi::units::volt_t> maxInput) override;
354 void SetMechanismGearing(const gearing::MechanismGearing& gearing) override;
360 void SetMechanismCircumference(wpi::units::meter_t circumference) override;
361
369 void* GetMotorController() override;
375 void* GetMotorControllerConfig() override;
376
377 private:
378 rev::spark::SparkBase* m_spark{nullptr};
379 rev::spark::SparkClosedLoopController* m_sparkPid{nullptr};
380 rev::spark::SparkRelativeEncoder* m_relEncoder{nullptr};
382 rev::spark::SparkAbsoluteEncoder* m_absEncoder{nullptr};
384 rev::RelativeEncoder* m_quadratureEncoder{nullptr};
386 rev::detached::DetachedEncoder* m_detachedEncoder{nullptr};
388 double m_detachedEncoderZeroOffset{0.0};
390 double m_absEncoderZeroOffset{0.0};
395 wpi::units::turn_t m_absoluteEncoderDiscontinuityPoint{1.0};
397 wpi::units::turn_t m_detachedEncoderSimAngle{0.0};
398 wpi::math::DCMotor m_motor;
399
400 // SparkMaxConfig and SparkFlexConfig are non-copyable/non-movable;
401 // exactly one will be constructed via emplace().
402 std::optional<rev::spark::SparkMaxConfig> m_maxConfig;
403 std::optional<rev::spark::SparkFlexConfig> m_flexConfig;
404
405 std::optional<wpi::sim::DCMotorSim> m_motorSim;
406 std::optional<rev::spark::SparkSim> m_sparkSim;
407 std::optional<rev::spark::SparkRelativeEncoderSim> m_relEncoderSim;
408 std::optional<rev::spark::SparkAbsoluteEncoderSim> m_absEncoderSim;
409 std::optional<rev::spark::SparkMaxAlternateEncoderSim> m_altEncoderSim;
410 std::optional<rev::spark::SparkExternalEncoderSim> m_extEncoderSim;
411 math::DerivativeTimeFilter m_accelFilter{20_ms};
412
417 double m_mechanismToFeedbackSensorRatio{1.0};
419 bool m_velocityGainsApplied{false};
421 std::optional<wpi::math::TrapezoidProfile<wpi::units::turns>::State> m_simMaxMotionState;
422
423 rev::spark::SparkLowLevel::ControlType m_positionControlType{
424 rev::spark::SparkLowLevel::ControlType::kPosition};
425 rev::spark::SparkLowLevel::ControlType m_velocityControlType{
426 rev::spark::SparkLowLevel::ControlType::kVelocity};
427
428 rev::spark::ClosedLoopSlot m_closedLoopSlot{rev::spark::ClosedLoopSlot::kSlot0};
429
430 std::optional<wpi::util::Alert> m_rioControllerAlert;
432 std::optional<wpi::util::Alert> m_externalEncoderGearingDiscontinuityAlert;
434 std::optional<wpi::util::Alert> m_feedbackNotAppliedAlert;
437 std::optional<wpi::units::second_t> m_velocityMeasurementDelay;
439 wpi::units::second_t m_velocitySignalPeriod{0.02};
441 std::optional<wpi::util::Alert> m_feedforwardNotAppliedAlert;
442
443 void Init(rev::spark::SparkBase* spark, wpi::math::DCMotor motor,
444 SmartMotorControllerConfig* config);
446 rev::spark::SparkBaseConfig& SparkConfig();
448 bool ConfigureSpark(const std::function<rev::REVLibError()>& call,
449 wpi::units::second_t retryFor = wpi::units::second_t{0.015});
450
459 bool ConfigureSpark(rev::spark::SparkBaseConfig& config);
460
468 bool ConfigureSpark(rev::spark::ClosedLoopConfig& closedLoop);
469
477 bool ConfigureSpark(rev::spark::FeedForwardConfig& feedForward);
479 rev::PersistMode PersistModeForState() const;
481 void ConfigureAsync();
483 std::string AlertId(const std::string& alertType) const;
485 void ApplyFeedback(double kP, double kI, double kD);
487 double MechanismToExternalEncoderRatio() const;
489 void UpdateFeedbackSensorRatio(const SmartMotorControllerConfig& config);
491 void WriteSparkPID(double kP, double kI, double kD, rev::spark::ClosedLoopSlot slot);
493 void WriteSparkFeedforward(double kS, double kV, double kA, rev::spark::ClosedLoopSlot slot);
495 void WriteSlotGains(const SmartMotorControllerConfig& config, ClosedLoopControllerSlot slot);
497 void WriteMotionProfile(const SmartMotorControllerConfig& config);
499 void WriteClosedLoopTolerance(const SmartMotorControllerConfig& config);
501 void WriteSoftLimits(const SmartMotorControllerConfig& config);
503 void RewriteScaledParameters();
505 void UseVelocityGains(bool velocity);
507 void ApplyExternalEncoder(const SmartMotorControllerConfig& config, bool useExternalEncoder);
509 std::optional<wpi::units::turn_t> GetExternalEncoderSensorPosition();
511 std::optional<wpi::units::turns_per_second_t> GetExternalEncoderSensorVelocity();
513 void IterateSimulatedMaxMotionPosition();
518 void IterateSimulatedArmGravity();
520 bool SimulatingMaxMotion() const;
522 bool HasExponentialProfile() const;
523};
524
525} // namespace yams::motorcontrollers::local
Definition MechanismGearing.hpp:19
Definition SmartMotorControllerConfig.hpp:65
ClosedLoopControllerSlot
Definition SmartMotorControllerConfig.hpp:74
MotorMode
Definition SmartMotorControllerConfig.hpp:70
Definition SmartMotorController.hpp:48
SmartMotorControllerConfig::ClosedLoopControllerSlot ClosedLoopControllerSlot
Definition SmartMotorController.hpp:50
virtual void SetVelocity(wpi::units::turns_per_second_t velocity)=0
Definition SparkWrapper.hpp:94
SparkWrapper(rev::spark::SparkFlex *spark, wpi::math::DCMotor motor, SmartMotorControllerConfig *config)
wpi::units::turn_t GetRelativeMechanismPosition() override
void SetOpenLoopRampRate(wpi::units::second_t rampRate) override
void SetEncoderVelocity(wpi::units::meters_per_second_t velocity) override
void SetEncoderVelocity(wpi::units::turns_per_second_t velocity) override
void SetVelocity(wpi::units::turns_per_second_t velocity) override
void SetExponentialProfile(std::optional< double > kV, std::optional< double > kA, std::optional< wpi::units::volt_t > maxInput) override
void SetMeasurementUpperLimit(wpi::units::meter_t upperLimit) override
SmartMotorControllerConfig & GetConfig() override
void SetVoltage(wpi::units::volt_t voltage) override
wpi::units::meter_t GetMeasurementPosition() override
void SetClosedLoopSlot(ClosedLoopControllerSlot slot) override
void SetPosition(wpi::units::turn_t angle) override
wpi::units::turns_per_second_t GetRotorVelocity() override
void SetMechanismGearing(const gearing::MechanismGearing &gearing) override
std::optional< wpi::units::second_t > GetVelocityMeasurementDelay() const override
void SetMechanismLowerLimit(wpi::units::turn_t lowerLimit) override
void SetMechanismLimits(wpi::units::turn_t lower, wpi::units::turn_t upper) override
wpi::units::celsius_t GetTemperature() override
std::optional< wpi::units::ampere_t > GetSupplyCurrent() override
void SetClosedLoopRampRate(wpi::units::second_t rampRate) override
void SetMotionProfileMaxAcceleration(wpi::units::meters_per_second_squared_t maxAcc) override
void SetMotionProfileMaxJerk(wpi::units::angular_jerk::turns_per_second_cubed_t maxJerk) override
std::optional< wpi::units::turns_per_second_t > GetExternalEncoderMechanismVelocity() override
wpi::units::volt_t GetVoltage() override
wpi::units::meters_per_second_t GetMeasurementVelocity() override
void SetEncoderPosition(wpi::units::meter_t distance) override
void SetMotionProfileMaxAcceleration(wpi::units::turns_per_second_squared_t maxAcc) override
void SetEncoderInverted(bool inverted) override
void SetMechanismCircumference(wpi::units::meter_t circumference) override
wpi::units::turns_per_second_t GetRelativeMechanismVelocity() override
void SetFeedback(double kP, double kI, double kD) override
wpi::units::turn_t GetMechanismPosition() override
void SetDutyCycle(double dutyCycle) override
telemetry::UnsupportedTelemetryFields GetUnsupportedTelemetryFields() override
wpi::units::turns_per_second_squared_t GetMechanismAcceleration() override
bool ApplyConfig(const SmartMotorControllerConfig &config) override
void SetZeroPower(MotorMode mode) override
void SetEncoderPosition(wpi::units::turn_t angle) override
std::optional< wpi::units::turn_t > GetExternalEncoderMechanismPosition() override
void SetVelocity(wpi::units::meters_per_second_t velocity) override
void SetStatorCurrentLimit(wpi::units::ampere_t currentLimit) override
void SetSupplyCurrentLimit(wpi::units::ampere_t currentLimit) override
void SetVelocity(wpi::units::turns_per_second_t velocity, wpi::units::newton_t feedforwardForce) override
wpi::units::meters_per_second_squared_t GetMeasurementAcceleration() override
void SetMechanismLimitsEnabled(bool enabled) override
wpi::math::DCMotor GetDCMotor() override
void SetMotionProfileMaxVelocity(wpi::units::turns_per_second_t maxVelocity) override
void SetMechanismUpperLimit(wpi::units::turn_t upperLimit) override
wpi::units::turns_per_second_t GetMechanismVelocity() override
void SetPosition(wpi::units::meter_t distance) override
void SetMotionProfileMaxVelocity(wpi::units::meters_per_second_t maxVelocity) override
void SetFeedforward(double kS, double kV, double kA, double kG) override
wpi::units::ampere_t GetStatorCurrent() override
void SetMotorInverted(bool inverted) override
void SetMeasurementLowerLimit(wpi::units::meter_t lowerLimit) override
SparkWrapper(rev::spark::SparkMax *spark, wpi::math::DCMotor motor, SmartMotorControllerConfig *config)
wpi::units::turn_t GetRotorPosition() override
Definition NovaWrapper.hpp:18
Definition SmartMotorControllerTelemetry.hpp:107