Robocikowo>ROBOCIKOWO
Robotyka

rosidl::Buffer

2026EksperymentalnyOpublikowano: 22 września 2026Aktualizacja: 22 września 2026Opublikowany
Natywny kontener C++ w rdzeniu ROS 2 (rosidl_buffer), zamiennik std::vector<T> dla pol uint8[], abstrahujacy backend pamieci (CPU/CUDA/ROCm) dla zero-copy transportu miedzy wezlami.
Kluczowa innowacja
Wprowadza do rdzenia ROS 2 typowany kontener pol wiadomosci, ktory abstrahuje backend pamieci (CPU/CUDA/ROCm), umozliwiajac zero-copy transport pamieci akceleratora miedzy wezlami zamiast wymuszania kopii do std::vector na hoscie.
Kategoria
Robotyka
Poziom abstrakcji
Building block
Poziom operacji
Sterowanie robotemInferencja
Zastosowania
Zero-copy transport obrazow, chmur punktow i tensorow w potokach percepcji GPU (ROS 2)Wymiana danych miedzy wezlami ROS 2 na tym samym urzadzeniu bez kopii host-devicePola uint8[] wiadomosci (np. sensor_msgs/msg/Image.data) z backendem CUDA/ROCmIntegracja przyspieszonego transportu pamieci z Fast DDS oraz ZenohWymiana tensorow miedzy C++ a Python (planowane wsparcie rclpy)

Jak działa

1) Generator kodu ROS 2 emituje rosidl::Buffer<uint8_t> zamiast std::vector<uint8_t> dla pol uint8[]. 2) Buffer<T> stosuje wzorzec PIMPL i deleguje do BufferImplBase<T>; domyslnie tworzy CpuBufferImpl<T> opakowujacy std::vector<T>. 3) Backend ustawia sie raz przy konstrukcji (brak settera po konstrukcji, aby unikac wyscigow). 4) Na CPU dostepne jest pelne API std::vector i niejawna konwersja; na backendach innych niz CPU dostep do elementow rzuca std::runtime_error, a kopie na hosta uzyskuje sie przez to_vector(). 5) Backendy dostawcow (BufferBackend) sa odkrywane i ladowane przez pluginlib (BufferBackendRegistry). 6) Podczas komunikacji warstwa serializacji wola create_descriptor_with_endpoint(); przy zgodnym backendzie po obu stronach przesylany jest deskryptor (<= 4096 B, np. uchwyt IPC pamieci GPU) i odtwarzany przez from_descriptor_with_endpoint() bez kopiowania danych; gdy peer nie wspiera backendu, deskryptor jest nullptr i nastepuje fallback do serializacji CPU. Endpointy oglaszaja obslugiwane backendy i negocjuja zgodnosc (on_creating_endpoint / on_discovering_endpoint).

Rozwiązany problem

W ROS 2 pola binarne wiadomosci (uint8[]) byly reprezentowane jako std::vector<T> w pamieci hosta, co przy duzych danych (obrazy, chmury punktow, tensory) wymuszalo kosztowne kopie miedzy CPU a akceleratorem i uniemozliwialo natywny, zero-copy transport pamieci GPU miedzy wezlami bez rozwiazan spoza rdzenia.

Komponenty

Buffer<T>Kontener pol wiadomosci (PIMPL)

Szablonowy kontener zastepujacy std::vector<T> dla pol uint8[]. Dla backendu CPU udostepnia pelne API std::vector i niejawna konwersje do std::vector<T>&; API dla wszystkich backendow: size(), get_backend_type(), get_impl(), to_vector(). Semantyka wartosci: gleboka kopia przez clone().

BufferImplBase<T>Abstrakcyjna baza implementacji backendu

Minimalna klasa bazowa (get_backend_type(), size(), to_cpu(), clone()). Konkretne backendy: CpuBufferImpl, CUDA, ROCm itd.

Oficjalna

CpuBufferImpl<T>Domyslna implementacja CPU

