AcresSensors.h#
Acres/Source/Acres/AcresSensors.h Generated
Synthetic sensor episode recorder for the ACRE tractor: truth, actions, GNSS, IMU, LiDAR, camera and CAN.
The 120 Hz physics step is the clock. Truth, actions, IMU, GNSS and CAN rows are made on the physics thread (Unreal's Chaos physics runs on its own thread; AsyncPhysicsTickActor in AcresVehicle.cpp calls PhysicsSample once per fixed step). LiDAR scans and camera captures need the Unreal world and the renderer, so they run on the game thread (Unreal's main thread, where actors tick) at a pose stamped by the physics thread. Heavy work (PLY/PNG encoding, the camera sensor model) runs on Unreal's thread pool, and every text row goes through one bounded writer thread (an FRunnable, Unreal's thread-body interface) into <root>/episode-NNN/<stream>.jsonl.
With a live stream attached (SetStream, AcresSensorStream.h: -SensorStream=) the same INS epochs, organized LiDAR clouds and processed camera images also go to a local client (the ROS 2 bridge), with or without the files (SetFileOutput).
Output frames are ENU (east, north, up) for world quantities and body FLU (forward, left, up) for sensor quantities, in SI units. Unreal itself uses centimetres and a left-handed world with X east, Y south, Z up in this project; the recorder converts at the boundary. Nothing here applies forces to the vehicle.
The per-sensor models live in AcresGnssModel.h (receiver), AcresLidarModel.h (radiometry and returns), AcresLidarGpu.h (GPU ray tracing) and AcresCameraModel.h (lens and image sensor). Configuration comes from Content/Simulation/sensors.json plus -Sensor* command-line flags. All noise is seeded, so an episode can be reproduced exactly from its seed.
| Name | Type | Unit | Default | Description |
|---|---|---|---|---|
UsSurveyFootM |
inline constexpr double |
m | 1200. / 3937. |
Length of one US survey foot in metres (exactly 1200/3937). |
IndianaWestFeetToGeographic#
Converts EPSG:2968 grid coordinates (NAD83(HARN) / Indiana West, US survey feet) to geographic coordinates.
Inverse Transverse Mercator on the GRS80 ellipsoid using the Snyder (1987) series, lat0 37.5 deg, lon0 -87.0833 deg, k0 0.999966667, false easting 900000 m, false northing 250000 m. Sub-millimetre this close to the central meridian.
| Argument | Description |
|---|---|
EastingFt |
Grid easting in US survey feet. |
NorthingFt |
Grid northing in US survey feet. |
LatitudeDeg |
Output NAD83(HARN) latitude in degrees. |
LongitudeDeg |
Output NAD83(HARN) longitude in degrees (negative west). |
GeographicToIndianaWestFeet#
Forward EPSG:2968 projection: NAD83(HARN) latitude/longitude to Indiana West grid feet (Snyder 1987 series).
| Argument | Description |
|---|---|
LatitudeDeg |
NAD83(HARN) latitude in degrees. |
LongitudeDeg |
NAD83(HARN) longitude in degrees (negative west). |
EastingFt |
Output grid easting in US survey feet. |
NorthingFt |
Output grid northing in US survey feet. |
WriteBytes#
Writes a byte buffer to a file, replacing it. Used for the PLY/PNG sensor files and the camera self-test.
| Argument | Description |
|---|---|
Path |
Destination file. |
Data |
Bytes to write. |
Bytes |
Number of bytes. |
Returns: True if the file was opened and written without error.
Note
Thread-safe (called from thread-pool tasks).
IsTreeActor#
Whether an actor holds trees (instanced tree meshes whose crowns the LiDAR and GNSS proxies model): the woodland plantings (tag "woodland"), the surveyed single trees (REF_ACRE_Planting_MeasuredTrees: tag "ACRETree") and, for levels saved before those tags, any vegetation actor (tag "ACREVegetation", not a trunk-collision "ACREObstacle", shrub or crop actor) whose instanced meshes are tree assets (/Game/ACRE/Trees/). The actor's name is not used: in a cooked game it is the class name plus a number (BP_ReferenceInstances_C_2), not the editor label.
| Argument | Description |
|---|---|
Actor |
Any actor (null is not a tree). |
Returns: True for a tree-holding actor.
FAcresPcg32#
Reproducible random numbers: PCG32 (PCG-XSH-RR, O'Neill 2014) plus Box-Muller Gaussians.
Every noise source in the recorder owns one of these, seeded from sensors.json "seed" so an episode can be replayed bit for bit.
Example
| Name | Type | Unit | Default | Description |
|---|---|---|---|---|
State |
uint64 |
0 |
64-bit LCG state. | |
Inc |
uint64 |
0 |
Stream increment (always odd); different increments give independent streams. |
FAcresPcg32::Seed#
Seeds the generator the way the PCG reference pcg32_srandom_r does.
| Argument | Description |
|---|---|
InitState |
Starting state (the recorder uses seed + k * 1009 per stream). |
InitSeq |
Stream selector; the increment becomes 2 * InitSeq + 1. |
FAcresPcg32::Next#
Returns the next 32-bit output and advances the state.
FAcresPcg32::Uniform#
Uniform double in (0, 1), never exactly 0 or 1, so log(Uniform()) is safe.
FAcresPcg32::Gaussian#
Standard normal draw (mean 0, sigma 1) from the cosine branch of Box-Muller; consumes two uniforms.
FAcresSensorConfig#
All recorder settings, loaded from Content/Simulation/sensors.json and the -Sensor* command line.
Units follow the suffix: Hz, seconds (S), metres (M), m/s2, rad/s, degrees (Deg), pixels. Extrinsics are FLU metres from the chassis reference origin (the actor origin, not the centre of mass).
Example
const FAcresSensorConfig Config = FAcresSensorConfig::Load();
auto Recorder = MakeShared<FAcresSensorRecorder>(Pawn, Body, Farm, Ignored, Config);
| Name | Type | Unit | Default | Description |
|---|---|---|---|---|
Seed |
int |
42 |
Master seed for every PCG32 stream (GNSS, IMU, LiDAR, camera noise, GNSS constellation). | |
DelayS |
double |
s | .05 |
Modelled transport latency added to every delayed stream (GNSS, IMU, LiDAR, camera), seconds. |
Gnss, Imu, Lidar, Camera, Can |
bool |
Per-stream enable switches (sensors.json "<stream>.enabled", or -SensorNo<Stream>). | ||
GnssHz, ImuHz, LidarHz, CameraHz, CanHz |
double |
Sample rates in Hz, each 1-120. The default camera rate matches the Polaris recording profile. | ||
GnssStdM, AccelStdMps2, GyroStdRadps, AccelBiasMps2, GyroBiasRadps, LidarStdM |
double |
GnssStdM: legacy GNSS noise field, kept in the config export but unused (the receiver model sets the noise). AccelStdMps2 / GyroStdRadps: IMU white noise per axis per sample (m/s2, rad/s). AccelBiasMps2 / GyroBiasRadps: sigma of the constant per-episode IMU bias draw (m/s2, rad/s). LidarStdM: LiDAR range-noise floor, metres (the radiometric model adds low-SNR noise on top). | ||
LidarRangeM |
double |
m | 60 |
Maximum range, m (1-200). |
LidarElevationMinDeg |
double |
° | -20 |
Elevation of the lowest and highest ring. |
LidarElevationMaxDeg |
double |
° | 10 |
See above. |
LidarColumns |
int |
180 |
Azimuth steps over 360 deg (4-720). | |
LidarRings |
int |
8 |
Elevation rings, evenly spaced (1-32). | |
CameraWidth, CameraHeight |
int |
Delivered camera image size in pixels (64-4096 x 64-2160). | ||
CameraHfovDeg |
double |
° | 90 |
Pinhole-equivalent horizontal field of view that defines fx, degrees (20-120). |
CameraExposure |
FString |
TEXT("volume") |
Exposure mode for the scene capture. "volume" leaves exposure to the level's post-process volume (the look of the review camera). "physical" fixes EV100 = log2(N^2 / t * 100 / ISO) like a real camera, from CameraFstop, CameraShutterS and CameraIso. "copy" copies the highest-priority unbound post-process volume onto the capture component. Load applies the -SensorCameraExposure= override, so this is always the mode in use. |
|
CameraFstop |
double |
8 |
Aperture N. | |
CameraShutterS |
double |
s | 1. / 333 |
Exposure time, s (also the dark-current integration time). |
CameraIso |
double |
100 |
ISO; gain in the sensor model = ISO / base ISO. | |
CameraTemporal |
bool |
true |
Temporal history for the camera render. Lumen GI and sky occlusion, TSR anti-aliasing and volumetric clouds all accumulate over frames. A lone on-demand capture has no history (black shadows, smeared clouds), so with this on the capture renders on several frames, like the main view. Costs extra scene renders (see CameraWarmupFrames). | |
CameraWarmupFrames |
int |
2 |
With temporal history on: render the capture only on the N frames leading up to each sample (Lumen and TSR improve with more history). 0 = render every frame. Clamped to 0-16. The default uses two renders per sample at 10 Hz, matching Polaris; settings can trade additional GPU time for more temporal convergence. | |
CameraModel |
FAcresCameraModelConfig |
Lens, rolling shutter and photometric post-processing (AcresCameraModel.h). | ||
LidarModel |
FAcresLidarModelConfig |
Intensity, multi-return and dropout model (AcresLidarModel.h). | ||
GnssModel |
FAcresGnssModelConfig |
RTK fix states, Gauss-Markov errors, sky obstruction and datum chain (AcresGnssModel.h). | ||
GnssFlu, ImuFlu, LidarFlu, CameraFlu |
FVector |
Sensor mounting points in body FLU metres from the chassis reference origin (each within 10 m). With MountFrame "base_footprint" the file gives them from the vehicle's base_footprint (the rear-axle midpoint on the ground, as the vehicle's URDF) and Load adds BaseFootprintFlu. | ||
LidarRpyDeg, CameraRpyDeg |
FVector |
Mount rotations of the LiDAR and the camera (lidar.rpy_deg, camera.rpy_deg): roll, pitch, yaw, deg, the ROS convention (fixed axes x, y, z of the body FLU frame, R = Rz(yaw) Ry(pitch) Rx(roll), positive pitch looks down). Zero: the sensor frame is parallel to the body. | ||
MountFrame |
FString |
TEXT("chassis") |
"chassis" (default) or "base_footprint": where the mounting points in the file are measured from. | |
BaseFootprintFlu |
FVector |
FVector::ZeroVector |
The vehicle's base_footprint in the chassis FLU frame, m (the pawn's rear-axle midpoint on the ground; set by Load from its argument). The INS reports the pose of this point. | |
LidarElevationsDeg |
TArray<double> |
° | LiDAR beam table (lidar.elevations_deg): the elevation of every ring, deg, in the sensor's ring order (the column order of an organized cloud). Empty: LidarRings rings evenly spaced from min to max. The RoboSense Helios table of the Purdue Ranger comes from its recorded clouds (sensors_polaris.json). | |
LidarClockwise |
bool |
false |
Column direction (lidar.azimuth_order): false "ccw" (column 0 forward, counter-clockwise, the default) or true "cw" (column k at -360 k / columns deg, the row order of rslidar_sdk's organized clouds). | |
LidarAzimuthOffsetsDeg |
TArray<double> |
° | Horizontal offset of every ring from its column's azimuth (lidar.azimuth_offsets_deg), deg counter-clockwise, in ring order; empty = none. The Helios' two laser banks sit +3.9..+5.1 deg (even rings) and -3.6..-5.0 deg (odd). | |
LidarLensCenterM |
double |
m | 0 |
Lens centre distance from the spin axis (lidar.lens_center_m), m: each beam starts there, at the column's azimuth, and points are written as rslidar_sdk does (range along the beam plus the lens offset). 0 = on the axis. |
LidarSelfReturns |
FString |
The vehicle seen by its own LiDAR (lidar.self_returns): a file of 4 x columns x rings float32 (per cell: the probability that the beam returns from the body, the body's range, m, and intensity, and the probability that the body blocks the beam without a return), relative to Content/Simulation. Empty = none (the vehicle's meshes are skipped by the traces). | ||
LidarDelayS |
double |
s | -1 |
Delivery delay of LiDAR rows (lidar.delay_s), s; negative = delay_s. The Helios reaches the bag 11-12 ms after its stamp. |
LidarOutput |
FString |
TEXT("ply") |
Point files (lidar.output): "ply" (default), "pcd" (an organized PCD laid out as the vehicle's PointCloud2: HEIGHT = columns, WIDTH = rings, x y z intensity float32, NaN where a beam has no return) or "both". | |
LidarFrameId |
FString |
TEXT("lidar") |
Frame id of the LiDAR's clouds (lidar.frame_id; "lidar" on the Ranger). | |
Ins |
bool |
false |
INS (OxTS-like) stream, "ins" block: enabled, rate, Hz; reported point (ins.position_flu_m: the INS output point, base_footprint on the Ranger); position error as a Gauss-Markov process (sigma, m; correlation time, s) plus white noise, m; heading and roll / pitch errors, deg (1 sigma, Gauss-Markov with the same time); white velocity, acceleration and angular-rate noise (m/s, m/s2, rad/s); latitude / longitude datum ("nad83" = NAD83(2011) as an RTK fix, or "wgs84_g2139"); UTM zone of the odometry. | |
SourcePath |
FString |
The sensors.json actually loaded. | ||
SourceSha1 |
FString |
SHA-1 of its text, written to episode.json. | ||
ProfileName |
FString |
TEXT("tractor-default") |
ProfileName: the sensor profile the files name ("profile" of sensors.json or the vehicle overlay: tractor-default, polaris). bProfileValidated: the profile's camera and LiDAR were validated against the real sensors ("profile_validated"; the Polaris: Calibration/Polaris/camera_results.md, lidar_results.md). | |
ProfileChanges |
TArray<FString> |
Camera and LiDAR settings that differ from the profile as shipped (Content/Simulation/sensors.json plus the overlay, no command line), as JSON paths such as "camera.width" or "camera.model.noise": what the menu's session file or command-line flags changed. Empty when the camera and LiDAR record the profile's data. |
FAcresSensorConfig::Load#
Loads the configuration, applies command-line overrides and validates it.
Reads Content/Simulation/sensors.json (or the file given by -SensorConfig=), merges a vehicle overlay on top (every key of the overlay replaces the base's, objects merged key by key; the Polaris uses sensors_polaris.json), then applies -SensorSeed=, -SensorDelay=, -Sensor<Stream>Hz=, -SensorLidarColumns=/Rings=/Range=, -SensorCameraWidth=/Height=/Hfov=, -SensorCameraWarmup=, -SensorCameraNoHistory, -SensorCameraExposure=, -SensorNo<Stream>, -SensorNoNoise (no noise in any sensor, camera included) and the model-specific flags of the camera, LiDAR and GNSS configs.
| Argument | Description |
|---|---|
OverlayFile |
Vehicle overlay JSON (empty = none). |
BaseFootprintFlu |
The vehicle's base_footprint in the chassis FLU frame, m (for MountFrame "base_footprint"). |
Returns: The validated configuration.
Note
Uses checkf (Unreal's assert with a message; active in the Development builds this project packages), so a broken or out-of-range file stops the game instead of recording a bad episode. ProfileChanges is filled by comparing DataSignature with that of the same overlay on the shipped sensors.json without the command line.
FAcresSensorConfig::DataSignature#
The camera and LiDAR settings that define their data (resolution, rate, mount, lens and photometry, capture strategy and exposure; beam table, geometry, radiometry and returns), without the on/off switches and the point-file format.
Returns: {"camera": {...}, "lidar": {...}}.
FAcresSensorConfig::ToJson#
Serialises the configuration (including the three model blocks) as compact JSON for sensors-config.json and the "config" block of episode.json.
Returns: One JSON object as a string.
FAcresSensorPhysicsSample#
One snapshot of the chassis, as handed to the recorder.
On the physics thread every field is filled once per 120 Hz step. On the game thread (GameTick) only PhysicsTimeS, Step, PositionCm, Rotation and VelocityMps are filled, from the latest published telemetry. Positions are Unreal world centimetres (X east, Y south, Z up); velocities are Unreal world axes in m/s.
| Name | Type | Unit | Default | Description |
|---|---|---|---|---|
Dt |
double |
0 |
Physics step, s (1/120). | |
PhysicsTimeS |
double |
s | 0 |
The run's physics clock, s. |
EpisodeTimeS |
double |
s | 0 |
The vehicle's own episode clock, s (restarts on a vehicle reset). |
Step |
uint64 |
0 |
Physics step counter. | |
ResetEpoch |
uint64 |
0 |
Increments when the vehicle is reset (the IMU restarts its finite differences on a change). | |
PositionCm |
FVector |
cm | FVector::ZeroVector |
Actor origin, Unreal world cm. |
VelocityMps |
FVector |
m/s | FVector::ZeroVector |
Chassis linear velocity, Unreal world axes, m/s. |
AngularRadps |
FVector |
rad/s | FVector::ZeroVector |
Chassis angular velocity, Unreal world axes, rad/s. |
CenterOfMassCm |
FVector |
cm | FVector::ZeroVector |
Centre of mass offset from the actor origin in the body frame, cm. |
Rotation |
FQuat |
FQuat::Identity |
Chassis orientation, body to Unreal world. | |
Rpm |
double |
0 |
Engine speed, rev/min. | |
SteerRad |
double |
rad | 0 |
Actual road-wheel steer angle, rad. |
SteerRequestRad |
double |
rad | 0 |
Requested steer angle, rad. Throttle, |
Throttle |
double |
0 |
See above. | |
Brake |
double |
0 |
Pedal commands 0-1. | |
Direction |
double |
1 |
+1 forward, -1 reverse. | |
MassKg |
double |
kg | 0 |
Chassis mass, kg. |
FarmTimeS |
double |
s | 0 |
Farm simulation clock, s. |
BunkerKg |
double |
kg | 0 |
Harvested grain on board, kg. |
Gear |
int |
0 |
Selected gear, 1-based. | |
ControlSource |
const TCHAR* |
TEXT("manual") |
Who is driving: "manual", "replay", "scripted_test", "route_review" or "benchmark". | |
Wheels |
std::array<AcresSim::FWheelState, 4> |
Per-wheel state from the vehicle model (contact, normal load, slip, sinkage, surface). |
FAcresSensorRecorder#
Records one sensor episode at a time for the tractor.
AAcresVehiclePawn creates one recorder in BeginPlay with FAcresSensorConfig::Load(). Start (game thread, F6 or -SensorRecord) opens <root>/episode-NNN/; after that the pawn calls PhysicsSample from its fixed-step physics callback and GameTick from its per-frame Tick. Finish (game thread, F6 again or destruction) drains everything and writes the final episode.json.
The recorder is itself the writer thread's body (FRunnable::Run). Rows are formatted where they are produced, held in a latency buffer until their available time, and then queued to the writer. Queues are bounded; anything dropped is counted in episode.json "dropped" instead of stretching time.
Example
auto Recorder = MakeShared<FAcresSensorRecorder>(this, Body, Farm, {this}, FAcresSensorConfig::Load());
const FString Error = Recorder->Start(FPaths::ProjectSavedDir() / TEXT("sensors"));
// ... physics thread: Recorder->PhysicsSample(Sample); game thread: Recorder->GameTick(Latest);
Recorder->Finish();
| Name | Type | Unit | Default | Description |
|---|---|---|---|---|
Config |
const FAcresSensorConfig |
The configuration this recorder was built with (read-only). |
FAcresSensorRecorder::FAcresSensorRecorder#
Builds the recorder. Does not start recording.
Also self-checks the frame conversion, reads the georeference origin from Content/Simulation/ACRE/site.json and loads the 4 m ground-cover raster (field-grid.json + cover.u8) used for LiDAR ground materials.
| Argument | Description |
|---|---|
Owner |
The tractor actor; owns the camera capture component and supplies the world. |
Body |
The chassis physics component the camera is attached to and reads angular velocity from. |
Farm |
Shared farm state (crop proxies for the CPU LiDAR, water grid for wetness). May be null. |
IgnoredActors |
Actors the LiDAR must see through (the tractor and its trailer). |
Config |
Settings; copied into the public Config member. |
FAcresSensorRecorder::~FAcresSensorRecorder#
Calls Finish, then waits for any thread-pool task still using the recorder, so a recording in progress is closed cleanly and nothing touches the object after it is freed.
FAcresSensorRecorder::Start#
Starts a new episode.
Creates <Root>/episode-NNN (NNN one above the highest existing number) with camera/ and lidar/ subfolders, opens the seven .jsonl streams, writes sensors-config.json, seeds the RNG streams, draws the IMU bias, gathers LiDAR and GNSS obstacle proxies, creates the camera capture and render target, starts the writer thread and writes an initial episode.json with state "recording".
| Argument | Description |
|---|---|
Root |
Parent folder for episodes (default <vehicle output>/sensors, or -SensorOutput=). |
Returns: Empty string on success, otherwise a short error message.
Note
Game thread only.
FAcresSensorRecorder::Finish#
Stops the episode and flushes everything.
Waits for an in-progress physics sample, finishes the pending camera readback, runs the LiDAR scans that were already stamped, waits for every PLY/PNG encode (no timeout), delivers still-delayed rows with "pending_at_stop":true, stops the writer thread, closes files and writes the final episode.json. Does nothing if not recording.
Note
Game thread only. Blocks the game thread while it drains.
FAcresSensorRecorder::IsRecording#
True between Start and Finish. Safe from any thread.
FAcresSensorRecorder::IsIdle#
True when nothing that fell due is still in flight: no LiDAR scan queued, on the GPU or being encoded, no camera image due, rendering, reading back or being processed. Lockstep (AcresSimControl.h) waits for this before it answers a step, so every sensor output of the steps has gone to the stream. Game thread.
FAcresSensorRecorder::SensorProfile#
The episode's sensor profile: "<profile>-calibrated" (a validated profile recorded as validated, with the calibrated sensor render profile), "<profile>" (an unvalidated one such as tractor-default), "<...>-reduced-6gb" (recorded with the low tier's reduced sensor render profile, AcresRenderTier.h) or "custom" (camera or LiDAR settings changed from the profile, or the pinned render settings overridden on the console).
FAcresSensorRecorder::SetMountOffsets#
Hardware shift of the sensor mounts (AcresSimControl.h set_vehicle_shift): offsets added to the camera and LiDAR mount positions (FLU, m) and roll / pitch / yaw (deg) of sensors.json. Scans and images taken from now on use them; the stream's hello keeps the calibrated mounts (as a drifted sensor's description would). Game thread.
FAcresSensorRecorder::PhysicsSample#
Records one physics step.
Writes a truth and an actions row every step, then, when due: a GNSS epoch, an IMU sample, a LiDAR scan request (queued for the game thread) and two CAN frames. Finally delivers delayed rows whose available time has passed.
| Argument | Description |
|---|---|
S |
Fully filled physics sample for this step. |
Note
Physics thread, once per fixed step. time_s in the rows is (steps since Start) x Dt.
FAcresSensorRecorder::GameTick#
Per-frame work on the game thread: camera capture scheduling and readback, finishing GPU LiDAR scans and starting the next queued LiDAR scan.
| Argument | Description |
|---|---|
Latest |
The latest physics telemetry (pose, velocity, step and physics time only). |
Note
Game thread, once per frame.
FAcresSensorRecorder::StatusLabel#
One-line status for the HUD, e.g. "Recording episode-003 | 12.5 s | truth 1500 imu ...".
FAcresSensorRecorder::CopyLivePoints#
Copies the latest scan's points for display.
| Argument | Description |
|---|---|
Out |
Receives the points (sensor FLU metres). |
RangeM |
Receives the configured LiDAR range, m, for scaling the view. |
Note
Thread-safe (takes a lock); the points are replaced by a thread-pool task after each scan is encoded.
FAcresSensorRecorder::CopyLiveCamera#
Copies the latest camera image if it is newer than the caller's copy (compares Frame). Thread-safe.
| Argument | Description |
|---|---|
InOut |
The caller's copy; replaced when a newer image exists. |
Returns: True when InOut was replaced.
FAcresSensorRecorder::SetStream#
Also sends every INS epoch, LiDAR cloud and camera image to a local client (AcresSensorStream.h). Call before Start; null = no stream.
FAcresSensorRecorder::SetFileOutput#
Episode files on (default) or off. Off, the recorder runs for the stream only: no folder, no .jsonl rows, no PLY/PCD/PNG files and no episode.json. Call before Start.
FAcresSensorRecorder::StreamHello#
The stream's Hello JSON: sensor rates, the LiDAR layout, the camera's output intrinsics and distortion, and the mount poses relative to base_footprint (FLU m, ROS roll/pitch/yaw deg). Call after Start (the camera model exists then).
| Argument | Description |
|---|---|
AgentName |
The agent's name. |
Vehicle |
"maxxum" or "polaris". |
Returns: One JSON object as a string.
FLivePoint#
One point of the latest LiDAR scan for the live HUD view.
| Name | Type | Unit | Default | Description |
|---|---|---|---|---|
X, Y, Z |
float |
Point position in the sensor FLU frame, metres (x forward, y left, z up). | ||
Class |
uint8 |
Semantic class id (see episode.json lidar.classes). | ||
Intensity |
uint8 |
Calibrated reflectivity byte 0-255. |
FLiveImage#
The latest camera image for the live HUD view: the processed sensor image (distortion, noise) at half resolution.
| Name | Type | Unit | Default | Description |
|---|---|---|---|---|
Width, Height |
int |
Width, Height: pixels. Frame: capture counter (changes with every new image; 0 = none yet). |