StateMachine

The MARTe2 StateMachine (see also StateMachine) 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 Messages, which are used to trigger state transitions. Each state can define one or more 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 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:

StateMachine configuration. The initial state is selected via command-line arguments.
 1+StateMachine = {
 2    Class = StateMachine
 3    +INITIAL = {
 4        Class = ReferenceContainer      
 5        +START_CONSTANT_REF = {
 6            Class = StateMachineEvent
 7            NextState = "IDLE"
 8            NextStateError = "ERROR"
 9            Timeout = 0
10            +ChangeRTAppToStateConstantRef = {
11                Class = Message
12                Destination = MassSpringApp 
13                Mode = ExpectsReply
14                Function = PrepareNextState
15                +Parameters = {
16                    Class = ConfigurationDatabase
17                    param1 = StateConstantRef
18                }
19            }
20            +StartNextStateExecutionRTApp = {
21                Class = Message
22                Destination = MassSpringApp
23                Function = StartNextStateExecution
24                Mode = ExpectsReply
25            }
26        }
27        +START_WAVEFORM_REF = {
28            Class = StateMachineEvent
29            NextState = "IDLE"
30            NextStateError = "ERROR"
31            Timeout = 0
32            +ChangeRTAppToStateWaveformRef = {
33                Class = Message
34                Destination = MassSpringApp 
35                Mode = ExpectsReply
36                Function = PrepareNextState
37                +Parameters = {
38                    Class = ConfigurationDatabase
39                    param1 = StateWaveformRef
40                }
41            }
42            +StartNextStateExecutionRTApp = {
43                Class = Message
44                Destination = MassSpringApp
45                Function = StartNextStateExecution
46                Mode = ExpectsReply
47            }
48        }
49    }
50    +IDLE = {
51        Class = ReferenceContainer
52        +GOTO_IDLE = {
53            Class = StateMachineEvent
54            NextState = "IDLE"
55            NextStateError = "ERROR"
56            Timeout = 0 
57        }
58    }
59    +ERROR = {
60        Class = ReferenceContainer
61        +GOTO_IDLE = {
62            Class = StateMachineEvent
63            NextState = "IDLE"
64            NextStateError = "ERROR"
65            Timeout = 0 
66        }
67    }
68}

Depending on the selected initial state, the Message parameter matches one of the RealTimeApplication states:

