Astute DDS
Real-Time Data Connectivity for Defence Systems
The middleware that powers mission-critical vehicle platforms
Fully featured DDS with X-Types. Weapons grade DDS for defence.
Powering defence
Astute DDS is the data distribution middleware at the heart of Astute Systems' complete DEF-STAN 23-009 Generic Vehicle Architecture (GVA) solution. From sensors to screens, one unified platform connects every subsystem in your military vehicle.
Why Publish/Subscribe
The Problem with Traditional Architectures
Legacy vehicle systems use point-to-point connections. When you add a new subsystem, you must modify every system it talks to. This creates:
- ❌ Expensive integration — Each new component requires custom coding
- ❌ Fragile systems — One failure can cascade through the network
- ❌ Vendor lock-in — Proprietary protocols trap you with a single supplier
- ❌ Slow upgrades — Changing one subsystem means retesting everything
The Publish/Subscribe Solution
With DDS publish/subscribe architecture, subsystems simply publish data to named topics. Any system that needs that data subscribes to the topic. No point-to-point connections. No custom integration code.
| Business Benefit | How Pub/Sub Delivers |
|---|---|
| 💰 Lower Integration Costs | Add new subsystems without modifying existing ones |
| 🔧 Easier Maintenance | Replace or upgrade components independently |
| 🛡️ Greater Resilience | Systems continue operating even when others fail |
| 🏭 Multi-Vendor Freedom | Mix equipment from different suppliers on one data bus |
| ⏱️ Faster Time-to-Market | Standard interfaces mean less custom development |
Single Source for the Full GVA Stack
Astute Systems is the only vendor providing a complete, integrated software stack for GVA-compliant military vehicles:
| Component | What It Does |
|---|---|
| Bohemian | View and validate SysML models, generate interface definitions |
| LDMX | Best-in-class Land Data Model editor and validator for LDM v10.0.0 |
| ToolX | Automated code generation, build integration, and deployment tooling |
| Astute DDS | Connect all subsystems with real-time, secure data distribution |
| Land Data Model v10.0.0 | Pre-built GVA-compliant data types for all vehicle domains |
| Astute HMI | Crew display software meeting DEF-STAN 23-009 requirements |
Benefits of the Full Stack
| Benefit | Impact |
|---|---|
| 🎯 Single Point of Responsibility | One contract, one support team, one integration partner |
| 📋 Proven Compliance | Pre-validated against DEF-STAN 23-009 requirements |
| 🔄 Seamless Updates | Upgrade any component without breaking the others |
| 💰 Predictable Costs | No surprise integration fees or licensing gotchas |
| ⏱️ Faster Delivery | Start with working software, not empty frameworks |
Comparison
Procurement Considerations
| Factor | Astute DDS | RTI Connext | CycloneDDS | OpenDDS | Fast DDS |
|---|---|---|---|---|---|
| Licence Model | Flexible options | Per-seat commercial | Eclipse EPL 2.0 | LGPL | Apache 2.0 |
| Licence Cost | Competitive | $$$ per deployment | Free | Free | Free |
| Support Model | Australian vendor contract | Global enterprise | Eclipse Foundation | OCI commercial | eProsima commercial |
| Australia-Based Support | ✅ Yes | ❌ US-based | ❌ No | ❌ US-based | ❌ Spain-based |
| GVA Pre-Integration | ✅ Built-in | ❌ Custom work | ❌ DIY | ❌ DIY | ❌ DIY |
| Full Stack Available | ✅ Single source: HMI + LDM + DDS + Tools | ❌ Middleware only | ❌ Middleware only | ❌ Middleware only | ❌ Middleware only |
| SysML Tooling | ✅ Bohemian + LDMX + ToolX | ❌ None | ❌ None | ❌ None | ❌ None |
| Export Control | Australian jurisdiction | US ITAR considerations | EU | US | EU |
Technical Feature Comparison
| Feature | Astute DDS | RTI Connext | CycloneDDS | OpenDDS | Fast DDS |
|---|---|---|---|---|---|
| DDSI-RTPS 2.5 | ✅ Complete | ✅ Complete | ✅ Complete | ✅ Complete | ✅ Complete |
| DDS Security 1.1 | ✅ Complete | ✅ Complete | ⚠️ Partial | ✅ Complete | ✅ Complete |
| X-Types 1.3 | ✅ Complete | ✅ Complete | ⚠️ Partial | ⚠️ Partial | ⚠️ Partial |
| Dynamic Data API | ✅ Complete | ✅ Complete | ❌ None | ⚠️ Basic | ⚠️ Basic |
| TypeLookup Service | ✅ Complete | ✅ Complete | ❌ None | ❌ None | ⚠️ Partial |
| Content Filtering | ✅ Complete | ✅ Complete | ✅ Complete | ✅ Complete | ✅ Complete |
| Shared Memory Transport | ✅ Complete | ✅ Complete | ✅ Complete | ❌ None | ✅ Complete |
| TCP Transport | ✅ Complete | ✅ Complete | ✅ Complete | ✅ Complete | ✅ Complete |
| Zero-Copy | ✅ Supported | ✅ Supported | ✅ Supported | ❌ None | ✅ Supported |
Standards Compliance
| Standard | Astute DDS | RTI Connext | CycloneDDS | OpenDDS | Fast DDS |
|---|---|---|---|---|---|
| OMG DDS 1.4 | ✅ | ✅ | ✅ | ✅ | ✅ |
| OMG DDSI-RTPS 2.5 | ✅ | ✅ | ✅ | ✅ | ✅ |
| OMG DDS-XTypes 1.3 | ✅ | ✅ | ⚠️ | ⚠️ | ⚠️ |
| OMG DDS Security 1.1 | ✅ | ✅ | ⚠️ | ✅ | ✅ |
| OMG IDL 4.2 | ✅ | ✅ | ✅ | ✅ | ✅ |
| DEF-STAN 23-009 (GVA) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Land Data Model v10.0.0 | ✅ | ❌ | ❌ | ❌ | ❌ |
Language & Platform Support
| Capability | Astute DDS | RTI Connext | CycloneDDS | OpenDDS | Fast DDS |
|---|---|---|---|---|---|
| C++ | C++20 | C++11 | C99 wrapper | C++11 | C++11 |
| C | Via C++ | ✅ Native | ✅ Native | ❌ | ✅ Native |
| Python | ✅ | ✅ | ✅ | ✅ | ✅ |
| Rust | ✅ | ❌ | ✅ | ❌ | ❌ |
| Linux | ✅ | ✅ | ✅ | ✅ | ✅ |
| Windows | ✅ | ✅ | ✅ | ✅ | ✅ |
| VxWorks | Roadmap | ✅ | ⚠️ | ✅ | ⚠️ |
| Embedded/RTOS | ✅ Designed for | ✅ Micro variant | ⚠️ | ⚠️ | ⚠️ |
| Static Linking | ✅ Single library | ⚠️ | ⚠️ Shared libs | ⚠️ Shared libs | ⚠️ Shared libs |
Why Astute DDS Wins
| vs RTI Connext | vs CycloneDDS | vs OpenDDS | vs Fast DDS |
|---|---|---|---|
| Flexible licensing options | Complete X-Types support | Complete Dynamic Data API | Australian-based support |
| Australian vendor, no ITAR concerns | Built-in security | TypeLookup Service | Full GVA compliance |
| Single source full GVA stack | Best-in-class LDMX + ToolX | Best-in-class LDMX + ToolX | Simpler deployment |
| LDM v10.0.0 included | Commercial support | Australian jurisdiction | Complete X-Types |
Why Astute DDS
"We reduced our GVA integration timeline by 40% using the Astute stack. Having one vendor responsible for middleware, HMI, and data model eliminated the finger-pointing that plagued previous programmes."
— Programme Manager, UK Defence Prime
Interoperability Guaranteed
Astute DDS is fully interoperable with all major DDS implementations. Your vehicle can communicate seamlessly with:
No vendor lock-in. If a partner system uses a different DDS implementation, Astute DDS will connect without modification.
Defence Standards Compliance
Built for Military Requirements
| Standard | Status |
|---|---|
| DEF-STAN 23-009 | ✅ Full GVA compliance |
| Land Data Model v10.0.0 | ✅ Complete domain types |
| NATO STANAG | ✅ Interoperability ready |
| Cyber Essentials | ✅ Security certified |
Security You Can Trust
- 🔐 Encrypted communications — All data protected in transit
- 🎫 Certificate-based authentication — Only authorised systems connect
- 📋 Access control policies — Define who can publish or subscribe to each topic
- 📝 Full audit logging — Complete trail for security reviews
Proven in Production
Deployed Across Multiple Programmes
Astute DDS is trusted by defence primes across Australia, UK, and allied nations:
| Domain | Applications |
|---|---|
| 🎖️ Armoured Vehicles | Crew displays, sensor fusion, weapons integration |
| 🤖 Robotics & Autonomous Systems | Unmanned ground vehicles, robotic platforms, autonomous navigation |
| 🛡️ Counter-UAS (CUAS) | Drone detection, tracking, and defeat systems |
| ✈️ Ground Control Stations | UAV command and control, sensor feeds |
| 🚢 Naval Systems | Bridge displays, damage control, navigation |
| 🏭 Training & Simulation | Synthetic environments, after-action review, debriefing |
🎬 Request Demo
See Astute DDS and the complete GVA stack in action. Find out more about our stack or request a demonstarion now.
Frequently Asked Questions
The top questions developers ask most often when adopting Astute DDS,.
1. What is Astute DDS?
Astute DDS is a C++20 implementation of the OMG Data Distribution Service
(DDS) DCPS API, DDSI-RTPS 2.5 wire protocol, DDS-XTypes 1.3 type system,
DDS-Security 1.1/1.2 plugins, and IDL 4.2. It is delivered as the static
library libastutedds.a (plus C, Python and Rust bindings) and ships with
the astutedds-inspect diagnostics GUI and an interoperable Shapes Demo.
2. How do I publish and subscribe to a topic?
Create a DomainParticipant, a Topic, then a DataWriter (publisher side)
or DataReader (subscriber side):
using namespace astutedds::dcps;
auto dpf = DomainParticipantFactory::get_instance();
auto dp = dpf->create_participant(0, PARTICIPANT_QOS_DEFAULT, nullptr, 0);
auto topic = dp->create_topic("Hello", "HelloMsg", TOPIC_QOS_DEFAULT, nullptr, 0);
// Publisher
auto pub = dp->create_publisher(PUBLISHER_QOS_DEFAULT, nullptr, 0);
auto writer = pub->create_datawriter(topic, DATAWRITER_QOS_DEFAULT, nullptr, 0);
writer->write(sample, HANDLE_NIL);
// Subscriber
auto sub = dp->create_subscriber(SUBSCRIBER_QOS_DEFAULT, nullptr, 0);
auto reader = sub->create_datareader(topic, DATAREADER_QOS_DEFAULT, nullptr, 0);See Getting Started › First Application.
3. What is the difference between read() and take()?
read()returns samples but leaves them in the reader cache, so later
calls (or other readers in the same subscriber) can read them again.take()returns samples and removes them from the cache.
Use read() when the topic represents shared state you want to inspect
repeatedly; use take() when the topic represents events you want to
consume exactly once.
4. Why don't late-joining subscribers receive earlier samples?
By default DURABILITY is VOLATILE, so samples written before a subscriber
is matched are not delivered. To deliver historic samples to late joiners,
configure the writer and matching readers with TRANSIENT_LOCAL
durability (which also requires RELIABLE reliability):
DataWriterQos qos;
writer->get_qos(qos);
qos.durability().kind = TRANSIENT_LOCAL_DURABILITY_QOS;
qos.reliability().kind = RELIABLE_RELIABILITY_QOS;
writer->set_qos(qos);For persistence across writer restarts use the
Persistence Service or the TRANSIENT/PERSISTENT
durability kinds.
5. What does the RELIABILITY QoS do?
BEST_EFFORT(default for many built-in topics): samples that are lost on
the wire are not retransmitted. Lowest overhead.RELIABLE: the writer tracks acknowledgements (ACKNACK/ heartbeat) from
each matched reader and retransmits missed sequence numbers until the
reader catches up or the history is full.
Reliability is per-writer/per-reader and must be compatible: a BEST_EFFORT
reader can match a RELIABLE writer, but not the reverse.
6. What does the DURABILITY QoS do?
DURABILITY controls whether samples are retained for delivery to readers
that join after the sample was written:
| Kind | Available to late joiners? |
|---|---|
VOLATILE | No |
TRANSIENT_LOCAL | Yes, while the writer is alive |
TRANSIENT | Yes, across writer lifetime (via Persistence Service) |
PERSISTENT | Yes, across process restarts (on-disk) |
7. What is the difference between HISTORY and DURABILITY?
HISTORY (KEEP_LAST(depth) or KEEP_ALL) controls how many samples the
writer/reader cache holds at any instant. DURABILITY controls whether the
writer offers samples to readers that match later. They work together but
solve different problems: KEEP_ALL alone does not make samples available
to late joiners.
8. How do I specify a domain ID?
Pass the domain ID as the first argument to create_participant:
auto dp = DomainParticipantFactory::get_instance()
->create_participant(42, PARTICIPANT_QOS_DEFAULT, nullptr, 0);Participants on different domains do not communicate. The DDSI-RTPS port
formula 7400 + 250 * domain_id determines the base UDP ports used for
discovery.
9. Why aren't my publisher and subscriber discovering each other?
Common causes:
- Different domain IDs — both participants must use the same ID.
- Multicast blocked — SPDP uses UDP multicast on
239.255.0.1by
default. Check the host firewall and switch IGMP snooping. - Wrong network interface — on multi-homed hosts set
ASTUTEDDS_NETWORK_INTERFACE=<name>or configure it in the discovery
JSON / XML profile (see JSON Discovery Config). - Incompatible QoS — see question 15.
- Different transports — verify both peers use UDPv4 (or both UDPv6,
TCP, SHM).
Enable trace logging with ASTUTEDDS_LOG_LEVEL=trace and inspect a packet
capture with astutedds-inspect.
10. What IDL features are supported?
The bundled astutedds-idl compiler implements OMG IDL 4.2 including:
- Primitive types (
boolean,octet, integer typesint8–uint64,float/double/long double,char/wchar,string/wstring). - Structures, unions, enumerations, bitmasks, typedefs.
- Bounded and unbounded sequences, arrays, maps.
@key,@id,@optional,@default,@range,@min,@max,@unit,@extensibility(FINAL|APPENDABLE|MUTABLE),@nested.- Constants and
modulenamespaces.
Generated C++ uses XCDR2 by default with optional XCDR1 for interop.
11. How do I filter samples I published myself?
Two options:
- Ignore at participant level: call
dp->ignore_publication(handle)
passing the local writer'sInstanceHandle_t. - Filter in the reader callback using
SampleInfo::publication_handle
and comparing it to your writer'sget_instance_handle().
A content-filtered topic can also exclude a self-published key field.
12. What characters are allowed in topic names?
Topic names may contain ASCII alphanumeric characters, _, and / as a
hierarchy separator. Length is bounded by 256 characters. Avoid leading
digits and reserved DDS built-in prefixes (DCPS, dds). Type names follow
the same rule.
13. How do I detect when a remote writer or reader goes away?
Install a DataReaderListener and implement on_subscription_matched /on_liveliness_changed, or pollreader->get_subscription_matched_status(). The current_count_change
field is negative when a peer un-matches.
Liveliness is governed by the LIVELINESS QoS — setkind = AUTOMATIC_LIVELINESS_QOS with a lease_duration to detect
silent peers within a bounded time.
14. How do I receive a callback when new data arrives?
Attach a listener with the DATA_AVAILABLE_STATUS mask:
class MyListener : public DataReaderListener {
void on_data_available(DataReader* reader) override {
// call reader->take(...) here
}
};
reader->set_listener(&listener, DATA_AVAILABLE_STATUS);on_data_available fires for both new samples and instance-lifecycle
changes; always inspect SampleInfo::valid_data before dereferencing the
sample payload.
15. What does "Incompatible QoS" mean?
A writer and reader match only when every Request/Offered QoS is
compatible:
| Policy | Requested ≤ Offered |
|---|---|
RELIABILITY | reader BEST_EFFORT ≤ writer RELIABLE |
DURABILITY | reader kind ≤ writer kind (in spec ordering) |
DEADLINE | reader period ≥ writer period |
LATENCY_BUDGET | reader duration ≥ writer duration |
OWNERSHIP | must be equal (SHARED or EXCLUSIVE) |
PARTITION | at least one partition name must overlap |
Listen for on_offered_incompatible_qos / on_requested_incompatible_qos
to find the exact policy ID at runtime.
16. How do I send samples larger than a UDP datagram?
Astute DDS automatically fragments samples larger than the configuredfragment_size (default 1344 bytes for IPv4) and reassembles them on the
reader using DDSI-RTPS DATA_FRAG submessages. The reliability protocol
recovers missing fragments without re-sending the whole sample.
For very large samples (≥ 1 MB) increase the OS socket buffers:
sudo sysctl -w net.core.rmem_max=8388608
sudo sysctl -w net.core.wmem_max=8388608and consider switching to the shared-memory transport for local readers.
17. How do I configure which network interface is used?
Three options, in order of precedence:
- Environment variable:
ASTUTEDDS_NETWORK_INTERFACE=eth0. - JSON discovery config — see JSON Discovery Config.
- XML QoS profile — see DDS-XML QoS Profiles.
If none is set Astute DDS selects the first non-loopback interface with a
multicast-capable address.
18. Can I use Astute DDS on a network without multicast?
Yes. Two alternatives:
- Unicast SPDP peer list: provide a list of peer host/port pairs in the
discovery config; Astute DDS unicasts SPDP announcements to each peer. - TCP transport: switch the participant to the TCP RTPS transport for
environments that block UDP entirely. See
DDS Domain Router for crossing isolated networks.
19. How do I tune for low latency?
- Use
RELIABLEreliability withKEEP_LAST(1)history on both ends so
retransmits are minimal. - Enable the shared-memory transport for co-located participants.
- Pin Astute DDS threads with CPU affinity and use real-time scheduling
(SCHED_FIFO) on the publisher and subscriber processes. - Disable Nagle by using UDP (the default).
- Increase socket buffers (see question 16) to absorb bursts.
- Set
LATENCY_BUDGET = 0to disable any batching delay.
20. Why do I see latency spikes when publishing large samples?
When samples exceed the OS default socket buffer (often 208 KB on Linux),
the kernel drops packets and the reliable protocol must retransmit, causing
spikes. Raising net.core.rmem_max / net.core.wmem_max to at least the
sample size resolves this. Consider fragmenting with smaller fragment_size
on lossy networks.
21. How do I bridge two DDS domains?
Use the Astute DDS Domain Router — a service that joins two or more
domains and forwards configured topics between them, with optional
key/content filtering and QoS translation. See
DDS Domain Router.
22. What language bindings are available?
| Language | Status | Notes |
|---|---|---|
| C++20 | Stable | Primary API — libastutedds.a |
| C | Stable | Flat C API for FFI, see include/astutedds/c/astutedds.h |
| Python | Stable | pybind11 bindings, CPython 3.10 – 3.13 |
| Rust | Beta | astutedds crate (safe wrapper over the C API) |
23. Which platforms and OS versions are supported?
| Platform | Tested versions |
|---|---|
| Linux | Ubuntu 22.04 / 24.04, RHEL 9 / 10, AlmaLinux 9 / 10, Debian 12 |
| Windows | Windows 10, Windows 11, Windows Server 2022 |
The Linux Python wheels are tagged manylinux_2_28 (glibc ≥ 2.28) and run
on any compatible distribution.
24. How do I enable DDS Security?
- Provision identity (X.509) and permissions (signed XML) artefacts.
- Configure the participant property QoS with the Auth, Access Control and
Crypto plugin properties (CA cert, identity cert/key, permissions file,
governance file). - Link against Astute DDS built with
-DASTUTEDDS_ENABLE_SECURITY=ON.
See DDS Security for end-to-end instructions and a
governance/permissions template.
25. How do I persist data across restarts?
Run the Persistence Service alongside your domain. It subscribes to
configured TRANSIENT / PERSISTENT topics, stores samples in a local
database (SQLite by default), and re-publishes them to late-joining
subscribers — including those that join after the original writer is gone.
See Persistence Service.
26. How do I record and replay traffic?
Use the bundled astutedds-record tool to capture a domain into a.astdb file, and astutedds-replay to publish it back with adjustable
time scaling. Recording is type-aware and uses XCDR2 internally. See
Recording and Replay.
27. How do I evolve a data type without breaking subscribers?
Annotate the IDL type with @extensibility(MUTABLE) (or APPENDABLE) and
tag each member with @id(N). XCDR2 mutable streams allow:
- Adding new members to either end.
- Removing optional members.
- Reordering members.
Mismatched members are skipped via the X-Types assignability rules.@extensibility(FINAL) locks the layout and must be used when binary
compatibility with legacy XCDR1 readers matters.
28. How do I use content-filtered topics?
Create a ContentFilteredTopic from a regular topic with a SQL-like filter
expression and bind a DataReader to it:
std::vector<std::string> params{"42"};
auto cft = dp->create_contentfilteredtopic(
"HighSeverity", topic, "severity > %0", params);
auto reader = sub->create_datareader(cft, DATAREADER_QOS_DEFAULT, nullptr, 0);The filter is evaluated on the writer side when possible to save bandwidth.
29. How do I configure QoS from an XML file?
Use XmlQosLoader to read a DDS-XML profile and apply it when creating
entities:
XmlQosLoader loader;
loader.load_file("qos_profiles.xml");
auto qos = loader.get_datawriter_qos("MyLib", "ReliableProfile");
auto writer = pub->create_datawriter(topic, qos, nullptr, 0);See DDS-XML QoS Profiles for the schema and worked
examples.
30. How do I debug interop or discovery issues?
- Run
astutedds-inspectagainst the domain to view discovered
participants, endpoints and matched status in real time. - Capture traffic with
tcpdump -i any -w dds.pcap 'udp port 7400 or portrange 7400-7500'and open it in Wireshark — the RTPS dissector
decodes SPDP, SEDP and user data. - Enable trace logs:
ASTUTEDDS_LOG_LEVEL=trace ASTUTEDDS_LOG_FILE=/tmp/astutedds.log. - Verify entity IDs and ports:
- SPDP writer/reader:
0000:c2/0000:c7 - SEDP publication:
0003:c2/0003:c7 - SEDP subscription:
0004:c2/0004:c7 - Base port:
7400 + 250 × domain_id.
- SPDP writer/reader:
- Confirm both peers advertise compatible vendor IDs and protocol version
(DDSI-RTPS 2.5).
Shapes Demo
To get started with DDS Quality of Service (QoS), the Astute DDS Shapes Demo is the perfect hands-on tool no coding required. The Shapes Demo is a game-like, interactive application that lets you explore DDS capabilities without having to do any programming, making it ideal for anyone new to DDS concepts. Once launched, you publish and subscribe to shape topics (Circles, Squares, and Triangles) on a shared domain and begin experimenting with policies immediately. You can configure Reliability, Durability, History, Filters, Ownership, and more, with the results clearly visible in how shapes appear, disappear, or replay on screen. RtiTwinoakscomputing

Astute DDS also makes it easy to validate interoperability across your DDS network. Run multiple Shapes Demo instances across machines on the same network and domain ID — because Astute DDS uses the standard RTPS wire protocol, participants discover each other automatically. QoS follows a request-offered model if a DataReader requests a higher level of service than the DataWriter is offering, the policies are considered incompatible and the DataWriter will not send data to the DataReader something you can observe directly when shapes stop appearing. Download Astute DDS below and start exploring today.