Skip to content

Map Products#

This page gives the format of each map file that the game and ACRES Core read at the start of a session. The ACRE Scene describes the contents of the map and the frames.

The map pipeline of ACRES: the data sources go through the tools of Tools/ACRE/Map, the tools write the runtime map files in Content/Simulation/ACRE, and the game, ACRES Core, the Core scene builder and the scouting map builder read the files. DATA SOURCES TOOLS/ACRE/MAP CONTENT/SIMULATION/ACRE READERS Imagery and vectors Orthophoto 2023, NAIP 2025 County 2025: measure only LiDAR 2018, road polygons RTK drives of the Polaris Ground layer tools lanes.py, layer.py hardstanding.py, verges.py us52.py, game_layer.py site_edits.py Ground layer surface_polygons.json surfaces.u8, cover.u8 grass-lanes.u8 minimap.png Field outlines Review of the farm user Edges of the ground layer Field tools fields_recut.py field_edits.py Fields fields.json, field_ids.u8 field-grid.json Building footprints Microsoft, Purdue, OSM LiDAR 2018 roof heights Site tools buildings.py, us52.py building_models.py Site site.json Roads, buildings, bins, grid Crop evidence Sentinel-2, CDL, Mesonet Camera of the Polaris Crop tools crops.py game_crops.py Crop season crops_2026.json Crop, date, temperatures Place labels Points and areas, by hand Place tool places.py Named places places.json Survey products Terrain of LiDAR 2018 SSURGO soil survey Tree survey No tool in the repository. The files are the products. Terrain and soil heights.f32 soils.json, soil_units.u8 vegetation.json Game Wheels, implements Farm and sensors Menu and HUD Farm traffic Optimizer ACRES Core Terrain, surfaces Soil units, fields Named places Core scene builder build_scene.py Writes Core/Data/ acre_scene.json for ACRES Core Scouting map builder build_map.py Writes the folder ACRE/Scouting for the scouting task The readers load the files at the start of a session or of a build.
The tools of Tools/ACRE/Map write the runtime map files. The game, ACRES Core and two builders read them. Open the diagram
File Format Contents
site.json JSON The grid, the origin, the roads, the building boxes, the bins.
heights.f32 float32 grid, 1001 x 1001 The heights of the terrain.
surface_polygons.json JSON The ground layer: polygons with a surface class.
surfaces.u8 uint8 grid, 1000 x 1000 The surface codes of the survey cells.
grass-lanes.u8 uint8 grid, 1000 x 1000 The grass mask of the survey cells.
field-grid.json JSON The geometry of the 4 m grid.
field_ids.u8 uint8 grid, 382 x 382 The field of each 4 m cell.
cover.u8 uint8 grid, 382 x 382 The land cover of each 4 m cell.
fields.json JSON The outlines of the 59 fields.
crops_2026.json JSON The crop and the planting date of each field in 2026.
vegetation.json JSON The planting record of the level.
soils.json JSON The soil map units and their properties.
soil_units.u8 uint8 grid, 1000 x 1000 The soil map unit of each survey cell.
places.json JSON The named places and the spawn places.
minimap.png PNG, 2048 x 2048 The map image of the HUD and the menu.
Scouting/ JSON and uint8 grid The products of the scouting map.
acre_scene.json JSON The buildings, bins and trees for ACRES Core.
road_mask.bin uint8 grid, 1160 x 1620 A road mask of a map that is not in the game now.

Conventions#

The runtime map files are in the folder Acres/Content/Simulation/ACRE. The examples use paths relative to the repository root.

Rule Description
Binary grids A grid file has no header. The values are in row sequence. Row 0 is the north edge of the tile and column 0 is the west edge.
Byte sequence heights.f32 is little-endian. The other grids have one byte for each cell.
Survey grid 1000 x 1000 cells of 1.524003048 m. Cell \((u, v)\) is at column \(u\) and row \(v\).
4 m grid 382 x 382 cells of 4 m. Its north-west corner is the corner of the survey grid.
Units Metres, unless the key name gives a different unit (_ft, _cm, _px, _ha, _deg).
Suffix _px or _uv A position in survey grid cells: \(u\) east, \(v\) south.
Python The examples need numpy. Use the conda environment torchenv.

