Skip to content

Tools and Scripts#

This page lists each tool and script of the repository outside the learning stack, with its usage, its inputs, its outputs and its environment. Run each command from the repository root.

Group Folder and Content
Terramechanics Tools Tools/Terramechanics. The tests and the test stand of the tyre and soil model.
Implement Model Tools Tools/ImplementModel. The tests and the data files of the implement model.
Polaris Model Tools Tools/PolarisModel. The tests, the fit and the replay library of the Polaris model.
LiDAR Model Tools Tools/LidarModel. The tests of the LiDAR radiometry.
Episode Log Tools Tools/EpisodeLog. The tests and the schema generator of the episode log.
Simulator Control Tools Tools/SimControl. A Python client and four checks that use the simulator control channel.
Performance Tools Tools/Performance. The benchmarks of the packaged game.
UI Text Check Tools/ui_text_check.py. The style check of the text in the game UI.
Map and Asset Pipelines Tools/ACRE. The scripts that make the map layers, the meshes and the materials of the tile.
ACRES Core Tools Core. The build, the benchmark and the comparisons of ACRES Core.
ROS 2 Tools ROS/Env, ROS/Tools. The environment scripts and the checks of the ROS 2 workspace.
Calibration Tools Calibration. The scripts that compare the simulator with recorded data of the farm and the Polaris.
Demonstration Scripts Demo. Scripted sessions of the packaged game.
Documentation Tools Documentation/Tools. The generator and the checks of this site.

Environments#

Each row of this page names the environment that the tool needs. See also Install.

Environment Names#

Environment Description
torchenv The conda environment for the Python scripts. It has NumPy, SciPy, OpenCV and pandas.
ros2 The RoboStack ROS 2 Humble conda environment. The command source ROS/Env/setup_env.sh activates it and applies the DDS loopback fence.
C++ compiler g++ with C++20, or the compiler in the variable CXX.
Blender Blender in background mode: blender -b --python <script>. The authors used Blender 5.2.2.
Editor Python The Python interpreter of the editor, started as a commandlet. Close the editor before you start the commandlet.
Packaged game Packaged/Linux/Acres.sh. The tools start the game themselves. Only one game can run at a time.
Core build The folder Core/Build that Core/build.sh makes. The Python scripts need PYTHONPATH=Core/Build.

The examples show one command for each environment, in the sequence of the table. An editor script needs the variable UE, the Unreal Engine folder.

conda activate torchenv
python Tools/ACRE/Map/test_map.py
source ROS/Env/setup_env.sh
python Tools/EpisodeLog/check_ros.py episode_test.mcap
CXX=clang++ Tools/LidarModel/build.sh
blender -b --python Tools/ACRE/Props/acre_sign.py
"$UE/Engine/Binaries/Linux/UnrealEditor-Cmd" \
    Acres/Acres.uproject -run=pythonscript \
    -script=Tools/ACRE/Tools/dump_trees.py
Packaged/Linux/Acres.sh -VehicleDemo
PYTHONPATH=Core/Build python Core/Scripts/bench.py

Data Locations#

Some tools read data that is not in the repository. These environment variables give the locations. The table also shows the common variables of the build scripts.

Name Type Unit Default Description
UE path ~/Downloads/UnrealEngine5.8.2 The Unreal Engine folder. package.sh has no default value.
CXX text g++ The C++ compiler of the build scripts.
BUILD_DIR path one folder for each tool The output folder of a build script.
POLARIS_EXTRACT path ~/Codes/polaris/extract The local copy of the logs of the real Polaris.
POLARIS_EPISODES path ~/Codes/polaris/episodes The folder of the episodes that episodes.py makes from the logs.
POLARIS_FOLLOWER path $POLARIS_EPISODES/follower The folder of the closed-loop runs.
POLARIS_LIDAR_WORK path $POLARIS_EPISODES/lidar_sim The work folder of the LiDAR calibration.
ACRE_WEATHER path ~/Codes/polaris/weather The folder of the weather record of the ACRE station.
export UE=~/UnrealEngine
export POLARIS_EXTRACT=/data/polaris/extract
export POLARIS_EPISODES=/data/polaris/episodes
export ACRE_WEATHER=/data/polaris/weather

Terramechanics Tools#

These programs run the tyre and soil model of the game without Unreal Engine. The header VehicleBench.h is the test stand: a planar chassis that runs the vehicle model at 120 Hz. The page Tyre and Soil gives the model.

Tools/Terramechanics/build.sh#

Builds the three programs of this folder from the model sources of the game. The compiler flags make each warning an error.

  • Environment: a C++ compiler.
  • Input: physics_tests.cpp, demo_data.cpp, bench_pull.cpp, VehicleBench.h and the model sources in Acres/Source/Acres.
  • Output: the programs physics_tests, demo_data and bench_pull in Tools/Terramechanics.
Name Type Unit Default Description
CXX text g++ Environment variable. The C++ compiler.
Tools/Terramechanics/build.sh

physics_tests#

Tests the soil library, the tyre and soil model, the fuel map, the energy ledger and the rain total of a storm. The exit code is 0 when each check passes.

  • Environment: none. Start the program from the repository root.
  • Input: Acres/Content/Simulation/soil_library.json.
  • Output: the result of each check on the terminal.
Name Type Unit Default Description
--csv path Writes the Brixius comparison and the convergence traces as CSV files into this folder.
--export-soils path Writes the soil library of the code as JSON into this file. The program then stops.
--library path the shipped file The soil library file that the last check compares with the code.

See also Tests and Regression Checklist.

Tools/Terramechanics/physics_tests
Tools/Terramechanics/physics_tests --csv /tmp/terramechanics
49 passed, 0 failed

demo_data#

Writes drawbar pull data and rain data of the vehicle model on the test stand.

  • Environment: none.
  • Input: one optional argument, the output folder. The default is the current folder. The folder must exist.
  • Output: drawbar_<soil>_<state>.csv for four soils in three moisture states, and rain.csv.

Each drawbar file is a ramp of the drawbar pull with 30 samples for each second. The file rain.csv is a storm on a silt loam field while the Maxxum pulls a chisel plow. soil_weather_analysis.py --bench reads the drawbar files.

mkdir -p /tmp/drawbar
Tools/Terramechanics/demo_data /tmp/drawbar

bench_pull#

Runs one steady drawbar pull of the Maxxum on a uniform soil and prints one JSON object. The values are the mean of 5 s in gear 7 at full throttle.

  • Environment: none.
  • Input: the positional arguments of the table, in this sequence.
  • Output: the slip of the rear and front tyres, the net traction ratio, the loads, the sinkage and the tractive efficiency.
Name Type Unit Default Description
class text The id of the soil class, for example silt_loam.
se number The effective saturation of the soil, from 0 to 1.
wetness number The wetness of the surface, from 0 to 1.
water_mm number mm The depth of the water on the surface.
pull_n number N The drawbar pull.
mass_kg number kg Maxxum Optional. The mass of the vehicle.
hitch_m number m test stand Optional. The height of the pull point.

soil_weather_analysis.py starts this program. See also the tutorial Set Soil and Weather.

Tools/Terramechanics/bench_pull silt_loam 0.5 0 0 20000
{"rear_slip": 0.05822, "front_slip": 0.07214,
 "ntr": 0.3504, "front_share": 0.3336,
 "rear_load_n": 19016.6,
 "sinkage_front_m": 0.01366,
 "sinkage_rear_m": 0.01366,
 "tractive_eff": 0.8343, "theta": 0.2486}

Implement Model Tools#

These tools run the implement model of the game without Unreal Engine. The page Implement Mechanics gives the model.

Tools/ImplementModel/build.sh#

Builds the program implement_tool and runs its tests against the shipped data files.

  • Environment: a C++ compiler.
  • Input: implement_tool.cpp, implement_tests.cpp, implement_data.cpp, implement_tool.h, json_lite.h and the model sources in Acres/Source/Acres.
  • Output: the program implement_tool in the build folder, and the test results on the terminal.
Name Type Unit Default Description
CXX text g++ Environment variable. The C++ compiler.
BUILD_DIR path $TMPDIR/acres-implement-model Environment variable. The folder of the program.
UE_CLANG path Environment variable. The clang++ of Unreal Engine. The script then also compiles the model with it.

Without TMPDIR, the build folder is in /tmp.

Tools/ImplementModel/build.sh
BUILD_DIR=build/implement Tools/ImplementModel/build.sh

implement_tool#

Tests the implement model, prints the comparison with ASABE D497.7 and writes the data files. The first argument selects the command.

  • Environment: none.
  • Input: for test, the folder Acres/Content/Simulation/implements.
  • Output: for write-json, one file <id>.json for each implement and the file soils.json.
Name Type Unit Default Description
test command Runs all checks. The exit code is the number of failed checks, 100 at most.
--data path With test: the folder of the implement data files.
--verbose flag off With test: prints each check.
asabe command Prints the draft of the model and of ASABE D497.7 as a Markdown table.
write-json command Writes the data files from the default values of the code into the folder that follows.

See also the tutorial Attach and Operate Implements.

B=/tmp/acres-implement-model
$B/implement_tool test --data Acres/Content/Simulation/implements
$B/implement_tool asabe
$B/implement_tool write-json /tmp/implements
244 checks, 0 failed

Polaris Model Tools#

These tools run the Polaris model of the game without Unreal Engine. The header UtvBench.h is the test stand of the Polaris. The header DbwLog.h reads the recorded drive-by-wire logs. The pages Polaris Ranger Dynamics and Drive-by-Wire and ULC give the models.

Tools/PolarisModel/build.sh#

Builds the test program and the replay library of the Polaris model, then runs the tests.

  • Environment: a C++ compiler.
  • Input: polaris_tests.cpp, polaris_replay.cpp, DbwLog.h, UtvBench.h and the model sources in Acres/Source/Acres.
  • Output: polaris_tests and libpolaris.so in the build folder.
Name Type Unit Default Description
CXX text g++ Environment variable. The C++ compiler.
BUILD_DIR path $TMPDIR/acres-polaris-model Environment variable. The folder of the two outputs.
UE_CLANG path Environment variable. The clang++ of Unreal Engine. The script then also compiles the model with it.
Tools/PolarisModel/build.sh

polaris_tests#

Tests the Polaris model: mass and statics, cornering, power and top speed, braking, the drive-by-wire actuators, the energy ledger and the driveline. The tests also replay the recorded logs and compare the model with the reports of the vehicle.

  • Environment: none. Start the program from the repository root.
  • Input: polaris.json and the logs in Tools/PolarisModel/Data.
  • Output: the result of each check on the terminal. The exit code is 0 when each check passes.
Name Type Unit Default Description
--config path Acres/Content/Simulation/polaris.json The parameter file of the Polaris.
--data path Tools/PolarisModel/Data The folder of the recorded logs.
/tmp/acres-polaris-model/polaris_tests \
    --data Tools/PolarisModel/Data \
    --config Acres/Content/Simulation/polaris.json
44 passed, 0 failed

polaris_dbw.py#

Fits the drive-by-wire actuator model of the Polaris to the logs of the real vehicle. The script calls the C++ model through libpolaris.so.

  • Environment: torchenv, and libpolaris.so from Tools/PolarisModel/build.sh.
  • Input: for extract, the logs in $POLARIS_EXTRACT. For fit and replay, the files in Tools/PolarisModel/Data.
  • Output: see the table.
