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:

sudo apt install ldm-sdk

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:

mkdir build && cd build
cmake ..
cmake --build .

Common helpers under common/

Every SDK example uses two small helpers so the calling code stays readable:

  • gva_qos.hppwriter_qos_for_topic(...) and reader_qos_for_topic(...). Given a topic constant, returns the correct AstuteDDS dds::pub::qos::DataWriterQos / dds::sub::qos::DataReaderQos for 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 a T_CommandResponseType with the same A_referenceNum arrives. 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 requestResourceIdsupplyResourceIdRegistered_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