The map tools read source data from the folder Acres/Raw/ACRE. That folder is not in the repository. Thus a build of the game does not need the tools. The command python Tools/ACRE/Map/test_map.py tests the mathematics of the tools without the source data.

Site and Terrain#

site.json#

The site file gives the geometry of the survey grid and the georeference of the tile. It also contains the road centrelines, the building boxes and the grain bins of the original map.

Name Type Unit Default Description
origin_source_ft array ftUS 2977500, 1902500, 705 The origin in EPSG:2968 and its NAVD88 height.
crs text EPSG:2968 The coordinate reference system.
grid_step_m number m 1.524003048 The size of a survey cell.
grid_x0_m, grid_y0_m number m -762.001524 The world position of the north-west corner.
grid_width, grid_height integer node 1001 The size of heights.f32.
surface_width, surface_height integer cell 1000 The size of the survey grid.
spawn_uv, spawn_yaw_deg array, number cell, deg 625, 477; 180 The start pose when places.json is not available.
roads array 35 items name, kind, width_m, points_px. US 52 also has lane_offsets_m.
buildings array 23 items name, bounds_px (\(u_0, v_0, u_1, v_1\)), height_m, ground_m, footprint_id.
silos array 32 items id, group, uv, diameter_m, height_m, ground_m.
trees array 174 items The trees of the first survey.
road_review_corrections array 1 item The record of the height correction along the roads.
terrain_revision text 2026-09-23-road-review-3 The revision of heights.f32.
Use Item
Readers in the game AcresVehicle.cpp (grid, spawn, review routes), AcresNpc.cpp (road graph), AcresOptimizer.cpp, AcresHud.cpp, AcresSensors.cpp, AcresPolaris.cpp, AcresSimControl.cpp.
Readers in ACRES Core FAcresTerrain::Load, FSiteGeoreference::Load.
Other readers Core/Scripts/build_scene.py, Calibration/Polaris/geo.py, the scouting map builder.
Tools that write it us52.py (US 52), building_models.py (buildings, bins), site_edits.py, fix_icsc_driveway.py.
import json
from pathlib import Path

ACRE = Path("Acres/Content/Simulation/ACRE")
site = json.loads((ACRE / "site.json").read_text())
s = site["grid_step_m"]
x0, y0 = site["grid_x0_m"], site["grid_y0_m"]


def grid_to_enu(u, v):
    """Survey grid cells to world ENU metres."""
    return x0 + u * s, -(y0 + v * s)


print(grid_to_enu(474.6, 592.2))
# (-38.70967741935476, -140.51308102616213)
print(len(site["roads"]), len(site["buildings"]),
      len(site["silos"]))
# 35 23 32

heights.f32#

The terrain heights at the nodes of the survey grid.

Property Value
Data type float32, little-endian
Shape 1001 rows x 1001 columns (grid_height x grid_width)
Size 4008004 bytes
Index heights[j, i] is node \((u, v) = (i, j)\)
Origin Node (0, 0) is the north-west corner. Node (500, 500) is the origin of the world.
Spacing 1.524003048 m
Unit m above the origin height (NAVD88 height minus 214.884 m)
Range -12.652 to 7.833
Use Item
Readers in the game AAcresVehiclePawn::LoadAcreTerrain, FAcresFieldSetup::SurveyHeights, FAcresFarmRuntime::Initialize, AcresSoilVisuals.cpp.
Readers in ACRES Core FAcresTerrain::Load.
Other readers Core/Scripts/build_scene.py, Calibration/Polaris/geo.py, the building and tree tools.
Tool that writes it None in the repository. The file is the survey product with the road review correction.

A point between the nodes has the height of one of the two triangles of its cell.

