FTC++
  • Home
  • 📷Vision
    • Introduction
    • AprilTags
    • Bitmaps
    • Custom Algorithms
  • 🔢Data
    • Introduction
    • Moving Average Filter
    • Kalman Filter
    • Sensor Fusion
    • Multi-Variable Kalman Filter
  • 🎮Control Theory
    • Introduction
    • State Space Control
    • Linear Quadratic Regulator
    • Model Predictive Control
    • Odometry
  • 🧊3D Modelling
    • Odometry pods
    • Sensors
    • Turrets
  • 📚Resources
    • Resources
Powered by GitBook
On this page
  1. Vision

AprilTags

april tag + opencv

PreviousIntroductionNextBitmaps

Last updated 1 year ago

picture by Iron Reign

AprilTags are a type of visual fiducial marker system used in robotics, computer vision, and augmented reality applications. They are designed to be easily detectable and uniquely identifiable by computer vision algorithms. The term "AprilTag" is specific to a particular implementation of these markers developed by the April Robotics Lab at the University of Michigan.

AprilTags work by encoding a pattern of black and white squares, forming a unique binary code. The code consists of a central black square surrounded by a grid of smaller black and white squares, representing a specific marker ID. Each marker can be uniquely identified by its binary code, allowing for quick and accurate detection.

When a camera captures an image or a video frame, computer vision algorithms process the data to identify AprilTags in the scene. The algorithms look for the distinctive black and white square patterns and use the binary code to determine the marker's ID. The marker's location and orientation in the image can also be determined based on the positions of the corner points of the detected pattern.