Name Type Unit Default Description
extract command Writes <run>_commands.csv and <run>_reports.csv into Tools/PolarisModel/Data.
fit command Fits each actuator, prints the error before and after, and writes Data/fit_results.json.
--write flag off With fit: writes the fitted values into Acres/Content/Simulation/polaris.json.
replay command Writes the model trace of one run as a CSV file. The arguments are the run name and the output file.

See also the tutorial Calibrate against Real Logs.

python Tools/PolarisModel/polaris_dbw.py extract
python Tools/PolarisModel/polaris_dbw.py fit
python Tools/PolarisModel/polaris_dbw.py fit --write
python Tools/PolarisModel/polaris_dbw.py replay \
    dbw_direct_test_01 /tmp/dbw_direct_test_01.csv

polaris_replay.cpp#

The source of libpolaris.so. The library gives a C interface to the Polaris model for polaris_dbw.py.

Function Description
polaris_create Loads the parameters from a polaris.json file.
polaris_set Sets one parameter by its key. The key replay.surface selects the ground.
polaris_get Returns a derived value, for example mass_kg.
polaris_replay Replays a command log and returns one row for each physics step.
polaris_columns Returns the number of columns of a row.
polaris_destroy Releases the model.

The ground of a replay is asphalt, gravel, grass or silt loam soil.

import ctypes
lib = ctypes.CDLL("/tmp/acres-polaris-model/libpolaris.so")
lib.polaris_create.restype = ctypes.c_void_p
lib.polaris_get.restype = ctypes.c_double
lib.polaris_get.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
model = lib.polaris_create(
    b"Acres/Content/Simulation/polaris.json")
print(lib.polaris_get(model, b"mass_kg"))
1233.0

LiDAR Model Tools#

Tools/LidarModel/build.sh#

Builds and runs lidar_tests.cpp, the tests of the LiDAR radiometry in AcresLidarPhysics.h. The tests compare the C++ code with the fitted values of Calibration/Polaris/lidar_model.py.

  • Environment: a C++ compiler.
  • Input: lidar_tests.cpp and Acres/Source/Acres/AcresLidarPhysics.h.
  • Output: the program lidar_tests in the build folder, and the test results. The exit code is 0 when each check passes.
Name Type Unit Default Description
CXX text g++ Environment variable. The C++ compiler.
BUILD_DIR path $TMPDIR/acres-lidar-model Environment variable. The folder of the program.

The page LiDAR gives the model.

Tools/LidarModel/build.sh

Episode Log Tools#

These tools test the writer and the reader of the episode log. The page Episode Log gives the format.

Tools/EpisodeLog/build.sh#

Examines the schema header, builds episode_log_tests.cpp and runs it. In the ros2 environment the script also runs check_ros.py on the test file.

  • Environment: a C++ compiler and Python. The ros2 environment is optional.
  • Input: episode_log_tests.cpp and Acres/Source/Acres/AcresEpisodeLog.cpp.
  • Output: the program episode_log_tests and the file episode_test.mcap in the build folder.
Name Type Unit Default Description
CXX text g++ Environment variable. The C++ compiler.
BUILD_DIR path $TMPDIR/acres-episode-log Environment variable. The folder of the outputs.

The program episode_log_tests has one optional argument, the path of the MCAP file that it writes.

Tools/EpisodeLog/build.sh
source ROS/Env/setup_env.sh
Tools/EpisodeLog/build.sh

gen_schemas.py#

Generates the header AcresEpisodeSchemas.h with the message definitions of the episode log. The game and ACRES Core write the episode log without ROS 2, thus they need the definitions as text.

  • Environment: Python, and the message files of the ros2 environment.
  • Input: ROS/acres_interfaces/msg and the msg folders of std_msgs, geometry_msgs and builtin_interfaces.
  • Output: Acres/Source/Acres/AcresEpisodeSchemas.h.
Name Type Unit Default Description
--check flag off Writes no file. The exit code is 1 when the header is not up to date.
ROS_SHARE path ~/miniconda3/envs/ros2/share Environment variable. The share folder of the ROS 2 packages.
python Tools/EpisodeLog/gen_schemas.py --check
schemas up to date
python Tools/EpisodeLog/gen_schemas.py

check_ros.py#

Reads an episode log with the MCAP reader of ROS 2 and the type support of acres_interfaces. The script compares the values with the test data of episode_log_tests.

  • Environment: ros2, with ROS/acres_interfaces built.
  • Input: one argument, the file episode_test.mcap from Tools/EpisodeLog/build.sh.
  • Output: the result on the terminal.
source ROS/Env/setup_env.sh
python Tools/EpisodeLog/check_ros.py \
    /tmp/acres-episode-log/episode_test.mcap

Simulator Control Tools#

These tools use the simulator control channel and the vehicle bridge on the local sockets, without ROS 2. The page Simulator Control Channel gives the operations.

sim_control.py#

A Python module with two clients. It has no command line. Each client refuses a host that is not a loopback address.

  • Environment: Python, and a running game or ACRES Core with the related port.
  • SimControl: the client of the simulator control channel. call(op, **fields) sends one request and returns the reply. The list events keeps the events.
  • JsonBridge: the client of the vehicle bridge. send(message) sends one command. The attributes observation, report and barrier keep the last data.
Name Type Unit Default Description
port integer 5600 The port. JsonBridge has no default port.
host text 127.0.0.1 The host. It must be a loopback address.
timeout_s number s 600 SimControl only. The time limit of a reply.
connect_s number s 300 The time limit of the connection. The client tries one time each second.

See also the tutorial Lockstep Stepping.

Packaged/Linux/Acres.sh -VehicleDemo -Vehicle=polaris \
    -SimControl=5600 -Lockstep -RlPort=5556
import sys
sys.path.insert(0, "Tools/SimControl")
from sim_control import JsonBridge, SimControl

ctl = SimControl(5600)
print(ctl.call("hello")["agents"])
dbw = JsonBridge(5556)
dbw.send({"dbw": {"enable": True}})
ctl.call("step", steps=120)

lockstep_determinism.py#

Starts the simulator two or more times in lockstep with the same commands and compares the paths of the Polaris. The check passes when the largest position difference is 1 cm or less.

  • Environment: Python and the packaged game. --game core needs the built ROS 2 workspace. --game editor needs UE.
  • Input: none. The ports are 5600 and 5556.
  • Output: for each run game<k>.log, run<k>.mcap and run<k>.csv, and the file summary.json.
Name Type Unit Default Description
--out path Necessary. The output folder.
--runs integer 2 The number of runs.
--seconds number s 60 The simulated time of each run.
--game choice packaged The simulator: packaged, editor or core.
--headless flag off Starts the game with -nullrhi, without images.
--npc flag off Adds the farm traffic and the workers.

See also Time Stepping and Determinism.

python Tools/SimControl/lockstep_determinism.py \
    --out /tmp/determinism --runs 2 --seconds 60
python Tools/SimControl/lockstep_determinism.py \
    --out /tmp/determinism-core --game core

compare_episodes.py#

Compares the agent paths of two episode logs step by step. For each agent it prints the largest difference of position and heading.

  • Environment: ros2, with ROS/acres_interfaces built.
  • Input: two arguments, the two MCAP files.
  • Output: one line for each agent on the terminal.

See also the tutorial Replay.

source ROS/Env/setup_env.sh
python Tools/SimControl/compare_episodes.py a.mcap b.mcap

render_check.py#

Records the camera, the LiDAR and the main view of the Polaris at fixed poses, times and weather. Two captures let you compare two builds image by image and scan by scan.

  • Environment: torchenv and the packaged game. The control port is 5600.
  • Input: for capture, the built-in pose list or a JSON list of poses.
  • Output: for capture, main/<pose>.png, camera/<pose>.png, lidar/<pose>.pcd and capture.json.
Name Type Unit Default Description
capture command Starts the game in lockstep and records each pose.
--out path With capture: necessary. The output folder.
--poses path built-in list With capture: a JSON list of poses.
--only text all With capture: the names of the poses to record.
--game-args text With capture: more game options, with spaces between them. Write it as --game-args=<options>.
--exec text With capture: console commands at the start, with commas between them.
--res text pixel 1920x1080 With capture: the size of the main view.
--settle-steps integer step 240 With capture: the physics steps after the vehicle moves to a pose.
--hold-s number s 3.0 With capture: the wall time that the renderer gets to become stable.
compare command Prints the differences of capture B against capture A. The arguments are the two folders.
--floor path With compare: a second capture of A. It gives the difference between two equal runs.
--json path With compare: writes the metrics into this file.

The image metrics are the mean absolute difference, PSNR and SSIM. The pages Camera and LiDAR give the sensor models.

python Tools/SimControl/render_check.py capture \
    --out /tmp/render-a
python Tools/SimControl/render_check.py capture \
    --out /tmp/render-b --game-args=-RenderTier=low
python Tools/SimControl/render_check.py compare \
    /tmp/render-a /tmp/render-b --json /tmp/render.json

can_over_ros_check.py#

Drives the Maxxum with J1939 frames on the topic /maxxum/can/tx and examines the frames on /maxxum/can/rx. The script starts the packaged game and the ROS 2 bridge, and stops only the processes that it started.

  • Environment: ros2 with the workspace built, and the packaged game.
  • Input: none. The ports are 5600, 5602, 5557 and 5610.
  • Output: game.log, bridge.log and result.json in the output folder. The exit code is 0 when the check passes.
Name Type Unit Default Description
--out path Necessary. The output folder.
--seconds number s 20 The simulated time.
--curvature number 1/m 0.05 The commanded curvature of the path. A positive value turns left.
--throttle number 0.45 The pedal value of the torque command.

See also Wheel and CAN Signals.

source ROS/Env/setup_env.sh
python Tools/SimControl/can_over_ros_check.py \
    --out /tmp/can-check

Performance Tools#

The benchmarks start the packaged game at 1920 x 1080 with the option -RenderBenchmark. The file field-loop.json is the drive script of the benchmark. The Maxxum drives a circle at 8 km/h in gear 8. See also Platforms and GPU Tiers.

benchmark_linux.py#

Measures the frame rate, the physics rate and the peak GPU memory of the packaged game on Linux. The script refuses to start when a game runs.

  • Environment: Python, the packaged game and nvidia-smi.
  • Input: Tools/Performance/field-loop.json with --field-loop.
  • Output: summary.json, arguments.json, runtime.log, wall-frames.csv, engine.csv and review.png in <out>/<name>.
Name Type Unit Default Description
--name text Necessary. The name of the result folder.
--vehicle choice maxxum The vehicle: maxxum or polaris.
--sensors flag off Records the sensors of the vehicle.
--field-loop flag off Uses the spawn of the field loop. The Maxxum then also uses the drive script.
--render-tier choice auto The render tier: auto, low or high.
--warmup number s 15 The time before the measurement.
--duration number s 15 The time of the measurement.
--extra text More game options, with spaces between them.
--exec text More console commands, with commas between them.
--out path Acres/Saved/Performance The parent folder of the results.
python Tools/Performance/benchmark_linux.py \
    --name high-maxxum --field-loop --render-tier high
python Tools/Performance/benchmark_linux.py \
    --name low-polaris-sensors --vehicle polaris \
    --sensors --render-tier low

benchmark_windows.ps1#