import numpy as np

w, h = site["surface_width"], site["surface_height"]
heights = np.fromfile(ACRE / "heights.f32", dtype="<f4")
heights = heights.reshape(h + 1, w + 1)
print(heights.shape, heights.dtype)  # (1001, 1001) float32
print(heights[500, 500])             # 0.32698855


def height_at(u, v):
    """Height on the two triangles of the cell."""
    i, j = min(int(u), w - 1), min(int(v), h - 1)
    fx, fy = u - i, v - j
    a, b = heights[j, i], heights[j, i + 1]
    c, d = heights[j + 1, i], heights[j + 1, i + 1]
    if fx + fy <= 1:
        return a + (b - a) * fx + (c - a) * fy
    return d + (c - d) * (1 - fx) + (b - d) * (1 - fy)


print(round(float(height_at(474.6, 592.2)), 3))
# 0.639  (the ICSC garage spawn)

Ground Layer#

surface_polygons.json#

The ground layer. The wheels, the implements and the farm read the surface class from these polygons. The schema is acres-surface-polygons-1. The frame is the Unreal world in centimetres: X east, Y south.

Name Type Unit Default Description
classes array 7 names field, asphalt, concrete, gravel, grass_lane, grass, dirt. The index is the class code.
priority object 60, 55, 40, 30, 20, 10 The priority of asphalt, concrete, gravel, dirt, grass_lane, grass.
polygons array 521 items The polygons. A later polygon has priority over an earlier one of the same priority.
polygons[].id text The identifier, for example G0017.
polygons[].class text The surface class.
polygons[].priority integer The priority of the polygon.
polygons[].ring array cm The outer ring: integer points \([X, Y]\). The ring is open.
polygons[].holes array cm none Rings that the polygon does not contain. 28 polygons have holes.
polygons[].source text The origin of the polygon, for example verges:R0012.
polygons[].role text none verge for a road verge.
polygons[].centreline array cm none The centre line of a grass lane.
polygons[].wheel_track_m number m 1.55 The distance between the wheel tracks of a grass lane.
polygons[].edge_source text none The image that gave the edges. county2025 marks the county orthophoto.
Use Item
Reader in the game FAcresFieldSetup::SurfaceMap (one time for each process), then FSurfaceMap::ClassAt.
Reader in ACRES Core FAcresWorld loads it into the same FSurfaceMap.
Other readers Calibration/Polaris/geo.py, the scouting map builder.
Tools that write it game_layer.py, then game_layer_fit.py, then site_edits.py.

All coordinates are in the range of ±76200 cm.

# These tools need the folder Acres/Raw/ACRE.
python Tools/ACRE/Map/game_layer.py
python Tools/ACRE/Map/game_layer_fit.py
python Tools/ACRE/Map/site_edits.py
layer = json.loads(
    (ACRE / "surface_polygons.json").read_text())
polygons = layer["polygons"]
print(len(polygons))  # 521


def inside(ring, x, y):
    """Even-odd test of a point against one ring."""
    hit = False
    for (xi, yi), (xj, yj) in zip(ring, ring[-1:] + ring[:-1]):
        if (yi > y) != (yj > y) and \
                x < (xj - xi) * (y - yi) / (yj - yi) + xi:
            hit = not hit
    return hit


def class_at(x_cm, y_cm):
    """Surface class at an Unreal world point (cm)."""
    best = None
    for k, p in enumerate(polygons):
        if not inside(p["ring"], x_cm, y_cm):
            continue
        if any(inside(q, x_cm, y_cm)
               for q in p.get("holes", [])):
            continue
        key = (p["priority"], k)
        if best is None or key > best[0]:
            best = (key, p["class"])
    return best[1] if best else "field"


print(class_at(-3871, 14051))  # concrete
print(class_at(0, 0))          # field

surfaces.u8#

The surface code of each survey cell. game_layer.py makes it from the polygons with 4 x 4 samples in each cell. The code with the most samples applies. If two codes have equal counts, the lower code applies.

