Skip to content

Add terminal support#120

Draft
Tc-Fast wants to merge 2 commits intomodelica:mainfrom
Tc-Fast:terminals
Draft

Add terminal support#120
Tc-Fast wants to merge 2 commits intomodelica:mainfrom
Tc-Fast:terminals

Conversation

@Tc-Fast
Copy link
Copy Markdown

@Tc-Fast Tc-Fast commented Mar 16, 2026

This draft adds support for FMI 3.0-style terminals to SSP 2.1. The draft closely follows the proposals from @DagBruck in #83.

Related to #59, #56, #84

Terminals are defined globally at the SSD root level (similar to Units and Enumerations), giving them a name that components can reference by. A terminal connector is declared with kind="terminal" and carries a <ssc:Terminal name="..."/> child pointing at the global terminal defintiion.

Member variables are bound by naming convention: a connector named portName.memberName is automatically associated with the terminal connector portName. This avoids any new connection syntax and keeps full backward compatibilty with SSP 2.0 systems.

Terminals carry a matchingRule attribute (plug, bus, sequence, none) taken from the FMI 3.0 terminal semantics, which tools can use for connection validation. Fan-out of terminal connections follows the same rules as scalar connections — an input member may only be written by one source.

┌──────────────────────────────────────────────────────────────────┐
│ System                                                           │
│  ┌───────────────┐                        ┌────────────────┐     │
│  │ Controller    │                        │ Plant          │     │
│  │               │                        │                │     │
│  │  controlPort <╪═══╦════════════════════╪> controlPort   │     │
│  │               │   ║                    │                │     │
│  │ externalSet- <┼───║────────────────────┼  measuredPos.  │     │
│  │  point        │   ║                    │                │     │
│  └───────────────┘   ║                    └────────────────┘     │
│                      ║                                           │
│                      ║     ┌──────────────────────────────────┐  │
│                      ║     │ Monitor                          │  │
│                      ║     │                 ┌──────────────┐ │  │
│                      ║     │                 │ Logger       │ │  │
│                      ╚═════╪> monitorPort    │              │ │  │
│                            │   .position ────┼> logPosition │ │  │
│                            │   .velocity ────┼> logVelocity │ │  │
│                            │                 └──────────────┘ │  │
│                            └──────────────────────────────────┘  │
└──────────────────────────────────────────────────────────────────┘