RealTimeApplication state definition.
1    +States = {
2        Class = ReferenceContainer
3        +StateConstantRef = {
4            Class = RealTimeState
5            +Threads = {
6        +StateWaveformRef = {
7            Class = RealTimeState
8            +Threads = {

A second application uses a 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:

StateMachine diagram

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.

StateMachine configuration.
  1+StateMachine = {
  2    Class = StateMachine
  3    +INITIAL = {
  4        Class = ReferenceContainer      
  5        +START = {
  6            Class = StateMachineEvent
  7            NextState = "CONSTANT_REF"
  8            NextStateError = "ERROR"
  9            Timeout = 0
 10            +ChangeRTAppToStateConstantRef = {
 11                Class = Message
 12                Destination = MassSpringApp 
 13                Mode = ExpectsReply
 14                Function = PrepareNextState
 15                +Parameters = {
 16                    Class = ConfigurationDatabase
 17                    param1 = StateConstantRef
 18                }
 19            }
 20            +StartNextStateExecutionRTApp = {
 21                Class = Message
 22                Destination = MassSpringApp
 23                Function = StartNextStateExecution
 24                Mode = ExpectsReply
 25            }
 26        }
 27    }
 28    +CONSTANT_REF = {
 29        Class = ReferenceContainer
 30        +GOTO_CONSTANT_REF = {
 31            Class = StateMachineEvent
 32            NextState = "CONSTANT_REF"
 33            NextStateError = "ERROR"
 34            Timeout = 0 
 35        }
 36        +GOTO_WAVEFORM_REF = {
 37            Class = StateMachineEvent
 38            NextState = "WAVEFORM_REF"
 39            NextStateError = "ERROR"
 40            Timeout = 0 
 41            +ChangeRTAppToStateWaveformRef = {
 42                Class = Message
 43                Destination = MassSpringApp 
 44                Mode = ExpectsReply
 45                Function = PrepareNextState
 46                +Parameters = {
 47                    Class = ConfigurationDatabase
 48                    param1 = StateWaveformRef 
 49                }
 50            }
 51            +StopCurrentStateExecutionRTApp = {
 52                Class = Message
 53                Destination = MassSpringApp
 54                Function = StopCurrentStateExecution
 55                Mode = ExpectsReply
 56            }
 57            +StartNextStateExecutionRTApp = {
 58                Class = Message
 59                Destination = MassSpringApp
 60                Function = StartNextStateExecution
 61                Mode = ExpectsReply
 62            }
 63        }
 64    }
 65    +WAVEFORM_REF = {
 66        Class = ReferenceContainer
 67        +GOTO_WAVEFORM_REF = {
 68            Class = StateMachineEvent
 69            NextState = "WAVEFORM_REF"
 70            NextStateError = "ERROR"
 71            Timeout = 0 
 72        }
 73        +GOTO_CONSTANT_REF = {
 74            Class = StateMachineEvent
 75            NextState = "CONSTANT_REF"
 76            NextStateError = "ERROR"
 77            Timeout = 0 
 78            +ChangeRTAppToStateConstantRef = {
 79                Class = Message
 80                Destination = MassSpringApp 
 81                Mode = ExpectsReply
 82                Function = PrepareNextState
 83                +Parameters = {
 84                    Class = ConfigurationDatabase
 85                    param1 = StateConstantRef 
 86                }
 87            }
 88            +StopCurrentStateExecutionRTApp = {
 89                Class = Message
 90                Destination = MassSpringApp
 91                Function = StopCurrentStateExecution
 92                Mode = ExpectsReply
 93            }
 94            +StartNextStateExecutionRTApp = {
 95                Class = Message
 96                Destination = MassSpringApp
 97                Function = StartNextStateExecution
 98                Mode = ExpectsReply
 99            }
100        }
101    }
102    +ERROR = {
103        Class = ReferenceContainer
104        +GOTO_CONSTANT_REF = {
105            Class = StateMachineEvent
106            NextState = "CONSTANT_REF"
107            NextStateError = "ERROR"
108            Timeout = 0 
109        }
110    }
111}

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:

MessageGAM configuration.
 1        +GAMMessageStateChange = {
 2            Class = MessageGAM
 3            +Events = {
 4                Class = ReferenceContainer
 5                +EventConstantRef = {
 6                    Class = EventConditionTrigger
 7                    EventTrigger = {
 8                        CommandTriggerStateChange = 0
 9                    }
10                    +Message = {
11                        Class = Message
12                        Destination = StateMachine
13                        Function = GOTO_CONSTANT_REF
14                        Mode = ExpectsReply
15                    }
16                }
17                +EventWaveformRef = {
18                    Class = EventConditionTrigger
19                    EventTrigger = {
20                        CommandTriggerStateChange = 1
21                    }
22                    +Message = {
23                        Class = Message
24                        Destination = StateMachine
25                        Function = GOTO_WAVEFORM_REF
26                        Mode = ExpectsReply
27                    }
28                }
29            }
30            InputSignals = {
31                CommandTriggerStateChange = {
32                    DataSource = DDB1
33                    Type = uint8
34                }
35            }
36            OutputSignals = {
37                PendingStateChangeMessages = {
38                    DataSource = DDB1
39                    Type = uint32
40                }
41            }
42        }
MathExpressionGAM generating the trigger signal.
 1        +GAMMathTriggerStateChange = {
 2            Class = MathExpressionGAM
 3            Expression = "
 4                TriggerEveryMicroSecs = (uint32)10000000;
 5                TruncatedTime = (Time / TriggerEveryMicroSecs) * TriggerEveryMicroSecs;
 6                CommandTriggerStateChange = (uint8)(Time == TruncatedTime);"
 7            InputSignals = {
 8                Time = {
 9                    DataSource = DDB1
10                    Type = uint32
11                }
12            }
13            OutputSignals = {
14                TruncatedTime = {
15                    DataSource = DDB1
16                    Type = uint32
17                }
18                CommandTriggerStateChange = {
19                    DataSource = DDB1
20                    Type = uint8
21                }
22            }
23        }

Running the applications

Start the first application with:

./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:

$ [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:

./MARTeApp.sh -f ../Configurations/MassSpring/RTApp-MassSpring-50.cfg -l RealTimeLoader -m StateMachine::START_WAVEFORM_REF

Now the reference position varies over time:

$ [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:

./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:

$ [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:

StateMachine diagram

The configuration already includes the RealTimeState named StateSwitchOff, which sets Force = 0.0.

  1. Run:

./MARTeApp.sh -f ../Configurations/MassSpring/RTApp-MassSpring-52.cfg -l RealTimeLoader -m StateMachine::START_SWITCH_OFF
  1. Verify the output:

$ [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
Solution

Implement the StateMachine as required:

StateMachine with switch-off state.
  1+StateMachine = {
  2    Class = StateMachine
  3    +INITIAL = {
  4        Class = ReferenceContainer      
  5        +START = {
  6            Class = StateMachineEvent
  7            NextState = "CONSTANT_REF"
  8            NextStateError = "ERROR"
  9            Timeout = 0
 10            +ChangeRTAppToStateConstantRef = {
 11                Class = Message
 12                Destination = MassSpringApp 
 13                Mode = ExpectsReply
 14                Function = PrepareNextState
 15                +Parameters = {
 16                    Class = ConfigurationDatabase
 17                    param1 = StateConstantRef
 18                }
 19            }
 20            +StartNextStateExecutionRTApp = {
 21                Class = Message
 22                Destination = MassSpringApp
 23                Function = StartNextStateExecution
 24                Mode = ExpectsReply
 25            }
 26        }
 27        +START_SWITCH_OFF = {
 28            Class = StateMachineEvent
 29            NextState = "SWITCH_OFF"
 30            NextStateError = "ERROR"
 31            Timeout = 0
 32            +ChangeRTAppToStateSwitchOff = {
 33                Class = Message
 34                Destination = MassSpringApp 
 35                Mode = ExpectsReply
 36                Function = PrepareNextState
 37                +Parameters = {
 38                    Class = ConfigurationDatabase
 39                    param1 = StateSwitchOff
 40                }
 41            }
 42            +StartNextStateExecutionRTApp = {
 43                Class = Message
 44                Destination = MassSpringApp
 45                Function = StartNextStateExecution
 46                Mode = ExpectsReply
 47            }
 48        }
 49
 50    }
 51    +CONSTANT_REF = {
 52        Class = ReferenceContainer
 53        +GOTO_CONSTANT_REF = {
 54            Class = StateMachineEvent
 55            NextState = "CONSTANT_REF"
 56            NextStateError = "ERROR"
 57            Timeout = 0 
 58        }
 59        +GOTO_SWITCH_OFF = {
 60            Class = StateMachineEvent
 61            NextState = "SWITCH_OFF"
 62            NextStateError = "ERROR"
 63            Timeout = 0 
 64            +ChangeRTAppToStateSwitchOff = {
 65                Class = Message
 66                Destination = MassSpringApp 
 67                Mode = ExpectsReply
 68                Function = PrepareNextState
 69                +Parameters = {
 70                    Class = ConfigurationDatabase
 71                    param1 = StateSwitchOff
 72                }
 73            }
 74            +StopCurrentStateExecutionRTApp = {
 75                Class = Message
 76                Destination = MassSpringApp
 77                Function = StopCurrentStateExecution
 78                Mode = ExpectsReply
 79            }
 80            +StartNextStateExecutionRTApp = {
 81                Class = Message
 82                Destination = MassSpringApp
 83                Function = StartNextStateExecution
 84                Mode = ExpectsReply
 85            }
 86        }
 87        +GOTO_WAVEFORM_REF = {
 88            Class = StateMachineEvent
 89            NextState = "WAVEFORM_REF"
 90            NextStateError = "ERROR"
 91            Timeout = 0 
 92            +ChangeRTAppToStateWaveformRef = {
 93                Class = Message
 94                Destination = MassSpringApp 
 95                Mode = ExpectsReply
 96                Function = PrepareNextState
 97                +Parameters = {
 98                    Class = ConfigurationDatabase
 99                    param1 = StateWaveformRef 
100                }
101            }
102            +StopCurrentStateExecutionRTApp = {
103                Class = Message
104                Destination = MassSpringApp
105                Function = StopCurrentStateExecution
106                Mode = ExpectsReply
107            }
108            +StartNextStateExecutionRTApp = {
109                Class = Message
110                Destination = MassSpringApp
111                Function = StartNextStateExecution
112                Mode = ExpectsReply
113            }
114        }
115    }
116    +WAVEFORM_REF = {
117        Class = ReferenceContainer
118        +GOTO_WAVEFORM_REF = {
119            Class = StateMachineEvent
120            NextState = "WAVEFORM_REF"
121            NextStateError = "ERROR"
122            Timeout = 0 
123        }
124        +GOTO_SWITCH_OFF = {
125            Class = StateMachineEvent
126            NextState = "SWITCH_OFF"
127            NextStateError = "ERROR"
128            Timeout = 0 
129            +ChangeRTAppToStateSwitchOff = {
130                Class = Message
131                Destination = MassSpringApp 
132                Mode = ExpectsReply
133                Function = PrepareNextState
134                +Parameters = {
135                    Class = ConfigurationDatabase
136                    param1 = StateSwitchOff
137                }
138            }
139            +StopCurrentStateExecutionRTApp = {
140                Class = Message
141                Destination = MassSpringApp
142                Function = StopCurrentStateExecution
143                Mode = ExpectsReply
144            }
145            +StartNextStateExecutionRTApp = {
146                Class = Message
147                Destination = MassSpringApp
148                Function = StartNextStateExecution
149                Mode = ExpectsReply
150            }
151        }
152        +GOTO_CONSTANT_REF = {
153            Class = StateMachineEvent
154            NextState = "CONSTANT_REF"
155            NextStateError = "ERROR"
156            Timeout = 0 
157            +ChangeRTAppToStateConstantRef = {
158                Class = Message
159                Destination = MassSpringApp 
160                Mode = ExpectsReply
161                Function = PrepareNextState
162                +Parameters = {
163                    Class = ConfigurationDatabase
164                    param1 = StateConstantRef 
165                }
166            }
167            +StopCurrentStateExecutionRTApp = {
168                Class = Message
169                Destination = MassSpringApp
170                Function = StopCurrentStateExecution
171                Mode = ExpectsReply
172            }
173            +StartNextStateExecutionRTApp = {
174                Class = Message
175                Destination = MassSpringApp
176                Function = StartNextStateExecution
177                Mode = ExpectsReply
178            }
179        }
180    }
181    +SWITCH_OFF = {
182        Class = ReferenceContainer
183        +GOTO_SWITCH_OFF = {
184            Class = StateMachineEvent
185            NextState = "SWITCH_OFF"
186            NextStateError = "ERROR"
187            Timeout = 0 
188        }
189        +GOTO_CONSTANT_REF = {
190            Class = StateMachineEvent
191            NextState = "CONSTANT_REF"
192            NextStateError = "ERROR"
193            Timeout = 0 
194            +ChangeRTAppToStateConstantRef = {
195                Class = Message
196                Destination = MassSpringApp 
197                Mode = ExpectsReply
198                Function = PrepareNextState
199                +Parameters = {
200                    Class = ConfigurationDatabase
201                    param1 = StateConstantRef 
202                }
203            }
204            +StopCurrentStateExecutionRTApp = {
205                Class = Message
206                Destination = MassSpringApp
207                Function = StopCurrentStateExecution
208                Mode = ExpectsReply
209            }
210            +StartNextStateExecutionRTApp = {
211                Class = Message
212                Destination = MassSpringApp
213                Function = StartNextStateExecution
214                Mode = ExpectsReply
215            }
216        }
217        +GOTO_WAVEFORM_REF = {
218            Class = StateMachineEvent
219            NextState = "WAVEFORM_REF"
220            NextStateError = "ERROR"
221            Timeout = 0 
222            +ChangeRTAppToStateWaveformRef = {
223                Class = Message
224                Destination = MassSpringApp 
225                Mode = ExpectsReply
226                Function = PrepareNextState
227                +Parameters = {
228                    Class = ConfigurationDatabase
229                    param1 = StateWaveformRef 
230                }
231            }
232            +StopCurrentStateExecutionRTApp = {
233                Class = Message
234                Destination = MassSpringApp
235                Function = StopCurrentStateExecution
236                Mode = ExpectsReply
237            }
238            +StartNextStateExecutionRTApp = {
239                Class = Message
240                Destination = MassSpringApp
241                Function = StartNextStateExecution
242                Mode = ExpectsReply
243            }
244        }
245    }
246    +ERROR = {
247        Class = ReferenceContainer
248        +GOTO_CONSTANT_REF = {
249            Class = StateMachineEvent
250            NextState = "CONSTANT_REF"
251            NextStateError = "ERROR"
252            Timeout = 0 
253        }
254    }
255}