VLink  2.0.0
A high-performance communication middleware
qos_profile.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2026 by Thun Lu. All rights reserved.
3  * Author: Thun Lu <thun.lu@zohomail.cn>
4  * Repo: https://github.com/thun-res/vlink
5  * _ __ __ _ __
6  * | | / / / / (_) ____ / /__
7  * | | / / / / / / / __ \ / //_/
8  * | |/ / / /___ / / / / / / / ,<
9  * |___/ /_____/ /_/ /_/ /_/ /_/|_|
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  * http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  */
23 
24 /**
25  * @file qos_profile.h
26  * @brief Curated catalogue of pre-built @c Qos instances for common VLink workloads.
27  *
28  * @details
29  * Picking the right @c Qos for a topic involves balancing reliability, history depth,
30  * durability, publish mode and priority. This file declares sixteen ready-to-use
31  * @c constexpr profiles inside @c vlink::QosProfile, each tuned for a specific class of
32  * traffic encountered in autonomy and embedded stacks. Every profile is constructed
33  * with @c valid set to @c true and can be passed straight to any VLink endpoint or
34  * registered with a transport (@c DdsConf::register_qos) before being referenced from
35  * a URL.
36  *
37  * Profile catalogue (use-case oriented):
38  *
39  * | Profile | Reliability | History | Durability | PublishMode | Priority |
40  * | -------------- | ---------------- | -------------- | --------------- | ----------- | ---------- |
41  * | @c kEvent | Reliable | KeepLast(5) | Volatile | Sync | RealTime |
42  * | @c kMethod | Reliable | KeepAll | Volatile | Sync | High |
43  * | @c kField | Reliable | KeepLast(1) | TransientLocal | Sync | High |
44  * | @c kSensor | BestEffort | KeepLast(10) | Volatile | ASync | Normal* |
45  * | @c kParameter | Reliable | KeepLast(500) | TransientLocal | Sync | Normal |
46  * | @c kService | Reliable | KeepLast(10) | TransientLocal | Sync | Normal |
47  * | @c kClock | BestEffort | KeepLast(1) | Volatile | Sync | Low* |
48  * | @c kStatic | Reliable | KeepAll | TransientLocal | Sync | Normal |
49  * | @c kLight | Reliable | KeepLast(1) | Volatile | ASync | High |
50  * | @c kPoor | BestEffort | KeepLast(5) | Volatile | ASync | Background |
51  * | @c kBetter | BestEffort | KeepLast(50) | Volatile | Sync | RealTime |
52  * | @c kBest | Reliable | KeepLast(200) | Volatile | Sync | RealTime |
53  * | @c kLarge | Reliable (HB500) | KeepLast(500) | Volatile | Sync | Low |
54  * | @c kAlarm | Reliable | KeepAll | TransientLocal | Sync | RealTime* |
55  * | @c kCommand | Reliable | KeepLast(1) | Volatile | Sync | RealTime |
56  * | @c kLog | Reliable | KeepLast(100) | Volatile | ASync | Background |
57  *
58  * Profiles marked @c * (@c kSensor, @c kClock, @c kAlarm) are dispatched as express (the
59  * @c is_express flag is set). Use-case mapping:
60  * @c kEvent = discrete control events, @c kMethod = RPC, @c kField = latest-value state sync,
61  * @c kSensor = high-rate sensors, @c kParameter = slow config, @c kService = discovery,
62  * @c kClock = time sync, @c kStatic = maps / calibration, @c kLight = small frequent traffic,
63  * @c kPoor = low-priority telemetry, @c kBetter = best-effort throughput,
64  * @c kBest = reliable throughput, @c kLarge = large payload (heartbeat 500 ms),
65  * @c kAlarm = safety-critical alarms, @c kCommand = actuator commands, @c kLog = log streams.
66  *
67  * @par Looking profiles up by name
68  * @code
69  * const auto& qos_map = vlink::QosProfile::get_available_qos_map();
70  *
71  * if (auto it = qos_map.find("sensor"); it != qos_map.end()) {
72  * vlink::DdsConf::register_qos("my_sensor_qos", it->second);
73  * }
74  * @endcode
75  *
76  * @par Using a profile by URL
77  * @code
78  * // Built-in names are recognised directly in URLs:
79  * auto pub = vlink::Publisher<MyMsg>::create_unique("dds://sensor_data?qos=sensor");
80  *
81  * // Or apply a profile programmatically:
82  * vlink::Qos qos = vlink::QosProfile::kField;
83  * qos.history.depth = 5; // tweak the depth before use
84  * vlink::DdsConf::register_qos("my_field_qos", qos);
85  * @endcode
86  */
87 
88 #pragma once
89 
90 #include <string>
91 #include <unordered_map>
92 
93 #include "../base/macros.h"
94 #include "./qos.h"
95 
96 namespace vlink {
97 
98 /**
99  * @namespace vlink::QosProfile
100  * @brief Pre-built @c Qos constants for common autonomy and embedded workloads.
101  *
102  * @details
103  * Every constant in this namespace carries @c valid = @c true and is safe to pass
104  * directly to any VLink endpoint or to register with a transport. Pick the closest
105  * profile for your traffic and customise a copy if you need finer control.
106  *
107  * @see Qos, get_available_qos_map()
108  */
109 namespace QosProfile { // NOLINT(readability-identifier-naming)
110 
111 /**
112  * @brief Reliable, KeepLast(5), Volatile, Sync, RealTime priority.
113  *
114  * @details Designed for discrete control events where delivery must be guaranteed and
115  * a small backlog of late arrivals is acceptable. A 1000 ms automatic liveliness lease
116  * surfaces a dead writer quickly and samples are dropped after 2000 ms (Lifespan); no
117  * Deadline is imposed because control events are aperiodic.
118  */
119 [[maybe_unused]] static inline constexpr Qos kEvent{
120  "event",
121  true,
128  Qos::Ownership{},
129  Qos::Deadline{-1},
130  Qos::Lifespan{2000},
134 };
135 
136 /**
137  * @brief Reliable, KeepAll, Volatile, Sync, High priority.
138  *
139  * @details Designed for RPC-style request/response flows. KeepAll ensures no request
140  * is dropped even under sustained load. A 2000 ms liveliness lease detects a stalled
141  * peer and unanswered requests expire after 5000 ms (Lifespan); no Deadline is imposed
142  * because request arrival is demand-driven, not periodic.
143  */
144 [[maybe_unused]] static inline constexpr Qos kMethod{
145  "method",
146  true,
153  Qos::Ownership{},
154  Qos::Deadline{-1},
155  Qos::Lifespan{5000},
159 };
160 
161 /**
162  * @brief Reliable, KeepLast(1), TransientLocal, Sync, High priority.
163  *
164  * @details Designed for Field model traffic where only the latest value matters but
165  * late-joining subscribers must still receive that latest value on demand. A 2000 ms
166  * liveliness lease guards the writer; Lifespan is infinite (-1) so the latest state never
167  * expires, and no Deadline is imposed because state updates are change-driven.
168  */
169 [[maybe_unused]] static inline constexpr Qos kField{
170  "field",
171  true,
178  Qos::Ownership{},
179  Qos::Deadline{-1},
180  Qos::Lifespan{-1},
184 };
185 
186 /**
187  * @brief BestEffort, KeepLast(10), Volatile, ASync, Normal priority, express delivery.
188  *
189  * @details Designed for high-rate sensor streams (LiDAR, camera, IMU) where throughput
190  * dominates and a few dropped samples are preferable to back-pressure. A tight 500 ms
191  * liveliness lease catches a frozen sensor, a 200 ms Deadline flags a stalled feed (the
192  * stream is periodic), and a 500 ms Lifespan discards stale frames before they queue up.
193  */
194 [[maybe_unused]] static inline constexpr Qos kSensor{
195  "sensor",
196  true,
203  Qos::Ownership{},
204  Qos::Deadline{200},
205  Qos::Lifespan{500},
209 };
210 
211 /**
212  * @brief Reliable, KeepLast(500), TransientLocal, Sync, Normal priority.
213  *
214  * @details Designed for configuration parameters that change rarely but must be delivered
215  * reliably. TransientLocal lets late-joining subscribers catch up on the retained history,
216  * and the KeepLast depth of 500 stays within the default @c max_samples_per_instance limit.
217  * A relaxed 5000 ms liveliness lease suits slow traffic; Lifespan is infinite (-1) so the
218  * configured values never expire, and no Deadline is imposed because changes are sporadic.
219  */
220 [[maybe_unused]] static inline constexpr Qos kParameter{
221  "parameter",
222  true,
229  Qos::Ownership{},
230  Qos::Deadline{-1},
231  Qos::Lifespan{-1},
235 };
236 
237 /**
238  * @brief Reliable, KeepLast(10), TransientLocal, Sync, Normal priority.
239  *
240  * @details Designed for service registration and discovery messages where late joiners
241  * must see the current set of advertised services. A 3000 ms liveliness lease lets a
242  * vanished provider be reaped; Lifespan is infinite (-1) so an advertisement persists
243  * until withdrawn, and no Deadline is imposed because registrations are event-driven.
244  */
245 [[maybe_unused]] static inline constexpr Qos kService{
246  "service",
247  true,
254  Qos::Ownership{},
255  Qos::Deadline{-1},
256  Qos::Lifespan{-1},
260 };
261 
262 /**
263  * @brief BestEffort, KeepLast(1), Volatile, Sync, Low priority, express delivery.
264  *
265  * @details Designed for periodic time synchronisation broadcasts where only the most
266  * recent tick has value and an occasional skipped tick is harmless. Synchronous express
267  * dispatch keeps tick jitter low; a 1000 ms liveliness lease and a 1500 ms Deadline catch
268  * a stopped clock (the broadcast is periodic), and a 1000 ms Lifespan drops stale ticks.
269  */
270 [[maybe_unused]] static inline constexpr Qos kClock{
271  "clock",
272  true,
279  Qos::Ownership{},
280  Qos::Deadline{1500},
281  Qos::Lifespan{1000},
285 };
286 
287 /**
288  * @brief Reliable, KeepAll, TransientLocal, Sync, Normal priority.
289  *
290  * @details Designed for largely static datasets (HD maps, calibration tables) that any
291  * late-joining subscriber should receive in full (retained up to the configured
292  * @c ResourceLimits). A long 10000 ms liveliness lease
293  * tolerates a writer that publishes once and stays quiet; Lifespan is infinite (-1) so the
294  * dataset never expires, and no Deadline is imposed because the data is essentially static.
295  */
296 [[maybe_unused]] static inline constexpr Qos kStatic{
297  "static",
298  true,
305  Qos::Ownership{},
306  Qos::Deadline{-1},
307  Qos::Lifespan{-1},
311 };
312 
313 /**
314  * @brief Reliable, KeepLast(1), Volatile, ASync, High priority.
315  *
316  * @details Designed for small frequent messages where only the latest value matters
317  * and asynchronous delivery keeps CPU overhead low. A 1000 ms liveliness lease guards
318  * the writer and a 1000 ms Lifespan drops superseded values; no Deadline is imposed so the
319  * profile stays usable for both periodic and bursty small-message traffic.
320  */
321 [[maybe_unused]] static inline constexpr Qos kLight{
322  "light",
323  true,
330  Qos::Ownership{},
331  Qos::Deadline{-1},
332  Qos::Lifespan{1000},
336 };
337 
338 /**
339  * @brief BestEffort, KeepLast(5), Volatile, ASync, Background priority.
340  *
341  * @details Designed for low-priority telemetry and diagnostics where any sample loss
342  * is acceptable and the goal is to minimise CPU and bandwidth impact. A relaxed 5000 ms
343  * liveliness lease keeps overhead low, a 3000 ms Lifespan bounds backlog, and no Deadline
344  * is imposed because telemetry cadence is not contractual.
345  */
346 [[maybe_unused]] static inline constexpr Qos kPoor{
347  "poor",
348  true,
355  Qos::Ownership{},
356  Qos::Deadline{-1},
357  Qos::Lifespan{3000},
361 };
362 
363 /**
364  * @brief BestEffort, KeepLast(50), Volatile, Sync, RealTime priority.
365  *
366  * @details Designed for high-throughput best-effort streams that benefit from a deeper
367  * buffer and real-time dispatch priority. A 1000 ms liveliness lease guards the writer
368  * and a 1000 ms Lifespan keeps the deep buffer from serving stale samples; no Deadline is
369  * imposed so the profile suits variable-rate throughput.
370  */
371 [[maybe_unused]] static inline constexpr Qos kBetter{
372  "better",
373  true,
380  Qos::Ownership{},
381  Qos::Deadline{-1},
382  Qos::Lifespan{1000},
386 };
387 
388 /**
389  * @brief Reliable, KeepLast(200), Volatile, Sync, RealTime priority.
390  *
391  * @details Designed for high-throughput reliable streams that require predictable
392  * latency, pairing reliability with synchronous publishing and a deep buffer. A 1000 ms
393  * liveliness lease guards the writer and a 2000 ms Lifespan bounds how long the deep buffer
394  * retains samples; no Deadline is imposed so the profile suits variable-rate throughput.
395  */
396 [[maybe_unused]] static inline constexpr Qos kBest{
397  "best",
398  true,
405  Qos::Ownership{},
406  Qos::Deadline{-1},
407  Qos::Lifespan{2000},
411 };
412 
413 /**
414  * @brief Reliable, KeepLast(500), Volatile, Sync, Low priority with a shorter 500 ms heartbeat.
415  *
416  * @details Designed for large payload transfers (maps, point clouds, images) where a
417  * large buffer and a tighter 500 ms heartbeat (vs the 3000 ms default) trigger faster
418  * NACK-driven recovery of lost fragments over slower transport pipelines.
419  * A 3000 ms liveliness lease suits the slower cadence and a generous 10000 ms Lifespan
420  * keeps a bulky payload available without expiring it mid-transfer; no Deadline is imposed
421  * because large transfers are not periodic.
422  */
423 [[maybe_unused]] static inline constexpr Qos kLarge{
424  "large",
425  true,
432  Qos::Ownership{},
433  Qos::Deadline{-1},
434  Qos::Lifespan{10000},
438 };
439 
440 /**
441  * @brief Reliable, KeepAll, TransientLocal, Sync, RealTime priority, express delivery.
442  *
443  * @details Designed for safety-critical alarms and fault events that must be delivered
444  * reliably and made available to late-joining subscribers. KeepAll plus TransientLocal
445  * latch the outstanding alarm set (retained up to the configured @c ResourceLimits — raise
446  * @c max_samples_per_instance for very bursty alarm sources), express + RealTime minimise
447  * dispatch latency, a tight 500 ms liveliness lease detects a dead annunciator, and Lifespan
448  * is infinite (-1) so an alarm stays valid until explicitly cleared; no Deadline is imposed
449  * because alarms are aperiodic.
450  */
451 [[maybe_unused]] static inline constexpr Qos kAlarm{
452  "alarm",
453  true,
460  Qos::Ownership{},
461  Qos::Deadline{-1},
462  Qos::Lifespan{-1},
466 };
467 
468 /**
469  * @brief Reliable, KeepLast(1), Volatile, Sync, RealTime priority.
470  *
471  * @details Designed for actuator and vehicle-control commands where only the most recent
472  * command is valid and delivery must be guaranteed with minimal latency. KeepLast(1) keeps
473  * just the latest order, a tight 500 ms liveliness lease detects a dead commander, and a
474  * 1000 ms Lifespan voids a stale command; no Deadline is imposed because commands are issued
475  * on demand rather than on a fixed cadence.
476  */
477 [[maybe_unused]] static inline constexpr Qos kCommand{
478  "command",
479  true,
486  Qos::Ownership{},
487  Qos::Deadline{-1},
488  Qos::Lifespan{1000},
492 };
493 
494 /**
495  * @brief Reliable, KeepLast(100), Volatile, ASync, Background priority.
496  *
497  * @details Designed for log and event streams that should be delivered reliably without
498  * stealing cycles from the data plane. KeepLast(100) buffers a short burst, asynchronous
499  * dispatch at Background priority keeps logging off the hot path, a relaxed 5000 ms
500  * liveliness lease suits the low cadence, and a 5000 ms Lifespan bounds backlog; no Deadline
501  * is imposed because log volume is bursty.
502  */
503 [[maybe_unused]] static inline constexpr Qos kLog{
504  "log",
505  true,
512  Qos::Ownership{},
513  Qos::Deadline{-1},
514  Qos::Lifespan{5000},
518 };
519 
520 /**
521  * @brief Returns the name-to-@c Qos lookup table containing every profile in this namespace.
522  *
523  * @details
524  * The map is keyed by profile name (e.g. @c "sensor", @c "event") and is safe to read
525  * concurrently from any thread once initialised.
526  *
527  * @return Constant reference to the global @c unordered_map<string, Qos>.
528  */
529 [[nodiscard]] VLINK_EXPORT const std::unordered_map<std::string, Qos>& get_available_qos_map() noexcept;
530 
531 } // namespace QosProfile
532 
533 } // namespace vlink
#define VLINK_EXPORT
Definition: macros.h:81
Quality of Service (QoS) policy aggregate for VLink publishers and subscribers.