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:
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:
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 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.
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:
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 }
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.
Edit
../Configurations/MassSpring/RTApp-MassSpring-52.cfgand implement the StateMachine shown below:
The configuration already includes the RealTimeState named StateSwitchOff, which sets Force = 0.0.
Run:
./MARTeApp.sh -f ../Configurations/MassSpring/RTApp-MassSpring-52.cfg -l RealTimeLoader -m StateMachine::START_SWITCH_OFF
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:
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}