Skip to content

AcresSensorStream.h#

Acres/Source/Acres/AcresSensorStream.h Generated

Binary sensor stream: one vehicle's heavy sensor data (full organized LiDAR clouds, camera images) and its 100 Hz INS epochs, live, as length-prefixed binary frames over a local TCP socket. The ROS 2 bridge (ROS/acres_sim, the sim_bridge executable) turns them into sensor_msgs; the JSON RL bridge (AcresRlBridge.h) carries the drive-by-wire commands and reports next to it.

-SensorStream=<port>               agent 0 (or an agent's "sensor_stream" JSON key)
-SensorStreams=5601,5602           one port per agent, by index

The socket listens on 127.0.0.1 only. Streaming starts the vehicle's sensor recorder (AcresSensors.h) without files unless -SensorRecord is also given, and turns the INS stream on for a vehicle whose overlay has none (the Maxxum), reported at base_footprint.

Frame = 32-byte header + payload, little-endian:

| offset | type | field | |---|---|---| | 0 | char[4] | magic "TSS1" | | 4 | uint16 | frame type (EFrame) | | 6 | uint16 | flags (0) | | 8 | uint32 | sequence number (per stream, all types) | | 12 | uint32 | payload bytes | | 16 | float64 | stamp: simulation time of the data, s (the world's physics clock, shared by every vehicle) | | 24 | float64 | publish time: CLOCK_MONOTONIC of this machine when the frame was queued, s (for latency) |

Payloads:

  • Hello (1), sent first on every connection: UTF-8 JSON with the agent, vehicle, sensor rates, LiDAR layout, camera intrinsics and distortion, and every mount pose relative to base_footprint (FAcresSensorRecorder::StreamHello).
  • Clock (2), every physics step (120 Hz): float64 the vehicle's own physics time, s. The header stamp is the world time; their difference converts the vehicle times of the JSON bridge's DBW reports.
  • Ins (3), at ins.hz: InsFields float64 values, in the order of EIns.
  • Lidar (4), per scan: uint32 columns (the cloud's height), uint32 rings (width), uint32 point step (16), uint32 0; then columns x rings x (x, y, z, intensity) float32 in the sensor frame (FLU, m), NaN xyz where a beam has no return (the vehicle's rslidar_sdk layout). Stamp = end of the sweep.
  • Camera (5), per image: uint32 width, uint32 height, uint32 encoding (1 = bgr8), uint32 row step; then the processed sensor image (lens distortion, rolling shutter, noise), row-major, top row first. Stamp = the render's physics time.
  • Barrier (6), lockstep only (AcresSimControl.h): uint64 the world step a step request reached. Every frame the steps produced (clock, INS, LiDAR, camera) was queued before it. Stamp = the vehicle's latest physics time.

Flow control: one client at a time (a new one waits until the old one disconnects). Frames are queued only while a client is connected; with more than MaxQueuedBytes queued, LiDAR and camera frames are dropped (counted) rather than delaying everything else. The sender is its own thread (FRunnable), so a slow client never blocks the physics, game or render threads.

Name Type Unit Default Description
MaxQueuedBytes static constexpr int64 96ll &lt;&lt; 20 Queued bytes above which LiDAR and camera frames are dropped.

FAcresSensorStream#

Opens the listening socket on 127.0.0.1 and starts the sender thread.

Argument Description
Port TCP port (1-65535).
Name Agent name, for the log.
FAcresSensorStream(int Port, const FString& Name);

~FAcresSensorStream#

Stops the thread and closes the sockets.

~FAcresSensorStream();

SetHello#

Sets the Hello JSON sent to every new client (FAcresSensorRecorder::StreamHello). Any thread.

void SetHello(const FString& Json);

SetTimeOffset#

Sets the world time minus the vehicle's physics time, s: added to every stamp given in vehicle time. The pawn sets it once, at its first physics step.

void SetTimeOffset(double OffsetS) ;

TimeOffset#

World time minus vehicle time, s.

double TimeOffset() const ;

Publish#

Queues one frame (copies the payload). Any thread; does nothing without a client.

Argument Description
Type Frame type.
VehicleTimeS Stamp in the vehicle's physics time, s (the time offset is added).
Head Optional leading payload bytes (a small fixed header), may be null.
HeadBytes Their length.
Body Payload body bytes.
BodyBytes Their length.
void Publish(EFrame Type, double VehicleTimeS, const void* Head, int64 HeadBytes, const void* Body, int64 BodyBytes);

PublishClock#

Queues a Clock frame for this physics step. Physics thread.

void PublishClock(double VehicleTimeS);

PublishBarrier#

Queues a Barrier frame (lockstep: everything of the steps up to Step went before it). Game thread.

Argument Description
Step The world step the step request reached.
VehicleTimeS The vehicle's latest physics time, s (the stamp).
void PublishBarrier(uint64 Step, double VehicleTimeS);

StatsText#

One-line statistics (frames, MB, drops per type), e.g. for the log.

FString StatsText() const;

EFrame#

enum class EFrame : uint16

Frame types (header offset 4).

Value Description
Hello
Clock
Ins
Lidar
Camera
Barrier

EIns#

enum EIns : int

Index of each float64 in an Ins payload. Position and orientation of base_footprint as the INS reports them (with its errors); Truth* are the simulator's exact values for ground truth.

Value Description
UtmE
UtmN
UtmH
UtmQx
UtmQy
UtmQz
UtmQw
VelX
VelY
VelZ
GyroX
GyroY
GyroZ
AccelX
AccelY
AccelZ
Lat
Lon
Height
CovE
CovN
CovU
EnuQx
EnuQy
EnuQz
EnuQw
EnuX
EnuY
EnuZ
FixStatus
GridRotationDeg
UtmZone
TruthEnuX
TruthEnuY
TruthEnuZ
TruthQx
TruthQy
TruthQz
TruthQw
TruthSpeed
InsFields