sensors.ColorSensor

class sensors.ColorSensor(port: Optional[int] = None)

Sensor for measuring colors from a camera.

The following example guides a line following robot that is preconfigured to follow the yellow line on the floor in the sandbox.

from dataclasses import dataclass
from sensors import ColorSensor
from inputs import *
from color import Color

@dataclass
class Configurables():
        # use the paint tools color picker to find the color of the line
        # this is a list because the line might have a few shades to it
        # the sensor will believe that it is over a line if it senses any of these
        line_colors = ["#FEF7B1","#FEEFAB"]

        # this script assumes that some kind wasd style control schemes
        # are set up to drive the robot around on one of the handed transmitters
        # you can pick which transmitter that is here
        transmitter_hand = Hand.LEFT
        transmitter_number = 0

        # this is the key that you press once you've line up the robot on the line
        activation_key = "x"

        # these lists hold the port numbers for color sensors
        # the left ones are all sensors that are left of the center of the robot
        # and the right ones are correspondingly on the right side
        # a good setup is to put all the sensors in one line perpendicular to the
        # drive direction. It's fine to just have one sensor on each side too
        left_sensor_ports = [i for i in range(0,7)]
        right_sensor_ports = [i for i in range(7,15)]

        # it's not a great idea to ask if 2 colors are exactly the same due to rounding
        # so we instead ask if the color is "within" some threshold. Between 0 and ~1.44
        color_threshold = .1

        # here's a tunable turn speed factor, bigger means the robot turns harder
        turn_factor = .25



configurables = Configurables()

transmitter = TransmitterReference(configurables.transmitter_hand,configurables.transmitter_number)
left_sensors = [ColorSensor(port) for port in configurables.left_sensor_ports]
right_sensor = [ColorSensor(port) for port in configurables.right_sensor_ports]


line_colors = [Color.from_hex(hex) for hex in configurables.line_colors]


def sense_line(sensor : ColorSensor) -> bool:
        # determines if the sensor is looking at the line
        sample = sensor.color()
        dists = [sample.distance(c) < configurables.color_threshold for c in line_colors]
        return any(dists)

# wait for the activation key to be hit
activation_stream = Input.stream(configurables.activation_key)
activated = False
while not activated:
        for event in activation_stream:
                if event == ButtonState.UP:
                        activated = True

# go forward
transmitter.press("up")
while True:
        # how many sensors on the left side are looking at the line?
        touching_left = [sense_line(sensor) for sensor in left_sensors].count(True)
        # how many on the right side?
        touching_right = [sense_line(sensor) for sensor in right_sensor].count(True)
        # theta represents "how much" to the left we want to turn
        theta = (touching_left - touching_right) / len(left_sensors + right_sensor)
        if theta > 0:
                # we want to turn left
                transmitter.press("up",.51)
                transmitter.press("R",0)
                transmitter.press("L",.5 + theta * configurables.turn_factor)
        elif theta < 0:
                # we want to turn right
                transmitter.press("up",.51)
                transmitter.press("L",0)
                transmitter.press("R",.5 - theta * configurables.turn_factor)
        elif theta == 0:
                # we can go straight forward
                transmitter.press("up",1)
                transmitter.press("L",0)
                transmitter.press("R",0)
color() Color

The color in front of the sensor.

from sensors import ColorSensor
from controllables import TextScreen

color_sensor = ColorSensor(0)
screen = TextScreen(1)

while True:
    color = color_sensor.color()
    screen.text = color.to_hex()
    screen.color = color
name() str

Returns the user editable name of the controllable as found in the properties tab of the game.

The following example assumes that any controllable or sensor is assigned to port 0 and prints out its name.

from ports import PortReference

print(PortReference(0).name())
stream() Stream[Color]

Creates an stream of all the colors that the sensor has recorded.

If you want to catch a color that quickly passes in front of the color sensor. It’s essential to use the stream instead of the direct query so that the desired color sample is not missed.

The following example demonstrates how to see if a sufficiently close color is seen by the sensor.

from sensors import ColorSensor
from color import Color
from streams import Stream
from controllables import TextScreen
from time import time

stream : Stream[Color] = ColorSensor().stream()

desired_color = "#FEEFAB"

max_color_dist = .1

screen = TextScreen()

screen.text = ''
time_of_last_color_hit = time()

while True:
        for color_sample in stream:
                if color_sample.distance(Color.from_hex(desired_color)) < max_color_dist:
                        time_of_last_color_hit = time()
                        screen.text = 'Color Has Been Found!'
        if time() - time_of_last_color_hit > 1:
                screen.text = ''