Skip to content

State and sensor data

Every decision your program makes comes from a value it read: a stick position, a gyro rate, a battery voltage. This page is about where those values come from, how old they might be, and how to tell when one should not be trusted.

Reading a value from MARLIN never makes your program wait. In the background, MARLIN keeps a copy of the most recent data it received from the robot and the controller. When you read a property or call read(), you get that stored copy straight away.

This means a read always succeeds, but the value can be old. The ok field below is how you tell the difference.

Sensor readings

Every sensor reading includes:

Field Meaning
timestamp Robot-brain time in milliseconds when the sample was taken
age Approximate milliseconds since the sample was taken
ok True when the reading is usable: the data arrived intact and is no more than 250 ms old

Check ok before you use a reading to decide how the robot moves. If it is False, the number is missing or too old to trust, so stop instead of steering on a stale value:

reading = robot.imu("S1").read()
if reading.ok:
    gyro_z = reading.gyro_z
else:
    robot.thruster("M1").set_duty(0)

Before a sensor has sent anything, read() still works, but it returns an empty reading: timestamp == 0, age == math.inf (infinity), and ok == False. This is normal for the first moments after your program starts.

The extension and robot synchronise time when possible. During local or simulated operation without a synchronised offset, age falls back to time since the sample was received.

Units

Value Unit or range
IMU acceleration (accel_x, accel_y, accel_z) g
IMU gyro (gyro_x, gyro_y, gyro_z) degrees per second
IMU magnetometer (mag_x, mag_y, mag_z) raw integers
Radio beacon signal (rssi) dBm
Radio beacon signal-to-noise (snr) dB
Controller scaled axes -100 to 100
Controller raw axes the unprocessed stick number, 0 to 4095
Battery voltage volts

rssi and snr describe signal quality, not distance. The library has no distance measurement. A stronger (less negative) rssi usually means the beacon is nearer, but RSSI is not a distance reading.

Controller state

Controller input is available through robot.controller. Sticks and buttons are both looked up by name:

left = robot.controller.joystick("ONE").value      # -100 to 100
right = robot.controller.joystick("THREE").value        # -100 to 100
a_is_down = robot.controller.button("A").is_down    # True or False

The controller has two physical sticks, and MARLIN treats each stick's two directions as a separate, single-axis joystick:

Name Physical axis
"ONE" Left stick, up and down
"TWO" Left stick, left and right
"THREE" Right stick, up and down
"FOUR" Right stick, left and right

An unknown joystick name raises ValueError, so a typo stops your program instead of reading zero forever. Button names are checked the same way. See below.

Controller state comes from the Controller's own input packets. It can remain available even when robot.link_ok is false, as long as the extension and Controller connection are still operating.

Buttons expose only is_down. To detect a new press, keep the last value in a variable and compare consecutive loop iterations:

previous = False

while robot.running:
    current = robot.controller.button("A").is_down
    if current and not previous:
        print("A was just pressed")
    previous = current

The button names are A, B, X, Y, UP, DOWN, LEFT, RIGHT, LEFT_TRIGGER, and RIGHT_TRIGGER. Case does not matter. See Controller input for the diagram they come from.

Any other name raises ValueError, so a misspelled button stops your program instead of reporting False forever. If a button never seems to respond, check its spelling against that list first.

Robot status

The robot exposes cached status through read-only properties:

robot.link_ok
robot.estopped
robot.overtemp
robot.battery_voltage

robot.overtemp is true while the robot brain has shut itself down to avoid overheating. It trips at 50 °C and clears once the board cools to 45 °C. Like estopped, your program can read it but cannot change it. See Safety ownership.

Watch out at startup: a value of False or 0.0 can mean "the robot has not reported yet" rather than "the robot reported a real zero". A battery_voltage of 0.0 in the first moments does not mean the battery is flat.

So do not make a decision from a status value the instant your program starts. Wait for the link first:

def driver(robot):
    while robot.running:
        if not robot.link_ok:
            robot.thruster("M1").set_duty(0)
            continue

        robot.thruster("M1").set_duty(robot.controller.joystick("ONE").value)