AprilTags are robust and efficient, making them popular for various applications in robotics and augmented reality. They are used for tasks such as robot localization (determining a robot's position and orientation in a known environment), object tracking, augmented reality marker-based tracking, and more.

Due to their ease of use and accuracy, AprilTags have become a popular choice in robotics competitions like FTC and other robotics challenges, where precise localization and identification of objects and markers are crucial for successful navigation and task completion.

Alright, now that we know what april tags are, lets figure out how to implement it. lets first import the necessary libraries

import android.annotation.SuppressLint;
import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
import org.openftc.easyopencv.OpenCvCamera;
import org.openftc.easyopencv.OpenCvCameraRotation;
import org.openftc.easyopencv.OpenCvCameraFactory;
import com.qualcomm.robotcore.hardware.WebcamName;
import org.openftc.apriltag.AprilTagDetection;
import org.firstinspires.ftc.teamcode.opencv.AprilTagDetectionPipeline; // New import
import java.util.ArrayList;

Remember to add the AprilTagDetection Pipeline to your coding repository also keep them in a designated OpenCV folder Which can be downloaded here NOT NEEDED AFTER V8.2

public class AprilTagDetectionOpMode extends LinearOpMode {
    // Declare necessary variables
    OpenCvCamera camera;
    AprilTagDetectionPipeline aprilTagDetectionPipeline;

    // Camera calibration parameters
    double fx = 578.272;
    double fy = 578.272;
    double cx = 402.145;
    double cy = 221.506;
    double tagsize = 0.166;

    int ONE = 1;
    int TWO = 2;
    int THREE = 3;

    AprilTagDetection tagOfInterest = null;
  • This part includes necessary imports and declares the class AprilTagDetectionOpMode which extends LinearOpMode (an FTC class for linear OpModes).

  • It declares the necessary variables for the OpMode, including the camera, the AprilTag detection pipeline, camera calibration parameters (fx, fy, cx, cy, and tagsize), and some tag IDs (ONE, TWO, and THREE) to identify the tags of interest.

  • tagOfInterest is declared to hold the detected AprilTag of interest.

  • fx and fy are the focal length in pixels. cx and cy are the optical center coordinates in pixels.

@Override
    public void runOpMode() {
        // Get the camera monitor view ID
        int cameraMonitorViewId = hardwareMap.appContext.getResources().getIdentifier("cameraMonitorViewId", "id", hardwareMap.appContext.getPackageName());

        // Create the webcam and the AprilTag detection pipeline
        camera = OpenCvCameraFactory.getInstance().createWebcam(hardwareMap.get(WebcamName.class, "Webcam 1"), cameraMonitorViewId);
        aprilTagDetectionPipeline = new AprilTagDetectionPipeline(tagsize, fx, fy, cx, cy);

        // Set the pipeline to the camera
        camera.setPipeline(aprilTagDetectionPipeline);

        // Asynchronously open the camera device
        camera.openCameraDeviceAsync(new OpenCvCamera.AsyncCameraOpenListener() {
            @Override
            public void onOpened() {
                // Start streaming frames from the camera with the desired resolution and rotation
                camera.startStreaming(800, 600, OpenCvCameraRotation.UPRIGHT);
            }

            @Override
            public void onError(int errorCode) {
                // Handle any errors that may occur during camera opening
            }
        });
  • This is the main method of the OpMode that will run when the OpMode is started.

  • It starts by getting the camera monitor view ID from the app context to display the camera stream on the driver station.

  • Next, it creates the webcam and the AprilTag detection pipeline using the specified calibration parameters.

  • The pipeline is set to the camera so that it can process frames from the camera in real-time.

  • The camera is asynchronously opened, and when it is successfully opened, streaming of frames begins with the desired resolution and rotation (portrait mode in this case).

// Set the telemetry transmission interval
        telemetry.setMsTransmissionInterval(50);

        // WHILE WAIT FOR START, FIND APRIL TAG ------------------------------------------------------
        while (!isStarted() && !isStopRequested()) {
            // Get the latest AprilTag detections from the pipeline
            ArrayList<AprilTagDetection> currentDetections = aprilTagDetectionPipeline.getLatestDetections();

            // Check if any of the AprilTags of interest are detected
            if (currentDetections.size() != 0) {
                boolean tagFound = false;
                for (AprilTagDetection tag : currentDetections) {
                    if (tag.id == ONE || tag.id == TWO || tag.id == THREE) {
                        tagOfInterest = tag;
                        tagFound = true;
                        break;
                    }
                }

                // Display telemetry based on whether the tag is found
                if (tagFound) {
                    telemetry.addLine("Tag of interest is in sight!\n\nLocation data:");
                    tagToTelemetry(tagOfInterest);
                } else {
                    telemetry.addLine("Don't see tag of interest :(");
                    if (tagOfInterest == null) {
                        telemetry.addLine("(The tag has never been seen)");
                    } else {
                        telemetry.addLine("\nBut we HAVE seen the tag before; last seen at:");
                        tagToTelemetry(tagOfInterest);
                    }
                }
            } else {
                telemetry.addLine("Don't see tag of interest :(");
                if (tagOfInterest == null) {
                    telemetry.addLine("(The tag has never been seen)");
                } else {
                    telemetry.addLine("\nBut we HAVE seen the tag before; last seen at:");
                    tagToTelemetry(tagOfInterest);
                }
            }

            // Update the telemetry and sleep for a short duration
            telemetry.update();
            sleep(20);
        }

        // Stop the camera streaming
        camera.stopStreaming();
    }
  • The OpMode enters a loop that continues until it is started or stopped.

  • Inside the loop, it retrieves the latest AprilTag detections from the pipeline.

  • It then checks if any of the tags of interest (IDs 1, 2, or 3) are present in the current detections.

  • If a tag of interest is found, it updates the tagOfInterest variable and displays telemetry indicating the tag's presence and its location data.

  • If no tag of interest is found, it displays appropriate telemetry messages indicating that the tag is not in sight or that it has been seen before.

  • The telemetry is updated and the loop sleeps for a short duration (20 milliseconds) before continuing.

@SuppressLint("DefaultLocale")
void tagToTelemetry(AprilTagDetection detection) {
    // Display the detected AprilTag's information in telemetry
    telemetry.addLine(String.format("\nDetected tag ID=%d", detection.id));
    telemetry.addLine(String.format("Translation X: %.2f feet", detection.pose.x * FEET_PER_METER));
    telemetry.addLine(String.format("Translation Y: %.2f feet", detection.pose.y * FEET_PER_METER));
    telemetry.addLine(String.format("Translation Z: %.2f feet", detection.pose.z * FEET_PER_METER));
    telemetry.addLine(String.format("Rotation Yaw: %.2f degrees", Math.toDegrees(detection.pose.yaw)));
    telemetry.addLine(String.format("Rotation Pitch: %.2f degrees", Math.toDegrees(detection.pose.pitch)));
    telemetry.addLine(String.format("Rotation Roll: %.2f degrees", Math.toDegrees(detection.pose.roll)));
}
  • This method is used to display the detected AprilTag's information in telemetry.

  • The method takes an AprilTagDetection object as a parameter, which contains information about the detected tag, including its ID and pose.

  • The telemetry object is used to display the tag's ID and pose information in degrees and feet, converted from meters using the FEET_PER_METER constant (not shown in the provided code).

That's the complete breakdown of the code. The OpMode continuously processes frames from the camera, detects AprilTags, and provides real-time telemetry feedback about the detected tags, including their IDs and 6DOF pose (translation and rotation information) relative to the camera. Hopefuly you found this helpful

📷
😄
10KB
AprilTagDetectionPipeline.java
needed library for this project