Skip to content

The acres_simulator Package#

acres_simulator is the Python interface of the run-time library acres_runtime. It has no numerical code. The compiled library makes the plans, the routes, the command chain and the physics steps.

Before you start

Install#

The package needs no other package for its version and identity. A fleet gives its arrays as numpy arrays.

PYTHON=$(command -v python) Runtime/build.sh                 # the library and the module _acres_runtime
pip install --no-build-isolation --no-deps -e Simulator     # the package, with no download

Without an install, set the path:

PYTHONPATH=Simulator:Learning:Core/Build ACRES_RUNTIME_BUILD=Runtime/Build python my_program.py

The package finds the module _acres_runtime in this order:

  1. On the Python path.
  2. In the folder of the variable ACRES_RUNTIME_BUILD.
  3. In Runtime/Build of the repository.

The variable ACRES_ROOT names the repository that has the world content and the configuration files. The default is the repository of the package.

Modules#

Module or Name Content
acres_simulator Core, Fleet, Observation, Driver, run, Skills, SkillResult, run_skills, identity, repository, sweep_materials
acres_simulator.plans Mission plans, routes, prepared paths, cost tables and the identity of the tree
acres_simulator.maps The maps of the simulator by name
acres_simulator.scenarios The other actors on the path of a mission: generator, run and contact class
acres_simulator.scan The scan filter, the crop mask and the shield, for tools
acres_simulator.vehicle The control step of one vehicle with inputs from outside (Vehicle)
acres_simulator.learned Learned skills that propose chunks through the checker
acres_simulator.training Many vehicles of one skill world as arrays (Training)
acres_simulator.evaluate, acres_simulator.plot The evaluation of a learned skill and its figures
acres_simulator.tables A command that drives the cost tables and writes them to the cache

A Fleet of Missions#

A fleet drives many missions on one batch of ACRES Core. A model reads the observation and proposes chunks. The library checks each chunk, drives the command chain and the physics, and gives the scores.

fleet.py
import acres_simulator as acres

world = acres.Core(num_envs=64, threads=8)   # ACRES Core in this process
fleet = acres.Fleet(world, grip="unknown")
fleet.load(missions=["single-F56"], condition="dry")

obs = fleet.observe()                    # arrays that view the memory of the library
chunks = fleet.default_chunks(n=16)      # the chunk of the default driver for each slot
verdicts = fleet.propose(chunks)         # the chunks of each vehicle, checked in parallel
command = fleet.step()                   # the best accepted chunk, or the default driver
scores = fleet.scores()

class MyDriver(acres.Driver):            # the hook for a model
    def propose(self, obs):
        return fleet.default_chunks(n=16)

acres.run(fleet, driver=MyDriver(), deadline_s=0.05)
fleet.close()
Name Function
acres.Core(num_envs, threads, root, config_dir, content_dir, scan_history) A world of ACRES Core for a fleet or a skill world. threads 0 uses one thread for each hardware thread.
acres.Fleet(world, grip, order, shield_scan) A fleet. grip is a level name of envelope_v1.json or its index. order is "longest" or "queue".
acres.Driver The hook: a class with propose(obs) that returns chunks or None.
acres.run(fleet, driver, deadline_s, max_steps) Observes, proposes, checks and steps until no mission runs. Returns the scores.
acres.identity() The versions of the package and the library, the ABI version, the simulation version, the build commit and the map hash.
acres.repository() The ACRES repository that the package uses.

One process has one fleet or one skill world at a time. Close a fleet with close(), or use a with block, before you make the next one.

Method of Fleet Function
load(missions, condition, kind, append, chain, jobs) Puts missions into the queue and starts them. A mission is a name such as "single-F56" or a prepared mission.
observe() Returns the Observation. Its arrays are views.
default_chunks(n, step_m, copies) A new array [slots, copies] with the chunk of the default driver for each slot.
propose(chunks, slots, deadline_s) Checks the chunks, one task for each slot. Returns the verdicts.
step() Makes one control step of each slot. Returns the command of each slot.
run(max_steps) Steps with the default driver until no mission runs.
scores(), timing() The score of each mission in queue order, and the counts and times of the work.
set_parameters(slot, overrides), set_steer_rate_scale(slot, scale), check_inputs(slot, chunk) Setters for a sensitivity study, and the checker inputs of a chunk.
slots, threads, running, missions, close() The size of the fleet, the missions that run, and the release of the fleet.

The argument kind selects the command chain of a mission:

  • "acceptance": the default driver, the launch hold, the shield and the gear logic, with the scan.
  • "single": the default driver and the gear logic.

The calls load, observe, default_chunks, propose, step and run release the Python GIL.

Warning

Do not set deadline_s in an evaluation. It is a wall-clock limit, thus a result then depends on the speed of the computer.

