Shooter Alignment works only after enabling/disabling teleop?

I have a feeling we’re missing something obvious, but we just don’t see it. When we use our limelight to auto-align in autonomous, it doesn’t move at all. But if we switch to teleop, enable the robot, disable the robot and switch back to auto, it works fine. Help is appreciated!

Github link: NutronsShooterBot/src/main/java/frc/robot/commands at main · FRCTeam2370/NutronsShooterBot · GitHub

I think one issue is that you’re creating a new instance of the Shooter class in your command. You don’t want to do this. Use one instance and pass into the constructor of your command classes

3 Likes

I took a quick look at your code, and noticed that you’re creating multiple Limelight Subystems.
In AutoAim, you have the line:

Limelight mLimelight = new Limelight();

Based on your robot container, this means that you have two different LimelightSubystems at any given time.
In contrast, your AutoAutoAim has that line and passes the limelight as an argument to the constructor, setting mLimelight here:

this.mLimelight = mLimelight;

In general, you probably don’t actually want to create two Limelights, so the first line in AutoAutoAim should be

Limelight mLimelight;

(It’s fine to not use the ‘=’ here if you set it in the constructor).
It looks like you have a lot of these double instantiation bugs in your subsystems, which can be unpredictable. I can’t be sure that it’s the exact cause of your bug, but I’d strongly recommend passing subsystems as arguments like in AutoAutoAim

Thanks for the quick response! We’re clearing out any place we’ve made more than one instance and will give it another shot.

Thanks for the quick response! We will make the changes and update.

We’ve removed all the duplicate instantiations mLimelight and re-pushed to github.

The robot will still only use the AimWithLimeligtht Command in autonomous if we enable and disable in teleop mode first.

To solve the double subsystem problem our team uses the singleton design pattern and it works really well. What it does is make sure that there is only ever one instance of a certain class.

For example

public class Limelight{
private static Limelight instance;

public static Limelight getInstance(){
      if (instance == null) {
           Instance= new Shooter();
      }
      return instance;
}

Constructors and class logic and methods go 
 here ...

}

This way by accessing getInstance throughout your program only one instance is ever created and you can use your subsystem like you would in any other scenario.

1 Like

A couple of things:

  1. Just to confirm that the problem is in AutoAlign, and not AutoAim? I think I got confused in my first glance (Also heads up that you may have missed a null pointer exception by forgetting to assign in the constructor in AutoAim).
  2. I haven’t opened it in PathPlanner, but are you running the “First Test” auto, which is configured to only do AutoAlign?
  3. Do the print statements in AimWithLimelight.java print when you’re encountering the issue? If no, then something is preventing the Command itself from running (maybe the pathplanner auto itself, since pathplanner paths also require the drivetrain? My dig into AutoBuilder didn’t suggest it though you could test a non-pathplanner auto to see if that works properly) If yes, then something is preventing the drivetrain from obeying the request. (Either the limelight rotation is null or N/A, or maybe there’s a conflicting line elsewhere also telling the drivetrain to do something, in which case I’d suggest some print statements to check this further)
  4. This is probably not the problem, as it’s unused and might even be intended, but I noticed that the applyRequest Command in your drivetrain subsystem doesn’t list the drivetrain subsytem as a requirement, meaning that it won’t cancel existing drivetrain commands, and might potentially end up fighting against them.

I would log the Command Scheduler to SmartDashboard or Shuffleboard to see exactly what commands are running.

The way you are rotating the robot by modifying the swerve request instead of applying another swerve request is kinda weird.