User Tools

Site Tools


cds:german:skripte_2017_18

Skripte der Anlage Winter 2017/18


Anhand meiner Anlage aus der Wintersaison 2017/18 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.
Weiters setze ich voraus, dass der p. t. Leser RR, seine Objekte und ihre Funktionalität kennt.
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

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

Anlagenplan


Der Plan kurz erklärt:
Links die Blöcke Bf_E3_Gl1 bis Bf_E3_Gl8, die Bestandteile eines Schattenbahnhofs für 2 Nahverkehrs- bzw. Güter-Nebenbahnzüge (Aufstell-Block), 3 Fernverkehrszüge und 4 Güterzüge sind. Halblinks 3 Blöcke im Kopfbahnhof für Nahverkehrszüge und Güter-Nebenbahn. In der Mitte der Abzweigbahnhof mit 7 Gleisen und einem Abstellgleis. Rechts ein weiterer Schattenbahnhof mit 3 Gleisen für Nahverkehrs- bzw. Güter-Nebenbahnzüge, 2 Gleisen für Fernverkehrszüge und 5 Gleisen für Güterzüge. Ein Gleis ist als Reserve für alle Typen von Zügen vorgesehen.

An Hand der Richtungspfeile ist zu erkennen, dass es ein sehr einfacher Gleisplan mit weitgehendem Richtungsbetrieb ist. Herzstück ist der Abzweigbahnhof in der Mitte, in dem sehr viel Betrieb herrscht.

Steuerung Aufstellblock Bf_E3_Gl1

Ich bin M* Dreileiter-Fahrer und benutze punktförmige Rückmelder. Somit kann es vorkommen, dass ein Fahrzeug (vorzugsweise lange Personen- und Güterwagen mit Drehgestellen oder Lok-Drehgestell mit Haftreifen) die IN-Melder im Aufstellblock (AB) nicht dauerhaft belegen. Was im normalen Betrieb kein Problem darstellt, ist im AB suboptimal. Der AB benötigt für das ordnungsgemäße Funktionieren die Belegung der IN-Melder. Steht ein Zug in einem Abschnitt und ist der IN-Melder nicht belegt, erfolgt kein Aufrücken → der AB ist blockiert.
Um diesem Problem entgegen zu wirken, habe ich virtuelle Rückmelder (RM) eingebaut, die wie folgt vom xmlScript gesteuert werden: Ein Zug fährt in den AB, löst ENTER und darauf den ersten IN-Melder "RM_Bf_E3_Gl1_i_1" aus. Beim Status "on" wird das xmlScript per Aktion aufgerufen. Ist das aufrufenden Objekt der RM "RM_Bf_E3_Gl1_i_1", sein Status "on" und der virtuelle RM "Virt_RM_Bf_E3_Gl1_i_1" off, wird der virtuelle RM "Virt_RM_Bf_E3_Gl1_i_1" auf "on" gesetzt (er leuchtet rot). Ab jetzt ist es unwesentlich, ob der reale RM "RM_Bf_E3_Gl1_i_1" belegt ist oder nicht (siehe Bild oben: der reale Melder ist weiß, der virtuelle ist rot). Das Skript wird verlassen ("exit" mit Kommentar).
Der Zug rückt auf.
Beim Auslösen des nächsten realen RMs "RM_Bf_E3_Gl1_i_2" (Status = "on") wird das xmlScript per Aktion aufgerufen und die zweite if-Bedingung ausgeführt (das aufrufende Objekt ist "RM_Bf_E3_Gl1_i_2", der Status des RM "RM_Bf_E3_Gl1_i_2" ist on, der virtuelle RM "Virt_RM_Bf_E3_Gl1_i_2" ist off). Der virtuelle RM "Virt_RM_Bf_E3_Gl1_i_2" wird auf "on" gesetzt, der virtuelle RM "Virt_RM_Bf_E3_Gl1_i_1" auf off. Ab jetzt ist es unwesentlich, ob der reale RM "RM_Bf_E3_Gl1_i_2" belegt ist oder nicht. Das Skript wird verlassen.
Der Zug ist nun vollständig im Ausfahrabschnitt, der erste Abschnitt ist frei.
Der Zug fährt aus dem AB aus.
Befährt der Zug nun den ersten RM "RM_Str1_E3_E2_e2i" nach der Bfs.ausfahrt, wird wieder beim Status "on" das xmlScript per Aktion aufgerufen. Es wird geprüft, ob das aufrufende Objekt der RM "RM_Str1_E3_E2_e2i", sein Status "on", der virtuelle RM "Virt_RM_Bf_E3_Gl1_i_2" "on" ist. Zusätzlich wird abgefragt, ob die Ausfahrweiche aus dem AB in Ablenkung steht, um das Skript nur dann auszuführen, wenn Züge aus dem AB ausgefahren sind. Bei allen anderen Ausfahrten aus dem Bf. würde diese Weiche gerade stehen und die if-Bedingung würde nicht vollständig zutreffen. Treffen alle Bedingungen zu, wird der virtuelle RM "Virt_RM_Bf_E3_Gl1_i_2" auf off gesetzt.
Der Zug ist nun vollständig ausgefahren, der zweite (Ausfahr-)Abschnitt ist frei.

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Virtuelle_RM_im_AB">
 
