package org.firstinspires.ftc.teamcode.auto; import android.annotation.SuppressLint; import com.acmerobotics.dashboard.FtcDashboard; import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName; import org.firstinspires.ftc.teamcode.config.RuntimeConfig; import org.openftc.apriltag.AprilTagDetection; import org.openftc.easyopencv.OpenCvCamera; import org.openftc.easyopencv.OpenCvCameraFactory; import org.openftc.easyopencv.OpenCvCameraRotation; import java.util.ArrayList; public abstract class AprilTagAutonBase extends LinearOpMode { OpenCvCamera camera; AprilTagDetectionPipeline aprilTagDetectionPipeline; // Lens intrinsics // UNITS ARE PIXELS // NOTE: this calibration is for the C920 webcam at 800x448. // You will need to do your own calibration for other configurations! double fx = 578.272; double fy = 578.272; double cx = 402.145; double cy = 221.506; // UNITS ARE METERS double tagSize = 0.0381; // 1.5 in // All from the 36h11 family int[][] ID_TAGS_OF_INTEREST = { { 584, 449, 275, }, { 125, 345, 392, }, { 87, 93, 554 }, { 1, 2, 3 } }; int VARIANT_COUNT = ID_TAGS_OF_INTEREST.length; AprilTagDetection[][] tagsOfInterest = new AprilTagDetection[VARIANT_COUNT][3]; abstract void onInit(); abstract void onPlay(int signalZone); @Override public void runOpMode() { if (RuntimeConfig.SIGNAL_SLEEVE_VARIANT == null) { double endTime = getRuntime() + 5; while (!isStarted() && getRuntime() < endTime) { telemetry.addLine("Signal sleeve variant not set!"); telemetry.addLine("Press play or wait 5 seconds to end the opmode."); telemetry.addLine("Here is a flashing block to get your attention:"); telemetry.addLine("####################################"); telemetry.addLine("####################################"); telemetry.addLine("####################################"); telemetry.update(); telemetry.addLine("Signal sleeve variant not set!"); telemetry.addLine("Press play or wait 5 seconds to end the opmode."); telemetry.addLine("Here is a flashing block to get your attention:"); telemetry.addLine(""); telemetry.addLine(""); telemetry.addLine(""); telemetry.update(); } return; } onInit(); int cameraMonitorViewId = hardwareMap.appContext.getResources().getIdentifier("cameraMonitorViewId", "id", hardwareMap.appContext.getPackageName()); camera = OpenCvCameraFactory.getInstance().createWebcam(hardwareMap.get(WebcamName.class, "Webcam 1"), cameraMonitorViewId); aprilTagDetectionPipeline = new AprilTagDetectionPipeline(tagSize, fx, fy, cx, cy); camera.setPipeline(aprilTagDetectionPipeline); camera.openCameraDeviceAsync(new OpenCvCamera.AsyncCameraOpenListener() { @Override public void onOpened() { camera.startStreaming(800,448, OpenCvCameraRotation.SIDEWAYS_RIGHT); FtcDashboard dashboard = FtcDashboard.getInstance(); dashboard.startCameraStream(camera, 0); } @Override public void onError(int errorCode) {} }); telemetry.setMsTransmissionInterval(50); Integer[] mostRecentlySeenPerVariant = new Integer[VARIANT_COUNT]; /* * The INIT-loop: * This REPLACES waitForStart! */ while (!isStarted() && !isStopRequested()) { telemetry.addLine("Chosen variant: " + RuntimeConfig.signalSleeveVariantName()); ArrayList currentDetections = aprilTagDetectionPipeline.getLatestDetections(); ArrayList[] tagsFound = new ArrayList[VARIANT_COUNT]; // fill the array, cause i dont know how to do this better for (int i = 0; i < tagsFound.length; i++) tagsFound[i] = new ArrayList<>(); for (AprilTagDetection tag : currentDetections) { for (int variant_index = 0; variant_index < VARIANT_COUNT; variant_index++) { for (int id_index = 0; id_index < 3; id_index++) { if (tag.id == ID_TAGS_OF_INTEREST[variant_index][id_index]) { tagsFound[variant_index].add(id_index); tagsOfInterest[variant_index][id_index] = tag; } } } } for (int variant_index = 0; variant_index < VARIANT_COUNT; variant_index++) { if (tagsFound[variant_index].size() == 1) { mostRecentlySeenPerVariant[variant_index] = tagsFound[variant_index].get(0); } } if (tagsFound[RuntimeConfig.SIGNAL_SLEEVE_VARIANT].size() == 1) { int id = mostRecentlySeenPerVariant[RuntimeConfig.SIGNAL_SLEEVE_VARIANT]; telemetry.addLine("Tag " + RuntimeConfig.signalSleeveVariantName() + "-" + (id + 1) + " is in sight!\n\nLocation data:"); tagToTelemetry(tagsOfInterest[RuntimeConfig.SIGNAL_SLEEVE_VARIANT][id]); } else { telemetry.addLine("Don't currently see any tags from variant " + RuntimeConfig.signalSleeveVariantName() + " :("); if (mostRecentlySeenPerVariant[RuntimeConfig.SIGNAL_SLEEVE_VARIANT] == null) { telemetry.addLine("(No tags have ever been seen)"); } else { int id = mostRecentlySeenPerVariant[RuntimeConfig.SIGNAL_SLEEVE_VARIANT]; telemetry.addLine("\nBut we HAVE seen tags before; tag " + RuntimeConfig.signalSleeveVariantName() + "-" + (id + 1) + " last seen at:"); tagToTelemetry(tagsOfInterest[RuntimeConfig.SIGNAL_SLEEVE_VARIANT][id]); } } telemetry.update(); sleep(20); } /* * The START command just came in: now work off the latest snapshot acquired * during the init loop. */ int signalZone; if (mostRecentlySeenPerVariant[RuntimeConfig.SIGNAL_SLEEVE_VARIANT] == null) { telemetry.addLine("Uh oh, we never saw variant " + RuntimeConfig.signalSleeveVariantName() + "! Checking other variants..."); Integer id = null; Integer variant = null; for (int variant_index = 0; variant_index < VARIANT_COUNT; variant_index++) { if (mostRecentlySeenPerVariant[variant_index] != null) { id = mostRecentlySeenPerVariant[variant_index]; variant = variant_index; } } if (id != null) { telemetry.addLine("We saw tag " + RuntimeConfig.signalSleeveVariantName(variant) + "-" + (id + 1) + " at some point, using that."); signalZone = id; } else { telemetry.addLine("Nope, nothing, nada, defaulting to signal zone 1."); signalZone = 1; } telemetry.update(); } else { signalZone = mostRecentlySeenPerVariant[RuntimeConfig.SIGNAL_SLEEVE_VARIANT]; } this.onPlay(signalZone + 1); } @SuppressLint("DefaultLocale") void tagToTelemetry(AprilTagDetection detection) { telemetry.addLine(String.format("\nDetected tag ID=%d", detection.id)); telemetry.addLine(String.format("Translation X: %.2f metres", detection.pose.x)); telemetry.addLine(String.format("Translation Y: %.2f metres", detection.pose.y)); telemetry.addLine(String.format("Translation Z: %.2f metres", detection.pose.z)); 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))); } }