Measures the frame rate and the physics rate of the packaged game on Windows, with the time of each GPU pass. The script stops when the output is not 1920 x 1080.

  • Environment: PowerShell and the game in Packaged/Windows.
  • Input: Tools/Performance/field-loop.json with -FieldLoop.
  • Output: summary.json, arguments.json, runtime.log and a screenshot in BuildReports/Performance/<Name>.
Name Type Unit Default Description
-Name text packaged The name of the result folder.
-Preset choice packaged packaged uses the defaults of the game. The other presets are overrides for diagnosis.
-Vehicle choice maxxum The vehicle: maxxum or polaris.
-Sensors flag off Records the sensors of the vehicle.
-FieldLoop flag off Uses the spawn and the drive script of the field loop.
-SpawnAt text The name of a place for the spawn.
-Warmup integer s 15 The time before the measurement.
-Duration integer s 15 The time of the measurement.
-AnalyzeOnly flag off Does not start the game. Computes the summary from the files of an earlier run.
-ExtraCommands text More console commands, with semicolons between them.
-CameraWidth integer pixel 0 The width of the sensor camera. 0 keeps the configured value.
-CameraHeight integer pixel 0 The height of the sensor camera. 0 keeps the configured value.
-CameraHz integer Hz 0 The rate of the sensor camera. 0 keeps the configured value.
-CameraMainFamily flag off Adds the game option -SensorCameraMainFamily.
-CameraSelfTest flag off Adds the game option -SensorCameraSelfTest.
-FoliageWindDistance integer cm 3000 The value of acres.FoliageWindDistance for a preset that is not packaged.
-FoliageMaskDistance integer cm 0 The value of acres.FoliageMaskDistance. 0 keeps the default value.

The presets are baseline, memory, balanced, fast, raster, distance, optimized and packaged.

./Tools/Performance/benchmark_windows.ps1 -Name field `
    -Preset packaged -FieldLoop
./Tools/Performance/benchmark_windows.ps1 -Name sensors `
    -Preset packaged -FieldLoop -Sensors

UI Text Check#

ui_text_check.py#