<if condition="%callerid% # RM_Bf_E3_Gl1_i_1" state="fb RM_Bf_E3_Gl1_i_1 = on|fb Virt_RM_Bf_E3_Gl1_i_1 = off" alltrue="true">
  <then>
    <fb id="Virt_RM_Bf_E3_Gl1_i_1" cmd="on"/>
    <exit cmt="Virt_RM_Bf_E3_Gl1_i_1 = on"/>
  </then>
</if>
 
<if condition="%callerid% # RM_Bf_E3_Gl1_i_2" state="fb RM_Bf_E3_Gl1_i_2 = on|fb Virt_RM_Bf_E3_Gl1_i_2 = off" alltrue="true">
  <then>
    <fb id="Virt_RM_Bf_E3_Gl1_i_2" cmd="on"/>
    <fb id="Virt_RM_Bf_E3_Gl1_i_1" cmd="off"/>
    <exit cmt="Virt_RM_Bf_E3_Gl1_i_2 = on, Virt_RM_Bf_E3_Gl1_i_1 = off"/>
  </then>
</if>
 
<if condition="%callerid% # RM_Str1_E3_E2_e2i" state="fb RM_Str1_E3_E2_e2i = on|fb Virt_RM_Bf_E3_Gl1_i_2 = on|sw W10_E3 = turnout" alltrue="true">
  <then>
    <fb id="Virt_RM_Bf_E3_Gl1_i_2" cmd="off"/>
    <exit cmt="Virt_RM_Bf_E3_Gl1_i_2 = off"/>
  </then>
</if>
 
</xmlscript>

Wichtig zu wissen ist, dass im AB die virtuellen Melder konfiguriert werden (nicht die realen!).

Alle Züge fahren nach Hause

Alle Züge fahren auf Knopfdruck (S4) nach Hause.

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_Alles_heim">
 
<!-- Aufruf durch Schalter S4, grün -->
<if state="co S4 = on">
  <then>
    <sw id="W19_E1" cmd="close"/>
    <sw id="W11_E1" cmd="close"/>
    <sw id="W7_E3" cmd="close"/>
    <st id="[KBf_E2_Gl1-]-[Str1_E2+]" state="closed"/>
    <st id="[KBf_E2_Gl2-]-[Str1_E2+]" state="closed"/>
    <st id="[KBf_E2_Gl3-]-[Str1_E2+]" state="closed"/>
    <sb id="Bf_E3_Gl1" exitstate="closed"/>
    <exit cmt="Script_Alles_heim: Weichen und FS geschlossen"/>
  </then>
</if>
 
<!-- Aufruf durch Schalter S4, rot -->
<if state="co S4 = off">
  <then>
    <sw id="W19_E1" cmd="open"/>
    <sw id="W11_E1" cmd="open"/>
    <sw id="W7_E3" cmd="open"/>
    <st id="[KBf_E2_Gl1-]-[Str1_E2+]" state="open"/>
    <st id="[KBf_E2_Gl2-]-[Str1_E2+]" state="open"/>
    <st id="[KBf_E2_Gl3-]-[Str1_E2+]" state="open"/>
    <exit cmt="Script_Alles_heim: Weichen und FS geoeffnet"/>
  </then>
</if>
 
</xmlscript>

Das xmlScript ist einfach und nahezu selbsterklärend. Im Wesentlichen werden die Weichen der Bfs.ausfahrten außer Betrieb gesetzt. Dort wo das nicht möglich ist, weil auch die Einfahrt gesperrt werden würde, wird mit Sperren der FS gearbeitet.
Funktionsweise: Klick auf S4, alle Züge fahren irgendwann in die Bfe. *_E1, *_E3 oder KBf_E2 und können nicht mehr ausfahren. Stehen alle Züge, bediene ich "Alle Loks stoppen", schalte S4 aus, schalte die Automatik und den Strom aus.

Steuerung Fernverkehr (FV)

