CTRE Phoenix 6 C++ 25.1.0
Loading...
Searching...
No Matches
SimSwerveDrivetrain.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) Cross The Road Electronics.  All rights reserved.
3 * License information can be found in CTRE_LICENSE.txt
4 * For support and suggestions contact support@ctr-electronics.com or file
5 * an issue tracker at https://github.com/CrossTheRoadElec/Phoenix-Releases
6 */
7#pragma once
8
12#include <frc/simulation/DCMotorSim.h>
13#include <frc/system/plant/LinearSystemId.h>
14
15namespace ctre {
16namespace phoenix6 {
17namespace swerve {
18
19/**
20 * \brief Simplified swerve drive simulation class.
21 *
22 * This class assumes that the swerve drive is perfect, meaning
23 * that there is no scrub and the wheels do not slip.
24 *
25 * In addition, it assumes the inertia of the robot is governed only
26 * by the inertia of the steer module and the individual drive wheels.
27 * Robot-wide inertia is not accounted for, and neither is translational
28 * vs rotational inertia of the robot.
29 *
30 * These assumptions provide a simplified example that can demonstrate the
31 * behavior of a swerve drive in simulation. Users are encouraged to
32 * expand this model for their own use.
33 */
35protected:
37 public:
38 /** \brief Reference to motor simulation for drive motor */
39 frc::sim::DCMotorSim DriveMotor;
40 /** \brief Reference to motor simulation for the steer motor */
41 frc::sim::DCMotorSim SteerMotor;
42 /** \brief Reference to steer gearing for updating encoder */
43 units::scalar_t DriveGearing;
44 /** \brief Reference to steer gearing for updating encoder */
45 units::scalar_t SteerGearing;
46 /** \brief Voltage necessary for the drive motor to overcome friction */
47 units::volt_t DriveFrictionVoltage;
48 /** \brief Voltage necessary for the steer motor to overcome friction */
49 units::volt_t SteerFrictionVoltage;
50 /** \brief Whether the drive motor is inverted */
52 /** \brief Whether the steer motor is inverted */
54 /** \brief Whether the azimuth encoder is inverted */
56
58 units::scalar_t driveGearing, units::kilogram_square_meter_t driveInertia,
59 units::volt_t driveFrictionVoltage, bool driveMotorInverted,
60 units::scalar_t steerGearing, units::kilogram_square_meter_t steerInertia,
61 units::volt_t steerFrictionVoltage, bool steerMotorInverted,
62 bool encoderInverted
63 ) :
64 DriveMotor{frc::LinearSystemId::DCMotorSystem(frc::DCMotor::KrakenX60FOC(1), driveInertia, driveGearing), frc::DCMotor::KrakenX60FOC(1)},
65 SteerMotor{frc::LinearSystemId::DCMotorSystem(frc::DCMotor::KrakenX60FOC(1), steerInertia, steerGearing), frc::DCMotor::KrakenX60FOC(1)},
66 DriveGearing{driveGearing},
67 SteerGearing{steerGearing},
68 DriveFrictionVoltage{driveFrictionVoltage},
69 SteerFrictionVoltage{steerFrictionVoltage},
70 DriveMotorInverted{driveMotorInverted},
71 SteerMotorInverted{steerMotorInverted},
72 EncoderInverted{encoderInverted}
73 {}
74 };
75
77 std::vector<SimSwerveModule> _modules;
78
80 Rotation2d _lastAngle{};
81
82public:
83 template <
84 typename... ModuleConstants,
85 typename = std::enable_if_t<std::conjunction_v<
86 std::is_same< ModuleConstants, SwerveModuleConstants<configs::TalonFXConfiguration, configs::TalonFXConfiguration, configs::CANcoderConfiguration> >...
87 >>
88 >
90 std::vector<Translation2d> wheelLocations,
91 sim::Pigeon2SimState &pigeonSim,
92 ModuleConstants const &... moduleConstants
93 ) :
94 _pigeonSim{pigeonSim},
97 moduleConstants.DriveMotorGearRatio,
98 moduleConstants.DriveInertia,
99 moduleConstants.DriveFrictionVoltage,
100 moduleConstants.DriveMotorInverted,
101 moduleConstants.SteerMotorGearRatio,
102 moduleConstants.SteerInertia,
103 moduleConstants.SteerFrictionVoltage,
104 moduleConstants.SteerMotorInverted,
105 moduleConstants.EncoderInverted
106 }...
107 },
108 _kinem{std::move(wheelLocations)}
109 {}
110
111 template <
112 typename DriveMotorT,
113 typename SteerMotorT,
114 typename EncoderT,
115 typename = std::enable_if_t<std::is_base_of_v<hardware::traits::CommonTalon, DriveMotorT>>,
116 typename = std::enable_if_t<std::is_base_of_v<hardware::traits::CommonTalon, SteerMotorT>>,
117 typename = std::enable_if_t<std::is_base_of_v<hardware::ParentDevice, EncoderT>>
118 >
119 void Update(
120 units::second_t dt,
121 units::volt_t supplyVoltage,
122 std::vector<std::unique_ptr<SwerveModule<DriveMotorT, SteerMotorT, EncoderT>>> const &modulesToApply
123 ) {
124 if (modulesToApply.size() != _modules.size()) return;
125
126 if constexpr (!(std::is_same_v<hardware::TalonFX, DriveMotorT> &&
127 std::is_same_v<hardware::TalonFX, SteerMotorT> &&
128 std::is_same_v<hardware::CANcoder, EncoderT>))
129 {
130 return;
131 }
132
133 std::vector<SwerveModuleState> states(modulesToApply.size());
134 /* update our sim devices */
135 for (size_t i = 0; i < modulesToApply.size(); ++i) {
136 sim::TalonFXSimState &driveMotor = modulesToApply[i]->GetDriveMotor().GetSimState();
137 sim::TalonFXSimState &steerMotor = modulesToApply[i]->GetSteerMotor().GetSimState();
138 sim::CANcoderSimState &encoder = modulesToApply[i]->GetEncoder().GetSimState();
139
143
144 driveMotor.SetSupplyVoltage(supplyVoltage);
145 steerMotor.SetSupplyVoltage(supplyVoltage);
146 encoder.SetSupplyVoltage(supplyVoltage);
147
148 _modules[i].DriveMotor.SetInputVoltage(AddFriction(driveMotor.GetMotorVoltage(), _modules[i].DriveFrictionVoltage));
149 _modules[i].SteerMotor.SetInputVoltage(AddFriction(steerMotor.GetMotorVoltage(), _modules[i].SteerFrictionVoltage));
150
151 _modules[i].DriveMotor.Update(dt);
152 _modules[i].SteerMotor.Update(dt);
153
154 driveMotor.SetRawRotorPosition(_modules[i].DriveMotor.GetAngularPosition() * _modules[i].DriveGearing);
155 driveMotor.SetRotorVelocity(_modules[i].DriveMotor.GetAngularVelocity() * _modules[i].DriveGearing);
156
157 steerMotor.SetRawRotorPosition(_modules[i].SteerMotor.GetAngularPosition() * _modules[i].SteerGearing);
158 steerMotor.SetRotorVelocity(_modules[i].SteerMotor.GetAngularVelocity() * _modules[i].SteerGearing);
159
160 /* azimuth encoders see the mechanism, so don't account for the steer gearing */
161 encoder.SetRawPosition(_modules[i].SteerMotor.GetAngularPosition());
162 encoder.SetVelocity(_modules[i].SteerMotor.GetAngularVelocity());
163
164 states[i] = modulesToApply[i]->GetCurrentState();
165 }
166
167 auto const angularVel = _kinem.ToChassisSpeeds(states).omega;
168 _lastAngle = _lastAngle + Rotation2d{angularVel * dt};
171 }
172
173protected:
174 /**
175 * \brief Applies the effects of friction to dampen the motor voltage.
176 *
177 * \param motorVoltage Voltage output by the motor
178 * \param frictionVoltage Voltage required to overcome friction
179 * \returns Friction-dampened motor voltage
180 */
181 static units::volt_t AddFriction(units::volt_t motorVoltage, units::volt_t frictionVoltage)
182 {
183 if (units::math::abs(motorVoltage) < frictionVoltage) {
184 motorVoltage = 0_V;
185 } else if (motorVoltage > 0_V) {
186 motorVoltage -= frictionVoltage;
187 } else {
188 motorVoltage += frictionVoltage;
189 }
190 return motorVoltage;
191 }
192};
193
194}
195}
196}
Class to control the state of a simulated hardware::CANcoder.
Definition CANcoderSimState.hpp:32
ctre::phoenix::StatusCode SetSupplyVoltage(units::voltage::volt_t volts)
Sets the simulated supply voltage of the CANcoder.
ChassisReference Orientation
The orientation of the CANcoder relative to the robot chassis.
Definition CANcoderSimState.hpp:44
ctre::phoenix::StatusCode SetVelocity(units::angular_velocity::turns_per_second_t rps)
Sets the simulated velocity of the CANcoder.
ctre::phoenix::StatusCode SetRawPosition(units::angle::turn_t rotations)
Sets the simulated raw position of the CANcoder.
Class to control the state of a simulated hardware::Pigeon2.
Definition Pigeon2SimState.hpp:31
ctre::phoenix::StatusCode SetAngularVelocityZ(units::angular_velocity::degrees_per_second_t dps)
Sets the simulated angular velocity Z component of the Pigeon2.
ctre::phoenix::StatusCode SetRawYaw(units::angle::degree_t deg)
Sets the simulated raw yaw of the Pigeon2.
Class to control the state of a simulated hardware::TalonFX.
Definition TalonFXSimState.hpp:33
ctre::phoenix::StatusCode SetRawRotorPosition(units::angle::turn_t rotations)
Sets the simulated raw rotor position of the TalonFX.
units::voltage::volt_t GetMotorVoltage() const
Gets the simulated output voltage of the motor.
ctre::phoenix::StatusCode SetRotorVelocity(units::angular_velocity::turns_per_second_t rps)
Sets the simulated rotor velocity of the TalonFX.
ctre::phoenix::StatusCode SetSupplyVoltage(units::voltage::volt_t volts)
Sets the simulated supply voltage of the TalonFX.
ChassisReference Orientation
The orientation of the TalonFX relative to the robot chassis.
Definition TalonFXSimState.hpp:45
frc::sim::DCMotorSim DriveMotor
Reference to motor simulation for drive motor.
Definition SimSwerveDrivetrain.hpp:39
frc::sim::DCMotorSim SteerMotor
Reference to motor simulation for the steer motor.
Definition SimSwerveDrivetrain.hpp:41
units::volt_t DriveFrictionVoltage
Voltage necessary for the drive motor to overcome friction.
Definition SimSwerveDrivetrain.hpp:47
SimSwerveModule(units::scalar_t driveGearing, units::kilogram_square_meter_t driveInertia, units::volt_t driveFrictionVoltage, bool driveMotorInverted, units::scalar_t steerGearing, units::kilogram_square_meter_t steerInertia, units::volt_t steerFrictionVoltage, bool steerMotorInverted, bool encoderInverted)
Definition SimSwerveDrivetrain.hpp:57
bool SteerMotorInverted
Whether the steer motor is inverted.
Definition SimSwerveDrivetrain.hpp:53
units::volt_t SteerFrictionVoltage
Voltage necessary for the steer motor to overcome friction.
Definition SimSwerveDrivetrain.hpp:49
units::scalar_t SteerGearing
Reference to steer gearing for updating encoder.
Definition SimSwerveDrivetrain.hpp:45
bool EncoderInverted
Whether the azimuth encoder is inverted.
Definition SimSwerveDrivetrain.hpp:55
bool DriveMotorInverted
Whether the drive motor is inverted.
Definition SimSwerveDrivetrain.hpp:51
units::scalar_t DriveGearing
Reference to steer gearing for updating encoder.
Definition SimSwerveDrivetrain.hpp:43
Simplified swerve drive simulation class.
Definition SimSwerveDrivetrain.hpp:34
static units::volt_t AddFriction(units::volt_t motorVoltage, units::volt_t frictionVoltage)
Applies the effects of friction to dampen the motor voltage.
Definition SimSwerveDrivetrain.hpp:181
impl::SwerveDriveKinematics _kinem
Definition SimSwerveDrivetrain.hpp:79
sim::Pigeon2SimState & _pigeonSim
Definition SimSwerveDrivetrain.hpp:76
SimSwerveDrivetrain(std::vector< Translation2d > wheelLocations, sim::Pigeon2SimState &pigeonSim, ModuleConstants const &... moduleConstants)
Definition SimSwerveDrivetrain.hpp:89
std::vector< SimSwerveModule > _modules
Definition SimSwerveDrivetrain.hpp:77
Rotation2d _lastAngle
Definition SimSwerveDrivetrain.hpp:80
void Update(units::second_t dt, units::volt_t supplyVoltage, std::vector< std::unique_ptr< SwerveModule< DriveMotorT, SteerMotorT, EncoderT > > > const &modulesToApply)
Definition SimSwerveDrivetrain.hpp:119
Swerve Module class that encapsulates a swerve module powered by CTR Electronics devices.
Definition SwerveModule.hpp:39
Class that converts a chassis velocity (dx, dy, and dtheta components) into individual module states ...
Definition SwerveDriveKinematics.hpp:42
ChassisSpeeds ToChassisSpeeds(WheelSpeeds const &moduleStates) const
Performs forward kinematics to return the resulting chassis state from the given module states.
@ Clockwise_Positive
The device should read a clockwise rotation as positive motion.
@ CounterClockwise_Positive
The device should read a counter-clockwise rotation as positive motion.
Definition MotionMagicExpoTorqueCurrentFOC.hpp:18
Definition span.hpp:401