Dynamische blokken in RocRail: verschil tussen versies
k |
k |
||
Regel 1: | Regel 1: | ||
− | |||
== RocRail Dynamische blokken == | == RocRail Dynamische blokken == | ||
In de overstap van het ene besturingsprogramma naar het andere, loop je aan tegen de inrichting van je baan die vaak door de jaren heen toegesneden is op de mogelijkheden en je kennis van het pakket. Stap je dan over, dan is er naast de gewone leercurve en zijn uitdagingen dus ook nog iets waar je tegenaan kan lopen omdat die desbetreffende inrichting van je baan niet zomaar zonder grote ingrepen te wijzigen is. Een daarvan is de implementatie van zgn. dynamische blokken. Dit artikel helpt je mogelijk om het geheel toch min of meer aan de praat te krijgen, zonder hak en breekwerk in je baan. | In de overstap van het ene besturingsprogramma naar het andere, loop je aan tegen de inrichting van je baan die vaak door de jaren heen toegesneden is op de mogelijkheden en je kennis van het pakket. Stap je dan over, dan is er naast de gewone leercurve en zijn uitdagingen dus ook nog iets waar je tegenaan kan lopen omdat die desbetreffende inrichting van je baan niet zomaar zonder grote ingrepen te wijzigen is. Een daarvan is de implementatie van zgn. dynamische blokken. Dit artikel helpt je mogelijk om het geheel toch min of meer aan de praat te krijgen, zonder hak en breekwerk in je baan. |
Huidige versie van 12 jul 2022 om 20:51
RocRail Dynamische blokken
In de overstap van het ene besturingsprogramma naar het andere, loop je aan tegen de inrichting van je baan die vaak door de jaren heen toegesneden is op de mogelijkheden en je kennis van het pakket. Stap je dan over, dan is er naast de gewone leercurve en zijn uitdagingen dus ook nog iets waar je tegenaan kan lopen omdat die desbetreffende inrichting van je baan niet zomaar zonder grote ingrepen te wijzigen is. Een daarvan is de implementatie van zgn. dynamische blokken. Dit artikel helpt je mogelijk om het geheel toch min of meer aan de praat te krijgen, zonder hak en breekwerk in je baan.
Voor wie is dit bedoeld
Dit stuk is vooral bedoeld voor hen die overstappen van Koploper naar Rocrail of dit overwegen en willen weten of een van de meest handige functies, die van de dynamische blokken, ook geïmplementeerd kan worden. Of natuurlijk voor een geïnteresseerde die zich verder wil verdiepen in Rocrail.
Overstap van Koploper naar RocRail
Dit geschreven artikel gaat over Koploper en RocRail en is zonder enig waardeoordeel. Het gaat dus niet om wat is goed of wat is beter, het gaat om de vertaling van de implementatie. En dit alles in het uiterste respect en waardering voor de makers van beide programma's.
Hoe werken dynamische blokken
Even in het kort, wat er veel uitgebreider in de handleiding van Koploper beschreven staat. Dynamische blokken zijn - kort gezegd - twee aaneengesloten blokken samen een fysieke lengte hebben, maar door de software dynamisch opgeknipt worden, zodat een lange en een korte trein die qua lengtes opgeteld, de fysieke gezamenlijke bloklengte niet overschrijden. Leg je een aantal van dit soort blokken naast elkaar, dan heb je een prachtig opstel gebied waar een behoorlijk ideale verdeling van langere en korte locomotieven automatisch plaatsvindt.
Hoe wordt dit fysieke geïmplementeerd
Een dynamisch blok (de set van 2 blokken) heeft een inkomstmelder in de eerste en een eindmelder in de laatste. Deze melders kunnen worden gedeeld. Op die manier kunnen de extra blokken gebruik maken van dezelfde bezetmelder. De oplossing is nog uit de tijd bedacht dat de terugmelders erg prijzig waren, dus was een 'verkoop' argument voor dynamische blokken. Maar de kracht zit hem niet in 'goedkoop' maar het dynamische van de lengtes. Wie er voor kiest om een gemeenschappelijke eindmelder voor meerdere dynamische blokken te hebben ziet dat de locomotief na het genereren van de melding door Koploper in zijn achteruit wordt gezet, totdat de melder weer vrij komt, zodat een naastliggend blok ook weer gebruik kan maken van deze melder. Dit is echter niet het geval in de voorgestelde oplossing, maar kan op een iets andere manier opgelost wordt (zoals die trouwens ook bij de meeste gebruikers in Koploper wordt gebruikt).
Hoe werkt het in RocRail
Wie in Rocrail of op het forum de zoekterm 'dynamische blokken' invoert, zal geen hit vinden met een verwijzing naar de implementatie. Rocrail werkt nou eenmaal anders, anders had het wel Koploper geheten. In Rocrail wordt gebruik gemaakt van zogeheten opstelblokken. Functioneel doet dat min of meer wat we willen: ruimte geven aan locomotieven die opgesteld moeten worden, het liefst zo optimaal mogelijk. Rocrail kent het principe van secties, waarbij iedere sectie een eigen bezetmelder heeft. Dus even met een makkelijk rekensommetje: Een opstelblok van 200 cm die bestaat uit 5 secties kent dan 6 melders: 1 als enter(binnenkomst) melder en 5 sectie melders. Rocrail bepaalt dan zelf aan de hand van de lengte van de loc hoeveel bezetmelders hij dan bezet houdt. Zo kan er een loc van 140 cm en een van 25 dus prima staan. En uiteraard: hoe meer secties, hoe minder snijverlies tussen de verschillende lengtes van de locomotieven. Wie zijn baan dus al op deze manier inricht of ingericht heeft, heeft een bijzonder goed en effectief mechanisme voor het behoorlijk optimaal opstellen van de locomotieven met verschillende lengte. Hier ligt hem dus ook de crux van dit stukje: wie een bestaande baan heeft en geen grootschalige uitbreiding met melders kan of wil doen, die kan hier wat inspiratie opdoen. Overigens kan Rocrail in een opstelblok met de hier genoemde 5 secties 5 locomotieven opstellen, mits die de sectielengte niet overschrijden. Dat is dan weer een mooie extra qua effectiviteit.
Het compromis
De oplossing lijkt bijna in zijn geheel op die van de dynamische blokken: twee blokken in een opstelblok van verschillende lengtes, zonder hak en breekwerk in de bestaande melderstructuur. Behalve... De eindmelder. In de Koplopervariant mag deze gemeenschappelijk zijn en rijdt de loc terug als deze bezet is, dat doet deze oplossing niet. Deze gebruikt de melder om te stoppen, verder niet. Dat betekent voor hen die 1 eindmelder hebben, toch een kleine aanpassing als ze meerdere blokken naast elkaar hebben.
De oplossing in grote lijnen
Overbodig te zeggen dat Rocrail een programma is en heel veel mogelijkheden heeft. Niet alleen om snel en eenvoudig aan de slag te gaan, maar ook om vrij diep onder water een aantal dingen te doen. In grote lijnen werkt de dynamische blok oplossing als volgt:
- maak een opstelblok aan met een gemeenschappelijke inmelder met naastliggende opstelblokken.
- maak per opstelblok 1 fysieke eindmelder aan.
- Er worden per opstelblok 10 niet-fysieke melders aangemaakt. Die zijn dus niet fysiek aanwezig noch bedraad, maar worden door Rocrail aangestuurd om iets te doen.
- Er worden een paar acties gedefinieerd en xml scriptjes opgestart als 1 van de genoemde fysieke melders een melding afgeeft. Dat kan zijn bij de overgang van 'bezet naar niet bezet' en 'niet bezet naar bezet'.
Met speciale acties is het mogelijk om bijvoorbeeld het opstelblok dicht te zetten. Op die manier voorkom je dat er meer dan twee locomotieven in kunnen rijden.
De implementatie
Tot nu toe droge kost, maar nu gaan we aan de slag met een proef baantje waar alles in zit en je naar hartenlust kan experimenteren. Of in real life of gewoon in simulatie mode. Probeer in de naamconventie altijd een beetje structuur te houden. Nog even kort op een rijtje die naamconventie:
- Mxx voor melder
- Sxx voor wissel
- Bxx voor blok
- OBxx voor opstelblok
- Bij de sectiemelders de toevoeging: Sxx
- Txx voor tekstveld
- De melder aan de plus kant van een blok krijgt de toevoeging p en de min kant de m.
Baanplan
In onderstaand baanplan is de testopzet weergegeven. Het behoeft nauwelijks toelichting: in blok B01 staat een loc die vertrekt richting de opstelblokken OB01 of OB02 en daar een plekje zoekt in de laatst beschikbare sectie. En als de tijd daar is, vertrekt uit deze sectie weer een loc naar blok B02 en herhaalt het geheel zich.
Instellingen
Even de standaard instellingen voor het opstelblok. Hier tab 'algemeen'. De fysiek beschikbare lengte is 240 centimeter en de ingangsmelder is - conform de naam conventie - MOB01p: M van Melder, OB van OpstelBlok, 01 het opstelbloknummer en de p die verwijst naar de plus indicatie.
Vervolgens wordt voor iedere sectie opgegeven welk nummer die heeft en welke bezetmelder er bij hoort. Als - zoals hier - de lengte van alle secties gelijk is, kan die lengte hier op 0 blijven.
En met 'Toevoegen' wordt dan de sectie toegevoegd en ontstaat na alle secties ingevoerd te hebben, onderstaande samenvatting bij 'Secties', net voordat we op 'Toevoegen' van sectie 11 drukken:
Doe dezelfde instellingen voor opstelblok OB02.
Check ook nog even of in de algemene instellingen van Rocrail de melders met de 'gewone' blokken zijn verbonden en plaats - indien nodig - onderstaand vinkje linksboven bij 'verbind melders met blokken' conform onderstaande afbeelding en herstart Rocrail daarna.
Vervolgens kan alvast de router gestart worden en het setje rijwegen worden gegenereerd:
In de trace kolom links mogen dan geen foutmeldingen staan. Indien dat zo is, weet je dat het eerste deel goed gegaan is.
Gemeenschappelijke enter melders
Rocrail kent standaard niet zoiets als een gemeenschappelijke enter melder. Sterker nog: als je 1 adres op twee verschillende melders koppelt, krijg je met de router met het genereren van de rijwegen een foutmelding. Maar er is een eenvoudig trucje voor, waarbij je nog steeds gebruik kan maken van een gemeenschappelijke enter melder. Dit idee werkt als volgt: Aan een melder kan je een actie koppelen als hij aan of uit gaat. En vervolgens kan je in die actie een bezetmelder in het relevante blok aan of uit zetten. Door nu ook de rijweg die gekozen is meteen mee uit te vragen, weet je ook voor welk blok de bezetmelder nou eigenlijk echt bedoeld is. In het baanplan zie je de melder die min of meer loshangt bij het wissel S01. Dat is de melder die fysiek gekoppeld is aan een terugmelder (een poort op de S88). Voor de entermelders in OB01 en OB02 ziet de code er als volgt uit:
spoor_on.xml
<xmlscript>
<if state="st [B01+]-[OB01+] = locked">
<then>
<fb id="MOB01p" cmd="on"/>
<exit/>
</then>
</if>
<if state="st [B01+]-[OB02+] = locked">
<then>
<fb id="MOB02p" cmd="on"/>
<exit/>
</then>
</if>
</xmlscript>
Even in wat woorden wat hierboven staat: er wordt uitgevraagd of de twee mogelijke routes tussen B01 en OB01 of OB02 gereserveerd zijn. Zo ja, dan wordt de bezetmelder met het <fb commando aangezet.
De UIT code voor de melder natuurlijk heel eenvoudig: zet altijd de de twee entermelders van OB01 en OB02 uit. Hier hoef je niks uit te vragen, dat maakt het lekker simpel. En een melder uitzetten die al uitstond is ook helemaal niet erg:
Spoor_off.xml:
<xmlscript>
<fb id="MOB01p" cmd="off"/>
<fb id="MOB02p" cmd="off"/>
</xmlscript>
We gaan nu twee acties maken, die deze scriptjes in gang gaan zetten.
Dat doen we door onderstaande in te vullen bij 'Acties' die we via 'Tabellen' in het hoofdmenu aankiezen:
Bij 'Definitie' vullen we dit aan:
En we maken conform bovenstaande ook weer een off aan.
Invoeren gebeurt bij 'Acties' bij de desbetreffende bezetmelder:
Hier zien we bij ID de twee hier beschikbare speciale acties. Voor het aangaan van de melder kiezen we de ON variant, zoals we voor de OFF variant de off kiezen. Dan ziet het er als volgt uit:
Daarmee is de gemeenschappelijke entermelder een feit!
acties
Aan zowel de Enter als aan de laatste sectiemelder worden acties gekoppeld. Het toevoegen is conform wat in het vorige hoofdstukje stond, hier kort de uitleg van de scripts. Er is maar 1 soort script, de parameter die meegegeven wordt (het bloknummer) wordt in het script samengevoegd en uitgevoerd. Zo houden we het overzichtelijk.
In onderstaande afbeelding de Entermelder van OB01. De In melder (de laatste melder S12) zie er net zo uit, net als ook voor OB02. De 'parameter' bepaalt wat er in het script gebeurt.
Tot slot worden er nog 2 x 2 acties gemaakt om een opstelblok in gebruik te stellen (als er ruimte is) of buiten gebruik te stellen (als er 2 locomotieven in staan)
Als je alles (goed) ingevuld hebt, dan heb je onderstaande acties staan:
XML
Voor de 2 melders van een opstelblok, zijn er 4 xml scripts, voor het aan en uitgaan van de melder. Voor alle scripts maak ik gebruik van een aantal variablen, die hier even worden toegelicht:
- Var1 is een telller die bijhoudt welke sectie we bekijken
- Var6 is een hulpstring om een variabele tekst samen te stellen
- Var7 is de parameter die meegegeven werd, in ons geval dus 1 of 2
- Var8 is de hulpstring om samen te stellen. De M staat voor Melder
- Var4 is de een spretty print, zodat er een voorloop 0 bij komt
- Var5 is ook een spretty print die er "OB01" of "OB02" van maakt
Algemeen In een 'While' lus wordt met een query gekeken of in de sectie van het desbetreffende opstelblok een trein staat. Daar wordt ook de Var3 met een spretty print opgemaakt op de desbetreffende bezetmelder, bijvoorbeeld 'MOB01S09'
DyBloEnterOff.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <xmlscript>
- <vr id="var1" value="0"/>
- <vr id="var6" text="OB"/>
- <vr id="var7" value="%param1%"/>
- <vr id="var8" text="MOB"/>
- <vr id="var9" text="S"/>
- <vr id="var4" format="%02d" text="#var7"/>
- <vr id="var5" format="%s%02d" text="@var6 #var7"/>
- <while condition="#var1 < 10" max="11">
- <query vr="var2" table="sblist" id="@var5" sub="section" subidx="#var1" get="lcid"/>
- <query vr="var2" table="sblist" id="@var5" sub="section" subidx="#var1" get="lcid"/>
- <vr id="var10" value="#var1 + 1"/>
- <vr id="var3" format="%s%02d%s%02d" text="@var8 #var7 @var9 #var10"/>
- <if condition="@var2 = (null)">
- <then>
- <fb id="@var3" cmd="off"/>
- <fb id="@var3" cmd="off"/>
- </then>
- <else>
- <fb id="@var3" cmd="on"/>
- <fb id="@var3" cmd="on"/>
- </else>
- <then>
- </if>
- <vr id="var1" value="#var1 + 1"/>
- </while>
- <vr id="var1" value="0"/>
- </xmlscript>
DyBloEnterOn.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <xmlscript>
- <vr id="var1" value="10"/>
- <vr id="var6" text="OB"/>
- <vr id="var7" value="%param1%"/>
- <vr id="var8" text="MOB"/>
- <vr id="var9" text="S"/>
- <vr id="var4" format="%02d" text="#var7"/>
- <vr id="var5" format="%s%02d" text="@var6 #var7"/>
- <while condition="#var1 > 0" max="11">
- <query vr="var2" table="sblist" id="@var5" sub="section" subidx="#var1" get="lcid"/>
- <if condition="@var2 = (null)">
- <then>
- <vr id="var1" value="0"/>
- <vr id="var1" value="0"/>
- </then>
- <else>
- <vr id="var3" format="%s%03d%s%02d" text="@var8 #var7 @var9 #var1"/>
- <fb id="@var3" cmd="on"/>
- <vr id="var3" format="%s%03d%s%02d" text="@var8 #var7 @var9 #var1"/>
- </else>
- <then>
- </if>
- <if condition="@var2 = (null)">
- <vr id="var1" value="#var1 - 1"/>
- <query vr="var2" table="sblist" id="@var5" sub="section" subidx="#var1" get="lcid"/>
- </while>
- <vr id="var1" value="10"/>
- </xmlscript>
DyBloInOff.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <xmlscript>
- <vr id="var1" value="9"/>
- <vr id="var6" text="OB"/>
- <vr id="var7" value="%param1%"/>
- <vr id="var8" text="MOB"/>
- <vr id="var9" text="S"/>
- <vr id="var4" format="%02d" text="#var7"/>
- <vr id="var5" format="%s%02d" text="@var6 #var7"/>
- <while condition="#var1 > -1" max="11">
- <query vr="var2" table="sblist" id="@var5" sub="section" subidx="#var1" get="lcid"/>
- <vr id="var10" value="#var1 + 1"/>
- <vr id="var3" format="%s%02d%s%02d" text="@var8 #var7 @var9 #var10"/>
- <query vr="var2" table="sblist" id="@var5" sub="section" subidx="#var1" get="lcid"/>
- <if condition="@var2 = (null)">
- <then>
- <fb id="@var3" cmd="off"/>
- <fb id="@var3" cmd="off"/>
- </then>
- <else>
- <fb id="@var3" cmd="on"/>
- <fb id="@var3" cmd="on"/>
- </else>
- <then>
- </if>
- <vr id="var1" value="#var1 - 1"/>
- <vr id="var1" value="#var1 - 1"/>
- </while>
- <vr id="var1" value="9"/>
- </xmlscript>
DyBloInOn.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <xmlscript>
- <vr id="var1" value="10"/>
- <vr id="var6" text="OB"/>
- <vr id="var7" value="%param1%"/>
- <vr id="var8" text="MOB"/>
- <vr id="var9" text="S"/>
- <vr id="var4" format="%02d" text="#var7"/>
- <vr id="var5" format="%s%02d" text="@var6 #var7"/>
- <while condition="#var1 > -1" max="11">
- <query vr="var2" table="sblist" id="@var5" sub="section" subidx="#var1" get="lcid"/>
- <vr id="var10" value="#var1 + 1"/>
- <vr id="var3" format="%s%02d%s%02d" text="@var8 #var7 @var9 #var10"/>
- <trace text="@var3"/>
- <if condition="@var2 = (null)">
- <then>
- <fb id="@var3" cmd="off"/>
- <fb id="@var3" cmd="off"/>
- </then>
- <else>
- <fb id="@var3" cmd="on"/>
- <fb id="@var3" cmd="on"/>
- </else>
- <then>
- </if>
- <query vr="var2" table="sblist" id="@var5" sub="section" subidx="#var1" get="lcid"/>
- <vr id="var1" value="#var1 - 1"/>
- </while>
- <vr id="var1" value="10"/>
- </xmlscript>
Verdere mogelijkheden
Rocrail biedt de mogelijkheden om ook afbeeldingen te tonen van de loc. Dat is op zich wel plezierig, zodat je meteen ziet wat ergens staat, zonder dat je alle nummers of locadressen steeds in je hoofd moet vertalen.
Bij gewone blokken zet je bij de Rocview instellen deze optie met een vinkje aan, voor de opstelblokken is iets meer werk nodig. Je maakt eerst tekstvelden aan en die geef je weer volgens de naam conventie een naam. In dit geval worden dit vier tekstvelden: TOB01S01, TOB01S11, TOB02S01 en TOB02S11. Dus Tekst OpstelBlok, Sectie.
Vervolgens mag je ook nog vier acties aanmaken voor de tekstvelden, zodat de afbeeldingen ook daadwerkelijk geplaatst worden.
Dit doe je voor alle vier de tekstvelden.
Vervolgens mag je nog bij de eigenschap van het opstelblok bij 'Acties' deze aanzetten voor sectie 1 en sectie 11.
Nu is alles gereed en zie je de afbeeldingen van de twee locomotieven in de opstelblokken.
In de relevante XML scriptjes worden bij het aan of uitzetten van de melder de overeenkomstige locomotieven erbij gezocht en wordt de afbeelding er van in het tekstveld opgevoerd. Zo zie je dus altijd welke locomotieven er in het dynamische blok staan.
De wijzigingen in de eerder genoemde xml zijn hieronder aangegeven met de toevoegingen in het blauw.
DyBloEnterOff.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <xmlscript>
- <vr id="var1" value="0"/>
- <vr id="var6" text="OB"/>
- <vr id="var7" value="%param1%"/>
- <vr id="var8" text="MOB"/>
- <vr id="var9" text="S"/>
- <vr id="var26" text="TOB"/>
- <vr id="var28" text="S01"/>
- <vr id="var4" format="%02d" text="#var7"/>
- <vr id="var5" format="%s%02d" text="@var6 #var7"/>
- <vr id="var25" format="%s%02d%s" text="@var26 #var7 @var28"/>
- <vr id="bFirst" value="0"/>
- <tx id="@var25" format=" "/>
- <while condition="#var1 < 10" max="11">
- <query vr="var2" table="sblist" id="@var5" sub="section" subidx="#var1" get="lcid"/>
- <vr id="var10" value="#var1 + 1"/>
- <vr id="var3" format="%s%02d%s%02d" text="@var8 #var7 @var9 #var10"/>
- <if condition="@var2 = (null)">
- <then>
- <fb id="@var3" cmd="off"/>
- <fb id="@var3" cmd="off"/>
- </then>
- <else>
- <fb id="@var3" cmd="on"/>
- <if condition="#bFirst = 0">
- <then>
- <query vr="var18" table="lclist" id="@var2" get="image"/>
- <tx id="@var25" format="@var18"/>
- <vr id="bFirst" value="1"/>
- <query vr="var18" table="lclist" id="@var2" get="image"/>
- </then>
- <fb id="@var3" cmd="on"/>
- </if>
- </else>
- <then>
- </if>
- <vr id="var1" value="#var1 + 1"/>
- <query vr="var2" table="sblist" id="@var5" sub="section" subidx="#var1" get="lcid"/>
- </while>
- <vr id="var1" value="0"/>
- </xmlscript>
DyBloInOn.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <xmlscript>
- <vr id="var1" value="10"/>
- <vr id="var6" text="OB"/>
- <vr id="var7" value="%param1%"/>
- <vr id="var8" text="MOB"/>
- <vr id="var9" text="S"/>
- <vr id="var26" text="TOB"/>
- <vr id="var28" text="S11"/>
- <vr id="var4" format="%02d" text="#var7"/>
- <vr id="var5" format="%s%02d" text="@var6 #var7"/>
- <vr id="var25" format="%s%02d%s" text="@var26 #var7 @var28"/>
- <vr id="bFirst" value="0"/>
- <tx id="@var25" format=" "/>
- <while condition="#var1 > -1" max="11">
- <query vr="var2" table="sblist" id="@var5" sub="section" subidx="#var1" get="lcid"/>
- <vr id="var10" value="#var1 + 1"/>
- <vr id="var3" format="%s%02d%s%02d" text="@var8 #var7 @var9 #var10"/>
- <trace text="@var3"/>
- <if condition="@var2 = (null)">
- <then>
- <fb id="@var3" cmd="off"/>
- <fb id="@var3" cmd="off"/>
- </then>
- <else>
- <fb id="@var3" cmd="on"/>
- <if condition="#bFirst = 0">
- <then>
- <query vr="var18" table="lclist" id="@var2" get="image"/>
- <tx id="@var25" format="@var18"/>
- <vr id="bFirst" value="1"/>
- <query vr="var18" table="lclist" id="@var2" get="image"/>
- </then>
- <then>
- </if>
- <fb id="@var3" cmd="on"/>
- </else>
- <then>
- </if>
- <query vr="var2" table="sblist" id="@var5" sub="section" subidx="#var1" get="lcid"/>
- <vr id="var1" value="#var1 - 1"/>
- </while>
- <vr id="var1" value="10"/>
- </xmlscript>