OPAL Commands
Built-in commands and functions reference
OPAL Commands
Complete reference for all built-in commands and functions available in OPAL (OctoMY™ Programming and Automation Language).
Pro Tip
Always include a
delay()in yourloopblocks - even justdelay(50)for 20Hz updates. Without a delay, your plan will consume 100% CPU and may trigger the E207 timeout error. The delay also gives other plans and system tasks a chance to run.
Control flow
delay
Pause execution for a specified time.
delay(milliseconds)
| Parameter | Type | Description |
|---|---|---|
| milliseconds | number | Time to pause in ms |
delay(100) // 100ms pause
delay(1000) // 1 second pause
wait_for
Wait for a condition to become true.
wait_for(condition)
wait_for(condition, timeout_ms)
| Parameter | Type | Description |
|---|---|---|
| condition | expression | Condition to wait for |
| timeout_ms | number | Maximum wait time (optional) |
wait_for(sensors.distance.front < 30)
wait_for(battery.level > 20, 5000) // 5s timeout
if / else
Conditional execution.
if condition {
// code
} else if other_condition {
// code
} else {
// code
}
if distance < 30 {
stop()
} else if distance < 60 {
slow_down()
} else {
full_speed()
}
loop
Continuous execution loop.
loop {
// code runs forever
}
loop {
check_sensors()
update_motors()
delay(50)
}
for
Iterate over a range or collection.
for i in start..end {
// code
}
for item in collection {
// code
}
// Count 0 to 9
for i in 0..10 {
log("Count: " + i)
}
// Iterate array
var readings = [10, 20, 30]
for r in readings {
log("Reading: " + r)
}
while
Loop while condition is true.
while condition {
// code
}
var count = 0
while count < 10 {
log("Count: " + count)
count = count + 1
}
break
Exit the current loop.
loop {
if should_stop {
break
}
}
continue
Skip to next loop iteration.
for i in 0..10 {
if i == 5 {
continue // Skip 5
}
log(i)
}
Motor control
drive
Set both motor speeds for differential drive.
drive(left_speed, right_speed)
| Parameter | Type | Range | Description |
|---|---|---|---|
| left_speed | number | -100 to 100 | Left motor speed |
| right_speed | number | -100 to 100 | Right motor speed |
drive(60, 60) // Forward
drive(-60, -60) // Reverse
drive(50, -50) // Spin right
drive(-50, 50) // Spin left
drive(60, 30) // Curve right
stop
Stop all motors immediately.
stop()
set_motor
Set individual motor speed.
set_motor(name, speed)
| Parameter | Type | Description |
|---|---|---|
| name | string | Motor identifier |
| speed | number | Speed -100 to 100 |
set_motor("motors.left", 50)
set_motor("motors.right", 50)
set_servo
Set servo position.
set_servo(name, angle)
set_servo(name, angle, speed)
| Parameter | Type | Description |
|---|---|---|
| name | string | Servo identifier |
| angle | number | Target angle in degrees |
| speed | number | Movement speed (optional) |
set_servo("head.pan", 90) // Center
set_servo("head.tilt", 45) // Look up
set_servo("arm.shoulder", 120, 50) // Move slowly
Sensor access
sensors
Access sensor readings.
sensors.<category>.<name>
| Path | Type | Description |
|---|---|---|
sensors.distance.front |
number | Front distance (cm) |
sensors.distance.left |
number | Left distance (cm) |
sensors.distance.right |
number | Right distance (cm) |
sensors.imu.heading |
number | Compass heading (degrees) |
sensors.imu.pitch |
number | Pitch angle (degrees) |
sensors.imu.roll |
number | Roll angle (degrees) |
sensors.imu.accel.x |
number | X acceleration (g) |
sensors.imu.accel.y |
number | Y acceleration (g) |
sensors.imu.accel.z |
number | Z acceleration (g) |
sensors.line.left |
boolean | Left line detected |
sensors.line.center |
boolean | Center line detected |
sensors.line.right |
boolean | Right line detected |
sensors.bump.front |
boolean | Front bumper triggered |
sensors.light |
number | Ambient light (0-100) |
sensors.temperature |
number | Temperature (Celsius) |
var dist = sensors.distance.front
var heading = sensors.imu.heading
var on_line = sensors.line.center
battery
Access battery status.
battery.level // Percentage 0-100
battery.voltage // Voltage in V
battery.charging // Boolean
battery.low // Boolean (< 20%)
if battery.level < 20 {
return_to_base()
}
Logging
log
Output a message to the log.
log(message)
log("Starting patrol")
log("Distance: " + sensors.distance.front + " cm")
log_debug
Debug-level logging (verbose).
log_debug(message)
log_warn
Warning-level logging.
log_warn(message)
log_error
Error-level logging.
log_error(message)
log_debug("Checking sensor...")
log("Sensor value: " + value)
log_warn("Battery low!")
log_error("Sensor not responding!")
Math functions
abs
Absolute value.
abs(-5) // Returns 5
min / max
Minimum and maximum.
min(a, b) // Smaller value
max(a, b) // Larger value
min(5, 10) // 5
max(5, 10) // 10
clamp
Constrain value to range.
clamp(value, min, max)
clamp(150, 0, 100) // Returns 100
clamp(-20, 0, 100) // Returns 0
clamp(50, 0, 100) // Returns 50
round / floor / ceil
Rounding functions.
round(3.7) // 4
floor(3.7) // 3
ceil(3.2) // 4
sqrt / pow
Square root and power.
sqrt(16) // 4
pow(2, 3) // 8
pow(10, 2) // 100
sin / cos / tan
Trigonometric functions (radians).
sin(0) // 0
cos(0) // 1
sin(3.14159/2) // ~1
atan2
Two-argument arctangent.
atan2(y, x) // Angle in radians
degrees / radians
Angle conversion.
degrees(3.14159) // ~180
radians(180) // ~3.14159
random
Generate random number.
random() // 0.0 to 1.0
random(max) // 0 to max
random(min, max) // min to max
var r = random(100) // 0-100
var angle = random(-45, 45) // -45 to 45
String functions
length
String length.
length("hello") // 5
substring
Extract substring.
substring(str, start)
substring(str, start, length)
substring("hello", 1) // "ello"
substring("hello", 1, 3) // "ell"
contains
Check if string contains substring.
contains("hello world", "world") // true
starts_with / ends_with
Check string prefix/suffix.
starts_with("hello", "he") // true
ends_with("hello", "lo") // true
split
Split string into array.
split("a,b,c", ",") // ["a", "b", "c"]
join
Join array into string.
join(["a", "b", "c"], "-") // "a-b-c"
to_string
Convert value to string.
to_string(42) // "42"
to_string(3.14) // "3.14"
to_string(true) // "true"
to_number
Parse string to number.
to_number("42") // 42
to_number("3.14") // 3.14
Array functions
length
Array length.
var arr = [1, 2, 3]
length(arr) // 3
push
Add element to end.
var arr = [1, 2]
push(arr, 3) // arr is now [1, 2, 3]
pop
Remove and return last element.
var arr = [1, 2, 3]
var last = pop(arr) // last is 3, arr is [1, 2]
shift / unshift
Add/remove from beginning.
var arr = [2, 3]
unshift(arr, 1) // arr is [1, 2, 3]
var first = shift(arr) // first is 1, arr is [2, 3]
slice
Extract portion of array.
var arr = [1, 2, 3, 4, 5]
slice(arr, 1, 3) // [2, 3]
find
Find first matching element.
var arr = [1, 2, 3, 4, 5]
find(arr, x -> x > 3) // 4
filter
Filter elements by condition.
var arr = [1, 2, 3, 4, 5]
filter(arr, x -> x > 2) // [3, 4, 5]
map
Transform elements.
var arr = [1, 2, 3]
map(arr, x -> x * 2) // [2, 4, 6]
reduce
Reduce array to single value.
var arr = [1, 2, 3, 4]
reduce(arr, (acc, x) -> acc + x, 0) // 10
Communication
broadcast
Send message to all peers.
broadcast(event_name, data)
broadcast("status_update", {state: "moving"})
broadcast("obstacle_detected", {x: 10, y: 20})
send_to
Send message to specific peer.
send_to(peer_name, event_name, data)
send_to("Worker Beta", "task", {id: 123})
on_message
Handle incoming messages.
on_message(event_name) { data ->
// handle data
}
on_message("task") { task ->
log("Received task: " + task.id)
execute_task(task)
}
Time
now
Current timestamp in milliseconds.
var timestamp = now()
time
Current time components.
time.hour // 0-23
time.minute // 0-59
time.second // 0-59
time.day // 1-31
time.month // 1-12
time.year // e.g., 2024
time.weekday // 0-6 (Sunday=0)
if time.hour >= 22 || time.hour < 6 {
log("Night mode")
}
elapsed
Time since a reference point.
var start = now()
do_something()
var duration = now() - start
log("Took " + duration + "ms")
State management
var
Declare a variable.
var name = value
var speed = 60
var state = "idle"
var readings = []
var config = {threshold: 30, speed: 50}
const
Declare a constant.
const MAX_SPEED = 100
const PI = 3.14159
global
Access global state.
global.key = value
var x = global.key
global.patrol_count = 0
plan Patrol {
loop {
patrol_area()
global.patrol_count = global.patrol_count + 1
}
}
Functions
function
Define a function.
function name(params) {
// code
return value
}
function calculate_distance(x1, y1, x2, y2) {
var dx = x2 - x1
var dy = y2 - y1
return sqrt(dx*dx + dy*dy)
}
var dist = calculate_distance(0, 0, 3, 4) // 5
return
Return value from function.
function is_close(distance) {
return distance < 30
}
Error handling
try / catch
Handle errors gracefully.
try {
risky_operation()
} catch error {
log_error("Failed: " + error.message)
}
throw
Raise an error.
if battery.level < 5 {
throw "Battery critically low"
}
Navigation
navigate_to
Move to a position.
navigate_to(x, y)
navigate_to(x, y, heading)
navigate_to(100, 200)
navigate_to(0, 0, 0) // Return to origin facing north
turn_to
Turn to face a heading.
turn_to(heading)
turn_to(90) // Face east
turn_to(180) // Face south
position
Current position.
position.x
position.y
position.heading
log("At: " + position.x + ", " + position.y)
Plan control
activate
Activate another plan.
activate(plan_name)
if emergency {
activate("EmergencyStop")
}
deactivate
Stop a running plan.
deactivate(plan_name)
deactivate() // Stop current plan
pause / resume
Pause and resume plans.
pause("PatrolPlan")
// ... do something ...
resume("PatrolPlan")