CARLA
Loading...
Searching...
No Matches
CarlaEngine.h
Go to the documentation of this file.
1// Copyright (c) 2026 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
7#pragma once
8
15
22#if WITH_ROS2
23 #include <carla/ros2/ROS2.h>
24#endif
26
27#include <util/ue-header-guard-begin.h>
28#include "Misc/CoreDelegates.h"
29#include "Engine/World.h"
30#include <util/ue-header-guard-end.h>
31
32#include <atomic>
33#include <mutex>
34#include <optional>
35
36class UCarlaSettings;
37struct FEpisodeSettings;
38
40{
41public:
42
43 static uint64_t FrameCounter;
44
46
47 void NotifyInitGame(const UCarlaSettings &Settings);
48
49 void NotifyBeginEpisode(UCarlaEpisode &Episode);
50
51 void NotifyEndEpisode();
52
53 const FCarlaServer &GetServer() const
54 {
55 return Server;
56 }
57
59 {
60 return Server;
61 }
62
67
68 void SetRecorder(ACarlaRecorder *InRecorder)
69 {
70 Recorder = InRecorder;
71 }
72
73 static uint64_t GetFrameCounter()
74 {
76 }
77
78 static uint64_t UpdateFrameCounter()
79 {
81 #if defined(WITH_ROS2)
83 if (ROS2->IsEnabled())
84 ROS2->SetFrame(FCarlaEngine::FrameCounter);
85 #endif
87 }
88
89 static void ResetFrameCounter(uint64_t Value = 0)
90 {
92 #if defined(WITH_ROS2)
94 if (ROS2->IsEnabled())
95 ROS2->SetFrame(FCarlaEngine::FrameCounter);
96 #endif
97 }
98
99 std::shared_ptr<carla::multigpu::Router> GetSecondaryServer()
100 {
101 return SecondaryServer;
102 }
103
104 /// False on a Multi-GPU secondary. Known from NotifyInitGame on, before any
105 /// actor of the first map begins play.
106 bool IsPrimaryServer() const
107 {
108 return bIsPrimaryServer;
109 }
110
111private:
112
113 void OnPreTick(UWorld *World, ELevelTick TickType, float DeltaSeconds);
114
115 void OnPostTick(UWorld *World, ELevelTick TickType, float DeltaSeconds);
116
117 void OnEpisodeSettingsChanged(const FEpisodeSettings &Settings);
118
119 /// Applies FEpisodeSettings::bDeterministicCollisions to the world about to
120 /// be created.
121 void OnPreWorldInitialization(UWorld *World, const UWorld::InitializationValues IVS);
122
124
125 /// Secondary only: binds a sensor replayed from the primary to the stream
126 /// its clients were given (see carla::multigpu::SensorStreamRegistry).
127 void BindReplayedSensor(uint32_t PrimaryActorId, uint32_t LocalActorId, bool bCreated);
128
129 /// Primary only: keeps processing RPC until every secondary sent LOAD_MAP
130 /// reports its episode ready (bounded by a timeout).
132
133 /// Secondary only (FCoreDelegates::OnBeginFrame, before the engine computes
134 /// this frame's delta): waits for the primary's next frame and makes its
135 /// delta this engine frame's time step.
136 void OnBeginFrame();
137
138 /// Secondary only: plays the primary's frame on the frame OnBeginFrame
139 /// prepared, with the primary's clocks and settings.
140 void PlayPrimaryFrame(UWorld &World, float DeltaSeconds, FFrameData &Frame);
141
143
144 /// Secondary only: tells the primary this episode is ready, which also
145 /// makes it send a full resync.
146 void SendEpisodeReady();
147
148 /// Sends EPISODE_READY once the world's generated content has finished spawning.
150
151 /// Secondary only: stops mirroring the primary for good (it is gone, or
152 /// this server cannot load its map). Never call it holding FrameToProcessMutex.
153 void DetachFromPrimary(const char *Reason);
154
155 /// Secondary only: puts back any mirror that moved since its frame was
156 /// played (a local mover the mirror does not stop), right before capture.
157 void RestorePlayedPoses();
158
159 bool bIsRunning = false;
160
161 bool bSynchronousMode = false;
162
163 bool bMapChanged = false;
164
166
168
170
172
174
175 FDelegateHandle OnPreTickHandle;
176
177 FDelegateHandle OnPostTickHandle;
178
180
181 FDelegateHandle OnBeginFrameHandle;
182
183 FDelegateHandle OnTravelFailureHandle;
184
185 // Primary, game thread: the world's clocks recorded in OnPreTick of the
186 // current frame, before UWorld::Tick accumulates them; sent in OnPostTick.
188 {
189 float DeltaSeconds = 0.0f;
190 double TimeSeconds = 0.0;
192 double RealTimeSeconds = 0.0;
193 double AudioTimeSeconds = 0.0;
194 float TimeDilation = 1.0f;
195 };
196 std::optional<FPendingFrameTime> PendingFrameTime;
197
198 // Secondary, game thread: the primary frame OnBeginFrame prepared this
199 // engine frame for, the last one played, and whether this engine frame
200 // played one (only then does it capture and broadcast).
201 std::optional<uint64_t> PreparedFrame;
202 std::optional<uint64_t> LastPlayedFrame;
208 uint64_t DeltaMismatches = 0u;
211
212 // Secondary: set from the game thread or the multi-GPU command thread when
213 // this server misses primary state; OnBeginFrame then asks for a resync.
214 std::atomic<bool> bResyncRequested{false};
215
216 // Secondary: frames queued in FramesToProcess, readable without the lock.
217 std::atomic<size_t> QueuedFrames{0u};
218
219 // Secondary, game thread: set when loading the primary's map failed.
220 bool bTravelFailed = false;
221
223
224 /// Value of p.Chaos.AccelerationStructureUseDynamicTree before deterministic
225 /// collisions changed it; unset while they are off.
227
228 bool bIsPrimaryServer = true;
229
230 // Set from the router's io-context thread (ConnectSession/HandleResponse
231 // callbacks); consumed and cleared from the game thread in OnPostTick.
232 std::atomic<bool> bNewConnection{false};
233
234 std::unordered_map<uint32_t, uint32_t> MappedId;
235
236 // Secondary, game thread: what playing the primary's frames keeps between
237 // them (mirrors spawned, attachments pending, poses just set).
239
240 // Secondary, game thread: mirrors something moved between playing a frame
241 // and its capture, in this episode, and the classes already reported.
242 uint64_t RestoredPoses = 0u;
244
245 // Secondary only. Resolved and reset from the multi-GPU command thread
246 // (GET_TOKEN, LOAD_MAP), bound from the game thread; internally synchronized.
248
249 std::shared_ptr<carla::multigpu::Router> SecondaryServer;
250 std::shared_ptr<carla::multigpu::Secondary> Secondary;
251
252 std::vector<FFrameData> FramesToProcess;
254
255 // Tracks whether this secondary is currently considered behind the
256 // primary's SEND_FRAME cadence, so the backlog warning logs on state
257 // change only rather than once per queued frame.
259
260 // Frames from the primary that could not be parsed completely in this
261 // episode, and whether this episode already reported frames written by
262 // another build; guarded by FrameToProcessMutex.
263 uint64_t DroppedFrames = 0u;
264 bool bWarnedFrameFormat = false;
265
266 // Game thread only: BindReplayedSensor warns once per opened episode.
268
270 // What came with it: a world the primary generated (guarded like it).
272 std::atomic<bool> bLoadMapPending{false};
273
274 // Secondary, game thread: EPISODE_READY waits for generated content (OpenDRIVE street furniture).
277
278 // Secondary, game thread: the map of the load started last.
279 FString LoadingMap;
280
281 // SensorStreams epoch of PendingLoadMap (guarded by FrameToProcessMutex) and
282 // of the map load the game thread started last (game thread only).
285
286 // Primary's id of PendingLoadMap and of the load started last, echoed in
287 // the episode-ready message; same guards as the epochs above.
290};
291
292// Note: this has a circular dependency with FCarlaEngine; it must be included late.
Recorder for the simulation.
void SendEpisodeReadyWhenContentReady()
Sends EPISODE_READY once the world's generated content has finished spawning.
void OnEpisodeSettingsChanged(const FEpisodeSettings &Settings)
uint64_t RestoredPoses
FDelegateHandle OnEpisodeSettingsChangeHandle
std::shared_ptr< carla::multigpu::Router > SecondaryServer
uint64_t DeltaMismatches
FString LoadingMap
std::atomic< size_t > QueuedFrames
std::mutex FrameToProcessMutex
void OnPreTick(UWorld *World, ELevelTick TickType, float DeltaSeconds)
TSet< FName > RestoredPoseClasses
bool bWarnedSensorBindRefused
static uint64_t FrameCounter
Definition CarlaEngine.h:43
carla::multigpu::SensorStreamRegistry::epoch_type PendingLoadEpoch
static uint64_t GetFrameCounter()
Definition CarlaEngine.h:73
void ResetSimulationState()
const FCarlaServer & GetServer() const
Definition CarlaEngine.h:53
void MirrorPrimarySettings(const carla::multigpu::FrameTime &Time)
FWorldObserver WorldObserver
uint64_t DroppedFrames
FCarlaServer Server
FDelegateHandle OnBeginFrameHandle
static void ResetFrameCounter(uint64_t Value=0)
Definition CarlaEngine.h:89
bool bWarnedNoSensorTicks
void OnBeginFrame()
Secondary only (FCoreDelegates::OnBeginFrame, before the engine computes this frame's delta): waits f...
void NotifyEndEpisode()
std::atomic< bool > bResyncRequested
double LastOwnClockFrameSeconds
bool bFramesToProcessBacklogged
std::unordered_map< uint32_t, uint32_t > MappedId
double EpisodeReadyPendingSince
bool bWarnedFrameFormat
std::shared_ptr< carla::multigpu::Router > GetSecondaryServer()
Definition CarlaEngine.h:99
FEpisodeSettings CurrentSettings
carla::multigpu::SensorStreamRegistry::epoch_type LoadingEpoch
bool bEpisodeReadyPending
static uint64_t UpdateFrameCounter()
Definition CarlaEngine.h:78
void SendEpisodeReady()
Secondary only: tells the primary this episode is ready, which also makes it send a full resync.
std::atomic< bool > bLoadMapPending
UCarlaEpisode * CurrentEpisode
FMirrorState MirrorState
FDelegateHandle OnPreWorldInitializationHandle
std::vector< FFrameData > FramesToProcess
void DetachFromPrimary(const char *Reason)
Secondary only: stops mirroring the primary for good (it is gone, or this server cannot load its map)...
void BindReplayedSensor(uint32_t PrimaryActorId, uint32_t LocalActorId, bool bCreated)
Secondary only: binds a sensor replayed from the primary to the stream its clients were given (see ca...
carla::multigpu::LoadMapExtras PendingLoadMapExtras
std::atomic< bool > bNewConnection
std::optional< uint64_t > PreparedFrame
void NotifyBeginEpisode(UCarlaEpisode &Episode)
void NotifyInitGame(const UCarlaSettings &Settings)
TOptional< int32 > DynamicTreeBeforeDeterministicCollisions
Value of p.Chaos.AccelerationStructureUseDynamicTree before deterministic collisions changed it; unse...
carla::multigpu::load_map_id_type LoadingLoadMapId
std::optional< FPendingFrameTime > PendingFrameTime
ACarlaRecorder * Recorder
void SetRecorder(ACarlaRecorder *InRecorder)
Definition CarlaEngine.h:68
void PlayPrimaryFrame(UWorld &World, float DeltaSeconds, FFrameData &Frame)
Secondary only: plays the primary's frame on the frame OnBeginFrame prepared, with the primary's cloc...
bool bIsPrimaryServer
bool bWarnedUntimedFrame
bool bWarnedUnpairedFrame
bool bFramePlayedThisTick
double LastResyncRequestSeconds
FCarlaServer & GetServer()
Definition CarlaEngine.h:58
FString PendingLoadMap
bool bSynchronousMode
void WaitForSecondaryEpisodes()
Primary only: keeps processing RPC until every secondary sent LOAD_MAP reports its episode ready (bou...
FDelegateHandle OnPreTickHandle
std::optional< uint64_t > LastPlayedFrame
void RestorePlayedPoses()
Secondary only: puts back any mirror that moved since its frame was played (a local mover the mirror ...
carla::multigpu::SensorStreamRegistry SensorStreams
bool bWasConnectedToPrimary
FDelegateHandle OnTravelFailureHandle
FDelegateHandle OnPostTickHandle
std::shared_ptr< carla::multigpu::Secondary > Secondary
bool IsPrimaryServer() const
False on a Multi-GPU secondary.
UCarlaEpisode * GetCurrentEpisode()
Definition CarlaEngine.h:63
void OnPreWorldInitialization(UWorld *World, const UWorld::InitializationValues IVS)
Applies FEpisodeSettings::bDeterministicCollisions to the world about to be created.
carla::multigpu::load_map_id_type PendingLoadMapId
void OnPostTick(UWorld *World, ELevelTick TickType, float DeltaSeconds)
Serializes and sends all the actors in the current UCarlaEpisode.
A simulation episode.
Global settings for CARLA.
Secondary-side map from a primary sensor actor to its local stream, exposed to clients only through a...
static std::shared_ptr< ROS2 > GetInstance()
Definition ROS2.h:61
uint32_t load_map_id_type
Identifies one LOAD_MAP broadcast.
Definition commands.h:46
What a Multi-GPU secondary keeps between the primary frames it plays.
Definition FrameData.h:59
Frame data packet 25: the primary's clocks and episode settings for one frame.
Definition frameTime.h:20
What a LOAD_MAP carries besides the map: for a world the primary generated from OpenDRIVE (generate_o...
Definition commands.h:51