Source of truth
This guide is maintained in the PacketFive/TORUS repository under
torus-isaac-sim/docs/ and is published here verbatim from
torus-isaac-sim.
TORUS simulation user and developer guide¶
This guide covers installation, configuration, execution, scene generation, website capture, troubleshooting, and extension of the TORUS deployment simulation stack.
TORUS provides two related runtimes:
- The portable planner runs with standard Python and does not require a GPU. It computes actor tracks, material attenuation, TORUS-SN-to-MEG RF link budgets, multi-modal detections, geofence transitions, and alarms.
- The Isaac Sim campus twin runs on an NVIDIA RTX GPU. It converts the same scenario into layered OpenUSD, opens the animated timeline, and produces RTX-rendered stills.
The portable planner is the source of planning events. Isaac Sim is the 3D visualization, animation, physics integration, and synthetic-data environment. Running the OpenUSD generator does not replace the planning model with PhysX.
1. Repository layout¶
Run commands from TORUS/torus-isaac-sim unless a command says otherwise.
torus-isaac-sim/
├── bin/torus-sim Unified launcher
├── run_sim.py Portable planner CLI
├── torus_sim/ Planner implementation
├── scenarios/ Example JSON scenarios
├── docs/
│ ├── USER_DEVELOPER_GUIDE.md This guide
│ ├── PARAMETERS.md Complete scenario parameter reference
│ └── BUILD_DEPLOY_USE.md Deployment-oriented summary
├── isaac/
│ ├── torus_isaac_scene.py Layered OpenUSD generator and GUI launcher
│ ├── capture_website.py Branded RTX screenshot generator
│ └── generated/campus/ Default generated stage
├── container/ Isaac Sim container image and entrypoint
├── compose.yaml GPU container service
├── tests/ Portable planner tests
└── output/ User-generated plans, events, and stages
Generated OpenUSD files are reproducible outputs. Do not make permanent edits
under isaac/generated/ or output/campus/; change the scenario, generator,
or replacement USD assets and regenerate the stage.
2. Choose a runtime¶
| Task | Portable planner | Isaac Sim |
|---|---|---|
| Edit and validate scenarios | Yes | Uses validated scenario |
| Compare node placement and RF margins | Yes | Visualizes results |
| Generate SVG deployment plan | Yes | No |
| Generate JSON events and detections | Yes | Embeds result in USD |
| Run on CPU-only server | Yes | No |
| View animated campus | No | Yes |
| RTX rendering and website screenshots | No | Yes |
| Add cameras, LiDAR, Replicator, or physics | No | Yes |
| CI regression tests | Yes | Normally not required |
Start with the portable planner. Move a scenario to Isaac Sim only after its coordinates, timing, link margins, and alarm behavior are plausible.
3. System requirements¶
3.1 Portable planner¶
- Python 3.8 or newer.
- Linux, macOS, or Windows.
- No third-party Python packages.
- No GPU.
3.2 Isaac Sim practical baseline¶
The official NVIDIA compatibility checker is the authority for a particular Isaac Sim release and driver combination. For the current TORUS procedural campus, use this practical baseline:
| Component | TORUS guidance |
|---|---|
| Operating system | Linux x86-64 is the primary TORUS workstation, server, and container platform |
| GPU | NVIDIA RTX-capable GPU with RT Cores |
| Unsupported GPU class | Data-center GPUs without RT Cores, including A100 and H100, are not supported by Isaac Sim |
| VRAM | 10 GB practical floor for the procedural campus; 16 GB or more recommended for path tracing, detailed assets, or many sensors |
| Host memory | 32 GB recommended; 64 GB for large asset libraries or synthetic-data workloads |
| CPU | Modern x86-64 processor; 8 or more cores recommended |
| Storage | Allow at least 50 GB for Isaac Sim, shader caches, TORUS, generated USD, and captures |
| Driver | NVIDIA production driver compatible with the selected Isaac Sim release |
| Network | Required for downloads and for extensions or assets that are not local |
| Display | Required for local GUI; not required for headless generation or capture |
Run nvidia-smi before installing Isaac Sim:
The command must show the intended GPU and a healthy driver. A GPU attached to the host is still required when no X display is available.
3.3 Supported Isaac Sim version policy¶
The TORUS scripts are currently validated with Isaac Sim 5.1. NVIDIA's archived 5.1 documentation is now marked unsupported upstream, so:
- pin 5.1 when exact reproducibility is required;
- evaluate newer Isaac Sim releases in a branch;
- rerun scene generation, single-view capture, full capture, and visual checks before declaring a newer release supported;
- do not assume standalone Python or Replicator APIs are unchanged.
Official references:
- Isaac Sim 5.1 requirements
- Isaac Sim 5.1 workstation installation
- Isaac Sim 5.1 container installation
Omniverse Launcher, Nucleus Workstation, and Nucleus Cache are no longer a required installation path. TORUS uses the standalone Isaac Sim archive or the NGC container.
4. Install TORUS¶
No package installation is required for the portable planner:
Do not install isaacsim, pxr, or Omniverse modules into the portable
planner environment. Isaac scripts must use the Python launcher supplied by
the matching Isaac Sim installation.
5. Install Isaac Sim on a Linux workstation¶
5.1 Download and extract¶
- Download the standalone Isaac Sim release from NVIDIA.
- Create an installation directory.
- Extract the archive.
- Run the post-install script.
Example:
sudo mkdir -p /opt/isaacsim
sudo chown "$USER":"$USER" /opt/isaacsim
unzip ~/Downloads/<isaac-sim-archive>.zip -d /opt/isaacsim
cd /opt/isaacsim
./post_install.sh
If Isaac Sim is installed elsewhere, set:
The TORUS launcher defaults to /opt/isaacsim/python.sh.
5.2 Run the compatibility checker¶
Resolve red or unsupported results before running TORUS. The checker evaluates the GPU, driver, VRAM, CPU, RAM, storage, operating system, and display.
5.3 Accept the EULA and start Isaac Sim¶
Choose the full Isaac Sim application. The first launch can take several minutes while shaders and extensions initialize. Subsequent launches are faster if the cache is retained.
For a direct launch:
Useful NVIDIA recovery commands are:
Use them only for configuration or cache corruption; clearing caches causes the next launch to rebuild shaders.
5.4 Verify the bundled Python runtime¶
Always use this launcher for:
isaac/torus_isaac_scene.py;isaac/capture_website.py;- code importing
isaacsim,omni, orpxr.
6. Install Isaac Sim for a headless GPU server¶
A display server is not required for TORUS generation and website capture. The machine still needs a supported RTX GPU and driver.
export ISAAC_SIM_ROOT=/opt/isaacsim
export ISAAC_PYTHON="$ISAAC_SIM_ROOT/python.sh"
export OMNI_KIT_ACCEPT_EULA=yes
bin/torus-sim generate scenarios/configurable_campus_security.json \
--output output/campus
Headless generation precomputes the complete portable scenario, authors the OpenUSD animation, performs a few Kit updates, and exits. It does not wait for a four-hour or two-day scenario to elapse in real time.
7. Container installation¶
The provided container is the preferred remote deployment package. Vagrant is not used because it adds a guest operating system but still needs host-specific GPU pass-through.
7.1 Host prerequisites¶
Install and verify:
- Docker Engine with Compose support;
- NVIDIA driver;
- NVIDIA Container Toolkit;
- access to
nvcr.io.
Verify GPU pass-through:
Authenticate to NGC and pull the base image:
Use an NGC API key as the password when required by the NVIDIA account.
7.2 Build and run TORUS¶
cd TORUS/torus-isaac-sim
mkdir -p output assets
docker compose build
docker compose run --rm torus-isaac
The default command generates the configurable campus headlessly. Generated
files appear under ./output.
The Compose service mounts:
| Host | Container | Access |
|---|---|---|
./output |
/workspace/output |
Read/write |
${TORUS_ASSET_ROOT:-./assets} |
/workspace/assets |
Read-only |
Supported container commands:
docker compose run --rm torus-isaac generate
docker compose run --rm torus-isaac preview --duration 2h
docker compose run --rm torus-isaac shell
The current Compose configuration is intended for headless use. Use a native workstation install for the full GUI.
Environment variables:
| Variable | Default | Purpose |
|---|---|---|
ISAAC_SIM_IMAGE |
nvcr.io/nvidia/isaac-sim:5.1.0 |
Base image used by the build |
TORUS_SCENARIO |
Configurable campus path in the container | Scenario loaded by the entrypoint |
TORUS_OUTPUT |
/workspace/output/campus |
Generated stage directory |
TORUS_ASSET_ROOT |
./assets on host |
Licensed replacement asset directory |
ACCEPT_EULA |
Y |
NVIDIA container EULA acceptance |
OMNI_KIT_ACCEPT_EULA |
yes |
Kit EULA acceptance |
PRIVACY_CONSENT |
Y |
NVIDIA container privacy-consent setting |
8. Portable planner quick start¶
python3 run_sim.py \
--scenario scenarios/configurable_campus_security.json \
--duration 30m \
--svg output/campus-plan.svg \
--events-json output/campus-events.json
Equivalent launcher command:
bin/torus-sim preview scenarios/configurable_campus_security.json \
--duration 30m \
--svg output/campus-plan.svg \
--events-json output/campus-events.json
8.1 Unified launcher¶
bin/torus-sim preview SCENARIO [planner options]
bin/torus-sim generate SCENARIO [generator options]
bin/torus-sim gui SCENARIO [generator options]
bin/torus-sim container [docker compose options]
| Command | Runtime |
|---|---|
preview |
System Python, no GPU |
generate |
Isaac bundled Python with --headless --no-play added |
gui |
Isaac bundled Python with an interactive window |
container |
docker compose -f compose.yaml |
The launcher reads ISAAC_SIM_ROOT and ISAAC_PYTHON. Generator options after
the scenario path are passed through unchanged.
The terminal summary reports:
- scenario and duration;
- actor and node counts;
- time and output intervals;
- weakest RF link margin;
- track-point, detection, and event counts;
- first detection or first intrusion alarm.
9. Portable planner command reference¶
| Option | Default | Meaning |
|---|---|---|
--scenario PATH |
Required | Scenario JSON file |
--svg PATH |
None | Write a self-contained top-down deployment plan |
--events-json PATH |
None | Write normalized actors, RF links, detections, and events |
--duration VALUE |
Scenario/natural | Override duration with seconds or s, m, h, d suffix |
--set PATH=VALUE |
None | Override a top-level field or nested dictionary field; repeatable |
--list-profiles |
False | List built-in actor and material profiles |
--max-event-lines N |
50 |
Limit detection lines printed to the terminal |
--set parses the value as JSON when possible:
python3 run_sim.py \
--scenario scenarios/configurable_campus_security.json \
--set rf.path_loss_exponent=2.8 \
--set thermal.enabled=false \
--set scene.weather='"rain"' \
--events-json output/variant.json
Current overrides support top-level fields and nested dictionaries. They do
not address list elements such as actors.0.speed_mps; edit or generate a
scenario file for list changes.
10. Scenario authoring workflow¶
- Copy the closest scenario:
- Set the site extent and campus dimensions.
- Enter the MEG and SN coordinates.
- Confirm that devices are not inside buildings, roads, water, or inaccessible service areas.
- Add attenuation objects for the actual line-of-sight paths.
- Define protected and monitored geofences.
- Add actors with start times, routes, speeds, behavior, and threat status.
- Select detection modalities and thresholds.
- Run the portable planner and inspect RF margins, events, and SVG.
- Create environmental and tolerance variants instead of relying on one optimistic scenario.
- Generate the OpenUSD campus and inspect important event timestamps.
All coordinates and dimensions are metres. Times are seconds unless a compact
duration such as 5m, 4h, or 2d is used.
See PARAMETERS.md for every supported field, default, profile, material coefficient, and output record.
10.1 Bundled scenarios¶
| File | Purpose |
|---|---|
configurable_campus_security.json |
Four-hour multi-domain campus with people, animals, truck, drone, UAV, balloon, and aircraft |
long_duration_patrol.json |
Two-day patrol and scheduled intrusion study |
data_center_campus.json |
Basic landscaped campus using the legacy single-actor schema |
human_intrusion.json |
Footfall intrusion example |
vehicle_approach.json |
Strong ground-coupled vehicle example |
drone_overflight.json |
Acoustic and RF small-UAS example |
wildlife_transit.json |
Benign animal classification example |
urban_block.json |
Higher-noise urban environment |
rural_perimeter.json |
Lower-noise rural deployment |
11. Choosing time resolution¶
simulation.time_step_s controls detection and geofence evaluation.
simulation.output_interval_s controls stored report tracks. Isaac animation
uses the unthinned evaluation track, so increasing the output interval reduces
stored planner and SVG track density without skipping animation samples.
| Scenario | Suggested time_step_s |
Suggested output_interval_s |
|---|---|---|
| Walking intrusion | 0.5-2 s | 2-10 s |
| Vehicle approach | 0.2-1 s | 1-5 s |
| Drone/UAV | 0.1-0.5 s | 0.5-2 s |
| Multi-hour mixed domain | 1-5 s | 10-60 s |
| Day-scale patrol | 10-30 s | 60-300 s |
The step must be small enough that the fastest actor cannot cross an important zone or detection footprint between evaluations.
12. Generate the OpenUSD campus¶
12.1 Headless generation¶
export ISAAC_SIM_ROOT=/opt/isaacsim
export OMNI_KIT_ACCEPT_EULA=yes
bin/torus-sim generate scenarios/configurable_campus_security.json \
--output output/campus \
--renderer RaytracedLighting
The root stage is:
12.2 Direct generator command¶
"$ISAAC_SIM_ROOT/python.sh" isaac/torus_isaac_scene.py \
--scenario scenarios/configurable_campus_security.json \
--output output/campus \
--headless \
--no-play
Generator options:
| Option | Default | Meaning |
|---|---|---|
--scenario PATH |
scenarios/data_center_campus.json |
Portable scenario used for nodes, actors, routes, and detections |
--output DIRECTORY |
isaac/generated/campus |
Destination for all generated USD layers |
--asset-root DIRECTORY |
None | Licensed replacement USD assets |
--headless |
False | Run without a GUI window |
--renderer RaytracedLighting |
Selected | Interactive/default renderer |
--renderer PathTracing |
Not selected | Higher-quality renderer for final stills |
--no-play |
False | Open stage without starting timeline playback |
Use RaytracedLighting for authoring and routine capture. Use path tracing only
after the scene fits comfortably in VRAM:
13. Generated OpenUSD layers¶
| File | Contents |
|---|---|
terrain.usda |
Ground, habitat zones, roads, and access surfaces |
facilities.usda |
Data halls, operations building, substation, and generators |
landscape.usda |
Trees, berms, and retention lakes |
security.usda |
Fence, gate, lighting, and perimeter infrastructure |
torus.usda |
TORUS-SN, MEG, SN-TIR, RF rings, links, and planning geometry |
scenario.usda |
Time-sampled actors, routes, detections, and thermal frustums |
torus-campus.usda |
Root stage that composes the other layers |
Open the root stage, not an individual layer, unless debugging that layer. In
Isaac Sim use File > Open and select
output/campus/torus-campus.usda. The bin/torus-sim gui command regenerates
and opens the correct root stage automatically.
14. Run and inspect the GUI simulation¶
bin/torus-sim gui scenarios/configurable_campus_security.json \
--output output/campus \
--renderer RaytracedLighting
The script:
- runs the complete portable scenario;
- regenerates every OpenUSD layer;
- opens the root stage;
- sets the timeline start to zero and end to the scenario duration;
- starts looping playback unless
--no-playis supplied.
For long scenarios, use the timeline to jump to the event time rather than waiting in real time. Important configurable-campus times include:
| Event | Approximate scenario time |
|---|---|
| Ground intruder starts | 300 s |
| Authorized worker starts | 600 s |
| Security dog starts | 1200 s |
| Delivery truck starts | 2100 s |
| Hostile drone starts | 3600 s |
| Authorized survey UAV starts | 5400 s |
| Balloon starts | 7200 s |
| Civil aircraft starts | 10800 s |
Recommended GUI review:
- Confirm the MEG and all SN/SN-TIR devices are above terrain and outside obstacles.
- Check actor routes against roads, water, fences, and buildings.
- Inspect the first degraded RF link and first intrusion alarm.
- Toggle RF and thermal planning geometry when it obscures device inspection.
- Confirm replacement assets use correct scale and pivots.
- Save experiments to a separate USD layer; do not overwrite generated source layers as the only copy of a change.
15. Generate branded website screenshots¶
First generate the configurable campus at the default stage location:
"$ISAAC_SIM_ROOT/python.sh" isaac/torus_isaac_scene.py \
--scenario scenarios/configurable_campus_security.json \
--headless \
--no-play
Generate the complete gallery:
The full command launches one isolated Isaac process per view for reliable
Replicator cleanup. It writes 1920x1080 PNG files to
../site/images/isaac-campus/ and adds the canonical TORUS corner symbol.
Capture one view while tuning:
Capture options:
| Option | Default | Meaning |
|---|---|---|
--stage PATH |
isaac/generated/campus/torus-campus.usda |
Root stage to render |
--output DIRECTORY |
site/images/isaac-campus |
PNG destination |
--brand-symbol PATH |
Canonical TORUS ring PNG | Corner mark |
--width PIXELS |
1920 |
Output width |
--height PIXELS |
1080 |
Output height |
--subframes N |
16 |
RTX accumulation subframes |
--view NAME |
All views | One view or a short comma-separated batch; isolated single-view runs are most reliable |
Available view names:
campus-aerial-southeast
campus-aerial-northwest
campus-main-gate
campus-data-halls
campus-west-retention-lake
campus-east-retention-lake
campus-torus-perimeter
torus-wireless-sensor-zone
torus-sn-ground-node
torus-meg-gateway
torus-visual-mast
torus-rf-field-overview
torus-thermal-camera-feed
torus-intrusion-correlation
torus-vehicle-gate-approach
torus-drone-overwatch
torus-meg-service-zone
torus-multi-domain-overview
The capture tool temporarily enlarges selected devices or actors in some marketing views. Captions identify planning visualizations; the apparent size in such a still is not a deployment dimension.
16. Licensed replacement assets¶
Pass a directory containing any of these files:
Example:
bin/torus-sim generate scenarios/my-site.json \
--asset-root /srv/torus-assets \
--output output/my-site
Missing files fall back to repository-owned procedural geometry.
Replacement asset requirements:
- metres per unit;
- Z-up;
- useful pivot at the placement point;
- local geometry near the origin;
- correct normals and simulation-ready materials;
- no unresolved external textures;
- license suitable for the intended distribution;
- proxy or purpose geometry for high-detail assets;
- instanceable tree assets where possible.
17. Output interpretation¶
The planner JSON includes:
- normalized actor configuration;
- TORUS-SN-to-MEG RF links;
- detections;
- events.
Important event types:
| Event | Meaning |
|---|---|
rf_link_degraded |
Node link margin is below minimum_link_margin_db |
geofence_enter |
Actor entered a circle or polygon |
geofence_exit |
Actor exited a circle or polygon |
sensor_detection |
A node or thermal mast passed the configured decision rule |
intrusion_alarm |
A threat actor was detected inside a protected geofence |
An alarm is correlated independently of terminal detection-line suppression.
first_detection_per_node and detection_cooldown_s control repeated
detection records, not whether a protected-zone alarm can be raised.
18. Developer guide¶
18.1 Planner code map¶
| File | Responsibility |
|---|---|
torus_sim/config.py |
Schema defaults, actor/material profiles, loading, validation, overrides |
torus_sim/field.py |
Explicit or ring-based SN placement |
torus_sim/intruder.py |
Actor path length, timing, loop/hold/ping-pong motion |
torus_sim/detection.py |
Obstacle crossings, attenuation, RF budget, modality decisions |
torus_sim/engine.py |
Time loop, tracks, geofences, detections, alarms, RF warnings |
torus_sim/report_svg.py |
Self-contained branded planning SVG |
run_sim.py |
Portable CLI and JSON serialization |
18.2 Isaac code map¶
| File/function | Responsibility |
|---|---|
isaac/torus_isaac_scene.py |
Isaac app lifecycle and layer generation |
build_terrain |
Ground and road layer |
build_facilities |
Data halls and equipment |
build_landscape |
Trees, berms, and lakes |
build_security |
Fence, gate, and lighting |
build_torus |
SN, MEG, SN-TIR, RF visualization |
build_scenario |
Actors, time samples, routes, detections, thermal frustums |
build_root |
Sublayer composition and default camera |
isaac/capture_website.py |
Replicator camera definitions and branded PNG output |
18.3 Add an actor profile¶
- Add the profile and defaults to
ACTOR_PROFILESintorus_sim/config.py. - Decide whether it is ground or air domain.
- Set speed and available source terms.
- Add a procedural shape in
actor_shapeif the fallback geometry is not sufficient. - Add a scenario and unit test.
- Verify one-shot visibility end time and long-duration behavior.
Unknown actor types inherit the human planner profile and generic spherical
Isaac geometry, so spelling mistakes do not create a new validated profile.
18.4 Add a material¶
- Add
rf_loss_db,acoustic_factor,seismic_factor, andthermal_occlusiontoMATERIAL_PROFILES. - Add a color to the SVG renderer if required.
- Add representative scenarios and tests.
- Keep planning coefficients separate from Isaac visual materials.
Scenario obstacle materials affect the portable top-down propagation path. They do not automatically create new 3D meshes in the fixed campus template. Add corresponding OpenUSD generation logic when a visual obstacle is needed.
18.5 Add a scenario field¶
- Add a typed top-level dataclass field or a documented nested-dictionary field.
- Define its default and fallback behavior.
- Validate unsafe or inconsistent values.
- Use it in both the planner and Isaac generator if it affects both.
- Update
PARAMETERS.md. - Add tests for success and invalid input.
18.6 Add a website view¶
- Add the name to
ALL_VIEW_NAMES. - Add its camera and behavior to
VIEWS. - Use
time_codefor event views. - Hide planning geometry that obscures the subject.
- Use
scaleonly when the overlay or caption makes the enlargement clear. - Render the single view and inspect it.
- Run the full capture command.
- Add the PNG and caption to
site/simulation.html.
18.7 Run developer checks¶
python3 -m py_compile \
isaac/torus_isaac_scene.py \
isaac/capture_website.py
python3 -m unittest discover -s tests -q
git diff --check
For Isaac changes, also generate the configurable campus and render at least one affected view.
19. Troubleshooting¶
ModuleNotFoundError: isaacsim, omni, or pxr¶
The script was run with system Python. Use:
Isaac Sim starts but no window appears¶
- confirm the command is not using
--headless; - confirm
DISPLAYis valid for local GUI use; - run the compatibility checker;
- use native workstation installation for GUI instead of the TORUS container.
Headless run reports no GPU¶
Fix the host driver or NVIDIA Container Toolkit before changing TORUS.
First launch is slow¶
Isaac Sim is warming shader and extension caches. Retain caches and allow the first run to complete.
Out of VRAM¶
- use
RaytracedLighting; - reduce capture resolution and subframes;
- remove high-detail replacement assets;
- reduce camera, LiDAR, or Replicator products;
- capture one view per process;
- use proxy and instanceable USD assets.
Scenario validation fails¶
The most common causes are:
time_step_s <= 0;output_interval_s < time_step_s;- invalid duration text;
- malformed JSON;
- unknown
--settop-level path.
No detections¶
Check:
- actor active time and route;
- enabled modalities;
- actor source amplitudes or RF transmitter;
- noise floors and thresholds;
- node/mast distance;
- obstacle losses and density;
fusion=all, which requires every enabled modality to pass.
Too many detections¶
Set:
or increase thresholds/noise assumptions after calibration.
Replacement asset is missing¶
Confirm the exact filename. Missing replacements intentionally use procedural fallback assets.
Generated root stage opens without the full campus¶
Keep all generated layer files together and open torus-campus.usda. Relative
sublayer paths must remain valid.
20. Model and safety boundaries¶
The portable model is a deterministic planning approximation. It is not a certified RF, seismic, acoustic, thermal, hydrological, or geotechnical solver.
Before using results for deployment guarantees, calibrate with:
- site RF survey and antenna data;
- soil and vibration measurements;
- acoustic recordings and ambient distributions;
- thermal camera range and contrast tests;
- measured material and foliage losses;
- seasonal and weather variants;
- external engineering solvers where required.
PhysX and a future Newton backend can validate contact, friction, terrain traversal, installation mechanisms, mast stability, and robotics. Neither backend replaces propagation or placement analysis.
21. Recommended end-to-end deployment study¶
- Survey the site and coordinate system.
- Build pessimistic, nominal, and optimistic scenarios.
- Run the portable planner for all variants.
- Reject placements with poor RF margin or detection gaps.
- Review geofence alarms and benign actor classifications.
- Generate the OpenUSD campus for surviving candidates.
- Inspect installation access, occlusion, routes, and maintenance clearances.
- Add licensed assets and sensors only after the procedural scene is correct.
- Capture approved planning evidence.
- Validate the selected design with field trials and measured calibration.