Skip to content

Add RoboticsDeviceIntegrationServer + OpenUSD end-to-end (OPC 40010 robot cell) - #16

Merged
marcschier merged 6 commits into
openusd-bindingfrom
openusd-robotics-e2e
Jul 17, 2026
Merged

Add RoboticsDeviceIntegrationServer + OpenUSD end-to-end (OPC 40010 robot cell)#16
marcschier merged 6 commits into
openusd-bindingfrom
openusd-robotics-e2e

Conversation

@marcschier

Copy link
Copy Markdown
Owner

Adds RoboticsDeviceIntegrationServer + an OpenUSD end-to-end for the OPC 40010 Robotics companion, driven by the same generic connector used by the pump sample (no robot-specific bridge code). Stacked on openusd-binding (#13).

What it adds

  • A self-contained server exposing a MotionDeviceSystem "RobotCell" → two 6-axis articulated robots → 12 axes (15 representations: 1 system + 2 robots + 12 axes) bound to OpenUSD via the draft OPC UA — OpenUSD Bindings model.
  • Recursive composition: system —Many/Reference→ robots —Many/Child→ axes.
  • Per-axis live articulation: each Axis ActualPosition (deg) drives a joint xformOp:rotate on the robot.usda kinematic chain (RenderTargetKind = Rotation).
  • Emergency-stop safety visuals (Visibility on beacon + per-robot warning), an opt-in SpeedOverride command (fail-closed), and a gripper tool composed dynamically on R1's flange via model-change events.
  • RobotOpenUsdE2eTests10 passing cases (net10.0): discovery of 15 representations, articulation, robot aggregation, nested axis composition, safety visuals, dynamic tool, command fail-closed/enabled, stage digest.

Design note — runtime NodeSet import

The OPC 40010 Robotics model (+ its IA dependency) is loaded at runtime from embedded NodeSet2.xml via UANodeSet.Read + Import, not source-generated: the Robotics model uses base state-machine/method types whose generated NodeState proxies are not all present in this repo's Opc.Ua.Core, so the generator's output does not compile for it. Runtime import loads the full, faithful OPC 40010 type structure; the server builds instances from BaseObjectState + numeric type NodeIds, so no generated Robotics/IA typed classes are needed. Only OpenUsdBinding is source-generated.

Validation

  • e2e 10/10 (net10.0); server builds clean net10.0 + net48 (0 warnings / 0 errors).
  • A real bridge run (PumpDeviceIntegrationBridgelive.usda) composes both robots with independent joint rotations + the dynamic tool + safety visibility.

The example USD assets, descriptor, writer, and step-by-step guide live in marcschier/opcua-drafts under core-specs/extras/openusd-binding/examples/robotics/ (PR #12).

marcschier and others added 6 commits July 15, 2026 19:52
…obot cell)

A self-contained OPC UA server exposing an OPC 40010 Robotics MotionDeviceSystem
(a cell of two 6-axis articulated robots) bound to OpenUSD via the draft
OPC UA - OpenUSD Bindings companion model, driven by the SAME generic connector
used by the pump sample (no robot-specific bridge code).

- Recursive composition: system -Many/Reference-> robots -Many/Child-> axes
  (15 representations: 1 system + 2 robots + 12 axes).
- Per-axis live articulation: each Axis ActualPosition (deg) drives a joint
  xformOp:rotate on the robot.usda kinematic chain (RenderTargetKind=Rotation).
- Emergency-stop safety visuals (Visibility on beacon + per-robot warning),
  opt-in SpeedOverride command (fail-closed), and a gripper tool composed
  dynamically on R1's flange via model-change events.
- IA + Robotics NodeSets are loaded at runtime (UANodeSet.Read+Import) because
  their generated NodeState proxies reference base state-machine types absent
  from this fork's Core; only OpenUsdBinding is source-generated.
- RobotOpenUsdE2eTests: 10 passing cases (net10.0); server builds net10.0+net48.
…aming)

Serve the artist-authored USD asset closure (root layer + component
references) through the OPC UA address space so a generic connector can
enumerate, stream, verify, cache, and compose a self-contained local
stage with no external asset setup, then live-update as before. Servers
that do not expose Assets remain conformant (external resolution).

- OpenUsdShared/UsdAssetDelivery.cs: read-only Part 5 FileState serving
  helper (Open/Read/Close/GetPosition/SetPosition over byte[], bounded
  handles); AttachStageAssets materializes the stage Assets folder with
  one OpenUsdAssetType (+ SHA-256 Digest) per served layer.
- Pump + Robotics servers: embed their USD assets and serve the stage
  closure (Plant/pump/remote-pump; Cell/robot/tool).
- Connector: OpenUsdConnector.Assets.cs enumerates stage.Assets, streams
  each layer via Part 5, verifies Digest (fail-closed), and caches with
  path sanitization; --fetch-assets writes a self-contained stage.usda.
- Regenerated OpenUsdBinding NodeSet in both servers' Model/.
- e2e: ServedAssetsAreFetchedVerifiedAndCached (pump + robotics).
…et FileType (PR #14 review)

Sync the C# reference impl to the updated companion NodeSet:

Live-binding split (spec 5.4):
- Servers create the concrete binding subtype per intent (retype the
  <Binding> placeholder child to OpenUsd{Telemetry,Alarm,History,Command}
  BindingType) and set intent-specific members via the subtype factories;
  the removed IntentProfile enum is no longer written.
- Connector matches the four binding subtype NodeIds and derives the intent
  from the instance TypeDefinition (was: reading the IntentProfile property);
  the internal OpenUsdIntentProfile discriminator + downstream logic are kept.

Asset content delivery (spec 5.15): OpenUsdAssetType now subtypes Part 5
FileType, so the asset node itself is the file — UsdAssetDelivery wires the
read-only Open/Read/Close handlers onto the asset node, and the connector
streams each asset directly (no File child).

- Regenerated OpenUsdBinding NodeSet copied into both servers' Model/.
- Verified: OpenUsd e2e 27/27 (net10.0); bridge + both servers build clean
  on net10.0 and net48.
…s (PR #14 review)

Sync impl to the renamed OpenUsdValueChangeBindingType (was Telemetry) and the
now-Mandatory command members: OpenUsdModel + connector use ValueChangeBindingTypeId;
both servers default CreateBinding to ObjectTypes.OpenUsdValueChangeBindingType.
Copied regenerated NodeSet into both servers' Model/.

Verified: OpenUSD e2e 27/27 (net10.0); bridge + both servers build clean on net10.0 + net48.
Code-review audit fixes:
- Connector Convert now applies the spec 5.8 conversion offset
  (target = Scale * converted + Offset); BindingInfo gains Offset, read from
  the binding node (default 0.0). No behavior change on the examples (offset=0).
- Fix stale comments referencing the removed OpenUsdTelemetryBindingType name
  (-> OpenUsdValueChangeBindingType).
- Re-copied the regenerated OpenUsdBinding NodeSet (Model Version 0.2.0) into
  both servers' Model/.

Verified: OpenUSD e2e 27/27 (net10.0); bridge + both servers clean on net10.0 + net48.
OpenUSD: intent-subtype live bindings + server-delivered asset content
@marcschier
marcschier merged commit e579422 into openusd-binding Jul 17, 2026
@marcschier
marcschier deleted the openusd-robotics-e2e branch July 17, 2026 07:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant