Skip to content

AcresCoreLidar.h#

Core/Source/AcresCoreLidar.h Generated

Ray-cast LiDAR for ACRES Core: the Polaris' RoboSense Helios (1800 columns x 32 rings at 10 Hz, sensors_polaris.json "lidar") and the scouting task's planar 360-beam scan, traced against the terrain (AcresCoreTerrain.h), the static obstacle scene (AcresCoreScene.h) and the other vehicles' boxes.

Beam layout as the game builds it (AcresSensors.cpp, FAcresSensorRecorder): ring r at elevations_deg[r]; column c at the block azimuth 360 c / columns deg counter-clockwise from forward, or for a "cw" layout (the Helios) at -360 c / columns deg; plus the ring's azimuth_offsets_deg[r] (counter-clockwise). A beam starts at the lens centre, lens_center_m off the spin axis at the block azimuth, and a point is written as rslidar_sdk does: range along the beam plus the lens offset, in the sensor frame (the mount rotation applied, points not rotated back). The sensor frame is the base_footprint FLU frame turned by the mount rpy_deg (R = Rz Ry Rx, fixed axes, as URDF) and moved to position_flu_m. Organized output as the game's PCD: cell = column x rings + ring (HEIGHT = columns, WIDTH = rings).

Radiometry (AcresLidarModel.cpp in the game, simplified): apparent reflectance = Minnaert(reflectivity, cos incidence, k) + specular lobe; signal S = S10 (rho / 0.1) (R10 / R)^2 (1 - exp(-(R / R_overlap)^2)) times the peak loss of a grazing footprint (AcresLidarPhysics.h); a return is kept when S reaches the detection threshold (the signal detected with the spec probability at the 10 % point). One return per beam; tree crowns are one foliage layer each, passed with their material's transmission (a deterministic hash per beam). The vehicle's own body comes from the measured self-return table (polaris_lidar_self.f32) as in the game. Not modelled: multiple echoes, crops and ground cover, weather, the rolling sweep's motion distortion.

Threads: FAcresLidar is read-only after construction; Scan may run on many threads at once.

FAcresLidarPattern#

struct FAcresLidarPattern

Beam pattern, mount and radiometry of a LiDAR.

Name Type Unit Default Description
Columns, Rings int Columns (azimuth steps per turn) and rings (beams per column).
ElevationDeg, AzimuthOffsetDeg std::vector<double> Elevation and horizontal offset (counter-clockwise) of every ring, deg.
bClockwise bool true Column order: true when column c is at -360 c / columns deg (clockwise, the Helios / rslidar_sdk layout).
LensCenterM, MinRangeM, MaxRangeM double Lens centre distance from the spin axis, m; nearest and farthest range, m.
MountPositionM, MountRpyDeg FVec3 MountPositionM; Mount in the base_footprint FLU frame: position, m; roll, pitch, yaw, deg (R = Rz Ry Rx).
RangeAt10PctM, SignalAt10PctCounts, AmbientCounts, DetectionAtSpec, OverlapRangeM, StdM, RangeStdLowSnrM, DivergenceHMrad, DivergenceVMrad, PulseLengthM double Radiometry: range at which a 10 % target gives SignalAt10PctCounts, m (per ring when RingRangeAt10PctM is filled); ambient counts; detection probability at the spec point; near-field overlap range, m; range noise at high SNR and its low-SNR scale, m; beam divergence horizontal and vertical, mrad; pulse length, m.
bRadiometry bool true False: every hit within range is a return (no signal model); the planar scan uses this.
SelfP, SelfRangeM, SelfIntensity, SelfBlockP std::vector<float> The vehicle seen by its own LiDAR (lidar.self_returns, polaris_lidar_self.f32, measured from the recorded scans), per cell: probability of a return from the body, its range (m) and intensity, and probability that the body blocks the beam without a return. Empty: no body. Used as the game does (a hash per scan and cell).

FAcresLidarPattern::FromSensorsJson#

Reads the "lidar" block of a sensors JSON (Content/Simulation/sensors_polaris.json).

Argument Description
Path The file.
Out Receives the pattern.
Error Why it failed (may be null).

Returns: True on success.

static bool FromSensorsJson(const std::string& Path, FAcresLidarPattern& Out, std::string* Error = nullptr);

FAcresLidarPattern::Planar#

The scouting task's planar scan: Beams beams 360 / Beams deg apart counter-clockwise from forward, level in the vehicle frame (no mount tilt), at the Helios position, MaxRangeM range, no lens offset and no radiometry.

static FAcresLidarPattern Planar(int Beams = 360, double MaxRangeM = 30);

FAcresLidarPattern::BeamCount#

Beams per scan.

int BeamCount() const ;

FAcresLidarPattern::MountRotation#

Mount rotation (sensor frame to base_footprint FLU).

FQuat MountRotation() const;

FAcresLidarPattern::Beam#

Direction (unit) and lens origin of a beam in the sensor frame, m.

void Beam(int Ring, int Column, FVec3& DirectionSensor, FVec3& LensSensor) const;

FAcresLidarPattern::DetectionThresholdCounts#

Signal counts that are detected with DetectionAtSpec probability at the spec point.

double DetectionThresholdCounts() const;

FAcresLidarBox#

struct FAcresLidarBox

An oriented box another vehicle presents to the LiDAR.

Name Type Unit Default Description
Centre FVec3 Centre (world m), orientation (world <- box), half extents along the box axes, m.

EAcresLidarMaterial#

enum EAcresLidarMaterial : uint8_t

Material codes of a beam besides the scene's material indices.

Value Description
LidarNoReturn
LidarTerrain
LidarVehicleBox
LidarSelf A return from the scanning vehicle's own body (FAcresLidarPattern::SelfP).

FAcresLidarScanOut#

struct FAcresLidarScanOut

One scan, organized as the game's PCD (cell = column x rings + ring).

Name Type Unit Default Description
RangeM std::vector&lt;float> m Range along the beam from the lens centre per cell, m; NaN without a return.
Points std::vector&lt;float> x y z intensity per cell (sensor frame, m; NaN x y z without a return; intensity the calibrated reflectivity byte 0-255 as a float, as the vehicle's /lidar/points).
Material std::vector&lt;uint8_t> What each beam hit: a scene material index, LidarTerrain, LidarVehicleBox or LidarNoReturn.
Returns int 0 Beams with a return.

FAcresLidarOptions#

struct FAcresLidarOptions

Scan options.

Name Type Unit Default Description
bNoise bool false Range and signal noise (deterministic from Seed and the beam); off gives exact ranges.
bFoliage bool true Tree crowns pass a beam with their material's transmission (else they are solid).
bSelfReturns bool true Apply the pattern's self-return table (the vehicle's own body) when it has one.
GroundMaterial int -1 Scene material of the terrain for the radiometry (index into the scene's materials, -1: "grass" if the scene has it, else a reflectivity of 0.17), or a function of the hit point (x, y) giving one.

FAcresLidar#

class FAcresLidar

Ray-cast LiDAR over a terrain, an optional scene and dynamic boxes.

Example

FAcresLidarPattern Helios;
FAcresLidarPattern::FromSensorsJson("Acres/Content/Simulation/sensors_polaris.json", Helios);
const FAcresLidar Lidar(Terrain, &Scene);
FAcresLidarScanOut Scan;
Lidar.Scan(Helios, BasePosition, BaseOrientation, {}, Scan);

FAcresLidar::FAcresLidar#

Keeps references to the terrain and scene (they must outlive this object).

FAcresLidar(const FAcresTerrain& InTerrain, const FAcresScene* InScene);

FAcresLidar::Scan#

Traces one scan from a vehicle pose.

Argument Description
Pattern The LiDAR.
BasePosition base_footprint (rear-axle midpoint on the ground), world m.
BaseOrientation World <- base_footprint FLU.
Boxes Other vehicles.
Out Receives the scan (resized to the pattern).
Options Noise, foliage and ground material.
void Scan(const FAcresLidarPattern& Pattern, const FVec3& BasePosition, const FQuat& BaseOrientation, const std::vector<FAcresLidarBox>& Boxes, FAcresLidarScanOut& Out, const FAcresLidarOptions& Options = ;) const;

FAcresLidar::CastRay#

Closest hit of one ray on the terrain, the scene (crowns passed per Options) and the boxes.

Argument Description
MaxT Farthest range, m.
BeamKey Hash key of the beam (foliage decisions).
Boxes Dynamic boxes.
Options As for Scan.
Hit Receives the hit.
Material Receives the material code (EAcresLidarMaterial or a scene index).

Returns: True on a hit.

bool CastRay(const FVec3& Origin, const FVec3& Direction, double MaxT, uint64_t BeamKey, const std::vector<FAcresLidarBox>& Boxes, const FAcresLidarOptions& Options, FRayHit& Hit, int& Material) const;