Feat/embedded rtps merge espp - #672
Conversation
|
⚡ Static analysis result ⚡ 🔴 cppcheck found 43 issues! Click here to see details.espp/components/rtps_embedded/include/rtps/ThreadPool.h Lines 39 to 44 in 751f118 !Line: 39 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/rtps.h Lines 31 to 34 in 751f118 !Line: 31 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/config_desktop.h Lines 31 to 36 in 751f118 !Line: 31 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/config_esp32.h Lines 31 to 36 in 751f118 !Line: 31 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/utils/hash.h Lines 31 to 36 in 751f118 !Line: 31 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/utils/printutils.h Lines 14 to 19 in 751f118 !Line: 14 - error: Code 'C++ cast <...' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/utils/Diagnostics.h Lines 31 to 36 in 751f118 !Line: 31 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/utils/sysFunctions.h Lines 33 to 38 in 751f118 !Line: 33 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/utils/udpUtils.h Lines 33 to 38 in 751f118 !Line: 33 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/common/Locator.h Lines 35 to 40 in 751f118 !Line: 35 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/common/types.h Lines 36 to 41 in 751f118 !Line: 36 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/messages/MessageReceiver.h Lines 35 to 40 in 751f118 !Line: 35 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/messages/MessageTypes.h Lines 34 to 39 in 751f118 !Line: 34 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/messages/MessageFactory.h Lines 40 to 45 in 751f118 !Line: 40 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
!Line: 32 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
!Line: 34 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/storages/MemoryPool.h Lines 33 to 38 in 751f118 !Line: 33 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/storages/CacheChange.h Lines 34 to 39 in 751f118 !Line: 34 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/storages/PayloadBuffer.h Lines 33 to 38 in 751f118 !Line: 33 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
!Line: 32 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/entities/ReaderProxy.h Lines 32 to 37 in 751f118 !Line: 32 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/entities/StatefulWriter.h Lines 38 to 43 in 751f118 !Line: 38 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/entities/Domain.h Lines 42 to 47 in 751f118 !Line: 42 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/entities/StatefulReader.h Lines 36 to 41 in 751f118 !Line: 36 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/entities/Writer.h Lines 55 to 60 in 751f118 !Line: 55 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/entities/Participant.h Lines 40 to 45 in 751f118 !Line: 40 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/entities/Reader.h Lines 38 to 43 in 751f118 !Line: 38 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/entities/StatelessWriter.h Lines 36 to 41 in 751f118 !Line: 36 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/entities/StatelessReader.h Lines 31 to 36 in 751f118 !Line: 31 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/entities/WriterProxy.h Lines 32 to 37 in 751f118 !Line: 32 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
!Line: 39 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/discovery/SPDPAgent.h Lines 48 to 53 in 751f118 !Line: 48 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/discovery/TopicData.h Lines 37 to 42 in 751f118 !Line: 37 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/discovery/SEDPAgent.h Lines 37 to 42 in 751f118 !Line: 37 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
!Line: 34 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
!Line: 41 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/include/rtps/communication/PacketInfo.h Lines 37 to 42 in 751f118 !Line: 37 - error: Code 'namespacertps{' is invalid C code. [syntaxError]
espp/components/rtps_embedded/src/discovery/SEDPAgent.cpp Lines 361 to 366 in 751f118 !Line: 361 - style: inconclusive: Statements following 'return' will never be executed. [unreachableCode]
espp/components/rtps_embedded/src/discovery/SEDPAgent.cpp Lines 504 to 506 in 751f118 !Line: 504 - style: inconclusive: Statements following 'return' will never be executed. [unreachableCode]
espp/components/rtps_embedded/src/communication/EsppTransport.cpp Lines 140 to 145 in 751f118 !Line: 140 - style: Condition '!channel.socket' is always false [knownConditionTrueFalse]
espp/components/rtps_embedded/src/communication/EsppTransport.cpp Lines 78 to 83 in 751f118 !Line: 78 - style: Consider using std::find_if algorithm instead of a raw loop. [useStlAlgorithm]
espp/components/rtps_embedded/src/communication/EsppTransport.cpp Lines 87 to 92 in 751f118 !Line: 87 - style: Consider using std::find_if algorithm instead of a raw loop. [useStlAlgorithm]
espp/components/rtps_embedded/src/communication/EsppTransport.cpp Lines 197 to 202 in 751f118 !Line: 197 - style: Consider using std::any_of algorithm instead of a raw loop. [useStlAlgorithm]
|
|
|
||
| rtps::Writer *Participant::getWriter(EntityId_t id) { | ||
| std::lock_guard<std::recursive_mutex> lock(m_mutex); | ||
| for (uint8_t i = 0; i < m_writers.size(); ++i) { |
|
|
||
| rtps::Reader *Participant::getReader(EntityId_t id) { | ||
| std::lock_guard<std::recursive_mutex> lock(m_mutex); | ||
| for (uint8_t i = 0; i < m_readers.size(); ++i) { |
|
|
||
| rtps::Reader *Participant::getReaderByWriterId(const Guid_t &guid) { | ||
| std::lock_guard<std::recursive_mutex> lock(m_mutex); | ||
| for (uint8_t i = 0; i < m_readers.size(); ++i) { |
|
|
||
| rtps::Writer *Participant::getMatchingWriter(const TopicData &readerTopicData) { | ||
| std::lock_guard<std::recursive_mutex> lock(m_mutex); | ||
| for (uint8_t i = 0; i < m_writers.size(); ++i) { |
|
|
||
| rtps::Reader *Participant::getMatchingReader(const TopicData &writerTopicData) { | ||
| std::lock_guard<std::recursive_mutex> lock(m_mutex); | ||
| for (uint8_t i = 0; i < m_readers.size(); ++i) { |
| rtps::Writer * | ||
| Participant::getMatchingWriter(const TopicDataCompressed &readerTopicData) { | ||
| std::lock_guard<std::recursive_mutex> lock(m_mutex); | ||
| for (uint8_t i = 0; i < m_writers.size(); ++i) { |
| rtps::Reader * | ||
| Participant::getMatchingReader(const TopicDataCompressed &writerTopicData) { | ||
| std::lock_guard<std::recursive_mutex> lock(m_mutex); | ||
| for (uint8_t i = 0; i < m_readers.size(); ++i) { |
| bool Participant::hasReaderWithMulticastLocator( | ||
| const std::array<uint8_t, 4> &address) { | ||
| std::lock_guard<std::recursive_mutex> lock(m_mutex); | ||
| for (uint8_t i = 0; i < m_readers.size(); i++) { |
There was a problem hiding this comment.
Pull request overview
Integrates the embeddedRTPS RTPS/DDS stack into ESPP as a new component (rtps_embedded), adds a new reusable thread_pool component, and introduces PC-side standalone publisher/subscriber tests to exercise the stack outside ESP-IDF.
Changes:
- Add
components/rtps_embeddedwith ESPP-based transport/task/threading adapters plus an ESP-IDF example app. - Add
components/thread_poolas a reusable worker-queue abstraction with an ESP-IDF example. - Extend
pc/build to compile embeddedRTPS-based host tests and include the necessary sources (including Micro-CDR).
Reviewed changes
Copilot reviewed 82 out of 83 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| pc/tests/rtps_embedded_subscriber.cpp | Adds standalone PC subscriber test for embeddedRTPS. |
| pc/tests/rtps_embedded_publisher.cpp | Adds standalone PC publisher test for embeddedRTPS. |
| pc/CMakeLists.txt | Adds embeddedRTPS + Micro-CDR sources to PC tests; enables C compilation for those tests. |
| components/thread_pool/src/thread_pool.cpp | Implements espp::ThreadPool. |
| components/thread_pool/README.md | Documents the new thread pool component. |
| components/thread_pool/include/thread_pool.hpp | Public API for the new thread pool component. |
| components/thread_pool/idf_component.yml | IDF Component Manager manifest for thread_pool. |
| components/thread_pool/example/sdkconfig.defaults | Example sdkconfig enabling C++ exceptions. |
| components/thread_pool/example/README.md | Build instructions for the thread_pool example. |
| components/thread_pool/example/main/thread_pool_example.cpp | Example showing how to submit jobs and await completion. |
| components/thread_pool/example/main/CMakeLists.txt | Registers example main component. |
| components/thread_pool/example/CMakeLists.txt | ESP-IDF project CMake for the thread_pool example. |
| components/thread_pool/CMakeLists.txt | Registers the thread_pool component sources/includes. |
| components/socket/CMakeLists.txt | Adjusts socket component requirements list. |
| components/rtps_embedded/src/utils/Diagnostics.cpp | Adds embeddedRTPS diagnostics storage definitions. |
| components/rtps_embedded/src/messages/MessageTypes.cpp | Adds embeddedRTPS message (de)serialization implementation. |
| components/rtps_embedded/src/messages/MessageReceiver.cpp | Adds RTPS submessage processing/dispatch. |
| components/rtps_embedded/src/entities/Writer.cpp | Adds Writer proxy management and base Writer logic. |
| components/rtps_embedded/src/entities/StatelessReader.cpp | Adds StatelessReader implementation. |
| components/rtps_embedded/src/entities/Reader.cpp | Adds Reader callback/proxy management implementation. |
| components/rtps_embedded/src/discovery/ParticipantProxyData.cpp | Adds SPDP participant proxy deserialization and locator parsing. |
| components/rtps_embedded/src/communication/EsppTransport.cpp | Implements ESPP-backed UDP transport adapter for embeddedRTPS. |
| components/rtps_embedded/README.md | High-level component documentation (architecture/config/quick-start). |
| components/rtps_embedded/include/rtps/utils/udpUtils.h | Port/address helper utilities. |
| components/rtps_embedded/include/rtps/utils/sysFunctions.h | Platform timestamp helper implementation. |
| components/rtps_embedded/include/rtps/utils/printutils.h | Debug print helpers for RTPS IDs. |
| components/rtps_embedded/include/rtps/utils/Log.h | Compile-time verbosity switches for embeddedRTPS logging. |
| components/rtps_embedded/include/rtps/utils/hash.h | Hash utility used for compressed topic matching. |
| components/rtps_embedded/include/rtps/utils/Diagnostics.h | Diagnostics extern declarations. |
| components/rtps_embedded/include/rtps/utils/constants.h | Placeholder constants header. |
| components/rtps_embedded/include/rtps/ThreadPool.h | embeddedRTPS threadpool facade integrating with espp::ThreadPool. |
| components/rtps_embedded/include/rtps/storages/ThreadSafeCircularBuffer.tpp | Thread-safe circular buffer implementation. |
| components/rtps_embedded/include/rtps/storages/ThreadSafeCircularBuffer.h | Thread-safe circular buffer API. |
| components/rtps_embedded/include/rtps/storages/SimpleHistoryCache.h | Stateless history cache implementation. |
| components/rtps_embedded/include/rtps/storages/PayloadBuffer.h | Payload buffer wrapper around std::vector<uint8_t>. |
| components/rtps_embedded/include/rtps/storages/MemoryPool.h | Fixed-size memory pool container for embeddedRTPS entities. |
| components/rtps_embedded/include/rtps/storages/HistoryCacheWithDeletion.h | Deletable history cache used by stateful endpoints. |
| components/rtps_embedded/include/rtps/storages/CacheChange.h | CacheChange model for payload + sequencing. |
| components/rtps_embedded/include/rtps/rtps.h | Convenience header for rtps::Domain. |
| components/rtps_embedded/include/rtps/messages/MessageReceiver.h | MessageReceiver API. |
| components/rtps_embedded/include/rtps/messages/MessageFactory.h | RTPS message construction helpers. |
| components/rtps_embedded/include/rtps/entities/WriterProxy.h | WriterProxy model and missing-sequence computation. |
| components/rtps_embedded/include/rtps/entities/Writer.h | Writer base class interface. |
| components/rtps_embedded/include/rtps/entities/StatelessWriter.tpp | Stateless writer implementation template. |
| components/rtps_embedded/include/rtps/entities/StatelessWriter.h | Stateless writer API. |
| components/rtps_embedded/include/rtps/entities/StatelessReader.h | Stateless reader API. |
| components/rtps_embedded/include/rtps/entities/StatefulWriter.h | Stateful writer API. |
| components/rtps_embedded/include/rtps/entities/StatefulReader.h | Stateful reader API. |
| components/rtps_embedded/include/rtps/entities/ReaderProxy.h | ReaderProxy model. |
| components/rtps_embedded/include/rtps/entities/Reader.h | Reader base class interface + ReaderCacheChange definition. |
| components/rtps_embedded/include/rtps/entities/Participant.h | Participant API including discovery agents and endpoint management. |
| components/rtps_embedded/include/rtps/entities/Domain.h | Domain API for participants/readers/writers plus lifecycle methods. |
| components/rtps_embedded/include/rtps/discovery/TopicData.h | Topic metadata structures and matching logic. |
| components/rtps_embedded/include/rtps/discovery/SPDPAgent.h | SPDP discovery agent API. |
| components/rtps_embedded/include/rtps/discovery/SEDPAgent.h | SEDP discovery agent API. |
| components/rtps_embedded/include/rtps/discovery/ParticipantProxyData.h | ParticipantProxyData model + liveliness checks. |
| components/rtps_embedded/include/rtps/discovery/BuiltInEndpoints.h | Built-in endpoint pointers used by discovery. |
| components/rtps_embedded/include/rtps/config.h | Selects config header based on build target. |
| components/rtps_embedded/include/rtps/config_esp32.h | ESP32-focused config constants. |
| components/rtps_embedded/include/rtps/config_desktop.h | Desktop-focused config constants. |
| components/rtps_embedded/include/rtps/communication/PacketInfo.h | PacketInfo structure for transport send/receive. |
| components/rtps_embedded/include/rtps/communication/EsppTransport.h | Transport adapter API wrapping espp::UdpSocket. |
| components/rtps_embedded/include/rtps/common/Locator.h | Locator types and helpers for IPv4 locators. |
| components/rtps_embedded/example/sdkconfig.defaults | Example sdkconfig for rtps_embedded (partition table, stacks). |
| components/rtps_embedded/example/partitions.csv | Custom partition table for the rtps_embedded example. |
| components/rtps_embedded/example/main/main.cpp | ESP-IDF example app integrating WiFi + RTPS pub/sub demo. |
| components/rtps_embedded/example/main/Kconfig.projbuild | Menuconfig options for role/topics/multicast/network settings. |
| components/rtps_embedded/example/main/CMakeLists.txt | Registers example main component and dependencies. |
| components/rtps_embedded/example/CMakeLists.txt | ESP-IDF project CMake for rtps_embedded example. |
| components/rtps_embedded/CMakeLists.txt | Registers rtps_embedded component sources/includes and dependencies. |
| .gitmodules | Adds Micro-CDR as a submodule under rtps_embedded thirdparty. |
| .gitignore | Ignores generated Micro-CDR config header under the submodule. |
| bool serializeIntoUdcrBuffer(ucdrBuffer &buffer) { | ||
| if (ucdr_buffer_remaining(&buffer) < sizeof(FullLengthLocator)) { | ||
| return false; | ||
| } else { | ||
| ucdr_serialize_array_uint8_t(&buffer, reinterpret_cast<uint8_t *>(this), | ||
| sizeof(FullLengthLocator)); | ||
| } | ||
| } |
| #include <chrono> | ||
| #include <cstdint> | ||
| #include <cstdlib> | ||
| #include <thread> |
| // Keep topic/type names short because embeddedRTPS desktop config caps lengths. | ||
| rtps::Writer *writer = | ||
| domain.createWriter(*participant, topic.c_str(), "UInt32", false); | ||
| if (writer == nullptr) { |
| uint32_t value = 0; | ||
| while (true) { | ||
| ++value; | ||
| const rtps::CacheChange *change = | ||
| writer->newChange(rtps::ChangeKind_t::ALIVE, | ||
| reinterpret_cast<const uint8_t *>(&value), | ||
| static_cast<rtps::DataSize_t>(sizeof(value))); | ||
| logger.info("publish {} -> {}", value, change != nullptr ? "queued" : "dropped"); | ||
| std::this_thread::sleep_for(std::chrono::milliseconds(period_ms)); | ||
| } |
| - Configurable worker count | ||
| - Bounded or unbounded queue | ||
| - Optional blocking submit mode for backpressure | ||
| - Graceful stop (drains queued jobs) |
| [submodule "components/rtps_embedded/thirdparty/Micro-CDR"] | ||
| path = components/rtps_embedded/thirdparty/Micro-CDR | ||
| url = git@github.com:esp-cpp/Micro-CDR.git |
| idf_component_register( | ||
| SRCS | ||
| "src/ThreadPool.cpp" | ||
| "src/communication/EsppTransport.cpp" | ||
| "src/discovery/ParticipantProxyData.cpp" | ||
| "src/discovery/SEDPAgent.cpp" | ||
| "src/discovery/SPDPAgent.cpp" | ||
| "src/discovery/TopicData.cpp" | ||
| "src/entities/Domain.cpp" | ||
| "src/entities/Participant.cpp" | ||
| "src/entities/Reader.cpp" | ||
| "src/entities/StatelessReader.cpp" | ||
| "src/entities/Writer.cpp" | ||
| "src/messages/MessageReceiver.cpp" | ||
| "src/messages/MessageTypes.cpp" | ||
| "src/utils/Diagnostics.cpp" | ||
| "thirdparty/Micro-CDR/src/c/common.c" | ||
| "thirdparty/Micro-CDR/src/c/types/array.c" | ||
| "thirdparty/Micro-CDR/src/c/types/basic.c" | ||
| "thirdparty/Micro-CDR/src/c/types/sequence.c" | ||
| "thirdparty/Micro-CDR/src/c/types/string.c" | ||
| INCLUDE_DIRS | ||
| "include" | ||
| "thirdparty/Micro-CDR/include" | ||
| REQUIRES | ||
| base_component cdr task thread_pool socket | ||
| ) |
| idf_component_register( | ||
| INCLUDE_DIRS "include" | ||
| SRC_DIRS "src" | ||
| REQUIRES base_component task) |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 72 out of 73 changed files in this pull request and generated no new comments.
Suppressed comments (7)
components/rtps_embedded/include/rtps/common/Locator.h:96
FullLengthLocator::serializeIntoUdcrBufferis declared to returnboolbut does not return a value on the success path, which can lead to undefined return values (and may fail builds with-Werror).
bool serializeIntoUdcrBuffer(ucdrBuffer &buffer) {
if (ucdr_buffer_remaining(&buffer) < sizeof(FullLengthLocator)) {
return false;
pc/tests/rtps_embedded_publisher.cpp:20
- This file uses
std::sscanf, but it never includes<cstdio>. With the current include set,std::sscanfis not declared and this test won't compile reliably.
.gitmodules:42 - The Micro-CDR submodule URL is using an SSH form (
git@github.com:...), which will break anonymous CI checkouts and developers without configured SSH keys. Prefer an HTTPS URL here.
[submodule "components/rtps_embedded/thirdparty/Micro-CDR"]
path = components/rtps_embedded/thirdparty/Micro-CDR
url = git@github.com:esp-cpp/Micro-CDR.git
components/rtps_embedded/src/entities/Domain.cpp:118
- User-traffic multicast forwarding filters participants using
packet.destAddr, but the receive pipeline populates that field with the sender address (seeThreadPool::onDatagram/EsppTransport::onReceive). This means user multicast packets will typically not be delivered to any participant whose reader is bound to a multicast group.
components/rtps_embedded/example/main/main.cpp:50 copy_lenis computed as a bounded size, butcopyIntois still called withsizeof(buffer). SincecopyIntorequiresdestSize >= change.getDataSize(), any message larger than the buffer will be silently dropped andcopy_lenbecomes misleading. Either explicitly reject oversized payloads with a clear log or allocate a buffer sized tochange.getDataSize().
const rtps::DataSize_t copy_len =
(change.getDataSize() < static_cast<rtps::DataSize_t>(sizeof(buffer) - 1))
? change.getDataSize()
: static_cast<rtps::DataSize_t>(sizeof(buffer) - 1);
if (copy_len == 0 ||
!change.copyInto(reinterpret_cast<uint8_t *>(buffer), sizeof(buffer))) {
return;
components/rtps_embedded/example/main/Kconfig.projbuild:8
- The help text says the example verifies "UInt32 sample exchange", but the example code publishes/receives
std_msgs::msg::String(seeexample/main/main.cpp). This is confusing when configuring the demo.
Build one board as the initiator and a second board as the responder
to verify RTPS discovery and end-to-end UInt32 sample exchange.
components/rtps_embedded/include/rtps/storages/CacheChange.h:67
CacheChange::reset()clears metadata but leaves the payload buffer intact, so large samples can stay resident in memory even after the change is "reset" (e.g., when history slots are reclaimed). Clearing the payload helps avoid unbounded memory retention on long runs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 71 out of 72 changed files in this pull request and generated 2 comments.
Suppressed comments (9)
pc/tests/rtps_embedded_publisher.cpp:9
parse_ipv4usesstd::sscanf, but this file does not include<cstdio>, which can fail to compile on stricter toolchains.
components/rtps_embedded/include/rtps/common/Locator.h:98FullLengthLocator::serializeIntoUdcrBufferdoes not returntrueon the success path, which will trigger “control reaches end of non-void function” (and can be treated as an error).
bool serializeIntoUdcrBuffer(ucdrBuffer &buffer) {
if (ucdr_buffer_remaining(&buffer) < sizeof(FullLengthLocator)) {
return false;
} else {
ucdr_serialize_array_uint8_t(&buffer, reinterpret_cast<uint8_t *>(this),
.gitmodules:42
- The Micro-CDR submodule URL uses an SSH-style remote (
git@github.com:...). This will fail for users/CI environments without GitHub SSH keys; HTTPS is the more portable default for public submodules.
[submodule "components/rtps_embedded/thirdparty/Micro-CDR"]
path = components/rtps_embedded/thirdparty/Micro-CDR
url = git@github.com:esp-cpp/Micro-CDR.git
components/rtps_embedded/src/entities/Participant.cpp:170
deleteWriter()dereferencesm_writers[i]without checking fornullptr, and also doesn't handle a nullwriterargument. This can crash when the array contains empty slots.
components/rtps_embedded/src/entities/Domain.cpp:442- Same overflow issue as
createWriter():strlen(...) == MAX_*_LENGTHpasses the current check butstrcpywill overflow by writing the null terminator. Use>=and bounded copies.
pc/tests/rtps_embedded_subscriber.cpp:70 - The subscriber defaults to topic
rtps_emb_pubbut uses a String type (std_msgs::msg::String). The publisher test also defaults tortps_emb_pubbut publishes aUInt32, so running both with defaults will not interoperate and is confusing.
components/rtps_embedded/include/rtps/discovery/ParticipantProxyData.h:169 Duration_t.fractionis encoded as seconds / 2^32 (seesysFunctions.h), butisAlive()treats it as microseconds by multiplying by1e-6. This inflates lease durations and breaks liveliness expiration logic.
bool ParticipantProxyData::isAlive() const {
uint32_t lease_in_ms =
m_leaseDuration.seconds * 1000 + m_leaseDuration.fraction * 1e-6;
uint32_t max_lease_in_ms =
Config::SPDP_MAX_REMOTE_LEASE_DURATION.seconds * 1000 +
Config::SPDP_MAX_REMOTE_LEASE_DURATION.fraction * 1e-6;
components/rtps_embedded/src/communication/EsppTransport.cpp:212
joinMultiCastGroup()returns success for the first multicast group even if all existing sockets fail to join (becausem_multicastGroups.size() == 1). That can hide real join failures when channels already exist.
components/rtps_embedded/src/entities/Participant.cpp:159deleteReader()dereferencesm_readers[i]without checking fornullptr, and also doesn't handle a nullreaderargument. This can crash when deleting readers if the array contains empty slots.
This issue also appears on line 161 of the same file.
| if (strlen(topicName) > Config::MAX_TOPICNAME_LENGTH || | ||
| strlen(typeName) > Config::MAX_TYPENAME_LENGTH) { | ||
| return nullptr; | ||
| } | ||
| strcpy(attributes.topicName, topicName); | ||
| strcpy(attributes.typeName, typeName); |
| #include "rtps/ThreadPool.h" | ||
|
|
||
| #include "rtps/entities/Domain.h" | ||
| #include "rtps/entities/Writer.h" | ||
| #include "rtps/utils/Diagnostics.h" | ||
| #include "rtps/utils/Log.h" | ||
| #include "rtps/utils/udpUtils.h" | ||
| #include "thread_pool.hpp" |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 73 out of 74 changed files in this pull request and generated 2 comments.
Suppressed comments (6)
components/rtps_embedded/include/rtps/common/Locator.h:101
- FullLengthLocator::serializeIntoUdcrBuffer() can reach the end of a non-void function without returning a value, which will fail compilation under stricter warnings/settings (and is undefined behavior if used).
} else {
ucdr_serialize_array_uint8_t(&buffer, reinterpret_cast<uint8_t *>(this),
sizeof(FullLengthLocator));
}
}
pc/tests/rtps_embedded_publisher.cpp:9
- This file uses std::sscanf and std::string but does not include / . This can fail to compile depending on transitive includes.
.gitmodules:42 - The Micro-CDR submodule URL uses an SSH form (git@github.com:...), which typically fails in CI/for contributors without GitHub SSH keys configured. Prefer an https:// URL for public submodules.
[submodule "components/rtps_embedded/thirdparty/Micro-CDR"]
path = components/rtps_embedded/thirdparty/Micro-CDR
url = git@github.com:esp-cpp/Micro-CDR.git
components/rtps_embedded/include/rtps/storages/CacheChange.h:67
- CacheChange::reset() does not clear the PayloadBuffer, so caches that reuse CacheChange instances can retain large payload allocations indefinitely (and can keep stale data around longer than intended).
pc/tests/rtps_embedded_subscriber.cpp:11 - This file uses std::string and std::mutex but does not include / . Relying on transitive includes is brittle and can break compilation.
components/rtps_embedded/README.md:8 - This PR adds a new component, but the repo’s component conventions appear incomplete here: there is no components/rtps_embedded/idf_component.yml, and the docs/CI registries don’t reference rtps_embedded (no entries in doc/Doxyfile, .github/workflows/build.yml matrix, or .github/workflows/upload_components.yml). Without these, docs generation, CI example builds, and component-registry uploads will likely miss/fail this component.
# rtps_embedded
ESPP component that integrates the [embeddedRTPS](https://github.com/embedded-software-laboratory/embeddedRTPS)
RTPS/DDS stack into the ESPP ecosystem.
Any platform that can build ESPP — including ESP32, Linux, and desktop PCs —
can use this component to discover and exchange typed messages with ROS 2 nodes
or any other DDS participant on the same network using the standard RTPS wire
protocol.
|
|
||
| reference operator*() const { return m_pool.m_data[m_bit]; } | ||
|
|
||
| reference operator->() const { return m_pool.m_data[m_bit]; } |
| if (valid_locators == Config::SPDP_MAX_NUM_LOCATORS) { | ||
| buffer.iterator += sizeof(FullLengthLocator); | ||
| PPD_LOG("Max number of valid locators exceeded, ignoring this locator as we have at least one valid locator"); | ||
| return true; | ||
| } |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 73 out of 74 changed files in this pull request and generated 2 comments.
Suppressed comments (10)
pc/tests/rtps_embedded_publisher.cpp:1
- This file uses std::sscanf and std::string but does not include and . Relying on transitive includes is fragile and can break builds on different standard library implementations; add the missing standard headers explicitly.
pc/tests/rtps_embedded_subscriber.cpp:1 - This file uses std::mutex and std::string but does not include and . It may compile depending on transitive includes today, but can fail on other platforms/toolchains; include the required headers explicitly.
components/rtps_embedded/src/messages/MessageReceiver.cpp:1 - processMessage() ignores the return value of processSubmessage(). As written, processing failures (including unsupported submessages where processSubmessage returns false) will be silently ignored and processMessage will still return true, which can lead to hard-to-debug dropped/partial parsing. Make processMessage propagate failure (or have processSubmessage always return true for 'skipped but OK' cases).
components/rtps_embedded/include/rtps/storages/CacheChange.h:1 - CacheChange::reset() does not clear the payload buffer (data). Since HistoryCacheWithDeletion::incrementTail() calls reset() when dropping entries, payload vectors can retain (and potentially grow) capacity over time, increasing memory usage. Consider calling data.reset() (or otherwise clearing/shrinking as appropriate) as part of reset(), or documenting that payload memory retention is intentional.
components/rtps_embedded/src/discovery/ParticipantProxyData.cpp:1 - This branch advances ucdrBuffer by mutating buffer.iterator directly without updating the buffer bookkeeping (e.g., last_data_size/alignment). Other parts of the file use ucdr_advance_buffer() for safe skipping. Use ucdr_advance_buffer(&buffer, sizeof(FullLengthLocator)) here too to avoid deserialization state corruption.
components/rtps_embedded/include/rtps/storages/ThreadSafeCircularBuffer.h:1 - The method name peakFirst appears to be a typo for peekFirst (peek at the first element without removing it). If this is a new API surface, consider correcting the name now to avoid long-term public API drift.
components/rtps_embedded/include/rtps/utils/udpUtils.h:1 - The header guard is RTPS_UDP_UTILS_H but the trailing #endif comment says RTPS_UDP_H. Keeping these consistent reduces confusion during debugging and maintenance.
components/rtps_embedded/src/communication/EsppTransport.cpp:1 - New channels force the underlying UDP socket log level to DEBUG. This can produce very noisy logs and degrade runtime performance in deployments. Consider defaulting this to WARN/INFO (or making it configurable via rtps::Config) and only enabling DEBUG when explicitly requested.
.gitmodules:42 - The submodule URL uses the SSH form (git@github.com:...), which requires developers/CI environments to have SSH keys configured. For broader accessibility (and fewer CI failures), prefer an HTTPS URL (https://github.com/...).
[submodule "components/rtps_embedded/thirdparty/Micro-CDR"]
path = components/rtps_embedded/thirdparty/Micro-CDR
url = git@github.com:esp-cpp/Micro-CDR.git
components/rtps_embedded/include/rtps/discovery/TopicData.h:68
- The default constructor hard-codes a non-local IP (192.168.0.42) into unicastLocator. If any code path accidentally uses a default-constructed TopicData before overriding locators, it can advertise invalid endpoints on the wire. Prefer initializing locators as invalid/zero (or using the local interface IP) to make unsafe defaults less likely.
TopicData()
: endpointGuid(GUID_UNKNOWN), typeName{'\0'}, topicName{'\0'},
reliabilityKind(ReliabilityKind_t::BEST_EFFORT),
durabilityKind(DurabilityKind_t::VOLATILE) {
rtps::FullLengthLocator someLocator =
rtps::FullLengthLocator::createUDPv4Locator(
192, 168, 0, 42, rtps::getUserUnicastPort(0));
unicastLocator = someLocator;
multicastLocator = FullLengthLocator();
};
| bool serializeIntoUdcrBuffer(ucdrBuffer &buffer) { | ||
| if (ucdr_buffer_remaining(&buffer) < sizeof(FullLengthLocator)) { | ||
| return false; | ||
| } else { | ||
| ucdr_serialize_array_uint8_t(&buffer, reinterpret_cast<uint8_t *>(this), | ||
| sizeof(FullLengthLocator)); | ||
| } | ||
| } |
| bool ParticipantProxyData::isAlive() const { | ||
| uint32_t lease_in_ms = | ||
| m_leaseDuration.seconds * 1000 + m_leaseDuration.fraction * 1e-6; | ||
|
|
||
| uint32_t max_lease_in_ms = | ||
| Config::SPDP_MAX_REMOTE_LEASE_DURATION.seconds * 1000 + | ||
| Config::SPDP_MAX_REMOTE_LEASE_DURATION.fraction * 1e-6; | ||
|
|
||
| auto heatbeat_age_in_ms = getAliveSignalAgeInMilliseconds(); |
Description
integrates the embeddedRTPS RTPS/DDS stack into the ESPP ecosystem.
Motivation and Context
Try to have an embedded rtps that could be used to talk between embedded board as well as a PC/Jetson that running ROS2 or any other DDS participant on the same network using the standard RTPS wire protocal
How has this been tested?
Tested pub/sub between
ESP32 <-----> ESP32
ESP32 <-----> PC (embedded rtps)
ESP32 <-----> PC (fastRTPS)
ESP32 <-----> PC (ROS2)
Screenshots (if appropriate, e.g. schematic, board, console logs, lab pictures):
ROS:


ESP32:
Types of changes
Checklist:
Software
.github/workflows/build.ymlfile to add my new test to the automated cloud build github action.Hardware