Observation#

Each array has one entry for each slot. The arrays are read-only views of the library memory. They get new values at the next call of observe or step.

Attribute Shape and Type Content
state [slots, 49] float64 The state rows of ACRES Core. obs.columns gives the index of each name (x, y, yaw, speed, ...).
scan [slots] records The newest planar scan: ranges [360], material [360], stamp_s.
history_scan, history_x, history_y, history_yaw [slots, K] The ring of the last K scans with the pose of each.
projection [slots] records s_m, cross_track_m, segment, leg, direction, half_left_m, half_right_m.
base [slots] records The command of the default driver: curvature_per_m, speed_mps, path_cap_mps.
limits [slots] records The limits of the ground below the vehicle: speed, deceleration, obstacle margin, lateral acceleration, overshoot.
active, phase, mission [slots] 1 when the slot has a mission. The phase: 0 idle, 1 goto, 2 scout, 3 return, 4 done, 5 failed. The queue index, or -1.
corridor(slot) dictionary The corridor of the active leg: rasters, line, frame and speed limits.

Caution

Copy a value of corridor(slot) that you keep. The library frees the corridor when the leg changes.

Chunks, Verdicts and Commands#

The records have the fields of the structures of Runtime/Include/acres_runtime/types.h.

Record Fields
Chunk (AcresRtChunk) n, dt_s, station0_m, step_m, offset_m [64], speed_mps [64], t0_s, deadline_s
Verdict (AcresRtVerdict) accept, reason, index, counterexample (x, y, s, value, limit, rule)
Command (AcresRtCommand) curvature, speed, ulc, gear, obstacle_m, proposed_speed, held_speed, violated, shift, intervened, hold_changed, source

A chunk gives a side offset from the mission path and a signed speed at n stations. The stations are step_m apart and start at station0_m.

  • A verdict reason is 0 for an accepted chunk and 1 to 16 for the first failed rule of the checker.
  • The reason 100 is a late answer. The reason 101 is "no checker": build with ACRES_RUNTIME_LEAN=generated to load the checker.
  • The command source is 1 for the default driver and 2 for a chunk.

Scores#

A score has these keys:

Keys Content
success, failure, truncated The result
time_s, fuel_j, ground_j, crop_m2, edge_m2, distance_m, steps, reverse_m, gear_changes The totals
min_obstacle_m, cmd_rms_change, max_cross_track_m, cross_track The smallest obstacle distance, the command changes and the cross-track error
coverage, scouted, interventions, interventions_per_1000, rules, phases, t_ref_s Field coverage, shield interventions, phases and the reference time

Skills of One Vehicle#

acres.Skills drives one vehicle of a world through skills: go to a field, scout it, return home, wait.

skills.py
import acres_simulator as acres

world = acres.Core(num_envs=1, threads=1)
skills = acres.Skills(world, agent=0)

result = skills.scout("F56")       # result.code, result.cause, result.counterexample
if result.code == "blocked":       # the shield held the vehicle for 10 s
    skills.wait(30.0)
    result = skills.resume()
result = skills.return_home()
skills.close()
Name Function
Skills(world, agent=0, planner=None, name="polaris", **options) The skills of one agent. The first agent of a Core makes the skill world. options has shield_scan ("config", "planar" or "sweep").
goto(place), scout(field), return_home(), wait(seconds), stop(), resume() Start a skill and step to its end. Each returns a SkillResult.
start(skill, args), step(steps), advance(s), charge(s), run(...) A request that does not block, and control steps.
events(since), observation(), clock(), truth(), route(), state(), active The interface documents and the truth of the simulator.
set_objects(rows), set_scenario(scenario), scenario(), reset(pose) The objects on the path and a new episode.
check(skill, args), refuse(skill, cause) The problem of a request, and a refusal with that sentence.
scan(), sweep(pattern, noise, seed, crops, motion, intensity), command() The scan of the shield, a LiDAR sweep of ACRES Core, and the last command of the chain.
start_log(path, metadata), stop_log(), flush_log() The episode log of the agent: an MCAP file that the game can replay.
SkillResult code, cause, counterexample, skill, skill_id, time_s.
acres.run_skills(agents, max_steps) Steps the world until a skill of an agent ends. The agents step in parallel.

The skills, the result codes and the objects on the path are in Fleet, Skills and Routes.

Plans and Routes#

The module acres_simulator.plans connects to the planner and the routes of the library.

from acres_simulator import plans

