.. date: 13/04/2026 author: Andre' Neto copyright: Copyright 2017 F4E | European Joint Undertaking for ITER and the Development of Fusion Energy ('Fusion for Energy'). Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "Licence") You may not use this work except in compliance with the Licence. You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl warning: Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Licence permissions and limitations under the Licence. StateMachine ============ The MARTe2 :vcisdoxygencl:`StateMachine` (see also :ref:`MARTeStateMachine`) allows changing the application state asynchronously based on external triggers. This enables the implementation of different behaviours depending on the system state. The StateMachine is based on the concept of :ref:`MARTeMessages`, which are used to trigger state transitions. Each state can define one or more :vcisdoxygencl:`StateMachineEvent` elements, which specify transitions and the associated messages. A transition may trigger additional messages, which can in turn activate actions in the RealTimeApplication or directly in components (e.g. GAMs or DataSources). For example, the :vcisdoxygenmccl:`ConstantGAM` can update its output value upon receiving a message. In the first example, the StateMachine switches the application between two states: - a state where the reference position is fixed at 2.0 - a state where the reference position is generated by a waveform The configuration is shown below: .. literalinclude:: /_static/tutorial/Configurations/MassSpring/RTApp-MassSpring-50.cfg :language: c++ :lines: 1-68 :caption: StateMachine configuration. The initial state is selected via command-line arguments. :linenos: :emphasize-lines: 5, 17, 27, 39 Depending on the selected initial state, the ``Message`` parameter matches one of the RealTimeApplication states: .. literalinclude:: /_static/tutorial/Configurations/MassSpring/RTApp-MassSpring-50.cfg :language: c++ :lines: 906-910,925-927 :caption: RealTimeApplication state definition. :linenos: :emphasize-lines: 3,6 A second application uses a :vcisdoxygenmccl:`MessageGAM` to change the reference position dynamically based on the application state. The application defines two main states: ``WAVEFORM_REF`` and ``CONSTANT_REF``. The StateMachine transitions and triggered messages are illustrated below: .. figure:: images/RTApp-MassSpring-51-StateMachine.png :align: center :alt: StateMachine diagram :width: 700px StateMachine transitions and associated messages. In ``WAVEFORM_REF``, the message ``GOTO_CONSTANT_REF`` switches to ``CONSTANT_REF`` and triggers the relevant messages. Conversely, ``GOTO_WAVEFORM_REF`` performs the opposite transition. .. literalinclude:: /_static/tutorial/Configurations/MassSpring/RTApp-MassSpring-51.cfg :language: c++ :lines: 1-111 :caption: StateMachine configuration. :linenos: :emphasize-lines: 5, 7, 17, 28, 36, 38, 48, 65, 73, 75 The ``MessageGAM`` triggers state transitions based on the signal ``CommandTriggerStateChange``. This signal is generated by a ``MathExpressionGAM`` implementing logic to trigger a transition every 10 seconds: .. literalinclude:: /_static/tutorial/Configurations/MassSpring/RTApp-MassSpring-51.cfg :language: c++ :lines: 164-205 :caption: MessageGAM configuration. :linenos: :emphasize-lines: 8, 13-14, 20, 25-26 .. literalinclude:: /_static/tutorial/Configurations/MassSpring/RTApp-MassSpring-51.cfg :language: c++ :lines: 615-637 :caption: MathExpressionGAM generating the trigger signal. :linenos: :emphasize-lines: 6 Running the applications ------------------------ Start the first application with: .. code-block:: bash ./MARTeApp.sh -f ../Configurations/MassSpring/RTApp-MassSpring-50.cfg -l RealTimeLoader -m StateMachine::START_CONSTANT_REF Verify that the reference position is fixed at 2.0: .. code-block:: console $ [Warning - Threads.cpp:185]: Failed to change the thread priority (likely due to insufficient permissions) $ [Information - StateMachine.cpp:340]: In state (INITIAL) triggered message (StartNextStateExecutionRTApp) $ [Information - LoggerBroker.cpp:152]: Time [0:0]:1000000 $ [Information - LoggerBroker.cpp:152]: ReferencePosition [0:0]:2.000000 Run again with: .. code-block:: bash ./MARTeApp.sh -f ../Configurations/MassSpring/RTApp-MassSpring-50.cfg -l RealTimeLoader -m StateMachine::START_WAVEFORM_REF Now the reference position varies over time: .. code-block:: console $ [Warning - Threads.cpp:185]: Failed to change the thread priority (likely due to insufficient permissions) $ [Information - StateMachine.cpp:340]: In state (INITIAL) triggered message (StartNextStateExecutionRTApp) $ [Information - LoggerBroker.cpp:152]: Time [0:0]:1000000 $ [Information - LoggerBroker.cpp:152]: ReferencePosition [0:0]:0.400000 Start the second application: .. code-block:: bash ./MARTeApp.sh -f ../Configurations/MassSpring/RTApp-MassSpring-51.cfg -l RealTimeLoader -m StateMachine::START The application starts in ``CONSTANT_REF`` and transitions to ``WAVEFORM_REF`` after 10 seconds: .. code-block:: console $ [Warning - Threads.cpp:185]: Failed to change the thread priority (likely due to insufficient permissions) $ [Information - StateMachine.cpp:340]: In state (CONSTANT_REF) triggered message (StartNextStateExecutionRTApp) $ [Information - LoggerBroker.cpp:152]: Time [0:0]:51990000 $ [Information - LoggerBroker.cpp:152]: ReferencePosition [0:0]:2.000000 ... $ [Information - StateMachine.cpp:340]: In state (WAVEFORM_REF) triggered message (StartNextStateExecutionRTApp) $ [Information - LoggerBroker.cpp:152]: Time [0:0]:61990000 $ [Information - LoggerBroker.cpp:152]: ReferencePosition [0:0]:0.772000 ... Exercises --------- Ex. 1: Add a switch-off state ----------------------------- The goal is to add a new state where the system is switched off (i.e. ``Force = 0.0``). This configuration will be reused in later exercises. 1. Edit ``../Configurations/MassSpring/RTApp-MassSpring-52.cfg`` and implement the StateMachine shown below: .. figure:: images/RTApp-MassSpring-52-StateMachine.png :align: center :alt: StateMachine diagram :width: 700px The configuration already includes the ``RealTimeState`` named ``StateSwitchOff``, which sets ``Force = 0.0``. 2. Run: .. code-block:: bash ./MARTeApp.sh -f ../Configurations/MassSpring/RTApp-MassSpring-52.cfg -l RealTimeLoader -m StateMachine::START_SWITCH_OFF 3. Verify the output: .. code-block:: console $ [Warning - Threads.cpp:185]: Failed to change the thread priority (likely due to insufficient permissions) $ [Information - StateMachine.cpp:340]: In state (INITIAL) triggered message (StartNextStateExecutionRTApp) $ [Information - LoggerBroker.cpp:152]: Time [0:0]:1000000 $ [Information - LoggerBroker.cpp:152]: Force [0:0]:0.000000 .. dropdown:: Solution :icon: key Implement the StateMachine as required: .. literalinclude:: /_static/tutorial/Configurations/MassSpring/RTApp-MassSpring-52-solution.cfg :language: c++ :lines: 1-255 :caption: StateMachine with switch-off state. :linenos: :emphasize-lines: 32,59,129,181