Skip to content

Conversation

@GrumpyBud
Copy link
Collaborator

This pull request introduces Choreo-based autonomous trajectory support to the robot codebase. It adds a new Autos class for managing autonomous routines using Choreo, integrates Choreo auto routines into the robot container and auto chooser, and updates the Drive subsystem to support trajectory following using PID control. Additionally, new Choreo trajectory and configuration files are included for autonomous routines.

Choreo Autonomous Integration:

  • Added a new Autos class to encapsulate Choreo-based autonomous routines, including a "Depot Auto" routine that uses Choreo trajectory files. (src/main/java/frc/robot/Autos.java)
  • Integrated the Autos class into RobotContainer, initializing it and adding the "Depot Auto (Choreo)" option to the dashboard auto chooser. (src/main/java/frc/robot/RobotContainer.java) [1] [2]

Drive Subsystem Enhancements:

  • Added PID controllers for X, Y, and heading control to the Drive subsystem for precise trajectory following. (src/main/java/frc/robot/subsystems/drive/Drive.java) [1] [2]
  • Implemented a followTrajectory method in Drive that consumes SwerveSample objects and uses the PID controllers to generate chassis speeds for trajectory tracking. (src/main/java/frc/robot/subsystems/drive/Drive.java)
  • Enabled continuous input for the heading PID controller to handle angle wrapping. (src/main/java/frc/robot/subsystems/drive/Drive.java)

Choreo Trajectory and Configuration Files:

  • Added a Choreo trajectory file (OutputAuto.traj) and a configuration file (depotAuto.chor) for the new autonomous routine. [1] [2]

- Add PID controllers (x, y, heading) to Drive subsystem
- Add followTrajectory(SwerveSample) method for Choreo integration
- Create Autos class with AutoFactory for managing Choreo routines
- Add depot auto routine using existing depotAuto.chor trajectory
- Integrate Choreo autos into RobotContainer auto chooser
- Maintain compatibility with existing PathPlanner autos
Copilot AI review requested due to automatic review settings January 31, 2026 16:32
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request introduces Choreo-based autonomous trajectory support to enable advanced path following capabilities for the robot. The changes integrate the ChoreoLib library and add infrastructure for defining and executing Choreo trajectories.

Changes:

  • Added ChoreoLib vendor dependency (version 2026.0.1) for trajectory generation and following
  • Created new Autos class to manage Choreo autonomous routines and integrated it with the robot container
  • Enhanced Drive subsystem with PID-based trajectory following capability using feedforward + feedback control

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
vendordeps/ChoreoLib2026.json Adds ChoreoLib vendor dependency for 2026 season
src/main/java/frc/robot/subsystems/drive/Drive.java Adds PID controllers and followTrajectory method for Choreo integration
src/main/java/frc/robot/RobotContainer.java Integrates Autos class and adds Choreo autonomous option to dashboard
src/main/java/frc/robot/Autos.java New class that manages Choreo autonomous routines with AutoFactory
depotAuto.chor Choreo configuration file (incorrectly placed in root directory)
OutputAuto.traj Trajectory file (incorrectly placed in root directory, unclear naming)
DepotAuto.traj Trajectory file (incorrectly placed in root directory)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -0,0 +1,120 @@
{
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The trajectory files (OutputAuto.traj, DepotAuto.traj) and configuration file (depotAuto.chor) are placed in the project root directory, but they should be located in src/main/deploy/choreo/ for Choreo to load them properly at runtime. The AutoFactory will look for trajectory files in the deploy directory on the robot. Move these files to the correct location to ensure they can be loaded during autonomous execution.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,178 @@
{
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The trajectory file (DepotAuto.traj) is placed in the project root directory, but it should be located in src/main/deploy/choreo/ for Choreo to load it properly at runtime. Move this file to the correct location to ensure it can be loaded during autonomous execution.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,84 @@
{
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The configuration file (depotAuto.chor) is placed in the project root directory, but it should be located in src/main/deploy/choreo/ for Choreo to load it properly at runtime. Move this file to the correct location to ensure it can be loaded during autonomous execution.

Copilot uses AI. Check for mistakes.
public AutoRoutine depotAuto() {
AutoRoutine routine = autoFactory.newRoutine("Depot Auto");

AutoTrajectory depotTraj = routine.trajectory("depotAuto");
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a naming inconsistency between the trajectory files. The code references "depotAuto" in line 47, but there are two trajectory files: "OutputAuto.traj" and "DepotAuto.traj". The file naming should match the trajectory name used in the code. Either rename "OutputAuto.traj" to match the intended trajectory name or update the code to reference the correct trajectory file name.

Suggested change
AutoTrajectory depotTraj = routine.trajectory("depotAuto");
AutoTrajectory depotTraj = routine.trajectory("DepotAuto");

Copilot uses AI. Check for mistakes.
Comment on lines +11 to +28
import frc.robot.subsystems.Choreographer;
import frc.robot.subsystems.drive.Drive;
import frc.robot.subsystems.shooter.flywheel.Flywheel;
import frc.robot.subsystems.shooter.hood.Hood;

public class Autos {
private final Drive drive;
private final Flywheel flywheel;
private final Hood hood;
private final Choreographer choreographer;
private final AutoFactory autoFactory;
private final AutoChooser autoChooser;

public Autos(Drive drive, Flywheel flywheel, Hood hood, Choreographer choreographer) {
this.drive = drive;
this.flywheel = flywheel;
this.hood = hood;
this.choreographer = choreographer;
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fields flywheel, hood, and choreographer are stored but never used in this class. If these subsystems are not needed for the Choreo autonomous routines, they should be removed from the constructor parameters and field declarations. If they will be used in future autonomous routines, consider adding a comment explaining their intended use.

Suggested change
import frc.robot.subsystems.Choreographer;
import frc.robot.subsystems.drive.Drive;
import frc.robot.subsystems.shooter.flywheel.Flywheel;
import frc.robot.subsystems.shooter.hood.Hood;
public class Autos {
private final Drive drive;
private final Flywheel flywheel;
private final Hood hood;
private final Choreographer choreographer;
private final AutoFactory autoFactory;
private final AutoChooser autoChooser;
public Autos(Drive drive, Flywheel flywheel, Hood hood, Choreographer choreographer) {
this.drive = drive;
this.flywheel = flywheel;
this.hood = hood;
this.choreographer = choreographer;
import frc.robot.subsystems.drive.Drive;
public class Autos {
private final Drive drive;
private final AutoFactory autoFactory;
private final AutoChooser autoChooser;
public Autos(Drive drive) {
this.drive = drive;

Copilot uses AI. Check for mistakes.
Comment on lines +33 to +42
autoChooser = new AutoChooser();

autoChooser.addRoutine("Depot Auto", this::depotAuto);

autoChooser.addCmd("Do Nothing", () -> Commands.none());
}

public AutoChooser getAutoChooser() {
return autoChooser;
}
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The autoChooser field is initialized and populated but the getAutoChooser() method is never called in the PR. If this is intended for future use or integration with a dashboard, consider documenting its purpose. If it's not needed, the field and method should be removed to avoid confusion.

Copilot uses AI. Check for mistakes.
Comment on lines +111 to +113
private final PIDController xController = new PIDController(10.0, 0.0, 0.0);
private final PIDController yController = new PIDController(10.0, 0.0, 0.0);
private final PIDController headingController = new PIDController(7.5, 0.0, 0.0);
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PID controller gains (P=10.0 for translation, P=7.5 for heading) appear to be placeholder values and may need tuning for the specific robot. Consider documenting these as initial values that require tuning, or extracting them to constants for easier adjustment during testing.

Copilot uses AI. Check for mistakes.
- Replace manual .schedule() with RobotModeTriggers.teleop().whileTrue() for debug logger
- Replace toggle flywheel logic with Commands.either() for cleaner command composition
- Fixes all deprecation warnings for WPILib 2026
Renamed trajectory and choreo files to new deploy path. Updated robot mass, moment of inertia, wheel coefficient of friction, gearing, and module positions in depotAuto.chor, TunerConstants.java, and Drive.java to match latest robot configuration. Cleaned up comments and improved consistency with physical robot measurements.
Replaced references to fieldLengthMeters and fieldWidthMeters in Constants with fieldLength and fieldWidth from FieldConstants in AllianceFlipUtil. This improves code organization by centralizing field dimension constants.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 11 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

private static final double ROBOT_MASS_KG = 29;
private static final double ROBOT_MOI = 2.1;
private static final double WHEEL_COF = 1.2;
private static final double WHEEL_COF = 1.916;
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The WHEEL_COF (coefficient of friction) constant in the Drive class (1.916) matches the depotAuto.chor configuration (1.916), but differs from the value in the trajectory files (1.2). This is correct since the .chor file is the source configuration, and the trajectories should be regenerated to match. Once the trajectories are regenerated with the correct configuration, this constant will be consistent throughout.

Copilot uses AI. Check for mistakes.

AutoTrajectory depotTraj = routine.trajectory("depotAuto");

routine.active().onTrue(Commands.sequence(depotTraj.resetOdometry(), depotTraj.cmd()));
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The depotAuto routine uses Commands.sequence() to first reset odometry and then run the trajectory. However, this creates a sequential command where resetOdometry() completes before the trajectory starts. If resetOdometry() is instantaneous (returns immediately), this is fine. But if you want both to start simultaneously, consider using Commands.parallel(). Also verify that routine.active().onTrue() is the correct trigger - this should activate when the autonomous routine becomes active, but ensure this matches your intended autonomous workflow.

Copilot uses AI. Check for mistakes.
Comment on lines +39 to +58
"mass":56.69904625,
"inertia":9.0,
"gearing":6.75,
"radius":0.0508,
"vmax":628.3185307179587,
"tmax":0.75,
"cof":1.2,
"bumper":{
"front":0.4064,
"side":0.4064,
"back":0.4064
},
"differentialTrackWidth":0.5588
},
"sampleType":"Swerve",
"waypoints":[0.0,1.37597,2.83374],
"samples":[
{"t":0.0, "x":3.63188, "y":2.0, "heading":0.0, "vx":0.0, "vy":0.0, "omega":0.0, "ax":-5.55428, "ay":-4.30019, "alpha":0.0, "fx":[-78.7306,-78.7306,-78.7306,-78.7306], "fy":[-60.95423,-60.95423,-60.95423,-60.95423]},
{"t":0.04745, "x":3.62563, "y":1.99516, "heading":0.0, "vx":-0.26354, "vy":-0.20403, "omega":0.0, "ax":-5.56727, "ay":-4.28259, "alpha":0.0, "fx":[-78.91474,-78.91474,-78.91474,-78.91474], "fy":[-60.70469,-60.70469,-60.70469,-60.70469]},
{"t":0.09489, "x":3.60686, "y":1.98066, "heading":0.0, "vx":-0.52769, "vy":-0.40723, "omega":0.0, "ax":-5.58236, "ay":-4.262, "alpha":0.0, "fx":[-79.1286,-79.1286,-79.1286,-79.1286], "fy":[-60.41282,-60.41282,-60.41282,-60.41282]},
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The trajectory configuration embedded in the .traj files has inconsistent physical parameters compared to the .chor configuration file. Specifically:

In depotAuto.chor:

  • mass: 64 lb = 29.03 kg (line 31-32)
  • inertia: 2.11 kg*m^2 (line 34-36)
  • cof: 1.916 (line 54-56)
  • gearing: 6.746031746 (line 38-40)
  • frontLeft position: 0.263525 m (10.375 in)

But in both OutputAuto.traj and DepotAuto.traj trajectory configs:

  • mass: 56.69904625 kg (line 52 in DepotAuto.traj, line 39 in OutputAuto.traj)
  • inertia: 9.0 kg*m^2 (line 53, line 40)
  • cof: 1.2 (line 58, line 45)
  • gearing: 6.75 (line 54, line 41)
  • frontLeft position: 0.3302 m (line 45, line 32)

These trajectories were likely generated with different robot configurations than specified in depotAuto.chor. The embedded trajectory physics won't match the actual robot, which could cause tracking errors or unexpected behavior. Regenerate the trajectories using the correct configuration from depotAuto.chor, or update depotAuto.chor to match the configuration used during generation.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +120
{
"name":"OutputAuto",
"version":3,
"snapshot":{
"waypoints":[
{"x":3.631880044937134, "y":2.0, "heading":0.0, "intervals":29, "split":false, "fixTranslation":true, "fixHeading":true, "overrideIntervals":false},
{"x":0.4056924879550934, "y":0.6689572930335999, "heading":0.0, "intervals":30, "split":false, "fixTranslation":true, "fixHeading":true, "overrideIntervals":false},
{"x":2.370190143585205, "y":4.021896839141846, "heading":0.0, "intervals":40, "split":false, "fixTranslation":true, "fixHeading":true, "overrideIntervals":false}],
"constraints":[
{"from":"first", "to":null, "data":{"type":"StopPoint", "props":{}}, "enabled":true},
{"from":"last", "to":null, "data":{"type":"StopPoint", "props":{}}, "enabled":true},
{"from":"first", "to":"last", "data":{"type":"KeepInRectangle", "props":{"x":0.0, "y":0.0, "w":16.541, "h":8.0692}}, "enabled":false}],
"targetDt":0.05
},
"params":{
"waypoints":[
{"x":{"exp":"3.631880044937134 m", "val":3.631880044937134}, "y":{"exp":"2 m", "val":2.0}, "heading":{"exp":"0 deg", "val":0.0}, "intervals":29, "split":false, "fixTranslation":true, "fixHeading":true, "overrideIntervals":false},
{"x":{"exp":"0.4056924879550934 m", "val":0.4056924879550934}, "y":{"exp":"0.6689572930335999 m", "val":0.6689572930335999}, "heading":{"exp":"0 deg", "val":0.0}, "intervals":30, "split":false, "fixTranslation":true, "fixHeading":true, "overrideIntervals":false},
{"x":{"exp":"2.370190143585205 m", "val":2.370190143585205}, "y":{"exp":"4.021896839141846 m", "val":4.021896839141846}, "heading":{"exp":"0 deg", "val":0.0}, "intervals":40, "split":false, "fixTranslation":true, "fixHeading":true, "overrideIntervals":false}],
"constraints":[
{"from":"first", "to":null, "data":{"type":"StopPoint", "props":{}}, "enabled":true},
{"from":"last", "to":null, "data":{"type":"StopPoint", "props":{}}, "enabled":true},
{"from":"first", "to":"last", "data":{"type":"KeepInRectangle", "props":{"x":{"exp":"0 m", "val":0.0}, "y":{"exp":"0 m", "val":0.0}, "w":{"exp":"16.541 m", "val":16.541}, "h":{"exp":"8.0692 m", "val":8.0692}}}, "enabled":false}],
"targetDt":{
"exp":"0.05 s",
"val":0.05
}
},
"trajectory":{
"config":{
"frontLeft":{
"x":0.3302,
"y":0.3302
},
"backLeft":{
"x":-0.3302,
"y":0.3302
},
"mass":56.69904625,
"inertia":9.0,
"gearing":6.75,
"radius":0.0508,
"vmax":628.3185307179587,
"tmax":0.75,
"cof":1.2,
"bumper":{
"front":0.4064,
"side":0.4064,
"back":0.4064
},
"differentialTrackWidth":0.5588
},
"sampleType":"Swerve",
"waypoints":[0.0,1.37597,2.83374],
"samples":[
{"t":0.0, "x":3.63188, "y":2.0, "heading":0.0, "vx":0.0, "vy":0.0, "omega":0.0, "ax":-5.55428, "ay":-4.30019, "alpha":0.0, "fx":[-78.7306,-78.7306,-78.7306,-78.7306], "fy":[-60.95423,-60.95423,-60.95423,-60.95423]},
{"t":0.04745, "x":3.62563, "y":1.99516, "heading":0.0, "vx":-0.26354, "vy":-0.20403, "omega":0.0, "ax":-5.56727, "ay":-4.28259, "alpha":0.0, "fx":[-78.91474,-78.91474,-78.91474,-78.91474], "fy":[-60.70469,-60.70469,-60.70469,-60.70469]},
{"t":0.09489, "x":3.60686, "y":1.98066, "heading":0.0, "vx":-0.52769, "vy":-0.40723, "omega":0.0, "ax":-5.58236, "ay":-4.262, "alpha":0.0, "fx":[-79.1286,-79.1286,-79.1286,-79.1286], "fy":[-60.41282,-60.41282,-60.41282,-60.41282]},
{"t":0.14234, "x":3.57554, "y":1.95654, "heading":0.0, "vx":-0.79256, "vy":-0.60945, "omega":0.0, "ax":-5.60009, "ay":-4.23759, "alpha":0.0, "fx":[-79.37997,-79.37997,-79.37997,-79.37997], "fy":[-60.06689,-60.06689,-60.06689,-60.06689]},
{"t":0.18979, "x":3.53163, "y":1.92285, "heading":0.0, "vx":-1.05826, "vy":-0.81051, "omega":0.0, "ax":-5.62123, "ay":-4.20821, "alpha":0.0, "fx":[-79.67963,-79.67963,-79.67963,-79.67963], "fy":[-59.65039,-59.65039,-59.65039,-59.65039]},
{"t":0.23724, "x":3.47509, "y":1.87966, "heading":0.0, "vx":-1.32498, "vy":-1.01018, "omega":0.0, "ax":-5.64686, "ay":-4.17216, "alpha":0.0, "fx":[-80.0429,-80.0429,-80.0429,-80.0429], "fy":[-59.13935,-59.13935,-59.13935,-59.13935]},
{"t":0.28468, "x":3.40587, "y":1.82703, "heading":0.0, "vx":-1.59291, "vy":-1.20814, "omega":0.0, "ax":-5.67856, "ay":-4.12688, "alpha":0.0, "fx":[-80.49229,-80.49229,-80.49229,-80.49229], "fy":[-58.49758,-58.49758,-58.49758,-58.49758]},
{"t":0.33213, "x":3.3239, "y":1.76506, "heading":0.0, "vx":-1.86234, "vy":-1.40395, "omega":0.0, "ax":-5.71877, "ay":-4.06835, "alpha":0.0, "fx":[-81.06226,-81.06226,-81.06226,-81.06226], "fy":[-57.66788,-57.66788,-57.66788,-57.66788]},
{"t":0.37958, "x":3.22909, "y":1.69387, "heading":0.0, "vx":-2.13368, "vy":-1.59698, "omega":0.0, "ax":-5.7714, "ay":-3.98978, "alpha":0.0, "fx":[-81.80823,-81.80823,-81.80823,-81.80823], "fy":[-56.55412,-56.55412,-56.55412,-56.55412]},
{"t":0.42703, "x":3.12136, "y":1.61361, "heading":0.0, "vx":-2.40752, "vy":-1.78628, "omega":0.0, "ax":-5.84313, "ay":-3.87886, "alpha":0.0, "fx":[-82.82496,-82.82496,-82.82496,-82.82496], "fy":[-54.98189,-54.98189,-54.98189,-54.98189]},
{"t":0.47447, "x":3.00055, "y":1.52449, "heading":0.0, "vx":-2.68476, "vy":-1.97033, "omega":0.0, "ax":-5.94632, "ay":-3.71078, "alpha":0.0, "fx":[-84.28771,-84.28771,-84.28771,-84.28771], "fy":[-52.59947,-52.59947,-52.59947,-52.59947]},
{"t":0.52192, "x":2.86648, "y":1.42682, "heading":0.0, "vx":-2.96689, "vy":-2.14639, "omega":0.0, "ax":-6.10615, "ay":-3.42738, "alpha":0.0, "fx":[-86.55321,-86.55321,-86.55321,-86.55321], "fy":[-48.58222,-48.58222,-48.58222,-48.58222]},
{"t":0.56937, "x":2.71883, "y":1.32112, "heading":0.0, "vx":-3.25661, "vy":-2.30901, "omega":0.0, "ax":-6.37872, "ay":-2.85636, "alpha":0.0, "fx":[-90.41687,-90.41687,-90.41687,-90.41687], "fy":[-40.48825,-40.48825,-40.48825,-40.48825]},
{"t":0.61681, "x":2.55713, "y":1.20835, "heading":0.0, "vx":-3.55927, "vy":-2.44454, "omega":0.0, "ax":-6.84408, "ay":-1.24205, "alpha":0.0, "fx":[-97.01316,-97.01316,-97.01316,-97.01316], "fy":[-17.60576,-17.60576,-17.60576,-17.60576]},
{"t":0.66426, "x":2.38055, "y":1.09097, "heading":0.0, "vx":-3.884, "vy":-2.50347, "omega":0.0, "ax":-4.67836, "ay":5.04786, "alpha":0.0, "fx":[-66.31458,-66.31458,-66.31458,-66.31458], "fy":[71.55223,71.55223,71.55223,71.55223]},
{"t":0.71171, "x":2.191, "y":0.97787, "heading":0.0, "vx":-4.10598, "vy":-2.26396, "omega":0.0, "ax":1.89594, "ay":6.68613, "alpha":0.0, "fx":[26.87455,26.87455,26.87455,26.87455], "fy":[94.77436,94.77436,94.77436,94.77436]},
{"t":0.75916, "x":1.99832, "y":0.87797, "heading":0.0, "vx":-4.01602, "vy":-1.94672, "omega":0.0, "ax":3.72204, "ay":5.91279, "alpha":0.0, "fx":[52.75908,52.75908,52.75908,52.75908], "fy":[83.81236,83.81236,83.81236,83.81236]},
{"t":0.8066, "x":1.81196, "y":0.79226, "heading":0.0, "vx":-3.83942, "vy":-1.66618, "omega":0.0, "ax":4.32157, "ay":5.50821, "alpha":0.0, "fx":[61.25717,61.25717,61.25717,61.25717], "fy":[78.07754,78.07754,78.07754,78.07754]},
{"t":0.85405, "x":1.63465, "y":0.71941, "heading":0.0, "vx":-3.63437, "vy":-1.40483, "omega":0.0, "ax":4.60713, "ay":5.28147, "alpha":0.0, "fx":[65.30493,65.30493,65.30493,65.30493], "fy":[74.8636,74.8636,74.8636,74.8636]},
{"t":0.9015, "x":1.4674, "y":0.6587, "heading":0.0, "vx":-3.41577, "vy":-1.15424, "omega":0.0, "ax":4.77243, "ay":5.13865, "alpha":0.0, "fx":[67.648,67.648,67.648,67.648], "fy":[72.83913,72.83913,72.83913,72.83913]},
{"t":0.94895, "x":1.3107, "y":0.60972, "heading":0.0, "vx":-3.18934, "vy":-0.91042, "omega":0.0, "ax":4.87981, "ay":5.0409, "alpha":0.0, "fx":[69.17014,69.17014,69.17014,69.17014], "fy":[71.45357,71.45357,71.45357,71.45357]},
{"t":0.99639, "x":1.16487, "y":0.57219, "heading":0.0, "vx":-2.9578, "vy":-0.67125, "omega":0.0, "ax":4.95505, "ay":4.96994, "alpha":0.0, "fx":[70.23663,70.23663,70.23663,70.23663], "fy":[70.44767,70.44767,70.44767,70.44767]},
{"t":1.04384, "x":1.03011, "y":0.54594, "heading":0.0, "vx":-2.7227, "vy":-0.43543, "omega":0.0, "ax":5.01065, "ay":4.91613, "alpha":0.0, "fx":[71.02473,71.02473,71.02473,71.02473], "fy":[69.68494,69.68494,69.68494,69.68494]},
{"t":1.09129, "x":0.90656, "y":0.53081, "heading":0.0, "vx":-2.48496, "vy":-0.20218, "omega":0.0, "ax":5.05339, "ay":4.87395, "alpha":0.0, "fx":[71.63054,71.63054,71.63054,71.63054], "fy":[69.08703,69.08703,69.08703,69.08703]},
{"t":1.13874, "x":0.79434, "y":0.52671, "heading":0.0, "vx":-2.24519, "vy":0.02908, "omega":0.0, "ax":5.08725, "ay":4.84, "alpha":0.0, "fx":[72.1106,72.1106,72.1106,72.1106], "fy":[68.6059,68.6059,68.6059,68.6059]},
{"t":1.18618, "x":0.69354, "y":0.53353, "heading":0.0, "vx":-2.00381, "vy":0.25872, "omega":0.0, "ax":5.11474, "ay":4.81211, "alpha":0.0, "fx":[72.50028,72.50028,72.50028,72.50028], "fy":[68.21047,68.21047,68.21047,68.21047]},
{"t":1.23363, "x":0.60422, "y":0.55123, "heading":0.0, "vx":-1.76113, "vy":0.48704, "omega":0.0, "ax":5.1375, "ay":4.78878, "alpha":0.0, "fx":[72.82284,72.82284,72.82284,72.82284], "fy":[67.87979,67.87979,67.87979,67.87979]},
{"t":1.28108, "x":0.52645, "y":0.57972, "heading":0.0, "vx":-1.51737, "vy":0.71426, "omega":0.0, "ax":5.15664, "ay":4.76898, "alpha":0.0, "fx":[73.09421,73.09421,73.09421,73.09421], "fy":[67.59919,67.59919,67.59919,67.59919]},
{"t":1.32852, "x":0.46026, "y":0.61898, "heading":0.0, "vx":-1.2727, "vy":0.94053, "omega":0.0, "ax":5.17297, "ay":4.75198, "alpha":0.0, "fx":[73.32564,73.32564,73.32564,73.32564], "fy":[67.35815,67.35815,67.35815,67.35815]},
{"t":1.37597, "x":0.40569, "y":0.66896, "heading":0.0, "vx":-1.02726, "vy":1.166, "omega":0.0, "ax":5.18556, "ay":4.73843, "alpha":0.0, "fx":[73.50412,73.50412,73.50412,73.50412], "fy":[67.16617,67.16617,67.16617,67.16617]},
{"t":1.42456, "x":0.3619, "y":0.73121, "heading":0.0, "vx":-0.77528, "vy":1.39625, "omega":0.0, "ax":5.19721, "ay":4.72492, "alpha":0.0, "fx":[73.66916,73.66916,73.66916,73.66916], "fy":[66.97467,66.97467,66.97467,66.97467]},
{"t":1.47316, "x":0.33036, "y":0.80464, "heading":0.0, "vx":-0.52273, "vy":1.62585, "omega":0.0, "ax":5.21088, "ay":4.70897, "alpha":0.0, "fx":[73.86299,73.86299,73.86299,73.86299], "fy":[66.74848,66.74848,66.74848,66.74848]},
{"t":1.52175, "x":0.31111, "y":0.8892, "heading":0.0, "vx":-0.26953, "vy":1.85467, "omega":0.0, "ax":5.22717, "ay":4.68984, "alpha":0.0, "fx":[74.09383,74.09383,74.09383,74.09383], "fy":[66.47732,66.47732,66.47732,66.47732]},
{"t":1.57034, "x":0.30419, "y":0.98486, "heading":0.0, "vx":-0.01553, "vy":2.08256, "omega":0.0, "ax":5.24688, "ay":4.66649, "alpha":0.0, "fx":[74.37334,74.37334,74.37334,74.37334], "fy":[66.14632,66.14632,66.14632,66.14632]},
{"t":1.61893, "x":0.30963, "y":1.09156, "heading":0.0, "vx":0.23943, "vy":2.30931, "omega":0.0, "ax":5.27125, "ay":4.63735, "alpha":0.0, "fx":[74.71867,74.71867,74.71867,74.71867], "fy":[65.7333,65.7333,65.7333,65.7333]},
{"t":1.66753, "x":0.32748, "y":1.20925, "heading":0.0, "vx":0.49557, "vy":2.53465, "omega":0.0, "ax":5.3021, "ay":4.59998, "alpha":0.0, "fx":[75.15606,75.15606,75.15606,75.15606], "fy":[65.20355,65.20355,65.20355,65.20355]},
{"t":1.71612, "x":0.35783, "y":1.33785, "heading":0.0, "vx":0.75322, "vy":2.75818, "omega":0.0, "ax":5.34244, "ay":4.55032, "alpha":0.0, "fx":[75.72782,75.72782,75.72782,75.72782], "fy":[64.49965,64.49965,64.49965,64.49965]},
{"t":1.76471, "x":0.40073, "y":1.47725, "heading":0.0, "vx":1.01282, "vy":2.97929, "omega":0.0, "ax":5.39739, "ay":4.48115, "alpha":0.0, "fx":[76.50667,76.50667,76.50667,76.50667], "fy":[63.51919,63.51919,63.51919,63.51919]},
{"t":1.8133, "x":0.45632, "y":1.62731, "heading":0.0, "vx":1.27509, "vy":3.19704, "omega":0.0, "ax":5.47655, "ay":4.37824, "alpha":0.0, "fx":[77.62883,77.62883,77.62883,77.62883], "fy":[62.06052,62.06052,62.06052,62.06052]},
{"t":1.86189, "x":0.52475, "y":1.78783, "heading":0.0, "vx":1.54121, "vy":3.40978, "omega":0.0, "ax":5.60015, "ay":4.20928, "alpha":0.0, "fx":[79.38074,79.38074,79.38074,79.38074], "fy":[59.66557,59.66557,59.66557,59.66557]},
{"t":1.91049, "x":0.60625, "y":1.95849, "heading":0.0, "vx":1.81333, "vy":3.61432, "omega":0.0, "ax":5.81824, "ay":3.88259, "alpha":0.0, "fx":[82.47221,82.47221,82.47221,82.47221], "fy":[55.03485,55.03485,55.03485,55.03485]},
{"t":1.95908, "x":0.70123, "y":2.1387, "heading":0.0, "vx":2.09605, "vy":3.80299, "omega":0.0, "ax":6.28335, "ay":3.01116, "alpha":0.0, "fx":[89.06504,89.06504,89.06504,89.06504], "fy":[42.68251,42.68251,42.68251,42.68251]},
{"t":2.00767, "x":0.8105, "y":2.32705, "heading":0.0, "vx":2.40137, "vy":3.94931, "omega":0.0, "ax":6.61002, "ay":-1.82757, "alpha":0.0, "fx":[93.69549,93.69549,93.69549,93.69549], "fy":[-25.90541,-25.90541,-25.90541,-25.90541]},
{"t":2.05626, "x":0.93499, "y":2.5168, "heading":0.0, "vx":2.72257, "vy":3.8605, "omega":0.0, "ax":5.35937, "ay":-4.04411, "alpha":0.0, "fx":[75.96773,75.96773,75.96773,75.96773], "fy":[-57.32433,-57.32433,-57.32433,-57.32433]},
{"t":2.10486, "x":1.07362, "y":2.69961, "heading":0.0, "vx":2.98299, "vy":3.66399, "omega":0.0, "ax":4.85009, "ay":-4.24665, "alpha":0.0, "fx":[68.7489,68.7489,68.7489,68.7489], "fy":[-60.19529,-60.19529,-60.19529,-60.19529]},
{"t":2.15345, "x":1.22429, "y":2.87264, "heading":0.0, "vx":3.21867, "vy":3.45763, "omega":0.0, "ax":-2.2299, "ay":-6.26724, "alpha":0.0, "fx":[-31.60831,-31.60831,-31.60831,-31.60831], "fy":[-88.83664,-88.83664,-88.83664,-88.83664]},
{"t":2.20204, "x":1.37806, "y":3.03326, "heading":0.0, "vx":3.11031, "vy":3.15309, "omega":0.0, "ax":-4.60236, "ay":-5.22508, "alpha":0.0, "fx":[-65.23734,-65.23734,-65.23734,-65.23734], "fy":[-74.06427,-74.06427,-74.06427,-74.06427]},
{"t":2.25063, "x":1.52377, "y":3.1803, "heading":0.0, "vx":2.88668, "vy":2.89919, "omega":0.0, "ax":-4.80479, "ay":-5.08209, "alpha":0.0, "fx":[-68.10669,-68.10669,-68.10669,-68.10669], "fy":[-72.03735,-72.03735,-72.03735,-72.03735]},
{"t":2.29923, "x":1.65836, "y":3.31518, "heading":0.0, "vx":2.6532, "vy":2.65224, "omega":0.0, "ax":-4.87897, "ay":-5.02698, "alpha":0.0, "fx":[-69.15821,-69.15821,-69.15821,-69.15821], "fy":[-71.25626,-71.25626,-71.25626,-71.25626]},
{"t":2.34782, "x":1.78153, "y":3.43813, "heading":0.0, "vx":2.41612, "vy":2.40797, "omega":0.0, "ax":-4.91739, "ay":-4.99785, "alpha":0.0, "fx":[-69.70287,-69.70287,-69.70287,-69.70287], "fy":[-70.84329,-70.84329,-70.84329,-70.84329]},
{"t":2.39641, "x":1.89313, "y":3.54923, "heading":0.0, "vx":2.17717, "vy":2.16512, "omega":0.0, "ax":-4.94088, "ay":-4.97984, "alpha":0.0, "fx":[-70.03579,-70.03579,-70.03579,-70.03579], "fy":[-70.588,-70.588,-70.588,-70.588]},
{"t":2.445, "x":1.99309, "y":3.64856, "heading":0.0, "vx":1.93708, "vy":1.92313, "omega":0.0, "ax":-4.95672, "ay":-4.9676, "alpha":0.0, "fx":[-70.26029,-70.26029,-70.26029,-70.26029], "fy":[-70.41461,-70.41461,-70.41461,-70.41461]},
{"t":2.49359, "x":2.08136, "y":3.73615, "heading":0.0, "vx":1.69623, "vy":1.68175, "omega":0.0, "ax":-4.96812, "ay":-4.95876, "alpha":0.0, "fx":[-70.42188,-70.42188,-70.42188,-70.42188], "fy":[-70.28919,-70.28919,-70.28919,-70.28919]},
{"t":2.54219, "x":2.15792, "y":3.81201, "heading":0.0, "vx":1.45481, "vy":1.44079, "omega":0.0, "ax":-4.97671, "ay":-4.95206, "alpha":0.0, "fx":[-70.54375,-70.54375,-70.54375,-70.54375], "fy":[-70.19426,-70.19426,-70.19426,-70.19426]},
{"t":2.59078, "x":2.22274, "y":3.87618, "heading":0.0, "vx":1.21298, "vy":1.20016, "omega":0.0, "ax":-4.98343, "ay":-4.94681, "alpha":0.0, "fx":[-70.63893,-70.63893,-70.63893,-70.63893], "fy":[-70.11991,-70.11991,-70.11991,-70.11991]},
{"t":2.63937, "x":2.2758, "y":3.92866, "heading":0.0, "vx":0.97083, "vy":0.95978, "omega":0.0, "ax":-4.98882, "ay":-4.94259, "alpha":0.0, "fx":[-70.71533,-70.71533,-70.71533,-70.71533], "fy":[-70.0601,-70.0601,-70.0601,-70.0601]},
{"t":2.68796, "x":2.31708, "y":3.96946, "heading":0.0, "vx":0.72841, "vy":0.71961, "omega":0.0, "ax":-4.99324, "ay":-4.93913, "alpha":0.0, "fx":[-70.77799,-70.77799,-70.77799,-70.77799], "fy":[-70.01095,-70.01095,-70.01095,-70.01095]},
{"t":2.73656, "x":2.34658, "y":3.99859, "heading":0.0, "vx":0.48578, "vy":0.47961, "omega":0.0, "ax":-4.99693, "ay":-4.93623, "alpha":0.0, "fx":[-70.83032,-70.83032,-70.83032,-70.83032], "fy":[-69.96985,-69.96985,-69.96985,-69.96985]},
{"t":2.78515, "x":2.36429, "y":4.01607, "heading":0.0, "vx":0.24296, "vy":0.23974, "omega":0.0, "ax":-5.00006, "ay":-4.93377, "alpha":0.0, "fx":[-70.87468,-70.87468,-70.87468,-70.87468], "fy":[-69.93497,-69.93497,-69.93497,-69.93497]},
{"t":2.83374, "x":2.37019, "y":4.0219, "heading":0.0, "vx":0.0, "vy":0.0, "omega":0.0, "ax":0.0, "ay":0.0, "alpha":0.0, "fx":[0.0,0.0,0.0,0.0], "fy":[0.0,0.0,0.0,0.0]}],
"splits":[0]
},
"events":[
{"name":"Marker", "from":{"target":1, "targetTimestamp":1.37597, "offset":{"exp":"0 s", "val":0.0}}, "event":{"type":"wait", "data":{"waitTime":{"exp":"4 s", "val":4.0}}}}]
}
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OutputAuto.traj file is not referenced anywhere in the codebase. This appears to be an unused trajectory file that should either be removed or integrated into the autonomous routines. If this is a work-in-progress trajectory, consider moving it to a different location or adding a comment explaining its purpose.

Copilot uses AI. Check for mistakes.
Comment on lines +418 to +422
new ChassisSpeeds(
sample.vx + xController.calculate(pose.getX(), sample.x),
sample.vy + yController.calculate(pose.getY(), sample.y),
sample.omega
+ headingController.calculate(pose.getRotation().getRadians(), sample.heading));
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The followTrajectory method constructs ChassisSpeeds from Choreo trajectory samples, which are field-relative (world frame). However, the runVelocity method expects robot-relative speeds. The SwerveSample values (vx, vy, omega) from Choreo are in field coordinates, but you're passing them directly to runVelocity without converting from field-relative to robot-relative coordinates.

You need to convert the speeds using ChassisSpeeds.fromFieldRelativeSpeeds() before passing to runVelocity, or ensure runVelocity handles field-relative speeds. Check the existing DriveCommands or other trajectory following code to see how field vs robot relative speeds are handled in this codebase.

Suggested change
new ChassisSpeeds(
sample.vx + xController.calculate(pose.getX(), sample.x),
sample.vy + yController.calculate(pose.getY(), sample.y),
sample.omega
+ headingController.calculate(pose.getRotation().getRadians(), sample.heading));
ChassisSpeeds.fromFieldRelativeSpeeds(
sample.vx + xController.calculate(pose.getX(), sample.x),
sample.vy + yController.calculate(pose.getY(), sample.y),
sample.omega
+ headingController.calculate(pose.getRotation().getRadians(), sample.heading),
pose.getRotation());

Copilot uses AI. Check for mistakes.
new Translation2d(TunerConstants.BackRight.LocationX, TunerConstants.BackRight.LocationY)
};
}

Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The followTrajectory method lacks documentation. Add a Javadoc comment explaining:

  • What the method does (follows a Choreo trajectory sample)
  • The parameter (SwerveSample sample from Choreo trajectory)
  • How it works (uses PID controllers for position tracking with feedforward from trajectory)
  • Any important notes about coordinate frames or usage

This is especially important for a new public API that will be called by autonomous routines.

Suggested change
/**
* Follow a single Choreo swerve trajectory sample using closed-loop position control.
*
* <p>This method takes a {@link SwerveSample} generated by Choreo, which contains the desired
* field-relative pose (x, y, heading) and chassis velocities (vx, vy, omega) for the current
* time step. It computes corrections with the internal PID controllers for X position, Y
* position, and heading based on the current estimated robot pose from {@link #getPose()}, then
* adds those corrections as feedback terms on top of the feedforward velocities provided by the
* trajectory sample before commanding the drive.
*
* <p><strong>Coordinate frames and usage:</strong>
*
* <ul>
* <li>The sample pose and velocities are expected to be in field coordinates, with positions
* in meters and heading in radians.
* <li>The internal pose estimator must use the same field coordinate frame and origin as the
* Choreo trajectory for accurate tracking.
* <li>This method should be called periodically (e.g., from an autonomous routine) with
* successive samples along the trajectory.
* </ul>
*
* @param sample the current Choreo {@link SwerveSample} specifying desired field-relative pose
* and chassis velocities to track
*/

Copilot uses AI. Check for mistakes.
Comment on lines +45 to +58
"x":0.3302,
"y":0.3302
},
"backLeft":{
"x":-0.3302,
"y":0.3302
},
"mass":56.69904625,
"inertia":9.0,
"gearing":6.75,
"radius":0.0508,
"vmax":628.3185307179587,
"tmax":0.75,
"cof":1.2,
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The trajectory configuration embedded in this file has inconsistent physical parameters compared to depotAuto.chor. Specifically:

In depotAuto.chor:

  • mass: 64 lb = 29.03 kg
  • inertia: 2.11 kg*m^2
  • cof: 1.916
  • gearing: 6.746031746
  • frontLeft position: 0.263525 m (10.375 in)

But in this trajectory config:

  • mass: 56.69904625 kg
  • inertia: 9.0 kg*m^2
  • cof: 1.2
  • gearing: 6.75
  • frontLeft position: 0.3302 m

This trajectory was likely generated with different robot configurations than specified in depotAuto.chor. The embedded trajectory physics won't match the actual robot, which could cause tracking errors or unexpected behavior. Regenerate the trajectory using the correct configuration from depotAuto.chor, or update depotAuto.chor to match the configuration used during generation.

Suggested change
"x":0.3302,
"y":0.3302
},
"backLeft":{
"x":-0.3302,
"y":0.3302
},
"mass":56.69904625,
"inertia":9.0,
"gearing":6.75,
"radius":0.0508,
"vmax":628.3185307179587,
"tmax":0.75,
"cof":1.2,
"x":0.263525,
"y":0.263525
},
"backLeft":{
"x":-0.263525,
"y":0.263525
},
"mass":29.03,
"inertia":2.11,
"gearing":6.746031746,
"radius":0.0508,
"vmax":628.3185307179587,
"tmax":0.75,
"cof":1.916,

Copilot uses AI. Check for mistakes.
Comment on lines +114 to +116
private final PIDController xController = new PIDController(10.0, 0.0, 0.0);
private final PIDController yController = new PIDController(10.0, 0.0, 0.0);
private final PIDController headingController = new PIDController(7.5, 0.0, 0.0);
Copy link

Copilot AI Jan 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PID controller gains (Kp=10.0 for translation, Kp=7.5 for rotation) appear to be quite high and may cause oscillation or instability during trajectory following. These values should be tuned empirically on the actual robot. Consider starting with lower gains (e.g., Kp=5.0 for translation, Kp=5.0 for rotation) and tuning up from there. Also consider adding derivative or integral terms if needed for better trajectory tracking.

Suggested change
private final PIDController xController = new PIDController(10.0, 0.0, 0.0);
private final PIDController yController = new PIDController(10.0, 0.0, 0.0);
private final PIDController headingController = new PIDController(7.5, 0.0, 0.0);
private final PIDController xController = new PIDController(5.0, 0.0, 0.0);
private final PIDController yController = new PIDController(5.0, 0.0, 0.0);
private final PIDController headingController = new PIDController(5.0, 0.0, 0.0);

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants