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#
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.
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.
FAcresLidarPattern::BeamCount#
Beams per scan.
FAcresLidarPattern::MountRotation#
Mount rotation (sensor frame to base_footprint FLU).
FAcresLidarPattern::Beam#
Direction (unit) and lens origin of a beam in the sensor frame, m.
FAcresLidarPattern::DetectionThresholdCounts#
Signal counts that are detected with DetectionAtSpec probability at the spec point.
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#
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#
One scan, organized as the game's PCD (cell = column x rings + ring).
| Name | Type | Unit | Default | Description |
|---|---|---|---|---|
RangeM |
std::vector<float> |
m | Range along the beam from the lens centre per cell, m; NaN without a return. | |
Points |
std::vector<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<uint8_t> |
What each beam hit: a scene material index, LidarTerrain, LidarVehicleBox or LidarNoReturn. | ||
Returns |
int |
0 |
Beams with a return. |
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#
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::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. |
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.