Implementacja opakowujaca std::vector<T>; domyslny backend zapewniajacy pelna zgodnosc wsteczna.

Oficjalna

BufferBackendInterfejs backendu dostawcy

Abstrakcyjny interfejs (pakiet rosidl_buffer_backend). Tworzy i odczytuje deskryptory (create_descriptor_with_endpoint / from_descriptor_with_endpoint, <= 4096 B), obsluguje hooki odkrywania/negocjacji endpointow (on_creating_endpoint, on_discovering_endpoint) i pozostaje niezalezny od RMW.

Oficjalna

BufferBackendRegistryRejestr backendow (pluginlib)

Pakiet rosidl_buffer_backend_registry. Dynamicznie odkrywa i tworzy instancje backendow przez pluginlib (create_backend_instance, get_backend_names).

Implementacja

Pułapki implementacyjne
Dostep do elementow na backendzie innym niz CPU rzuca wyjatekWysoka

operator[], at(), iteratory i inne operacje std::vector rzucaja std::runtime_error dla backendow innych niz CPU.

Rozwiązanie:Sprawdzaj get_backend_type() lub uzywaj to_vector()/API backendu; nie zakladaj backendu CPU.
to_vector() na backendzie GPU wymusza kopie host-deviceŚrednia

to_vector() to escape hatch zwracajacy kopie na CPU, co niweczy korzysc z zero-copy.

Rozwiązanie:Unikaj to_vector() na sciezce zero-copy; operuj na danych po stronie akceleratora.
Deskryptor backendu ograniczony do 4096 bajtowNiska

Kazdy deskryptor tworzony przez backend musi zserializowac sie do najwyzej kMaxBufferDescriptorSize (4096 B).

Brak wspolnego backendu -> fallback do serializacji CPUŚrednia

Gdy peer nie obsluguje backendu, create_descriptor_with_endpoint() zwraca nullptr i transport przechodzi na standardowa serializacje CPU (utrata zero-copy).

Rozwiązanie:Zapewnij zgodne backendy po obu stronach; monitoruj negocjacje endpointow.

Ewolucja

2026
Prototyp natywnych buforow (accelerated memory transport)

Watek na ROS Discourse przedstawiajacy dzialajacy prototyp zero-copy transportu pamieci akceleratora dla pol uint8[], prowadzony przez inzynierow NVIDIA.

2026
Dodanie rosidl_buffer i rosidl_buffer_backend do rdzenia ROS 2
Punkt przełomowy

PR #941 (scalony 2026-03-31) wprowadza rosidl::Buffer<T>, BufferImplBase<T>, CpuBufferImpl<T> i BufferBackend jako podstawowe typy natywnego bufora.

2026
Generator C++ emituje rosidl::Buffer dla pol uint8[]

Wydanie rosidl_buffer 5.1.4 (2026-04-09): sciezka generatora C++ zaczyna emitowac rosidl::Buffer dla pol typu uint8[] (PR #942).

Hiperparametry (konfigurowalne osie)

Backend pamieciKrytyczna

Typ backendu buforowania okreslany przy konstrukcji: 'cpu' (domyslny), 'cuda', 'rocm', 'demo'. Ustawiany raz, bez settera po konstrukcji.

cpu
cuda
rocm
Typ elementu TWysoka

Parametr szablonu Buffer<T>. Generator C++ emituje rosidl::Buffer<uint8_t> dla pol uint8[].

uint8_t
Maks. rozmiar deskryptoraŚrednia

Gorne ograniczenie zserializowanego deskryptora backendu: 4096 bajtow.

4096 B

Wymagania sprzętowe

Podstawowe

Backend CUDA pozwala trzymac i transportowac pamiec GPU bez kopii na hosta (zero-copy przez deskryptory), co jest glownym celem funkcji.

Dobry fit

Domyslny backend CPU i architektura pluggable sprawiaja, ze sam kontener nie zalezy od konkretnego sprzetu.