Skripte der Anlage Winter 2015/16


Anhand meiner Anlage aus der Wintersaison 2015/16 möchte ich meine Skripte vorstellen und erklären. Die Skripte dienen mehrheitlich dazu, die Automatik von Rocrail (RR) zu beeinflussen.
Wie Skripte erstellt und in RR via Aktionsdefinition eingebunden werden, ist hier erklärt; ich werde darauf nicht näher eingehen.
Anmerkung: Viele Wege führen zum Ziel! Alle hier vorgestellten Lösungen lassen sich mit hoher Wahrscheinlichkeit anders umsetzen. Alle Lösungen arbeiteten auf meiner Anlage zuverlässig und sind unter Bedachtnahme geringstmöglicher Redundanz in Bezug auf Coding und Ausführung entwickelt worden.

Anlagenplan

Hier nun der Plan meiner Anlage, der die Basis für alle Erklärungen darstellt:

Anlagenplan


Der Plan kurz erklärt:
Links die Blöcke SBf7_E1, SBf8_E1, SBf9_E1, die einen Endbahnhof für Pendelzüge (Nahverkehr, NV) bilden (Ortschaft, Mindestbelegung = 3, FiFo = ein). SBf10_E1 ist ein Tank-/Wartungs-/Warte-/Abstellgleis für Pendelzüge, von SBf6_E1 nicht befahrbar (keine Fahrstraße). Die Blöcke SBf3_E1, SBf4_E1, SBf5_E1 bilden einen Schattenbahnhof für Fernverkehrs(FV)züge (Ortschaft, Mindestbelegung = 3, FiFo = ein), die Blöcke SBf1_E1, SBf2_E1, SBf6_E1, SBf11_E1 bilden einen Schattenbahnhof für Güter(GV)züge (Ortschaft, Mindestbelegung = 4, FiFo = aus). An Hand der grünen Richtungspfeile ist zu erkennen, dass alle Züge den Bahnhof über den Block Str3_E2_E1 angefahren werden und über den Block Str1_E1_E2 (bzw. auch Str1_E1) verlassen.
In der Mitte bilden die Blöcke Bf1_E2 bis Bf5_E2 einen Durchgangs- bzw. Abzweigbahnhof via Strecke Str1_E2 zum Endbahnhof KBf1_E2 und KBf2_E2 (Pendelzüge, Ortschaft, Mindestbelegung = 2, FiFo = ein). Block Bf6_E2 ist ein Abstellgleis für eine Rangierlok.
Im rechten Anlagenteil stellen die Blöcke Bf1_E3 bis Bf4_E3 einen Abstellbahnhof für GV (Ortschaft, Mindestbelegung = 4, FiFo = ein) dar, die Blöcke Bf8_E3 und Bf9_E3 einen für FV (Ortschaft, Mindestbelegung = 2, FiFo = ein). Die Blöcke Bf6_E3 und Bf7_E3 bilden die Gleise des NV-Bahnhofs (Ortschaft, Mindestbelegung = 2, FiFo = ein) ab, Block Bf5_E3 ist ein Zulaufgleis für NV.

Steuerung Endbahnhof E2

Es ist deutlich zu erkennen, dass der Endbhf. KBf1_E2 und KBf2_E2 ein deadlock-Problem aufweist. Sind beide Blöcke belegt und ein weiterer NV-Zug fährt in die Strecke Str1_E2, so kann kein Zug den Endbhf. verlassen.
Anmerkung: Dies läßt sich auch anders lösen, z. B. durch Elimination des Blocks Str1_E2, doch wollte ich die Blöcke des Durchgangsbhfs. so rasch als möglich frei bekommen.
Ich habe folgendes Skript entwickelt:

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_FS_KBf_E2">
 
<!-- FS sperren -->
<if state="bk KBf1_E2 = occupied|bk KBf2_E2 = occupied" alltrue="true">
  <then>
    <st id="[Bf1_E2+]-[Str1_E2+]" state="closed"/>
    <st id="[Bf2_E2+]-[Str1_E2+]" state="closed"/>
    <st id="[Bf3_E2+]-[Str1_E2+]" state="closed"/>
    <st id="[Bf4_E2+]-[Str1_E2+]" state="closed"/>
    <exit cmt="Script FS_KBf_E2: FS geschlossen"/>
  </then>
</if>
 
<!-- FS öffnen -->
<if state="bk KBf1_E2 = free|bk KBf2_E2 = free" alltrue="false">
  <then>
    <st id="[Bf1_E2+]-[Str1_E2+]" state="open"/>
    <st id="[Bf2_E2+]-[Str1_E2+]" state="open"/>
    <st id="[Bf3_E2+]-[Str1_E2+]" state="open"/>
    <st id="[Bf4_E2+]-[Str1_E2+]" state="open"/>
    <exit cmt="Script FS_KBf_E2: FS geöffnet"/>
  </then>
</if>
 
</xmlscript>

und viermal als Aktion in die Blöcke KBf1_E2 und KBf2_E2 eingebunden:
-) FS_KBf1_E2, Status “occupied”,
-) FS_KBf2_E2, Status “free”,
-) FS_KBf2_E2, Status “occupied”,
-) FS_KBf2_E2, Status “free”,
jeweils ohne Aktionsbedingungen.
Beispielhaft hier die Angabe der Aktionssteuerung für die Aktion FS_KBf1_E2 im Block KBf1_E2:

<actionctrl id="FS_KBf_E2" reset="true" allconditions="true" desc="" atcmd="false" atevt="false" auto="true" manual="false" state="occupied" substate="" duration="0" timer="0" callerid="KBf1_E2" bkid="KBf1_E2" stid="[Str1_E2-]-[KBf1_E2+]"/>
<actionctrl id="FS_KBf_E2" reset="true" allconditions="true" desc="" atcmd="false" atevt="false" auto="true" manual="false" state="free" substate="" duration="0" timer="0" callerid="KBf1_E2" bkid="KBf1_E2" stid="[Str1_E2-]-[KBf1_E2+]"/>


