CARLA
Loading...
Searching...
No Matches
test_multigpu_frame_gate.cpp
Go to the documentation of this file.
1// Copyright (c) 2026 Computer Vision Center (CVC) at the Universitat Autonoma de Barcelona (UAB).
2// This work is licensed under the terms of the MIT license.
3// For a copy, see <https://opensource.org/licenses/MIT>.
4
5#include "test.h"
6
8
9#include <limits>
10
19
20namespace {
21
22 BeginFrameState Steady() {
23 BeginFrameState state;
24 state.connected = true;
25 state.has_episode = true;
26 return state;
27 }
28
29} // namespace
30
31TEST(MultiGpuFrameGate, a_connected_secondary_with_an_episode_waits_for_the_primary) {
32 EXPECT_EQ(DecideBeginFrame(Steady()), BeginFrameAction::Wait);
33}
34
35TEST(MultiGpuFrameGate, a_disconnected_secondary_runs_on_its_own_clock_whatever_else_holds) {
36 BeginFrameState state = Steady();
37 state.connected = false;
38 EXPECT_EQ(DecideBeginFrame(state), BeginFrameAction::OwnClock);
39 state.load_map_pending = true;
40 state.travel_pending = true;
41 EXPECT_EQ(DecideBeginFrame(state), BeginFrameAction::OwnClock);
42}
43
44TEST(MultiGpuFrameGate, never_waits_while_the_primary_waits_for_this_server) {
45 // The primary waits for EPISODE_READY, which only the travel sends: waiting
46 // here during a load would deadlock both servers until the timeout.
47 BeginFrameState travel = Steady();
48 travel.travel_pending = true;
49 EXPECT_EQ(DecideBeginFrame(travel), BeginFrameAction::DontWait);
50
51 BeginFrameState load_map = Steady();
52 load_map.load_map_pending = true;
53 EXPECT_EQ(DecideBeginFrame(load_map), BeginFrameAction::DontWait);
54
55 BeginFrameState no_episode = Steady();
56 no_episode.has_episode = false;
57 EXPECT_EQ(DecideBeginFrame(no_episode), BeginFrameAction::DontWait);
58
59 BeginFrameState exiting = Steady();
60 exiting.exit_requested = true;
61 EXPECT_EQ(DecideBeginFrame(exiting), BeginFrameAction::DontWait);
62}
63
64TEST(MultiGpuFrameGate, a_pending_load_map_takes_precedence_over_a_prepared_frame) {
65 EXPECT_EQ(DecidePreTick(true, true, true, true), PreTickAction::OpenLevel);
66 // Without an episode there is no world to open the level from yet.
67 EXPECT_EQ(DecidePreTick(true, false, false, false), PreTickAction::Skip);
68}
69
70TEST(MultiGpuFrameGate, only_a_prepared_frame_on_the_episode_world_is_played) {
71 EXPECT_EQ(DecidePreTick(false, true, true, true), PreTickAction::Play);
72 EXPECT_EQ(DecidePreTick(false, true, false, true), PreTickAction::Skip);
73 EXPECT_EQ(DecidePreTick(false, true, true, false), PreTickAction::Skip);
74 EXPECT_EQ(DecidePreTick(false, false, true, true), PreTickAction::Skip);
75}
76
77TEST(MultiGpuFrameGate, consecutive_frames) {
78 EXPECT_TRUE(IsConsecutive(41u, 42u));
79 EXPECT_FALSE(IsConsecutive(41u, 41u));
80 EXPECT_FALSE(IsConsecutive(41u, 43u));
81 EXPECT_FALSE(IsConsecutive(std::nullopt, 42u));
82}
83
84TEST(MultiGpuFrameGate, a_gap_asks_for_a_resync_unless_the_frame_is_one) {
85 EXPECT_TRUE(NeedsResync(41u, 43u, false));
86 EXPECT_FALSE(NeedsResync(41u, 43u, true));
87 EXPECT_FALSE(NeedsResync(41u, 42u, false));
88 // The first frame of an episode has nothing to follow.
89 EXPECT_FALSE(NeedsResync(std::nullopt, 42u, false));
90}
91
92TEST(MultiGpuFrameGate, only_finite_non_negative_deltas_become_the_time_step) {
93 EXPECT_TRUE(IsUsableDelta(0.05f));
94 EXPECT_TRUE(IsUsableDelta(0.0f));
95 EXPECT_FALSE(IsUsableDelta(-0.05f));
96 EXPECT_FALSE(IsUsableDelta(std::numeric_limits<float>::infinity()));
97 EXPECT_FALSE(IsUsableDelta(std::numeric_limits<float>::quiet_NaN()));
98}
bool IsConsecutive(std::optional< uint64_t > last_played, uint64_t frame)
Whether frame directly follows the last frame this secondary played.
Definition frameGate.h:69
bool IsUsableDelta(float delta_seconds)
Whether a primary's delta can be this engine frame's time step.
Definition frameGate.h:80
BeginFrameAction DecideBeginFrame(const BeginFrameState &state)
Definition frameGate.h:34
PreTickAction DecidePreTick(bool load_map_pending, bool has_episode, bool frame_prepared, bool episode_world)
Definition frameGate.h:54
BeginFrameAction
What a secondary does at the start of an engine frame, before the engine computes the frame's time st...
Definition frameGate.h:16
bool NeedsResync(std::optional< uint64_t > last_played, uint64_t frame, bool full_resync)
Whether playing frame shows that this secondary missed primary state (a frame went missing) that only...
Definition frameGate.h:75
PreTickAction
What a secondary does when its world starts ticking.
Definition frameGate.h:45
TEST(MultiGpuFrameGate, a_connected_secondary_with_an_episode_waits_for_the_primary)