Skip to content
CrocoDocs
Starter GuideProgrammingEngineeringDesignPortfolio
Documentation

Introduction

IntroductionBIOBUZZ game overview

Getting started

Getting startedBlocksOnBot JavaAndroid StudioYour first OpModeJava basicsMotors and servosNonblocking codeDebugging robot code

Control systems

Control systemsJoystick mappingField-centric mecanum drivePID controlFeedforwardFlywheel velocity controlSystem identificationMotion profilingKalman filterLow-pass filter

Autonomous

AutonomousTimed and encoder movementOdometryLocalization troubleshootingMotion planningReliable autonomous sequencesPure PursuitSensor fusionAuto to TeleOp handoff

Season topics

Season topicsProjectile mathematicsTurret aimingShooting on the move

Code practices

Code practicesNaming conventionsCode organizationLoop timing and bulk readsFormattingComments and documentationTeam collaboration

Libraries

LibrariesNextFTCFTCLibSolversLibPedro PathingRoad RunnerFTC DashboardMercurial v2Mercurial v1PanelsSloth

Community software

Community softwareBlaze FTCOpenLoopHive Vision

Sensors and vision

Vision overviewVision basicsLimelight 3A
Vision in autonomous
Vision troubleshooting
Starter Guide
Engineering
Design
Portfolio
Appearance
Advanced Topics

Vision in autonomous

Turn a tested camera detection into a safe autonomous choice

The camera should answer a small question for the , such as “is the practice target on the left, middle, or right?” Keep image processing separate from driving: first display the answer, check that it is stable, and only then let the answer choose a path.

This lesson uses the SDK VisionPortal and ColorBlobLocatorProcessor. It assumes you have already opened a camera and can read blobs. If not, complete VisionPortal and Color Blob Locator first.

Integration plan

  1. Open the camera and processor during OpMode initialization.
  2. While the is still waiting to start, display the current detection.
  3. Convert a blob's horizontal center into a simple label.
  4. Freeze that label when starts.
  5. Choose a route from the frozen label, with a safe fallback if nothing was seen.

The source Pollen image used for the controlled color-detection example.

This controlled product photo is not a camera calibration or field capture.

Image regions

Image coordinates start at the top-left: x = 0 is the left edge and larger x values are farther right. The exact width depends on the camera resolution. For example, if the frame is 640 pixels wide, the midpoint is 320.

Do not start with game-specific colors or locations copied from an old . Use a practice object and verify its measured position in the real camera preview.

Target classification

First define the possible answers and a variable to hold one of them:

enum PropPosition { LEFT, CENTER, RIGHT, NOT_FOUND }
PropPosition position = PropPosition.NOT_FOUND;
enum class PropPosition { LEFT, CENTER, RIGHT, NOT_FOUND }
var position = PropPosition.NOT_FOUND

After the processor has produced a list of blobs, handle the empty case before reading an element. If the list is not empty, use the center of the largest blob and compare it with thirds of the frame. Set frameWidth to the width of your camera resolution:

if (blobs.isEmpty()) {
    position = PropPosition.NOT_FOUND;
} else {
    double centerX = blobs.get(0).getBoxFit().center.x;

    if (centerX < frameWidth / 3.0) {
        position = PropPosition.LEFT;
    } else if (centerX < 2.0 * frameWidth / 3.0) {
        position = PropPosition.CENTER;
    } else {
        position = PropPosition.RIGHT;
    }
}
if (blobs.isEmpty()) {
    position = PropPosition.NOT_FOUND
} else {
    val centerX = blobs[0].getBoxFit().center.x

    position = when {
        centerX < frameWidth / 3.0 -> PropPosition.LEFT
        centerX < 2.0 * frameWidth / 3.0 -> PropPosition.CENTER
        else -> PropPosition.RIGHT
    }
}

This assumes blobs has already been sorted largest-first, as shown in the Color Blob Locator guide. If it has not, sort it first or choose a blob deliberately. The thirds are just a starting point; draw the boundaries on the preview and adjust them for your camera and target.

The detected center is compared with the left, center, and right thirds of this example frame; here the measured pixel is in the center third.

The marker shows the result after detection: the object center becomes a simple label. The thirds are an example decision rule, not a built-in FTC feature. On the robot, verify the camera width and zone boundaries in the live preview before choosing an autonomous route.

Classification telemetry

During the period, show the label and useful measurements in telemetry. This helps you check framing and thresholds while the robot is stationary. Do not command the during this exercise.

telemetry.addData("Position", position);
telemetry.addData("Blob count", blobs.size());
telemetry.update();
telemetry.addData("Position", position)
telemetry.addData("Blob count", blobs.size)
telemetry.update()

If the label flickers, check the camera mount, lighting, and color thresholds first. You can require the same label across several frames, but add that only after you can explain what the raw detections are doing.

Freezing the selection

When the starts autonomous, copy the current label into a separate selectedPosition value. Disable the color processor if you no longer need it. The choice should not silently change halfway through a route because a later frame saw a different blob.

Always decide what to do for NOT_FOUND. A safe default can be a short, tested route or remaining still. Do not let a missing detection fall through to an uninitialized path.

Route selection

The route-selection logic should be small and explicit:

switch (selectedPosition) {
    case LEFT:
        runLeftRoute();
        break;
    case CENTER:
        runCenterRoute();
        break;
    case RIGHT:
        runRightRoute();
        break;
    case NOT_FOUND:
        runSafeFallback();
        break;
}
when (selectedPosition) {
    PropPosition.LEFT -> runLeftRoute()
    PropPosition.CENTER -> runCenterRoute()
    PropPosition.RIGHT -> runRightRoute()
    PropPosition.NOT_FOUND -> runSafeFallback()
}

These route methods stand for your tested drive code; they are not FTC SDK methods. Start with slow, short movements in a clear practice area, keep a stop condition in every loop, and have a check the robot before testing near people or field elements.

Code placement

For a first autonomous OpMode, keeping camera setup and the label logic together is easier to follow. Once several OpModes need the same camera behavior, move setup and detection into a small Vision class that exposes a result such as LEFT, CENTER, or NOT_FOUND. Keep route selection in the OpMode so it remains clear what the robot will do.

Avoid copying old command-framework vision examples into a current project. FTC SDK camera APIs and library APIs evolve separately; this guide uses FTC SDK types and does not require Mercurial or NextFTC.

Integration checks

  • The preview clearly shows the practice target.
  • Each target position produces the expected label during INIT.
  • The empty-detection case is handled.
  • The selected label is saved when autonomous starts.
  • The fallback route is safe and tested.
  • Drive loops stop when the OpMode is stopped or the target is reached.

Next, review AprilTag detection for pose estimates, or Vision Troubleshooting if the camera result is unstable.

Sources

  • AndyMark: BIOBUZZ scoring elements — source photo

AprilTag detection

Read FTC AprilTag detections safely, including SDK 12 clusters

Vision troubleshooting

Diagnose camera and detection problems one step at a time

On this page

Integration planImage regionsTarget classificationClassification telemetryFreezing the selectionRoute selectionCode placementIntegration checksSources