Wie arbeitet das Skript?
Nun, im Wesentlichen schließt und öffnet das Skript Fahrstraßen (FS). Visualisiert wird dies durch das FS-Symbol links vom Block Str1_E2.
Die Ausgangslage ist, dass beide Blöcke KBf1_E2 und KBf2_E2 frei sind. Fährt ein Zug in Block KBf1_E2 ein und besetzt den Block (“occupied” beim IN-Ereignis), so wird das Skript aufgerufen. Die Abarbeitung trifft auf die erste IF-Zeile. In dieser wird geprüft, ob der Status im Block KBf1_E2 gleich “occupied” und (alltrue=“true”) im Block KBf2_E2 gleich “occupied” ist. Dies trifft nicht zu (KBf2_E2 ist ja noch frei) und die IF-Abfrage wird verlassen. Die nächste IF-Abfrage wird positiv bewertet, denn in der ODER-Bedingung (alltrue=“false”) ist Block KBf2_E2 “free”. Daher werden die nach dem “then” angeführten FS geöffnet und das Skript in der “exit”-Zeile verlassen. (In diesem einen Fall ist das Skript redundant, denn die FS sind geöffnet. Man könnte diese eine Abfrage aber noch elegant abfangen.)
Ein weiterer Zug kommt und fährt in KBf2_E2 ein, besetzt ihn und das Skript wird aufgerufen. Jetzt ist die erste IF-Abfrage true, die FS aus dem Durchgangs-/Abzweigbhf. zur Strecke Str1_E2 werden geschlossen, das FS-Symbol im Plan wird violett, das Skript via “exit” verlassen. Somit kann kein weiterer Zug mehr in die Strecke Str1_E2 fahren.
Verläßt ein Zug einen Block des Endbhfs. E2, so wird dieser Block mit Besetzen des Blocks Str1_E2 frei (“free”). Dieses Ereignis bewirkt den Aufruf des Skripts. Dieses wird abgearbeitet; die erste IF-Bedingung trifft nicht zu (beide Blöcke müssen besetzt sein), die zweite IF-Bedingung trifft zu, die FS werden geöffnet, das FS-Symbol wird weiß. Nachdem der Zug im Durchgangs-/Abzweigbhf. vollständig angekommen ist, kann ein anderer (oder derselbe) Zug wieder via Strecke Str1_E2 zum Endbhf. E2 fahren.

In diesem gezeigten Lösungsbeispiel zeigt sich die Eleganz des Einsatzes von Skripts: Mit einem Skript und vier Skriptaufrufen ist das Problem gelöst. Würde man das Problem mit klassischen Aktionen lösen, bräuchte man acht Aktionen, die in vier Aktionsaufrufen, über Bedingungen gesteuert, verarbeitet werden.

Steuerung von NV-Fahrten von Ebene 2 (_E2) nach Ebene 1 (_E2)

Der linke Teil der Anlage (Ebene 1) hält 4 Gleise für NV-Züge bereit: SBf7_E1, SBf8_E1, SBf9_E1, SBf10_E1. Sind diese 4 Gleise besetzt, müsste ein weiterer NV-Zug im Einfahrts-Block Str3_E2_E1 warten und blockierte somit den Zulauf zu den anderen FV- und GV-Gleisen. Eine mögliche Lösung wäre, die Fahrten von NV-Zügen in den Block Str1_E2_E1 zu zählen und bei Erreichen der Anzahl “4” diese Fahrten zu unterbinden. Mittels folgendem Skript wurde diese Lösung realisiert:

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_Abfahrt_NV_E2">
 
<!-- Anzahl NV -->
<!-- vr id="Var_NV" value="0"/-->
 
<!-- Ist Zug NV? -->
<if condition="%lccargo% # person|%lccargo% # lightgoods|%lccargo% # light" alltrue="false">
  <then>
    <!-- Aufruf ENTER aus Str1_E2_E1 -->
    <if condition="%callerid% # Str1_E2_E1">
      <then>
        <vr id="Var_NV" value="#Var_NV + 1"/>
	<tx id="T_Var_NV" format="NV: #Var_NV"/>
	<if condition="#Var_NV = 4">
	  <then>
	    <bk id="Str1_E2_E1" cmd="classdel" class="NV"/>
	    <bk id="Str1_E2_E1" cmd="classdel" class="GNB"/>
	    <bk id="Bf5_E2" cmd="classdel" class="NV"/>
	    <bk id="Bf5_E2" cmd="classdel" class="GNB"/>
	    <exit cmt="Script Abfahrt_NV_E2: Klassen NV und GNB gelöscht"/>
	  </then>
	</if>
      </then>
    </if>
    <!-- Aufruf ENTER aus Str1_E1_E2 -->
    <if condition="%callerid% # Str1_E1_E2">
      <then>
        <vr id="Var_NV" value="#Var_NV - 1"/>
	<tx id="T_Var_NV" format="NV: #Var_NV"/>
	<bk id="Str1_E2_E1" cmd="classadd" class="NV"/>
	<bk id="Str1_E2_E1" cmd="classadd" class="GNB"/>
	<bk id="Bf5_E2" cmd="classadd" class="NV"/>
	<bk id="Bf5_E2" cmd="classadd" class="GNB"/>
	<exit cmt="Script Abfahrt_NV_E2: Klassen NV und GNB hinzugefügt"/>
      </then>
    </if>
  </then>
  <else>
    <exit cmt="Script Abfahrt_NV_E2: Kein NV oder kein GNB"/>
  </else>
</if>
 
</xmlscript>

Das Skript wird in den Blöcken Str1_E2_E1 und Str1_E1_E2 beim Ereignis ENTER aufgerufen.