missions = plans.prepare(["single-F56", "single-RF004"], condition="dry", kind="acceptance", jobs=8)
plans.save("my-plans", missions)                    # one .npz file for each mission
missions = plans.load("my-plans", kind="acceptance")
route = plans.route("F53", pose=(x, y, yaw))        # the route of a skill from a pose
Function Content
prepare(missions, condition, kind, jobs, tables_dir) Plans each mission and prepares its path. Returns one dictionary for each mission with the path, the legs, the plan, the plan-check verdict and T_ref.
route(mission, pose, back_off_m, speed_cap_mps, reverse, back_track) The route of a skill. "home" gives a Return alone. A refused mission raises plans.RouteRefused.
order(fields, condition) The plan of the exact program for some fields, with no route.
check(visits, return_home, condition) The plan check of the visits in the order of the caller.
site(tables_dir), site_map() The planner of the process, and the map for a drawing: fields, loops, edges, scan frame and object kinds.
tables(condition), tables_file(condition, tables_dir) The cost tables of a condition set.
legs(mission), reasons() The legs of a prepared mission, and the reason names of the plan checker.
save(folder, missions), load(folder, kind, condition) Prepared missions as files.
identity(), map_hash(folder) The identity of the tree, and the map hash of a map folder.
heights(xy), task_fields(), scout_study(...), command_curvature(xy, speed_mps) Getters for tools: terrain heights, field names, a study of a Scout loop, and the curvature of the default driver.

Cost Tables#

prepare and route read the cost tables. The search order of the folder is:

  1. The argument tables_dir.
  2. The variable ACRES_COST_TABLES.
  3. Acres/Saved/Learning/costs of the repository.

The cache has the tables in <map hash>/v<simulation version>/<condition>.npz. The planner refuses tables of a different map.

When the cache has no tables for the tree, the package drives them in a separate process (python -m acres_simulator.tables). The three condition sets take about 2 minutes on 8 threads.

Variable Default Function
ACRES_COST_TABLES Acres/Saved/Learning/costs The cache of the cost tables
ACRES_DRIVE_TABLES 8, at most the hardware threads The threads of the table drive. 0 permits no drive: prepare and route then raise FileNotFoundError.

Maps#

The module acres_simulator.maps selects a map by its name. One process has one map.

Function Content
names() The default map and the variants in Acres/Content/SimulationMaps
use(name) Selects the map of this process before a world is made. It also sets ACRES_MAP for child processes.
current() The map of this process: that of use, else of ACRES_MAP, else default
folder(name), content_dir(name), maps_dir() The folders of a map
identity(name), tables_folder(name), drive_tables(name, threads, conditions) The identity and the cost tables of a map

Run python -m acres_simulator.maps --help for the command form. The page Map Data describes the map folders.

Scenarios of Other Actors#

The module acres_simulator.scenarios makes persons, trucks, tractors and cars on the path of a mission.

Function Content
generate(route, patterns, seed, mission, run, count, ...) The actors of one episode for a route
save(scenario, path) Writes a scenario file (acres-path-scenario-1)
config(override, path), config_path() The generator settings of path_objects_v1.json
Run Steps the scripts of a scenario outside a skill world
contact_class(vehicle, row, moving_mps) Who moved into whom: vehicle, actor, both or rest

Give a scenario to a skill world with Skills.set_scenario. Farm Traffic and Workers describes the behaviour of the actors.

Identity#

The identity of a simulated result has two values.

from acres_simulator import plans
tree = plans.identity()            # {"map_hash", "sim_version", "build_id", "commit"}
Value C Function Content
map_hash acres_runtime_map_hash 16 hexadecimal digits. It covers the scouting map and each map file that a drive reads.
sim_version acres_runtime_sim_version One whole number for the drives of the simulator and the command chain. It is the first line of Runtime/Reference/sim_version.txt.
build_id, commit acres_runtime_build_id, acres_runtime_commit Information only.

Only Runtime/Reference/refresh.sh changes the simulation version (Recorded Reference).

Warning

Run Runtime/Tests/baseline_regression.py before you commit a change of the library, ACRES Core, a configuration file or a map file. The regression test, not a hash, finds a change of a drive.

A cost table file and a dataset of simulated scans store map_hash and sim_version. The planner refuses a different map. A different simulation version gives a warning.

Commands#

Command Function
python -m acres_simulator.tables Drives the cost tables of the tree into the cache
python -m acres_simulator.maps Lists the maps, and runs a command for each map
python -m acres_simulator.baseline --fields F56,F04 --threads 4 --out <folder> Drives a set of single-field missions and writes results and reports
python -m acres_simulator.chunk_acceptance --out <folder> --threads 4 Counts the chunks of the default driver that the checker accepts
python -m acres_simulator.evaluate, python -m acres_simulator.plot Evaluates a learned skill and draws its figures
python Simulator/examples/noise_driver.py [<plans folder>] [<threads>] An example model: 64 vehicles with 16 chunks each

Add --help to a command for its options.