SDK Reference¶
The LDM SDK is delivered as a Debian meta-package, ldm-sdk, and
gives customers everything they need to write DDS clients that
interoperate with an LDM/AstuteDDS system:
- the LDM 10.0.0 IDL headers (from
libldm10-dev), - the AstuteDDS runtime (
astutedds-dev, pulled in transitively), - the LDM CLI diagnostic tools (
ldmx,bohemian), - a curated set of source-only DDS examples covering registration, the registry, alarms, UACM and display-extension apps.
This page is the customer-facing index of the examples: what each one demonstrates, which Def Stan 23-009 or GVA specification requirements it targets, and how to build it into your own project.
Installation¶
The meta-package is available on the LDM apt feed:
ldm-sdk is a metapackage with no files of its own; it depends on:
| Package | Purpose |
|---|---|
libldm10-dev |
LDM 10.0.0 IDL headers and CMake config files. Transitively depends on astutedds-dev. |
astutedds-dev |
AstuteDDS C++20 DDS runtime headers and static library. |
ldmx |
CLI DDS topic tap / injector. Used in every example's "how to observe" section. |
bohemian |
CLI participant browser. Used to sanity-check discovery. |
ldm-sdk-examples |
Source-only examples installed under /usr/share/ldm-sdk/examples/. |
After apt install ldm-sdk everything is on the system; there is no
runtime service to start.
Filesystem layout¶
/usr/share/ldm-sdk/examples/
├── CMakeLists.txt # in-tree build script (informational only)
├── common/ # helpers shared by every example
│ ├── gva_qos.hpp # writer/reader QoS lookup (per-topic pattern)
│ ├── gva_command_response.hpp # CRP §3 request/response helper
│ └── role_discovery.{hpp,cpp} # discover the calling app's crew role
├── registration/ # basic §8.2.10 request/supply handshake
├── registry-*/ # 15 registry / Platform_Configuration examples
├── alarms-*/ # 6 alarms-service examples (plus alarms-ack-repro,
│ # an internal AstuteDDS transport reproducer —
│ # not a customer teaching example, see below)
├── uacm*/ # 18 usage / condition-monitoring examples
├── displays-and-controls/ # display-extension state command example
├── hand-controller/ # HID → DDS bridge example
└── role-listen/ # crew-role subscriber
The top-level CMakeLists.txt shipped in the tree uses internal
LDM build helpers (ldm_dds_link_target) and is illustrative only —
customers should not import it. Instead, copy the sources you need
into your own project and use the customer CMake template below.
Building an example against ldm-sdk¶
Every example is a self-contained main.cpp that includes:
#include <dds/dds.hpp> // AstuteDDS DDS-XX C++ API
#include "P_Resource_ID_Allocation_PSM.h" // generated LDM 10.0.0 headers
#include "common/gva_qos.hpp" // QoS-per-topic helper
Minimum customer CMakeLists.txt to build any one example:
cmake_minimum_required(VERSION 3.20)
project(my_ldm_app CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Pulled in by `apt install ldm-sdk`
find_package(ldm10 REQUIRED)
find_package(AstuteDDS REQUIRED)
add_executable(my_ldm_app
main.cpp
common/role_discovery.cpp)
target_include_directories(my_ldm_app PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}) # for "common/..." includes
target_link_libraries(my_ldm_app PRIVATE
ldm10::ldm10 # generated LDM IDL types
AstuteDDS::astutedds) # DDS runtime
Copy main.cpp and any common/ files it references into your
project directory and configure with:
Common helpers under common/¶
Every SDK example uses two small helpers so the calling code stays readable:
gva_qos.hpp—writer_qos_for_topic(...)andreader_qos_for_topic(...). Given a topic constant, returns the correct AstuteDDSdds::pub::qos::DataWriterQos/dds::sub::qos::DataReaderQosfor that topic's pattern (state, event, command, response). Uses the same QoS table the internal Qt6 wrappers use, so QoS mismatches with the internal apps are impossible by construction.gva_command_response.hpp— a lightweight synchronous helper around the CRP §3 pattern. Given a command sample, publishes it on the matching command topic and (optionally) blocks on the matching response topic until aT_CommandResponseTypewith the sameA_referenceNumarrives. Handles the deferred-response and no-response cases per GVA_CRP_2/3.
Nothing in common/ depends on qt6-gva-resource-lib or any other
internal LDM library — it is pure DDS.
Registration — basic flow¶
The single most important example. Every LRU or application on the vehicle must complete this handshake before publishing anything else.
| Example | Def Stan / GVA reference | Demonstrates |
|---|---|---|
registration |
§8.2.10 / GVA_PCRR_010 | Basic requestResourceId / supplyResourceId handshake with UUID persistence via --persist-path=<file>, retry-forever via --retry-forever (per §8.2.8 / SG4), and --domain=<N> for the DDS domain. |
Run it against a live registry:
# Terminal 1 — start the registry (already installed by ldm-sdk)
gva-registry --domain=0 &
# Terminal 2 — observe the RIDA request/supply topics
ldmx --domain=0 \
--topic Resource_ID_Allocation__Registered_Platform_Resource__supplyResourceId
# Terminal 3 — run the example
/usr/share/ldm-sdk/examples/registration/main \
--domain=0 \
--persist-path=/tmp/my-lru.persist
See the Registration Service page for the wire semantics and idempotency rules this example illustrates.
Registry examples¶
Every non-trivial gva-registry behaviour has a paired example.
| Example | Def Stan / GVA reference | Demonstrates |
|---|---|---|
registry-approval-states |
R3 / GVA_PCRS_048/049/050 §6.1.7 / §6.1.13-15 | Four-state approval computation (Unapproved, Hardware_Approved_No_Software_Approval, Hardware_Approved_Software_Unapproved, Fully_Approved) as reflected in C_Discoverable_Resource::A_approval. |
registry-auto-map |
R7b / GVA_PCRS_052 §5.2.1 | A requestResourceId whose reported resourceInstance/versionedItems uniquely matches a Fully_Approved/Hardware_Approved_No_Software_Approval Discoverable_Resource_Specification with autoMapResource=true is mapped directly to that spec's logical role — no mapDescriptor command required, and Missing_Resource_Mapping is never raised. |
registry-clear-conflict |
GVA_PCRS_043 §5.2.5 | C_Conflicted_Resource_clearConflict — retract a raised conflict. |
registry-clear-flags |
GVA_PCRS_026 §5.2.6 + GVA_PCRS_027 §5.2.7 | Discoverable_Resource_clearNewlyMapped and Discoverable_Resource_clearVersionedItemsChanged — the two acknowledgement commands. |
registry-commands |
GVA CRP v2.0 §3 / GVA_CRP_1..10 | End-to-end CRP driver against every command topic on both RIDA and Platform_Configuration domains, including --response-required. |
registry-conflict |
GVA_PCRS_040/041 §5.2.3 (R5 non-happy path) | Publishing a C_Registered_Platform_Resource for a UUID the registry has never allocated. Registry publishes C_Conflicted_Resource. |
registry-descriptor-map |
R7a / GVA_PCRS_031/033/051 §5.2.2 + R7b / GVA_PCRS_052 §5.2.1 | mapDescriptor updates an allocation's logical role and re-emits C_Discoverable_Resource with newlyMapped=true; re-issuing requestResourceId for an existing UUID must not spuriously emit Missing_Resource_Mapping. Also drives the in-mapping conflict check (mapping a second allocation onto a role already held by another resets the first) and the A_overrideApproval=false reject path (a CRP Error when the target mapping is not Fully_Approved). |
registry-descriptor-unmap |
R7 / GVA_PCRS_032 §5.2.2 | Configured_Platform_With_Registry_unmapDescriptor — remove the mapping identified by a logical role. |
registry-platform-resource-mode |
SG3 / §5.4.7 | Optional Platform_Resource_setOperatingMode receiver — how a resource consumes an operator override of its own operating mode. |
registry-platform-spec-observer |
SG1 + SG2 / §4.1.2 | Subscribe to Configured_Platform_Specification, every Role_Definition, and every Discoverable_Resource_Specification. Useful as a starter for HMIs that render the platform layout. |
registry-registration-descriptor-match |
GVA_PCRS_040 §5.2.3 (2nd half) | The second half of the handshake — the registry accepts a C_Registered_Platform_Resource only when its A_resourceInstanceDescriptor matches an Approved_Resource_Definition. |
registry-role-change |
R1 / GVA_PCRS_013–016 §5.2.4 | Publish Configured_Platform_setCurrentRole and observe the registry's reconciliation of the active resource set. |
registry-set-nd-serial-number |
§5.4.4 Table 2 line 559 | Non_Discoverable_Resource_setSerialNumber — update a fitted ND resource's serial number for maintenance history. |
registry-set-nd-status |
§5.4.4 / GVA_PCRS_017/019-023 | Non_Discoverable_Resource_setStatus — mutate an ND resource's status across Not_Available / Missing / Broken / Partially_Functional / Fully_Functional. |
registry-set-operating-mode |
§5.2.4 / GVA_PCRS_012 | Configured_Platform_setOperatingMode — switch the platform's operating mode and observe the resulting C_Configured_Platform state. |
All 15 examples take at minimum --domain=<N> and expect
gva-registry to be running on the same domain. Individual examples
that mutate state accept extra flags (e.g. --role=Combat,
--mode=Operational, --source-id=20001); run any example with
--help for its full CLI.
Alarms examples¶
Cover the Alarms service (gva-alarms) — see Alarms Service.
Under Def Stan 23-009 Arch-2 the alarms service is split across three
actors: LRU (Alarm_Condition_Source) publishes conditions, the
register-side service publishes alarms and drives annunciation, and
The_Authorised_Operator (typically the HMI) publishes the five
command topics. Each example plays exactly one of those roles so you
can wire an end-to-end demo by starting a registry, the service, and
the two or three example binaries you need. Crew-role authorisation
against §7.4 Table 4 is not enforced by any example — the operator
binary is a raw driver that lets you supply any --caller-id and
observe how gva-alarms gates the command.
| Example | Role | Def Stan / GVA reference | Demonstrates |
|---|---|---|---|
alarms-lru-spec |
LRU (Alarm_Condition_Source) | §7.2.4 | LRU that owns its condition catalogue — publishes C_Alarm_Condition_Specification and C_Alarm_Condition (Active/Inactive). The service caches the LRU-supplied spec and skips the 10 s fallback pass for that condition ID. Intentionally skips platform registration (§8.2.10) to keep the alarms-only flow in one file, so its Source identity resolves only to System <resourceId> in the HMI. |
alarms-registered-lru |
LRU (Alarm_Condition_Source) | §7.2.4 + §8.2.10 / GVA_PCRR_006/010 | Same condition/spec flow as alarms-lru-spec, but performs the full requestResourceId → supplyResourceId → Registered_Platform_Resource registration handshake first and uses the allocated resourceId for its alarm condition. Publishes A_logicalRoleDescriptor="SDK Example LRU", so the HMI Alarms table's Source column resolves to that name instead of System <resourceId>. |
alarms-fallback-spec |
LRU (Alarm_Condition_Source) | §7.2.4 (Option-B fallback) | LRU that does not own a catalogue — publishes only C_Alarm_Condition. The service falls back to alarm_specifications.json's fallbacks[] (or legacy inline list) for the description, alarmText and category. |
alarms-commands |
The_Authorised_Operator (HMI proxy) | A2 / GVA_ALM_16/17/18/72/74/81/82/86 §7.4 | Operator-command driver for the five command topics: acknowledge, clearAlarm, annotate, Condition_override, Condition_removeOverride. Configurable --caller-id lets you drive both spec-compliant (e.g. Commander) and non-compliant callers so the service's Table 4 gate can be exercised. Reads CRP responses on Alarms__CommandResponseType. |
alarms-policy-suppression |
LRU + register-side observer | Option-B policy layer (repo-local, no spec §) | Two --case modes exercise the platform's disabled[] and overrides[] arrays in alarm_specifications.json. disabled asserts the service refuses to raise C_Alarm for a listed condition; override asserts the emitted C_Alarm carries the remapped category, not the LRU-supplied one. |
alarms-category-definitions |
Register-side observer | §7.2.2 Table 3 | Pure-DDS subscriber for Alarms__Alarm_Category_Definition — prints each category's A_annunciateSupported/A_overrideSupported/A_reannunciateTimeout fields as published on the wire at startup, for integrators who want to read the platform's category taxonomy rather than hard-code Table 3. |
alarms-annunciation-sequencing |
Register-side observer | §7.1.2, §7.3.2.4-6 / GVA_ALM_34/35 | Pure-DDS subscriber for the two annunciation command topics — prints a [START]/[STOP] line naming the catalog Kind for every sample, so a compliance test (or an integrator) can confirm gva-alarms drives at most one active visual and one active audio annunciation at a time, oldest-highest-category-first. |
alarms-ack-repro also lives under examples/sdk/ but is a repo-internal
AstuteDDS transport reproducer (bypasses the LDM Qt wrappers entirely to
isolate a transport-layer bug) rather than a customer teaching example —
it is intentionally not documented here.
Crew-role filtering is an HMI concern, not an example concern —
the HMI enables or disables its buttons per §3.3.1.2 Table 4 and only
issues commands the operator's current role permits. The
alarms-commands binary is deliberately unfiltered so integrators can
verify service-side behaviour with arbitrary --caller-id values.
End-to-end demo recipes¶
Raise → resolve, LRU with its own spec:
gva-registry --domain=0 &
gva-alarms --domain=0 --verbose &
# Publish spec + Active, wait 2 s, publish Inactive
/usr/share/ldm-sdk/examples/alarms-lru-spec/main --domain=0 \
--condition-id=15501 --category-id=90001
Raise → operator ack → clear, LRU without a spec:
gva-registry --domain=0 &
gva-alarms --domain=0 --verbose &
# LRU raises and holds the condition Active
/usr/share/ldm-sdk/examples/alarms-fallback-spec/main --domain=0 \
--condition-id=5001 --hold-active &
# Operator (Commander role, resourceId 20001) acks the alarm
/usr/share/ldm-sdk/examples/alarms-commands/main --domain=0 \
--op=ack --caller-id=20001 --target=<alarm-resource-id>
# LRU lowers the condition
/usr/share/ldm-sdk/examples/alarms-fallback-spec/main --domain=0 \
--condition-id=5001 --lower-only
Verify Option-B overrides[] remaps a Caution to a Warning:
# 1. Seed src/qt6/gva-alarms/etc/alarm_specifications.json with:
# "overrides": [ { "conditionSourceId": 15504, "categoryId": 90001 } ]
# and restart gva-alarms.
/usr/share/ldm-sdk/examples/alarms-policy-suppression/main --domain=0 \
--case=override --condition-id=15504
Observe the wire with ldmx --topic Alarms__Alarm and confirm the
resulting alarm's category matches 90001 (Warning), not whatever the
LRU claimed.
UACM examples¶
The Usage And Condition Monitoring subsystem — see UACM Service. The examples split cleanly into three roles that mirror the Def Stan 23-009 UCMS spec:
- R-role — the LRU that owns a monitored characteristic, fault event, or resource specification and publishes the state samples the service consumes.
- O-role — the operator (typically the HMI) that drives command topics against fault-events, maintenance actions, IBIT, and manual failure reports.
- Bridge driver — a foreign-participant publisher that stands in for an authoritative LRU on the wire so the service's bridge role (§7.2.1 / GVA_UCMR_003) can be exercised end-to-end.
Every example uses the common/gva_qos.hpp helper to pick QoS from
the topic-name constant; none of them hard-code QoS at the call site.
R-role publishers¶
| Example | Wire topics published | What it teaches |
|---|---|---|
uacm |
Monitoring_Data_Source_Specification, Resource_With_Monitoring, Monitored_Characteristic__supplyCharacteristicValue |
Baseline R-role bring-up: the mandatory MDSS + Resource_With_Monitoring preamble (§4.1.2 / GVA_UCMR_002) followed by a rolling supplyCharacteristicValue loop. Supports --response-required + --response-wait-ms to exercise the CRP §3 reply path. |
uacm-charspec-ingest |
one of Monitored_Attribute_Specification, ..._Average_..., ..._Event_Count_..., ..._Powered_On_..., ..._Time_... selected by --kind |
Table 5 §2 forbids publishing the base Monitored_Characteristic_Specification; this example demonstrates all five concrete subtypes (A4–A8) via a --kind selector plus the R-role preamble. |
uacm-resource-ingest |
Monitored_Resource_Specification, Discoverable_Resource, Non_Discoverable_Resource |
Publishes a Monitored_Resource_Specification (A2) so the service and any HMI can enumerate the LRU's monitored surface. Includes the R-role preamble. |
uacm-usage |
Characteristic_Usage_Specification, Characteristic_Usage, Resource_Usage_Specification (cached only), Expiry_Date_Usage_Specification |
Sustained usage-accumulator publisher. Exercises the two on-wire usage patterns (Characteristic_Usage, Expiry_Date_Usage) plus the cache-only Resource_Usage_Specification path (Table 5 §3). |
uacm-events |
Instantaneous_Event_Specification, Instantaneous_Event |
Rapid-fire discrete-event publisher (C7 + C8). Supports --event-count and --emit N for stress-test topologies. Includes the R-role preamble. |
uacm-faults |
Fault_Code_Specification, Fault_Code |
Pure R-role fault driver: publishes a Fault_Code_Specification (A15) then flips Fault_Code::A_faultCodeActive true→false around a hold window. When the declared identifier matches an internal Fault_Event_Specification (default FAULT_CODE::E001), the service emits the derived Fault_Event. Supports --skip-active/--skip-inactive so scripts can interleave O-role commands between edges. |
uacm-ibit |
Interruptive_Built_In_Test_Specification, Interruptive_Built_In_Test, Interruptive_Built_In_Test::startTest, Interruptive_Built_In_Test::stopTest |
Full IBIT round trip: declare the specification, run the test, publish the result. Supports --response-required. |
uacm-maintenance |
Maintenance_Action_Specification, Maintenance_Action, Maintenance_Action::complete, ..._blocked, ..._setComment, ..._remove |
Maintenance-action lifecycle: raise, comment, complete, block, remove. Supports --response-required. |
uacm-threshold-lifecycle |
Monitored_Attribute_Specification (A4), Instantaneous_Threshold_Requirement (A12), Monitored_Characteristic__supplyCharacteristicValue |
End-to-end demonstration that raising and lowering a monitored value across a declared threshold produces a Threshold_Exceedance_Event on the wire. |
uacm-with-thresholds |
Combined Monitored_Attribute_Specification + Instantaneous_Threshold_Requirement + rolling supplyCharacteristicValue + LRU-authoritative Resource_With_Monitoring health |
Compact reference for LRU teams: everything a single monitored characteristic needs, in one file, wire-compliant with Table 5. Demonstrates that the LRU (not the service) decides and publishes its own A_healthStatus, and subscribes to Monitored_Resource to observe the service echo it back verbatim. |
uacm-monitoring-requirements |
Monitored_Attribute_Specification, Periodic_Monitoring_Requirement (repeatable via --periodic-interval-ms), Change_Based_Monitoring_Requirement (--change-based), rolling supplyCharacteristicValue |
§5.4.13/§5.4.14/§5.4.15 driver: demonstrates the always-active periodic and change-based requirement variants and the smallest-interval reconciliation rule when more than one applies to the same characteristic. |
State observers (subscribers)¶
| Example | Wire topics subscribed | What it teaches |
|---|---|---|
uacm-resource-state-listen |
Monitored_Resource |
Pure-DDS subscriber that prints every received A_healthStatus (RAG) transition for a filtered (resourceId, instanceId). Used by the rag-rollup-compliant compliance test to assert real wire samples rather than log text. |
uacm-maintenance-listen |
Maintenance_Action |
Pure-DDS subscriber that prints every received A_state transition for a filtered recipient. Used by the maintenance-action-auto-due-compliant compliance test. |
uacm-usage-listen |
Characteristic_Usage/Expiry_Date_Usage |
Pure-DDS subscriber that prints every received A_state (Exceeded/Not_Exceeded) transition for a filtered usage counter. Used by usage-tracking-compliant to assert the wire-published state after updateCurrentUsage/resetUsage/setNewExpiryDate, not just log text. |
uacm-collection-data-set |
Collection_Data_Set_Definition |
Standalone subscriber for the named characteristic bundle a Threshold_Based_Monitoring_Requirement or Fault_Event_Specification references for bulk-logging — see Collection Data Set bulk-logging. |
O-role command drivers¶
| Example | Wire topics published | What it teaches |
|---|---|---|
uacm-commands |
Every UCMS command topic (Fault_Event::setOperatorComment, ..._remove, Interruptive_Built_In_Test::startTest, ..._stopTest, Maintenance_Action::complete, ..._blocked, ..._setComment, ..._remove, Manual_Failure_Report::updateDescription, ..._clear, Platform_With_Monitoring::reportManualFailure, Expiry_Date_Usage::setNewExpiryDate, Resource_Usage::resetUsage, Monitored_Characteristic::reset) |
GVA CRP v2.0 §3 command driver. Selects one operation via --op and drives it against a target resource; --response-required blocks until the matching reply arrives. |
uacm-manual-failure |
Platform_With_Monitoring::reportManualFailure (B14), Manual_Failure_Report::updateDescription (B9), Manual_Failure_Report::clear (B10) |
Operator-driven manual-failure lifecycle with the shared CommandResponseWaiter helper. Fills the gap left by uacm-commands for platform-scope operations. |
Bridge driver (foreign participant)¶
| Example | Wire topics published | What it teaches |
|---|---|---|
uacm-spec-publisher |
Fault_Event_Specification (A16), optional Monitored_Resource_Specification (A2) |
Foreign-participant driver that stands in for an authoritative R-role LRU. When gva-uacm has a BRIDGE_FALLBACK entry for the same (resourceId, instanceId) key, receiving this driver's sample promotes it to WIRE_LEARNED and suppresses the surrogate publish at grace-elapse. Used by the bridge-fallback-suppressed compliance test. |
Displays & controls / hand-controller / role-listen¶
Three examples covering the crew HID and display-extension paths.
| Example | Demonstrates |
|---|---|
displays-and-controls |
End-to-end publish/subscribe example using C_Light_setOnStatus — the canonical Def Stan 23-009 D&C command topic. Ships a README.md walkthrough. |
hand-controller |
HID device → DDS bridge that models a single hand controller publishing button/axis events. Ships a README.md walkthrough. |
role-listen |
Minimal crew-role subscriber — how any application can discover which crew role its own resourceID is currently assigned to. Wraps common/role_discovery.{hpp,cpp}. |
Running examples against a live system¶
Every example expects a gva-registry on the DDS domain it is
configured for. The recommended layout for developer experimentation:
# Terminal 1 — registry
sudo systemctl start gva-registry
# or, ad-hoc:
gva-registry --domain=0 --config=/etc/gva/registry/platform-config.json
# Terminal 2 — participant browser
bohemian --domain=0
# Terminal 3 — topic tap for whatever you're testing
ldmx --domain=0 --topic <topic-string>
# Terminal 4 — the example
./build/my_ldm_app --domain=0
Every example passes its --domain=<N> to the AstuteDDS runtime. All
processes on the same LDM system MUST use the same domain ID — the
registry, the LRUs, the example, and any ldmx / bohemian
instances.
Further reading¶
- Registration Service — wire semantics of the request/supply handshake and CRP responses.
- DDS Topics Reference — the full list of topic-name constants used by every example.
- Topic Producer/Consumer Matrix — which service owns which topic.