Repository navigation
Add OPC UA Robotics companion SDK (tracking: split into #4123-#4127) #4096
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from 23 commits
Commits
Show all changes
55 commits
Select commit
Hold shift + click to select a range
cb05d55
Source generator: support source-generating compiled companion NodeSets
marcschier a9edb38
Add OPC UA Robotics companion SDK
marcschier 12a5800
Add OPC UA — OpenUSD binding integration (libraries, connector, sampl…
marcschier f6e2161
review: locks, browse continuation points, INullable guards, Robotics…
marcschier 25065b4
review: Variant sink API, history continuation+batch, IAsyncDisposabl…
marcschier 59288ae
review: DI+fluent AddOpenUsdConnector (both surfaces), options object…
marcschier 8049ca1
review: digest as ByteString, AttachStageAssets ArrayOf<T>, fix e2e d…
marcschier 52c9aec
review: add unit tests for UsdFileSink, Convert, sinks, options, fact…
marcschier 332335c
review: remove dead IntentFromTypeId, use named type-id consts, add D…
marcschier 8b565f3
review: net48 test compat (avoid DateTime.UnixEpoch), dispose connect…
marcschier f3091fb
review: add OpenUsd.Client and Robotics.Client unit test project sources
marcschier 0e0112d
Merge origin/master into marcschier/openusd-integration
marcschier d3ba2ad
robot sample: create robotics instances via generated CreateInstanceO…
marcschier 6ec1482
Use INullable semantics in OpenUSD APIs
marcschier 2e1268e
Add referenced-model fluent accessor generation
marcschier 8752610
Add common OPC UA Robotics contracts
marcschier 21efcf1
Add fluent OPC UA Robotics server hosting
marcschier 904d088
Add fluent OPC UA Robotics topology builders
marcschier e83b999
Add OPC UA RSL and GPOS positioning support
marcschier f52e80b
Generate typed NodeSet method signatures
marcschier d9436e3
Merge remote-tracking branch 'origin/marcschier/openusd-integration' …
marcschier afe21af
Merge remote-tracking branch 'origin/master' into marcschier/robotics…
marcschier 0748861
Add Robotics package documentation
marcschier 2c5c1a5
Address PR review feedback on the Robotics SDK
marcschier e418545
OpenUSD: fix critical/high spec-conformance defects (Part 1 0.3.0)
marcschier 1b84b67
Remove reintroduced AsBoxedObject uses in the OpenUSD connector
marcschier e474273
Add standard Robotics operations, Programs, and a shared FileDirector…
marcschier 5dadd32
Add Robotics operation conventions and the high-level client facade
marcschier 8a653f7
Migrate MinimalRobotServer onto the stock Robotics hosting
marcschier 808894b
Split Robotics server tests into a dedicated project and fix a net48 …
marcschier be15437
Add the OpenUSD Scene Materialization (Part 2) companion SDK
marcschier 474273f
Use the new ConnectionPaths member instead of a side channel
marcschier a408a7d
Add an in-process OpenUSD viewport to the connector behind --view
marcschier afaf9c6
Model the robot cell on a real KUKA KR 16-2 and give it a pick-and-pl…
marcschier f0c1a3c
Make the pump twin a real EN 733 pump that visibly runs
marcschier 2de0c54
Fix the net8.0 build and the pump E2E expectation after the viewport …
marcschier 62ba83c
Sample the mobile robot's frame atomically in the positioning E2E tests
marcschier 53c50e8
Merge origin/master into marcschier/robotics-3827-api
marcschier 4e62c5a
Merge origin/master into marcschier/robotics-3827-api
marcschier 1870c69
Merge origin/master into marcschier/robotics-3827-api
marcschier 95a4dbb
Consume the OpenUSD packages from nuget.org and add the viewer to UA.…
marcschier f47e899
Stop node copies from consuming NodeIds from the NodeIdFactory
marcschier 362a6ab
Address PR review feedback: docs, naming, and file layout
marcschier f4474e6
Merge the Robotics and OpenUSD test projects per review feedback
marcschier 1236122
Put the call on the assignment line where it fits
marcschier 6a63237
Unify the GPS provider seam behind one IGeoLocationProvider
marcschier 8320f83
Poll a geo location provider that cannot push
marcschier 92c8238
Fix security review findings and correct a stale-generator test baseline
marcschier 93b41b1
Restore the pump NodeId baseline
marcschier 1705eef
Keep the inherited method declaration when an override keeps its sign…
marcschier 67d45f2
Resolve unqualified file system path segments in the provider namespace
marcschier 190e053
Skip single-TFM projects in solution builds pinned to another framework
marcschier 8f46468
Cover the OpenUSD connector, sinks and scene server with unit tests
marcschier 7a07782
Merge origin/master into marcschier/robotics-3827-api
marcschier 512feae
Fix the net4x build break and the pump baseline found while splitting…
marcschier File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,151 @@ | ||
| # OPC UA — OpenUSD binding | ||
|
|
||
| This guide covers the client- and server-side libraries that bridge an OPC UA address space to an | ||
| [OpenUSD](https://openusd.org/) stage. For the OPC 40010 Robotics companion SDK used to label and drive robot-cell | ||
| twins, see [Robotics](Robotics.md). | ||
|
|
||
| > The OPC UA — OpenUSD Bindings companion model is a **draft** (experimental) model. The type NodeIds and the | ||
| > `Server/OpenUSD/Representations` registry described here are subject to change until the companion specification is | ||
| > ratified. | ||
|
|
||
| ## Libraries | ||
|
|
||
| | Package | Role | | ||
| | --- | --- | | ||
| | `OPCFoundation.NetStandard.Opc.Ua.OpenUsd` | The draft OpenUSD-binding companion model (source-generated NodeStates). | | ||
| | `OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Client` | The generic, domain-agnostic `OpenUsdConnector`, the `IUsdSink` abstraction, and the file/mock sinks. | | ||
| | `OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Server` | Server-side authoring helpers (`UsdAssetDelivery`, representation authoring). | | ||
| | `OPCFoundation.NetStandard.Opc.Ua.OpenUsd.Connector` | A ready-to-run console connector tool built on the client library. | | ||
|
|
||
| ## The connector | ||
|
|
||
| `OpenUsdConnector` is a **client**: it discovers a server's `OpenUsdRepresentation` instances through the Part 1 | ||
| `Server/OpenUSD/Representations` registry, subscribes to the bound source Variables, applies the declared conversion, | ||
| and writes the target USD attributes into an `IUsdSink`. It is domain-agnostic — it knows only the OpenUSD binding | ||
| model, never "pump" or "robot". | ||
|
|
||
| ### Progressive API | ||
|
|
||
| The simplest usage needs only a connected session and a sink: | ||
|
|
||
| ```csharp | ||
| using Opc.Ua.OpenUsd.Client; | ||
|
|
||
| // session is a connected ISession (for example a ManagedSession). | ||
| var sink = new UsdFileSink("live.usda"); | ||
| await using var connector = new OpenUsdConnector(session, sink); | ||
|
|
||
| await connector.StartAsync(cancellationToken); // discover + subscribe + compose | ||
| // ... the sink now receives live updates ... | ||
| await connector.StopAsync(cancellationToken); // stop streaming | ||
| ``` | ||
|
|
||
| `OpenUsdConnector` implements `IAsyncDisposable`; `await using` (or an explicit `DisposeAsync`) stops streaming and | ||
| closes any connector-owned remote sessions opened for cross-server federation. The caller-provided primary session is | ||
| never closed by the connector. | ||
|
|
||
| Advanced behaviour is configured through `OpenUsdConnectorOptions`: | ||
|
|
||
| ```csharp | ||
| var options = new OpenUsdConnectorOptions | ||
| { | ||
| EnableCommands = true, // opt in to UsdToUaCommand actuation (fail-closed by default) | ||
| RemoteSessionFactory = (endpointUrl, ct) => OpenRemoteSessionAsync(endpointUrl, ct), // §5.14 cross-server federation | ||
| MaxAssetBytes = 32 * 1024 * 1024, // per-asset read cap | ||
| MaxTotalAssetBytes = 128L * 1024 * 1024, // per-fetch read cap | ||
| }; | ||
| await using var connector = new OpenUsdConnector(session, sink, options, telemetry); | ||
| ``` | ||
|
|
||
| ### Values cross the boundary as `Variant` | ||
|
|
||
| `IUsdSink` never exposes `object`. A scalar attribute is a `double`, a colour is a three-element `float` array | ||
| (`ArrayOf<float>`), and a token/visibility value is a `string` — all carried as `Variant`: | ||
|
|
||
| ```csharp | ||
| public interface IUsdSink | ||
| { | ||
| void SetAttribute(string primPath, string propertyName, Variant value); | ||
| void SetTimeSample(string primPath, string propertyName, DateTime time, Variant value); | ||
| void ComposePrim(string primPath, OpenUsdCompositionArc arc, string? assetReference, bool active); | ||
| IDisposable BeginBatch(); | ||
| } | ||
| ``` | ||
|
|
||
| Two sinks ship in the box: | ||
|
|
||
| * `UsdFileSink` authors a text USD override layer (`live.usda`). It validates every prim-path segment and property | ||
| name as a USD identifier, escapes token values, and rejects unsafe asset references, so a hostile or malformed name | ||
| from the server cannot corrupt or inject into the layer. | ||
| * `MockUsdSink` is an in-memory, thread-safe sink used by tests and diagnostics. | ||
|
|
||
| `BeginBatch()` lets a file-backed sink defer flushes; history replay uses it to author many time samples with a single | ||
| file write. | ||
|
|
||
| ### History replay and commands | ||
|
|
||
| * `ReplayHistoryAsync(startTime, endTime, ct)` replays Part 11 history for every `UaHistoryToUsd` binding, following | ||
| continuation points and authoring the returned values as USD time samples. Sources that do not historize degrade to | ||
| zero samples without throwing. | ||
| * `IssueCommandAsync(value, ct)` actuates the opt-in `UsdToUaCommand` binding. It is **fail-closed**: it throws unless | ||
| the connector was constructed with `EnableCommands = true`. | ||
|
|
||
| ### Integrity | ||
|
|
||
| When a stage advertises a `RootLayerDigest`, the connector verifies it (constant-time) before authoring any opinions, | ||
| and refuses to compose on a mismatch. Served asset closures (`FetchServedAssetsAsync`) are streamed through the Part 5 | ||
| `FileType`, digest-verified fail-closed, and cached under sanitized relative paths (path-traversal is defended). | ||
|
|
||
| ## Dependency injection | ||
|
|
||
| Both a standalone `IServiceCollection` extension and the fluent `IOpcUaClientBuilder` extension register the singleton | ||
| `OpenUsdConnectorFactory`; the direct constructors remain available as a non-DI fallback. | ||
|
|
||
| ```csharp | ||
| // Standalone. | ||
| services.AddOpenUsdConnector(o => o.EnableCommands = true); | ||
|
|
||
| // Fluent, chained onto the client builder. | ||
| services.AddOpcUa() | ||
| .AddClient(configuration) | ||
| .AddOpenUsdConnector(o => o.MaxAssetBytes = 32 * 1024 * 1024); | ||
| ``` | ||
|
|
||
| Resolve the factory and create a connector per connected session: | ||
|
|
||
| ```csharp | ||
| public sealed class TwinWorker(OpenUsdConnectorFactory connectors) | ||
| { | ||
| public async Task RunAsync(ISession session, IUsdSink sink, CancellationToken ct) | ||
| { | ||
| await using OpenUsdConnector connector = connectors.Create(session, sink); | ||
| await connector.StartAsync(ct); | ||
| // ... | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| Observability is threaded through `ITelemetryContext` (resolved from DI), which the factory passes to each connector. | ||
|
|
||
| ## Server-side authoring | ||
|
|
||
| `UsdAssetDelivery.AttachStageAssets(context, stage, openUsdNs, assets)` serves artist-authored USD layers through the | ||
| address space as read-only Part 5 files with SHA-256 digests, so a generic connector can fetch, verify, cache, and | ||
| render the twin with no external asset resolver. `assets` is an `ArrayOf<ServedAsset>` and the method returns the | ||
| created `OpenUsdAssetState` nodes as an `ArrayOf<OpenUsdAssetState>`. | ||
|
|
||
| ## Samples | ||
|
|
||
| * [`MinimalRobotServer`](../samples/MinimalRobotServer) — a self-contained server exposing an OPC 40010 | ||
| MotionDeviceSystem with two independently mobile robots. OPC 10000-210 RSL | ||
| frames drive live `double3` translation/rotation, and OPC 10000-211 GPOS | ||
| locations drive geospatial metadata; a generic connector renders the cell | ||
| live. See [Positioning](Positioning.md). | ||
| * [`PumpDeviceIntegrationServer`](../samples/PumpDeviceIntegrationServer) — a DI pump line bound to OpenUSD, including | ||
| component composition, cross-server components, and served-asset delivery. | ||
|
|
||
| ## The connector tool | ||
|
|
||
| `Opc.Ua.OpenUsd.Connector` is a console application that connects to any server implementing the draft binding, | ||
| discovers `Server/OpenUSD/Representations`, subscribes, optionally fetches the served asset closure, and authors a live | ||
| `live.usda` override layer. It is the end-to-end reference for the client library. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.