Wie funktioniert nun das Skript?
Angenommen, die Blöcke SBf7_E1, SBf8_E1, SBf9_E1, SBf10_E1 (Ebene 1) sind leer. Somit ist auch die Variable “Var_NV” = 0 und dieser Wert wird im Textfeld “T_Var_NV” angezeigt (im Anlagenplan zu sehen unterhalb der 3 Ausgänge - hier: “NV: 4”).
Fährt nun ein Zug vom Durchgangs-/Abzweigbf. in Ebene 2 in den Block Str1_E2_E1, so wird das Skript aufgerufen. In der ersten IF-Abfrage wird geprüft, ob es sich bei der Zugart um NV-Züge (“person”) handelt (dazu zählen in diesem Fall auch Nebenbahn = “light” und Güternebenbahn = “lightgoods”), denn nur diese Zugart ist hier relevant. Führe ein FV-Zug in den Block, würde das Skript ebenfalls aufgerufen, aber auf Grund einer negativen Bedingungsprüfung das Skript sofort wieder verlassen werden. (Ein Beispiel für meine Bedachtnahme auf geringstmögliche Redundanz und effiziente Bearbeitung.) Die nächste IF-Bedingung prüft, von welchem Block das Skript aufgerufen wurde. Hier liefert die Abfrage ein “wahr” zurück und folgende Schritte werden ausgeführt:
-) die Variable “Var_NV” wird um “1” erhöht,
-) der neue Wert wird in der Textvariablen “T_Var_NV” ausgegeben.
Im nachfolgenden IF wird geprüft, ob die Variable den Wert “4” hat. Dies ist nicht der Fall und das Skript wird verlassen.
Die Anlage läuft, NV-Zug um NV-Zug fährt von Ebene 2 in die Ebene 1 (aus der noch kein NV-Zug ausgefahren ist, weil die Ortschaftsbedingung nicht erfüllt ist). Irgendwann ist die Bedingung ”#Var_NV = 4” erfüllt und
-) aus dem Block Str1_E2_E1 werden die Klassen “GNB” und “NV” gelöscht,
-) aus dem Block Bf5_E2 werden die Klassen “GNB” und “NV” gelöscht,
-) das Skript wird verlassen.
Dies bewirkt, dass keine NV-Züge mehr in die Ebene 1 fahren dürfen. (Block Bf5_E2 ist hier als Sonderfall ebenfalls mit diesen Klassen beaufschlagt, da von diesem Block kein NV-Zug mehr alternativ nach Str1_E2 fahren könnte und somit diesen Block längere Zeit blockieren würde.)
Die Ebene 1 ist mit NV-Zügen voll (4), irgendwann fährt der erste NV-Zug aus Ebene 1 ab und ruft bei ENTER im Block Str1_E1_E2 das Skript auf. Nun trifft die Bedingung “condition=”%callerid% # Str1_E1_E2” zu und diese Einstellungen werden gemacht:
-) die Variable “Var_NV” wird um “1” verringert,
-) der neue Wert wird in der Textvariablen “T_Var_NV” ausgegeben.
-) in den Blöcken Bf5_E2 und Str1_E2_E1 werden die Klassen “GNB” und “NV” gesetzt,
-) das Skript wird verlassen.
Nun darf wieder ein NV-Zug von Ebene 2 über Block Str1_E2_E1 in die Ebene 1 fahren und das Spiel beginnt von neuem.

Steuerung der Fahrten an der Überleitstelle

Im rechten Anlagenteil (Ebene 3) ist oberhalb der Blöcke Str1_E3 und Str2_E3 eine Überleitstelle mit 4 Weichen platziert. Wird die RR-Automatik nicht beeinflusst, werden die Zugfahrten über die Blöcke Str1_E3 und Str2_E3 über eine gewisse Zeit gleichverteilt. Das wollte ich nicht. Ich wollte, dass von Str3_E2_E3 kommende Züge, wenn frei, die Strecke Str1_E3 befahren und über Str2_E3 den Bahnhof erreichen - kurz: die Runde machen.
Weiters wollte ich verhindern, dass bei besetzten Bahnhofsgleisen die Züge im Block Str2_E3 (und ggfs. den davor liegenden) stecken bleiben. Wenn möglich, sollten sie kreisen (ich weiß, das ist nicht vorbildgerecht).
Zu diesen Zwecken habe ich folgendes Skript entwickelt:

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_Uest_E3">
 
<!-- FS aus Str3_E2_E3 sperren -->
<if condition="%callerid% # Str3_E2_E3">
  <then>
    <if state="bk Str3_E2_E3 = reserved|bk Str1_E3 = free" alltrue="true">
      <then>
        <vr id="Uest_Lok1" text="%lcid%"/>
        <st id="[Str3_E2_E3-]-[Str2_E3-]" state="closed"/>
	<exit/>
      </then>
    </if>
  </then>
</if>
 
<!-- Und FS im Block Str1_E3 wieder öffnen -->
<if condition="%callerid% # Str1_E3">
  <then>
    <if condition="@Uest_Lok1 = %lcid%" alltrue="true">
      <then>
        <st id="[Str3_E2_E3-]-[Str2_E3-]" state="open"/>
	<vr id="Uest_Lok1" text=""/>
	<exit/>
      </then>
    </if>
  </then>
</if>
 