Property Value
Data type uint8
Shape 1000 rows x 1000 columns
Index surfaces[v, u]
Cell size 1.524003048 m
Code Surface Cells
0 asphalt 28233
1 concrete 1290
2 gravel 22851
3 dry_soil 947626
4 wet_soil 0
5 mud 0
Use Item
Readers in the game AAcresVehiclePawn::SampleSurface (only when surface_polygons.json is not available), AcresSoilVisuals.cpp (the vertex colours of the terrain).
Reader in ACRES Core FAcresWorld, only when surface_polygons.json is not available.
Tools that write it game_layer.py (write_game_rasters), site_edits.py.
surfaces = np.fromfile(ACRE / "surfaces.u8", dtype=np.uint8)
surfaces = surfaces.reshape(h, w)
print(surfaces.shape, np.bincount(surfaces.ravel()))
# (1000, 1000) [ 28233   1290  22851 947626]
print(surfaces[592, 474])  # 1: row v, column u

grass-lanes.u8#

A mask of the survey cells with grass. A cell has the value 1 when grass_lane or grass has 8 or more of its 16 samples.

Property Value
Data type uint8, values 0 and 1
Shape 1000 rows x 1000 columns
Index grass[v, u]
Cells with the value 1 166350
Use Item
Reader in the game AcresSoilVisuals.cpp (the vertex colours of the terrain tiles near the vehicle).
Tools that write it game_layer.py (write_game_rasters), site_edits.py.
grass = np.fromfile(ACRE / "grass-lanes.u8", dtype=np.uint8)
grass = grass.reshape(h, w)
print(grass.shape, int(grass.sum()))
# (1000, 1000) 166350

Fields and Land Cover#

field-grid.json#

The geometry of the 4 m grid. field_ids.u8, cover.u8 and the water grid of the farm use this grid.

Name Type Unit Default Description
width integer cell 382 The number of cells on each side.
step_m number m 4.0 The cell size.
origin_m number m -762.001524 The Unreal world position of the north-west corner, for X and for Y.
fields_sha256 text The SHA-256 hash of the bytes of fields.json.
scope text A note about the use of the grid.

The cell of an Unreal world point \((X, Y)\) in metres is

\[ \text{column} = \left\lfloor\frac{X - o}{\Delta}\right\rfloor, \qquad \text{row} = \left\lfloor\frac{Y - o}{\Delta}\right\rfloor \]

with \(o\) = origin_m and \(\Delta\) = step_m. FAcresFarmRuntime::CellAt uses this equation. The grid is 1528 m wide. Thus the last column and the last row go 4 m outside the tile.

grid = json.loads((ACRE / "field-grid.json").read_text())
n, step = grid["width"], grid["step_m"]
origin = grid["origin_m"]
print(n, step, origin)  # 382 4.0 -762.001524003048


