VEX V5 PYTHON | 02.1 DRIVE BY DISTANCE
Guide objective
Use distance-based forward and reverse commands in autonomous, set movement speed and timeout, and compare commanded travel with measured results.
01 | FROM TIME TO DISTANCE
A timed command says “drive for half a second”. A distance command says “drive 300 millimetres”. The second expresses a physical target and uses the drivetrain’s configured geometry with encoder feedback to estimate how much motor rotation is needed.
It is still an estimate of ground travel. Wheel slip, incorrect geometry and mechanical differences can make measured movement differ from the target.
Complete the direction checks from Part 1 and use your measurements from 01.4 Drivetrain Geometry before testing distances.
02 | USE DRIVE_FOR WITH EXPLICIT UNITS
drivetrain.set_drive_velocity(20, PERCENT) drivetrain.drive_for(FORWARD, 300, MM) drivetrain.drive_for(REVERSE, 300, MM)
FORWARD or REVERSE selects direction. 300 is the distance magnitude. MM makes the unit explicit. Keep the distance positive so the direction is easy to read.
The second movement is relative to wherever the robot is when that command starts. It does not navigate to an absolute field coordinate.
Speed percentage is a command setting, not millimetres per second. Changing speed affects how quickly the robot attempts the distance, not the requested distance itself.
03 | DISTANCE COMMANDS NEED GEOMETRY
A MotorGroup identifies a side of the robot. A DriveTrain combines left and right sides with wheel travel, track width, wheelbase and external gearing.
drivetrain = DriveTrain(
left_drive, right_drive,
WHEEL_TRAVEL_MM, TRACK_WIDTH_MM, WHEEL_BASE_MM,
MM, EXTERNAL_GEAR_RATIO
)Wheel travel is circumference, not diameter. For a nominal 101.6 mm diameter wheel, circumference is approximately 319.19 mm. The complete example uses direct drive, so its external ratio is 1.
Do not use an internal cartridge ratio as the external gear ratio. For externally geared robots, confirm your settings using the geometry guide and installed VEXcode Help.
04 | WAITING AND ORDER OF ACTIONS
By default, drive_for blocks: the next line waits until the movement command ends. This makes a short sequence easy to read.
drivetrain.drive_for(FORWARD, 300, MM) wait(500, MSEC) drivetrain.drive_for(REVERSE, 300, MM)
The robot attempts the forward distance, pauses, then attempts the reverse distance. The pause starts after the forward command ends, not at the same time as it begins.
A non-blocking call with wait=False is useful later when coordinating other actions, but issuing another drive command immediately can replace the previous movement. Begin with the default waiting behaviour.
05 | TIMEOUT IS NOT SUCCESS
A timeout limits how long a movement may try to finish. If a robot is blocked or cannot reach its target, the program should not remain on the movement indefinitely.
drivetrain.set_timeout(3, SECONDS)
A command returning after a timeout is not proof that the target was reached. The example’s Routine ended message means only that the sequence reached its final line.
Choose a timeout that allows a normal movement at the selected speed while still bounding a failed attempt. A short timeout can stop a healthy movement early. Diagnose that before changing wheel geometry.
06 | COMPLETE FORWARD-AND-REVERSE STARTER
This extends the competition starter from 01.6 and retains left-stick forward/back and right-stick turning for driver control. Autonomous attempts 300 mm forward, pauses and attempts 300 mm reverse.
Keep generated imports and Brain setup above the code, with import math available. Place the example below # Begin project code, replacing previous user-code starters. Do not duplicate the manually declared motors or Controller in the Devices panel.
Ports, blue cartridges, reversal flags and dimensions are examples. Match them to your robot. For the first check, support the wheels securely; measure distance only in a clear floor area with suitable competition controls.
# =============================================================================
# TEAM [MY TEAM NAME / NUMBER]
# =============================================================================
# ROBOT CONFIGURATION
# - FOUR-motor drivetrain:
# Left = Ports 3 and 4
# Right = Ports 1 and 2
# - Example: blue cartridges, left normal, right reversed.
# VERIFY your actual ports, cartridges and direction settings.
# DRIVER CONTROLS
# - Left joystick vertical (axis3): forward/back
# - Right joystick horizontal (axis1): turn
# - This program MOVES in autonomous and driver-control modes.
# - Autonomous: forward, pause, reverse.
# - Example geometry assumes DIRECT drive (external ratio 1).
# - Add BELOW # Begin project code, outside generated configuration.
# - Do not also define these drive motors in the Devices panel.
# - Keep generated from vex import * and brain = Brain() above.
# =============================================================================
# FOUR-MOTOR DRIVETRAIN
# =============================================================================
left_motor_1 = Motor(Ports.PORT3, GearSetting.RATIO_6_1, False)
left_motor_2 = Motor(Ports.PORT4, GearSetting.RATIO_6_1, False)
right_motor_1 = Motor(Ports.PORT1, GearSetting.RATIO_6_1, True)
right_motor_2 = Motor(Ports.PORT2, GearSetting.RATIO_6_1, True)
left_drive = MotorGroup(left_motor_1, left_motor_2)
right_drive = MotorGroup(right_motor_1, right_motor_2)
# =============================================================================
# MEASURED GEOMETRY: EXAMPLES, REPLACE WITH YOUR MEASUREMENTS
# =============================================================================
WHEEL_DIAMETER_MM = 101.6
WHEEL_TRAVEL_MM = math.pi * WHEEL_DIAMETER_MM
TRACK_WIDTH_MM = 300
WHEEL_BASE_MM = 250
EXTERNAL_GEAR_RATIO = 1.0 # This example is direct drive only
drivetrain = DriveTrain(
left_drive, right_drive,
WHEEL_TRAVEL_MM, TRACK_WIDTH_MM, WHEEL_BASE_MM,
MM, EXTERNAL_GEAR_RATIO
)
# =============================================================================
# CONTROLLER, SETTINGS AND HELPERS
# =============================================================================
controller = Controller(PRIMARY) # Do not duplicate a generated Controller
DEADBAND = 5
DRIVE_LIMIT_PERCENT = 30 # Start low; increase only after testing
TURN_GAIN = 0.7
LOOP_DELAY_MS = 20
AUTON_SPEED_PERCENT = 20
TEST_DISTANCE_MM = 300
MOVE_TIMEOUT_SECONDS = 3
PAUSE_MS = 500
def apply_deadband(value):
return 0 if abs(value) <= DEADBAND else value
def drive_mix(forward, turn):
left = forward + turn
right = forward - turn
largest = max(100, abs(left), abs(right))
left = left * 100 / largest
right = right * 100 / largest
return (left * DRIVE_LIMIT_PERCENT / 100,
right * DRIVE_LIMIT_PERCENT / 100)
def set_side_output(side, output):
if abs(output) < 0.01:
side.stop(BRAKE)
elif output > 0:
side.spin(FORWARD, output, PERCENT)
else:
side.spin(REVERSE, -output, PERCENT)
def show_status(message):
brain.screen.clear_screen()
brain.screen.set_cursor(1, 1)
brain.screen.print(message)
def stop_drive():
left_drive.stop(BRAKE)
right_drive.stop(BRAKE)
def drive_distance(direction, distance_mm):
# Use a positive magnitude; the direction argument selects travel direction.
if distance_mm <= 0:
raise ValueError("Distance must be positive")
if not (competition.is_enabled() and competition.is_autonomous()):
stop_drive()
return
drivetrain.set_drive_velocity(AUTON_SPEED_PERCENT, PERCENT)
drivetrain.set_stopping(BRAKE)
drivetrain.set_timeout(MOVE_TIMEOUT_SECONDS, SECONDS)
drivetrain.drive_for(direction, distance_mm, MM) # Blocking by default
drivetrain.stop()
# Command ended; this does NOT prove the floor target was reached.
# =============================================================================
# PRE-AUTON: CALLED ONCE AT PROJECT STARTUP
# =============================================================================
def pre_autonomous():
stop_drive()
show_status("Setup ready")
# Later: initialise sensors and starting values here.
# Finish setup before the robot is enabled for a match.
# =============================================================================
# AUTONOMOUS: A FINITE ROUTINE
# =============================================================================
def autonomous():
show_status("Autonomous")
drive_distance(FORWARD, TEST_DISTANCE_MM)
if not (competition.is_enabled() and competition.is_autonomous()):
stop_drive()
return
wait(PAUSE_MS, MSEC)
drive_distance(REVERSE, TEST_DISTANCE_MM)
stop_drive()
show_status("Routine ended")
# =============================================================================
# DRIVER CONTROL: REPEATING UPDATES WHILE ENABLED
# =============================================================================
def driver_control():
show_status("Driver control")
while competition.is_enabled() and competition.is_driver_control():
forward = apply_deadband(controller.axis3.position())
turn = apply_deadband(controller.axis1.position()) * TURN_GAIN
left_output, right_output = drive_mix(forward, turn)
set_side_output(left_drive, left_output)
set_side_output(right_drive, right_output)
wait(LOOP_DELAY_MS, MSEC)
stop_drive()
# =============================================================================
# PROGRAM START: SETUP, THEN CALLBACK REGISTRATION
# =============================================================================
pre_autonomous()
competition = Competition(driver_control, autonomous)
# Keep the main task alive without running a driving loop here.
while True:
wait(100, MSEC)
The helper checks that autonomous is enabled before beginning a movement. Competition controls still govern enabled state during the command. Repeat disable tests after adding movement.
Both forward and reverse use the same helper and explicit units. The driver loop uses the same MotorGroups, but should act only in driver-control mode. Avoid other tasks sending drivetrain commands at the same time.
07 | CHECK THE MEASURED RESULT
Mark the position of a consistent point on the chassis. Measure that same point after the forward movement. For an out-and-back routine, also record its final displacement from the start.
| Trial | Commanded forward | Measured forward | Final displacement from start |
|---|---|---|---|
| 1 | 300 mm | Record result | Record result |
| 2 | 300 mm | Record result | Record result |
| 3 | 300 mm | Record result | Record result |
A robot that returns close to its starting point has not necessarily driven the correct distance. Forward and reverse errors can cancel. Measure the outward leg as well as the final position.
Compare repeatability separately from accuracy. Similar results show consistency; closeness to the target shows accuracy.
08 | DIAGNOSE BEFORE TUNING
- Consistently too far or too short: recheck circumference, units and external gearing.
- Stops early at a similar time: inspect the timeout and whether the movement can finish at that speed.
- Different results each run: investigate slip, loose wheels, load and surface variation.
- Curves while driving: check side directions, matching gearing, wheel drag and load distribution.
- Forward works but reverse does not: inspect mechanical interference, backlash and the direction of the command.
- Unexpected second action: confirm that the first command did not simply time out.
Change one variable at a time and retest. Keep measured dimensions separate from any later effective calibration values.
CHALLENGES | BUILD A MEASURABLE AUTONOMOUS ROUTINE
- Read the command: identify direction, magnitude, units, speed and timeout.
- Match the configuration: verify ports, groups and geometry against your robot.
- Short trial: test a forward movement with the reverse step temporarily removed, then measure its distance.
- Reverse trial: test the same distance in reverse from a marked start.
- Out and back: restore the short sequence and record both the outward distance and final displacement.
- Repeatability: run three trials using the same speed, load and floor surface.
- Compare speed: after the short test is reliable, change only speed and compare the measured results.
- Test disabling: use your competition controls to verify that movement stops when disabled.
Success evidence
A saved project and test log distinguishing commanded distance, measured distance and final position. You can explain that a timeout or a returned command does not prove target achievement.
OFFICIAL REFERENCE
VEX V5 Python: drive_for, speed, stopping and timeout
This is an independent learning resource; VEX and VEXcode are trademarks of their respective owners.