<if condition="%callerid% # Str3_E3">
  <then>
    <!-- Zufahrt zum Bahnhof_NV_E3 regeln -->
    <if condition="%lccargo% # person|%lccargo% # lightgoods|%lccargo% # light" alltrue="false">
      <then>
        <vr id="Uest_Lok2" text="%lcid%"/>
        <if state="bk Str2_E3 = free|bk Bf5_E3 = free"  alltrue="true">
          <then>
	    <st id="[Str3_E3+]-[Str1_E3-]" state="closed"/>
            <exit/>
          </then>
        </if>
      </then>
    </if>
    <!-- Zufahrt zum Bahnhof_GV_E3 regeln -->
    <if condition="%lccargo% # goods" alltrue="true">
      <then>
        <vr id="Uest_Lok2" text="%lcid%"/>
        <if state="bk Str2_E3 = free|bk Str2_E3 ! closed" alltrue="true">
	  <then>
	    <if state="bk Bf1_E3 = free|bk Bf2_E3 = free|bk Bf3_E3 = free|bk Bf4_E3 = free" alltrue="false">
              <then>
	        <st id="[Str3_E3+]-[Str1_E3-]" state="closed"/>
	        <exit/>
              </then>
	      <else>
	        <st id="[Str3_E3+]-[Str2_E3-]" state="closed"/>
	        <exit/>
	      </else>
            </if>
	  </then>
	  <else>
	    <exit/>
	  </else>
	</if>
      </then>
    </if>
    <!-- Zufahrt zum Bahnhof_FV_E3 regeln -->
    <if condition="%lccargo% # ice" alltrue="true">
      <then>
        <vr id="Uest_Lok2" text="%lcid%"/>
	<if state="bk Str2_E3 = free|bk Str2_E3 ! closed" alltrue="true">
	  <then>
            <if state="bk Bf8_E3 = free|bk Bf9_E3 = free" alltrue="false">
              <then>
	        <st id="[Str3_E3+]-[Str1_E3-]" state="closed"/>
	        <exit/>
              </then>
	      <else>
	        <st id="[Str3_E3+]-[Str2_E3-]" state="closed"/>
	        <exit/>
	      </else>
            </if>
          </then>
        </if>
      </then>
    </if>
  </then>
</if>
 
<!-- Und FS im Block Str2_E3 wieder öffnen -->
<if condition="%callerid% # Str2_E3">
  <then>
    <if condition="@Uest_Lok2 = %lcid%" alltrue="true">
      <then>
        <st id="[Str3_E3+]-[Str1_E3-]" state="open"/>
	<vr id="Uest_Lok2" text=""/>
	<exit/>
      </then>
    </if>
  </then>
</if>
 
<!-- Und FS im Block Str1_E3 wieder öffnen -->
<if condition="%callerid% # Str1_E3">
  <then>
    <if condition="@Uest_Lok2 = %lcid%" alltrue="true">
      <then>
        <st id="[Str3_E3+]-[Str2_E3-]" state="open"/>
	<vr id="Uest_Lok2" text=""/>
        <exit/>
      </then>
    </if>
  </then>
</if>
 
</xmlscript>

Der Aufruf des Skripts erfolgt in diesen Blöcken:
-) Str3_E2_E3, bei RESERVED, keine Bedingung,
-) Str1_E3, bei ENTER, keine Bedingung,
-) Str3_E3, bei RESERVED, keine Bedingung,
-) Str2_E3, bei OCCUPIED, keine Bedingung.

