Coding for AprilTag IDs with a Limelight

Like the thing next to my username, I am quite new to Programming, the team I am in uses Java programming, and the main issue I am having is that I am trying to make some code that runs when the robot detects a specific ID on the AprilTag, I tried checking the AprilTag documentation. If you want to check the code, here it is: GitHub - SmartKirb99/Other-Chassis-Bot
I don’t know what to do…

Do you need it to detect other tags? If not the easiest thing to do is to use the limelights built in tag filtering.

Currently, it would be quite helpful, mainly since I’m supposed to learn how to do so on a Chassis Robot before trying to program my team’s main robot.

At this point (may change in the nearish (hopefully) future you need to use LimeLightHelper and iterate through the targets fiducial looking at the ID of each.

hmm… I know that the ID’s of the Apriltags I am using are 6, and 7

I currently have the limelight helper in the code, but now I am struggling with making the if statement of if the limelight detects an Apriltag of, let’s say 7. Currently, as a placeholder, I am making a print statement run when I spot the ID

See this code here for some of the general idea of getting a “result” using Limelight helper.

You will want to do:

for (LimelightTarget_Fiducial target: result.targets_Fiducials) {
  if (target.fiducialID == 7) {
    // Do your stuff here
  }
}

Thanks for the help, I did notice though that the code is meant for Swerve Drive, currently I am trying to get code working for an Arcade Drive Robot (It has rollers on the front and back wheels, which I believe makes the robot have easier mobility). Is there any code I would have to change to make the current code work with the robot I am trying to program?

It wouldn’t change the LL detection stuff but will probably affect what you do with the LL results.

The usage will probably be similar in that you will want to use PID to control rotation

I believe the robot I am programming also doesn’t have PID, I assume that because the robot I’m testing it on has VictorSPX as the motor controllers

Here is a simple “P” controller…

 public double getRotationalRate() {
    // if we don't see a game piece don't turn
    if (!this.isGamePieceFound()) {
      return 0;
    }

    double answer = 0;
    double offset = -Math.toRadians(m_LL_GamePiece.getEntry("tx").getDouble(0));

    double deadzone = 0.05; // TODO tune this
    double kP = 1.5; // TODO tune this
    double kS = 0.1; // TODO tune this

    if (offset < 0.0) {
      kS = kS * -1;
    }

    answer = (offset * kP) + kS;

    if (Math.abs(offset) < deadzone) {
      answer = 0;
    }

    return answer;
  }

Assuming tank drive…. Use the answer to feed your left side drive train and use the negative of answer to feed your right side drive train. (Or maybe that is reversed…)

I believe it might be tank drive, According to other sources, there are 4 omni wheels(This is what I got from other sources) and 2 general use tank drive wheels

https://docs.wpilib.org/en/stable/docs/software/hardware-apis/motors/wpi-drive-classes.html#drive-modes

I looked at the document, which shows that it is an Arcade Drive Robot because I noticed that my code has a speed function and a turn function

Great! So then feed answer into the drive as turning input.

Ok, albeit I don’t know which file to put the code into

This is a tough learning curve! Keep at it! Keep it simple.

In your limelight subsystem put the code to calculate the answer.

And this is NOT what you should do for your final robot…. But to play with it and learn from it….

In your RobotContainer replace the portion of the drive command that uses the joystick to use answer calculated from the limelight subsystem.

It would look something like…

driveSubsystem.setDefaultCommand(new ArcadeDriveCMD(driveSubsystem, () -> joystick2.getLeftY(), () -> limelight.getRotationalRate()));

Then in theory when it sees the April tag the robot should turn to face it.

It seems the code gives me some errors after implementing my code. Mainly the issues are in the limelight file but it also puts some errors in my code, such as “The constructor ArcadeDriveCMD(DriveSubsystem, () → {}, () → {}, () → {}) is undefined”. I copied the line of code and changed it to the code recommended, but it also gave errors. One of which being “The Constructor ArcadeDriveCMD(DriveSubsystem, DoubleSupplier, () → is undefined” and “limelight cannot be resolved”. So I changed limelight to Limelight, then it asked for an import so I did so, then it said that non-static doesn’t work for static, which broke the if statement of if the game piece isn’t found, which already has an error for the method not being defined, and the m_LL_Gamepiece cannot be resolved, and gives me a syntax error on the semicolon for defining kS.

OK… A couple of things:

In your RobotContainer class you need to instantiate your Limelight subsystem.

private Limelight limelight = new Limelight();

Inside your Limelight.java you need to create a function that determines whether the Limelight sees the target or not. In my pseudocode I had “isGamePieceFound()” but you need to create it.

something like:

public boolean isGamePieceFound() {
    double d = 0.0;

    // do we see the correct target
    d = NetworkTableInstance.getDefault().getTable("limelight").getEntry("tv").getDouble(0);
    if (d > 0) {
      return true;
    } 
    return false;
}

I hope this gets you closer!

I seem to have less errors now thanks to adding the code in, but I still seem to have an error relating to being unable to make a static reference to the non-static method of getRotationRate(), alongside m_LL_Gamepiece being unable to be resolved, the kS double semicolon having a syntax error with the code expecting {}, and the end part of the entire code, not anything inside the code just the curly brace/bracket that goes with the start of the limelight code having a syntax error saying to insert } to complete ClassBody, but I figured out to fix that I just needed an excess }.

Edit: My team’s programming mentor helped out, apparently I don’t need a Limelight Subsystem as I have the LimelightHelpers file