Photon Vision Apriltag Targeting

I am a programmer on team 2977. We are using photon vision to target apriltags for shooting into the speaker. Photon vision gets the best apriltag and I don’t know how to change that. I want to target the apriltag directly under the speaker, not the one off to the side. But photon vision gets whatever it sees better.

How can I target a specific apriltag?

1 Like

Instead of calling result.getBestTarget() you can call:

List<PhotonTrackedTarget> targets = result.getTargets();

That will give you the complete list. You can then check the id of each returned target for the tag id:

int targetID = target.getFiducialId();

Good luck!

2 Likes

I’ll try that out. Thank you

You could also try instead of targeting off of one tag, using a pose estimator to estimate the robot pose and calculate from there. This introduces more complexity but it also might lead to more accurate positioning data drawing from multiple targets.

1 Like

When I use the code written below, it works to target the apriltag with a bigger fiducial ID. But when there is only one apriltag, The code crashes. is there a way around that?

var cameraToTarget = targets.get(1).getBestCameraToTarget();

Thank you for the idea. I will try that out as soon as I can get the robotPose working.

Lists are zero based, so to get the first element in the list you should use index 0. However, I don’t think there’s any guarantee on the order of results, so I recommend checking all targets, and existing after you find one with the tag ID you’re looking for.

How do I cycle through the list of apriltags photon vision captured?

Or how do I check the length of a list?

If you’ll look at PhotonLib’s Java API reference for getTargets() you’ll see it returns a regular Java List, which you can find a description of all methods here:

Thank you. That helped me a lot. I couldn’t find the Java API.

1 Like

Could someone be more specific how I can focus on one target and ignore the others? One speaker has a center AprilTag of 4 and the other is AprilTag 8. I just want to focus on those tags.

Pseudo code here as I am just typing on the fly… But if you have questions let me know.

//Assume camera is your photonVision camera/pipeline, etc.. 
if (camera.hasTargets())
{
  List<PhotonTrackedTarget>targets = camer.getTargets();
  for (PhotonTrackedTarget target in targets) 
  {
    int targetId = target.getFiducialId();
    if (targetId == myTargetICareAbout)
    {
      //Do something with this target.. Get the Pose2d, etc.
    }
  } // end for
} // end hasTargets
1 Like

Does the for loop in your code go through all the targets found? I will see if I can make sense out of your code.

Correct, you can also add a break at the end of the if, if you have found the target you care about.

The pseudo code for the for loop is a for each… In Java it looks like the below.

//Loop through all targets, one at a time.
for (PhotonTrackedTarget target : targets)
{
 ... 
 if (..) { 
  break;   // Break out of the rest of the for loop since we found the only item we care about
 }
}
1 Like

I would need examples of actual code to understand. For loops generally go through integers from 1 to something until a condition hits.

The code Rick provided is very similar (if not identical) to real Java code. You should read about for-each loops if you’re not familiar with them:
https://www.geeksforgeeks.org/for-each-loop-in-java/amp/

1 Like

I was able to get the apriltag I wanted by using the code below.

 var foundTargets = targets.stream().filter(t -> t.getFiducialId() == 4)
                      .filter(t -> !t.equals(4) && t.getPoseAmbiguity() <= .2 && t.getPoseAmbiguity() != -1)
                      .findFirst();
 var result = photoncamera.getLatestResult();
    
      
    
    if (result.hasTargets()) {
    //LIST of targets photon vision has
    targets = result.getTargets();

    //checks to see if there is a list of apriltags to check. if no targets are visable, end command
      if (targets.isEmpty()) {
        SmartDashboard.putBoolean("done", true);
      }

     var foundTargets = targets.stream().filter(t -> t.getFiducialId() == 4)
                      .filter(t -> !t.equals(4) && t.getPoseAmbiguity() <= .2 && t.getPoseAmbiguity() != -1)
                      .findFirst();

      if (foundTargets.isPresent()) {
     var cameraToTarget = foundTargets.get().getBestCameraToTarget();
}}

Edit: for clarification, if you replace the 4 with a different apriltag fiducial id you can get a different apriltag.

That looks like something I can work with. Thank you.

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.