Wie arbeitet das Skript?
Ein Zug verläßt Ebene 2 und fährt in den Block Str2_E2_E3. Beim ENTER-Ereignis wird die nächste FS zum Block Str3_E2_E3 reserviert, im Block Str3_E2_E3 tritt das Ereignis RESERVED ein, das Skript wird aufgerufen. Gleich das erste IF im Skript fängt diesen Aufruf ab und prüft, ob der Block wirklich reserved ist und (“alltrue=true”) ob Block Str1_E3 frei ist. Wenn ja, wird die aktuell im Block gemeldete Lok in der Variablen “Uest_Lok1” gespeichert, die FS zum Block Str2_E3 gesperrt und das Skript verlassen. Wenn nein, greift die RR-Automatik und eine FS wird zum Block Str2_E3 gestellt. Ist auch Block Str2_E3 besetzt, muss der Zug im Block Str3_E2_E3 warten.
Fährt der Zug in den Block Str1_E3, wird das Skript bei ENTER aufgerufen und verarbeitet (condition=”%callerid% # Str1_E3”). Es wird geprüft, ob es dieselbe Lok ist (@Uest_Lok1 = %lcid%), die zuvor die FS nach Str2_E3 gesperrt hat. Wenn ja, wird diese FS wieder geöffnet, die Variable “Uest_Lok1” wird geleert (””) und das Skript verlassen. Wenn nein, läuft das Skript weiter unten in eine weitere Abfrage (siehe später).
Dreht ein Zug die Runde über Str4_E3 und Str3_E3, weiß er nicht, ob die Einfahrt in den Bahnhof möglich ist. Mittels Skriptaufruf bei RESERVED im Block Str3_E3 wird das geklärt.
Für den Fall, dass ein NV-Zug im Anrückbereich ist, wird geprüft, ob es sich um eine ebensolche Zugart (zudem auch Nebenbahn und Güternebenbahn) handelt. Wenn ja, wird die gemeldete Lok in der Variablen “Uest_Lok2” gespeichert. Sodann wird geprüft, ob der Zufahrtsblock zum Bahnhof Str2_E3 und der Block Bf5_E3 frei sind. Ist dies der Fall, wird die FS von Str3_E3 zum Block Str1_E3 gesperrt und der Zug fährt in den Bf. Das Skript wird verlassen. Kommt ein GV-Zug, wird die Lok gespeichert und geprüft, ob die Zufahrt Str2_E3 zum Bahnhof frei und nicht geschlossen ist. Ist dies der Fall, wird geprüft, ob ein Bfs.gleise für den GV frei ist. Wenn ja, wird die FS zur Strecke Str1_E3 geschlossen, der Zug fährt in den Bf. Wenn nein, wird die FS zum Zufahrtsblock Str2_E3 geschlossen und der Zug dreht eine weitere Runde. Das Skript wird verlassen.
Kommt ein FV-Zug, verläuft die Bearbeitung analog zum GV-Zug.
Fahren die Züge in den Block Str2_E3, wird das Skript bei OCCUPIED aufgerufen und verarbeitet (condition=”%callerid% # Str2_E3”). Es wird geprüft, ob es dieselbe Lok ist (@Uest_Lok2 = %lcid%), die zuvor im Block Str3_E3 das Skript aufgerufen hat. Wenn ja, wird die FS von Str3_E3 nach Str3_E1 wieder geöffnet, die Variable “Uest_Lok2” wird geleert (””) und das Skript verlassen.
Es bleibt nur noch den Fall zu betrachten, falls ein Zug die Runde drehen muss und dafür die FS zum Block Str2_E3 gesperrt hat. Dafür ist das letzte IF im Skript zuständig; es sollte mittlerweile selbsterklärend sein.

Steuerung der Routenwahl in Ebene 2

GV-Züge, die von Ebene 1 kommen, sollen ohne Halt auf Gleis/Block Bf3_E2 durchfahren, GV-Züge, die von Ebene 2 kommen, sollen ohne Halt auf Gleis/Block Bf4_E2 durchfahren. RR ist diesbezüglich konfiguriert, es zeigte sich aber laufend, dass die GV-Züge die beiden Gleise auskreuzen: Fahrten von E1→E3 führen über Bf4_E2, Fahrten von E3→E1 führen über Bf3_E2. Das ist unschön, denn es bewirkt unnötige Halte anderer anrückender Züge. Mit Bordmittel ist dieses Problem nicht zu lösen, die Funktion “Vorzugsfahrstraßen” gibt es nicht.
Für NV- und FV-Züge exisitiert diese Problem weitest gehend nicht, denn für diese Art von Zügen sind die Blöcke Bf1_E2, Bf2_E2 und Bf5_E3 bevorzugte Ziele.
Gleichwohl sollen NV-Züge aus Block Str1_E2 nicht in das Bfs.gleis B4_E2 fahren, wenn Bf3_E2 frei ist. Damit wird ebenfalls ein Auskreuzen verhindert.
Das folgende Skript löst alle diese Problemstellungen:

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_FS_Bf_E2">
 
<!-- Wenn Zug aus Str3_E3_E2 -->
<if condition="%callerid% # Str3_E3_E2">
  <then>
     <!-- Auskreuzen Bf3/Bf4 verhindern, FS sperren -->
     <if state="bk Bf4_E2 = free" alltrue="true">
       <then>
         <vr id="Lok1_Bf2" text="%lcid%"/>
         <st id="[Str3_E3_E2+]-[Bf3_E2-]" state="closed"/>
	 <exit cmt="Script FS_Bf_E2, Str3_E3_E2: FS [Str3_E3_E2+]-[Bf3_E2-] gesperrt"/>
       </then>
       <else>
         <exit cmt="Script FS_Bf_E2, Str3_E3_E2: Bf4_E2 nicht frei"/>
       </else>
     </if>
  </then>
</if>
 
<!-- Wenn Zug aus Str3_E1_E2 -->
<if condition="%callerid% # Str3_E1_E2">
  <then>
     <!-- Auskreuzen Bf3/Bf4 verhindern, FS sperren -->
     <if state="bk Bf3_E2 = free" alltrue="true">
       <then>
         <vr id="Lok2_Bf2" text="%lcid%"/>
         <st id="[Str3_E1_E2-]-[Bf4_E2+]" state="closed"/>
	 <exit cmt="Script FS_Bf_E2, Str3_E1_E2: FS [Str3_E1_E2-]-[Bf4_E2+] gesperrt"/>
       </then>
       <else>
         <exit cmt="Script FS_Bf_E2, Str3_E1_E2: Bf3_E2 nicht frei"/>
       </else>
     </if>
  </then>
</if>
 
<!-- Wenn Zug aus Str1_E2: Fahrt in Bf4 verhindern, wenn Bf3 frei ist -->
<if condition="%callerid% # Str1_E2">
  <then>
    <!-- Kommt Zug von "-"-Seite? -->
    <if state="st [KBf1_E2+]-[Str1_E2-] = locked|st [KBf2_E2+]-[Str1_E2-] = locked" alltrue="false">
      <then>
        <!-- Bf3 frei? -->
        <if state="bk Bf3_E2 = free">
          <then>
            <!-- FS sperren -->
            <st id="[Str1_E2+]-[Bf4_E2+]" state="closed"/>
 	    <exit cmt="Script FS_Bf_E2: FS [Str1_E2+]-[Bf4_E2+] gesperrt"/>
          </then>
          <else>
	    <!-- Wenn Bf3 nicht frei, exit -->
            <exit cmt="Script FS_Bf_E2, Str1_E2: Bf3_E2 nicht frei"/>
          </else>
        </if>
      </then>
      <else>
        <!-- Wenn nicht von "-"-Seite", exit -->
        <exit cmt="Script FS_Bf_E2, Str1_E2: Zug nicht von - Seite"/>
      </else>
    </if>
  </then>
</if>
 
<!-- Wenn Zug in Bf3_E2 -->
<!-- Aufruf bei ENTER, da sonst %frombkid% = "" -->
<if condition="%callerid% # Bf3_E2">
  <then>
    <!-- FS öffnen aus Str3_E1_E2 -->
    <if condition="@Lok2_Bf2 = %lcid%|%frombkid% # Str3_E1_E2" state="st [Str3_E1_E2-]-[Bf4_E2+] = closed" alltrue="true">
      <then>
        <st id="[Str3_E1_E2-]-[Bf4_E2+]" state="open"/>
        <!-- <exit cmt="Script FS_Bf_E2, Bf3_E2: FS [Str3_E1_E2-]-[Bf4_E2+] geöffnet"/>
 -->
      </then>
    </if>
    <!-- FS öffnen aus Str1_E2 -->
    <if condition="%frombkid% # Str1_E2" state="st [Str1_E2+]-[Bf4_E2+] = closed" alltrue="true">
      <then>
	<st id="[Str1_E2+]-[Bf4_E2+]" state="open"/>
        <exit cmt="Script FS_Bf_E2, Bf3_E2: FS [Str1_E2+]-[Bf4_E2+] geöffnet"/>
      </then>
    </if>
  </then>
</if>
 
<!-- Wenn Zug in Bf4_E2 aus Str3_E3_E2 -->
<if condition="%callerid% # Bf4_E2|@Lok1_Bf2 = %lcid%" state="st [Str3_E3_E2+]-[Bf3_E2-] = closed" alltrue="true">
  <then>
     <!-- FS öffnen -->
     <st id="[Str3_E3_E2+]-[Bf3_E2-]" state="open"/>
     <exit cmt="Script FS_Bf_E2, Bf4_E2: FS [Str3_E3_E2+]-[Bf3_E2-] geöffnet"/>
  </then>
</if>
 
<!-- Wenn Zug in Bf1_E2 -->
<if condition="%callerid% # Bf1_E2">
  <then>
    <if condition="@Lok2_Bf2 = %lcid%" state="st [Str3_E1_E2-]-[Bf4_E2+] = closed" alltrue="true">
      <then>
        <!-- FS öffnen aus Str3_E1_E2 -->
        <st id="[Str3_E1_E2-]-[Bf4_E2+]" state="open"/>
        <exit cmt="Script FS_Bf_E2, Bf1_E2: FS [Str3_E1_E2-]-[Bf4_E2+] geöffnet"/>
      </then>
    </if>
    <if condition="@Lok1_Bf2 = %lcid%" state="st [Str3_E3_E2+]-[Bf3_E2-] = closed" alltrue="true">
      <then>
        <!-- FS öffnen aus Str3_E3_E2 -->
        <st id="[Str3_E3_E2+]-[Bf3_E2-]" state="open"/>
        <exit cmt="Script FS_Bf_E2, Bf1_E2: FS [Str3_E3_E2+]-[Bf3_E2-] geöffnet"/>
      </then>
    </if>
    <if state="st [Str1_E2+]-[Bf4_E2+] = closed" alltrue="true">
      <then>
        <!-- FS öffnen aus Str1_E2 -->
        <st id="[Str1_E2+]-[Bf4_E2+]" state="open"/>
        <exit cmt="Script FS_Bf_E2, Bf1_E2: FS [Str1_E2+]-[Bf4_E2+] geöffnet"/>
      </then>
      <else>
        <exit cmt="Script FS_Bf_E2, Bf1_E2: FS nicht geschlossen oder falsche Lok"/>
      </else>
    </if>
  </then>
</if>
 
<!-- Wenn Zug in Bf2_E2 -->
<if condition="%callerid% # Bf2_E2">
  <then>
    <if condition="@Lok2_Bf2 = %lcid%" state="st [Str3_E1_E2-]-[Bf4_E2+] = closed" alltrue="true">
      <then>
        <!-- FS öffnen aus Str3_E1_E2 -->
        <st id="[Str3_E1_E2-]-[Bf4_E2+]" state="open"/>
        <exit cmt="Script FS_Bf_E2, Bf2_E2: FS [Str3_E1_E2-]-[Bf4_E2+] geöffnet"/>
      </then>
    </if>
    <if condition="@Lok1_Bf2 = %lcid%" state="st [Str3_E3_E2+]-[Bf3_E2-] = closed" alltrue="true">
      <then>
        <!-- FS öffnen aus Str3_E3_E2 -->
        <st id="[Str3_E3_E2+]-[Bf3_E2-]" state="open"/>
        <exit cmt="Script FS_Bf_E2, Bf2_E2: FS [Str3_E3_E2+]-[Bf3_E2-] geöffnet"/>
      </then>
    </if>
    <if state="st [Str1_E2+]-[Bf4_E2+] = closed" alltrue="true">
      <then>
        <!-- FS öffnen aus Str1_E2-->
        <st id="[Str1_E2+]-[Bf4_E2+]" state="open"/>
        <exit cmt="Script FS_Bf_E2, Bf2_E2: FS [Str1_E2+]-[Bf4_E2+] geöffnet"/>
      </then>
      <else>
        <exit cmt="Script FS_Bf_E2, Bf2_E2: FS nicht geschlossen oder falsche Lok"/>
      </else>
    </if>
  </then>
</if>
 
<!-- Wenn Zug in Bf5_E2 -->
<if condition="%callerid% # Bf5_E2">
  <then>
    <if condition="@Lok1_Bf2 = %lcid%" state="st [Str3_E3_E2+]-[Bf3_E2-] = closed" alltrue="true">
      <then>
        <!-- FS öffnen aus Str3_E3_E2 -->
        <st id="[Str3_E3_E2+]-[Bf3_E2-]" state="open"/>
        <exit cmt="Script FS_Bf_E2, Bf5_E2: FS [Str3_E3_E2+]-[Bf3_E2-] geöffnet"/>
      </then>
      <else>
        <exit cmt="Script FS_Bf_E2, Bf5_E2: FS nicht geschlossen oder falsche Lok"/>
      </else>
    </if>
  </then>
</if>
 
</xmlscript>

Aufruforte des Skripts:
-) Bf1_E2, ENTER, keine Bedingung,
-) Bf2_E2, ENTER, keine Bedingung,
-) Bf3_E2, ENTER, keine Bedingung,
-) Bf4_E2, ENTER, keine Bedingung,
-) Bf5_E2, ENTER, keine Bedingung,
-) Str3_E3_E2, RESERVED, keine Bedingung,
-) Str3_E1_E2, RESERVED, keine Bedingung,
-) Str1_E2, RESERVED, keine Bedingung.