Examines the style of each string that the user sees in the game UI. Titles, buttons and labels use title case. Descriptions and messages use sentence case. The script also examines the units, the number ranges and the words in capital letters.

  • Environment: Python, with Documentation/Tools on PYTHONPATH.
  • Input: ten source files of the game in Acres/Source/Acres, Demo/Menu/*.json and the Python files in Learning/acres_learn.
  • Output: each violation as file:line on the terminal. The exit code is 1 when there is a violation.
Name Type Unit Default Description
--list flag off Also prints each string with its category.
--all flag off With --list: also prints the strings that the check ignores.

Note

The script imports the module titlecase of the documentation tools. Without PYTHONPATH=Documentation/Tools the script stops with ModuleNotFoundError.

See also Coding and Naming Conventions.

PYTHONPATH=Documentation/Tools python Tools/ui_text_check.py
ui_text_check: 1149 visible strings checked,
0 violations in 0 strings
PYTHONPATH=Documentation/Tools python Tools/ui_text_check.py --list

Map and Asset Pipelines#

The scripts in Tools/ACRE made the map layers, the meshes and the materials of the tile. You do not need them to build or to run the game. Use them when you change the map or an asset. The pages Map Products and The ACRE Scene describe the results.

Note

Most of these scripts read or write the folder Acres/Raw/ACRE. This folder is local and is not in the repository. fetch_sources.py downloads the public sources of the map into it.

The scripts have three kinds. The kind sets the environment.

Kind Folders and Environment
Map script Tools/ACRE/Map. The environment is torchenv. Start the script with python.
Blender script Tools/ACRE/Structures, Props, Vegetation and Vehicles. The environment is Blender. Arguments of the script follow --.
Editor script Tools/ACRE/Tools and Vehicles. The environment is Editor Python. Most scripts write a report into Acres/Saved.

Map Sources and Registration#

These scripts download the public sources, put them on the grids of the tile and measure their position errors.

Script Function
acre_map.py A module with the grids, the paths and the coordinate functions of the tile.
fetch_sources.py Downloads the LiDAR tiles, the orthophotos and the vector sources. Writes sources.json.
rasters.py Puts the orthophotos and the LiDAR points on the grids of the tile as .npy files.
register.py Measures the shift of each image against the LiDAR. Writes registration.json.
source_checks.py Measures the vector and control sources against the survey. Writes Calibration/Map/source_checks.json.
tracks.py A module that reads the Polaris tracks on the tile.
test_map.py Tests of the map mathematics. The tests need no data files.
Name Type Unit Default Description
vectors command fetch_sources.py: downloads only the vector and control sources.
county command fetch_sources.py: downloads the county orthophoto of 2025. Its licence permits local use only.
--only choice all rasters.py: makes one product: ortho, naip, lidar or features.
python Tools/ACRE/Map/fetch_sources.py
python Tools/ACRE/Map/rasters.py
python Tools/ACRE/Map/register.py
python Tools/ACRE/Map/source_checks.py
python Tools/ACRE/Map/test_map.py

Lane, Road and Ground Layer#

These scripts measure the lanes, the roads and the hard surfaces, and write the ground layer of the game. The ground layer is the file Acres/Content/Simulation/ACRE/surface_polygons.json.

Script Function
lanes.py Measures the farm lanes, the grass strips and the plot alleys. Writes lanes_raw.json.
layer.py Gives each lane segment a class. Writes Calibration/Map/Layers/lanes.geojson and three rasters.
road_audit.py Measures the position and the width of each road in the images. Writes road_audit.json.
hardstanding.py Measures the yards, the lots and the pads. Writes hardstanding.json.
verges.py Measures the grass strip between each road and the field. game_layer.py calls it.
us52.py Puts the highway US 52 on its real line. Writes us52.json and the data of the road mesh.
game_layer.py Writes surface_polygons.json and the rasters that the game reads from the same polygons.
game_layer_fit.py Moves the polygons of the lots and the building pads to the fitted meshes.
site_edits.py Adds the woodland, the entrances and the driveways, and makes the edges of the hard ground smooth.
smooth_ground_edges.py Removes the stair steps from the outlines of the lawns.
fix_icsc_driveway.py Corrects the drive between US 52 and the ICSC building.
game_textures.py Draws the ground layer into the textures of the ground material.
game_textures_striped.py The same textures in horizontal strips, for a computer with 16 GB of memory.
Name Type Unit Default Description
--no-fields flag off game_layer.py, site_edits.py: does not cut the field polygons again.
--no-verges flag off game_layer.py: does not measure the road verges.
--no-textures flag off game_layer_fit.py, site_edits.py: does not draw the textures.
--no-site flag off us52.py: does not change site.json.
--no-imaged flag off us52.py: does not compare the line with the orthophoto.
--size integer pixel 16384 game_textures.py, game_textures_striped.py: the size of the texture.
--rows integer pixel 256 game_textures_striped.py: the height of one strip.

smooth_ground_edges.py and fix_icsc_driveway.py have no arguments. Each one starts its work immediately.

python Tools/ACRE/Map/lanes.py
python Tools/ACRE/Map/layer.py
python Tools/ACRE/Map/road_audit.py
python Tools/ACRE/Map/hardstanding.py
python Tools/ACRE/Map/us52.py
python Tools/ACRE/Map/game_layer.py
python Tools/ACRE/Map/site_edits.py
python Tools/ACRE/Map/game_textures.py --size 16384

Field, Crop and Place Layers#

These scripts write the field polygons, the crop season, the named places and the tree check.

Script Function
fields_recut.py Cuts the 59 field polygons along the measured edges. Writes fields.json and field_ids.u8.
field_edits.py Measures the edits of the fields F50, F52 and F58. site_edits.py applies them.
crops.py Finds the crop of each field in 2026 from satellite data. Writes Calibration/Map/Layers/crops_2026.json.
game_crops.py Writes the crop season file of the game, Acres/Content/Simulation/ACRE/crops_2026.json.
places.py Writes places.json from a folder of place labels. The argument is the folder.
tree_check.py Compares each surveyed tree with recent images and lists the trees that no longer stand.
Name Type Unit Default Description
measure command field_edits.py: writes the outline of the woods into field_edits_t22.json.
--trees path local file field_edits.py measure: the tree file from dump_trees.py.
yards command field_edits.py: writes the yard outlines into field_edits_t23.json.
evidence command field_edits.py: prints the crop evidence for the fields F52 and F58.
figure command field_edits.py: writes the figures into Calibration/Map/Figures.
canopy command tree_check.py: writes the two canopy rasters.
check command tree_check.py: writes the verdicts, the report and the figures.
--dump path tree_check.py check: necessary. The tree file from dump_trees.py.

game_crops.py reads the weather record in $ACRE_WEATHER. See also Crops and Ground Classes.

python Tools/ACRE/Map/fields_recut.py
python Tools/ACRE/Map/crops.py
python Tools/ACRE/Map/game_crops.py
python Tools/ACRE/Map/tree_check.py canopy
python Tools/ACRE/Map/tree_check.py check \
    --dump Acres/Saved/trees_level.json

Building Footprints and Fits#

These scripts measure the buildings and compute the placement of the building meshes and the parking lots.

Script Function
buildings.py Selects the best footprint of each building and adds the LiDAR roof heights. Writes buildings.geojson.
building_models.py Makes the parts and the roof forms of each building. Writes building_models.json.
fit_original_buildings.py Fits the original building meshes into the measured footprints. Writes original_buildings_fit.json.
fit_lots.py Fits the parking lot meshes to the painted stalls. Writes lots_fit.json.
Map/icsc_portico.py Measures the shift and the width of the entry portico of the ICSC building.
Name Type Unit Default Description
--geom path fit_original_buildings.py, fit_lots.py: necessary. The geometry folder from dump_structures.py.
--pre-level path The same two scripts: necessary. The actor file of the level with the original placements.
--t15-level path fit_original_buildings.py: necessary. The actor file of the level with the generated models.
--out path a file in Calibration/Map/Layers The same two scripts: the output file.
measure command Map/icsc_portico.py: writes icsc_portico.json.
update command Map/icsc_portico.py: updates the ICSC row of the fit file. --geom gives the geometry file.
figure command Map/icsc_portico.py: writes the figure.

The outputs are in Calibration/Map/Layers. Core/Scripts/build_scene.py reads building_models.json.

python Tools/ACRE/Map/buildings.py
python Tools/ACRE/Map/building_models.py
python Tools/ACRE/Map/fit_lots.py \
    --geom /tmp/geom --pre-level /tmp/pre_level.json
python Tools/ACRE/Map/icsc_portico.py measure

Structure Generators#

These Blender scripts make the meshes of the buildings, the farmyard and the paved surfaces. Each script exports FBX files into Acres/Raw/ACRE/Structures.

Script Function
acre_layout.py A module with the positions of the lawns, the pads, the drives and the parking lots. It does not use Blender.
acre_buildings.py Makes the 23 original buildings and the pavement pads. Call its function build() in Blender.
acre_farmyard.py Makes the grain bins, the elevator leg, the Quonset hut, the sheds and the wagons. Call build().
acre_footprint_buildings.py Makes one building mesh for each measured footprint from building_models.json.
acre_surfaces.py Makes the surface patches, the lots and the road meshes that follow the terrain.
dust_collector.py Makes the dust collector at the ICSC building.
Structures/icsc_portico.py Makes the ICSC building again with the portico at the measured position.
redrape_lots.py Puts a moved parking lot mesh on the terrain again. The arguments are the lot names.
Name Type Unit Default Description
--only text all acre_footprint_buildings.py: the names of the buildings, with commas between them.
--no-export flag off acre_footprint_buildings.py, dust_collector.py: does not write the FBX files.
--preview path dust_collector.py: writes preview images into this folder.
--us52 flag off acre_surfaces.py: makes the meshes of US 52. Without it the script only defines functions.
--shift number m measured value Structures/icsc_portico.py: the shift of the portico.
--width number m measured value Structures/icsc_portico.py: the width of the portico.
--check path Structures/icsc_portico.py: compares the model with a geometry file. The defaults are then 0 m and 13 m.
blender -b --python \
    Tools/ACRE/Structures/acre_footprint_buildings.py
blender -b --python Tools/ACRE/Structures/acre_surfaces.py \
    -- --us52
blender -b --python Tools/ACRE/Structures/redrape_lots.py \
    -- lot_D_ics_front

Prop Generators#

These Blender scripts make the small meshes of the scene and the legacy implement meshes. Each script exports FBX files into Acres/Raw/ACRE/Props. import_props.py imports them.

Script Function
acre_sign.py Makes the entrance board of ACRE at US 52.
dumpster.py Prepares the dumpster model and its textures.
harvester_header.py Makes the harvester header and its reel from a licensed model. It also exports the body of the source model.
implements.py Makes seven procedural implement meshes, for example chisel_plow and potato_digger.
Name Type Unit Default Description
preview_dir path harvester_header.py, implements.py: the first argument. A folder for preview images.
type text all implements.py: the next arguments. The implement types to make.

The source model of harvester_header.py has the licence CC BY-NC 4.0. The game shows the header and the reel on the Maxxum with the option -FarmHarvester.

blender -b --python Tools/ACRE/Props/acre_sign.py
blender -b --python Tools/ACRE/Props/implements.py \
    -- /tmp/preview chisel_plow

Tree and Vegetation Pipeline#

The Blender scripts in Tools/ACRE/Vegetation make the tree and crop meshes. The editor scripts in Tools/ACRE/Tools import the meshes and put the trees into the level V03ACRE.

Script Function
elm_variants.py Blender. Makes three elm meshes from a source model.
elm_street.py Blender. Makes the street tree from an elm. This is a legacy script: repair_street_trees.py replaces its result.
spruce.py Blender. Makes two procedural spruce meshes.
straight_trees.py Blender. Exports two straight street trees from a tree set.
prep_straight_textures.py Python. Makes the leaf texture of the tree set.
potato_patches.py Blender. Makes three potato crop patches from Acres/Raw/farm.blend.
import_trees.py Editor. Imports the elm meshes.
import_street_trees.py Editor. Imports the street elm and sets it on the street tree component.
rebuild_trees.py Editor. Puts the surveyed trees and the woodland trees on the tree components.
add_trees.py Editor. Adds the spruce row and the street trees along the Beck drive.
repair_street_trees.py Editor. Makes the 19 street trees again from the broadleaf source mesh.
remove_absent_trees.py Editor. Removes the trees that tree_check.py lists.
tree_nanite.py Editor. Sets the Nanite option that keeps the leaf area of the foliage meshes.
dump_trees.py Editor, read only. Writes each tree instance into Acres/Saved/trees_level.json.
import_potato_patches.py Editor. Imports the potato crop patches.
lawn_fields.py Editor. Removes the crop patches of the lawn fields and adds turf.
clear_paved_cover.py Editor. Removes ground cover and trees that are on paved ground or in a building.
turf_stats.py Editor, read only. Counts the turf instances. Writes Acres/Saved/turf_stats.json.
Name Type Unit Default Description
ACRES_DUMP_OUT path Acres/Saved/trees_level.json Environment variable. dump_trees.py: the output file.
blender -b --python Tools/ACRE/Vegetation/elm_variants.py
blender -b Acres/Raw/farm.blend --python \
    Tools/ACRE/Vegetation/potato_patches.py
python Tools/ACRE/Vegetation/prep_straight_textures.py
"$UE/Engine/Binaries/Linux/UnrealEditor-Cmd" \
    Acres/Acres.uproject -run=pythonscript \
    -script=Tools/ACRE/Tools/dump_trees.py

Vehicle and Implement Asset Import#

These scripts bring the meshes of the vehicles, the implements and the traffic cars into the game. The source models are in Acres/Raw/farm-equipment.

Script Function
export_rig_map.py Blender. Writes the equipment rig of each asset as JSON into Acres/Content/Simulation/rigs. It also makes the FBX files and the material lists for the import.
import_farm_equipment.py Editor. Imports the Maxxum, the implements and the Polaris as skeletal meshes into /Game/FarmEquipment.
prep_npc_cars.py Blender. Prepares the downloaded car models for the highway traffic.
import_npc_cars.py Editor. Imports the prepared cars and writes Acres/Content/Simulation/npc_cars.json.
Name Type Unit Default Description
asset text all export_rig_map.py: the asset names after --, for example maxxum_150 polaris.
car text all prep_npc_cars.py: the car names after --.
--list flag off prep_npc_cars.py: prints the statistics of the material slots and exports no file.
ACRES_ONLY text all Environment variable. import_farm_equipment.py, import_npc_cars.py: the asset names, with commas between them.

Run export_rig_map.py before import_farm_equipment.py. The two scripts ignore the asset combine_harvester of the source catalog, unless you give its name. The game has no combine harvester. See also Add a Vehicle.

blender -b --factory-startup --python \
    Tools/ACRE/Vehicles/export_rig_map.py
"$UE/Engine/Binaries/Linux/UnrealEditor-Cmd" \
    Acres/Acres.uproject -run=pythonscript \
    -script=Tools/ACRE/Vehicles/import_farm_equipment.py \
    -unattended -nosplash -nullrhi
blender -b --factory-startup --python \
    Tools/ACRE/Vehicles/export_rig_map.py -- maxxum_150 polaris

Editor Import Scripts#

These editor scripts import the structures and the surfaces, and put them into the level V03ACRE.

Script Function
import_building_textures.py Makes the textured material instances of the buildings.
reimport_buildings.py Imports the generated building FBX files again. The actors keep their references.
import_icsc_portico.py Imports the ICSC building with the moved portico.
import_lots.py Imports the pavement materials, the lots and the light poles.
import_surfaces.py Imports the surface meshes of the lots, the drives and the roads.
import_props.py Imports the dumpster, the dust collector, the sign, the harvester header and the implement meshes.
import_vertex_color_mesh.py Imports one FBX file and keeps its vertex colours.
place_original_buildings.py Puts the original buildings, the grain bins and the lots at their fitted positions.
reimport_us52.py Imports US 52 on its measured line and moves its actors.
reimport_road_lanes.py Imports the texture RoadLanes again.
dump_structures.py Read only. Writes the static mesh actors of the level, and the mesh geometry when you set the folder.
t18_level_edits.py Applies the site edits of site_edits.py to the level.
fix_icsc_driveway_level.py Puts the entrance sign in position and removes the crops from the corrected drive.
Name Type Unit Default Description
ACRES_ONLY text all import_building_textures.py, reimport_buildings.py: the names to import.
ACRES_IMPORT text import_vertex_color_mesh.py: necessary. One job is the FBX file, the content folder and the asset name, with a vertical bar between them.
ACRES_DUMP_OUT path Acres/Saved/structures_level.json dump_structures.py: the output file.
ACRES_GEOM_DIR path dump_structures.py: also writes the geometry of the building meshes into this folder.
ACRES_GEOM_MESHES text building meshes dump_structures.py: the asset paths of the meshes, with commas between them.
ACRES_NO_LEVEL flag off dump_structures.py: the value 1 writes no actor file.
ACRES_IMPORT_LEG flag off place_original_buildings.py: the value 1 imports the elevator leg.
ACRES_IMPORT_LOTS flag off place_original_buildings.py: the value 1 imports the lots at their fitted positions.
ACRES_KEEP_EDITOR flag off place_original_buildings.py: the value 1 keeps the editor open at the end.
ACRES_SKIP_LEG flag off t18_level_edits.py: the value 1 does not import the elevator leg.

All names of this table are environment variables. place_original_buildings.py adds actors, thus it needs the full editor and not the commandlet.

ACRES_GEOM_DIR=/tmp/geom \
"$UE/Engine/Binaries/Linux/UnrealEditor-Cmd" \
    Acres/Acres.uproject -run=pythonscript \
    -script=Tools/ACRE/Tools/dump_structures.py
"$UE/Engine/Binaries/Linux/UnrealEditor" Acres/Acres.uproject \
    -ExecutePythonScript=Tools/ACRE/Tools/place_original_buildings.py \
    -RenderOffscreen -unattended

Material and Render Scripts#

These scripts make the materials of the ground and the weather, and contain the corrections for a GPU fault.

CAUTION

release_cleanup.py deletes actors of the level and asset packages. Do not start it on content that you want to keep.

Script Function
make_ground_layer_materials.py Editor. Imports the textures of the ground layer and makes the ground materials that read them.
make_field_work_materials.py Editor. Makes the materials of the worked soil, the spray fans, the dust and the splashes.
make_rain_lens.py Editor. Makes the post-process material that shows rain on the view.
editor_ground_layer.py Editor. A record of an old level edit. On the current level it changes nothing.
terrain_nanite_off.py Editor. Sets the terrain tiles and the masked ground meshes to render without Nanite.
fix_wpo_bounds.py Editor. Sets the maximum wind displacement of the foliage materials.
release_cleanup.py Editor. A record of the content cleanup before the release. It deletes unused actors and assets.
check_acre_layer_shader.py Python. Compiles Acres/Shaders/AcresAcreLayer.ush with the shader compiler of the engine, without the editor.
gpu_fault_repro.sh Shell. Renders the Polaris camera many times at one pose and counts the GPU faults.
Name Type Unit Default Description
ACRES_SKIP_TEXTURES flag off Environment variable. make_ground_layer_materials.py: does not import the textures.
ACRES_SKIP_MATERIALS flag off Environment variable. make_ground_layer_materials.py: does not make the materials.
ACRES_RESTORE flag off Environment variable. terrain_nanite_off.py: the value 1 sets Nanite on again.
ACRES_PASS choice level Environment variable. release_cleanup.py: the pass, level or assets.
shader path the shipped file check_acre_layer_shader.py: the shader file.
out_dir path ~/Codes/polaris/episodes/_gpu_repro gpu_fault_repro.sh: the first argument. The output folder.
n integer 25 gpu_fault_repro.sh: the second argument. The number of renders.

gpu_fault_repro.sh starts Calibration/Polaris/camera_render.py and thus the packaged game. check_acre_layer_shader.py needs the variable UE.

python Tools/ACRE/Map/game_textures.py
"$UE/Engine/Binaries/Linux/UnrealEditor-Cmd" \
    Acres/Acres.uproject -run=pythonscript \
    -script=Tools/ACRE/Tools/make_ground_layer_materials.py
python Tools/ACRE/Tools/check_acre_layer_shader.py
Tools/ACRE/Tools/gpu_fault_repro.sh /tmp/gpu-repro 25

Package and Play Scripts#

These scripts package the game, start it for a screenshot and connect to the editor.

CAUTION

package.sh stops the running game and the editor. play.sh stops the running game. Save your work in the editor before you start package.sh.

Script Function
package.sh Packages the game for Linux in the configuration Development into the folder Packaged.
play.sh Starts the packaged game at a survey cell and makes a screenshot of the desktop.
shot.py Makes a screenshot of the full desktop through the desktop portal of GNOME on Wayland.
cast.py Records an area of the screen with the screencast service of GNOME Shell.
decode_capture.py Converts a viewport capture of the Unreal MCP server from text to a PNG file.
uemcp.py A small HTTP client of the Unreal MCP server of the editor on port 8000.
Name Type Unit Default Description
logfile path Acres/Saved/work/build.log package.sh: the log file of the build.
U V YAW out.png text play.sh: the survey cell, the heading in degrees and the output image. More game options can follow.
out.png path shot.png shot.py: the output image.
out seconds text cast.py: the output name and the time. The area x y w h can follow.
result.txt out.png path decode_capture.py: the input and the output. A maximum width can follow.
--script path uemcp.py: sends a Python file to the editor. Without it, the arguments are the tool set, the tool and the JSON arguments.

package.sh needs the variable UE. The page Build the Game gives the full procedure. shot.py needs the Python package jeepney.

export UE=~/UnrealEngine
Tools/ACRE/Tools/package.sh
Tools/ACRE/Tools/play.sh 480 405 0 /tmp/field.png

ACRES Core Tools#

These tools build ACRES Core and compare it with the game and with the recorded logs. The page Build ACRES Core gives the build procedure. See also the tutorial Headless Core Runs.

Core/build.sh#

Builds libacres_core, the Python module acres_core, the test programs and the tools, then runs the tests.

  • Environment: a C++ compiler, CMake, Ninja and Python with pybind11, numpy and mcap.
  • Input: Core/CMakeLists.txt, Core/Source, Core/Python, Core/Tests, Core/Tools and the model sources of the game.
  • Output: the library, the module, core_tests, lidar_tests, core_replay and lidar_compare in the build folder.
Name Type Unit Default Description
--no-tests flag off Builds only. Does not run the tests.
BUILD_DIR path Core/Build Environment variable. The build folder.
PYTHON path python3 on PATH Environment variable. The interpreter of the Python module.

The tests are the programs *_tests and the files Core/Tests/test_*.py. The exit code is 1 when a test fails.

Core/build.sh
PYTHON=~/miniconda3/envs/torchenv/bin/python \
    Core/build.sh --no-tests

bench.py#

Measures the speed of ACRES Core: simulated seconds for each second of wall time, and LiDAR scans for each second. The Polaris drives on the tile with terrain, surface, soil and crop data.

  • Environment: torchenv and the Core build.
  • Input: the configuration and map files of the repository.
  • Output: the results on the terminal, and a JSON file with --json.
Name Type Unit Default Description
--root path repository root The repository folder.
--envs integer 64 The number of environments.
--seconds number s 20 The simulated time of each measurement.
--json path Writes the results into this file.
PYTHONPATH=Core/Build python Core/Scripts/bench.py \
    --envs 4 --seconds 2
farm_1_thread         685 x real time
farm_all_threads     1201 x real time
no_farm_1_thread      571 x real time
no_farm_all_threads  1251 x real time
lidar helios  1 thread:    99.7 scans/s
lidar planar  1 thread: 16814.2 scans/s

build_scene.py#

Writes Core/Data/acre_scene.json, the static obstacles of the tile for the LiDAR and the collisions of ACRES Core. The obstacles are the buildings, the grain bins and the trees.

  • Environment: torchenv.
  • Input: building_models.json and tree_check.json in Calibration/Map/Layers, sensors_polaris.json, and a tree file in $POLARIS_EPISODES.
  • Output: Core/Data/acre_scene.json.
Name Type Unit Default Description
--episodes path $POLARIS_EPISODES The folder that contains the tree file of the level.
--out path Core/Data/acre_scene.json The output file.
python Core/Scripts/build_scene.py

replay_logs.py and core_replay#

Replays the recorded drive-by-wire logs of the Polaris through ACRES Core and through the test stand. core_replay is the C++ program from Core/Tools/core_replay.cpp. replay_logs.py starts it for each log and compares the traces.

  • Environment: torchenv and the Core build.
  • Input: the logs in Tools/PolarisModel/Data and fit_results.json.
  • Output: <prefix>_core.csv and <prefix>_bench.csv from core_replay. A JSON summary and figures from replay_logs.py.
Name Type Unit Default Description
--root path repository root Both: the repository folder.
--build path <root>/Core/Build replay_logs.py: the Core build folder.
--out path $TMPDIR/acres-core-replay replay_logs.py: the folder of the traces.
--json path <out>/replay_logs.json replay_logs.py: the summary file.
--figures path ~/UnrealEngine/Demo/26-acres-core replay_logs.py: the folder of the figures.
--run text core_replay: necessary. The name of the log.
--ground text bench_asphalt core_replay: bench_asphalt, bench_grass, bench_gravel or a surface of tractor.json.
--data path <root>/Tools/PolarisModel/Data core_replay: the folder of the logs.
--out path the run name core_replay: the prefix of the two output files.
Core/build.sh --no-tests
python Core/Scripts/replay_logs.py \
    --out /tmp/core-replay --figures /tmp/core-replay
Core/Build/core_replay --root . \
    --run dbw_direct_test_01 --out /tmp/dbw_direct

compare_unreal.py and unreal_dbw_replay.py#

compare_unreal.py drives ACRES Core with the commands of a recording of the game and compares the motion. unreal_dbw_replay.py sends a recorded command log to the running game and writes the commands that it sent.

  • Environment: torchenv and the Core build. unreal_dbw_replay.py needs a running game with the Polaris and -RlPort=5556.
  • Input: a bag of the game with --bag, or a session folder with --session.
  • Output: commands_sent.csv, reports.jsonl and replay.json from the replay. A JSON summary and figures from the comparison.
Name Type Unit Default Description
--bag path compare_unreal.py: a recording as a bag folder, a .db3 file or an .mcap file.
--session path compare_unreal.py: a session folder of the game from unreal_dbw_replay.py.
--commands path With --session: its file commands_sent.csv. In the replay script: a command file in place of --run.
--session2 path With --session: a second session of the same log.
--commands2 path --commands With --session2: its file commands_sent.csv.
--follower-all flag off Compares each run of $POLARIS_FOLLOWER/sim/configs.json.
--only text all With --follower-all: the run ids.
--content-commit text Compares on the map of this commit.
--content-dir path Compares on this configuration folder.
--overrides text Polaris parameters as key=value, with semicolons between them.
--game-drop flag off Starts with the 0.2 m drop of the game.
--farm-water flag from the session The wheels read the soil water of the farm. --no-farm-water is the opposite.
--every number s 10 The time between two comparison windows.
--warmup number s 3 The time that Core runs before a window.
--horizon number s 10 The length of a window.
--json path Writes the summary into this file.
--figure-dir path Writes the figures into this folder.
--selftest flag off Both scripts: a test that does not need the game.
--run text dbw_direct_test_01 unreal_dbw_replay.py: a log of Tools/PolarisModel/Data.
--port integer 5556 unreal_dbw_replay.py: the port of the vehicle bridge.
--place text spawn-icsc-garage unreal_dbw_replay.py: the start place from places.json.
--start text unreal_dbw_replay.py: the start pose as east,north,heading_deg.
--speed number m/s 0 unreal_dbw_replay.py: the speed at the start.
--settle number s 3 unreal_dbw_replay.py: the time at rest before the first command.
--tail number s 2 unreal_dbw_replay.py: the time of the record after the last command.
--out path replay unreal_dbw_replay.py: the output folder.

compare_unreal.py also accepts --root, the repository folder.

Packaged/Linux/Acres.sh -VehicleDemo -Vehicle=polaris \
    -RlPort=5556 -SessionLog -FarmDisabled \
    -VehicleOutput=/tmp/core_cmp -RenderOffscreen
python Core/Scripts/unreal_dbw_replay.py \
    --run dbw_direct_test_01 --port 5556 \
    --out /tmp/core_cmp/replay
PYTHONPATH=Core/Build python Core/Scripts/compare_unreal.py \
    --session /tmp/core_cmp \
    --commands /tmp/core_cmp/replay/commands_sent.csv

compare_lidar.py and lidar_compare#

Compares the ray-cast LiDAR of ACRES Core with the LiDAR renders of the game at the same poses. lidar_compare is the C++ program from Core/Tools/lidar_compare.cpp. It makes one Core scan for each pose.

  • Environment: torchenv and the Core build.
  • Input: the work folder of the LiDAR calibration, with the renders of Calibration/Polaris/lidar_sim.py.
  • Output: <out>/<name>.scan from lidar_compare. A JSON summary and a figure from compare_lidar.py.
Name Type Unit Default Description
--work path $POLARIS_LIDAR_WORK compare_lidar.py: the work folder of the LiDAR calibration.
--label text after compare_lidar.py: the label of the renders.
--poses integer 60 compare_lidar.py: the maximum number of scans.
--bin path Core/Build/lidar_compare compare_lidar.py: the C++ program.
--scratch path temporary folder compare_lidar.py: the folder of the poses and the Core scans.
--summary path compare_lidar.py: writes the summary into this file.
--figure path ~/UnrealEngine/Demo/26-acres-core/lidar_compare.png compare_lidar.py: the figure file.
--root path . lidar_compare: the repository folder.
--poses path lidar_compare: necessary. A CSV file with one pose in each line.
--out path lidar_compare: necessary. The output folder.
--noise flag off lidar_compare: adds the sensor noise.
python Core/Scripts/compare_lidar.py --label after \
    --poses 60 --summary /tmp/lidar.json \
    --figure /tmp/lidar_compare.png
Core/Build/lidar_compare --root . \
    --poses /tmp/poses.csv --out /tmp/core-scans

ROS 2 Tools#

The scripts in ROS/Env make the ros2 environment safe. The scripts in ROS/Tools examine bags and build support packages. The page Build the ROS 2 Workspace gives the procedure.

setup_env.sh and dds_safety.sh#

setup_env.sh prepares one shell for the ROS 2 workspace. Use it with source. It activates the conda environment, applies the DDS loopback fence and adds the built workspace. dds_safety.sh contains the fence. The settings keep all ROS 2 traffic on the address 127.0.0.1.

WARNING

Do not start ROS 2 nodes of this repository without the DDS loopback fence. A drive-by-wire command that leaves the workstation can move the real vehicle.

  • Environment: bash and conda with the ros2 environment.
  • Input: ROS/Env/cyclonedds_localhost.xml, ROS/Env/colcon_defaults.yaml and ROS/install/setup.bash.
  • Output: the environment variables of the fence, and one status line.

The fence sets these variables. It also removes ROS_STATIC_PEERS and ROS_DISCOVERY_SERVER.

Variable Value
ROS_LOCALHOST_ONLY 1. ROS 2 Humble then uses only the loopback interface.
ROS_AUTOMATIC_DISCOVERY_RANGE LOCALHOST. The same limit for newer ROS 2 releases.
ROS_DOMAIN_ID 77. The real vehicle uses domain 0.
RMW_IMPLEMENTATION rmw_cyclonedds_cpp. The middleware.
CYCLONEDDS_URI The file cyclonedds_localhost.xml: loopback interface only, no multicast.

These variables are the inputs of the two scripts.

Name Type Unit Default Description
ACRES_ROS_ENV text ros2 The name of the conda environment.
CONDA_ROOT path ~/miniconda3 The conda folder.
ACRES_ROS_DDS_XML path next to the script A different middleware configuration file.
source ROS/Env/setup_env.sh
# Only the fence, in an environment that is active:
source ROS/Env/dds_safety.sh

install_conda_hooks.sh#

Installs the DDS loopback fence into the activation scripts of a conda environment. After that, conda activate ros2 alone applies the fence. Run the script again after you change the fence files.

  • Environment: bash and a conda environment.
  • Input: dds_safety.sh and cyclonedds_localhost.xml. One optional argument, the prefix of the environment.
  • Output: the files in <prefix>/etc/acres_ros, the two scripts zz-acres-ros-dds-safety.sh, and <prefix>/.condarc.
Name Type Unit Default Description
prefix path ~/miniconda3/envs/ros2 The folder of the conda environment.
ACRES_ROS_ENV_PREFIX path Environment variable. The default prefix when you give no argument.
ROS/Env/install_conda_hooks.sh
conda deactivate
conda activate ros2

check_dds_isolation.sh#

Proves that the DDS loopback fence operates. The script starts a demonstration talker and a listener and records each network destination of the talker.

  • Environment: the active ros2 environment with strace.
  • Input: one optional argument, the time of the test in seconds. The default is 6.
  • Output: PASS or FAIL and the evidence on the terminal, and the logs in a temporary folder. The exit code is 0 for PASS.
conda activate ros2
ROS/Env/check_dds_isolation.sh
ROS/Env/check_dds_isolation.sh 10

bench_sensor_stream.sh#

Measures the frame rate cost of the sensor stream in four configurations of the packaged game. The configurations are no sensors, the sensor stream without a client, the sensor stream with the ROS 2 bridge, and the file recorder.

  • Environment: ros2 with the workspace built, and the packaged game. The ports are 5601 and 5556.
  • Input: none.
  • Output: <out>/<config>/wall-frames.csv, <out>/summary.json and bridge_stats.json for the configuration ros.
Name Type Unit Default Description
out_dir path ROS/log/bench_sensor_stream The first argument. The output folder.
seconds integer s 40 The second argument. The time of each measurement.
CONFIGS text base stream ros files Environment variable. The configurations to run.

The page Sensor Stream gives the protocol.

source ROS/Env/setup_env.sh
ROS/Tools/bench_sensor_stream.sh /tmp/bench-stream 40
CONFIGS="base ros" ROS/Tools/bench_sensor_stream.sh

build_lab_follower.sh#

Builds the path follower of the Purdue lab, polaris_qgis_follower, in the overlay ROS/lab_ws. The script copies the package and does not change its source. The overlay is not in the repository.

  • Environment: ros2 with the workspace built.
  • Input: the package folder. The default is in $POLARIS_EXTRACT/refs/pc/ros2_ws/src.
  • Output: ROS/lab_ws/install and the checksum file ROS/lab_ws/SOURCE_SHA256.
Name Type Unit Default Description
src_dir path the folder in $POLARIS_EXTRACT The folder of the package polaris_qgis_follower.
source ROS/Env/setup_env.sh
ROS/Tools/build_lab_follower.sh
source ROS/lab_ws/install/local_setup.bash

check_msg_defs.py#

Examines whether the messages of a bag agree with a set of .msg definitions, byte by byte. The script decodes each message with the definitions and encodes it again.

  • Environment: Python with the package rosbags. ROS 2 is not necessary.
  • Input: one or more bags, as folders or .db3 files.
  • Output: the result on the terminal. The exit code is 0 when each message agrees.
Name Type Unit Default Description
bags path Necessary. One or more bags.
--msgs path Necessary. One or more folders of message packages.
--limit integer all The number of messages for each topic.
--quiet flag off Prints only the verdict.
python ROS/Tools/check_msg_defs.py /tmp/bag \
    --msgs ROS/vendor/ds_dbw_msgs --limit 1000

check_topic_parity.py#

Compares the topics of a simulator bag with the topics of a bag of the real vehicle. For each common topic the message type, the quality of service and the frame ids must agree.

  • Environment: Python with the package rosbags.
  • Input: one or more simulator bags and one or more vehicle bags.
  • Output: the differences on the terminal. The exit code is 0 when each common topic agrees.
Name Type Unit Default Description
--sim path Necessary. One or more bags of the ROS 2 bridge.
--vehicle path Necessary. One or more bags of the real vehicle.
--json path Writes the result into this file.

See also Topics.

python ROS/Tools/check_topic_parity.py \
    --sim /tmp/sim-bag --vehicle /tmp/vehicle-bag \
    --json /tmp/parity.json

export_polaris_meshes.py#

Exports the Polaris model as visual meshes for RViz, one STL file for each colour group, and a URDF macro.

  • Environment: Blender.
  • Input: Acres/Raw/farm-equipment/polaris/graphite/polaris_graphite.blend. The argument after -- is the package folder.
  • Output: <pkg>/meshes/polaris/<group>.stl and <pkg>/urdf/polaris_visual.xacro.
blender -b \
    Acres/Raw/farm-equipment/polaris/graphite/polaris_graphite.blend \
    --python ROS/Tools/export_polaris_meshes.py \
    -- ROS/acres_description

Calibration Tools#

These scripts compare the simulator with recorded data of the farm and of the real Polaris. Most of them need local data that is not in the repository: see the variables in Environments. The tutorial is Calibrate against Real Logs. The environment is torchenv unless a row gives a different one.

Map Checks#

The scripts in Calibration/Map measure the map of the game against the survey data and the RTK drives.

Script Function
validate_lanes.py Examines the lane layer against RTK drives, the LiDAR and the images. Writes lanes_validation.json.
validate_game_layer.py Examines the ground layer with the same lookup rule as the game. Writes game_layer_validation.json.
game_surface_check.py Compares the surface under the wheels in path replays of the game with the Python lookup.
buildings_game_check.py Compares the buildings of the level with the footprints and the LiDAR roofs.
error_budget.py Collects the differences between the real farm and the simulator. Writes error_budget.json.
Name Type Unit Default Description
--sessions path game_surface_check.py: necessary. The folder of the replay sessions.
--out path Calibration/Map/game_surface_check.json game_surface_check.py: the output file.
--level-dump path buildings_game_check.py: the actor file from dump_structures.py.

The page Map Products describes the layers.

python Calibration/Map/validate_lanes.py
python Calibration/Map/validate_game_layer.py
python Calibration/Map/buildings_game_check.py \
    --level-dump Acres/Saved/structures_level.json
python Calibration/Map/error_budget.py

Log Extraction from the Vehicle PC#

These two scripts copy a compact form of the bags from the PC of the real Polaris. run_remote_extract.sh runs on the workstation and connects to the vehicle PC. extract_on_device.py runs on the vehicle PC.

CAUTION

run_remote_extract.sh connects to the PC of the real vehicle. Use it only with the permission of the lab. Do not start it while a person uses the vehicle.

Script Function
run_remote_extract.sh Copies the extractor to the vehicle PC, starts it with a limit on memory and CPU, and downloads the result.
extract_on_device.py Reads the bags and writes the small topics, the LiDAR statistics and sampled scans and images.
Name Type Unit Default Description
probe command Examines whether the memory and CPU limit operates.
upload command Copies the extractor to the vehicle PC.
start command Starts the extractor. More arguments go to extract_on_device.py.
status command Shows the state, the progress and the end of the log.
fetch command Downloads the completed bags. --follow continues until the extractor stops.
refs command Downloads small reference files.
stop command Stops the extractor.
cleanup command Removes the work folder from the vehicle PC.
POLARIS_ENV path Environment variable. The file with the access data of the vehicle PC. It is not in the repository.
POLARIS_HOST text Environment variable. The address of the vehicle PC. No address is in the repository.
FETCH_KBPS integer kbit/s 6000 Environment variable. The limit of the download rate.
--out path extract_on_device.py: necessary. The output folder.
--roots path built-in list extract_on_device.py: the folders to search for bags.
--bags path all extract_on_device.py: only these bags.
--lidar-hz number Hz 1.0 extract_on_device.py: the sample rate of scans and frames on moving runs.
--static-hz number Hz 0.2 extract_on_device.py: the sample rate on static runs.
--jpeg-quality integer 90 extract_on_device.py: the quality of the colour frames.
--max-read-mbps number MB/s 80 extract_on_device.py: the limit of the read rate.
--budget-gb number GB 2.0 extract_on_device.py: the limit for all sampled scans and frames.
--native-scans integer 4 extract_on_device.py: the number of bags that keep the first scan in its original format.
--min-mem-gb number GB 8.0 extract_on_device.py: stops temporarily below this free memory.
--max-load number 6.0 extract_on_device.py: stops temporarily above this system load.
--min-disk-gb number GB 20.0 extract_on_device.py: stops below this free disk space.
--check-s number s 2.0 extract_on_device.py: the interval of the safety checks.
--max-pause-s number s 600 extract_on_device.py: the longest pause.

The extractor only reads the bags. It makes no ROS 2 node and publishes nothing. It stops when a person logs in or when a ROS 2 or drive-by-wire process runs. The result is in $POLARIS_EXTRACT.

Calibration/Polaris/run_remote_extract.sh probe
Calibration/Polaris/run_remote_extract.sh upload
Calibration/Polaris/run_remote_extract.sh start
Calibration/Polaris/run_remote_extract.sh status
Calibration/Polaris/run_remote_extract.sh fetch --follow
Calibration/Polaris/run_remote_extract.sh cleanup

Episodes and Replay#

These scripts read the local logs of the Polaris and make the files for a replay in the game.

Script Function
runs.py A module that finds and reads the local logs.
geo.py A module that converts between the coordinates of the logs and the coordinates of the simulator.
episodes.py Writes the vehicle state of each run at 100 Hz, and a replay file replay.csv for the game.
inventory.py Lists each run with its place and its use. Writes inventory.json and inventory.md.
replay_tracking.py Computes the path error of a path replay against the real track.
Name Type Unit Default Description
--runs text all episodes.py: the run ids.
--out path $POLARIS_EPISODES episodes.py: the output folder.
--rebuild-episodes flag off inventory.py: makes the episodes again.
--session path geo.py: examines the coordinates of a session folder of the game. In replay_tracking.py: necessary, the folder with tractor.csv.
--replay path replay_tracking.py: necessary. The replay file that the game followed.
--shift text m 0,0 replay_tracking.py: the east and north shift of the run.
--json path replay_tracking.py: writes the numbers into this file.

See also the tutorial Replay. The page Session Log gives the format of tractor.csv.

python Calibration/Polaris/episodes.py
python Calibration/Polaris/inventory.py
python Calibration/Polaris/replay_tracking.py \
    --replay /tmp/run/replay.csv \
    --session /tmp/session --json /tmp/tracking.json

Camera Calibration#

These scripts solve the mounting pose of the Polaris camera and compare real frames with frames of the simulator.

Script Function
reolink_lens.py A module with the lens model of the camera, the same model as in the simulator.
camera_extrinsic.py Solves the mounting pose from the calibration bag. Writes camera_extrinsic.json.
camera_render.py Starts the packaged game and renders the camera at each pose of a CSV file.
camera_compare.py Runs the three steps of the camera test: select, refine and evaluate.
camera_evaluate.py A module with the scores of the camera test. Writes camera_metrics.json.
segformer_eval.py Runs the segmentation model of the lab on real frames and on simulator frames.
grass_look.py Compares the colour and the texture of the mown grass. Writes grass_look.json.
camera_landmarks.py Writes the surveyed landmarks of the field-day camera check into camera_landmarks.json.
camera_mount_check.py Solves the mounting pose again from a field-day capture and reports its change.
Name Type Unit Default Description
--poses path camera_render.py: necessary. The CSV file of the poses.
--out path camera_render.py: necessary. The output folder. In camera_mount_check.py: the output folder.
--port integer 5570 camera_render.py: the port of the vehicle bridge.
--settle number s 1.5 camera_render.py: the simulated time before the frame.
--res text pixel 960x540 camera_render.py: the size of the main view.
--skip-existing flag off camera_render.py: does not render a frame that exists.
ACRES_GAME_ARGS text Environment variable. camera_render.py: more game options.
--work path $POLARIS_EPISODES/camera_sim camera_compare.py: the work folder.
--bootstrap integer 40 camera_extrinsic.py: the number of bootstrap samples.
--no-figure flag off camera_landmarks.py: writes no figure.
--draws integer 40 camera_mount_check.py: the number of Monte Carlo samples.
--record flag off camera_mount_check.py: adds the result to camera_mount_history.json.
--selftest path camera_mount_check.py: runs a test with synthetic captures.
--model path lab model segformer_eval.py: the folder of the segmentation model.
--images path labelled samples segformer_eval.py: a folder of real frames.
--compare path segformer_eval.py: a folder of simulator frames with the same file names.
--level choice refined grass_look.py: the pose level of the renders, refined or logged.
--per-frame flag off grass_look.py: keeps the numbers of each frame in the JSON file.

The page Camera gives the camera model.

python Calibration/Polaris/camera_extrinsic.py
python Calibration/Polaris/camera_compare.py select
python Calibration/Polaris/camera_render.py \
    --poses /tmp/poses_grid.csv --out /tmp/renders
python Calibration/Polaris/camera_compare.py refine
python Calibration/Polaris/camera_compare.py evaluate
python Calibration/Polaris/camera_mount_check.py \
    ~/fieldday/2026-10-02 --record

LiDAR Calibration#

These scripts measure the recorded LiDAR scans, fit the LiDAR model and compare it with the simulator.

Script Function
lidar_stats.py Computes the statistics of the recorded scans. The steps are label, tables, stats and export.
lidar_report.py A module with the statistics, the comparison metrics and the figures.
lidar_model.py A Python copy of the LiDAR radiometry. The step fit writes lidar_model_fit.json.
lidar_sim.py Renders the simulated LiDAR at the poses of the recorded scans. It starts the packaged game.
Calibration/Polaris/lidar_compare.py A module that compares the real and the simulated statistics. lidar_sim.py compare starts it.
Name Type Unit Default Description
step choice lidar_sim.py: necessary. select, headings, pick, render, tables or compare.
--work path $POLARIS_LIDAR_WORK lidar_sim.py, lidar_stats.py: the work folder.
--poses text poses_final.csv lidar_sim.py: the pose file in the work folder.
--label text before lidar_sim.py: the label of the renders.
--overlay path lidar_sim.py: the sensor configuration file of the Polaris for the render.
--port integer 5571 lidar_sim.py: the port of the vehicle bridge.
--only text all lidar_sim.py: renders only the runs with this text in the id.

The page LiDAR gives the model. Tools/LidarModel/build.sh examines the C++ code against the fit.

python Calibration/Polaris/lidar_stats.py tables
python Calibration/Polaris/lidar_stats.py stats
python Calibration/Polaris/lidar_model.py fit
python Calibration/Polaris/lidar_sim.py select
python Calibration/Polaris/lidar_sim.py render --label after
python Calibration/Polaris/lidar_sim.py tables --label after
python Calibration/Polaris/lidar_sim.py compare

Closed-Loop Test#

These scripts drive the simulated Polaris with the path follower of the lab on the routes of real runs.

Script Function
follower_logs.py Makes the real closed-loop runs from the ROS 2 logs of the follower.
closed_loop_sim.py Runs the test in four steps: configs, session, extract and analyze.
closed_loop_analysis.py A module with the metrics and the figures. The step analyze starts it.
pp_kinematic.py A kinematic reference of the follower on its real routes. It has no arguments.
Name Type Unit Default Description
--vehicle choice session: necessary. The vehicle hypothesis: H1, H2 or H3.
--only text all session: the names of the run configurations.
--redo flag off session, extract: makes results again that exist.
--core flag off session: uses ACRES Core in place of the game.
--core-rate number 1.0 session: the speed of ACRES Core. 1 is real time.
--capture path session: records a video of the game into this file.
--capture-seconds integer s 480 session: the length of the video.
--drive-script path session: a camera script for the video.
--res integer pixel 1920 1080 session: the width and the height of the game view.
--no-hud flag off session: hides the HUD.
--bag path extract: one bag folder in place of all bags.
--out path extract: the output file, with --bag. In follower_logs.py: the output folder.
--logs path local logs follower_logs.py: the folder of the follower logs.
--gap number s 30 follower_logs.py: the longest stop in one run.
--min-progress number m 5 follower_logs.py: the minimum progress of a run along the route.
--no-taught flag off follower_logs.py: does not compare the routes with the taught paths.

The steps session and extract need the ros2 environment and the overlay from build_lab_follower.sh. The step session uses the ports 5601 and 5556. The results are in $POLARIS_FOLLOWER/sim. follower_logs.py also accepts --loader-logs, --route-roots and --bag.

python Calibration/Polaris/closed_loop_sim.py configs
source ROS/Env/setup_env.sh
source ROS/lab_ws/install/local_setup.bash
python Calibration/Polaris/closed_loop_sim.py session \
    --vehicle H1
python Calibration/Polaris/closed_loop_sim.py extract
python Calibration/Polaris/closed_loop_sim.py analyze

Field-Day Kit#

The numbered scripts in Calibration/Polaris/FieldDay run on the PC of the real Polaris, in this sequence. All outputs go into the folder ~/fieldday/<date>. The tutorial is Field-Day Kit.

WARNING

05_dbw_tests.py --live sends drive-by-wire commands to the real Polaris. The vehicle can move. Use it only on the closed ICSC lot. Read the section "Safety" of Calibration/Polaris/FieldDay/README.md first.

WARNING

10_policy_run.py --drive sends steering and speed commands to the real Polaris. A safety driver must sit in the vehicle and must be ready to take control at all times.

Script Function
00_check.sh Examines the vehicle PC before the day: ROS 2, disk space, topics, clock and recorders. It sends nothing.
01_wait_rtk.py Waits until the INS has an RTK fix that stays stable for 30 s.
02_measurements.py Asks for the tape measurements and writes measurements.json.
03_record_start.sh Starts the two bag recorders in the background.
04_runs.py Guides the manual test drives and writes runs.csv with the markers of each run.
05_dbw_tests.py Optional. Tests the drive-by-wire actuators. The default is a dry run that publishes nothing.
06_soil.py Asks for the soil measurements at each test site and writes soil.csv.
07_camera_check.py Records still images at two marked positions for the check of the camera pose.
08_summary.py Writes the report of the day, summary.md.
09_record_stop.sh Stops the recorders and writes the information of each bag.
10_policy_run.py Runs the scouting driver. The default mode only listens. See Deployment.
fieldday_common.py A module with the common functions of the kit.
Name Type Unit Default Description
--replay-ok flag off 00_check.sh: accepts old time stamps. For tests with replayed bags only.
--hold number s 30 01_wait_rtk.py: the time that all criteria must hold.
--sigma-cm number cm 3 01_wait_rtk.py: the maximum horizontal sigma.
--height number m 179 187 01_wait_rtk.py: the permitted range of the height.
--max-tilt number deg 5 01_wait_rtk.py: the maximum roll and pitch at rest.
--timeout-min number min 25 01_wait_rtk.py: the time limit.
--no-attitude flag off 01_wait_rtk.py: does not examine the attitude at rest.
--sections text all 02_measurements.py: the section numbers.
--oxts-config path 02_measurements.py: INS configuration files to copy.
--no-snapshot flag off 02_measurements.py: does not copy the transforms and the configuration files.
--no-sensors flag off 03_record_start.sh: records only the control bag.
--surface choice 04_runs.py: starts with the cards of one surface.
--live flag off 05_dbw_tests.py: sends the commands.
--dry-run flag on 05_dbw_tests.py: prints the commands and sends nothing. This is the default.
--tests text steer,ulc,rolling,brake 05_dbw_tests.py: the tests. throttle is optional.
--swa-max number deg 180 05_dbw_tests.py: the largest step of the steering wheel angle.
--ulc-max number m/s 3 05_dbw_tests.py: the largest speed of the ULC.
--ulc-hold number s 5 05_dbw_tests.py: the time of each speed step.
--wait-s number s 180 05_dbw_tests.py: the maximum wait for the conditions of a test.
--clear flag off 05_dbw_tests.py: sets clear on the first command of each test.
--no-gps flag off 06_soil.py: does not read the position from the INS.
--seconds number s 10 07_camera_check.py: the length of a capture.
--stance choice 07_camera_check.py: starts at this stance.
--target flag off 07_camera_check.py: starts at the optional board captures.
--no-lidar flag off 07_camera_check.py, 10_policy_run.py: does not use the LiDAR.
--date text today 08_summary.py: the date of the session.
--no-stop flag off 08_summary.py: does not offer to stop the recorders.
--mission text F53 10_policy_run.py: a field, a list of fields, home or goto:F53.
--driver text ppo 10_policy_run.py: ppo or reference.
--policy path bundled policy 10_policy_run.py: the policy file.
--drive flag off 10_policy_run.py: sends the commands.
--speed-cap number m/s 2.0 10_policy_run.py: the maximum speed. The limit is 4.0.
--stop-on text 10_policy_run.py: the checks that stop the run.
--off-path-m number m 3.0 10_policy_run.py: the distance of the path warning.
--max-run-s number s 0 10_policy_run.py: the time of the time warning. 0 is no limit.
--datum choice nad83_2011 10_policy_run.py: the datum of the odometry.
--check flag off 10_policy_run.py: examines the dependencies and stops.

The two scripts do not enable the drive-by-wire and do not change the gear. The driver does these two things. The variables FIELDDAY_ROOT and FIELDDAY_DATE change the output folder for tests.

bash 00_check.sh
python3 01_wait_rtk.py
python3 02_measurements.py
bash 03_record_start.sh
python3 04_runs.py
python3 06_soil.py
python3 07_camera_check.py
python3 08_summary.py
bash 09_record_stop.sh
# A dry run. It publishes nothing.
python3 05_dbw_tests.py
# The shadow mode. It publishes nothing.
python3 10_policy_run.py --mission F53

Field-Day Kit Tests#

The scripts in Calibration/Polaris/FieldDay/Test test the kit on the workstation, inside the DDS loopback fence.

WARNING

Do not run the scripts of this folder on the vehicle PC. fake_vehicle.py publishes the report topics of the vehicle.

Script Function
fake_vehicle.py Publishes the topics of the Polaris as a substitute for the real vehicle, with fault injection.
bag_stand.sh Plays the local bags of the real Polaris in a loop. The commands are start and stop with a state folder.
sim_run.sh Runs the kit against the simulated Polaris in the packaged game.
core_run.sh Runs the kit against ACRES Core.
policy_core_run.sh Runs the scouting driver against ACRES Core for a list of cases.
policy_game_run.sh Runs the scouting driver against the packaged game and records a video.
test_dbw_safety.py Tests the safety stops of 05_dbw_tests.py against fake_vehicle.py.
test_policy_run.py Tests 10_policy_run.py against fake_vehicle.py, on ROS domain 78.
test_camera_check.py Tests 07_camera_check.py against fake_vehicle.py, on ROS domain 79.
test_camera_solver.py Tests camera_mount_check.py with synthetic captures. It needs torchenv and no ROS 2.
Name Type Unit Default Description
work dir path The four *_run.sh scripts: necessary. The first argument, the output folder.
capture seconds integer s 900 sim_run.sh: the second argument. The length of the video.
case text all policy_core_run.sh and the three test_*.py scripts for ROS 2: the cases to run.
--sim integer test_dbw_safety.py: the process id of the ROS 2 bridge. The test then uses the simulated Polaris.
--work path test_camera_check.py, test_camera_solver.py: the work folder.
mission text F53 policy_game_run.sh: the second argument.
driver text reference policy_game_run.sh: the third argument.
capture seconds integer s 300 policy_game_run.sh: the fourth argument. The length of the video.
max run seconds integer s 0 policy_game_run.sh: the fifth argument. 0 runs the full mission.
--fix, --odom, --dbw, --camera, --lidar flag off fake_vehicle.py: the topic groups to publish.
--fix-schedule text built-in schedule fake_vehicle.py: the fix status and the sigma against time.
--park text ICSC garage apron fake_vehicle.py: the parked pose as UTM east, north and heading.
--wobble number m 0 fake_vehicle.py: moves the parked pose by this distance.
--gear integer 5 fake_vehicle.py: the reported gear. 5 is L.
--start-enabled flag off fake_vehicle.py: starts with the drive-by-wire enabled.
--image path grey gradient fake_vehicle.py: the picture for --camera.

The environment is ros2 after source ROS/Env/setup_env.sh. sim_run.sh and policy_game_run.sh also need the packaged game. core_run.sh and policy_core_run.sh use the default ports of the game. Close the game before you start them.

source ROS/Env/setup_env.sh
python3 Calibration/Polaris/FieldDay/Test/test_dbw_safety.py
python3 Calibration/Polaris/FieldDay/Test/test_policy_run.py
python3 Calibration/Polaris/FieldDay/Test/test_camera_check.py
source ROS/Env/setup_env.sh
Calibration/Polaris/FieldDay/Test/core_run.sh /tmp/kit-core
Calibration/Polaris/FieldDay/Test/sim_run.sh /tmp/kit-game
conda run -n torchenv python \
    Calibration/Polaris/FieldDay/Test/test_camera_solver.py

Tractor Study#

Calibration/Tractor/soil_weather_analysis.py makes the tables and the figures of the soil and weather study of the Maxxum. It reads the session logs that Demo/soil_weather.sh records.

  • Environment: torchenv. The program bench_pull is optional.
  • Input: <runs>/<scenario>/tractor.csv of each session.
  • Output: soil_weather_results.json, the figures Figures/soil_weather_*.png and Markdown tables on the terminal.
Name Type Unit Default Description
runs path Necessary. The folder of the sessions.
--bench path The folder of the drawbar data from demo_data.

See also the tutorial Set Soil and Weather.

Demo/soil_weather.sh /tmp/soil_weather
python Calibration/Tractor/soil_weather_analysis.py \
    /tmp/soil_weather

Weather and Ground Conditions#

The scripts in Calibration/Weather download the weather record of the ACRE station and find the conditions of each real run.

Script Function
acre_mesonet.py Downloads the 30-minute weather and soil record of the station and makes a clean table.
ground_conditions.py Finds the weather and the soil water of each real Polaris run. Writes the weather replay files.
soil_state_cli.cpp A small program that computes the soil strength with the soil library of the game. ground_conditions.py compiles and starts it.
Name Type Unit Default Description
cmd choice all acre_mesonet.py: fetch downloads, build makes the table, all does the two steps.
--start text 2023-01 acre_mesonet.py: the first month.
--end text 2026-09 acre_mesonet.py: the last month.
--refresh flag off acre_mesonet.py: downloads each month again.
--no-asos flag off acre_mesonet.py: does not download the airport record for the cross-check.
--nonreal-followers flag off ground_conditions.py: also lists the follower runs without progress.

The record is in $ACRE_WEATHER. The outputs are ground_conditions.md, ground_conditions.json and Replay/env_<date>.json. The game reads a replay file with the option -EnvConfig=. The pages Weather and Soil Water give the models.

python Calibration/Weather/acre_mesonet.py
python Calibration/Weather/ground_conditions.py
Packaged/Linux/Acres.sh -VehicleDemo \
    -EnvConfig=$PWD/Calibration/Weather/Replay/env_2026-06-18.json

Demonstration Scripts#

The scripts in Demo start scripted sessions of the packaged game. Each shell script refuses to start when a game runs. The outputs go into Demo/videos. This folder is local and is not in the repository.

Data Function
Demo/Menu The menu scripts normal.json, rain.json and harvest.json for the option -MenuDemo=.
Demo/Multi The drive scripts, the sensor file and the path of the demonstration with two vehicles.
Demo/SoilWeather The drive scripts and the field setups of the soil and weather study.
Demo/harvest_path.csv The path replay file of the harvest video.

gameplay.sh and record_all.sh#

gameplay.sh records one video. The game operates its own menu, starts the session and records its window. record_all.sh records the four videos normal, rain, harvest and cab. It has no arguments.

  • Environment: the packaged game and ffmpeg with an H.264 or MPEG-4 encoder. A desktop is not necessary.
  • Input: Demo/Menu/<menu>.json.
  • Output: Demo/videos/<name>.mp4 and Demo/videos/logs/<name>-game.log.
Name Type Unit Default Description
name text gameplay.sh: necessary. The name of the video.
menu text gameplay.sh: necessary. The name of the menu script.
seconds integer s gameplay.sh: necessary. The length of the video.
game args text gameplay.sh: more game options.
Demo/gameplay.sh normal normal 75 -VehicleRoute=5 -NpcTraffic=24
Demo/record_all.sh

multi_agent_demo.sh#

Runs one session with two vehicles. The Maxxum works field F29 with the chisel plow. The Polaris follows the lanes at the edge of the field with drive-by-wire commands on its own vehicle bridge.

  • Environment: the packaged game and Python with the learning package in Learning. The ports are 5555 and 5556.
  • Input: the files in Demo/Multi.
  • Output: agents.json, game.log, client.log, polaris-dbw-reports.csv and the session folder session.
Name Type Unit Default Description
out dir path Demo/videos/multi The output folder.
VIDEO flag off Environment variable. The value 1 also records session.mp4.
PYTHON path python3 Environment variable. The interpreter of the Polaris client.

See also the tutorial Run Several Vehicles.

Demo/multi_agent_demo.sh /tmp/multi
VIDEO=1 Demo/multi_agent_demo.sh /tmp/multi

soil_weather.sh#

Runs the soil and weather study. The Maxxum makes the same pass on field F21 in 12 sessions with different soil and weather. Each session has its own drive script, and the script stops the session at the end.

  • Environment: the packaged game.
  • Input: Demo/SoilWeather and the weather replay files in Calibration/Weather/Replay.
  • Output: <out>/<session>/tractor.csv and <out>/<session>-game.log for each session.
Name Type Unit Default Description
out dir path Demo/videos/soil_weather The output folder.
SESSIONS text all Environment variable. The sessions to run, for example dry wet.

The sessions are dry, wet, saturated, loamy-sand, sand and rain with the chisel plow. The sessions transport-* have no implement. The sessions harrow-* use the disc harrow. See also the tutorial Set Soil and Weather.

Demo/soil_weather.sh /tmp/soil_weather
SESSIONS="dry wet" Demo/soil_weather.sh /tmp/soil_weather

lockstep_drive.py#

A ROS 2 client that drives the simulated Polaris in lockstep and records an episode log. Each 0.1 s of simulated time it publishes the drive-by-wire commands and requests 12 physics steps.

  • Environment: ros2 with the workspace built, a game with -SimControl= and -Lockstep, and the ROS 2 bridge.
  • Input: none.
  • Output: the episode log, and the progress on the terminal.
Name Type Unit Default Description
--log path Necessary. The file of the episode log.
--seconds number s 40 The simulated time.

See also the tutorial Lockstep Stepping.

Packaged/Linux/Acres.sh -VehicleDemo -Vehicle=polaris \
    -SensorStream=5601 -RlPort=5556 \
    -SimControl=5600 -Lockstep
source ROS/Env/setup_env.sh
ros2 launch acres_sim sim_bridge.launch.py
source ROS/Env/setup_env.sh
python Demo/lockstep_drive.py --log /tmp/episode.mcap

Documentation Tools#

The page Write Documentation gives the rules and the build procedure of this site. The environment is the conda environment acres-docs from Documentation/environment.yml.

gen_api.py#

Generates the reference pages from the source code: the C++ headers, the messages, the menu settings and the option index. MkDocs starts this file on each build. Start it alone to see the Markdown files.

  • Input: the headers of the game, of ACRES Core and of the ROS 2 packages, the message files and AcresSession.cpp.
  • Output: the Markdown files in the output folder.
Name Type Unit Default Description
--out path build/api-preview The output folder.
python Documentation/Tools/gen_api.py --out build/api-preview

hooks.py#

The MkDocs hooks of the site. This file has no command line.

Function Description
on_config Adds the generated header pages to the navigation.
on_page_content Puts each SVG diagram into the page, thus the diagram follows the theme.
# mkdocs.yml
hooks:
  - Documentation/Tools/hooks.py

ste_check.py#

Examines the text of the pages for the language rules. The exit code is 1 when a file has an error.

  • Input: the files of the arguments. Without arguments, all pages that persons wrote and README.md.
  • Output: each error as file:line on the terminal.
Name Type Unit Default Description
files path all pages The files to examine.
--warnings flag off Also prints possible passive voice and tenses that the rules do not approve.
python Documentation/Tools/ste_check.py
python Documentation/Tools/ste_check.py --warnings \
    Documentation/Reference/tools.md
ste_check: 1 files, 0 errors, 0 warnings

titlecase.py#

Writes the headings, the table headers and the link text of page titles in title case. It changes all Markdown files in Documentation and the navigation titles in mkdocs.yml.

  • Input: none.
  • Output: the changed files, and the list of them on the terminal.
Name Type Unit Default Description
--check flag off The exit code is 1 when the tool changed a file. The tool also writes the files in this mode.
python Documentation/Tools/titlecase.py

check_docs.py#

Examines the diagrams, the links, the coverage of the reference pages and the asset files. Without options it does all checks. The exit code is 1 when a check finds an error.

  • Input: the built site and the files in Documentation.
  • Output: each error on the terminal.
Name Type Unit Default Description
--site path site The folder of the built site.
--diagrams flag off Examines only the diagram rules.
--links flag off Examines only the links, the images and the anchors of the built site.
--coverage flag off Examines only the coverage of the options, the ROS 2 interfaces and the Python names.
--assets flag off Examines only that a page uses each asset file.
--external flag off Also requests each external link.
--sync-diagrams flag off Copies the common style block into each SVG file. Does no check.
mkdocs build --strict
python Documentation/Tools/check_docs.py
python Documentation/Tools/check_docs.py --diagrams