Annonce

Réduire
Aucune annonce.

Annonce

Réduire
Aucune annonce.

Exemple de circulation entre différents types de véhicules

Réduire
X
 
  • Filtre
  • Heure
  • Afficher
Tout nettoyer
nouveaux messages

  • Exemple de circulation entre différents types de véhicules

    Bonjour tout le monde. Un de nos utilisateurs (Messina, que je salue au passage) m'a envoyé un petit projet avec les éléments suivants :

    • Une gare avec 2 tramways qui circulent à tour de rôle sur une voie unique,
    • Une gare routière avec 2 bus qui circulent sur une route à double sens. Un bus jaune dans le sens des aiguilles d'une montre, un bus blanc dans le sens inverse des aiguilles d'une montre,
    • Des voitures qui circulent toujours sur la route principale.

    Dans le script initial reçu avec ce projet, les bus démarraient inopinément et percutaient les tramways ou les voitures. De plus, la fonction EEPMain() vérifiait 5 fois par secondes deux tableaux associatifs totalisant 51 segments de voies. Un rapide calcul donnait ceci : 51 x 5 x 60 = 15 300 vérifications à la minute, ce qui représentait une charge de travail supplémentaire pour EEP.

    Alors comment faire ? Nous allons voir que rien ne vaut la simplicité et un peu de logique pour réaliser ce travail. Ne vous fiez pas à la longueur du tutoriel car le script n'est pas très long. J'ai plutôt essayé d'apporter des réponses à des questions que vous pourriez légitimement vous poser.

    Avant de commencer, veuillez télécharger le projet en cliquant sur ce lien. Une fois le téléchargement terminé, décompressez le fichier archive. Ensuite, ouvrez EEP et charger le projet.

    Nous allons commencer par décrire brièvement le projet en image :

    Comme vous pouvez le constater, le réseau se divise en deux parties principales : la partie située à gauche (côté Ouest) et la partie à droite (côté Est).

    Pour le moment, ne vous préoccupez pas des info-bulles, nous allons y revenir plus tard. Vous remarquerez dans la partie supérieure, une bifurcation vers laquelle se situe la gare routière avec les arrêts de bus. La gare des tramways jouxte la gare routière (Pour une meilleure lisibilité, les gares ne sont pas représentées).

    Nous allons maintenant zoomer sur la partie Est dans la vue 2D :

    Les règles de circulation sont les suivantes :

    1. Les tramways sont prioritaires par rapport aux bus et aux voitures. Lorsqu'un tramway entre dans la gare, il donne l'ordre à l'autre tramway de démarrer dans le sens opposé et ainsi de suite.
    2. Les bus sont prioritaires par rapport aux voitures. Comme pour les tramways, lorsqu'un bus entre dans la gare routière, ordre est donné à l'autre bus de démarrer dans le sens opposé.
    3. Les voitures n'influent en rien le comportement des bus et tramways et restent toujours sur l'axe routier principal.

    Bien entendu, les mêmes règles de circulation s'appliquent pour la partie Ouest.

    L'ajout des véhicules dans le projet :

    Dans EEP, lors de l'ajout d'un matériel roulant, une fenêtre s'ouvre dans laquelle vous pouvez modifier le nom par défaut (voir l'image ci-après). L'idéal étant de donner des noms de véhicules explicites et simples. Pour les bus, j'ai choisi Bus_Jaune et Bus_Blanc. Après le trait de soulignement (chiffre 8 du clavier alphanumérique), vous pouvez écrire une dénomination précise comme la couleur par exemple ou encore une ville, un n° de ligne, etc. L'important est de bien commencer par Bus_ce-que-vous-voulez. Nous verrons par la suite comment extraire dans le script, la partie située à gauche du trait de soulignement.

    Pour les voitures et les tramways, vous pouvez laisser les noms par défaut car ils ne sont pas pertinents dans le cadre de notre tutoriel.

    Nous allons commencer par détailler les premières parties du script qui concerne :
    1. La déclaration des constantes,
    2. La déclaration des variables globales,
    3. L'enregistrement des 6 segments de voies et des 4 signaux.
    La déclaration des constantes :
    -- Efface le contenu de la fenêtre d'évènements
    clearlog()

    -- Constantes pour le statut des parcours (Début ou terminé)
    CONST_PARCOURS_DEBUT = 1
    CONST_PARCOURS_TERMINE = 10
    -- Constantes pour les signaux
    CONST_VOIE_LIBRE = 1
    CONST_ARRET = 2
    -- Constantes pour les aiguillages
    CONST_BRANCHE_PRINCIPALE = 1
    CONST_EMBRANCHEMENT = 2

    Ici, nous déclarons les constantes des parcours, des signaux et des aiguillages. En effet, il est plus parlant d'affecter des noms significatifs que des numéros. Pour les constantes des statuts, j'ai choisi arbitrairement les chiffres 1 et 10. Pour les constantes des signaux et des aiguillages, il faut respecter l'ordre d'affichage des axes tels qu'ils apparaissent dans la liste déroulante des éléments mobiles. Ainsi, lorsque nous aurons besoin de faire appel aux fonctions EEP, nous passerons en paramètre ces constantes en lieu et place des numéros.

    La déclaration des variables globales :
    -- Variables pour les mouvements des véhicules (Bus et Tramways)
    DEPART_Bus_Est = CONST_PARCOURS_TERMINE
    DEPART_Tram_Est = CONST_PARCOURS_TERMINE
    ARRIVEE_Tram_Est = CONST_PARCOURS_TERMINE
    ARRIVEE_Bus_Est = CONST_PARCOURS_TERMINE
    -- Partie Ouest = partie gauche du réseau
    DEPART_Bus_Ouest = CONST_PARCOURS_TERMINE
    DEPART_Tram_Ouest = CONST_PARCOURS_TERMINE
    ARRIVEE_Bus_Ouest = CONST_PARCOURS_TERMINE
    ARRIVEE_Tram_Ouest = CONST_PARCOURS_TERMINE

    Ici, nos 8 variables pour les parcours sont globales et exploitables dans toutes les fonctions du script. Elles sont définies par défaut sur CONST_PARCOURS_TERMINE. Il suffira ainsi de cliquer sur un des deux signaux dans la gare des tramways pour initialiser le processus de circulation.

    L'enregistrement des 4 segments de voies et des 4 signaux :
    -- ENREGISTREMENT DES 4 SEGMENTS DE VOIES --
    -- Segment devant le feu tricolore Entree bus côté Ouest
    EEPRegisterRoadTrack(30)
    -- Segment devant le feu tricolore Entree bus côté Est
    EEPRegisterRoadTrack(42)
    -- Segment devant le feu tricolore sortie bus côté Est
    EEPRegisterRoadTrack(66)
    -- Segment devant le feu tricolore sortie bus côté Ouest
    EEPRegisterRoadTrack(70)
    -- Enregistrement des signaux pour gérer les évènements dans les fonctions de rappel
    -- Signal feu tricolore côté Est dans la gare routière
    EEPRegisterSignal(4)
    -- Signal feu tricolore côté Ouest dans la gare routière
    EEPRegisterSignal(12)
    -- Signal du tramway côté Ouest dans la gare
    EEPRegisterSignal(7)
    -- Signal du tramway côté Est dans la gare
    EEPRegisterSignal(9)

    Nous devons enregistrer les segments à tester pour récupérer certaines informations lorsque les véhicules occuperont ces segments. Nous procédons également à l'enregistrement de 4 signaux pour exploiter les fonctions de rappels correspondantes. En effet, le fait d'intégrer le paramétrage adéquat des signaux et des aiguillages dans les fonctions de rappel, permettra de gérer également la circulation manuellement en cliquant directement sur les signaux concernés !

    Maintenant, désactivez la fonction EEPMain() car pour notre projet, nous n'avons pas besoin qu'elle s'exécute 5 fois par seconde.

    -- Désactiver la fonction EEPMain
    function EEPMain()
    return 0
    end

    Avant de nous intéresser aux points de contact, nous allons réfléchir et énumérer où, quand et comment les actions doivent être exécutées par le script (je vous rappelle que nous traitons uniquement le côté Est pour l'instant) :

    1. Nous savons qu'à partir du moment où notre tramway sort de la gare, les bus censés entrer dans ou sortir de la gare routière doivent attendre que celui-ci ait quitté la gare, les tramways étant prioritaires par rapport au bus,
    2. Nous devons vérifier une fois qu'un bus veut entrer dans la gare routière si un tramway entre ou sort de la gare et le cas échéant, commuter les signaux en conséquence,
    3. Lorsqu'un bus entre ou sort de la gare, nous devons arrêter la circulation des voitures,
    4. Bien entendu, les tramways ne peuvent pas circuler simultanément vu qu'il n'y a qu'une voie unique.

    Finalement, le point commun entre tous ces mouvements est l'entrée et la sortie des tramways et des bus. Il y a bien un début de parcours et une fin de parcours à un moment donné. Voilà pourquoi nous avons nos 2 constantes CONST_PARCOURS_DEBUT et CONST_PARCOURS_TERMINE qui seront affectées aux 4 binômes des variables globales DEPART_Bus_Est, ARRIVEE_Bus_Est, etc...

    Alors, où positionner tous ces points de contacts ? Rien de plus facile, il suffit de regarder attentivement l'image ci-dessous (ne pas hésiter à cliquer sur l'image pour l'agrandir) :

    Important : Dans l'image ci-dessus, remarquez bien dans quel sens de circulation sont activés les points de contacts pour les fonctions Lua associées.
    Les points de contacts véhicules :

    Pour commencer et par soucis de clarté, regroupons les fonctions classées par binômes :

    1. fncTramEntreeEst : cette fonction est appelée par le point de contact qui est posé sur la voie du tramway tout à droite de l'image,
    2. fncFinTramEntreeEst : cette fonction est appelée par le point de contact qui est posé sur la voie du tramway dans la gare.
    1. fncBusEntreeEst : cette fonction est appelée par le point de contact qui est posé sur l'axe routier principal tout à droite de l'image (devant la voiture rouge),
    2. fncFinBusEntreeEst : cette fonction est appelée par le point de contact qui est posé sur la voie routière dans la gare vers la fin de la courbe.
    1. fncDepartBusEst : cette fonction est appelée par le point de contact qui est posé sur la voie routière dans la gare (au dessus du signal n° 4),
    2. fncFinDepartBusEst : cette fonction est appelée par le point de contact qui est posé sur l'axe routier principal dans le sens de circulation, à droite.

    Vous remarquerez également un point de contact utilisé comme régulateur de vitesse fixée à 30 km/h uniquement pour les tramways. Ce point de contact réagit dans les deux sens de circulation. Ainsi, le tramway entrant voit sa vitesse réduite à 30 km/h pour entrer dans la gare alors que le tramway sortant, au début de son parcours, roulera au maximum à cette vitesse.

    Concernant le tramway sortant, le point de contact appelant la fonction fncFinTramSortieEst en profite également pour augmenter la vitesse du tramway à 60 km/h, vu que celui-ci se situe maintenant sur le tronçon principal.

    Les points de contacts des signaux :

    Les points de contacts rouges sont là pour commuter les signaux (Tramways et Bus) sur arrêt dès que le signal correspondant a été franchi. Cela nous simplifie la vie et nous évite d'écrire une fonction Lua spécifique pour réaliser ce travail. Bien-sûr, pour les tramways, et justement parce qu'il n'y a que des tramways circulant sur les rails, il est inutile de s'intéresser au type de véhicule. Mais qu'en est-il des bus qui partagent l'axe routier principal avec les voitures ?

    Il est bien évident que seuls les bus peuvent commuter les signaux vu que les voitures restent toujours sur l'axe principal. Alors comment faire ? Il suffit de regarder la fenêtre des propriétés du signal n° 13 pour obtenir la réponse :

    Dans l'encadré rouge, l'utilisation du filtre s'avère particulièrement pertinente dans notre cas. Nous pourrions obtenir la même chose à partir d'une fonction Lua spécifique à savoir, filtrer le nom du véhicule et commuter le signal sur Arrêt. Mais ici, notre point de contact exécute le travail à notre place. Nous n'allons pas nous en priver !

    Pour que le filtre soit opérationnel, il faut commencer par le signe # suivi des caractères que nous voulons capturer et ça tombe plutôt bien, car nous voulons que le contact réagisse au mot-clé Bus. Donc à chaque passage d'un véhicule sur le contact, celui-ci testera si le nom commence par Bus et ignorera tous les caractères situés à droite à partir du trait de soulignement. La casse des caractères n'a ici aucune importance.

    Si le nom du véhicule commence par Bus, alors le contact commutera le signal n° 13 sur la position Arrêt. Dans tous les autres cas, le contact sera pûrement et simplement ignoré et la position du signal restera inchangée.

    A partir de maintenant, nous allons commencer par étudier les fonctions une par une dans l'ordre du script.

    Le binôme fncTramEntreeEst - fncFinTramEntreeEst :

    Ces deux fonctions, travaillent en tandem, c'est-à-dire lorsque le tramway bleu (dans le sens droite-gauche) veut entrer dans la gare, il déclenche l'appel de la fonction fncTramEntreeEst par l'intermédiaire d'un point de contact pour véhicule. Tant que le tramway n'a pas franchi l'autre point de contact (appelle la fonction fncFinTramEntreeEst), les bus ne peuvent ni entrer, ni sortir de la gare routière et par conséquent, ne peuvent franchir le croisement route-rails du tramway.

    Détail de la fonction fncTramEntreeEst :
    -- Cette fonction est activée par le tramway jaune via un point de contact à l'entrée de la gare côté Est
    function fncTramEntreeEst()
    -- Positionne le parcours ARRIVEE_Tram_Est sur DEBUT
    ARRIVEE_Tram_Est = CONST_PARCOURS_DEBUT

    -- Si aucun bus ne quitte ou n'arrive dans la gare routière alors...
    if DEPART_Bus_Est == CONST_PARCOURS_TERMINE and ARRIVEE_Bus_Est == CONST_PARCOURS_TERMINE then
    -- Le tramway jaune peut rentrer dans la gare routière
    -- Commute le signal n° 10 du tramway sur voie Libre
    EEPSetSignal(10, CONST_VOIE_LIBRE, 1)
    -- Commute l'aiguillage n° 5 sur Branche Principale
    EEPSetSwitch(5, CONST_BRANCHE_PRINCIPALE)
    else
    -- ...sinon un bus quitte ou arrive dans la gare routière...
    -- ...donc, commute le signal n° 10 du tramway sur arrêt
    EEPSetSignal(10, CONST_ARRET, 1)
    end
    end -- Fin de la fonction fncTramEntreeEst
    1. Le tramway arrive du côté Est pour préparer son entrée dans la gare. On renseigne la variable ARRIVEE_Tram_Est avec la constante CONST_PARCOURS_DEBUT,
    2. La priorité est donnée aux tramways, néanmoins, nous devons tester si les bus ne sont pas déjà en mouvement pour sortir ou entrer dans la gare côté Est. Si tel était le cas, les deux variables DEPART_Bus_Est ou ARRIVEE_Bus_Est seraient égales à CONST_PARCOURS_DEBUT. Ici, dans le cas contraire, elles doivent être toutes les deux égales à CONST_PARCOURS_TERMINE. Remarquez le mot clé and dans la condition du test. Ce mot clé indique que les deux variables testées doivent retourner toutes les deux la valeur true (vraie) pour que le bloc qui suit immédiatement le test soit exécuté.
    3. Ainsi, si nos deux variables sont égales à CONST_PARCOURS_TERMINE, on commute le signal n° 10 sur Voie libre ainsi que l'aiguillage n° 5 sur Branche Principale,
    4. Par contre, si une ou les deux variables ne sont pas égales à CONST_PARCOURS_TERMINE, le programme passe au bloc suivant situé immédiatement après le mot clé else et le signal n° 10 est commuté sur Arrêt,
    5. La fonction est maintenant terminée.
    Détail de la fonction fncFinTramEntreeEst :
    -- Cette fonction est activée via un point de contact par le tramway jaune lorsque celui-ci rentre dans la gare côté est
    function fncFinTramEntreeEst()
    -- Positionne le parcours ARRIVEE_Tram_Est sur TERMINE
    ARRIVEE_Tram_Est = CONST_PARCOURS_TERMINE

    -- Si aucun bus ne quitte ou n'arrive dans la gare routière alors...
    if DEPART_Bus_Est == CONST_PARCOURS_TERMINE and ARRIVEE_Bus_Est == CONST_PARCOURS_TERMINE then
    -- Commute le signal n° 9 du tramway sur voie Libre
    EEPSetSignal(9, CONST_VOIE_LIBRE, 1)
    -- Les autres signaux sont commutés directement dans la fonction de rappel du signal n° 9
    end
    end -- Fin de la fonction fncFinTramEntreeEst
    1. Le tramway est maintenant entièrement entré dans la gare. On renseigne la variable ARRIVEE_Tram_Est avec la constante CONST_PARCOURS_TERMINE,
    2. La priorité est donnée aux tramways, néanmoins, nous devons tester si les bus ne sont pas déjà en mouvement pour sortir ou entrer dans la gare côté Est. Si tel était le cas, les deux variables DEPART_Bus_Est ou ARRIVEE_Bus_Est seraient égales à CONST_PARCOURS_DEBUT. Remarquez le mot clé and dans la condition du test. Ce mot clé indique que les deux variables testées doivent retourner toutes les deux la valeur true (vraie) pour que le bloc qui suit immédiatement soit exécuté.
    3. Ainsi, si nos deux variables sont égales à CONST_PARCOURS_TERMINE, on commute le signal n° 9 sur Voie libre. Dans le cas contraire, rien ne se passe et la fonction se termine.

    Il est temps maintenant de s'intéresser aux fonctions de rappel. A quoi elles servent et pourquoi. Ici, les deux conditions qui constituent le test retournent la valeur true (vraie), ce qui a pour effet de commuter le signal n° 9 sur Voie Libre. Rappelez-vous au début du script, nous avions enregistré 4 signaux dont le n° 9. En effet, EEP nous permet d'enregistrer grâce à la fonction EEPRegisterSignal, n'importe quel signal d'un projet. Il suffit juste d'indiquer le n° du signal correspondant entre parenthèses et le tour est joué.

    Or, lorsqu'un signal est enregistré, chaque changement de son état induit l'appel automatique à la fonction dite de rappel EEPOnSignal_9(hEtat). Vous l'aurez compris, le chiffre 9 correspond au n° du signal concerné. La variable hEtat entre parenthèse retourne l'état (la position) du signal à chaque fois que celui-ci est modifié.

    Pour reprendre le fil de notre fonction fncFinTramEntreeEst, le signal n° 9 a été commuté sur Voie libre. Donc à ce moment précis, la fonction de rappel EEPOnSignal_9(hEtat) a été exécutée. Voyons maintenant ce qu'elle contient :

    function EEPOnSignal_9(hEtat)

    if hEtat == CONST_VOIE_LIBRE then
    -- Le tramway bleu peut quitter la gare routière
    -- Positionne le parcours DEPART_Tram_Est sur DEBUT
    DEPART_Tram_Est = CONST_PARCOURS_DEBUT
    -- Commute l'aiguillage n° 5 sur Embranchement
    EEPSetSwitch(5, CONST_EMBRANCHEMENT)
    end
    end -- Fin de la fonction EEPOnSignal_9

    Ici, on teste dans un premier temps si le signal est commuté sur Voie Libre. Si c'est le cas alors on renseigne la variable DEPART_Tram_Est avec la constante CONST_PARCOURS_DEBUT et on commute l'aiguillage n° 5 sur embranchement. A ce stade, vous allez me demander, pourquoi ne pas écrire également ces lignes de code dans la fonction fncFinTramEntreeEst ? Et bien tout simplement parce que nous allons pouvoir exécuter directement du code Lua si on commute manuellement le signal dans EEP en cliquant sur celui-ci tout en maintenant la touche Shift enfoncée !

    Si le code de la fonction de rappel était restée dans la fonction fncFinTramEntreeEst, seul, le tramway bleu pouvait l'exécuter. Le fait de déplacer le code dans la fonction de rappel nous offre une souplesse d'utilisation et des possibilités d'exploitation accrues.

    Détail de la fonction fncFinTramSortieEst :
    -- Cette fonction est activée via un point de contact par le tramway bleu lorsque celui-ci a quitté la gare et a dépassé le croisement côté Est
    function fncFinTramSortieEst()

    -- Positionne le parcours DEPART_Tram_Est sur TERMINE
    DEPART_Tram_Est = CONST_PARCOURS_TERMINE

    -- Récupére les informations du segment 42 (ID voie 42 avec signal n° 13)
    Result, Occupe42, Name42 = EEPIsRoadTrackReserved(42, true)
    -- Récupére les informations du segment 66 (ID voie 66 avec signal n° 4)
    Result, Occupe66, Name66 = EEPIsRoadTrackReserved(66, true)
    -- Si un véhicule occupe le segment routier n° 42
    if Occupe42 == true then
    -- Extrait le nom du véhicule (variable Name42) présent sur le segment dans la variable strCategorieVehicule
    local strCategorieVehicule = string.sub(Name42, string.find(Name42, "%a+"))
    -- Si le nom du véhicule commence par Bus alors...
    if string.upper(strCategorieVehicule) == "BUS" then
    -- Positionne le parcours ARRIVEE_Bus_Est sur DEBUT
    ARRIVEE_Bus_Est = CONST_PARCOURS_DEBUT
    -- Commute le signal n° 11 (feu tricolore) sur arrêt
    EEPSetSignal(11, CONST_ARRET, 1)
    -- Commute l'aiguillage n° 17 sur Embranchement
    EEPSetSwitch(17, CONST_EMBRANCHEMENT)
    else
    -- ...Sinon on teste la condition si le bus jaune était entré juste avant le tramway jaune alors que
    -- ce dernier a déjà franchi le point de contact fncTramEntreeEst. Lorsque le bus jaune avait franchi le
    -- point de contact fncFinBusEntreeEst, le bus blanc ne pouvait pas démarrer car le tramway jaune entrait
    -- à son tour dans la gare.
    if Occupe66 == true then
    -- Commute le signal n° 4 sur voie libre
    EEPSetSignal(4, CONST_VOIE_LIBRE, 1)
    -- Les autres signaux sont commutés directement dans la fonction de rappel du signal n° 4
    end
    end
    -- Dans les 2 cas, commute le signal n° 13 (feu tricolore) sur voie Libre
    EEPSetSignal(13, CONST_VOIE_LIBRE, 1)

    else

    -- Idem que le test ci-dessus
    if Occupe66 == true then
    -- Commute le signal n° 4 sur voie libre
    EEPSetSignal(4, CONST_VOIE_LIBRE, 1)
    -- Les autres signaux sont commutés directement dans la fonction de rappel du signal n° 4
    end
    end

    end -- Fin de la fonction fncFinTramSortieEst

    Cette fonction est appelée (via un point de contact véhicule) lorsque le tramway bleu a rejoint le tronçon principal et comme déjà énoncé plus haut, la vitesse du tramway est fixée à 60 km/h. Nous allons maintenant découvrir de nouvelles fonctionnalités intéressantes !

    • Le tramway a dépassé le croisement côté Est et a rejoint le tronçon principal. On renseigne la variable DEPART_Tram_Est avec la constante CONST_PARCOURS_TERMINE,
    • Désormais, nous devons tester quel type de véhicule est arrêté devant le feu rouge (signal n° 13). En effet, le temps que notre tramway démarre et sorte de la gare, peut-être que notre bus jaune a pu se présenter devant la bifurcation pour entrer dans la gare, mais comme le signal n° 13 (feu tricolore), est positionné sur Arrêt (feu rouge), grâce à la fonction fncBusEntreeEst (à venir plus bas), nous devons maintenant laisser notre bus jaune entrer dans la gare routière.
    • Pour tester quel type de véhicule est arrêté devant le feu rouge, nous allons faire appel à la fonction EEP EEPIsRoadTrackReserved. Tout d'abord, pour que cette fonction retourne les valeurs souhaitées, il faut enregistrer l'ID du segment concerné. Ici dans notre cas, il s'agit du segment n°42 (celui du signal n° 13). Comment EEP enregistre t'il le segment ? Tout simplement en utilisant la fonction EEPRegisterRoadTrack(42) comme dans la section enregistrement des segments de voies et des signaux au début du script.

      Alors que fait exactement cette fonction EEPIsRoadTrackReserved(42, true) ? C'est simple, elle contient 2 arguments (entre les parenthèses) et retourne 3 valeurs qui seront stockées dans les 3 variables suivantes : Result, Occupe42, Name42.

      Détails : pour commencer, nous devons passer deux arguments qui sont, l'ID du segment concerné (ici, le n° 42) et le mot clé true. Pourquoi true ? pour récupérer dans la 3ème variable en retour Name42, le nom du véhicule occupant le segment. Si vous omettez ce 2ème argument, le nom du véhicule ne sera pas retourné. A ce stade, nous avons récupéré les valeurs retournées dans nos 3 variables alors regardons de plus près, quelles sont les informations contenues à l'intérieur de celles-ci :

      1. La valeur retournée dans la variable Result est égale à true si le segment existe sinon false dans le cas contraire. Il est évident qu'ici dans notre cas, le segment existe bel et bien. Ce qui explique pourquoi nous n'avons pas l'utilité de tester le résultat,
      2. La valeur retournée dans la variable Occupe42 va nous indiquer si le segment est occupé par un véhicule. Cette valeur est importante pour notre fonction, donc nous allons la tester sans plus tarder,
      3. La valeur retournée dans la variable Name42 va nous donner le nom du véhicule si celui-ci occupe le segment n°42. Dans le cas contraire, la valeur retournée est une chaine vide.
      4. La valeur retournée dans la variable Occupe66 va nous indiquer si le segment n° 66 situé dans la gare routière à la position du signal n° 4, est occupé par le bus blanc.
    • C'est parti ! nous testons la valeur de la variable Occupe42. Si la valeur est égale à true alors un véhicule occupe le segment n° 42, mais, nous avons besoin de connaitre quel type de véhicule se trouve sur ce segment. En effet, rappelez-vous, seuls les bus sont habilités à rentrer dans la gare, les voitures restant toujours sur l'axe routier principal,
    • Alors comment allons-nous faire pour récupérer le nom du véhicule stocké dans la variable Name42 ? Tout d'abord, voici à nouveau la ligne concernée : local strCategorieVehicule = string.sub(Name42, string.find(Name42, "%a+")). Ici plusieurs paramètres méritent quelques explications :
      1. Tout d'abord, on déclare une variable locale nommée strCategorieVehicule. Elle va nous servir tout simplement à stocker le nom du véhicule.
      2. Ensuite, on utilise la fonction Lua string.sub qui contient 2 arguments. Le premier est le nom de la variable à tester, ici il s'agit bien entendu de Name42. Ensuite, le 2ème argument contient une autre fonction Lua string.find qui va nous permettre de rechercher une chaine de caractères à partir du motif %a+ contenu entre guillemets. Euh... quel est cet intru ? continuons l'explication,
      3. La fonction string.sub retourne une sous-chaine contenue dans la variable Name42 correspondant au motif trouvé par la fonction Lua string.find. Cette dernière, recherche des caractères dans la variable Name42. Mais pas n'importe quels caractères ! Uniquement des lettres et seulement des lettres !
      4. Décomposition du motif : %a = n'importe quelle lettre et uniquement des lettres, le signe + demande à la fonction string.find de continuer la recherche tant que des lettres sont trouvées. Par contre, dès qu'un caractère comme le trait de soulignement est rencontré, la fonction arrête de chercher et retourne uniquement tout ce qu'elle a trouvé avant de rencontrer le trait de soulignement. Bref, tout ça pour dire ceci : tout ce qui ne correspond plus à des lettres est ignoré et la fonction arrête net sa recherche. Le résultat retourné est ensuite stocké dans la variable locale strCategorieVehicule.
      5. Juste pour information, toutes les variables déclarées avec le mot clé local sont... uniquement locales à la fonction. Ce qui veut dire que la variable ne sera pas exploitable dans une autre partie du script. Les variables locales sont moins gourmandes en ressources que les variables globales.

      Lorsque nous avons déposé les bus pour la première fois sur le réseau, EEP nous a demandé de les nommer. Ils s'appellent Bus_Jaune et Bus_Blanc. Maintenant, la réponse devrait vous paraitre évidente ! Tout ce qui était avant le trait de soulignement a été capturé, donc, si un bus occupait le segment n° 42 à l'arrêt au feu rouge, notre variable strCategorieVehicule contient (je vous laisse deviner !) le mot Bus !

      Maintenant, nous allons anticiper et éliminer un problème éventuel : imaginons que nous avons nommé notre modèle bUs_Jaune ou buS_Jaune ou encore bUS_Jaune, comme le test d'égalité est sensible à la casse des caractères, bUs ne sera jamais égal à Bus ou buS ! Donc, pour éviter tout dysfonctionnement, nous allons avant de lancer le test d'égalité, utiliser la fonction Lua string.upper(strCategorieVehicule) dans l'opérande de gauche qui va transformer notre chaine de caractères en majuscules indépendamment de la saisie ! Donc, il nous reste plus qu'à indiquer dans l'opérande de droite, la chaine BUS en majuscules et entre guillements pour tester à coup sûr qu'il s'agit bien du mot clé Bus !

      Ainsi, si strCategorieVehicule contient le mot clé Bus alors la condition if string.upper(strCategorieVehicule) == "BUS" then est vraie et l'execution continue immédialement au bloc d'instructions situé juste en dessous de la ligne et :

      1. Qui consiste à renseigner la variable ARRIVEE_Bus_Est avec la constante CONST_PARCOURS_DEBUT. En effet, le bus va entrer dans la gare routière,
      2. Commute le signal n° 11 (feu tricolore) sur Arrêt grâce à la fonction EEPSetSignal(11, CONST_ARRET, 1). En effet, les voitures circulant en sens inverse doivent s'arrêter au feu rouge pour laisser entrer le bus jaune dans la gare routière.
      3. Commute l'aiguillage n° 17 sur Embranchement grâce à la fonction EEPSetSwitch(17, CONST_EMBRANCHEMENT),

      Dans les 2 cas, bus ou pas, on commute le signal n° 13 (feu tricolore) sur Voie Libre grâce à la fonction EEPSetSignal(13, CONST_VOIE_LIBRE, 1).

      Si le mot clé stocké dans la variable strCategorieVehicule n'était pas égal à Bus alors la deuxième partie du test située après le mot clé else serait exécutée et nous allons maintenant faire preuve d'analyse et de logique !

      Nous devons considérer l'éventualité suivante : si le bus jaune franchi le point de contact fncBusEntreeEst quelques mètres avant le franchissement du point de contact fncTramEntreeEst par le tramway jaune, que se passe-il ? La fonction fncBusEntreeEst appelée en premier par le bus jaune affecte à la variable ARRIVEE_Bus_Est la valeur de la constante CONST_PARCOURS_DEBUT et commute en conséquence le signal n° 10 sur Arrêt.

      Il faut bien comprendre ici que notre bus jaune a ' volé ' la priorité du tramway jaune et donc celui-ci va entrer dans la gare routière en premier et va franchir ensuite le point de contact fncFinBusEntreeEst. Nous allons détailler cette fonction plus loin dans ce tutoriel mais retenez pour le moment que celle-ci est chargée de tester la variable ARRIVEE_Tram_Est. Dans ce cas précis, cette variable contient tout naturellement la valeur de la constante CONST_PARCOURS_DEBUT vu que notre tramway jaune a lui aussi franchi le point de contact fncTramEntreeEst avant d'être stoppé devant le signal n° 1.

      Par déduction, comme les tramways sont prioritaires sur les bus, la fonction fncFinBusEntreeEst va prioriser l'entrée du tramway en lieu et place du bus blanc comme dans le schéma de circulation habituel. Bien-sûr, dans le cas contraire, la fonction aurait validé le départ du bus blanc.

      Il incombe ainsi au tramway bleu une fois sorti de la gare, de vérifier si le bus blanc est arrêté devant le signal n° 4. Si la variable Occupe66 est égale à true (vrai) alors on commute le signal n° 4 sur Voie Libre (qui au passage va appeler la fonction de rappel du signal n° 4) et le bus blanc va démarrer.

      Maintenant, il nous reste à traiter le dernier cas ! En fait, il est strictement identique à la seconde partie du test ci-dessus. La seule différence (au moment où le tramway bleu franchi le point de contact lié à notre fonction fncFinTramSortieEst) réside dans le fait que le segment n° 42 précisement à ce moment là, est libre de toute occupation de véhicule.

    Arrivé à ce stade, nous avons atteint la fin de la fonction !

    Information : Avant de continuer, retenez bien ceci : nous avons 3 fonctions pour la gestion des tramways et 4 fonctions pour la gestion des bus. En effet, pour les tramways, la fonction fncFinTramEntreeEst gère l'arrivée du tramway jaune et le départ du tramway bleu. Pour les bus, l'arrivée et le départ sont séparés via deux fonctions distinctes. Pourquoi ? pour démontrer plusieurs méthodes possibles afin d'ajouter par exemple, de nouvelles fonctionnalités. Ici, on pourrait supposer (pour les bus), introduire des possibilités supplémentaires (comme l'affichage des destinations dans des panneaux d'information) entre l'arrivée et le départ d'un bus. Evidemment, cela induit des lignes de codes additionnelles et vouloir tout écrire dans une seule fonction nuirait à la lisibilité du code et son maintient dans le temps.

    Nous en avons fini avec les fonctions des tramways. Nous allons maintenant nous intéresser aux fonctions qui gèrent les mouvements des bus.

    Le binôme fncBusEntreeEst - fncFinBusEntreeEst :

    Ces deux fonctions, travaillent en tandem, c'est-à-dire lorsque le bus jaune (dans le sens droite-gauche) veut entrer dans la gare routière, il déclenche l'appel de la fonction fncBusEntreeEst par l'intermédiaire d'un point de contact pour véhicule. Tant que le bus n'a pas franchi l'autre point de contact (appelle la fonction fncFinBusEntreeEst), les tramways doivent attendre pour entrer ou sortir de la gare et par conséquent, ne peuvent franchir le croisement route-rails du tramway.

    Détail de la fonction fncBusEntreeEst :
    -- Cette fonction est activée via un point de contact par le bus jaune lorsque celui-ci veut entrer dans la gare routière côté Est
    function fncBusEntreeEst()

    -- Si aucun tram quitte ou arrive dans la gare alors...
    if ARRIVEE_Tram_Est == CONST_PARCOURS_TERMINE and DEPART_Tram_Est == CONST_PARCOURS_TERMINE then
    -- Positionne le parcours ARRIVEE_Bus_Est sur DEBUT
    ARRIVEE_Bus_Est = CONST_PARCOURS_DEBUT
    -- Commute le signal n° 11 (feu tricolore) sur arrêt
    EEPSetSignal(11, CONST_ARRET, 1)
    -- Commute l'aiguillage n° 17 sur Embranchement
    EEPSetSwitch(17, CONST_EMBRANCHEMENT)
    else
    -- ......sinon un tram quitte ou arrive dans la gare alors on commute le feu tricolore (signal n° 13) au rouge
    EEPSetSignal(13, CONST_ARRET, 1)
    end

    end -- Fin de la fonction fncTramEntreeEst
    1. La priorité étant donnée aux tramways, nous devons tester si ceux-ci ne sont pas déjà en mouvement pour sortir ou entrer dans la gare côté Est. Si tel était le cas, les deux variables DEPART_Tram_Est ou ARRIVEE_Tram_Est seraient égales à CONST_PARCOURS_DEBUT. Ici dans le cas contraire, elles doivent être toutes les deux égales à CONST_PARCOURS_TERMINE. Remarquez le mot clé and dans la condition du test. Ce mot clé indique que les deux variables testées doivent retourner toutes les deux la valeur true (vraie) pour que le bloc d'instructions qui suit immédiatement le test soit exécuté.
    2. Ainsi, si nos deux variables sont égales à CONST_PARCOURS_TERMINE, on renseigne la variable ARRIVEE_Bus_Est avec la constante CONST_PARCOURS_DEBUT,
    3. On commute le signal n° 11 sur Voie libre ainsi que l'aiguillage n° 17 sur Embranchement,
    4. Par contre, si une ou les deux variables ne sont pas égales à CONST_PARCOURS_TERMINE, le programme passe au bloc suivant situé immédiatement après le mot clé else et le signal n° 13 est commuté sur Arrêt (feu rouge),
    5. La fonction est maintenant terminée.
    Détail de la fonction fncFinBusEntreeEst :
    -- Cette fonction est activée via un point de contact par le bus jaune lorsque celui-ci vient juste de rentrer dans la gare routière côté Est
    function fncFinBusEntreeEst()

    -- Positionne le parcours ARRIVEE_Bus_Est sur TERMINE
    ARRIVEE_Bus_Est = CONST_PARCOURS_TERMINE

    -- Si le tramway jaune est en attente devant le signal n° 10 alors...
    if ARRIVEE_Tram_Est == CONST_PARCOURS_DEBUT then
    -- Commute les signaux 10 et 11 sur Voie Libre
    EEPSetSignal(10, CONST_VOIE_LIBRE, 1)
    EEPSetSignal(11, CONST_VOIE_LIBRE, 1)
    -- Commute l'aiguillage n° 5 sur Branche Principale
    EEPSetSwitch(5, CONST_BRANCHE_PRINCIPALE)
    else
    -- Sinon si pas de tramway en attente devant le signal n° 10 alors on commute l'aiguillage n° 17 sur Branche Principale et le signal n° 11 sur Voie Libre
    EEPSetSwitch(17, CONST_BRANCHE_PRINCIPALE)
    EEPSetSignal(11, CONST_VOIE_LIBRE, 1)
    end

    -- Dans les 2 cas, commute le signal n° 13 (feu tricolore) sur voie Libre
    EEPSetSignal(13, CONST_VOIE_LIBRE, 1)

    end -- Fin de la fonction fncFinBusEntreeEst
    1. Le bus est maintenant totalement entré dans la gare routière. On renseigne la variable ARRIVEE_Bus_Est avec la constante CONST_PARCOURS_TERMINE,
    2. La priorité étant donnée aux tramways, nous allons tester si le tramway jaune est en attente derrière le signal n° 10. Si tel est le cas, la variable ARRIVEE_Tram_Est est égale à la valeur de la constante CONST_PARCOURS_DEBUT car le tramway avait franchi le point de contact fncTramEntreeEst quelques secondes après le bus. Il nous reste à commuter les signaux 10 et 11 sur Voie Libre et l'aiguillage n° 5 sur Branche Principale.
    3. Sinon s'il n'y a pas de tramway en attente devant le signal n° 10 alors on commute l'aiguillage n° 17 sur Branche Principale et le signal n° 11 sur Voie Libre,
    4. Dans les 2 cas, bus ou pas, on commute le signal n° 13 (feu tricolore) sur Voie Libre grâce à la fonction EEPSetSignal(13, CONST_VOIE_LIBRE, 1),
    5. La fonction est maintenant terminée.

    Je vous avais annoncé plus haut avoir ajouté deux nouvelles fonctions pour le départ et l'arrivée des bus. Contrairement à la gestion des tramways dont l'arrivée du tramway jaune et le départ du tramway bleu sont gérés au sein d'une seule et unique fonction fncFinTramEntreeEst. Nous allons maintenant étudier le binôme fncDepartBusEst - fncFinDepartBusEst.

    Le binôme fncDepartBusEst - fncFinDepartBusEst :

    Ces deux fonctions travaillent en tandem. Le processus est enclenché lorsque le bus jaune (dans le sens droite-gauche) est entré dans la gare routière, après avoir franchi le 1er point de contact fncBusEntreeEst.

    Détail de la fonction fncDepartBusEst :
    -- Cette fonction est activée via un point de contact par le bus jaune lorsque celui-ci est entré dans la gare routière dans le sens droite-gauche
    function fncBusEntreeEst()

    -- Test si le bus blanc se trouve sur le segment de route devant le feu tricolore (signal n° 4)
    Result, Occupe66, Name66 = EEPIsRoadTrackReserved(66, true)
    -- Si le bus blanc est à l'arrêt et si aucun tram ne quitte ou n'arrive dans la gare alors...
    if Occupe66 == true and DEPART_Tram_Est == CONST_PARCOURS_TERMINE and ARRIVEE_Tram_Est == CONST_PARCOURS_TERMINE then
    -- Commute le signal n° 4 sur voie libre
    EEPSetSignal(4, CONST_VOIE_LIBRE, 1)
    -- Les autres signaux sont commutés directement dans la fonction de rappel du signal n° 4
    end

    end-- Fin de la fonction fncDepartBusEst
    1. La priorité étant donnée aux tramways, nous devons tester si ceux-ci ne sont pas déjà en mouvement pour sortir ou entrer dans la gare côté Est. Si tel était le cas, les deux variables DEPART_Tram_Est ou ARRIVEE_Tram_Est seraient égales à CONST_PARCOURS_DEBUT. Ici dans le cas contraire, elles doivent être toutes les deux égales à CONST_PARCOURS_TERMINE. Remarquez le mot clé and dans la condition du test. Ce mot clé indique que les deux variables testées doivent retourner toutes les deux la valeur true (vraie) pour que le bloc d'instructions qui suit immédiatement le test soit exécuté.
    2. Ainsi, si nos deux variables sont égales à CONST_PARCOURS_TERMINE, on commute le signal n° sur Voie Libre, ce qui aura pour effet d'appeler la fonction de rappel du signal n° 4 EEPOnSignal_4 et de commuter correctement les éléments concernés,
    3. La fonction est maintenant terminée.
    Détail de la fonction fncFinDepartBusEst :
    -- Cette fonction est activée via un point de contact par le bus blanc lorsque celui-ci vient de rentrer sur la route principale côté Est
    function fncFinDepartBusEst()

    -- Positionne le parcours DEPART_Bus_Est sur TERMINE
    DEPART_Bus_Est = CONST_PARCOURS_TERMINE

    -- Si le tramway jaune avait franchi le point de contact fncTramEntreeEst alors...
    if ARRIVEE_Tram_Est == CONST_PARCOURS_DEBUT then
    -- Commute les signaux 10 et 11 sur Voie Libre
    EEPSetSignal(10, CONST_VOIE_LIBRE, 1)
    EEPSetSignal(11, CONST_VOIE_LIBRE, 1)
    -- Commute l'aiguillage n° 5 sur Branche Principale
    EEPSetSwitch(5, CONST_BRANCHE_PRINCIPALE)
    else
    -- ... sinon on récupére les informations du segment n° 42
    Result, Occupe42, Name42 = EEPIsRoadTrackReserved(42, true)
    local strCategorieVehicule = string.sub(Name42, string.find(Name30, "%a+"))
    -- Si un véhicule occupe le segment routier n° 42 et s'il s'agit d'un bus alors...
    if Occupe42 == true and string.upper(strCategorieVehicule) == "BUS" then
    -- Positionne le parcours ARRIVEE_Bus_Est sur DEBUT
    ARRIVEE_Bus_Est = CONST_PARCOURS_DEBUT
    -- Commute le signal n° 11 (feu tricolore) sur arrêt
    EEPSetSignal(11, CONST_ARRET, 1)
    -- Commute l'aiguillage n° 17 sur Embranchement
    EEPSetSwitch(17, CONST_EMBRANCHEMENT)
    else
    -- Commute le signal n° 11 (feu tricolore) sur arrêt
    EEPSetSignal(11, CONST_VOIE_LIBRE, 1)
    end
    end

    end -- Fin de la fonction fncFinDepartBusEst

    Pour cette dernière fonction concernant le côté Est, j'ai modifié le code volontairement pour vous démontrer qu'à partir d'un problème à résoudre, plusieurs solutions sont possibles en fonction du cahier des charges imposé pour les règles de circulation.

    1. Le bus blanc est maintenant totalement sorti de la gare routière et a rejoint l'axe routier principal. On renseigne la variable ARRIVEE_Bus_Est avec la constante CONST_PARCOURS_TERMINE,
    2. La priorité étant donnée aux tramways, nous allons tester si le tramway jaune est en attente derrière le signal n° 10. Si tel est le cas, la variable ARRIVEE_Tram_Est est égale à la valeur de la constante CONST_PARCOURS_DEBUT car le tramway avait franchi le point de contact fncTramEntreeEst quelques secondes après le départ du bus. Il nous reste à commuter les signaux 10 et 11 sur Voie Libre et l'aiguillage n° 5 sur Branche Principale.
    3. Sinon, on teste si le segment n° 42 est occupé ET s'il s'agit d'un bus qui circule sur ce segment.
    4. Contrairement à la fonction fncFinTramSortieEst où le test s'effectuait en deux temps, ici on teste les deux arguments Occupe42 et string.upper(strCategorieVehicule) en même temps. Pourquoi ? tout simplement pour vous démontrer une autre variante pour ce test. Remarquez également la fonction Lua string.upper(strCategorieVehicule) utilisée dans la 2ème opérande après le mot clé and.

    5. Si le test retourne true (vraie) alors on renseigne la variable ARRIVEE_Bus_Est avec la constante CONST_PARCOURS_DEBUT.
    6. On commute le signal n° 11 (feu tricolore) sur Arrêt grâce à la fonction EEPSetSignal(11, CONST_ARRET, 1). En effet, les voitures circulant en sens inverse doivent s'arrêter au feu rouge pour laisser entrer le bus jaune dans la gare routière.
    7. On commute l'aiguillage n° 17 sur Embranchement grâce à la fonction EEPSetSwitch(17, CONST_EMBRANCHEMENT),
    8. Sinon, maintenant que le bus est parti, on commute le signal n° 11 (feu tricolore) sur Voie Libre pour que les voitures puissent redémarrer.
    9. La fonction est maintenant terminée.

    Si la question suivante vous a effleuré l'esprit : Pourquoi le script est-il conçu pour tester uniquement l'occupation des voies pour les bus et pas celles des tramways ? La réponse est simple : les tramways sont prioritaires avant tout, une fois que ceux-ci roulent sur les points de contacts fncTramEntreeEst et fncTramEntreeOuest, les variables ARRIVEE_Tram_Est et ARRIVEE_Tram_Ouest sont renseignées avec la constante CONST_PARCOURS_DEBUT. Donc, il suffit de tester les valeurs de ces variables sans attendre que les tramways occupent tel ou tel segment de rails pour savoir, s'ils se présentent à l'entrée ou à la sortie de la gare et déclencher une action. Pour les bus, la priorité est inférieure, voilà pourquoi nous n'avons pas besoin de renseigner une variable dans les fonctions d'entrée des bus. Seule, l'information pertinente qui nous intéresse est l'occupation éventuelle des segments 42, 30 et 66, 70.

    Bien-sûr, si nous avions utilisé des variables pour les mouvements des bus à l'entrée ou à la sortie de la gare routière, les tests seraient plus nombreux et nous n'aurions pas eu la possibilité de découvrir les fonctions EEP pour l'occupation des voies. En effet, ces fonctions sont régulièrement utilisées, il s'agit de EEPIsRailTrackReserved, EEPIsRoadTrackReserved, EEPIsTramTrackReserved et EEPIsAuxiliaryTrackReserved. Je vous rappelle que les segments concernés doivent être préalablement enregistrés. Je vous invite à consulter le manuel Lua pour EEP16 disponible au téléchargement sur le site pour plus d'informations.

    Dans le prochain tutoriel, nous aborderons également la phase d'optimisation du script. En effet, il y a des actions qui se répètent fréquemment. Celles-ci pourront être aisément regroupées au sein d'une même fonction.

    Pour conclure : Je vous laisse regarder la partie Ouest. Mais il y a quand même une différence ! Lorsque le bus jaune quitte la gare routière, il doit "couper" la voie de gauche de l'axe routier principal pour rejoindre la voie de droite. Cela impose une gestion de signaux supplémentaires mais rien de bien compliqué !

    J'espère que ce tutoriel vous apportera quelques éclaircissements pour gérer les signaux et les aiguillages dans EEP avec Lua. Pour le tutoriel suivant, je vous invite à réviser les tableaux associatifs et les fonctions aléatoires car nous allons grimper un peu dans la difficulté mais rassurez-vous, rien d'insurmontable ! Je vous dis à bientôt et n'hésitez pas à me contacter si vous avez d'autres idées ou pour me signaler une erreur. Merci à tous.

    Domi

    EEP16, 15, 14, 13, 11, MK, Home-Nos
Chargement...
X