Wie funktioniert das Skript?
Im Wesentlichen werden im Skript FS geschlossen und wieder geöffnet.
Mit den o. a. Beschreibungen zu den Skripts und der Doku im Skript selbst sollte es kein Problem sein, das Skript und seine Funktion zu interpretieren.

Steuerung der Ausfahrt aus dem NV-Bahnhof Ebene 3

Der NV-Bf. in Ebene 3 besteht aus 3 Gleisen: Bf5_E3, Bf6_E3, Bf7_E3. Die beiden Blöcke Bf6_E3 und Bf7_E3 bilden eine Ortschaft (siehe Einleitung). Sobald die Ortschaft voll besetzt ist, fährt ein Zug aus. Ich wollte erreichen, dass ein Zug aus der Ortschaft erst dann ausfährt, wenn auch das Gleis Bf5_E3 besetzt ist. Folgendes Skript steuert das:

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_Ausfahrt_NVBf_E3">
 
<!-- Wenn Zug in Bf5_E3, Ausfahrt öffnen -->
<if condition="%callerid% # Bf5_E3">
  <then>
    <if state="bk Bf6_E3 = occupied|bk Bf7_E3 = occupied" alltrue="true">
      <then>
        <sleep time="20000"/>
        <st id="[Bf6_E3-]-[Str1_E3_E2-]" state="open"/>
        <st id="[Bf7_E3-]-[Str1_E3_E2-]" state="open"/>
        <exit cmt="Ausfahrt geöffnet"/>
      </then>
      <else>
        <exit cmt="Bf6_E3 oder Bf7_E3 frei"/>
      </else>
    </if>
  </then>
