Reference for commands that manage Plan lifecycle, activation, and coordination.
Pro Tip
Plans can coordinate with each other using signals and groups. This lets you build complex behaviors from simple building blocks - for example, a "Patrol" plan that activates "ObstacleAvoid" when needed, then resumes when the coast is clear.
Start a Plan.
activate(plan_name)
activate(plan_name, options)
| Parameter | Type | Description |
|---|---|---|
| plan_name | string | Name of Plan to activate |
| options | object | Optional configuration |
Options:
| Option | Type | Default | Description |
|---|---|---|---|
| priority | number | 0 | Execution priority |
| exclusive | boolean | false | Stop conflicting Plans |
| params | object | {} | Parameters to pass |
// Simple activation
activate("PatrolPlan")
// With options
activate("EmergencyStop", {
priority: 100,
exclusive: true
})
// Pass parameters
activate("NavigateTo", {
params: {x: 100, y: 200}
})
Stop a Plan.
deactivate(plan_name)
deactivate() // Stop current Plan
// Stop specific Plan
deactivate("PatrolPlan")
// Stop self
deactivate()
Temporarily suspend a Plan.
pause(plan_name)
pause() // Pause current Plan
// Pause for emergency check
pause("PatrolPlan")
check_emergency()
resume("PatrolPlan")
Continue a paused Plan.
resume(plan_name)
resume("PatrolPlan")
Check if a Plan is running.
is_active(plan_name) -> boolean
if is_active("PatrolPlan") {
log("Patrol is running")
}
Check if a Plan is paused.
is_paused(plan_name) -> boolean
if is_paused("PatrolPlan") {
resume("PatrolPlan")
}
Get detailed Plan state.
get_state(plan_name) -> object
Returns:
{
name: "PatrolPlan",
state: "running", // "inactive", "running", "paused"
started_at: 1234567890,
run_time: 60000, // milliseconds
loop_count: 1200,
errors: 0
}
Get all available Plans.
list_plans() -> array
var plans = list_plans()
for plan in plans {
log(plan.name + ": " + plan.state)
}
Get currently running Plans.
list_active() -> array
var active = list_active()
log("Running: " + length(active) + " plans")
Higher priority Plans execute first in each cycle:
// Emergency Stop has highest priority
activate("EmergencyStop", {priority: 100})
// Normal operations
activate("PatrolPlan", {priority: 10})
// Background tasks
activate("DataLogger", {priority: 1})
Exclusive Plans stop conflicting Plans:
// Stop all motor-controlling Plans
activate("ManualControl", {
exclusive: true,
conflicts: ["PatrolPlan", "NavigateTo", "ObstacleAvoid"]
})
plan ResourceManager {
var motor_owner = null
function request_motors(plan_name) {
if motor_owner != null && motor_owner != plan_name {
return false // Motors busy
}
motor_owner = plan_name
return true
}
function release_motors(plan_name) {
if motor_owner == plan_name {
motor_owner = null
}
}
}
activate("NavigateTo", {
params: {
target_x: 100,
target_y: 200,
speed: 50
}
})
plan NavigateTo {
var target_x = params.target_x ?? 0
var target_y = params.target_y ?? 0
var speed = params.speed ?? 30
init {
log("Navigating to " + target_x + ", " + target_y)
}
loop {
move_toward(target_x, target_y, speed)
if at_position(target_x, target_y) {
deactivate()
}
delay(50)
}
}
plan Configurable {
// Use ?? operator for defaults
var threshold = params.threshold ?? 30
var speed = params.speed ?? 50
var enabled = params.enabled ?? true
}
// Send signal to another Plan
signal(plan_name, signal_name, data)
// Sender Plan
plan Scout {
loop {
if sensors.distance.front < 20 {
signal("Worker", "obstacle_found", {
x: position.x,
y: position.y
})
}
delay(100)
}
}
// Receiver Plan
plan Worker {
on_signal("obstacle_found") { data ->
log("Obstacle at: " + data.x + ", " + data.y)
avoid_location(data.x, data.y)
}
loop {
do_work()
delay(100)
}
}
// Block until signal received
wait_for_signal(signal_name)
wait_for_signal(signal_name, timeout_ms)
plan Synchronized {
init {
log("Waiting for start signal...")
wait_for_signal("start")
log("Starting!")
}
loop {
do_work()
delay(50)
}
}
create_group(group_name, plan_names)
create_group("patrol_team", ["Scout", "Worker1", "Worker2"])
activate_group(group_name)
// Start all patrol plans together
activate_group("patrol_team")
deactivate_group(group_name)
// Stop all patrol plans
deactivate_group("patrol_team")
// Signal all plans in group
signal_group("patrol_team", "return_home", {})
// Check if all plans in group are active
var all_active = group_all_active("patrol_team")
// Check if any plan in group is active
var any_active = group_any_active("patrol_team")
Activate Plan at specific time.
activate_at(plan_name, timestamp)
// Activate at specific time
var patrol_time = now() + 3600000 // 1 hour from now
activate_at("NightPatrol", patrol_time)
Activate Plan after delay.
activate_after(plan_name, delay_ms)
// Activate after 5 minutes
activate_after("DataUpload", 300000)
schedule(plan_name, interval_ms)
schedule(plan_name, cron_expression)
// Run every hour
schedule("StatusReport", 3600000)
// Run at specific times (cron-like)
schedule("NightPatrol", "0 22 * * *") // 10 PM daily
plan EventDemo {
on_plan_event("activated") { plan_name ->
log("Plan activated: " + plan_name)
}
on_plan_event("deactivated") { plan_name ->
log("Plan deactivated: " + plan_name)
}
on_plan_event("error") { error ->
log_error("Plan error: " + error.plan + " - " + error.message)
}
}
// Watch specific Plan
on_plan_state_change("PatrolPlan") { old_state, new_state ->
log("Patrol: " + old_state + " -> " + new_state)
}
plan RobustPlan {
on_error { error ->
log_error("Plan error: " + error.message)
stop() // Safe state
// Optionally restart
delay(1000)
activate("RobustPlan")
}
loop {
risky_operation()
delay(50)
}
}
plan AutoRestart {
const MAX_RESTARTS = 3
var restart_count = params.restart_count ?? 0
on_error { error ->
if restart_count < MAX_RESTARTS {
log_warn("Restarting after error: " + error.message)
activate("AutoRestart", {
params: {restart_count: restart_count + 1}
})
} else {
log_error("Max restarts reached, stopping")
}
}
init {
if restart_count > 0 {
log("Restart #" + restart_count)
}
}
loop {
do_work()
delay(50)
}
}
var info = plan_info("PatrolPlan")
// Returns:
// {
// name: "PatrolPlan",
// version: "1.0.0",
// author: "RobotBuilder",
// permissions: ["sensors.read", "actuators.motors"],
// description: "Autonomous patrol behavior"
// }
var has_motors = plan_has_permission("PatrolPlan", "actuators.motors")
if !has_motors {
log_warn("PatrolPlan cannot control motors")
}
var perms = plan_permissions("PatrolPlan")
for perm in perms {
log("Requires: " + perm)
}
function safe_activate(plan_name) {
// Check if already active
if is_active(plan_name) {
log("Plan already active: " + plan_name)
return false
}
// Activate
activate(plan_name)
// Verify
if !is_active(plan_name) {
log_error("Failed to activate: " + plan_name)
return false
}
return true
}
function safe_deactivate(plan_name) {
if is_active(plan_name) {
deactivate(plan_name)
// Wait for cleanup
var timeout = 5000
var start = now()
while is_active(plan_name) && now() - start < timeout {
delay(100)
}
if is_active(plan_name) {
log_error("Plan did not stop: " + plan_name)
return false
}
}
return true
}
function handoff(from_plan, to_plan, state_data) {
// Save state
global.handoff_state = state_data
// Deactivate old plan
deactivate(from_plan)
// Activate new plan with state
activate(to_plan, {
params: {handoff_state: state_data}
})
}
// Usage
handoff("SearchMode", "TrackMode", {
target_x: 100,
target_y: 200
})