OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Connector
2.0.0-preview.2
Prefix Reserved
dotnet add package OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Connector --version 2.0.0-preview.2
NuGet\Install-Package OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Connector -Version 2.0.0-preview.2
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Connector" Version="2.0.0-preview.2" />
<PackageVersion Include="OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Connector" Version="2.0.0-preview.2" />
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Connector" />
paket add OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Connector --version 2.0.0-preview.2
#r "nuget: OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Connector, 2.0.0-preview.2"
#:package OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Connector@2.0.0-preview.2
#addin nuget:?package=OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Connector&version=2.0.0-preview.2&prerelease
#tool nuget:?package=OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Connector&version=2.0.0-preview.2&prerelease
Opc.Ua.OpenUsd.Connector
A standalone, generic OPC UA → OpenUSD connector tool (the connector actor of the draft
OPC UA — OpenUSD Bindings companion specification), built on Opc.Ua.OpenUsd.Client. It
connects to any OPC UA server that implements the companion model, discovers the OpenUSD
representation and its live bindings from the server's address space, subscribes to the bound
Variables, converts the values, and authors a live USD override layer (live.usda). Composed
over a base USD asset, that layer drives a twin rendered with live data in usdview or
NVIDIA Omniverse — with no domain-specific code in the connector or the renderer.
The walkthrough below uses the PumpDeviceIntegrationServer sample; the same binary works
unchanged against the MinimalRobotServer sample or any other conforming server.
What it does
PumpDeviceIntegrationServer (OPC UA server: PumpType + OpenUSD bindings)
│ Server/OpenUSD/Representations (discovery)
▼
Opc.Ua.OpenUsd.Connector ──► UsdFileSink ──► live.usda (runtime override layer)
│ subLayers
▼
stage.usda = live.usda + Plant.usda
│
▼
usdview / NVIDIA Omniverse (the rendered live pump)
The bridge starts at the well-known Server/OpenUSD/Representations registry (Part 1
discovery), reads each OpenUsdLiveBinding (SourceNodeId, target prim/property,
RenderTargetKind, Scale), subscribes, applies the conversion, and writes the target
USD attribute. It never needs to know "pump" — the same binary works for any conforming
server.
The three live bindings (pump sample)
| Source (Pump measurement) | USD target | Kind | Visible effect |
|---|---|---|---|
MassFlow |
/Plant/Pumps/P101/Impeller · xformOp:rotateZ |
Rotation | impeller angle |
BearingTemperature |
/Plant/Pumps/P101/Body · primvars:displayColor |
DisplayColor | body colour (blue→red) |
DifferentialPressure |
/Plant/Pumps/P101/StatusLight/Mat/Surface · inputs:emissiveColor |
EmissiveColor | status-light glow |
Two further bindings exercise the rest of the model: an alarm binding (OpenUsdAlarmBindingType)
drives /Plant/Pumps/P101/StatusLight · visibility from the supervision alarm, and an
opt-in command binding (OpenUsdCommandBindingType) writes a USD inputs:speedSetpoint intent back
into the server's SpeedSetpoint Variable. The stage also advertises a RootLayerDigest
(Sha256) the bridge verifies before composing (Twin-BOM content integrity).
Prerequisites
- .NET SDK 10 — to build and run the server + bridge.
- A USD viewer: usdview (from a full OpenUSD build or NVIDIA Omniverse's
usdview), or NVIDIA Omniverse (USD Composer / Kit) for an RTX render with continuous.liveupdates. Theusd-corePyPI wheel provides thepxrPython modules for validation but not theusdviewGUI. - The base USD asset (
Plant.usda) and composed stage (stage.usda) from the companion spec repo:marcschier/opcua-drafts→core-specs/extras/openusd-binding/examples/pumps/.
Run it end-to-end
1. Build
dotnet build samples/DI/PumpDeviceIntegrationServer/PumpDeviceIntegrationServer.csproj -c Release -f net10.0
dotnet build tools/Opc.Ua.OpenUsd.Connector/Opc.Ua.OpenUsd.Connector.csproj -c Release -f net10.0
2. Prepare a working folder with the base asset
mkdir ~/pump-live
cp <opcua-drafts>/core-specs/extras/openusd-binding/examples/pumps/Plant.usda ~/pump-live/
cp <opcua-drafts>/core-specs/extras/openusd-binding/examples/pumps/stage.usda ~/pump-live/
stage.usda sublayers live.usda (stronger) over Plant.usda.
3. Start the server (terminal 1)
dotnet run --project samples/DI/PumpDeviceIntegrationServer -c Release -f net10.0 -- --host localhost --port 62810
Wait for OPC UA server listening at opc.tcp://localhost:62810/PumpDeviceIntegrationServer.
The pump simulation drives MassFlow, BearingTemperature, and DifferentialPressure,
which is what makes the render live.
4. Run the connector (terminal 2)
dotnet run --project tools/Opc.Ua.OpenUsd.Connector -c Release -f net10.0 -- \
--server opc.tcp://localhost:62810/PumpDeviceIntegrationServer --out ~/pump-live/live.usda --insecure
Options: --server <opc.tcp url> (default opc.tcp://localhost:62542/PumpDeviceIntegrationServer),
--out <live.usda>, --seconds N (run for a fixed time instead of until Ctrl+C), and
--insecure. The connector is secure by default (encrypted, signed channel with server-certificate
trust required, per spec §9). --insecure opts into an unsecured endpoint and blanket certificate
acceptance — appropriate only for this localhost demo, whose server uses a self-signed certificate.
Omit --insecure and place the server certificate in the bridge's trusted store for a secured run.
Rendering the twin in the same process
Steps 5 onward assume an external viewer. Install the optional
OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Connector.Viewer package alongside the connector and
--view renders the composed stage itself, streaming the same subscribed values into the picture on
screen as well as into live.usda:
dotnet run --project tools/Opc.Ua.OpenUsd.Connector -c Release -f net10.0 -- \
--server opc.tcp://localhost:62830/MinimalRobotServer --insecure --view
Without --fetch-assets or --stage, --view fetches the server's asset closure into a temporary
directory first, because a renderer needs geometry it can resolve. --renderer selects the backend
and --plugins points at the USD plugin tree when it is not beside the connector. Closing the window
stops the session; --seconds closes it automatically. The connector loads the viewport assembly on
demand, so the package stays small and every other option keeps working without it. The viewport
requires .NET 8 or later and a supported OpenUSD native runtime payload (win-x64, linux-x64, or
osx-arm64). A RID-less build or publish on a supported host uses that host's payload; use an
explicit RID when publishing for another platform.
Command bindings are disabled by default (fail-closed). Add --enable-commands and
--command-value <double> to actuate the single OpenUsdCommandBindingType binding once at start, e.g.
--enable-commands --command-value 1450 writes 1450 into the server's SpeedSetpoint
Variable (single-writer, authorized, fail-closed). Read-only telemetry/alarm flow is unaffected.
It rewrites live.usda on every value change, e.g.:
over "Plant" { over "Pumps" { over "P101" {
over "Impeller" { double xformOp:rotateZ = 0.0538 }
over "Body" { color3f[] primvars:displayColor = [(1.0000, 0.0000, 0.0000)] }
over "StatusLight" { over "Mat" { over "Surface" {
color3f inputs:emissiveColor = (0.1000, 1.0000, 0.2000) } } }
} } }
5. Open the rendered live pump
- usdview:
usdview ~/pump-live/stage.usda— a cylindrical body, a two-blade impeller, and a status light. usdview loads a snapshot; pressR(Reload All Layers) to pull the bridge's latest values. - NVIDIA Omniverse: open
~/pump-live/stage.usdain USD Composer — the override layer updates the viewport continuously under RTX (impeller spins, body warms toward red, status light glows).
The emissive glow needs a material-aware renderer (Omniverse RTX, or usdview with Storm);
displayColorand the transform render everywhere.
Validate composition without a GUI
With only usd-core installed:
python - <<'PY'
from pxr import Usd, UsdGeom
s = Usd.Stage.Open("stage.usda")
g = lambda p, a: s.GetPrimAtPath(p).GetAttribute(a).Get()
print("rotateZ :", g("/Plant/Pumps/P101/Impeller", "xformOp:rotateZ"))
print("displayColor:", g("/Plant/Pumps/P101/Body", "primvars:displayColor"))
print("emissive :", g("/Plant/Pumps/P101/StatusLight/Mat/Surface", "inputs:emissiveColor"))
PY
How it maps to the specification
- Discovery — the bridge starts at
Server/OpenUSD/Representations(base spec §4.2), never at "the pump". One binary serves any conforming server. - Bindings — each
OpenUsdLiveBindingdeclaresSourceNodeId, target prim/property,RenderTargetKind, andScale; the bridge reads them and applies the conversion (§5.7–§5.8). 0.2 addsSignalRole,SourceSemanticId, alarm (OpenUsdAlarmBindingType/AlarmAspect), and opt-in command (OpenUsdCommandBindingType/CommandTargetNodeId) members. - Integrity — the stage's
RootLayerDigest/RootLayerDigestAlgorithmare verified before composition (Twin-BOM content integrity, §5.11/§9); a mismatch is fail-closed. - Command safety — command bindings are normative but opt-in: disabled by default, single-writer, authorized, fail-closed (§5.10).
- Composition — the bridge assembles the asset's component hierarchy into USD prims
(
OpenUsdComponentBindingType, §5.12–5.14): 1:1 child prims, 1..n instanceable references, dynamic add/remove reconciled from model-change events, and cross-server federation. - Layering — OPC UA is the single mapping authority; the base USD asset is never
modified. Live values live in a composed override layer (the equivalent of an Omniverse
Nucleus
.livelayer, Part 3).
The generic companion specification and the full step-by-step guide live in
marcschier/opcua-drafts under core-specs/openusd-binding/.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Framework | net48 is compatible. net481 was computed. |
-
.NETFramework 4.8
- BitFaster.Caching (>= 2.6.0)
- BouncyCastle.Cryptography (>= 2.7.0)
- Microsoft.Bcl.AsyncInterfaces (>= 10.0.10)
- Microsoft.Bcl.HashCode (>= 6.0.0)
- Microsoft.Bcl.TimeProvider (>= 10.0.10)
- Microsoft.Extensions.Configuration (>= 10.0.10)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.10)
- Microsoft.Extensions.DependencyInjection (>= 10.0.10)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Diagnostics (>= 10.0.10)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Http (>= 10.0.10)
- Microsoft.Extensions.Http.Resilience (>= 10.8.0)
- Microsoft.Extensions.Logging (>= 10.0.10)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Logging.Console (>= 10.0.10)
- Microsoft.Extensions.Options (>= 10.0.10)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.10)
- OPCFoundation.NetStandard.Opc.Ua.Configuration.Debug (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Client.Debug (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.OpenUsdScene.Debug (>= 2.0.0-preview.2)
- System.Buffers (>= 4.6.1)
- System.Collections.Immutable (>= 9.0.0)
- System.Diagnostics.DiagnosticSource (>= 10.0.10)
- System.Formats.Asn1 (>= 10.0.10)
- System.Memory (>= 4.6.3)
- System.Runtime.CompilerServices.Unsafe (>= 6.1.2)
- System.Text.Json (>= 10.0.10)
- System.Threading.Channels (>= 10.0.10)
- System.Threading.RateLimiting (>= 10.0.10)
- System.Threading.Tasks.Extensions (>= 4.6.3)
-
net10.0
- BitFaster.Caching (>= 2.6.0)
- Microsoft.Bcl.TimeProvider (>= 10.0.10)
- Microsoft.Extensions.Configuration (>= 10.0.10)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.10)
- Microsoft.Extensions.DependencyInjection (>= 10.0.10)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Diagnostics (>= 10.0.10)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Http (>= 10.0.10)
- Microsoft.Extensions.Http.Resilience (>= 10.8.0)
- Microsoft.Extensions.Logging (>= 10.0.10)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Logging.Console (>= 10.0.10)
- Microsoft.Extensions.Options (>= 10.0.10)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.10)
- OPCFoundation.NetStandard.Opc.Ua.Configuration.Debug (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Client.Debug (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.OpenUsdScene.Debug (>= 2.0.0-preview.2)
- System.Threading.RateLimiting (>= 10.0.10)
-
net8.0
- BitFaster.Caching (>= 2.6.0)
- Microsoft.Bcl.TimeProvider (>= 10.0.10)
- Microsoft.Extensions.Configuration (>= 10.0.10)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.10)
- Microsoft.Extensions.DependencyInjection (>= 10.0.10)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Diagnostics (>= 10.0.10)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Http (>= 10.0.10)
- Microsoft.Extensions.Http.Resilience (>= 10.8.0)
- Microsoft.Extensions.Logging (>= 10.0.10)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Logging.Console (>= 10.0.10)
- Microsoft.Extensions.Options (>= 10.0.10)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.10)
- OPCFoundation.NetStandard.Opc.Ua.Configuration.Debug (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Client.Debug (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.OpenUsdScene.Debug (>= 2.0.0-preview.2)
- System.Collections.Immutable (>= 9.0.0)
- System.Diagnostics.DiagnosticSource (>= 10.0.10)
- System.Formats.Asn1 (>= 10.0.10)
- System.Text.Json (>= 10.0.10)
- System.Threading.Channels (>= 10.0.10)
- System.Threading.RateLimiting (>= 10.0.10)
-
net9.0
- BitFaster.Caching (>= 2.6.0)
- Microsoft.Bcl.TimeProvider (>= 10.0.10)
- Microsoft.Extensions.Configuration (>= 10.0.10)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.10)
- Microsoft.Extensions.DependencyInjection (>= 10.0.10)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Diagnostics (>= 10.0.10)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Http (>= 10.0.10)
- Microsoft.Extensions.Http.Resilience (>= 10.8.0)
- Microsoft.Extensions.Logging (>= 10.0.10)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Logging.Console (>= 10.0.10)
- Microsoft.Extensions.Options (>= 10.0.10)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.10)
- OPCFoundation.NetStandard.Opc.Ua.Configuration.Debug (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Client.Debug (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.OpenUsdScene.Debug (>= 2.0.0-preview.2)
- System.Diagnostics.DiagnosticSource (>= 10.0.10)
- System.Formats.Asn1 (>= 10.0.10)
- System.Text.Json (>= 10.0.10)
- System.Threading.Channels (>= 10.0.10)
- System.Threading.RateLimiting (>= 10.0.10)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.0-preview.2 | 46 | 8/24/2026 |