Frequently Asked Questions
This FAQ is based on the captured interactions on Github (related to both open as well as closed issues) and as such includes reference(s) to Github for more details related to the posed questions (and/or answers)
- Frequently Asked Questions
- Best Practices
- DataModel / IDL
- What is the difference between read() and take()?
- How do I assure that all subscribers get the data from a short-lived publisher?
- (Writer-)History QoS KEEP_ALL doesn't result in late-joining reader(s) to receive the data
- How to communicate between DDS-domains?
- Is DDS useful for intermittent local communications without a fixed network?
- What are the semantics behind on_data_available?
- Language Support
How do I specify a domain id?
There's some confusion w.r.t. the multiple ways to specify a domain id for Cyclone DDS.
- When specifying DDS_DOMAIN_DEFAULT upon creating a participant, the value as specified in the configuration (pointed to by the CYCLONEDDS_URI env. variable) will be used or 0 if not specified there.
- Not hardcoding the domain_id is seen as good practice yet its (now) also allowed to specify the (now default) value 'any' in the configuration which implies that a (or better any) domain id can be used in dds_create_participant()
How do I filter out 'self-sent' data?
- Set the
IgnoreLocalQoS on your reader to discard any samples written by readers local to your publisher or participant scope.
- The publication_handle can be checked on equality with the one returned by the get_instance_handle() on the writer-side.
- Use a ContentFilter to check the publisher id on the sample info.
take() operation returns no data?
A take() in combination with
TRANSIENT_LOCAL QoS and
BEST_EFFORT reliability sometimes returns no data.
RELIABLEdelivery so the use-case is actually a anti-pattern
- Note that the (re-)used pingpong example is messy w.r.t. either data-arrival or handling a signal could trigger the waitset (where in the latter case, no data would be returned)
DataModel / IDL
What IDL is supported?
- See this guide on what is supported.
What characters are allowed for topic-names?
- Only alphanumeric characters, '/' and '_' are allowed in topic-names
- Using a hyphen ('-') in a topic-name isn't accepted
- Contrary to the DDS spec (https://www.omg.org/spec/DDS/1.4/PDF) somehow both Cyclone DDS and OpenSpliceDDS support "_" rather than "-" as the spec prescribes
- An open question is: will/can we ever correct this and also: does this impact interoperability with other DDS implementations where topics with a "-" in the name might 'emerge' ?
What is the difference between
When looking at the examples, its unclear what the difference between them is and when to use one or the other
read()is non-destructive meaning you can read the data again (as it remains in your reader-history) whereas
take()actually removes the 'taken' samples from that history
- Typical usecases: when exploiting DDS as a shared-dataspace that (often) captures shared-state, a
read()operation is appropriate to access the most recent state whereas when using DDS for pub/sub event-distribution the
take()operation is more appropriate
How do I assure that all subscribers get the data from a short-lived publisher?
When starting many subscribers of the HelloWorld example, not all get all published data
- By default, data is volatile meaning that when data is published/written before subscribers/readers are present, data won't be delivered
- Multiple reasons/remedies can be identified for this 'seeming data-loss': (1) the writer may be gone already before the reader emerges, remedy is exploiting
TRANSIENTQoS for the data, (2) as discovery takes time, some data might already be published before the match between publisher/subscriber is discovered (even when both are started at the same time), remedy is to exploit 'endpoint-awareness' as provided by
dds_get_publication_matched_status()and wait in the publisher until the current_count equals the number of required/expected subscribers
KEEP_ALL doesn't result in late-joining reader(s) to receive the data
The (in the OMG-spec) specified
KEEP_ALL behavior seems to suggest that data is kept available for (later) delivery
For preserving published data for late-joining subscribers, the
DURABILITY QoS should be used (that works in conjuction with
HISTORY but isn't the same)
Durabilityare orthogonal concepts meaning that
KEEP_ALLwriter-history allows for a system 'in steady state' (in this case relating to existing readers) to 'eventually' deliver all samples from that writer-history to the history-cache of such an EXISTING reader. If on the other hand, data needs to be preserve for 'late-joining' readers, Durability features of DDS can be exploited (i.e.
TRANSIENTQoS) to assure that such non-volatile data will be preserved and delivered to late-joining NEW readers (and in case of
TRANSIENTdata even if the publisher/writer of that data has already 'gone', noting that
TRANSIENTQoS is still under development as of feb'22)
See also - cyclonedds#49
How to communicate between DDS-domains?
Cyclone DDS relies on Zenoh for that
- note that the question was asked in the ROS2 context which doesn't exploit the full DDS feature-set
- on each to-be-connected DDS domain a 'Zenoh bridge for DDS' can be deployed to bridge those two domains
Is DDS useful for intermittent local communications without a fixed network?
This is useful to cases related to mobile devices that regularly go in and out of range
- For such use-cases, the combination of Eclipse’s Cyclone DDS and Zenoh products is suggested
- Sister project Zenoh explicitly targets dynamic connectivity and allows for transparent integration with an (otherwise) DDS-based system
What are the semantics behind
- It seems that on_data_available is triggered not just on actual new data arriving
on_data_availablecallback applies to both data as well as (instance-lifecycle)meta-data
- following an on_data_available callback, a
take) will return either valid data (when new data arrived) or an invalid-sample to convey a lifecycle change related to the writer (typically for an empty instance i.e. one for which the data was already ‘taken’ by a previous call-back response
Why are there huge latency outliers when sending huge samples ?
When sending 1MB samples on a 'standard' Ubuntu distro, latencies can spike from a typical 2 milliseconds towards 150 milliseconds
- Although Cyclone DDS 'asks' the operating system for a 1 megabyte socket-receive-buffer, in many cases it will give out a smaller buffer and thus requires the user to configure a higher allowed maximum receive-buffer-size
- Inspecting /proc/sys/net/core/rmem_max (on Linux) typically shows that such a maximum is insufficient for the intended sample-sizes and thus needs to be 'upped' i.e. using sysctl -w net.core.rmem_max=
Is 'Rust' an available language binding?
As Cyclone DDS is about the only open source DDS implementation written in 'C', it should (at least theoretically) be possible to create a 'Rust' binding on-top of it
- At the time of asking (aug/2020), there was an initiative to add an open source Rust-binding to Cyclone DDS
- See below that current (jan'22) version is 0.1.2 with last update in sept'20
Is 'C#' an available language binding?
- At time of writing (august/2022) there is a C# language binding in the works by ZettaScale Technology.
How do I use multiple (network) partitions in a custom profile?
- Cyclone DDS allows you to map logical DDS-partitions on physical ‘network-partitions’ (typically multicast-groups)
- Although the question was driven by reducing discovery, the below reference still contains a nice write-up on how to exploit network-partitions in Cyclone DDS
See also - cyclonedds#883
How do I configure multiple network interfaces?
- Automatic routing might prevent correct communication in case of multiple configured interfaces
- Setting the ‘General/DontRoute’ config-option typically prevents the issue reported here
- Multi-homing and routing is slated for a ‘deep-dive’ topic as its likely to pop up regularly in more complex setups