</if>
 
<!-- Wenn Zug aus Bf6_E3 oder Bf7_E3, Ausfahrt schließen -->
<if condition="%callerid% # Bf6_E3|%callerid% # Bf7_E3" alltrue="false">
  <then>
    <st id="[Bf6_E3-]-[Str1_E3_E2-]" state="closed"/>
    <st id="[Bf7_E3-]-[Str1_E3_E2-]" state="closed"/>
    <exit cmt="Ausfahrt geschlossen"/>
  </then>
</if>
 
</xmlscript>

So wird das Skript aufgerufen:
-) Bf5_E3, OCCUPIED, keine Bedingung,
-) Bf6_E3, FREE, keine Bedingung,
-) Bf7_E3, FREE, keine Bedingung.

Wie funktioniert das Skript?
Kommt ein Zug in Bf5_E3 an und löst OCCUPIED aus, so startet das Skript, das erste IF wird durchlaufen und geprüft, ob die Blöcke Bf6_E3 und Bf7_E3 besetzt sind. Wenn ja, wartet RR 20 s und öffnet die beiden FS aus den Blöcken Bf6_E3 und Bf7_E3, dann wird das Skript verlassen.
Fährt ein Zug aus Bf6_E3 oder Bf7_E3 aus, werden die FS geschlossen.

Steuerung der Fahrten in das Tank-/Wartungs-/Warte-/Abstellgleis in Ebene 1

Züge aus den Gleisen SBf7_E1, SBf8_E1, SBf9_E1 fahren zufällig in das Tank-/Wartungs-/Warte-/Abstellgleis, verweilen dort eine Weile und kehren wieder in eines der genannten Gleise zurück. Ungesteuert würde die RR-Automatik solche Züge gelegentlich nochmals in das Tank-/Wartungs-/Warte-/Abstellgleis schicken. Diese Fahrten sind nicht gewollt, dieses Skript verhindert diese Zufälligkeiten:

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_FS_KBf_NV_E1">
 
<!-- Blockstatus ENTER -->
<!-- Wenn Zug aus Str3_E2_E1, dann Abbruch -->
<if state="sw W6_E1 = straight" condition="%frombkid% # Str3_E2_E1" alltrue="true">
  <then>
    <exit cmt="Zug aus Str3_E2_E1"/>
  </then>
</if>
<!-- Wenn Zug aus SBf10_E1, dann FS sperren -->
<if condition="%frombkid% # SBf10_E1">
  <then>
     <if state="sw W6_E1 = turnout|st [SBf10_E1-]-[SBf7_E1+] = locked" alltrue="true">
       <then>
	 <st id="[SBf7_E1+]-[SBf10_E1-]" state="closed"/>
       <exit/>
       </then>
     </if>
     <if state="sw W6_E1 = turnout|st [SBf10_E1-]-[SBf8_E1+] = locked" alltrue="true">
       <then>
         <st id="[SBf8_E1+]-[SBf10_E1-]" state="closed"/>
         <exit/>
       </then>
     </if>
     <if state="sw W6_E1 = turnout|st [SBf10_E1-]-[SBf9_E1+] = locked" alltrue="true">
       <then>
         <st id="[SBf9_E1+]-[SBf10_E1-]" state="closed"/>
	 <exit/>
       </then>
     </if>
  </then>
</if>
 
<!-- Blockstatus FREE -->
<if state="bk SBf7_E1 = free|bk SBf8_E1 = free|bk SBf9_E1 = free" alltrue="false">
  <then>
    <!-- Wenn Zug nach SBf10_E1, dann Abbruch -->
    <if state="sw W13_E1 = turnout">
      <then>
        <exit cmt="Zug nach SBf10_E1"/>
      </then>
    </if>
    <!-- Wenn Ausfahrt, FS öffnen -->
    <if state="bk SBf7_E1 = free|st [SBf7_E1+]-[SBf10_E1-] = closed" alltrue="true">
      <then>
        <st id="[SBf7_E1+]-[SBf10_E1-]" state="open"/>
	<exit/>
      </then>
    </if>
    <if state="bk SBf8_E1 = free|st [SBf8_E1+]-[SBf10_E1-] = closed" alltrue="true">
      <then>
        <st id="[SBf8_E1+]-[SBf10_E1-]" state="open"/>
	<exit/>
      </then>
    </if>
    <if state="bk SBf9_E1 = free|st [SBf9_E1+]-[SBf10_E1-] = closed" alltrue="true">
      <then>
        <st id="[SBf9_E1+]-[SBf10_E1-]" state="open"/>
	<exit/>
      </then>
    </if>
  </then>
</if>
 
<exit cmt="Kein Treffer"/>
 
