Skip to main content

Lesson 11.3: Sampling Alliance Colors with the REV Color Sensor


The Challenge of Color Detection Under Field Lighting

RGB color sensing sounds straightforward until you run it at a real competition venue. Stadium lighting varies between arenas, and shadow from the robot itself or from game elements can shift the raw channel values by a significant margin between one match and the next. A threshold that worked in your school gymnasium may completely fail under the bright LEDs of a competition field.

The key insight that makes color detection robust is that you rarely need to match an exact value. What you need is to determine which color component is dominant. A red game element will always have a higher red() reading than blue() or green() under almost any reasonable lighting condition, because the fundamental reflectance properties of the object do not change even if the overall brightness does. Comparing the channels against each other instead of against absolute constants is what separates reliable autonomous code from code that works only in practice.


ColorSensor in the SDK

The ColorSensor class provides three primary methods for reading individual color channels: red(), green(), and blue(). Each returns an int in the range of 0 to 255 -- larger values mean more of that color wavelength is being reflected back to the sensor.

The sensor operates using an internal white LED that illuminates the target surface. The photodetector then measures how much of each wavelength the surface reflects back. This means the proximity of the sensor to the object matters for consistent readings. The REV Color Sensor works best when held a few millimeters to a few centimeters from the target. Mounting it at a fixed, known distance from the scoring area or intake opening produces far more repeatable results than a sensor that can wobble or shift position.

A combined ARGB value is also accessible through argb(), which packs all four channels into a single int. For most FTC use cases, working with the individual channel methods is cleaner and more readable than unpacking a packed integer.


Annotated Code

package org.firstinspires.ftc.teamcode;

import com.qualcomm.robotcore.eventloop.opmode.OpMode;
import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
import com.qualcomm.robotcore.hardware.ColorSensor;
import com.qualcomm.robotcore.hardware.DcMotor;

@TeleOp(name="Color_Sensor_Demo")
public class ColorSensorDemo extends OpMode {

private ColorSensor intakeSensor;
private DcMotor intakeMotor;

@Override
public void init() {
intakeSensor = hardwareMap.get(ColorSensor.class, "intake_color");
intakeMotor = hardwareMap.get(DcMotor.class, "intake");
telemetry.addData("Status", "Color sensor ready");
}

@Override
public void loop() {
int r = intakeSensor.red();
int g = intakeSensor.green();
int b = intakeSensor.blue();

// Determine alliance color by comparing which component dominates
String detectedAlliance;
if (r > b && r > g) {
detectedAlliance = "RED";
intakeMotor.setPower(1.0); // Correct alliance -- collect it
} else if (b > r && b > g) {
detectedAlliance = "BLUE";
intakeMotor.setPower(-1.0); // Wrong alliance -- eject it
} else {
detectedAlliance = "UNKNOWN";
intakeMotor.setPower(0.0);
}

telemetry.addData("Alliance Detected", detectedAlliance);
telemetry.addData("R / G / B", "%d / %d / %d", r, g, b);
telemetry.update();
}
}

Fill-in-the-Blank Practice

  1. To read the intensity of the blue light channel from a ColorSensor, call colorSensor.__________().
  2. The individual channel methods (red(), green(), blue()) each return an __________ in the range of 0 to 255.
  3. For reliable alliance detection under varying field lighting, the recommended approach is to compare color channels __________ each other rather than against fixed absolute thresholds.
Show answers
  1. blue()
  2. int
  3. against (comparing relative channel dominance)

Template Challenge

Robot Scenario: Write a method called detectAlliance() that returns a String. If the red channel is greater than the blue channel, return "RED". If the blue channel is greater than the red channel, return "BLUE". Otherwise return "UNKNOWN". Assume colorSensor is already mapped as a class member.

package org.firstinspires.ftc.teamcode;

import com.qualcomm.robotcore.eventloop.opmode.OpMode;
import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
import com.qualcomm.robotcore.hardware.ColorSensor;

@TeleOp(name="Alliance_Detect_Challenge")
public class AllianceDetect extends OpMode {

private ColorSensor colorSensor;

@Override
public void init() {
colorSensor = hardwareMap.get(ColorSensor.class, "sensor");
}

// INSERT CODE HERE: Write the detectAlliance() method that returns a String
// "RED" if red > blue, "BLUE" if blue > red, "UNKNOWN" otherwise

@Override
public void loop() {
telemetry.addData("Alliance", detectAlliance());
telemetry.update();
}
}
Show answer
public String detectAlliance() {
if (colorSensor.red() > colorSensor.blue()) {
return "RED";
} else if (colorSensor.blue() > colorSensor.red()) {
return "BLUE";
} else {
return "UNKNOWN";
}
}

Ready to move on?

Sign in with Google to save your progress with Telemark, or continue without saving.