OpenUSD: the OPC UA to OpenUSD binding, scene materialization and connector - #4126
Merged
marcschier merged 3 commits intoAug 1, 2026
Merged
Conversation
This was referenced Jul 30, 2026
marcschier
marked this pull request as draft
July 30, 2026 14:03
marcschier
marked this pull request as ready for review
July 30, 2026 17:25
cristipogacean
approved these changes
Jul 31, 2026
…nector Fourth in the #4096 stack, on top of the positioning change. - Opc.Ua.OpenUsd and Opc.Ua.OpenUsd.Server carry the binding model: a server describes how its Variables drive USD prims, and serves the USD layers it refers to as Part 5 files with a content digest. - Opc.Ua.OpenUsdScene and Opc.Ua.OpenUsdScene.Server carry scene materialization, including the USDA writer. String values, composition arc references, variant set names and selections, doc and prim names are all escaped now; without that a value carrying a quote or a newline could author its own layer syntax. - Opc.Ua.OpenUsd.Client streams live values into an IUsdSink. CompositeUsdSink fans out to several sinks and the file sink interpolates between server samples so motion is continuous rather than stepped at the publishing interval. - tools/Opc.Ua.OpenUsd.Connector composes a stage from a live server. Its optional in-process viewport lives in a separate assembly probed at run time, so the connector still runs, and says why, when it is absent. Its asset cache and PKI root moved off the shared temp directory to the local application data directory. - PumpDeviceIntegrationServer gains an OpenUSD representation of the pump. The Opc.Ua.OpenUsd.Tests suite is 621 tests. UsdAssetDelivery hashes through SHA256.Create rather than the static HashData, which does not exist on the net472 and net48 targets this test project also builds for. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8cbb8cd0-f0cb-4ab0-bea2-6202fbf69485
marcschier
force-pushed
the
marcschier/3827-4-openusd
branch
from
July 31, 2026 12:01
f10ecaf to
99dcb6d
Compare
…bally Clearing <packageSources> does not re-enable a source that a user or machine level NuGet.config has disabled, so a checkout on a machine that disables nuget.org (common where a corporate feed proxy is configured) ends up with no usable feed at all. Restore then fails for any package that is not already in the global packages folder, which is why only newly introduced packages such as the OpenUSD ones surfaced the problem while everything else restored from cache. Clear <disabledPackageSources> as well so the feed declared here is the one that is actually used. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8cbb8cd0-f0cb-4ab0-bea2-6202fbf69485
marcschier
added a commit
that referenced
this pull request
Aug 1, 2026
#4127) **Stack 5/5** — base #4126. Part of the #4096 split; see #4096 for the overall picture. Closes the API work for #3827. > Review after #4123, #4124, #4125 and #4126. This branch is content-identical to the original #4096 branch, so merging the stack lands exactly what #4096 contained. ## The problem this solves OPC 40010 1.02 defines a rich robot **topology** but **no motion verbs at all** — its actuation surface is the SystemOperation and TaskControl state machines plus a Controller `Programs` directory. Meanwhile [URML](https://github.com/URML-MARS/URML) names OPC UA Robotics as its canonical non-ROS substrate and asks for `MoveTo` / `Grasp` / `Release` methods the companion spec does not define, so today it needs a hand-maintained per-deployment NodeId mapping file. This closes that gap in two clearly separated tiers, and never presents the second as standard. ## Contents **Server** — stock `RoboticsNodeManager`, ordered `IRoboticsModelProvider` composition, `IRoboticsConfigurator` code-behind, and validated fluent topology builders for systems, controllers, motion devices, axes, power trains, motors, gears, drives, safety states, software, task controls and task modules, with the correct OPC 40010 semantic references. **Standard operations** — `AddSystemOperation` and `AddTaskControlOperation` drive the Part 16 state machines. An illegal cause is rejected with `BadInvalidState` before the handler runs; a handler returning a bad `ServiceResult` does not move the machine; and a transition already in flight rejects a concurrent one rather than letting both commit. **Programs** — binds the optional `FileDirectoryType` through the reusable `IFileDirectoryBinder` added in 1/5. **Operation conventions** — opt-in and explicitly non-normative `MoveTo` / `MoveJ` / `MoveL` / `Grasp` / `Release` / `PickFrom` / `PlaceAt` / `SwapTool` / `SetOutput` / `CallProgram`, created **only** in an application-owned namespace — the OPC UA, DI, IA and Robotics namespaces are rejected — plus a generic `AddOperation<TRequest, TResponse>` extension point. **Client** — `RoboticsClient` extends the DI client, is subtype aware throughout, and provides typed topology snapshots, the standard operation and task-control clients, `ProgramsAsync`, streaming observation and a DI factory. Verbs resolve by BrowseName, so no NodeId mapping file is needed. **Sample** — `MinimalRobotServer` composes five models (Robotics, IA, DI, OpenUSD, RSL/GPOS) purely through `IRoboticsModelProvider` contributions, which is the real proof that the stock hosting is sufficient. It follows the published KUKA KR 16-2 kinematics and axis limits with an eased pick-and-place cycle. Also restores the vendor-subtype scanner test held back from 2/5, which uses the Robotics NodeSet as its fixture. ## Defects found and fixed along the way - **`ControllerType.CurrentUser`** is Mandatory in OPC 40010 but was neither built nor validated. Now has a builder and a validation error. - **`MotionDeviceType.TaskControlReference`** was absent because it must target a `TaskControlOperationType` instance that did not exist. Now wired. ## Validation `dotnet build UA.slnx` — 0 errors, 0 warnings. | Suite | Result | | --- | --- | | Opc.Ua.Robotics.Tests | 103 / 0 | | Opc.Ua.OpenUsd.Tests | 635 / 0 | | Opc.Ua.Di.Tests | 342 / 0 | | Opc.Ua.SourceGeneration.Tests | 94 / 0 | | Opc.Ua.Aot.Tests (NativeAOT) | 120 / 0 | --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8cbb8cd0-f0cb-4ab0-bea2-6202fbf69485
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Stack 4/5 — base #4125. Part of the #4096 split; see #4096 for the overall picture.
What this is
The generic OPC UA to OpenUSD binding, scene materialization, and the connector that drives a live stage from a running server.
Contents
Binding (Part 1) —
Opc.Ua.OpenUsdandOpc.Ua.OpenUsd.Server. A server describes how its Variables drive USD prims, and serves the USD layers it refers to as Part 5 files with a content digest.Scene materialization (Part 2) —
Opc.Ua.OpenUsdSceneandOpc.Ua.OpenUsdScene.Server, including the USDA writer.docand prim names were all emitted unescaped, so a value carrying a quote or a newline could author its own layer syntax. Every emit site now goes through the escapers. The tests assert the right property — not that the payload is absent (it legitimately survives inside the escaped literal) but that no payload becomes its own line of layer syntax.Client —
Opc.Ua.OpenUsd.Clientstreams live values into anIUsdSink.CompositeUsdSinkfans out to several sinks; the file sink interpolates between server samples so motion is continuous rather than stepped at the publishing interval.Connector —
tools/Opc.Ua.OpenUsd.Connectorcomposes a stage from a live server. The optional in-process viewport lives in a separate assembly probed at run time, so the connector still runs — and says why — when it is absent.LocalApplicationData.Sample —
PumpDeviceIntegrationServergains an OpenUSD representation of the pump.Notes for the reviewer
Directory.Build.targetschange from 1/5: without it, thenet8.0leg of the per-TFM CI build fails withCS0433because theSystem.Threading.Lockpolyfill collides with the real type.UsdAssetDeliveryhashes throughSHA256.Createrather than the staticHashData, which does not exist on the net472/net48 targets this test project also builds for.Validation
dotnet build UA.slnx— 0 errors, 0 warnings.