Repository navigation
How It Works
Published from
_docs/03-how-it-works.md— edit it there, not here. Changes made in the wiki are overwritten on the next sync.
How the digital twin is put together, and how a control program gets to drive it. The concrete per-vendor setups are on the next page, 04 · PLC connectivity; this one is the design they are all variations on.
This page uses the trade names as they are: 07 · Glossary has them in plain language.
Unity twin the machine: geometry, kinematics, sensors, engineering context
│ a process image, once per cycle
▼
simulation unit one function block per twin device — TwinCAT, real time
│ fieldbus simulated on this side, terminals on the other
▼
control program the thing being tested. It sees terminals, never Unity
Three layers, and the middle one is what makes the result mean anything. The control program is never given a special interface into the simulation: it talks to fieldbus terminals, exactly as it would on the real machine.
The project is built on Open Commissioning, and an Open Commissioning setup always has the same two parts. Everything vendor-shaped is added around them.
The Unity scene is where the twin lives. The model is a hierarchy of parts and components — actors, sensors, drives, cylinders — assembled into a hierarchical kinematic, so a movement applied to a parent carries everything mounted on it. Together with PILLAR Context, each part also carries its engineering context: its type and role, its properties, its metadata. That context is what 05 · Engineering workflow is about.
The scene's Client is the gateway. It aggregates every component in the scene into one interface and owns the connection to the second part.
The simulation unit is a TwinCAT PLC project (SIM_1) holding the same hierarchy and the same
component list as Unity, imported and kept in sync from the Unity side by OC Assistant.
Why TwinCAT, even for a setup that is not Beckhoff. It runs in real time at a 1 ms cycle, and it can host an emulated industrial fieldbus — EtherCAT emulation, emulated PROFINET devices. Real-time execution plus an emulated fieldbus is what lets the behaviour models run under the timing a PLC actually imposes, and it is what makes high-quality field device simulation possible at all. That matters for everything time-critical: drives, safety, fast I/O, and acyclic data exchange.
So TwinCAT here is infrastructure, not a control platform choice. What runs your program is a separate question, and the answer is the next page.
OC Assistant is the orchestration and synchronisation layer between them. It synchronises the model,
the hierarchy and the components between Unity and SIM_1, imports and updates components and their
context, generates the interface GVLs, scans networks and creates emulation units, and manages the
lifecycle of its plugins.
In every setup the control program talks to fieldbus terminals, never to Unity. The twin sits behind the simulated side of the bus.
That is what makes the result mean something: the control program cannot tell it is running against a twin, so nothing about it has to change when it runs against steel. A test rig the program is aware of proves much less.
It is also why SIL and HIL are the same setup — the twin, the simulation unit and the control program are identical, and only where the PLC executes changes:
| Mode | The machine is driven by | Where the PLC runs |
|---|---|---|
| MIL | C# sequences inside Unity | Nowhere — there is no PLC |
| SIL | A real control program | On this PC, on an emulated runtime |
| HIL | The same control program | On real controller hardware |
MIL is for seeing the machine and understanding the process. It proves nothing about a control program, and it is not meant to.
| Package | Provides |
|---|---|
com.open-commissioning.core |
Device components (Cylinder, SensorBinary, DriveSimple, …), the Client gateway and its transport, the hierarchy model |
com.open-commissioning.ui |
The runtime application UI — toolbar, selection, cameras, industrial panels |
com.pillar.context |
The authored engineering context on each part |
Project-specific behaviour is small and lives in Unity/Assets/Demo_1/Scripts/:
ControlBunker, DataReader, GripSensor, PartPressDetector, plus the MIL/ animation
coroutines.
The machine is a prefab — Unity/Assets/Demo_1/Prefabs/Machine_1.prefab — and every scene under
Unity/Assets/Demo_1/Scenes/ instances it. What a scene adds is its vendor's operator panel and the
Client for that setup:
| Scene | Adds |
|---|---|
VC_Demo_1_MIL |
Nothing — the machine, driven by the C# sequences |
VC_Demo_1_Beckhoff_1 |
H_ControlPanel → MAIN.FG_System.H_ControlPanel, 8 PackML buttons |
VC_Demo_1_Siemens_1 |
H_ControlPanel → MAIN.FG_System.H_ControlPanel_Siemens, 7 controls incl. a rotary switch |
A device that belongs to every vendor lives in the prefab, so there is exactly one copy of it.
Editing one scene's copy of a shared device is a mistake the build detects: the node stops being
identical across scenes and starts being marked † on the generated pages.
Read † as "this is one vendor's example". The generated machine pages are rendered from one
reference scene, currently Beckhoff. What is unmarked is the machine.
Adding a vendor is therefore adding a scene, not forking the machine.
The project keeps three kinds of fact apart, because each has a different owner and a different lifetime. Mixing them is how documentation starts to lie.
| The question it answers | Where it is written | By | |
|---|---|---|---|
| Structure | Which devices exist, what type each is, what its address is | context/ |
a generator, straight from the Unity twin |
| Behaviour | What the machine has to do — sequences, interlocks, faults, recovery | reference/ |
a human, once, for every platform |
| Realisation | How one particular PLC spells all that — function blocks, terminals, the HMI | each vendor's own repository | that platform's maintainers |
Structure is generated because it can be read out of the twin, so a generated page cannot drift
away from the machine. That is also why editing a page under context/ achieves nothing: the next
build overwrites it. Change the Unity scene instead — see
05 · Engineering workflow.
Behaviour is written by hand because it cannot be read out of anything — a sequence is a decision, and guessing one from a hierarchy produces something plausible and wrong. It is written once and platform-neutrally, so the Siemens implementation is held to exactly the same contract the TwinCAT one is.
Realisation is one answer per platform, so it lives with that platform and nowhere else.
The twin path is not the control path. The twin says MAIN.FG_01.P_Camera; TwinCAT says
MAIN.Machine.FG_01.P_Camera. The twin's spelling fails silently in a link and in an HMI binding,
so the machine pages state the twin path, and the verified control path is on the platform's page.
| Module | Path | Role |
|---|---|---|
| Unity twin | Unity/ |
The digital twin of the machinery, on Open Commissioning |
| Documentation | _docs/ |
These pages, the generated machine description, the behaviour contracts |
| How it is built | _workflow/ |
The specifications, the agent skills, and the tooling that reads only tracked files |
| A control platform |
Beckhoff/, Siemens/, … |
One separate, optional repository per platform, cloned into this root |
Each vendor module is a separate repository you clone into the main repo's root, where its path is gitignored so the two do not collide. Take only the platform you use. Nothing in the main repository depends on a vendor module being present, and each module carries a committed copy of the machine's structure, so it also builds on its own.
What crosses from this repository into a vendor's is a single generated file,
context/.machine.json — the machine's structure as schema-versioned JSON.
It crosses as a copy, not a reference: each module commits its own snapshot, so it builds from a
standalone clone with no Unity present.
Which modules exist and which versions pair with this twin is in
COMPATIBILITY.md; the declaration itself is
_workflow/config/modules.json.
| You want to | Read |
|---|---|
| See the concrete setups, and add your platform | 04 · PLC connectivity |
| Know where the generated description comes from | 05 · Engineering workflow |
| Know what the machine is made of | 06 · Machine description |
Generated from DT_PSA_OPCV by _workflow/tools/build_wiki.py — 39 pages. Edit the source there; changes made here are overwritten.
Getting started
- Home
- Setup
- Using-The-Application
- How-It-Works
- PLC-Connectivity
- Engineering-Workflow
- Machine-Description
- Glossary
The machine
- Machine
- Machine-PLC-Symbols
- Machine-Provenance
- Machine-FG_01
- Machine-FG_02
- Machine-FG_03
- Machine-FG_04
- Machine-FG_05
- Machine-FG_System
- Machine-FG_Transport
Behaviour
- Behaviour-FG_01
- Behaviour-FG_02
- Behaviour-FG_03
- Behaviour-FG_04
- Behaviour-FG_05
- Behaviour-FG_System-Safety
- Behaviour-Gripper-Station-Reset
- Behaviour-State-Lamp
- Behaviour-Transport
Device types
- Device-Button
- Device-ControlBunker
- Device-Cylinder
- Device-DataReader
- Device-DrivePosition
- Device-DriveSimple
- Device-Lamp
- Device-LinkByte
- Device-Lock
- Device-PanelSampler
- Device-SensorBinary
- Device-SignalBinary
Control platforms
- Beckhoff TwinCAT 3
- Siemens TIA Portal — no wiki yet