def cell_of(x_m, y_m):
    """Row and column of an Unreal world point (m)."""
    return (int((y_m - origin) // step),
            int((x_m - origin) // step))


print(cell_of(-38.71, 140.513))  # (225, 180)

field_ids.u8#

The field of each 4 m cell. The tool tests the centre of each cell against the outlines of fields.json.

Property Value
Data type uint8
Shape 382 rows x 382 columns
Index field_ids[row, column] of field-grid.json
Values 0: no field. 1 to 59: the field F01 to F59.
Use Item
Reader in the game FAcresFarmRuntime::Initialize (FieldAt).
Reader in ACRES Core FAcresWorld.
Tools that write it fields_recut.py, field_edits.py.
field_ids = np.fromfile(ACRE / "field_ids.u8", dtype=np.uint8)
field_ids = field_ids.reshape(n, n)
print(field_ids.shape, field_ids.max())  # (382, 382) 59

fields = json.loads((ACRE / "fields.json").read_text())
f39 = next(f for f in fields["fields"] if f["id"] == "F39")
u, v = f39["label_uv"]
print(field_ids[cell_of(x0 + u * s, y0 + v * s)])  # 39

cover.u8#

The land cover of each 4 m cell. The water model of the farm reads the roughness and the interception of a cell from this code. The LiDAR reads the material of a ground hit from it.

Property Value
Data type uint8
Shape 382 rows x 382 columns
Index cover[row, column] of field-grid.json
Code Cover Cells
0 bare 68596
1 corn 4176
2 soybean 4252
3 grass 25422
4 woodland 35968
5 shrubs 0
6 asphalt 4111
7 concrete 164
8 gravel 3235
9 potato 0
Use Item
Readers in the game FAcresFarmRuntime::Initialize, AcresSensors.cpp (ground material of the LiDAR).
Reader in ACRES Core FAcresWorld.
Tools that write it game_layer.py (write_game_rasters, 8 x 8 samples in each cell), site_edits.py, field_edits.py.

At the start of a session, the game changes the codes of the field cells in memory to the crops of the session. It does not change the file.

cover = np.fromfile(ACRE / "cover.u8", dtype=np.uint8)
cover = cover.reshape(n, n)
names = ["bare", "corn", "soybean", "grass", "woodland",
         "shrubs", "asphalt", "concrete", "gravel", "potato"]
counts = np.bincount(cover.ravel(), minlength=10)
print(dict(zip(names, counts.tolist())))
# {'bare': 68596, 'corn': 4176, 'soybean': 4252,
#  'grass': 25422, 'woodland': 35968, 'shrubs': 0,
#  'asphalt': 4111, 'concrete': 164, 'gravel': 3235,
#  'potato': 0}
print(names[cover[cell_of(-38.71, 140.513)]])  # concrete

fields.json#

The outlines of the 59 fields in survey grid coordinates.

Name Type Unit Default Description
schema_version integer 1 The version of the format.
coordinate_system text A note: survey grid cells, \(u\) east, \(v\) south.
fields array 59 items The fields.
fields[].id text F01 to F59.
fields[].land_cover text unassigned, corn, soybean, empty, lawn, shrubs or woodland.
fields[].crop text or null corn, soybean or null.
fields[].geometry_uv object cell A GeoJSON Polygon. The game reads only the outer ring.
fields[].label_uv array cell The position of the label on a map.
fields[].area_ha number ha The area of the field.
fields[].confidence text A note about the source of the outline.
fields[].geometry_source text The tool step that cut the outline.
Use Item
Readers in the game FAcresFieldSetup::Fields, FAcresSimControl::LoadFields, FAcresFarmRuntime::Initialize (fingerprint).
Reader in ACRES Core FAcresWorld.
Other readers Learning/acres_learn/acre.py, the scouting map builder.
Tools that write it fields_recut.py, field_edits.py, fix_icsc_driveway.py, smooth_ground_edges.py.

The game changes the land cover unassigned to corn.

doc = json.loads((ACRE / "fields.json").read_text())
print(len(doc["fields"]))  # 59
field = doc["fields"][38]
ring = field["geometry_uv"]["coordinates"][0]
print(field["id"], field["land_cover"],
      field["area_ha"], len(ring))
# F39 empty 0.469 19

crops_2026.json#

The crop season of 2026. The option -CropSeason=<name> selects the file crops_<name>.json. The default is 2026. The schema is acres-crop-season-1.

Name Type Unit Default Description
season text 2026 The name of the season.
rules array 5 items The rules that select the crop of a field.
fields[].id text F01 to F59.
fields[].crop text corn, soybean or none.
fields[].plant_date date The planting date, YYYY-MM-DD.
fields[].rule text The rule that applied. A rule that starts with default is not a call of the crop map.
fields[].confidence text high, medium or low.
fields[].call_2026 text The call of the crop map of 2026.
fields[].sim_land_cover text The land cover of fields.json.
weather.first_date date 2026-04-01 The date of the first temperature value.
weather.measured_days integer day 178 The number of measured days. The other days are means of 2023 to 2025.
weather.min_c, weather.max_c array °C 244 values The daily minimum and maximum air temperature.
Use Item
Reader in the game FAcresFieldSetup::CropSeason.
Reader in ACRES Core FAcresWorld (the crop of each field).
Tool that writes it game_crops.py, from Calibration/Map/Layers/crops_2026.json (crops.py).
# The tool reads the weather record from $ACRE_WEATHER.
python Tools/ACRE/Map/game_crops.py
season = json.loads(
    (ACRE / "crops_2026.json").read_text())
print(season["schema"], season["weather"]["first_date"],
      len(season["weather"]["min_c"]))
# acres-crop-season-1 2026-04-01 244
print({f["id"]: (f["crop"], f["plant_date"])
       for f in season["fields"][:3]})
# {'F01': ('soybean', '2026-05-28'),
#  'F02': ('soybean', '2026-06-29'),
#  'F03': ('soybean', '2026-05-30')}

vegetation.json#

The record of the planting of the level: the crop patches and the trees that the level contains for each field.

Name Type Unit Default Description
revision text 2026-09-23-planting-1 The revision of the planting.
fields object 27 keys One entry for each planted field or zone, for example F30.
fields.<id>.land_cover text corn, soybean, woodland or shrubs.
fields.<id>.area_ha number ha The planted area.
fields.<id>.instances integer The number of mesh instances.
fields.<id>.represented_plants integer The number of plants that the instances show.
fields.<id>.headland_m number m The strip without crop at the edge of the field.
zones array 1 item Areas that are not fields. V01 is the woodland south of US 52.
Use Item
Reader in the game FAcresFarmRuntime::Initialize (only for the fingerprint of a saved farm state).
Reader in ACRES Core FAcresWorld (headland_m of the planted crop fields).
Tool that writes it None in the repository.
veg = json.loads((ACRE / "vegetation.json").read_text())
print(veg["revision"], len(veg["fields"]))
# 2026-09-23-planting-1 27
print(veg["fields"]["F30"])
# {'land_cover': 'corn', 'area_ha': 0.8277693974742788,
#  'instances': 4735, 'represented_plants': 37880,
#  'headland_m': 1.8}

Soil#

soils.json#

The soil map units of the SSURGO survey on the tile and their hydraulic properties. Soil Water describes the model that uses them.

Name Type Unit Default Description
source text The query of the SSURGO data (2026-09-23).
manning_n object s/m^(1/3) 10 keys The roughness of each cover for sheet flow.
tile_drainage.coefficient_mm_day number mm/day 9.525 The drainage coefficient of the tile drains.
units array 16 items The map units.
units[].index integer 1 to 16 The value of the unit in soil_units.u8.
units[].musym, units[].muname text The symbol and the name of the unit, for example Cm.
units[].cells integer cell The number of survey cells of the unit.
units[].ksat_surface_mm_h number mm/h The saturated conductivity of the surface layer.
units[].ksat_profile_50cm_mm_h number mm/h The saturated conductivity of the top 0.5 m.
units[].ksat_sealed_mm_h number mm/h The conductivity of a sealed surface.
units[].wetting_suction_m number m The suction head of the Green-Ampt model.
units[].saturated_theta number m³/m³ The water content at saturation.
units[].field_capacity_theta number m³/m³ The water content at field capacity.
units[].wilting_theta number m³/m³ The water content at the wilting point.
units[].surface_*, units[].subsoil_* number m, m³/m³ The depth and the water contents of the two layers.
units[].drainage, units[].hydrologic_group text The drainage class and the hydrologic group.
units[].components array The soil components of the unit with their texture.
Use Item
Readers in the game FAcresFarmRuntime::Initialize, AAcresVehiclePawn::LoadAcreTerrain (soil texture), FAcresOptimizer::Run.
Reader in ACRES Core FAcresWorld.
Tool that writes it None in the repository.
soils = json.loads((ACRE / "soils.json").read_text())
unit = {x["index"]: x for x in soils["units"]}
print(len(unit), unit[9]["musym"], unit[9]["muname"])
# 16 Cm Chalmers silty clay loam
print(unit[9]["wilting_theta"],
      unit[9]["field_capacity_theta"],
      unit[9]["saturated_theta"])
# 0.22899999999999998 0.345 0.43

soil_units.u8#

The soil map unit of each survey cell.

Property Value
Data type uint8
Shape 1000 rows x 1000 columns
Index units[v, u]
Values 1 to 16: the index of a unit in soils.json. 0: no map unit (no cell has this value).
Use Item
Readers in the game FAcresFarmRuntime::Initialize, AAcresVehiclePawn::LoadAcreTerrain, FAcresOptimizer::Run.
Reader in ACRES Core FAcresWorld.
Tool that writes it None in the repository.
units = np.fromfile(ACRE / "soil_units.u8", dtype=np.uint8)
units = units.reshape(h, w)
print(units.shape, units.min(), units.max())
# (1000, 1000) 1 16
print(unit[int(units[592, 474])]["musym"])  # Cm

Places and Minimap#

places.json#

The named places of the tile. Each place gives its points in four frames.

Name Type Unit Default Description
schema integer 1 The version of the format.
places[].id text The identifier, for example spawn-icsc-garage.
places[].name text The name that the menu shows.
places[].category text spawn, landmark or yard.
places[].kind text point, route or area.
places[].heading_deg number or null deg The compass heading of a point.
places[].ue_yaw_deg number or null deg The Unreal yaw: the heading minus 90°.
places[].cells array cell The points in survey grid coordinates.
places[].ue_cm array cm The points in the Unreal world.
places[].enu_m array m The points in the world ENU frame.
places[].latlon_wgs84 array deg Latitude and longitude in WGS84(G2139) at the epoch 2026.75.
places[].spawn_flags text The spawn options of a point.
places[].area_m2 number m² The area of an area place.
Use Item
Reader in the game AcresPlaces::All (the first point and ue_yaw_deg of each place).
Readers in ACRES Core FAcresWorld, CoreSimServer.cpp.
Other readers Learning/acres_learn/acre.py, Core/Scripts/unreal_dbw_replay.py.
Tool that writes it places.py, from a folder with one JSON file for each place.
python Tools/ACRE/Map/places.py <folder-with-place-files>
places = json.loads(
    (ACRE / "places.json").read_text())["places"]
spawn = next(p for p in places
             if p["id"] == "spawn-icsc-garage")
print(spawn["cells"][0], spawn["enu_m"][0],
      spawn["heading_deg"])
# [474.6, 592.2] [-38.71, -140.513] 0

minimap.png#

The map image of the HUD and of the result page of the optimizer.

Property Value
Format PNG, RGB, 8 bits for each channel
Size 2048 x 2048 pixels
Extent The full tile. North is up.
Scale 0.7441 m for each pixel, 2.048 pixels for each survey cell
Use Item
Readers in the game AcresHud.cpp, AcresMenu.cpp (SAcresOptMap). The game loads the file from the disk at run time.
Tools that write it game_layer.py (write_minimap), site_edits.py.

The image shows the classes of the ground layer in fixed colours above a shaded image of the terrain.

from PIL import Image

image = Image.open(ACRE / "minimap.png")
print(image.size, image.mode)  # (2048, 2048) RGB
px = 2048 / 1000  # pixels for each survey cell
print(round(474.6 * px), round(592.2 * px))
# 972 1213  (the ICSC garage spawn)

Scouting Folder#

Scouting/#

The folder Acres/Content/Simulation/ACRE/Scouting contains the products of the scouting map: scouting_map.json, ground_classes.u8 and obstacles.json. Scouting Map gives their format.

Use Item
Readers in ACRES Core FAcresScene::LoadObstacles (obstacles.json), FAcresWorld (ground_classes.u8).
Tools that write it Learning/acres_learn/tasks/scouting/build_map.py and obstacles.py.
ls Acres/Content/Simulation/ACRE/Scouting
# ground_classes.u8  obstacles.json  scouting_map.json

Core Scene#

acre_scene.json#

The file Core/Data/acre_scene.json gives ACRES Core the static obstacles of the map: buildings, grain bins and trees. ACRES Core uses them for the ray-cast LiDAR and for the collision test of the vehicles. The schema is acres-core-scene-1. The frame is the world ENU frame in metres. The values have a resolution of 1 cm.

Name Type Unit Default Description
materials object 16 keys The LiDAR properties of each material, from sensors_polaris.json.
material_names array 16 names The names of the materials. A material index refers to this list.
triangles array m 2072 triangles A flat list with 10 numbers for each triangle: 3 points \((x, y, z)\) and the material index.
cylinders array m 7010 items \([x, y, r, z_0, z_1, m]\): vertical cylinders with caps. 26 bin walls and 6984 trunks.
ellipsoids array m 6984 items \([x, y, z, r_x, r_y, r_z, m]\): the crowns of the trees.
obstacles array m 89 items \([\text{kind}, z_0, z_1, x_0, y_0, x_1, y_1, \dots]\): collision outlines. Kind 0 is a building and kind 1 is a bin.

The builder makes these shapes.

  • Buildings. Each part of a building is a rectangle with walls and a roof: flat, shed, gable or arch.
  • Bins. A bin is a cylinder to the eave with a cone roof of 24 triangles.
  • Trunks. A trunk is the collision cylinder of the tree in the level. It goes 0.3 m into the terrain.
  • Crowns. A crown is a sphere. Its radius is 0.25 of the tree height, limited to the range from 1.5 m to 5 m.
Use Item
Reader FAcresScene::Load. It builds a bounding volume hierarchy and a collision grid with cells of 8 m.
Tool that writes it Core/Scripts/build_scene.py.
Inputs of the tool Calibration/Map/Layers/building_models.json, Calibration/Map/Layers/tree_check.json, heights.f32, site.json, sensors_polaris.json and a dump of the tree instances of the level.

The dump of the tree instances is a local file. The option --episodes gives its folder. Without the dump, the builder writes no trees.

python Core/Scripts/build_scene.py --out /tmp/acre_scene.json
# /tmp/acre_scene.json: 63 buildings, 26 bins,
# 2072 triangles, 7010 cylinders (6984 trunks),
# 6984 crowns (342 gone trees left out), 0.66 MB
scene = json.loads(
    Path("Core/Data/acre_scene.json").read_text())
print(scene["schema"])  # acres-core-scene-1
tri = np.array(scene["triangles"]).reshape(-1, 10)
print(tri.shape, len(scene["cylinders"]),
      len(scene["ellipsoids"]), len(scene["obstacles"]))
# (2072, 10) 7010 6984 89
print(scene["material_names"][int(tri[0, 9])])  # building

Legacy Files#

road_mask.bin and grass_mask.json#

These two files are in Acres/Content/Simulation. They describe the roads of a map that is not in the game now. The game loads them, but the level V03ACRE uses the ACRE files of this page.

Name Type Unit Default Description
x0, y0 number m -810 The world position of the first cell.
width, height integer cell 1620, 1160 The size of the mask.
step number m 1.0 The cell size.
eligible_m2, density_per_m2 number m², 1/m² 481930, 10 Values of a grass generator. The game does not read them.

road_mask.bin is a uint8 grid with height rows and width columns. A value other than 0 is a road.

Use Item
Reader in the game AAcresVehiclePawn (configuration load), SampleSurface for a map other than V03ACRE.
Tool that writes it None in the repository.
sim = Path("Acres/Content/Simulation")
meta = json.loads((sim / "grass_mask.json").read_text())
mask = np.fromfile(sim / "road_mask.bin", dtype=np.uint8)
mask = mask.reshape(meta["height"], meta["width"])
print(mask.shape, int(mask.sum()))  # (1160, 1620) 82030