Ich möchte die Steuerung des FV nicht ganz der Automatik überlassen. Ich sehe es gerne, wenn im Bf. E2 (Blöcke *_E2) nahezu zeitgleich von beiden Seiten die FV-Züge ankommen. Dies erreiche ich, indem ich die Ausfahrt eines FV-Zuges aus dem Bf. E3 erst erlaube, wenn ein FV-Zug aus dem Bf. E1 (Blöcke *_E1) ausgefahren ist. Das einfache xmlScript dazu sieht wie folgt aus:

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_Abfahrt_FV_E1_E3">
 
<!-- Aufruf aus Str1_E3_E2 bei ENTER und Zug = FV -->
<if condition="%callerid% # Str1_E3_E2|%lccargo% # ice" alltrue="true">
  <then>
    <bk id="Str1_E3_E2" cmd="classdel" class="FV"/>
    <exit cmt="Script Abfahrt_FV_E1_E3: Klasse FV in Str1_E3_E2 gelöscht"/>
  </then>
</if>
 
<!-- Aufruf aus Str1_E1 bei ENTER und Zug = FV -->
<if condition="%callerid% # Str1_E1|%lccargo% # ice" alltrue="true">
  <then>
    <bk id="Str1_E3_E2" cmd="classadd" class="FV"/>
    <exit cmt="Script Abfahrt_FV_E1_E3: Klasse FV in Str1_E3_E2 hinzugefügt"/>
  </then>
</if>
 
</xmlscript>

Das Skript ist unkompliziert, die aufrufenden Objekte mit den dazugehörigen Stati sind in den Kommentierungen angegeben. Gesteuert werden die FV-Fahrten durch Setzen und Löschen der Klasse "FV" im Block "Str1_E3_E2".
Achtung, Hier tut sich eine Falle auf! Wird im Block "Str1_E3_E2" unter Berechtigungen eine Klasse gesetzt (hier: "FV"), so können keine anderen Züge mehr aus dem Bf. E3 ausfahren, wenn sie andere Klassenbezeichnungen haben (siehe Klasse). Um diese Falle zu umgehen, gibt man im Block "Str1_E3_E2" unter Berechtigung einfach alle anderen Klassen kommagetrennt an.

Runden drehen

Zwischen den Blöcken "Str2-2_E2_E1" und "Str2-1_E2_E1" befindet sich eine lange Strecke. Um die Züge lange fahren zu sehen, sollen diese zweimal die lange Strecke befahren. Erst dann sollen sie in den Block "Str2-1_E2_E1" und weiter in den Bf. E1 fahren. Zu diesem Zweck habe ich mittels zweier Weichen eine Schleife realisiert. Die Weiche "W1_Str1_E2_E1" wird vom Skript gesteuert, die zweite Weiche wird ausschließlich stumpf befahren und kann eine auffahrbare Handweiche sein (M* Dreileiter sei Dank!). Der RM "RM_W1_Str1_E2_E1" liegt in der Schleife zwischen den beiden Weichen.
Das xmlScript dazu sieht wie folgt aus:

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_Runden_drehen">
 
<!-- Aufruf durch RM RM_W1_Str1_E2_E1 -->
<if condition="%callerid% # RM_W1_Str1_E2_E1">
  <then>
    <vr id="Var_Runden" value="#Var_Runden + 1"/>
    <if condition="#Var_Runden = 1">
      <then>
	<sw id="W1_Str1_E2_E1" cmd="straight"/>
    </then>
    </if>
  </then>
</if>
 
<!-- Aufruf durch ENTER Block Str1-2_E2_E1 -->
<if condition="%callerid% # Str1-2_E2_E1">
  <then>
    <vr id="Var_Runden" value="0"/>
    <sw id="W1_Str1_E2_E1" cmd="turnout"/>
  </then>
</if>
 
</xmlscript>

Jedes Befahren des RM "RM_W1_Str1_E2_E1" erhöht die Zählervariable "Var_Runden" um 1. Wenn "Var_Runden" gleich "1" ist (also 2 Runden gefahren wurden), wird die Weiche "W1_Str1_E2_E1" in Richtung Block "Str1-2_E2_E1" gestellt und die Strecke verlassen. Das Ereignis ENTER im Block "Str1-2_E2_E1" ruft den zweiten Teil des Skripts auf und setzt die Variable "Var_Runden" auf "0" zurück. Zudem wird die Weiche wieder Richtung Schleife gestellt. Der nächste Zug kann kommen und wieder seine Runden drehen.
Die aufrufenden Objekte mit den dazugehörigen Stati sind in den Kommentierungen angegeben.

