# Description Implement the released [OPC 40100-1](https://reference.opcfoundation.org/specs/OPC-40100-1) and [OPC 40100-2](https://reference.opcfoundation.org/specs/OPC-40100-2) specifications with generated models, provider-backed runtimes, typed clients, MCP workflows, and DI/Machinery integration. - **Part 1 stays in `Opc.Ua.Vision`** and its client/server packages alongside the distinct Perception model. Provide control/acquisition state machines, jobs and synchronized steps, recipe/product/configuration/result management, file transfers, diagnostics, events, and conditions. - **Part 2 is in `Opc.Ua.MachineVision`, `.Client`, and `.Server`.** Provide asset categories, identification, image-handling aspects, health/maintenance data, topology, and transactional updates. The base Vision assemblies do not reference these optional packages; the Part 2 wire model does not depend on Part 1. - Preserve the release-pinned model bytes, wire namespaces and NodeIds. Perception types are in `Opc.Ua.Vision.Perception`; the AMCM generated namespace remains `Opc.Ua.Vision.MachineVision.AMCM`, and asset client/server extension namespaces remain `Opc.Ua.Vision.Client` and `Opc.Ua.Vision.Server`. - Use `AddOpcUaMachineVision` and `AddOpcUaMachineVisionAMCM` for model loading and factory registration. Each has node-collection, encodeable-factory-builder and node-state-factory-builder overloads. These short entry points delegate to the generated implementations; existing namespace-derived generated names remain available for compatibility. - Support multiple independent named systems/assets under one namespace-owning manager. Reuse injectable providers, file binding, bounded memory stores, optional transactional `IFileSystemProvider` persistence, state machines, telemetry and conformance infrastructure. - Keep one `docs/Vision.md` guide, titled `Machine Vision (OPC 40100-1 and OPC 40100-2)`, and one `Opc.Ua.Mcp.Vision` package. Include deterministic server/client samples. - Expose 17 Machine Vision MCP tools, including capabilities/status, bounded relationships and observation, complete small-file uploads/downloads, management, explicit control, conditions, and chunked transfers. Catalogue counts: 39 Vision-specific, 43 with connection tools, 81 Vision+Robotics, 155 Full. Every Machine Vision wire parameter has a schema description. **Compatibility and limits:** `AddVision()` remains Perception-only unless released parts are selected. Standalone Part 2 uses `AddVision().AddMachineVision()`; Machinery composition uses `AddVisionToMachinery()`. Existing tool defaults and command signatures are preserved. Observation owns and cleans up its subscription: 5 seconds/50 notifications by default, capped at 60 seconds/100 notifications. Complete-file tools are capped at 1 MiB; larger files use chunked transfers. Domain Error values remain distinct from UA service failures. **Versioning:** the seven Vision/MachineVision/MCP packages and their Debug variants follow the repository root version instead of being forced to preview. Vision.OpenUsd and its descendants remain preview-only. Development builds still inherit the root prerelease version. No release version, tag, release branch, publication policy, or feed promotion is changed. **Review actions:** all fourteen review threads have action/evidence replies and are resolved. Changes include the unified guide, Perception namespace, separate Part 2 packages and final naming, multi-system ownership explanation, interrupted-write cleanup, observer failure isolation, complete MCP parameter descriptions, and explicit package inventory. The preview-layout migration topic and the requested ReleaseProcess caveat were removed. The test Publish collector now retries recognized transient failures within one cancellation budget and propagates other exceptions. Commit69b1f5db9applies the requested short loader names and renames standalone hosting to `AddMachineVision`, with callers, tests and documentation updated. The intervening master merge is preserved. ### Verification **Latest API naming changes, verified locally:** | Scope | Result | | --- | --- | | Full Vision suite, net10 | 572 passed, 1 existing skip, 0 failed | | Full Vision suite, net48 | 515 passed, 0 skipped, 0 failed | | Final loader/hosting cases after cross-TFM null-guard adjustment | 9 passed, 0 failed, 0 skipped | | Machine Vision MCP and profile cases | 198 passed, 0 failed, 0 skipped | | Main and MCP AOT test-project compilation | Both built with 0 warnings/errors | | MCP AOT companion, managed execution | 5 passed, 0 failed, 0 skipped; not claimed as native execution | `ModelLoaderNamesRegisterTypedFactories`, `ModelLoaderNamesRejectNullArguments`, and `GeneratedModelsLoadTogetherAndCreateTypedInstances` cover all six loader overloads, fluent return identities, typed instances, namespace coexistence and null guards. Existing standalone Part 2 tests verify idempotent registration, one-owner enforcement and null handling through `AddMachineVision`. No source-generator implementation, CLR namespace, wire identity or model payload was changed for these naming updates. The current69b1f5db9revision is running [CI](https://github.com/OPCFoundation/UA-.NETStandard/actions/runs/38165826937), [package validation](https://github.com/OPCFoundation/UA-.NETStandard/actions/runs/38165823359), [MCP usability](https://github.com/OPCFoundation/UA-.NETStandard/actions/runs/38165826874), [CodeQL](https://github.com/OPCFoundation/UA-.NETStandard/actions/runs/38165826906), and [Images CI](https://github.com/OPCFoundation/UA-.NETStandard/actions/runs/38165826884). These runs are not claimed as completed results. **Earlier completed verification:** all seven default-TFM package archives were inspected after the package rename: exact IDs, 27 clean DLLs, correct dependencies/readmes/licenses, and unchanged pinned model hashes. [CI onc75ec4fa6](https://github.com/OPCFoundation/UA-.NETStandard/actions/runs/38142519760) passed, including the formerly failing Linux batch and required summary. Its unchanged coverage gate passed at **88.56% lines, 78.96% branches, 84.28% patch** against the 75% patch floor. The later bounded-Publish-helper regressions reproduced 13 failures before the fix and passed afterward; the full mainline triggering fixture passed 67 tests on each of net10/net48. These are historical results, not current full-matrix results. <details> <summary>Executed API naming validation commands and outcomes</summary> Run from the worktree root using the established artifact trees. Dependency builds were performed before the no-build full net10 run; the focused loader/hosting selection was rebuilt and rerun after the final null-guard adjustment. ```powershell $files = 'C:\Users\mschier\.copilot\session-state\deb2ba10-b0e9-4a44-8783-8331bc850814\files' $env:DOTNET_CLI_USE_MSBUILD_SERVER = '0' $env:TEMP = 'C:\Temp\mv-deb2\followup' $env:TMP = $env:TEMP # Passed: 572; Failed: 0; Skipped: 1. dotnet test tests\Opc.Ua.Vision.Tests\Opc.Ua.Vision.Tests.csproj -c Release -f net10.0 --no-build --no-restore --artifacts-path artifacts\vision-followup -p:CustomTestTarget=net10.0 -p:UseSharedCompilation=false -m:1 -nr:false --logger 'console;verbosity=minimal' --logger trx --results-directory "$files\vision-api-names-net10" -- 'NUnit.WorkDirectory=C:\Temp\mv-deb2\followup' # Passed: 9; Failed: 0; Skipped: 0, on the final source. dotnet test tests\Opc.Ua.Vision.Tests\Opc.Ua.Vision.Tests.csproj -c Release -f net10.0 --no-restore --artifacts-path artifacts\vision-followup -p:CustomTestTarget=net10.0 -p:UseSharedCompilation=false -m:1 -nr:false --filter 'FullyQualifiedName~MachineVisionModelTests|FullyQualifiedName~StandalonePartTwoRegistrationUsesOneOwnerAndOneModelProvider|FullyQualifiedName~StandalonePartTwoRequiresRegistrationAndRejectsCompetingOwnership' --logger 'console;verbosity=minimal' --logger trx --results-directory "$files\vision-api-names-final-model" -- 'NUnit.WorkDirectory=C:\Temp\mv-deb2\followup' # Passed: 198; Failed: 0; Skipped: 0. dotnet test tests\Opc.Ua.Tools.Tests\Opc.Ua.Tools.Tests.csproj -c Release -f net10.0 --no-restore --artifacts-path artifacts\vision-followup -p:CustomTestTarget=net10.0 -p:UseSharedCompilation=false -m:1 -nr:false --filter 'FullyQualifiedName~VisionMachineToolsTests|FullyQualifiedName~McpHostBuilderTests|FullyQualifiedName~McpToolProfileCompositionTests' --logger 'console;verbosity=minimal' --logger trx --results-directory "$files\vision-api-names-final-mcp" -- 'NUnit.WorkDirectory=C:\Temp\mv-deb2\followup' $env:TEMP = 'C:\Temp\mv-deb2\followup48' $env:TMP = $env:TEMP # Passed: 515; Failed: 0; Skipped: 0. dotnet test tests\Opc.Ua.Vision.Tests\Opc.Ua.Vision.Tests.csproj -c Debug -f net48 --no-restore --artifacts-path "$files\solution-net48-artifacts" -p:CustomTestTarget=net48 -p:UseSharedCompilation=false -m:1 -nr:false --logger 'console;verbosity=minimal' --logger trx --results-directory "$files\vision-api-names-net48-final" -- 'NUnit.WorkDirectory=C:\Temp\mv-deb2\followup48' ``` Opt-in long-running/stress/durable tiers have not been rerun locally; the unqualified **all tests** checklist item remains open. Original implementation matrix counts are not presented as current results. </details> ## Related Issues - Fixes #4732. The requester reviewed and approved the implementation plan and subsequent packaging/API decisions in the development session. The tracking issue records the design; maintainer architectural discussion/sign-off there is still pending. This PR remains a draft. ## Checklist _Put an `x` in the boxes that apply. You can complete these step by step after opening the PR._ - [ ] I have signed the [CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf) and read the [CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md) doc. - [x] I have added tests that prove my fix is effective or that my feature works and increased code coverage. - [x] I have added all necessary documentation. - [x] I have verified that my changes do not introduce (new) build or analyzer warnings. - [ ] I ran **all** tests locally using the **UA.slnx** solution against at least .net **framework** and .net **10**, and all passed. - [ ] I fixed **all** failing and flaky tests in the CI pipelines and **all** CodeQL warnings. - [x] I have addressed **all** PR feedback received.
Bin Picking Cell
Reference server for the vision-guided bin-picking sample. Hosts a branch-stable four-axis palletizer as a Robot Intent controller, a Vision companion with an eye-in-hand camera parented to the flange, an in-address-space OpenUSD scene, and the frame tree the Robotics-Vision Addendum's example uses:
world → robot_base → flange → gripper_tcp
↳ camera_eih
flowchart TD
World["world<br/>/World"] --> Base["robot_base<br/>/World/Robot/Palletizer/Base"]
Base --> Flange["flange<br/>/World/Robot/Palletizer/.../Flange"]
Flange --> Tcp["gripper_tcp<br/>/World/Robot/Palletizer/.../Flange/Gripper/Tcp"]
Flange --> Camera["camera_eih<br/>/World/Robot/Palletizer/.../Flange/Camera"]
Five parts (RedCube, GreenCylinder, BlueSphere, YellowSlab,
OrangeBrick) sit in a bin on the workbench; a fixture is placed next
to it. The sample's paired client at
samples/Robotics/BinPickingClient runs the
perception-to-action loop against this server, either as a scripted
demo or under the control of an MCP-connected language model.
The cell is the example that motivates the Vision developer
guide — every §5.12 convention (quaternion
(x, y, z, w), metres, corner-datum principal point, empty-covariance
sentinel), every §6.4 media state and every facet the guide lists
appears in the cell's address space.
Running
Prerequisites: .NET 10 SDK.
dotnet run --project samples\Robotics\BinPickingCell\BinPickingCell.csproj -- --insecure
The server listens on opc.tcp://localhost:62855/BinPickingCell by
default. The endpoint URL and port are configurable through
--host <name> and --port <number>; the anonymous operator role is
mapped in code so the demo client can connect without user credentials.
--insecure is a demo convenience: it accepts any client certificate
and does not enforce trust. Do not use it in production.
Inference-location option
The cell selects one perception path once at startup and pins it for the lifetime of the process. The pipeline's advertised inference- location facet is derived from this and cannot change afterwards, so the cell always tells the truth about which path is in force.
--inferenceLocation OnServer(default) — the deterministicBinPickingGroundTruthInferenceProvidercomputesDetectionResultTyperesults locally. The pipeline advertisesVIS-Inference-OnServer, needs no GPU, no model and no network, and is what CI runs.--inferenceLocation EdgeOffServer— the pipeline exposes aVisionFeedbackTypebound toBinPickingAgentInferenceProvider; an agent connected over MCP looks at the frame and callsSubmitDetections. The pipeline advertisesVIS-Inference-OffServerand publishes results the Server itself did not compute.RunInferenceandStartContinuousare refused withBad_NotSupported— a client requesting an on-Server compute path in this mode gets an actionable refusal, not a silent stub.
The two paths are exclusive by construction: a pipeline binds either an inference provider or a feedback sink, never both at once, because mixing them would let a computed and a submitted result publish on the same pipeline out of any known order.
Startup options
| Option | Meaning |
|---|---|
--host <name> |
Endpoint host name. Default localhost. |
--port <number> |
Endpoint port. Default 62855. |
--inferenceLocation OnServer|EdgeOffServer |
Selects the perception path. OnServer is the default. |
--captureOnStartup true|false |
Whether the capture-proof hosted service captures a still on startup and writes it to disk (see below). Default true. |
--artifactDirectory <path> |
Where the capture-proof hosted service writes its still. Defaults to a temp path chosen by the host. |
--insecure |
Demo-only, per the note above. |
The parser accepts OnServer, EdgeOffServer, OffServer,
on-server, off-server and their case-insensitive variants for
--inferenceLocation. Unknown values silently fall back to OnServer
rather than failing to start.
What the cell publishes
- Under
Server/RobotIntent, one Robot Intent controller (BinPickingController) with four axes (J1base yaw,J2shoulder,J3elbow andJ4tool roll), lookup tables forBin,Fixture, one home location per part andParallelGripper. The controller shipsPickandPlaceintents targeting the sample parts. - Under
Server/Vision:- The frame tree above. Every frame carries a unit
(x, y, z, w)quaternion and a metres-based position;camera_eihis authored with theEyeInHandhand-eye pose the addendum specifies. BinPickingCameraTwin, anImageSensorTypewithRealityKind = Simulated,Modality = Area2D, anIntrinsicCalibrationType(Zhang method, residual 0.21 pixels), aHandEyeExtrinsicCalibrationType(EyeInHandmount, residual 0.0008), anIVisionSimulatedTypeinterface pointing at the USD stage andCameraprim, a live RTSPStreamEndpointTypeand aPickFramesClipEndpointTypewith inline delivery enabled up to 32 MiB.BinPickingPipeline(InferencePipelineType) bound to the sensor twin, with the deployment referenceOnServerDeploymentand either the ground-truth inference provider or the agent inference provider depending on--inferenceLocation.
- The frame tree above. Every frame carries a unit
- Under
Server/OpenUSD, the composedCell.usdastage the sensor renders from. - Under
Server/WorldState, one position variable per part, in the world frame. This is the cell's simulation ground truth, not a standard OPC UA concept: a part lying in a bin is not something Robot Intent or Vision models, and the scene has to be drivable from the address space to be watchable. The OpenUSD live bindings follow these variables, so a picked part moves in the viewport, and a client comparing what the detector claims against where the part actually is has both halves.
The USD stage
The scene is authored in Assets/Cell.usda and is extracted at
startup by BinPickingCellStage.Extract() into a working directory the
BinPickingMediaProvider and OpenUsdSceneCameraCaptureProvider share.
It references the cell-specific palletizer-arm.usda and
palletizer-gripper.usda assets, plus the shared gripper geometry, adds
the bin, fixture and parts, and parents the eye-in-hand UsdGeomCamera
to the flange so the view moves with the arm.
Scene lighting is load-bearing
The stage is lit by a single DomeLight at intensity 1000.
Do not reintroduce a DistantLight — at any intensity that shows
geometry, a DistantLight blows every surface to pure white regardless
of material, and the point of this cell is that a vision-language model
can pick "the red cube" by looking at the frame. Under a DomeLight
the five parts measure red (220, 37, 37), green (37, 208, 49),
blue (37, 73, 233) — distinct enough for an LLM to reason about.
The Cell.usda header records this contract explicitly so a future
scene-authoring change does not silently break the perception path.
Frame tree contract
/Worldis theworldframe origin./World/Robot/Palletizer/Baseis therobot_baseframe./World/Robot/Palletizer/Base/J1/J2/J3/Leveling/J4/Flangeis theflange(mechanical interface)./World/Robot/Palletizer/.../Flange/Camerais thecamera_eihUsdGeomCamerathe Vision sensor renders from./World/Robot/Palletizer/.../Flange/Gripper/Tcpisgripper_tcp.
The vision-side flange frame is authored at the scan pose the arm
would hold to point the eye-in-hand camera at the bin. In a live cell
the flange frame is dynamic and reflects the current joint state; for
this static-sample demo it is pinned to the scan pose so a consumer
composing camera_eih → flange → robot_base → world lands on the parts'
authored world positions — which is exactly what the ground-truth
detector reports for each detection's Pose. This is why the vision-
side frame ids match the robot-side frame ids exactly: the client can
compose a detection's pose from the camera into the world frame using
VisionFrameGraph and get a value it can hand straight to the robot-
side Pick intent.
The scan pose is one analytic palletizer configuration: TCP
(0.60, 0, 0.32) and flange (0.60, 0, 0.505) in robot_base.
The camera is 20 mm along flange +X and 160 mm along flange +Z,
which composes to world position (0.60, -0.16, 1.405). The extra
180-degree camera convention transform accounts for USD cameras
looking down local -Z while Vision projection uses camera-forward
+Z.
The visual and numeric chain use the same geometry:
- shoulder height 0.280 m;
- upper arm and forearm 0.480 m each;
- flange-to-jaw-centre TCP 0.185 m along flange
+X; - mechanical leveling
90° - J2 - J3, so the tool remains vertical; J4rolls around the down-facing tool axis, keeping jaw aperture visible without introducing offset-wrist IK branches.
The analytic IK emits at most the two real elbow branches, rejects unsupported pitch or roll, and chooses the nearest collision-clear branch. It does not generate periodic duplicates or run a numerical seed search, so a Cartesian leg cannot silently switch to an identical- looking but discontinuous wrist configuration.
Detected-pose picking and collision
Pick targets the selected detection pose, not the containing
Location's centre. The target provider stores result id, timestamp,
source frame and world pose by class label. Off-server detections must
use the calibrated camera_eih frame and remain within 80 mm of the
simulated part; targets expire after ten seconds. Only the built-in
on-server ground-truth path may fall back to current simulation state.
Motion retracts vertically, crosses at a clear height, descends, closes or opens the jaws, and reverses the exact local approach before the operation completes. A following Pick at the same fixture XY skips the cross-cell traverse. The collision model uses per-link radii and tests the bench, bin walls, fixture plate and pegs, every non-target part, the accumulated stack, and an explicit box swept by the held part.
What an agent actually receives
vision_get_frame (MCP) and GetClip (OPC UA) return a 612 × 512
PNG, delivered as inline bytes in the method's ByteString output and
base64-encoded into the MCP ImageContentBlock. The
VisionImageReferenceDataType alongside it carries a
opcua-inline://… reference and the frame's dimensions — it does not
carry the image, which would ship the payload twice.
612 × 512 is what the sensor declares, what the clip endpoint declares, what the intrinsics describe and what the renderer produces. The simulated device is a 2448 × 2048 area-scan camera operated with 4 × 4 binning, so the calibrated intrinsics are divided by four and the Brown-Conrady coefficients — expressed in normalised image coordinates — carry over unchanged. The native size survives only in the model and serial number, where it identifies the hardware rather than the image.
This matters because the ground-truth detector projects through the
declared intrinsics: the BoundingBox2D on every detection is in the
same pixel frame as the PNG an agent was handed. Previously the sensor
said 2448 × 2048, the clip endpoint said 1280 × 1024 and the renderer
produced 640 × 512 — not even the same aspect ratio — so a model asked
to "pick the red cube you can see" got a picture and a set of
coordinates that pointed off it.
After a successful GetClip, the Server publishes the frame on the clip
endpoint's LatestClip and its descriptor on LatestClipMetadata, so a
consumer that follows the model — read the published frame, call the
method only if there is none — gets a frame rather than a permanent
Bad_NoDataAvailable.
Rendering behaviour on CI
The Opc.Ua.Vision.OpenUsd capture provider needs a native OpenUSD
renderer payload plus a usable graphics device to produce pixels. On CI
neither is present — the provider reports
SceneCameraCaptureBackend.NoRenderingBackend on UnavailableReason,
and every LatestClip read against PickFrames reports
Bad_NoDataAvailable. The sensor still exists in the address space,
every browse still works, every calibration is still readable and the
inference proof hosted service still updates the world state.
This is by design: the point of the CI leg is to exercise the address
space, the fluent builder, the provider abstractions and the client
plumbing, not to prove that the machine has a GPU. --demo on the
paired client skips its "compose frame → world" step gracefully when
the frame is unavailable rather than falsely reporting a rendering
failure.
On a workstation with the renderer payload installed and a usable
graphics device, the same sensor renders normally and returns encoded
PNG bytes through the inline LatestClip or the by-reference
GetClip path.
Ground-truth vs agent inference
- Ground-truth path (
--inferenceLocation OnServer):BinPickingGroundTruthInferenceProviderreads the current world state fromBinPickingWorldState, projects each part into the camera through the authoredHandEyetransform and intrinsics, and publishes aDetectionResultTypewith the corresponding class label, bounding box and pose. Because this reads real geometry, the poses it publishes are the ones a correct agent would submit — which is what makes the ground-truth path useful as a check on an agent's answer. - Agent path (
--inferenceLocation EdgeOffServer):BinPickingAgentInferenceProvideris the sample's off-Server feedback sink.SubmitDetections,SubmitCorrectionandSubmitImageReferenceare accepted;RunInference,StartContinuous,StopandSubmitInspectionResultare refused withBad_NotSupportedbecause this pipeline exposesDetectionResultTyperesults only and has no on-Server compute path. The agent's submissions are validated before they land — see below.
Two hosted services publish loop-proof output regardless of MCP being attached:
BinPickingCaptureProofcaptures a still on startup (skipped with--captureOnStartup false), writes it to--artifactDirectorywhen set, and logs the resulting size or theNoRenderingBackendreason. Useful for verifying the render path from a CI leg.BinPickingInferenceProof(on-server) drives one round of the deterministic detector and mutatesBinPickingWorldState, orBinPickingOffServerProof(off-server) drives one round of agent submissions with valid detections. Both prove the end-to-end write path independently of the MCP tool surface. The on-server proof restores the bin afterwards: it runs before any client connects, and leaving a part picked would mean the paired client's demo started against a world it had not changed itself.
The robot moves the parts too. Pick travels to its Source, closes the
gripper around the current pose of the part named by the intent's
ObjectClass, marks it held only after the jaws finish closing, then
retracts. The part's world position follows the tool until Place
opens the gripper, settles it on the highest support, and retracts. The
ground-truth detector projects from those same positions, so it stops
reporting a part that has been moved out of the bin — which is what
makes the paired client's --demo verification real rather than a
formality.
Feedback validation
When an agent submits detections through
vision_submit_detections (or vision_submit_correction), the sample's
feedback sink validates every field and refuses malformed submissions
with Bad_InvalidArgument and a message the agent can act on:
- Unknown class label — refused with the exact list of parts that
do exist:
Detection 0 class 'PurplePyramid' is not a part in this cell. Known classes: RedCube, GreenCylinder, BlueSphere, YellowSlab, OrangeBrick. - Confidence outside
[0, 1]— refused with the observed value. - Bounding box outside the image — refused with the box centre, extents and the image dimensions.
- Non-positive box extents — refused with the extents.
NaNin a box or pose — refused with the detection index.- Zero-norm quaternion or
Orientationwith fewer than four components — refused with an explanation that references §5.12. Positionwith fewer than three components — refused likewise.- Pose frame other than
camera_eih— refused with both the submitted and calibrated frame ids. - Pose more than 80 mm from the matching simulated part — refused with the measured residual.
- Purpose not in
Overlay | Reconciliation | GroundTruthLabel | Trigger— refused with the offending value. - More than 15 detections in a single submission — refused as implausible for the five-part cell.
An empty detection set is refused too. §9.5 lists "Detections
empty" as Bad_InvalidArgument, and requires SubmitCorrection to
carry exactly one non-empty corrected array. The cell conforms, which
has a consequence worth knowing: an agent that has emptied the bin
cannot report "I looked and there is nothing there", and a false
positive cannot be retracted by correcting a result down to nothing.
Both are raised against the draft rather than worked around here — see
the Vision developer guide.
SubmitInspectionResult is refused with Bad_NotSupported regardless
of the arguments: this pipeline is a detection pipeline, not an
inspection pipeline, and an agent submitting an inspection result is
confused about which pipeline this is.
Related samples and docs
- BinPickingClient — the paired client, with
--demofor the scripted loop and--mcpfor an agent-driven one. - Vision developer guide — the
companion documentation for
Opc.Ua.Vision*andOpc.Ua.Mcp.Vision. - Robotics developer guide — the sibling companion; the Robot Intent controller in this cell is the topic of that guide.
- OpenUSD guide — the connector and scene materialisation used to bind the address space to the USD stage.
- MCP Server guide — profile composition
(
--profile vision,robotics), tool tables and connection semantics.