Rac3 Truck

Python code and building instructions for the LEGO MINDSTORMS EV3 Official Fan Creations (31313).

Rac3 Truck
Image credit: LEGO

Want a remote controlled truck? Got it! This is one fun cool ride. You can modify the truck to make it go faster by adding gears, and you can add a custom-built trailer so the truck can be used as a transport vehicle.


This program requires LEGO® MINDSTORMS® EV3 MicroPython v2.0 downloadable at https://education.lego.com/en-us/support/mindstorms-ev3/python-for-ev3.

Drive Rac3 Truck around according to instructions from Channel 1 of the IR Remote Control: - 2 Top/Up Buttons together: drive forward - 2 Bottom/Down Buttons together: drive backward - Top-Left/Red-Up: turn left forward - Top-Right/Blue-Up: turn right forward - Bottom-Left/Red-Down: turn left backward - Bottom-Right/Blue-Down: turn right backward

The code for the Rac3Truck class is in rac3_truck.py as follows:

from pybricks.ev3devices import Motor, InfraredSensor
from pybricks.parameters import Button, Direction, Port, Stop
from pybricks.robotics import DriveBase
from pybricks.tools import wait


class Rac3Truck:
    WHEEL_DIAMETER = 30   # milimeters
    AXLE_TRACK = 120      # milimeters

    def __init__(
            self,
            left_motor_port: str = Port.B, right_motor_port: str = Port.C,
            polarity: str = 'inversed',
            steer_motor_port: str = Port.A,
            ir_sensor_port: str = Port.S4, ir_beacon_channel: int = 1):
        if polarity == 'normal':
            self.left_motor = Motor(port=left_motor_port,
                                    positive_direction=Direction.CLOCKWISE)
            self.right_motor = Motor(port=right_motor_port,
                                     positive_direction=Direction.CLOCKWISE)
        else:
            self.left_motor = \
                Motor(port=left_motor_port,
                      positive_direction=Direction.COUNTERCLOCKWISE)
            self.right_motor = \
                Motor(port=right_motor_port,
                      positive_direction=Direction.COUNTERCLOCKWISE)
        self.driver = DriveBase(left_motor=self.left_motor,
                                right_motor=self.right_motor,
                                wheel_diameter=self.WHEEL_DIAMETER,
                                axle_track=self.AXLE_TRACK)

        self.steer_motor = Motor(port=steer_motor_port,
                                 positive_direction=Direction.CLOCKWISE)

        self.ir_sensor = InfraredSensor(port=ir_sensor_port)
        self.ir_beacon_channel = ir_beacon_channel

    def reset(self):
        self.steer_motor.run_time(
            speed=300,
            time=1500,
            then=Stop.COAST,
            wait=True)

        self.steer_motor.run_angle(
            speed=-500,
            rotation_angle=120,
            then=Stop.HOLD,
            wait=True)

        self.steer_motor.reset_angle(angle=0)

    def steer_left(self):
        if self.steer_motor.angle() > -65:
            self.steer_motor.run_target(
                speed=-200,
                target_angle=-65,
                then=Stop.HOLD,
                wait=True)

        else:
            self.steer_motor.hold()

    def steer_right(self):
        if self.steer_motor.angle() < 65:
            self.steer_motor.run_target(
                speed=200,
                target_angle=65,
                then=Stop.HOLD,
                wait=True)

        else:
            self.steer_motor.hold()

    def steer_center(self):
        if self.steer_motor.angle() < -7:
            self.steer_motor.run_target(
                speed=200,
                target_angle=4,
                then=Stop.HOLD,
                wait=True)

        elif self.steer_motor.angle() > 7:
            self.steer_motor.run_target(
                speed=-200,
                target_angle=-4,
                then=Stop.HOLD,
                wait=True)

        self.steer_motor.hold()

        wait(100)

    def drive_by_ir_beacon(self):
        ir_beacon_button_pressed = \
            set(self.ir_sensor.buttons(channel=self.ir_beacon_channel))

        # forward
        if ir_beacon_button_pressed == {Button.LEFT_UP, Button.RIGHT_UP}:
            self.driver.drive(
                speed=800,
                turn_rate=0)

            self.steer_center()

        # backward
        elif ir_beacon_button_pressed == {Button.LEFT_DOWN, Button.RIGHT_DOWN}:
            self.driver.drive(
                speed=-800,
                turn_rate=0)

            self.steer_center()

        # turn left forward
        elif ir_beacon_button_pressed == {Button.LEFT_UP}:
            self.left_motor.run(speed=600)
            self.right_motor.run(speed=1000)

            self.steer_left()

        # turn right forward
        elif ir_beacon_button_pressed == {Button.RIGHT_UP}:
            self.left_motor.run(speed=1000)
            self.right_motor.run(speed=600)

            self.steer_right()

        # turn left backward
        elif ir_beacon_button_pressed == {Button.LEFT_DOWN}:
            self.left_motor.run(speed=-600)
            self.right_motor.run(speed=-1000)

            self.steer_left()

        # turn right backward
        elif ir_beacon_button_pressed == {Button.RIGHT_DOWN}:
            self.left_motor.run(speed=-1000)
            self.right_motor.run(speed=-600)

            self.steer_right()

        # otherwise stop
        else:
            self.driver.stop()

            self.steer_center()

The code for the main program is in main.py as follows:

#!/usr/bin/env pybricks-micropython


from pybricks.tools import wait

from rac3_truck import Rac3Truck


rac3_truck = Rac3Truck()

rac3_truck.reset()

wait(1000)

while True:
    rac3_truck.drive_by_ir_beacon()


This project was submitted by The Lương-Phạm Family.