Einfahrrichtung Güter-Nebenbahn (GNB) im Bahnhof E1

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_Einfahrrichtung_GNB_E1">
 
<!-- Aufruf aus Block Str1-2_E2_E1 bei OCCUPIED-->
<if condition="%callerid% # Str1-2_E2_E1">
  <then>
    <if condition="%lccargo% # light|%lccargo% # lightgoods" alltrue="false">
      <then>
        <if state="lc %lcid% = fwd">
          <then>
	    <st id="[Str2_E2_E1+]-[Bf_E1_Gl9+]" state="closed"/>
            <st id="[Str2_E2_E1+]-[Bf_E1_Gl10+]" state="closed"/>
	    <st id="[Str2_E2_E1+]-[Bf_E1_Gl11+]" state="closed"/>
            <exit cmt="Script_Einfahrrichtung_GNB_E1: GNB oder NB fährt in Bf_E1_Gl8"/>
	  </then>
	</if>
	<if state="lc %lcid% = rev">
	  <then>
            <if state="bk Bf_E1_Gl11 = free|bk Bf_E1_Gl10 = free|bk Bf_E1_Gl9 = free" alltrue="false">
              <then>
	        <st id="[Str2_E2_E1+]-[Bf_E1_Gl8+]" state="closed"/>
	        <exit cmt="Script_Einfahrrichtung_GNB_E1: GNB oder NB fährt in Bf_E1_Gl9/10/11"/>
	      </then>
	    </if>
	  </then>
	</if>
      </then>
    </if>
  </then>
</if>
 
<!-- Aufruf aus Block Str2_E2_E1 bei OCCUPIED-->
<if condition="%callerid% # Str2_E2_E1">
  <then>
    <if condition="%lccargo% # light|%lccargo% # lightgoods" alltrue="false">
      <then>
        <if state="lc %lcid% = fwd">
          <then>
            <st id="[Str2_E2_E1+]-[Bf_E1_Gl9+]" state="open"/>
	    <st id="[Str2_E2_E1+]-[Bf_E1_Gl10+]" state="open"/>
 	    <st id="[Str2_E2_E1+]-[Bf_E1_Gl11+]" state="open"/>
	  </then>
	</if>
	<st id="[Str2_E2_E1+]-[Bf_E1_Gl8+]" state="open"/>
	<exit cmt="Script_Einfahrrichtung_GNB_E1: FSen in Betrieb"/>
      </then>
    </if>
  </then>
</if>
 
<!-- Wenn Lokrichtung in Block Bf_E1_Gl8 = rev, dann FS nach Str1_E1 sperren -->
<!-- Aufruf aus Block Bf_E1_Gl8 bei ENTER-->
<if condition="%callerid% # Bf_E1_Gl8">
  <then>
    <if state="lc %lcid% = rev">
      <then>
        <st id="[Bf_E1_Gl8-]-[Str1_E1+]" state="closed"/>
        <exit cmt="Script_Einfahrrichtung_GNB_E1: FS nach Str1_E1 gesperrt"/>
      </then>
    </if>
  </then>
</if>
 
<!-- Wenn Lok aus Block Bf_E1_Gl8 ausfährt, FS nach Str1_E1 öffnen -->
<!-- Aufruf aus W11_E1 bei turnout -->
<if condition="%callerid% # W11_E1">
  <then>
    <st id="[Bf_E1_Gl8-]-[Str1_E1+]" state="open"/>
    <exit cmt="Script_Einfahrrichtung_GNB_E1: FS nach Str1_E1 geöffnet"/>
  </then>
</if>
 
</xmlscript>


Ausfahrt aus dem Kopfbahnhof E2 steuern

Der Kopfbf. KBf*_E2 ist über den Block Str1_E2 mit dem Bf. E2 verbunden. Fährt ein Zug aus KBf*_E2 aus, so wird bei Auslösen des ENTER-Melders im Block Str1_E2 eine FS in einen der Blöcke des Bfs. E2 eingestellt. Da der Zug eine Weile unterwegs ist, blockiert die gestellte FS andere Fahrten.
Um diese lange Blockade zu verringern, habe ich ein virtuelles Signal eingerichtet, das standardmäßig auf Halt steht. Bevor ein Zug aus KBf*_E2 ausfährt, reserviert dieser eine FS zum Block Str1_E2. Dieses Ereignis, kombiniert mit der Einfahrrichtung des Zuges in den Block Str1_E2, löst einen Timer aus. Nach Ablauf des Timers nach 10 s, wird das Signal auf grün (Fahrt) gestellt und die Rocrail-Automatik kann eine FS suchen und einstellen ("Freies Fahrtziel bis um IN-Melder suchen" muss in den Lokomotiv-Eigenschaften konfiguriert sein). Das Signal wird bei Einfahrt in einen Bfs.block E2 automatisch auf Halt gestellt.

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_Signal_Str1_E2">
 
