We'll start with a pretty basic example that uses VisionPortal to run the the bundled AprilTagProcessor and explain line by line:
importcom.qualcomm.robotcore.eventloop.opmode.Disabled;importcom.qualcomm.robotcore.eventloop.opmode.LinearOpMode;importcom.qualcomm.robotcore.eventloop.opmode.TeleOp;importorg.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName;importorg.firstinspires.ftc.vision.VisionPortal;importorg.firstinspires.ftc.vision.apriltag.AprilTagDetection;importorg.firstinspires.ftc.vision.apriltag.AprilTagProcessor;@Autonomous(name ="Example VisionPortal OpMode")publicclassExampleVisionPortalOpModeextendsLinearOpMode { /** * The variable to store our instance of the AprilTag processor. */privateAprilTagProcessor aprilTag; /** * The variable to store our instance of the vision portal. */privateVisionPortal visionPortal; @OverridepublicvoidrunOpMode() { visionPortal =VisionPortal.easyCreateWithDefaults(hardwareMap.get(WebcamName.class,"Webcam 1"), aprilTag);telemetry.addData(">","Touch Play to start OpMode");telemetry.update();// Wait for the DS start button to be touched.``waitForStart();if (opModeIsActive()) {// ... }// Save more CPU resources when camera is no longer needed.visionPortal.close(); }}
Declares our LinearOpMode and annotates it as an autonomous program. LinearOpMode is often more useful when coding autonomous routines due to its inherent structure.
/** * The variable to store our instance of the AprilTag processor. */privateAprilTagProcessor aprilTag; /** * The variable to store our instance of the vision portal. */privateVisionPortal visionPortal;
Some convenience variables that will let us store our VisionProcessor and VisionPortal instances that we will be using later on.
@OverridepublicvoidrunOpMode() {
Inherits the method from LinearOpMode that will be executed when the OpMode is initialized. Any code put in here will be executed as a result.
// Create the AprilTag processor the easy way. aprilTag =AprilTagProcessor.easyCreateWithDefaults();// Create the vision portal the easy way. visionPortal =VisionPortal.easyCreateWithDefaults(hardwareMap.get(WebcamName.class,"Webcam 1"), aprilTag);
This is the key part of our image processing initialization; we'll create our AprilTagProcessor and VisionPortal instances by using easyCreateWithDefaults()methods, which allows us to effortlessly initialize things by only passing a few parameters.
We'll make a special emphasis on this part;
hardwareMap.get(WebcamName.class,"Webcam 1")
This line basically defines what will be the source of our images that are passed onto the attached VisionProcessors, usually a webcam for that matter. "Webcam 1" indicates the robot configuration name of the image capture device we wish to use, as it is commonly the default name automatically assigned by the FTC SDK.
In the case of EOCV-Sim, fortunately we have quite some other options here in order to provide more flexibility when it comes to testing your vision code;
Using other input sources in your OpModes
WebcamName code examples
USB Cameras
hardwareMap.get(WebcamName.class,"Webcam 1");hardwareMap.get(WebcamName.class,"0"); // Same as "Webcam 1"hardwareMap.get(WebcamName.class,"1"); // Other webcamhardwareMap.get(WebcamName.class,"2"); // Other webcam
"Webcam 1" refers to the first USB camera detected by your operating system
In order to use other cameras, you will need to enter their index number. "0" is the same as "Webcam 1", but you can specify any number that ranges from 0 to (n-1), where n is the number of USB cameras currently plugged.
Image
Images are specified by providing their absolute path as a WebcamName, the simulator automatically determines if it's an image by the file's extension.
Examples: "C:\Users\pepito\Pictures\OnePixel.png"
"/Users/PepitoRico/Downloads/OnePixel.png"
Video
Videos are pretty much the same as images, as they are specified by providing their absolute path as a WebcamName, the simulator automatically determines if it's an video by the file's extension. Note that mp4 is most likely not supported due to licensing issues.