Hide last authors
nbw 4.1 1
2
3 {{toc/}}
4
nbw 1.1 5 We compose our railway controller from several train controllers, combined with controllers for mutual exclusion.
6
7 == Mutual Exclusion ==
8
9 === Normal segments ===
10
nbw 3.1 11 **For each block** we generate one mutex controller, similar to the following pattern.
nbw 1.1 12
13 [[image:attach:Mutex.png]]
14
nbw 3.1 15 **For each controlled train** one state and the corresponding transitions are added.
nbw 1.1 16
nbw 6.1 17 A train **must** signal the wish to enter a segment by setting the variable **bool <segment>_req[trainNum] **to true.
18 The right to enter a segement is given to the train by setting the variable **int <segment>_perm** to the train number.
csp 9.1 19 After leaving a segment the train **must** remove its request by setting <segment>_req[trainNum] to false again.
nbw 6.1 20
csp 9.1 21 For a free track the *_perm variable is set to -1 and all tracks, apart from starting positions, are initialized with -1. For the starting positions the *_perm variables are set to the corresponding train number and the *_req variable for the train is set to true.
nbw 1.1 22
nbw 3.1 23 **A train must not enter a segment or alter the settings of a segment without holding the lock for the segment. No exceptions from this rule are allowed.**
nbw 1.1 24
25 === Kicking Horse Pass ===
26
nbw 3.1 27 To prevent collisions on the track, a special controller manages the rights to enter or leave the Kicking Horse Pass.
nbw 1.1 28
29 [[image:attach:Mutex_KH.png]]
30
nbw 3.1 31 The controller splits the pass into two parts, //left// and //right//, corresponding to the track layout chart. [[(Simplified track layout)>>url:http://www.informatik.uni-kiel.de/~~railway/Downloads/kscheme.pdf||shape="rect"]]
nbw 1.1 32
csp 9.1 33 Each part has two operational modes, //in// and //out//, being active when trains are allowed to either enter or leave the pass. When entering the pass the controller counts the entering trains and only lets two trains enter (one after the other). When leaving the pass the trains are removed from the counter, freeing space for the next train.
nbw 3.1 34
35 == Train controller ==
36
krat 14.1 37 Each train controller is set in a separate region with a referenced state. This state has the following interface:
nbw 3.1 38
39
40 \\\\\\\\
41
42 {{{    input int *_perm;         # All permission variables (Tracks) input bool *_perm # KH permission variables   input int trainNum;    input bool cleanup; input bool debug; output bool *_req[]; # All request variables}}}
43
krat 14.1 44 The train controller is composed of several //Station-2-Station// controllers. These are combined to form a complete schedule. Additionally, the cleanup signal has to be watched to abort the schedule and return back to the initial position.
nbw 3.1 45
sna 17.1 46 === Structure ===
47
48 {{code linenumbers="true" language="sct"}}
sna 18.1 49 //
50 // Structure of a train controller based on test case 2
51 //
52 scchart Test2 "Test of IC_JCT" {
53  // Set of request variables for all tracks for 11 trains
sna 17.1 54 bool IC_JCT_0_req[11], IC_LN_0_req[11], IC_LN_1_req[11], IC_LN_2_req[11];
55 bool IC_LN_3_req[11], IC_LN_4_req[11], IC_LN_5_req[11], IC_ST_0_req[11];
56 bool IC_ST_1_req[11], IC_ST_2_req[11], IC_ST_3_req[11], IC_ST_4_req[11];
57 bool IO_LN_0_req[11], IO_LN_1_req[11], IO_LN_2_req[11], KH_LN_0_req[11];
58 bool KH_LN_1_req[11], KH_LN_2_req[11], KH_LN_3_req[11], KH_LN_4_req[11];
59 bool KH_LN_5_req[11], KH_LN_6_req[11], KH_LN_7_req[11], KH_LN_8_req[11];
60 bool KH_ST_0_req[11], KH_ST_1_req[11], KH_ST_2_req[11], KH_ST_3_req[11];
61 bool KH_ST_4_req[11], KH_ST_5_req[11], KH_ST_6_req[11], KIO_LN_0_req[11];
62 bool KIO_LN_1_req[11], OC_JCT_0_req[11], OC_LN_0_req[11], OC_LN_1_req[11];
63 bool OC_LN_2_req[11], OC_LN_3_req[11], OC_LN_4_req[11], OC_LN_5_req[11];
64 bool OC_ST_0_req[11], OC_ST_1_req[11], OC_ST_2_req[11], OC_ST_3_req[11];
65 bool OC_ST_4_req[11], OI_LN_0_req[11], OI_LN_1_req[11], OI_LN_2_req[11];
sna 19.1 66 bool req_in_R, req_out_R, req_in_L, req_out_L;
sna 18.1 67
sna 19.1 68   // Set of permission variables for all tracks
sna 17.1 69 int IC_JCT_0_perm, IC_LN_0_perm, IC_LN_1_perm, IC_LN_2_perm;
70 int IC_LN_3_perm, IC_LN_4_perm, IC_LN_5_perm, IC_ST_0_perm;
71 int IC_ST_1_perm, IC_ST_2_perm, IC_ST_3_perm, IC_ST_4_perm;
72 int IO_LN_0_perm, IO_LN_1_perm, IO_LN_2_perm, KH_LN_0_perm;
73 int KH_LN_1_perm, KH_LN_2_perm, KH_LN_3_perm, KH_LN_4_perm;
74 int KH_LN_5_perm, KH_LN_6_perm, KH_LN_7_perm, KH_LN_8_perm;
75 int KH_ST_0_perm, KH_ST_1_perm, KH_ST_2_perm, KH_ST_3_perm;
76 int KH_ST_4_perm, KH_ST_5_perm, KH_ST_6_perm, KIO_LN_0_perm;
77 int KIO_LN_1_perm, OC_JCT_0_perm, OC_LN_0_perm, OC_LN_1_perm;
78 int OC_LN_2_perm, OC_LN_3_perm, OC_LN_4_perm, OC_LN_5_perm;
79 int OC_ST_0_perm, OC_ST_1_perm, OC_ST_2_perm, OC_ST_3_perm;
80 int OC_ST_4_perm, OI_LN_0_perm, OI_LN_1_perm, OI_LN_2_perm;
sna 19.1 81  bool perm_in_R, perm_out_R, perm_in_L, perm_out_L;
sna 18.1 82
83 // Debug flag for additional output
sna 17.1 84 bool debug = false;
sna 18.1 85 // Cleanup flag for halting the trains at home station tracks
86  bool cleanup = false;
87  // Variable, that gives the number of trains to C-Controller for stability check
sna 17.1 88 int trainCount;
sna 18.1 89
90 // Set of constants for binding to referenced SCCharts
sna 17.1 91 const int c_EINS = 1;
92 const int c_ZWEI = 2;
93 const int c_DREI = 3;
94 const int c_VIER = 4;
95 const int c_FUENF = 5;
96
sna 18.1 97 // State initializing the trains on corresponding tracks
sna 17.1 98 initial state init references initRailway11Trains
99 --> run;
100
sna 18.1 101 // State handling the train schedules
sna 17.1 102 state run {
sna 18.1 103 // Regions handling the mutual exclusion on the track segments
sna 17.1 104 region Mutexes:
sna 18.1 105  // State referenced to the MutexController for 11 Trains
sna 17.1 106 initial state Mutexes references mutexRailway11Trains;
107
108 region KH_Mutexes:
sna 18.1 109  // State referenced to additional MutexController for KH
sna 17.1 110 initial state KH_Mutexes references kh_mutex;
111
sna 18.1 112 // Regions that contain the schedules for individual trains
113 //--------------------------------------------------------------------------------------
114
115 // Region with schedule for train 4
sna 17.1 116 region Train4 :
sna 18.1 117  // State with the schedule for train 4
sna 17.1 118 initial state train4 {
119
sna 18.1 120 // Annotation for replacing following constant in the hostcode of referenced SCChart
sna 17.1 121 @alterHostcode
sna 18.1 122 // Number of the train for identifying on track segments
sna 17.1 123 const int trainNum = 4;
sna 18.1 124  // Variable specifying the track, where the train arrives at,
125 // and for transmitting the track number to next Station-2-Station controller
sna 17.1 126 int arrivalTrack = 3;
127
sna 18.1 128 // Schedule of train 4: train drives only in the IC, should use station track 3
129 // State Round referenced to ICIC Station-2-Station controller
sna 17.1 130 initial state Round references ICIC
131 bind depTrack to arrivalTrack,
132 destTrack to c_DREI,
133 arrTrack to arrivalTrack
sna 18.1 134  // Transition to checking state
sna 17.1 135 >-> Choice;
sna 18.1 136
137 // State for checking, when the train should halt and if the train is on corresponding track
sna 17.1 138 state Choice
sna 18.1 139 // Transition for driving additional circle, if cleanup = false or wrong track used
sna 17.1 140 --> Round with !cleanup | !(arrivalTrack == 3)
sna 18.1 141 // Transition to final state
sna 17.1 142 --> Done;
143
sna 18.1 144 final state Done;
sna 17.1 145 };
sna 18.1 146
147
148 // Region with schedule for train 5, identical to region above
149  region Train5 :
sna 17.1 150 initial state train5 {
151
152 @alterHostcode
153 const int trainNum = 5;
154 int arrivalTrack = 2;
155
156 initial state Round references ICIC
157 bind depTrack to arrivalTrack,
158 destTrack to c_ZWEI,
159 arrTrack to arrivalTrack
160 >-> Choice;
161
162 state Choice
163 --> Round with !cleanup | !(arrivalTrack == 2)
164 --> Done;
165
166 final state Done;
167
168 };
169
sna 18.1 170
171 // Region with schedule for train 9, identical to region above
sna 17.1 172 region Train9 :
173 initial state train9 {
174
175 @alterHostcode
176 const int trainNum = 9;
177 int arrivalTrack = 1;
178
179 initial state Round references ICIC
180 bind depTrack to arrivalTrack,
181 destTrack to c_EINS,
182 arrTrack to arrivalTrack
183 >-> Choice;
184
185 state Choice
186 --> Round with !cleanup | !(arrivalTrack == 1)
187 --> Done;
188
189 final state Done;
190 };
sna 18.1 191
192
193 // Region with schedule for train 7
sna 17.1 194 region Train7 :
195 initial state train7 {
196
197 @alterHostcode
198 const int trainNum = 7;
199 int arrivalTrack = 1;
200
sna 18.1 201 // Schedule of train 7: train drives from OC-Station track 1 to IC-Station track 2 and back
202 // arrivalTrack used for transmitting the number of station track where train arrived on
203 // to next controller where the train starts on
sna 17.1 204 initial state OCtoIC references OCIC
205 bind depTrack to arrivalTrack,
206 destTrack to c_ZWEI,
207 arrTrack to arrivalTrack
sna 18.1 208  // Transition to next Station-2-Station controller
sna 17.1 209 >-> ICtoOC;
210
211 state ICtoOC references ICOC
212 bind depTrack to arrivalTrack,
213 destTrack to c_EINS,
214 arrTrack to arrivalTrack
sna 18.1 215  // Transition to checking state because train at home station
sna 17.1 216 >-> Choice;
217
sna 18.1 218 // State for checking, when the train should halt and if the train is on corresponding track
sna 17.1 219 state Choice
sna 18.1 220 // Transition for driving additional circle, if cleanup = false or wrong track used
221  --> OCtoIC with !cleanup | !(arrivalTrack == 1)
222 // Transition to final state
sna 17.1 223 --> Done;
224
225 final state Done;
226 };
227 };
228 }
229 {{/code}}
230
231
232
nbw 3.1 233 == Station-2-Station controller ==
234
krat 14.1 235 Each Station-2-Station controller realizes the movement from one of the stations (IC,OC,KH) to another station. All controllers using IC or OC parts have to respect the traveling directions. For the Kicking Horse Pass two separate controllers, forwards and backwards, are used.
nbw 3.1 236
krat 14.1 237 The controllers starting from Kicking Horse Pass Station make an assumption of the direction of the train. These are dependent on the directions of the inner or outer circle, e.g. the KHIC controller starts backwards because this is the only valid direction to travel this path. To drive a train from the Kicking Horse Station (facing forward) to the Inner Circle we have to combine the KHOC and OCIC controllers.
nbw 4.1 238
239 [[image:attach:ICIC.png]]
240
nbw 5.1 241 When arriving on a station the train controller **must** first call the function //void railArrival(int train, int station)//. This starts the waiting timer for the train.
242 Next the train **must** wait for// int railDeparture(int train)// to return 1.
243 After the waiting has finished the controller can reach a final state and pass the control back to the train controller.
sna 10.1 244
sna 15.1 245 === Structure  ===
sna 10.1 246
sna 15.1 247 {{code linenumbers="true" language="sct"}}
248 //
249 // Structure of a Station-2-Station controller from Station * to Station *
250 //
251 scchart STST " * to * Controller " {
sna 10.1 252
sna 15.1 253 // Set of permission variables for required tracks
254 input int *_perm;
sna 10.1 255
sna 15.1 256 // Set of request variables for required tracks for 11 trains
257 output bool *_req[11];
sna 10.1 258
sna 15.1 259 // Train number
260 input int trainNum;
sna 10.1 261
sna 15.1 262 // Number of the departure track in a station
263 input int depTrack;
sna 10.1 264
sna 15.1 265 // Number of the destination track in a station
266 input int destTrack;
sna 10.1 267
sna 15.1 268 // Cleanup flag for selecting the destination track
269 input bool cleanup;
sna 10.1 270
sna 15.1 271 // Debug flag for additional output
272 input bool debug;
sna 10.1 273
sna 15.1 274 // Arrival track
275 output int arrTrack;
sna 10.1 276
sna 15.1 277 // Variable with value for arrTrack for selecting correct station elements
278 int i_arrOnTrack;
sna 10.1 279
sna 15.1 280 // Handles departing from a station *
281 initial state *_ST {
282 // hostcode call for additional output when debug
283 entry debug / 'println([trainNum][ST-ST] ... )';
sna 10.1 284
sna 15.1 285 // State, which sets requests for needed tracks
286 initial state waitForPerm {
287 entry / *_ST_4_req[trainNum] = true;
288 entry / *_LN_0_req[trainNum] = true;
289 }
290 // Transition is taken, if all permissions are received
291 --> gotPerm with (*_ST_4_perm == trainNum) & (*_LN_0_perm == trainNum)
292 // Transition is taken, if some (not all) permissions are received
293 --> backOff with (*_ST_4_perm == trainNum) | (*_LN_0_perm == trainNum);
sna 10.1 294
sna 15.1 295 // State for waiting an additional tick when not all permissions are received
296 state backOff
297 --> backOff1;
sna 10.1 298
sna 15.1 299 // State, which releases the requests for needed tracks
300 state backOff1 {
301 entry / *_ST_4_req[trainNum] = false;
302 entry / *_LN_0_req[trainNum] = false;
303 }
304 // Transition to repeat requesting permissions procedure
305 --> waitForPerm;
sna 10.1 306
sna 15.1 307 final state gotPerm;
308 }
309 // Transition to the departure state
310 >-> Dep_*_ST;
sna 10.1 311
sna 15.1 312 // State, which handles the departure of a train
313 state Dep_*_ST {
314 // Set of entry-Actions with hostcode calls to set tracks, points and signals according to depTrack
315 entry / 'railPoint(*,STRAIGHT)';
316 entry / 'railSignal(*_LN_0, FWD, RED)';
317 entry / 'railTrack(*_LN_0,FWD,trainNum,NORMAL)';
318 entry / 'railTrack(*_ST_4,FWD,trainNum,NORMAL)';
319 entry depTrack == 1 / 'railSignal(*_ST_1, FWD, GREEN)';
320 entry depTrack == 2 / 'railSignal(*_ST_2, FWD, GREEN)';
321 entry depTrack == 3 / 'railSignal(*_ST_3, FWD, GREEN)';
322 //...
323 // Transition to next track segment, if contact is triggered
324 } --> *_LN_0 with 'railContact(*_LN_0,0)';
sna 10.1 325
326
327
sna 18.1 328 // ----------------------------------------------------------------------------------------------------------------
sna 15.1 329 // Set of track segment controlling states such as follows
sna 18.1 330 // ----------------------------------------------------------------------------------------------------------------
sna 10.1 331
sna 15.1 332 // Transition to next track segment, if contact is triggered
333 state *_LN_0 {
334 // Hostcode calls for outputs
335 entry / 'println("[trainNum][ST-ST] Entering *_LN_0")';
336 entry debug / 'println("[trainNum][ST-ST] Requesting permission for *_LN_1")';
337 // Entry-Actions with hostcode calls to set previous signal according to depTrack to RED
338 entry depTrack == 1 / 'railSignal(*_ST_1, FWD, RED)';
339 entry depTrack == 2 / 'railSignal(*_ST_2, FWD, RED)';
340 entry depTrack == 3 / 'railSignal(*_ST_3, FWD, RED)';
341 // Requesting the next track segment
342 entry / *_LN_1_req[trainNum] = true;
sna 10.1 343
sna 15.1 344 // Region for handling train driving
345 region Travel:
346 initial state Entry
347 // Transition to continuing state, if permitted
348 --> Continue with 'railContact(*_LN_0,0)' & (*_LN_1_perm == trainNum)
349 // Transition to slowing down else
350 --> Slowdown with 'railContact(*_LN_0,0)';
sna 10.1 351
sna 15.1 352 // State for slowing down the train
353 state Slowdown {
354 entry debug / 'println("[trainNum][ST-ST] Slowing down on *_LN_0")';
355 // Entry-Action with hostcode calls for slowing down the train
356 entry / 'railTrack(*_LN_0,FWD,trainNum,CAUTION)';
357 }
358 // Transition to waiting state
359 --> Waiting with 'railContact(*_LN_0,1)'
360 // Transition to continuing state, if permitted
361 --> Continue with *_LN_1_perm == trainNum;
sna 10.1 362
sna 15.1 363 // State for train waiting on permission
364 state Waiting {
365 entry debug / 'println("[trainNum][ST-ST] Stopping on *_LN_0")';
366 // Entry-Action with hostcode call for stopping the train
367 entry / 'railTrackBrake(*_LN_0)';
368 }
369 --> Continue with *_LN_1_perm == trainNum;
sna 10.1 370
sna 15.1 371 // State to continuing driving on the track
372 final state Continue {
373 entry debug / 'println("[trainNum][ST-ST] Continuing on *_LN_0")';
374 // Entry-Actions with hostcode calls to set tracks and signals for driving
375 entry / 'railSignal(*_LN_0,FWD,GREEN)';
376 entry / 'railTrack(*_LN_0,FWD,trainNum,NORMAL)';
377 entry / 'railTrack(*_LN_1,FWD,trainNum,NORMAL)';
378 entry / 'railSignal(*_LN_1, FWD, RED)';
379 };
sna 10.1 380
sna 15.1 381 // Region for handling cleanup functionalities
382 region Cleanup:
383 initial state Entry
384 // Transition to cleanup state
385 --> cleanup with 'railContact(*_LN_0,0)';
sna 10.1 386
sna 15.1 387 // State for cleaning up the previous track segments
388 final state cleanup {
389 entry debug / 'println("[trainNum][ST-ST] Entered *_LN_0 completely")';
390 // Entry-Action with hostcode call to switching off the previous track
391 entry / 'railTrackOff(*_ST_4)';
392 // Entry-Action to release the previous track
393 entry / *_ST_4_req[trainNum] = false;
394 };
395 // Transition to transitional state
396 }>-> *_LN_0_*_LN_1;
sna 10.1 397
sna 15.1 398 state *_LN_0_*_LN_1
399 // Transition to next track segment, if contact is triggered
400 --> *_LN_1 with 'railContact(*_LN_1,0)';
sna 10.1 401
sna 18.1 402 // ----------------------------------------------------------------------------------------------------------------
sna 10.1 403
404
405
sna 15.1 406 // State for entering a station
407 state *_LN_5 {
408 // Variable for checking all needed permissions
409 int perm_all_next_segments = false;
410 entry / 'println("[trainNum][ST-ST] Entering *_LN_5")';
411 entry / 'railSignal(*_LN_4, FWD, RED)';
sna 10.1 412
sna 15.1 413 // Region for handling train driving such as above,
414 // only with perm_all_next_segments for permitting more than one track
415 region Travel:
416 initial state Entry
417 --> Continue with 'railContact(*_LN_5,0)' & perm_all_next_segments
418 --> Slowdown with 'railContact(*_LN_5,0)';
sna 10.1 419
sna 15.1 420 state Slowdown {
421 entry debug / 'println("[trainNum][ST-ST] Slowing down on *_LN_5")';
422 entry / 'railTrack(*_LN_5,FWD,trainNum,CAUTION)';
423 }
424 --> Waiting with 'railContact(*_LN_5,1)'
425 --> Continue with perm_all_next_segments;
sna 10.1 426
sna 15.1 427 state Waiting {
428 entry debug / 'println("[trainNum][ST-ST] Stopping on *_LN_5")';
429 entry / 'railTrackBrake(*_LN_5)';
430 }
431 --> Continue with perm_all_next_segments;
sna 10.1 432
sna 15.1 433 final state Continue {
434 entry debug / 'println("[trainNum][ST-ST] Continuing on *_LN_5")';
435 entry i_arrOnTrack == 1 / 'railTrack(*_ST_1,FWD,trainNum,NORMAL)';
436 entry i_arrOnTrack == 2 / 'railTrack(*_ST_2,FWD,trainNum,NORMAL)';
437 entry i_arrOnTrack == 3 / 'railTrack(*_ST_3,FWD,trainNum,NORMAL)';
438 //...
439 entry / arrTrack = i_arrOnTrack;
440 };
sna 10.1 441
sna 15.1 442 // Region for handling cleanup-functionalities such as above
443 region Cleanup:
444 initial state Entry
445 --> cleanup with 'railContact(*_LN_5,0)';
sna 10.1 446
sna 15.1 447 final state cleanup {
448 entry debug / 'println("[trainNum][ST-ST] Entered *_LN_5 completely")';
449 entry / 'railTrackOff(*_LN_4)';
450 entry / *_LN_4_req[trainNum] = false;
451 };
sna 10.1 452
sna 15.1 453 // Region for handling permissions of all needed tracks
454 region Permissions:
455 // State for requesting all needed tracks according to destination track and cleanup-Flag
456 initial state checking {
457 entry / *_ST_0_req[trainNum] = true;
458 entry destTrack == 1 | !cleanup / *_ST_1_req[trainNum] = true;
459 entry destTrack == 2 | !cleanup / *_ST_2_req[trainNum] = true;
460 entry destTrack == 3 | !cleanup / *_ST_3_req[trainNum] = true;
461 }
462 // Transitions for permitted tracks match wished tracks
463 --> success with destTrack == 1 & *_ST_0_perm == trainNum & *_ST_1_perm == trainNum / i_arrOnTrack = 1
464 --> success with destTrack == 2 & *_ST_0_perm == trainNum & *_ST_2_perm == trainNum / i_arrOnTrack = 2
465 --> success with destTrack == 3 & *_ST_0_perm == trainNum & *_ST_3_perm == trainNum / i_arrOnTrack = 3
466 // Transitions for permitted tracks don't match wished tracks
467 --> success with *_ST_0_perm == trainNum & *_ST_1_perm == trainNum / i_arrOnTrack = 1
468 --> success with *_ST_0_perm == trainNum & *_ST_2_perm == trainNum / i_arrOnTrack = 2
469 --> success with *_ST_0_perm == trainNum & *_ST_3_perm == trainNum / i_arrOnTrack = 3
470 // Transition for not all tracks permitted
471 --> resolving with *_ST_0_perm == trainNum | *_ST_3_perm == trainNum | *_ST_2_perm == trainNum | *_ST_1_perm == trainNum;
sna 10.1 472
sna 15.1 473 // State for waiting an additional tick
474 state resolving
475 --> resolving1;
476
477 // State for releasing track requests
478 state resolving1 {
479 entry / *_ST_0_req[trainNum] = false;
480 entry / *_ST_1_req[trainNum] = false;
481 entry / *_ST_2_req[trainNum] = false;
482 entry / *_ST_3_req[trainNum] = false;
483 }
484 // Transition for trying the requesting again
485 --> checking;
sna 10.1 486
sna 15.1 487 // State for waiting an additional tick
488 state success
489 --> success1;
sna 10.1 490
sna 15.1 491 // State for releasing not used track requests
492 final state success1 {
493 entry !(i_arrOnTrack == 1) / *_ST_1_req[trainNum] = false;
494 entry !(i_arrOnTrack == 2) / *_ST_2_req[trainNum] = false;
495 entry !(i_arrOnTrack == 3) / *_ST_3_req[trainNum] = false;
496 // Settting perm_all_next_segments to true
497 entry / perm_all_next_segments = true;
498 };
499 // Transition to station entry states
500 }>-> *_LN_5_*_ST;
sna 10.1 501
sna 15.1 502 // State waiting for station entry
503 state *_LN_5_*_ST
504 --> Arr_*_ST with i_arrOnTrack == 1 & 'railContact(*_ST_1,0)'
sna 16.1 505  --> Arr_*_ST with i_arrOnTrack == 2 & 'railContact(*_ST_2,0)'
sna 15.1 506 --> Arr_*_ST with i_arrOnTrack == 3 & 'railContact(*_ST_3,0)';
sna 10.1 507
sna 15.1 508 // State for setting tracks, points and signals according to i_arrOnTrack
509 // and releasing previous track request
510 state Arr_*_ST {
511 entry / 'railSignal(*_LN_5, FWD, RED)';
512 entry / 'railTrackOff(*_LN_5)';
513 entry / 'railTrack(*_ST_0,FWD,trainNum,SLOW)';
514 entry i_arrOnTrack == 1 / 'railTrack(*_ST_1,FWD,trainNum,SLOW)';
515 entry i_arrOnTrack == 2 / 'railTrack(*_ST_2,FWD,trainNum,SLOW)';
516 entry i_arrOnTrack == 3 / 'railTrack(*_ST_3,FWD,trainNum,SLOW)';
517 entry / *_LN_5_req[trainNum] = false;
sna 10.1 518
sna 15.1 519 initial state SlowEntry
520 --> Slow with i_arrOnTrack == 1 & 'railContact(*_ST_1,0)'
521 --> Slow with i_arrOnTrack == 2 & 'railContact(*_ST_2,0)'
522 --> Slow with i_arrOnTrack == 3 & 'railContact(*_ST_3,0)';
sna 10.1 523
sna 15.1 524 // State for switching off previous track and releasing the request
525 state Slow {
526 entry / 'railTrackOff(*_ST_0)';
527 entry / *_ST_0_req[trainNum] = false;
528 }
529 // Transitions to halt state, when train is at second contact of a track segment
530 --> Halt with i_arrOnTrack == 1 & 'railContact(*_ST_1,1)'
531 --> Halt with i_arrOnTrack == 2 & 'railContact(*_ST_2,1)'
532 --> Halt with i_arrOnTrack == 3 & 'railContact(*_ST_3,1)';
sna 10.1 533
sna 15.1 534
535 final state Halt {
536 // Entry-Actions for braking the train on correct track
537 entry i_arrOnTrack == 1 / 'railTrackBrake(*_ST_1)';
538 entry i_arrOnTrack == 2 / 'railTrackBrake(*_ST_2)';
539 entry i_arrOnTrack == 3 / 'railTrackBrake(*_ST_3)';
540 // Entry-Actions for waiting for timer on correct track
541 entry i_arrOnTrack == 1 / 'railArrival(trainNum, *_ST_1)';
542 entry i_arrOnTrack == 2 / 'railArrival(trainNum, *_ST_2)';
543 entry i_arrOnTrack == 3 / 'railArrival(trainNum, *_ST_3)';
544 };
545 }
546 >-> done;
sna 10.1 547
sna 15.1 548 state done
549 // Transition to final state, if timer is ready
550 --> reallyDone with 'railDeparture(trainNum)';
sna 10.1 551
sna 15.1 552 final state reallyDone;
553 }
554 {{/code}}
sna 19.1 555
556 == Dynamic Controller ==
557
558 The dynamic controller handles all 11 Trains. For each train the controller has a region with a referenced dynamic scheduling. Thereby each train can follow an arbitrary schedule. Additionally the controller has a region for stable cleanup function.
559
560 {{code linenumbers="true" language="sct"}}
561 //
562 // Dynamic controller for 11 trains
563 //
564 scchart DynamicController11 {
565 // Set of request variables for all tracks for 11 trains
566 bool IC_JCT_0_req[11], IC_LN_0_req[11], IC_LN_1_req[11], IC_LN_2_req[11];
567 bool IC_LN_3_req[11], IC_LN_4_req[11], IC_LN_5_req[11], IC_ST_0_req[11];
568 bool IC_ST_1_req[11], IC_ST_2_req[11], IC_ST_3_req[11], IC_ST_4_req[11];
569 bool IO_LN_0_req[11], IO_LN_1_req[11], IO_LN_2_req[11], KH_LN_0_req[11];
570 bool KH_LN_1_req[11], KH_LN_2_req[11], KH_LN_3_req[11], KH_LN_4_req[11];
571 bool KH_LN_5_req[11], KH_LN_6_req[11], KH_LN_7_req[11], KH_LN_8_req[11];
572 bool KH_ST_0_req[11], KH_ST_1_req[11], KH_ST_2_req[11], KH_ST_3_req[11];
573 bool KH_ST_4_req[11], KH_ST_5_req[11], KH_ST_6_req[11], KIO_LN_0_req[11];
574 bool KIO_LN_1_req[11], OC_JCT_0_req[11], OC_LN_0_req[11], OC_LN_1_req[11];
575 bool OC_LN_2_req[11], OC_LN_3_req[11], OC_LN_4_req[11], OC_LN_5_req[11];
576 bool OC_ST_0_req[11], OC_ST_1_req[11], OC_ST_2_req[11], OC_ST_3_req[11];
577 bool OC_ST_4_req[11], OI_LN_0_req[11], OI_LN_1_req[11], OI_LN_2_req[11];
578 bool req_in_R , req_out_R , req_in_L , req_out_L;
579  
580 // Set of permission variables for all tracks
581 int IC_JCT_0_perm, IC_LN_0_perm, IC_LN_1_perm, IC_LN_2_perm;
582 int IC_LN_3_perm, IC_LN_4_perm, IC_LN_5_perm, IC_ST_0_perm;
583 int IC_ST_1_perm, IC_ST_2_perm, IC_ST_3_perm, IC_ST_4_perm;
584 int IO_LN_0_perm, IO_LN_1_perm, IO_LN_2_perm, KH_LN_0_perm;
585 int KH_LN_1_perm, KH_LN_2_perm, KH_LN_3_perm, KH_LN_4_perm;
586 int KH_LN_5_perm, KH_LN_6_perm, KH_LN_7_perm, KH_LN_8_perm;
587 int KH_ST_0_perm, KH_ST_1_perm, KH_ST_2_perm, KH_ST_3_perm;
588 int KH_ST_4_perm, KH_ST_5_perm, KH_ST_6_perm, KIO_LN_0_perm;
589 int KIO_LN_1_perm, OC_JCT_0_perm, OC_LN_0_perm, OC_LN_1_perm;
590 int OC_LN_2_perm, OC_LN_3_perm, OC_LN_4_perm, OC_LN_5_perm;
591 int OC_ST_0_perm, OC_ST_1_perm, OC_ST_2_perm, OC_ST_3_perm;
592 int OC_ST_4_perm, OI_LN_0_perm, OI_LN_1_perm, OI_LN_2_perm;
593 bool perm_in_R , perm_out_R , perm_in_L , perm_out_L;
594
595 // Flags needed for stable cleanup function
596 //----------------------------------------------------------------------------------------
597 // Flags for trains are ready and back at home
598 bool trainDone[11];
599 // Flags for trains are on their home circle
600 bool circle[11];
601 // Flag for trains 0 to 7 are back at home and trains 8 to 10 are on their home circle
602  bool mainDone;
603 // Flag for all trains are back at home
604  bool allDone;
605 //----------------------------------------------------------------------------------------
606
607 // Debug flag for additional output
608  bool debug;
609 // Cleanup flag for halting the trains at home station tracks
610  bool cleanup;
611 // Variable, that gives the number of trains to C-Controller for stability check
612  int trainCount;
613 // Constant needed for binding to referenced SCCharts
614 const bool c_TRUE = true;
615
616
617 // State initializing the trains on corresponding tracks
618 initial state init references initRailway11Trains
619 >-> run;
620
621
622 // State handling the train schedules
623  state run {
624
625  // Region handling the cleanup function
626 region Abort:
627 initial state notDone
628  // Transition when trains 0 to 7 are back at home and trains 8 to 10 are on their home circle
629 --> mainDone with trainDone[0] & trainDone[1] & trainDone[2]
630 & trainDone[3] & trainDone[4] & trainDone[5]
631 & trainDone[6] & trainDone[7]
632 & circle[8] & circle[9] & circle[10];
633
634 // State for allowing trains 8 to 10 to halt on the home track
635 state mainDone
636 --> quitCircle with / mainDone = true;
637
638 // State waiting for trains 8 to 10 halt and setting flag for terminate the controller
639 state quitCircle
640 --> done with trainDone[8] & trainDone[9] & trainDone[10] / allDone = true;
641
642 final state done;
643
644 // Regions handling the mutual exclusion on the track segments
645 region Mutexes:
646 initial state Mutexes references mutexRailway11Trains
647 // terminates with a strong abort when all trains are at home
648 o-> done with allDone;
649
650 final state done;
651
652 region KH_Mutexes:
653 initial state KH_Mutexes references kh_mutex
654  // terminates with a strong abort when all trains are at home
655 o-> done with allDone;
656
657 final state done;
658
659 // Regions that contain the dynamic schedules for trains 0 to 7
660 //--------------------------------------------------------------------------------------
661
662 // Region with the dynamic schedule for train 0
663 region Train0:
664 initial state Train0 {
665 @alterHostcode
666 const int trainNum = 0
667  // Variable for saving the home track
668 int homeTrack = 1;
669 // Variable for saving the home station
670 int homeStation = 1;
671
672 // State referenced to dynamic scheduling
673 initial state drive
674 references DynamicSheduling
675  // Binding circleDone to true for halting at home if cleanup is set
676 bind circleDone to c_TRUE
677  // Set a flag and a light for train at home
678 >-> done with / 'railLight(10,1)'; trainDone[0] = true;
679
680 final state done;
681 }
682 >-> done;
683
684 final state done;
685
686 // ... (other regions for trains 1 to 7 such as before)
687
688  //--------------------------------------------------------------------------------------
689
690
691
692
693 // Regions that contain the dynamic schedules for trains 8 to 10
694 // Differences to regions above is that the trains 8 to 10 circle at home station circle
695 // until trains 0 to 7 are back at home station and track
696 // For this circleDone binds mainDone flag
697 //--------------------------------------------------------------------------------------
698
699 // Region with the dynamic schedule for train 8
700 region Train8:
701 initial state Train8 {
702 @alterHostcode
703 const int trainNum = 8
704 // Variable for saving the home track
705  int homeTrack = 5;
706 // Variable for saving the home station
707 int homeStation = 1;
708
709 // State referenced to dynamic scheduling
710 initial state drive
711 references DynamicSheduling
712  // Binding circleDone to mainDone for halting at home only if cleanup is set
713 // and trains 0 to 7 are at home and 8 to 10 on home circle
714 bind circleDone to mainDone
715 // Set a flag and a light for train at home 
716 >-> done with / 'railLight(6,1)'; trainDone[8] = true;
717
718 final state done;
719 }
720 >-> done;
721
722 final state done;
723
724 // ... (other regions for trains 9 and 10 such as before)
725 //--------------------------------------------------------------------------------------
726
727  }
728 >-> flash;
729
730 // State for flashing the lights at the end of the controller
731 state flash
732 --> done with / 'railFlashLight()';
733
734 final state done;
735 }
736 {{/code}}
nfl 20.1 737
738 === Dynamic Scheduling ===
739
740 Each train has the same dynamic scheduling. The basic idea are 4 station-states (KH, KHr, IC, OC). Each time a train is one of these states, the next target station is looked up. Depending on the current station there are 4 different travel paths available each leading into in of the 4 station-states. This way the dynamic scheduling can handle every possible schedule for each train.
741
742 In addition to the travel paths each station-state has a cleanup-transition. A train can only enter cleanup mode, when he arrived at his target station. Each train has a homestation and a hometrack, which he travels to once cleanup is started. Upon arriving at their hometrack, the train shuts down. Once every train is shut down, cleanup finished and every train is back at his starting position. Every station has one track, which does not allow the train, who wants to travel to that track, to shut down. These are KH_ST_5, IC_ST_1 and OC_ST_3. The trains traveling to these stations have to drive circles at KH_LN, IC_LN or OC_LN. Once these are the only trains driving, they are allowed to shut down too. This way a station can not block trains to drive through this station by shutting down all trains in that station.
743
744 [[image:attach:DynamicScheduling.png]]