<!-- Aufruf aus Block Str1_E2 bei ENTER und Zug aus KBf*_E2? -->
<if state="bk Str1_E2 = reserved|lc %lcid% = +" alltrue="true">
  <then>
    <!-- Warten, damit neues Fahrtziel spät gesucht wird -->
    <sleep time="10000"/>
    <!-- Signal Fahrt -->
    <sg id="S_Str1_E2" cmd="green"/>
    <exit cmt="Script_Signal_Str1_E2, Signal S_Str1_E2 auf Fahrt"/>
  </then>
</if>
 
</xmlscript>

Das xmlScript ist leicht nachzuvollziehen. Die aufrufenden Objekte mit den dazugehörigen Stati sind in den Kommentierungen angegeben.

Fahrten Nahverkehr (NV) und Güter-Nebenbahn (GNB) nach E1 steuern

Im Bf. E1 gibt es Platz für 4 Züge vom Typ NV und GNB; die Blöcke Bf_E1_Gl8, 9, 10, 11. Käme ein fünfter Zug dieser Typen an, müßte er vor dem Bf. warten und blockierte somit alle anderen Zugtypen. Das folgende xmlScript steuert die Anzahl der Fahrten der Zugtypen NV und GNB zum Bf. E1. Das Textfeld "NV/GNB:" zeigt die aktuelle Anzahl von Zügen dieser Zugtypen im Bf. und am Weg zum Bf. an

<?xml version="1.0" encoding="UTF-8"?>
<xmlscript desc="Script_NV_GNB_nach_E1">
 
<!-- Anzahl NV_GNB -->
<!-- vr id="Var_NV_GNB_E1" value="0"/-->
 
<!-- Ist Zug NV oder GNB -->
<if condition="%lccargo% # local|%lccargo% # lightgoods" alltrue="false">
  <then>
    <!-- Aufruf ENTER aus Str1_E2_E1 -->
    <if condition="%callerid% # Str1_E2_E1">
      <then>
        <vr id="Var_NV_GNB_E1" value="#Var_NV_GNB_E1 + 1"/>
	<tx id="T_Var_NV_GNB_E1" format="NV/GNB: #Var_NV_GNB_E1"/>
	<if condition="#Var_NV_GNB_E1 = 4">
	  <then>
	    <bk id="Str1_E2_E1" cmd="classdel" class="NV"/>
            <bk id="Str1_E2_E1" cmd="classdel" class="GNB"/>
	    <!-- <trace text="Script NV_GNB_nach_E1: Klassen NV und GNB gelöscht"/>-->
	    <exit cmt="Script NV_GNB_nach_E1: 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_GNB_E1" value="#Var_NV_GNB_E1 - 1"/>
	<tx id="T_Var_NV_GNB_E1" format="NV/GNB: #Var_NV_GNB_E1"/>
	<if condition="#Var_NV_GNB_E1 = 3">
	  <then>
            <bk id="Str1_E2_E1" cmd="classadd" class="NV"/>
	    <bk id="Str1_E2_E1" cmd="classadd" class="GNB"/>
	    <!-- <trace text="Script NV_GNB_nach_E1: Klassen NV und GNB hinzugefügt"/>-->
	    <exit cmt="Script NV_GNB_nach_E1: Klassen NV und GNB hinzugefügt"/>
	  </then>
	</if>
      </then>
    </if>
  </then>
  <else>
    <!-- <trace text="Script_NV_GNB_nach_E1: Kein NV oder kein GNB"/>-->
    <exit cmt="Script_NV_GNB_nach_E1: Kein NV oder kein GNB"/>
  </else>
</if>
 
</xmlscript>

Mit ein wenig xmlScript-Wissen ist das Skript leicht nachzuvollziehen. Die aufrufenden Objekte mit den dazugehörigen Stati sind in den Kommentierungen angegeben. Gesteuert werden die NV/GNB-Fahrten durch Setzen und Löschen der Klassen "NV" und "GNB" im Block "Str1_E2_E1".

Lebenszyklus der Anlage

Die Anlage gibt es ab Ostern 2018 nicht mehr; ich baue über die Wintermonate immer wieder eine neue.
02.04.2018: RIP

cds/german/skripte_2017_18.txt · Last modified: 2018/11/12 08:56 (external edit)