Skip to content

Commit a15526e

Browse files
Merge pull request #55 from 4201VitruvianBots/v1-drivetrain-setup
Merge V1Constants
2 parents d3101f8 + 15d35de commit a15526e

3 files changed

Lines changed: 318 additions & 4 deletions

File tree

src/main/java/frc/robot/RobotContainer.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
import frc.robot.commands.shooter.Shoot;
3232
import frc.robot.commands.shooter.ShootManualFlywheel;
3333
import frc.robot.constants.FIELD;
34-
import frc.robot.generated.WoodBotConstants;
34+
import frc.robot.generated.V1Constants;
3535
import frc.robot.simulation.Robot2d;
3636
import frc.robot.subsystems.*;
3737
import frc.robot.subsystems.Climber;
@@ -58,7 +58,7 @@ public class RobotContainer {
5858
@Logged(name = "Hood", importance = Logged.Importance.INFO)
5959
private Hood m_hood;
6060

61-
private CommandSwerveDrivetrain m_swerveDrive = WoodBotConstants.createDrivetrain();
61+
private CommandSwerveDrivetrain m_swerveDrive = V1Constants.createDrivetrain();
6262

6363
@Logged(name = "Intake", importance = Logged.Importance.INFO)
6464
private Intake m_intake;
@@ -94,7 +94,7 @@ public boolean isHubActive() {
9494

9595
@NotLogged
9696
private final double MaxSpeed =
97-
WoodBotConstants.kSpeedAt12Volts.in(MetersPerSecond); // kSpeed at 12 volts desired top speed
97+
V1Constants.kSpeedAt12Volts.in(MetersPerSecond); // kSpeed at 12 volts desired top speed
9898

9999
private Boolean m_flipToRight = false;
100100

Lines changed: 314 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,314 @@
1+
package frc.robot.generated;
2+
3+
import static edu.wpi.first.units.Units.*;
4+
5+
import com.ctre.phoenix6.CANBus;
6+
import com.ctre.phoenix6.configs.*;
7+
import com.ctre.phoenix6.hardware.*;
8+
import com.ctre.phoenix6.signals.*;
9+
import com.ctre.phoenix6.swerve.*;
10+
import com.ctre.phoenix6.swerve.SwerveModuleConstants.*;
11+
import edu.wpi.first.math.Matrix;
12+
import edu.wpi.first.math.numbers.N1;
13+
import edu.wpi.first.math.numbers.N3;
14+
import edu.wpi.first.units.measure.*;
15+
import frc.robot.subsystems.CommandSwerveDrivetrain;
16+
17+
// Generated by the 2026 Tuner X Swerve Project Generator
18+
// https://v6.docs.ctr-electronics.com/en/stable/docs/tuner/tuner-swerve/index.html
19+
public class V1Constants {
20+
// Both sets of gains need to be tuned to your individual robot.
21+
22+
// The steer motor uses any SwerveModule.SteerRequestType control request with the
23+
// output type specified by SwerveModuleConstants.SteerMotorClosedLoopOutput
24+
private static final Slot0Configs steerGains =
25+
new Slot0Configs()
26+
.withKP(100)
27+
.withKI(0)
28+
.withKD(0.5)
29+
.withKS(0.1)
30+
.withKV(2.49)
31+
.withKA(0)
32+
.withStaticFeedforwardSign(StaticFeedforwardSignValue.UseClosedLoopSign);
33+
// When using closed-loop control, the drive motor uses the control
34+
// output type specified by SwerveModuleConstants.DriveMotorClosedLoopOutput
35+
private static final Slot0Configs driveGains =
36+
new Slot0Configs().withKP(0.1).withKI(0).withKD(0).withKS(0).withKV(0.124);
37+
38+
// The closed-loop output type to use for the steer motors;
39+
// This affects the PID/FF gains for the steer motors
40+
private static final ClosedLoopOutputType kSteerClosedLoopOutput = ClosedLoopOutputType.Voltage;
41+
// The closed-loop output type to use for the drive motors;
42+
// This affects the PID/FF gains for the drive motors
43+
private static final ClosedLoopOutputType kDriveClosedLoopOutput = ClosedLoopOutputType.Voltage;
44+
45+
// The type of motor used for the drive motor
46+
private static final DriveMotorArrangement kDriveMotorType =
47+
DriveMotorArrangement.TalonFX_Integrated;
48+
// The type of motor used for the drive motor
49+
private static final SteerMotorArrangement kSteerMotorType =
50+
SteerMotorArrangement.TalonFX_Integrated;
51+
52+
// The remote sensor feedback type to use for the steer motors;
53+
// When not Pro-licensed, Fused*/Sync* automatically fall back to Remote*
54+
private static final SteerFeedbackType kSteerFeedbackType = SteerFeedbackType.FusedCANcoder;
55+
56+
// The stator current at which the wheels start to slip;
57+
// This needs to be tuned to your individual robot
58+
private static final Current kSlipCurrent = Amps.of(120);
59+
60+
// Initial configs for the drive and steer motors and the azimuth encoder; these cannot be null.
61+
// Some configs will be overwritten; check the `with*InitialConfigs()` API documentation.
62+
private static final TalonFXConfiguration driveInitialConfigs = new TalonFXConfiguration();
63+
private static final TalonFXConfiguration steerInitialConfigs =
64+
new TalonFXConfiguration()
65+
.withCurrentLimits(
66+
new CurrentLimitsConfigs()
67+
// Swerve azimuth does not require much torque output, so we can set a relatively
68+
// low
69+
// stator current limit to help avoid brownouts without impacting performance.
70+
.withStatorCurrentLimit(Amps.of(60))
71+
.withStatorCurrentLimitEnable(true));
72+
private static final CANcoderConfiguration encoderInitialConfigs = new CANcoderConfiguration();
73+
// Configs for the Pigeon 2; leave this null to skip applying Pigeon 2 configs
74+
private static final Pigeon2Configuration pigeonConfigs = null;
75+
76+
// CAN bus that the devices are located on;
77+
// All swerve devices must share the same CAN bus
78+
public static final CANBus kCANBus = new CANBus("", "./logs/example.hoot");
79+
80+
// Theoretical free speed (m/s) at 12 V applied output;
81+
// This needs to be tuned to your individual robot
82+
public static final LinearVelocity kSpeedAt12Volts = MetersPerSecond.of(4.39);
83+
84+
// Every 1 rotation of the azimuth results in kCoupleRatio drive motor turns;
85+
// This may need to be tuned to your individual robot
86+
private static final double kCoupleRatio = 4.5;
87+
88+
private static final double kDriveGearRatio = 7.03125;
89+
private static final double kSteerGearRatio = 26.09090909090909;
90+
private static final Distance kWheelRadius = Inches.of(2);
91+
92+
private static final boolean kInvertLeftSide = false;
93+
private static final boolean kInvertRightSide = true;
94+
95+
private static final int kPigeonId = 9;
96+
97+
// These are only used for simulation
98+
private static final MomentOfInertia kSteerInertia = KilogramSquareMeters.of(0.01);
99+
private static final MomentOfInertia kDriveInertia = KilogramSquareMeters.of(0.01);
100+
// Simulated voltage necessary to overcome friction
101+
private static final Voltage kSteerFrictionVoltage = Volts.of(0.2);
102+
private static final Voltage kDriveFrictionVoltage = Volts.of(0.2);
103+
104+
public static final SwerveDrivetrainConstants DrivetrainConstants =
105+
new SwerveDrivetrainConstants()
106+
.withCANBusName(kCANBus.getName())
107+
.withPigeon2Id(kPigeonId)
108+
.withPigeon2Configs(pigeonConfigs);
109+
110+
private static final SwerveModuleConstantsFactory<
111+
TalonFXConfiguration, TalonFXConfiguration, CANcoderConfiguration>
112+
ConstantCreator =
113+
new SwerveModuleConstantsFactory<
114+
TalonFXConfiguration, TalonFXConfiguration, CANcoderConfiguration>()
115+
.withDriveMotorGearRatio(kDriveGearRatio)
116+
.withSteerMotorGearRatio(kSteerGearRatio)
117+
.withCouplingGearRatio(kCoupleRatio)
118+
.withWheelRadius(kWheelRadius)
119+
.withSteerMotorGains(steerGains)
120+
.withDriveMotorGains(driveGains)
121+
.withSteerMotorClosedLoopOutput(kSteerClosedLoopOutput)
122+
.withDriveMotorClosedLoopOutput(kDriveClosedLoopOutput)
123+
.withSlipCurrent(kSlipCurrent)
124+
.withSpeedAt12Volts(kSpeedAt12Volts)
125+
.withDriveMotorType(kDriveMotorType)
126+
.withSteerMotorType(kSteerMotorType)
127+
.withFeedbackSource(kSteerFeedbackType)
128+
.withDriveMotorInitialConfigs(driveInitialConfigs)
129+
.withSteerMotorInitialConfigs(steerInitialConfigs)
130+
.withEncoderInitialConfigs(encoderInitialConfigs)
131+
.withSteerInertia(kSteerInertia)
132+
.withDriveInertia(kDriveInertia)
133+
.withSteerFrictionVoltage(kSteerFrictionVoltage)
134+
.withDriveFrictionVoltage(kDriveFrictionVoltage);
135+
136+
// Front Left
137+
private static final int kFrontLeftDriveMotorId = 20;
138+
private static final int kFrontLeftSteerMotorId = 21;
139+
private static final int kFrontLeftEncoderId = 10;
140+
private static final Angle kFrontLeftEncoderOffset = Rotations.of(0.390869140625);
141+
private static final boolean kFrontLeftSteerMotorInverted = false;
142+
private static final boolean kFrontLeftEncoderInverted = false;
143+
144+
private static final Distance kFrontLeftXPos = Inches.of(8.875);
145+
private static final Distance kFrontLeftYPos = Inches.of(12.625);
146+
147+
// Front Right
148+
private static final int kFrontRightDriveMotorId = 22;
149+
private static final int kFrontRightSteerMotorId = 23;
150+
private static final int kFrontRightEncoderId = 11;
151+
private static final Angle kFrontRightEncoderOffset = Rotations.of(0.239990234375);
152+
private static final boolean kFrontRightSteerMotorInverted = false;
153+
private static final boolean kFrontRightEncoderInverted = false;
154+
155+
private static final Distance kFrontRightXPos = Inches.of(8.875);
156+
private static final Distance kFrontRightYPos = Inches.of(-12.625);
157+
158+
// Back Left
159+
private static final int kBackLeftDriveMotorId = 24;
160+
private static final int kBackLeftSteerMotorId = 25;
161+
private static final int kBackLeftEncoderId = 12;
162+
private static final Angle kBackLeftEncoderOffset = Rotations.of(-0.01123046875);
163+
private static final boolean kBackLeftSteerMotorInverted = false;
164+
private static final boolean kBackLeftEncoderInverted = false;
165+
166+
private static final Distance kBackLeftXPos = Inches.of(-8.875);
167+
private static final Distance kBackLeftYPos = Inches.of(12.625);
168+
169+
// Back Right
170+
private static final int kBackRightDriveMotorId = 26;
171+
private static final int kBackRightSteerMotorId = 27;
172+
private static final int kBackRightEncoderId = 13;
173+
private static final Angle kBackRightEncoderOffset = Rotations.of(0.4248046875);
174+
private static final boolean kBackRightSteerMotorInverted = false;
175+
private static final boolean kBackRightEncoderInverted = false;
176+
177+
private static final Distance kBackRightXPos = Inches.of(-8.875);
178+
private static final Distance kBackRightYPos = Inches.of(-12.625);
179+
180+
public static final SwerveModuleConstants<
181+
TalonFXConfiguration, TalonFXConfiguration, CANcoderConfiguration>
182+
FrontLeft =
183+
ConstantCreator.createModuleConstants(
184+
kFrontLeftSteerMotorId,
185+
kFrontLeftDriveMotorId,
186+
kFrontLeftEncoderId,
187+
kFrontLeftEncoderOffset,
188+
kFrontLeftXPos,
189+
kFrontLeftYPos,
190+
kInvertLeftSide,
191+
kFrontLeftSteerMotorInverted,
192+
kFrontLeftEncoderInverted);
193+
public static final SwerveModuleConstants<
194+
TalonFXConfiguration, TalonFXConfiguration, CANcoderConfiguration>
195+
FrontRight =
196+
ConstantCreator.createModuleConstants(
197+
kFrontRightSteerMotorId,
198+
kFrontRightDriveMotorId,
199+
kFrontRightEncoderId,
200+
kFrontRightEncoderOffset,
201+
kFrontRightXPos,
202+
kFrontRightYPos,
203+
kInvertRightSide,
204+
kFrontRightSteerMotorInverted,
205+
kFrontRightEncoderInverted);
206+
public static final SwerveModuleConstants<
207+
TalonFXConfiguration, TalonFXConfiguration, CANcoderConfiguration>
208+
BackLeft =
209+
ConstantCreator.createModuleConstants(
210+
kBackLeftSteerMotorId,
211+
kBackLeftDriveMotorId,
212+
kBackLeftEncoderId,
213+
kBackLeftEncoderOffset,
214+
kBackLeftXPos,
215+
kBackLeftYPos,
216+
kInvertLeftSide,
217+
kBackLeftSteerMotorInverted,
218+
kBackLeftEncoderInverted);
219+
public static final SwerveModuleConstants<
220+
TalonFXConfiguration, TalonFXConfiguration, CANcoderConfiguration>
221+
BackRight =
222+
ConstantCreator.createModuleConstants(
223+
kBackRightSteerMotorId,
224+
kBackRightDriveMotorId,
225+
kBackRightEncoderId,
226+
kBackRightEncoderOffset,
227+
kBackRightXPos,
228+
kBackRightYPos,
229+
kInvertRightSide,
230+
kBackRightSteerMotorInverted,
231+
kBackRightEncoderInverted);
232+
233+
/**
234+
* Creates a CommandSwerveDrivetrain instance. This should only be called once in your robot
235+
* program,.
236+
*/
237+
public static CommandSwerveDrivetrain createDrivetrain() {
238+
return new CommandSwerveDrivetrain(
239+
DrivetrainConstants, FrontLeft, FrontRight, BackLeft, BackRight);
240+
}
241+
242+
/** Swerve Drive class utilizing CTR Electronics' Phoenix 6 API with the selected device types. */
243+
public static class TunerSwerveDrivetrain extends SwerveDrivetrain<TalonFX, TalonFX, CANcoder> {
244+
/**
245+
* Constructs a CTRE SwerveDrivetrain using the specified constants.
246+
*
247+
* <p>This constructs the underlying hardware devices, so users should not construct the devices
248+
* themselves. If they need the devices, they can access them through getters in the classes.
249+
*
250+
* @param drivetrainConstants Drivetrain-wide constants for the swerve drive
251+
* @param modules Constants for each specific module
252+
*/
253+
public TunerSwerveDrivetrain(
254+
SwerveDrivetrainConstants drivetrainConstants, SwerveModuleConstants<?, ?, ?>... modules) {
255+
super(TalonFX::new, TalonFX::new, CANcoder::new, drivetrainConstants, modules);
256+
}
257+
258+
/**
259+
* Constructs a CTRE SwerveDrivetrain using the specified constants.
260+
*
261+
* <p>This constructs the underlying hardware devices, so users should not construct the devices
262+
* themselves. If they need the devices, they can access them through getters in the classes.
263+
*
264+
* @param drivetrainConstants Drivetrain-wide constants for the swerve drive
265+
* @param odometryUpdateFrequency The frequency to run the odometry loop. If unspecified or set
266+
* to 0 Hz, this is 250 Hz on CAN FD, and 100 Hz on CAN 2.0.
267+
* @param modules Constants for each specific module
268+
*/
269+
public TunerSwerveDrivetrain(
270+
SwerveDrivetrainConstants drivetrainConstants,
271+
double odometryUpdateFrequency,
272+
SwerveModuleConstants<?, ?, ?>... modules) {
273+
super(
274+
TalonFX::new,
275+
TalonFX::new,
276+
CANcoder::new,
277+
drivetrainConstants,
278+
odometryUpdateFrequency,
279+
modules);
280+
}
281+
282+
/**
283+
* Constructs a CTRE SwerveDrivetrain using the specified constants.
284+
*
285+
* <p>This constructs the underlying hardware devices, so users should not construct the devices
286+
* themselves. If they need the devices, they can access them through getters in the classes.
287+
*
288+
* @param drivetrainConstants Drivetrain-wide constants for the swerve drive
289+
* @param odometryUpdateFrequency The frequency to run the odometry loop. If unspecified or set
290+
* to 0 Hz, this is 250 Hz on CAN FD, and 100 Hz on CAN 2.0.
291+
* @param odometryStandardDeviation The standard deviation for odometry calculation in the form
292+
* [x, y, theta]áµ€, with units in meters and radians
293+
* @param visionStandardDeviation The standard deviation for vision calculation in the form [x,
294+
* y, theta]áµ€, with units in meters and radians
295+
* @param modules Constants for each specific module
296+
*/
297+
public TunerSwerveDrivetrain(
298+
SwerveDrivetrainConstants drivetrainConstants,
299+
double odometryUpdateFrequency,
300+
Matrix<N3, N1> odometryStandardDeviation,
301+
Matrix<N3, N1> visionStandardDeviation,
302+
SwerveModuleConstants<?, ?, ?>... modules) {
303+
super(
304+
TalonFX::new,
305+
TalonFX::new,
306+
CANcoder::new,
307+
drivetrainConstants,
308+
odometryUpdateFrequency,
309+
odometryStandardDeviation,
310+
visionStandardDeviation,
311+
modules);
312+
}
313+
}
314+
}

src/main/java/frc/robot/subsystems/CommandSwerveDrivetrain.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
import edu.wpi.first.wpilibj2.command.Command;
3434
import frc.robot.Constants.CAN;
3535
import frc.robot.Constants.SWERVE;
36-
import frc.robot.generated.WoodBotConstants.TunerSwerveDrivetrain;
36+
import frc.robot.generated.V1Constants.TunerSwerveDrivetrain;
3737
import frc.team4201.lib.command.SwerveSubsystem;
3838
import frc.team4201.lib.utils.CtreUtils;
3939
import frc.team4201.lib.utils.ModuleMap;

0 commit comments

Comments
 (0)