TacticalMap (Next)
Renders tracked entities (crew vehicle, targets) as NATO-style symbols on a static, per-range background image rather than tiled map imagery. Built for ranges that have no internet access at runtime, unlike MapDisplay, which loads tiles from a mapURL.
Dashboard generation
| Value | |
|---|---|
| Runner node | dashboard-v2 |
| Frontend | ui/dashboard (TacticalMapDS -> TacticalMap) |
| Data envelope | $heat-dataservice (contract) |
Layout component identifier
TacticalMap: the value of configuration.component in v2 layout rows.
Layout configuration
| Field | Description |
|---|---|
component | "TacticalMap" |
name | Internal name |
titleContent | Panel title |
channels | Channel id(s) bound to this widget, mapdisplay shape |
defaultRealm | Realm for data lookup |
showOpenModalButton | Expand to modal |
TacticalMap has no mapDisplayItem-equivalent config block: there is no tile URL, zoom, or marker-cone styling to set. The background image and its geographic bounds are a fixed frontend constant (FIXED_RANGE_BOUNDS in ui/dashboard/src/utils/tactical-map/CoordinateProjection.ts), not something a session template configures.
Data contract
Envelope
Publish canonical $heat-dataservice with realms, groups, and channels per the dashboard-v2 upstream contract.
Map channel
| Property | Value |
|---|---|
shape | "mapdisplay" |
data | Same movements[] envelope as MapDisplay |
TacticalMap reads the same mapdisplay channel shape as MapDisplay, but interprets each movement point differently and requires more fields:
| Field | Required | Description |
|---|---|---|
movements[].entityConfig | Yes | { allegiance, domain, unitType }. A movement with no entityConfig is silently dropped, not shown with a generic icon. |
movements[].movement[].latitude/longitude | Yes | Real WGS84 degrees. Projected against the fixed range image bounds, so a session that took place outside that range will not land correctly on the image. |
movements[].movement[].health | No | 0-100. A target’s health reaching 0 removes its marker from the map (see TacticalMap.tsx’s visibleTargets filter). |
movements[].movement[].heading | No | Compass degrees, hull orientation. Drives marker rotation for tracked vehicles. |
movements[].movement[].yaw | No | Turret orientation, independent of heading. Drives the vision-cone rotation; falls back to heading when absent. |
movements[].movement[].engagementType | No | "fire" | "lase". Marks that point as a permanent “Engagement” marker on the map. |
movements[].movement[].engagementTargetId | No | Which target an engagement point targeted, if known. |
entityConfig’s allegiance/domain/unitType are the same enums as NatoSymbol . There is no channel-level affiliation source in the underlying capture (protobuf unit_type_data carries no friend/hostile field), so entityConfig has to be assigned upstream, in the arbex/processor script that builds the channel, not inferred by the frontend.
Example channel payload
{
"id": "tactical-map-tracks",
"name": "tactical-map-tracks",
"groupId": "map",
"shape": "mapdisplay",
"data": {
"movements": [
{
"name": "Puma",
"entityConfig": { "allegiance": "friend", "domain": "ground", "unitType": "tank" },
"movement": [
{
"latitude": "53.4701",
"longitude": "8.3850",
"heading": "45",
"yaw": "60",
"health": "100",
"capturedDate": "2026-08-17T11:56:40.029Z"
}
]
},
{
"name": "land_zbt_scheibe_58_pzturm_falling (482)",
"entityConfig": { "allegiance": "hostile", "domain": "ground", "unitType": "tank" },
"movement": [
{
"latitude": "53.4712",
"longitude": "8.3862",
"heading": "0",
"health": "100",
"capturedDate": "2026-08-17T11:56:40.029Z"
},
{
"latitude": "53.4712",
"longitude": "8.3862",
"heading": "0",
"health": "0",
"engagementType": "fire",
"capturedDate": "2026-08-17T11:58:12.500Z"
}
]
}
]
}
}Behaviour notes
- Playback-driven, not a live-updating track.
TacticalMapDSsamples every target’s track at the same fraction of a shared session duration (viauseClockandinterpolateTrack), throttled to a 100ms cadence. It does not render a raw point-by-point trail; short-lived and long-lived targets are kept in sync against one shared timeline rather than each target’s own span. - Vision cone. Rendered for any non-hostile
entityConfig.allegiance, oriented byyawwhen present, falling back toheading. - Tracked-vehicle marker. A friendly target with more than one track point renders as a rotating vehicle sprite (
VehicleMarker) instead of a NATO symbol. Everything else (hostile targets, single-point tracks) renders as aNatoSymbol. - No external tiles, no internet dependency. The background is a bundled static image (
public/assets/tactical-map/rme-range-map.png), matching the platform’s air-gapped runtime requirement.
Related
- MapDisplay (Next): tile-based map, different background and config model
- Next components index
- Dataservice migration status
- dashboard-v2 upstream contract
- Reference JSON:
tools/arbex/reference/next/TacticalMap.json