CARLA
Loading...
Searching...
No Matches
commands.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
9#include <cstddef>
10#include <cstdint>
11#include <cstring>
12#include <optional>
13#include <string>
14#include <string_view>
15
16namespace carla {
17namespace multigpu {
18
28
31 uint32_t size;
32};
33
34/// Largest message either end accepts: a frame (capped at 1 GiB by the
35/// primary) plus room for its headers. A larger size prefix can only be a
36/// corrupt stream, so the session is closed instead of allocating it.
37inline constexpr std::size_t kMaxMultiGpuMessageBytes = (std::size_t{1u} << 30u) + (std::size_t{1u} << 20u);
38
39/// Sent unprompted by a secondary, on the same channel as command responses,
40/// to signal that its episode is ready to receive frames (see
41/// Router::HandleResponse). No command reply may ever start with this value.
42inline constexpr std::string_view kEpisodeReadyMarker{"EPISODE_READY"};
43
44/// Identifies one LOAD_MAP broadcast. Assigned by the primary starting at 1;
45/// 0 means the episode was not started by a LOAD_MAP.
46using load_map_id_type = uint32_t;
47
48/// What a LOAD_MAP carries besides the map: for a world the primary
49/// generated from OpenDRIVE (generate_opendrive_world), the OpenDRIVE and the
50/// generation parameters (rpc::OpendriveGenerationParameters, msgpack).
52 std::optional<std::string> opendrive;
53 std::optional<std::string> generation_parameters;
54
55 bool operator==(const LoadMapExtras &rhs) const {
57 }
58};
59
60/// LOAD_MAP payload: the NUL-terminated map path, the load id, then the
61/// extras as [u8 kind][u32 size][bytes] fields; a reader skips the kinds it
62/// does not know.
63inline std::string MakeLoadMapPayload(
64 std::string_view map,
65 load_map_id_type load_id,
66 const LoadMapExtras &extras = {}) {
67 std::string payload(map);
68 payload.push_back('\0');
69 payload.append(reinterpret_cast<const char *>(&load_id), sizeof(load_id));
70 const auto append_field = [&payload](uint8_t kind, const std::optional<std::string> &value) {
71 if (!value) {
72 return;
73 }
74 const uint32_t size = static_cast<uint32_t>(value->size());
75 payload.push_back(static_cast<char>(kind));
76 payload.append(reinterpret_cast<const char *>(&size), sizeof(size));
77 payload.append(*value);
78 };
79 append_field(1u, extras.opendrive);
80 append_field(2u, extras.generation_parameters);
81 return payload;
82}
83
89
90inline LoadMapRequest ParseLoadMapPayload(std::string_view payload) {
91 LoadMapRequest request;
92 const auto end_of_map = payload.find('\0');
93 request.map = std::string(payload.substr(0u, end_of_map));
94 if (
95 (end_of_map == std::string_view::npos) ||
96 (payload.size() - end_of_map - 1u < sizeof(load_map_id_type))) {
97 return request;
98 }
99 std::memcpy(&request.load_id, payload.data() + end_of_map + 1u, sizeof(request.load_id));
100 std::size_t offset = end_of_map + 1u + sizeof(load_map_id_type);
101 while (payload.size() - offset >= 1u + sizeof(uint32_t)) {
102 const uint8_t kind = static_cast<uint8_t>(payload[offset]);
103 uint32_t size = 0u;
104 std::memcpy(&size, payload.data() + offset + 1u, sizeof(size));
105 offset += 1u + sizeof(uint32_t);
106 if (size > payload.size() - offset) {
107 // Cut short: what it carries is not usable.
108 request.extras = {};
109 break;
110 }
111 const std::string value(payload.substr(offset, size));
112 offset += size;
113 if (kind == 1u) {
114 request.extras.opendrive = value;
115 } else if (kind == 2u) {
116 request.extras.generation_parameters = value;
117 }
118 }
119 return request;
120}
121
122/// Episode-ready message: the marker followed by the load id of the LOAD_MAP
123/// that started the episode, so the primary can ignore a stale one.
124inline std::string MakeEpisodeReadyMessage(load_map_id_type load_id) {
125 std::string message(kEpisodeReadyMarker);
126 message.append(reinterpret_cast<const char *>(&load_id), sizeof(load_id));
127 return message;
128}
129
130/// Load id of an episode-ready message (0 for a bare marker), or nullopt if
131/// @a payload is not one.
132inline std::optional<load_map_id_type> ParseEpisodeReadyMessage(std::string_view payload) {
133 if (payload.substr(0u, kEpisodeReadyMarker.size()) != kEpisodeReadyMarker) {
134 return std::nullopt;
135 }
136 const auto load_id_bytes = payload.substr(kEpisodeReadyMarker.size());
137 if (load_id_bytes.empty()) {
138 return load_map_id_type{0u};
139 }
140 if (load_id_bytes.size() != sizeof(load_map_id_type)) {
141 return std::nullopt;
142 }
143 load_map_id_type load_id = 0u;
144 std::memcpy(&load_id, load_id_bytes.data(), sizeof(load_id));
145 return load_id;
146}
147
148/// GET_TOKEN request payload. The secondary resolves the sensor by
149/// @a actor_id (the primary's actor id) and serves it under @a stream_id (the
150/// primary's stream id), which stays the only stream id clients ever see.
152 uint32_t stream_id;
153 uint32_t actor_id;
154};
155static_assert(sizeof(GetTokenRequest) == 2 * sizeof(uint32_t));
156
157/// GET_TOKEN reply when the secondary cannot resolve the sensor to a stream
158/// (or the request is malformed). Shorter than a token on purpose.
159inline constexpr std::string_view kTokenNotReadyMarker{"TOKEN_NOT_READY"};
160
161} // namespace multigpu
162} // namespace carla
uint32_t load_map_id_type
Identifies one LOAD_MAP broadcast.
Definition commands.h:46
constexpr std::size_t kMaxMultiGpuMessageBytes
Largest message either end accepts: a frame (capped at 1 GiB by the primary) plus room for its header...
Definition commands.h:37
std::string MakeLoadMapPayload(std::string_view map, load_map_id_type load_id, const LoadMapExtras &extras={})
LOAD_MAP payload: the NUL-terminated map path, the load id, then the extras as [u8 kind][u32 size][by...
Definition commands.h:63
LoadMapRequest ParseLoadMapPayload(std::string_view payload)
Definition commands.h:90
constexpr std::string_view kTokenNotReadyMarker
GET_TOKEN reply when the secondary cannot resolve the sensor to a stream (or the request is malformed...
Definition commands.h:159
std::optional< load_map_id_type > ParseEpisodeReadyMessage(std::string_view payload)
Load id of an episode-ready message (0 for a bare marker), or nullopt if payload is not one.
Definition commands.h:132
std::string MakeEpisodeReadyMessage(load_map_id_type load_id)
Episode-ready message: the marker followed by the load id of the LOAD_MAP that started the episode,...
Definition commands.h:124
constexpr std::string_view kEpisodeReadyMarker
Sent unprompted by a secondary, on the same channel as command responses, to signal that its episode ...
Definition commands.h:42
This file contains definitions of common data structures used in traffic manager.
GET_TOKEN request payload.
Definition commands.h:151
What a LOAD_MAP carries besides the map: for a world the primary generated from OpenDRIVE (generate_o...
Definition commands.h:51
std::optional< std::string > generation_parameters
Definition commands.h:53
std::optional< std::string > opendrive
Definition commands.h:52
bool operator==(const LoadMapExtras &rhs) const
Definition commands.h:55