═══  Terminal connection (single connection, bidirectional signals)
───  Scalar connection
<?xml version="1.0" encoding="UTF-8"?>
<ssd:SystemStructureDescription
    xmlns:ssd="http://ssp-standard.org/SSP1/SystemStructureDescription"
    xmlns:ssc="http://ssp-standard.org/SSP1/SystemStructureCommon"
    name="TerminalExample" version="2.1">

    <ssd:System name="System">
        <ssd:Elements>
            <!-- Controller: outputs position/velocity commands, receives force feedback -->
            <ssd:Component name="Controller" source="resources/Controller.fmu">
                <ssd:Connectors>
                    <ssd:Connector kind="terminal" name="controlPort">
                        <ssc:Terminal name="com.example.ControlSignals"/>
                        <ssd:ConnectorGeometry x="1" y="0.5"/>
                    </ssd:Connector>
                    <ssd:Connector kind="output" name="controlPort.position">
                        <ssc:Real unit="m"/>
                    </ssd:Connector>
                    <ssd:Connector kind="output" name="controlPort.velocity">
                        <ssc:Real unit="m/s"/>
                    </ssd:Connector>
                    <ssd:Connector kind="input" name="controlPort.force">
                        <ssc:Real unit="N"/>
                    </ssd:Connector>
                    <ssd:Connector kind="input" name="externalSetpoint">
                        <ssc:Real/>
                    </ssd:Connector>
                </ssd:Connectors>
                <ssd:ElementGeometry x1="-80" y1="-20" x2="-40" y2="20"/>
            </ssd:Component>

            <!-- Plant: receives position/velocity commands, outputs force measurement -->
            <ssd:Component name="Plant" source="resources/Plant.fmu">
                <ssd:Connectors>
                    <ssd:Connector kind="terminal" name="controlPort">
                        <ssc:Terminal name="com.example.ControlSignals"/>
                        <ssd:ConnectorGeometry x="0" y="0.5"/>
                    </ssd:Connector>
                    <ssd:Connector kind="input" name="controlPort.position">
                        <ssc:Real unit="m"/>
                    </ssd:Connector>
                    <ssd:Connector kind="input" name="controlPort.velocity">
                        <ssc:Real unit="m/s"/>
                    </ssd:Connector>
                    <ssd:Connector kind="output" name="controlPort.force">
                        <ssc:Real unit="N"/>
                    </ssd:Connector>
                    <ssd:Connector kind="output" name="measuredPosition">
                        <ssc:Real unit="m"/>
                    </ssd:Connector>
                </ssd:Connectors>
                <ssd:ElementGeometry x1="40" y1="-20" x2="80" y2="20"/>
            </ssd:Component>

            <!-- Monitor subsystem: terminal on its interface, scalar access inside -->
            <ssd:System name="Monitor">
                <ssd:Connectors>
                    <ssd:Connector kind="terminal" name="monitorPort">
                        <ssc:Terminal name="com.example.ControlSignals"/>
                        <ssd:ConnectorGeometry x="0" y="0.5"/>
                    </ssd:Connector>
                    <ssd:Connector kind="input" name="monitorPort.position">
                        <ssc:Real unit="m"/>
                    </ssd:Connector>
                    <ssd:Connector kind="input" name="monitorPort.velocity">
                        <ssc:Real unit="m/s"/>
                    </ssd:Connector>
                </ssd:Connectors>
                <ssd:ElementGeometry x1="40" y1="-60" x2="80" y2="-30"/>
                <ssd:Elements>
                    <ssd:Component name="Logger" source="resources/Logger.fmu">
                        <ssd:Connectors>
                            <ssd:Connector kind="input" name="logPosition">
                                <ssc:Real unit="m"/>
                            </ssd:Connector>
                            <ssd:Connector kind="input" name="logVelocity">
                                <ssc:Real unit="m/s"/>
                            </ssd:Connector>
                        </ssd:Connectors>
                    </ssd:Component>
                </ssd:Elements>
                <ssd:Connections>
                    <!-- Inside the subsystem: connect individual terminal members -->
                    <ssd:Connection startConnector="monitorPort.position"
                                    endElement="Logger" endConnector="logPosition"/>
                    <ssd:Connection startConnector="monitorPort.velocity"
                                    endElement="Logger" endConnector="logVelocity"/>
                </ssd:Connections>
            </ssd:System>
        </ssd:Elements>

        <ssd:Connections>
            <!-- Terminal connection: carries position+velocity OUT and force IN -->
            <ssd:Connection startElement="Controller" startConnector="controlPort"
                            endElement="Plant" endConnector="controlPort"/>

            <!-- Same terminal to Monitor -->
            <ssd:Connection startElement="Controller" startConnector="controlPort"
                            endElement="Monitor" endConnector="monitorPort"/>

            <!-- Scalar connection (non-terminal) -->
            <ssd:Connection startElement="Plant" startConnector="measuredPosition"
                            endElement="Controller" endConnector="externalSetpoint"/>
        </ssd:Connections>
    </ssd:System>

    <ssd:Units>
        <ssc:Unit name="m">
            <ssc:BaseUnit m="1"/>
        </ssc:Unit>
        <ssc:Unit name="m/s">
            <ssc:BaseUnit m="1" s="-1"/>
        </ssc:Unit>
        <ssc:Unit name="N">
            <ssc:BaseUnit kg="1" m="1" s="-2"/>
        </ssc:Unit>
    </ssd:Units>

    <ssd:Terminals>
        <ssd:Terminal matchingRule="plug" name="com.example.ControlSignals"
                      terminalKind="com.example.ControlSignals">
            <ssd:Connectors>
                <ssd:Connector kind="local" name="position">
                    <ssc:Real unit="m"/>
                </ssd:Connector>
                <ssd:Connector kind="local" name="velocity">
                    <ssc:Real unit="m/s"/>
                </ssd:Connector>
                <ssd:Connector kind="local" name="force">
                    <ssc:Real unit="N"/>
                </ssd:Connector>
            </ssd:Connectors>
        </ssd:Terminal>
    </ssd:Terminals>

    <ssd:DefaultExperiment startTime="0.0" stopTime="10.0"/>

</ssd:SystemStructureDescription>

@Tc-Fast Tc-Fast added this to the 2.1-alpha milestone Mar 16, 2026
@Tc-Fast Tc-Fast marked this pull request as draft March 16, 2026 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant