Plan Commands
Managing and controlling Plans
Plan Commands
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.
Plan lifecycle
Activation commands
activate
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}
})
deactivate
Stop a Plan.
deactivate(plan_name)
deactivate() // Stop current Plan
// Stop specific Plan
deactivate("PatrolPlan")
// Stop self
deactivate()
pause
Temporarily suspend a Plan.
pause(plan_name)
pause() // Pause current Plan
// Pause for emergency check
pause("PatrolPlan")
check_emergency()
resume("PatrolPlan")
resume
Continue a paused Plan.
resume(plan_name)
resume("PatrolPlan")
Plan state commands
is_active
Check if a Plan is running.
is_active(plan_name) -> boolean
if is_active("PatrolPlan") {
log("Patrol is running")
}
is_paused
Check if a Plan is paused.
is_paused(plan_name) -> boolean
if is_paused("PatrolPlan") {
resume("PatrolPlan")
}
get_state
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
}
list_plans
Get all available Plans.
list_plans() -> array
var plans = list_plans()
for plan in plans {
log(plan.name + ": " + plan.state)
}
list_active
Get currently running Plans.
list_active() -> array
var active = list_active()
log("Running: " + length(active) + " plans")
Priority and conflicts
Plan priority
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 mode
Exclusive Plans stop conflicting Plans:
// Stop all motor-controlling Plans
activate("ManualControl", {
exclusive: true,
conflicts: ["PatrolPlan", "NavigateTo", "ObstacleAvoid"]
})
Conflict resolution
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
}
}
}
Parameter passing
Pass parameters on activation
activate("NavigateTo", {
params: {
target_x: 100,
target_y: 200,
speed: 50
}
})
Receive parameters
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)
}
}
Default parameter values
plan Configurable {
// Use ?? operator for defaults
var threshold = params.threshold ?? 30
var speed = params.speed ?? 50
var enabled = params.enabled ?? true
}
Plan communication
Signals between plans
// 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)
}
}
Wait for signal
// 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)
}
}
Plan groups
Create plan group
create_group(group_name, plan_names)
create_group("patrol_team", ["Scout", "Worker1", "Worker2"])
Activate group
activate_group(group_name)
// Start all patrol plans together
activate_group("patrol_team")
Deactivate group
deactivate_group(group_name)
// Stop all patrol plans
deactivate_group("patrol_team")
Group operations
// 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")
Scheduled activation
activate_at
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_after
Activate Plan after delay.
activate_after(plan_name, delay_ms)
// Activate after 5 minutes
activate_after("DataUpload", 300000)
Schedule recurring
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 events
Lifecycle events
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)
}
}
Subscribe to plan changes
// Watch specific Plan
on_plan_state_change("PatrolPlan") { old_state, new_state ->
log("Patrol: " + old_state + " -> " + new_state)
}
Error handling in plans
Plan-level error handler
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)
}
}
Restart on failure
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)
}
}
Plan metadata access
Get plan info
var info = plan_info("PatrolPlan")
// Returns:
// {
// name: "PatrolPlan",
// version: "1.0.0",
// author: "RobotBuilder",
// permissions: ["sensors.read", "actuators.motors"],
// description: "Autonomous patrol behavior"
// }
Check permissions
var has_motors = plan_has_permission("PatrolPlan", "actuators.motors")
if !has_motors {
log_warn("PatrolPlan cannot control motors")
}
List required permissions
var perms = plan_permissions("PatrolPlan")
for perm in perms {
log("Requires: " + perm)
}
Best practices
Clean activation
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
}
Clean deactivation
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
}
Plan handoff
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
})