</xmlscript>

So würde (Warum Konjunktiv? Erkläre ich gleich …) das Skript aufgerufen:
-) Bf7_E1, ENTER, keine Bedingung,
-) Bf8_E1, ENTER, keine Bedingung,
-) Bf9_E1, ENTER, keine Bedingung,
-) Bf7_E1, FREE, keine Bedingung,
-) Bf8_E1, FREE, keine Bedingung,
-) Bf9_E1, FREE, keine Bedingung,

Wie funktioniert das Skript?
Das Skript öffnet und schließt im Wesentlichen FS. Den Aufbau und die Funktionsweise kann der nun schon fortgeschrittene Skripter mühelos erkennen; Kommentare im Skript helfen dabei.
Zum Warum? Das Skript ist nicht notwendig. RR kann dieses Problem mit Bordmitteln lösen - Fahrstraßen-Bedingungen.

Verzögerung Abfahrt FV Ebene 3

Die FV-Züge fuhren mir aus Ebene 3 zu rasch ab, trotz hoch eingestellter Blockwartezeiten. Als Abhilfe habe ich ein kleines Skript entwickelt, das die Abfahrt der FV-Züge verzögert:

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_Abfahrt_FV_verzoegern_E3">
 
<!-- Aufruf aus Bf8_E3 oder Bf9_E3 bei OCCUPIED -->
<if state="bk Bf8_E3 = occupied|bk Bf9_E3 = occupied" alltrue="true">
  <then>
    <bk id="Str1_E3_E2" cmd="classdel" class="FV"/>
    <sleep time="60000"/>
    <bk id="Str1_E3_E2" cmd="classadd" class="FV"/>
    <exit cmt="Script Abfahrt_verzoegern_FV_E3: Abfahrt 1 min verzoegert"/>
  </then>
  <else>
    <exit cmt="Script Abfahrt_verzoegern_FV_E3: Bf8_E3 oder Bf9_E3 nicht besetzt"/>
  </else>
</if>
 
</xmlscript>

Der Aufruf des Skripts erfolgt aus
-) Bf8_E3, OCCUPIED, keine Bedingung,
-) Bf9_E3, OCCUPIED, keine Bedingung.

Die Funktion des Skripts sollte bereits selbsterklärend sein.

Steuerung des FV und GV

In Ebene 1 gibt es einen Bf. für FV und GV, detto in Ebene 3. Ließe man der RR-Automatik freien Lauf, starteten diese Züge ungeregelt, gesteuert nur durch die jeweiligen Ortschaftseinstellungen. Dies kann z. B. dazu führen, dass ein FV-Zug im Block Str3_E2_E1 zum Halten kommt, weil aus dem FV-Bf. in Ebene 1 (SBf3_E1, SBf4_E1, SBf5_E1) aus diversesten Gründen noch kein Zug ausgefahren ist. Das nachfolgende Skript regelt einen kontinuierlichen FV- und GV-Fluss:

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_Abfahrt_FV_GV_E1_E3">
 
<!-- <trace text="%lccargo%"/>

 
<!-- Aufruf aus Str1_E3_E2 bei ENTER -->
<if condition="%callerid% # Str1_E3_E2|%lccargo% # ice" alltrue="true">
  <then>
    <bk id="Str1_E1" cmd="classadd" class="FV"/>
    <exit cmt="Script Abfahrt_FV_GV_E1_E3: Klasse FV in Str1_E1 hinzugefügt"/>
  </then>
</if>
 
<!-- Aufruf aus Str1_E3_E2 bei ENTER -->
<if condition="%callerid% # Str1_E3_E2|%lccargo% # goods" alltrue="true">
  <then>
    <bk id="Str1_E3_E2" cmd="classdel" class="GV"/>
    <exit cmt="Script Abfahrt_FV_GV_E1_E3: Klasse GV in Str1_E3_E2 gelöscht"/>
  </then>
</if>
 
<!-- Aufruf aus Str1_E1 bei ENTER -->
<if condition="%callerid% # Str1_E1|%lccargo% # goods" alltrue="true">
  <then>
    <bk id="Str1_E3_E2" cmd="classadd" class="GV"/>
    <exit cmt="Script Abfahrt_FV_GV_E1_E3: Klasse GV in Str1_E3_E2 hinzugefügt"/>
  </then>
</if>
 
<!-- Aufruf aus Str1_E1 bei ENTER -->
<if condition="%callerid% # Str1_E1|%lccargo% # ice" alltrue="true">
  <then>
    <bk id="Str1_E1" cmd="classdel" class="FV"/>
    <exit cmt="Script Abfahrt_FV_GV_E1_E3: Klasse FV in Str1_E1 gelöscht"/>
  </then>
</if>
 
</xmlscript>

Der Aufruf des Skripts erfolgt aus
-) Str1_E3_E2, ENTER, keine Bedingung,
-) Str1_E1, ENTER, keine Bedingung.

Wie arbeitet das Skript?
Hier wird wieder mit Klassen gearbeitet. Fährt ein FV-Zug aus dem Bf. in Ebene 3 aus und in den Block Str1_E3_E2 ein (erstes IF), wird im Block Str1_E1 die Klasse “FV” gesetzt. Damit darf auch ein FV-Zug aus dem Bf. in Ebene 1 ausfahren. Ist dieser FV-Zug ausgefahren - durch Block Str1_E1 -, löscht er die Klasse “FV” wieder (viertes IF). Auch wenn sich der FV-Bf. in Ebene 1 wieder füllt, darf ein FV-Zug erst wieder ausfahren, wenn ein FV-Zug den FV-Bf. in Ebene 3 verlässt.
Analog wird mit GV-Zügen verfahren.

Fotos von der Anlage

Falls es von Interesse ist, hier gibt es Fotos von der Anlage. Übrigens: Die Anlage gibt es nicht mehr; ich baue über die Wintermonate immer wieder eine neue.



Personal Tools