Auteur Sujet: Modélisation logicielle d'un réseau - le système de Denis  (Lu 15626 fois)

DDEFF

  • Sr. Member
  • ****
  • Messages: 470
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Denis
« Réponse #60 le: septembre 14, 2018, 12:21:34 pm »
Voici un nouveau topo sur les itinéraires.

Petit aparté sur la TJS :

Comme je l'avais promis, j'ai essayé une TJS.
Au début, j'ai simplement changé la TJD Z9 en TJS et ça a marché du premier coup.
Évidemment, quelques possibilités d'itinéraires en moins, mais c'est tout à fait normal.
Et puis, j'ai remis la TJD en Z9 et changé Z15 pour une TJS.
Et là, comment dire, je ne retrouvais plus mes petits… :( :(

En fait, le problème ne venait pas de la TJS (ça faisait pareil avec une TJD), mais du fait que cet emplacement se combinait avec une raquette…
Déjà peu de réseaux ont une raquette, mais, en plus, que cette raquette ait comme élément fondamental une TJS/TJD est quasi introuvable… sauf ma future gare.



Sur le schéma (merci Jean-Luc  ;)), ça n'est pas flagrant : on ne voit pas de raquette.
Mais, si vous y réfléchissez, vous verrez que, quelle que soit la voie par laquelle vous sortez par la gauche, vous aurez parcouru une boucle de retournement en revenant par la gauche !!
Et comme vous ne pouvez pas sortir par la droite (c'est une gare terminus), je vais avoir ce problème de raquettes basées sur des TJD à grande échelle.

J'ai donc fait quelques ajustements et, maintenant, ça marche ! Ouf !
Merci Pierre d'avoir fait cette importante remarque.  ;)

Revenons aux itinéraires.

Les différentes typologies :

A la SNCF, on parlera de transit "rigide" pour dire que, une fois l'itinéraire créé, on ne touche plus aux aiguilles tant que le dernier wagon n'a pas quitté complètement l'itinéraire.
La plupart des réseaux miniatures fonctionnent comme ça parce que ça a le mérite d'être simple et efficace, en particulier quand les itinéraires sont courts.

Puis est venu le transit "souple" en 1934, mais pas encore en poste "tout relais".
En 1939, le premier PRA (Poste tout Relais à destruction Automatique) qui, comme son nom l'indique est géré entièrement par des relais.
C'est du transit "rigide", mais la nouveauté, c'est qu'on crée un itinéraire en appuyant sur un bouton.
C'est une grande avancée.
Et, mieux, on libère les aiguilles d'un seul coup : c'est la "destruction automatique".
Puis, en 1950, le premier PRS (Poste tout Relais à transit Souple).

Transit souple :

C'est l'aboutissement de la technologie à relais.
La nouveauté, c'est qu'on libère non pas l'itinéraire entier quand il a été entièrement parcouru, mais zone par zone, au fur et à mesure que le dernier wagon quitte une zone. La zone pouvant être un appareil de voie (AV), ou une zone sans appareil de voie (SAV).
On peut donc réutiliser cette zone immédiatement pour un autre itinéraire. La fluidité est maximale.

Mais, on n'a rien sans rien et la complexité est maximale :
Il faut obligatoirement une détection de présence sur chaque zone et plus on veut améliorer la fluidité, plus les zones doivent être petites et, donc, plus nombreuses.
D'où le fait que les PRS en train miniature sont quasi inexistants.
Lecteur de Loco Revue depuis 1974 (!!), j'ai recensé :
Le PRS à relais de Pierre Chenevez (1970-73) et celui des Frères Jesu LR 503, 504, 506 et 507 en 1988.
Depuis, plus rien.

C'est pourtant ce que j'ai choisi de développer (sans relais, bien sûr) et vous avez vu sur les précédentes vidéos que ça marche. Mais c'est du lourd !
Et c'est justifié pour une gare comme la mienne, avec deux doubles diagonales.

Pour être tout à fait exhaustif, ce sera un PRG (Poste tout Relais Géographique).
La différence fondamentale entre un PRS et un PRG, c'est qu'en PRS, on a un bouton par itinéraire, ce qui peut faire parfois beaucoup.
En PRG, on appuie sur le bouton de départ puis sur le bouton d'arrivée.
L'idée du PRG date du 19è siècle, mais le premier PRG est de 1971.

Gestion d'itinéraires :

J'ai trois niveaux d'affichage des itinéraires, chacun caractérisé par une couleur distincte :

1°) couleur SABLE :
On a donné le point A et le point B et le programme a trouvé tous les itinéraires possibles entre ces deux points.
Le premier itinéraire trouvé s'affiche couleur SABLE.
Par des clics GAUCHE successifs, on balaie tous les itinéraires trouvés, y compris un itinéraire vierge (et donc GRIS) qui sert à abandonner la recherche.

2°) couleur BLANCHE :
Par un clic DROIT, on choisit l'itinéraire souhaité qui passe en couleur BLANCHE.

3°) couleur VERTE/ROUGE :
Si on affecte un train à un itinéraire de couleur BLANCHE, il passe en couleur VERTE et est affiché.
Toutes les zones où est le train sont ROUGES.

Dans chaque couleur, il faut mémoriser les pavés et les zones concernées et, entre autres, la position des lames des AV.

Dans l'état actuel, pour un seul train, les différentes phases s'enchainent correctement.
On affiche les itinéraires SABLE, puis les BLANCS et enfin les VERTS.
Au fur et à mesure, les pavés affichent la bonne couleur, les AV la bonne position et, comme on affiche les itinéraires chaînés dans l'ordre où le train les parcourra, tout va bien.

On peut le voir pour deux trains simultanés sur la vidéo suivante (avec la TJS). Petit détail : pour la navette, j'ai choisi de ne pas passer par le même endroit pour l'aller et le retour. Mais on pourrait choisir le même parcours dans les deux sens.

Nota pour les vidéos : elles sont en HD (1920 x 1080) et en grand écran.
En particulier, surveiller le sens des trains (la petite flèche sur la loco).
Quand le train n'est pas ralenti, il est à fond. C'est moche et irréaliste, mais on voit bien si le train ralentit ou pas. Il y aura une accélération douce dans la version finale.



Mais vous remarquerez sans peine que j'ai bien fait attention qu'il n'y ait aucune zone commune pour les deux trains.
Parce qu'il me reste à faire s'imbriquer tous ces niveaux avec plusieurs trains…

Destruction manuelle d'itinéraire :


L'autre difficulté, c'est qu'à force de lancer plusieurs itinéraires chainés, on peut avoir envie de changer d'avis et de faire tout autre chose.
On peut aussi être amené, suite à un accident ou un wagon perdu, à contourner l'obstacle.
 Et il faut tout effacer pour reprogrammer autre chose, au pied levé.
Je comprends mieux, à postériori, pourquoi les aiguilleurs de la SNCF ont apprécié d'avoir des PRA, avec "destruction automatique"…

Et là, j'ai trouvé une méthode simple.

Tout d'abord, dès qu'un train est sur un itinéraire (il est donc VERT), cet itinéraire enregistre le numéro de ce train. Par exemple 3.
Et ce numéro de train ne démarre pas à 0, mais à 1. C'est très important.
Si on a des itinéraires chaînés, eux sont BLANCS et ont comme numéro de train -3.
Il y a donc un seul itinéraire (VERT) avec comme numéro de train 3 et un ou plusieurs itinéraires (BLANCS) avec -3.
C'est par ce simple système que je sais quel itinéraire est lié avec le suivant !

Et quand on veut changer d'avis, on sait immédiatement lesquels effacer.
Je n'utilise donc pas le 0 (évidemment) et quand on a dessiné un itinéraire BLANC, il a, par défaut, -1000 comme numéro de train.

Quand on a chaîné des itinéraires vides (BLANCS et -1000), ils sont chaînés par le début du suivant/fin du précédent.
Dès qu'on pose un train, on a un 3 et quelques -3 (par exemple) au lieu des -1000.

Cette partie est simple à effacer.
De même la partie VERTE de l'itinéraire où est le train.
Là où les choses se compliquent, c'est pour la partie occupée de l'itinéraire (ROUGE).

Parce que, au moment où on change d'avis, on peut très bien être à cheval sur plusieurs zones.

Mise en œuvre :

Au début, j'avais considéré comme une erreur le fait de choisir le même point (le même signal) pour A et B. Puis je me suis dit que ça déclencherait l'annulation.
Et ça pouvait même servir à changer le sens de déplacement d'un train sur place.

Si on choisit pour A et B le signal à l'avant du train, on efface tout. Et le train ne bouge pas. L'itinéraire est simplement raccourci.
On peut dès lors choisir pour lui un nouvel itinéraire qui va dans le même sens ou le sens opposé.

Voir les deux vidéos suivantes, qui montrent ces cas.





Si on choisit pour A et B le signal à l'arrière du train, on efface tout et on change le sens du train sur place. Ce qui, en fait correspond à inverser complètement l'itinéraire puisque c'est l'itinéraire qui donne le sens au train.
Puis on choisit pour lui un nouvel itinéraire qui va dans le même sens ou le sens opposé.

Voir les deux vidéos suivantes, qui montrent ces cas.





La nuance importante par rapport aux précédents cas, c'est qu'au lieu d'avoir une zone commune aux deux itinéraires (la dernière du précédent est la première du suivant), le train est à cheval sur trois zones (Z11, Z13 et Z14) et, suivant les cas, la loco est sur la première ou la dernière des 3 zones suivant le sens dans lequel on repart.
C'est "un peu plus complexe" que premier/dernier pour construire le nouvel itinéraire…

Récapitulatif des possibilités d'erreurs/annulations d'itinéraires gérées :

1°) Vous avez cliqué sur la mauvaise origine. Ce n'est pas la peine de continuer.
Vous recliquez sur le bouton recherche d'itinéraires du menu.

2°) Vous avez cliqué sur la bonne origine et sur la mauvaise extrémité.
Là, on est en itinéraires SABLE.
Vous cliquez GAUCHE pour faire défiler tous les itinéraires trouvés jusqu'à atteindre un itinéraire vierge (GRIS). Vous cliquez DROIT pour le valider, ce qui efface tout.

3°) Vous avez validé et vous êtes en itinéraires BLANCS. Mais vous avez choisi le mauvais.
Vous cliquez sur le bouton de recherche du menu.
Vous cliquez GAUCHE sur le point origine.
Comme deux itinéraires ne peuvent avoir la même origine, ça efface l'itinéraire.

4°) Vous avez positionné votre train et, même, il roule.  Votre itinéraire est VERT.
Et vous voulez tout recommencer.
Vous arrêtez le train et vous choisissez A et B sur le même signal (origine ou extrémité) de la zone en ROUGE.

Ce qui me plait particulièrement, c'est qu'il n'y a, pour tout ça qu'un seul et unique bouton (recherche d'itinéraires) et qu'on peut l'appliquer à n'importe quel signal du réseau. C'est quand même très souple.








DDEFF

  • Sr. Member
  • ****
  • Messages: 470
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Denis
« Réponse #61 le: octobre 31, 2018, 04:31:05 pm »
J'ai suspendu mon activité informatique jusqu'à fin septembre pour diverses autres occupations.
Depuis début octobre, je m'y suis replongé et … ça marche !!

Je fais maintenant fonctionner plusieurs trains ensemble en gérant des itinéraires avec des incompatibilités, les feux, etc…

Avant de continuer, je fais un petit aparté sur la question de Marc-Henri sur le fil de Jean-Luc (18/09/2018) concernant le fait de simuler le déplacement des trains sur le TCO.
Je souscris complètement aux réponses qui lui ont été faites par Pierre et Jean-Luc.

Le présent post vise à détailler les problèmes (nombreux) qui se posent.

Il n'est pas du tout évident de faire se déplacer des trains sur un TCO, au-delà des grands principes qui sont, eux, relativement simples. Le Diable se niche dans les détails.

Pour l'instant, je me limite aux Grandes Lignes et je ne traite pas les zones de manœuvre.
C'est en effet un autre monde, avec moins de zones, moins de signaux et une vitesse limitée.
Bien sûr, je traiterai le sujet. Mais plus tard.

Le modéliste :

Dire que le modéliste est à la fois conducteur et aiguilleur, c'est enfoncer une porte ouverte.
Poser un train sur le réseau, mettre le curseur à fond et bouger les aiguilles au gré de l'inspiration, on l'a tous fait. C'est naturel.

Mais je voudrais suivre un cheminement plus structuré en rentrant un peu plus dans chaque métier.

1°) Quand le conducteur prend "son" train en charge, il a son bulletin de freinage (ex bulletin de composition) qui détaille les caractéristiques du train.
Et, évidemment, il a son itinéraire (les gares traversées et la destination).

2°) L'aiguilleur, lui, a déjà préparé les itinéraires de sa zone.
Dans ce post, je ne traiterai que des itinéraires manuels, ceux qu'on construit en cas de dérangement (ex : un arbre tombé sur la voie et qu'il faut éviter).
C'est le bouton "choix d'itinéraire" du menu.

En effet, une fois qu'on sait traiter ces cas, on pourra alors gérer des itinéraires en automatisant certaines tâches.
Dans la réalité, quand l'aiguilleur saisit les origines et extrémités de l'itinéraire (A et B), le programme ne propose qu'un seul itinéraire (le meilleur parmi tous ceux possibles, tenant compte de certains paramètres).
Ce sera le bouton "meilleur itinéraire" du menu. On l'étudiera dans un autre post.

Les itinéraires manuels ont une autre utilité : la programmation d'un itinéraire précis, pas forcément le meilleur, mais celui qu'on veut. C'est particulièrement utile entre deux gares.

Exemple : je veux absolument passer par la voie de parade, même si, actuellement, elle est occupée.
Il y aurait bien un autre itinéraire, libre en plus, qui me permettrait aussi d'aller à destination, mais je veux passer par la voie de parade. Le recours aux itinéraires manuels est alors indispensable.

Les différents types d'itinéraires :

Jusque là, j'avais considéré et géré les itinéraires de la même façon (il faut bien se lancer…).
Mais il faut aller plus loin. Un itinéraire n'est pas seulement une liste de pavés orientés et de positions des lames des appareils de voie.

TCO et aiguilles :

Pour pouvoir gérer les trains de manière optimale, il faut en finir avec l'idée que le TCO reflète à tout moment la position réelle des aiguilles sur le réseau. Le mot important, là, c'est "à tout moment".

Il y aura donc, pour chaque pavé, deux variables :
"lame" qui reflète vraiment la position des aiguilles sur le terrain
"lame_tempo" qui affiche au TCO une position d'aiguille qui n'est pas celle du réseau ("tempo" est assez clair : ce sera temporaire).

TCO et occupation :

Plus subtilement, il y aura pour chaque pavé deux niveaux d'occupation :
"occupation" qui correspond à l'occupation réelle d'un véhicule sur le réseau.
"réserve" qui correspond au fait que le pavé, bien que physiquement non occupé, a déjà un numéro de train. Il est donc réservé par un train.
De cette façon, un pavé réservé ne pourra plus servir dans un autre itinéraire, tant qu'il restera réservé. C'est encore plus vrai s'il est vraiment occupé.

C'est particulièrement utile pour une traversée, une TJS ou une TJD.

Deux grands types d'itinéraires :

J'ai deux listes d'itinéraires (des ArrayList, c'est génial) :

La liste "tous_iti_tempo" qui correspondent aux itinéraires trouvés par le programme, suite à la recherche de tous les itinéraires entre A et B.
Ils sont affichés successivement, au dessus de tous les autres, de couleur SABLE.
Ils ne tiennent pas compte des occupations, des réservations et utilisent la position "lame_tempo".
Pendant l'affichage de ces itinéraires, les autres restent affichés (mais en dessous), les trains roulent normalement en suivant les vraies positions des lames d'aiguille.
Ces itinéraires sont indispensables aux aiguilleurs pour bien choisir celui qu'il veut sélectionner.
Avec le bouton "meilleur itinéraire", ils ne seront pas affichés puisqu'il n'y a qu'un itinéraire affiché. Et donc, pas de choix.

La liste "tous_iti" qui correspond aux autres itinéraires. Là encore, deux possibilités :

Les itinéraires réservés, affichés en BLANC.
Les itinéraires occupés, affichés en VERT (et en ROUGE pour les zones réellement occupées).

Itinéraires et points :

Les points servent "d'étapes" pour faire avancer les trains.
Un véhicule est dessiné à la verticale d'un point puis à la verticale d'un autre point un peu plus loin quand il avance.
Il est donc inutile de calculer les points pour les itinéraires SABLE et BLANC. On gagne ainsi un temps d'exécution précieux.
Et on peut même aller encore plus loin :
Quand un train arrive sur un itinéraire BLANC, il faut calculer les points pour qu'il puisse avancer. Mais si, parce que le train ne peut pas aller jusqu'au bout de l'itinéraire (ex : un autre itinéraire incompatible est déjà présent sur la fin de l'itinéraire ou coupe l'itinéraire), on ne calculera les points que jusqu'au pavé réservé ou occupé.

Il s'ensuit qu'un même itinéraire peut être VERT au début puis BLANC sur la fin.
Et, pour être tout  fait précis, forcément ROUGE au tout début puisque c'est là qu'est le train.

Autre façon de voir les choses : on n'a calculé les points que dans les parties VERT/ROUGE des itinéraires.

Remarque connexe : quand on affiche les itinéraires SABLE au dessus des autres, il faut mémoriser les couleurs de ces pavés pour pouvoir effacer ces itinéraires temporaires (quand on les fait défiler un par un) et retrouver la couleur précédente de chaque pavé.
Avec une difficulté supplémentaire puisque les trains bougent…

Effacement des pavés lors des mouvements de trains :

Parce que je suis en PRS, il faut effacer chaque zone au fur et à mesure du déplacement du train.
Là encore, on a le problème d'afficher la bonne couleur lors de l'effacement.
Voici des explications détaillées de la situation la plus simple avec deux trains, l'un bloquant l'autre, puis le débloquant.



Je choisis sur le réseau de cliquer gauche sur les points cerclés.
Le premier itinéraire utilisera les cercles jaunes et le deuxième les cercles bleus.
Pour le premier itinéraire, je clique d'abord dans le cercle jaune en haut à gauche, puis dans le cercle jaune au milieu.
A chaque fois qu'on clique, le feu correspondant devient NOIR, masquant temporairement le vrai signal.
Pour le deuxième itinéraire, je cliquerai gauche d'abord dans le cercle bleu du milieu, puis dans le cercle bleu en haut.

Je choisis l'itinéraire du premier train.
Les images sont petites, parce que l'important, c'est qu'on voie qu'entre les deux points choisis il y avait 4 itinéraires possibles.
Les itinéraires sont de couleur SABLE et, quand on change de choix (clic gauche) on retrouve bien la couleur GRIS précédente.
Première image : on vient de choisir A et B. Affichage du premier itinéraire trouvé.
Deuxième image : premier clic gauche. On efface le premier et on affiche le deuxième.
Troisième image : deuxième clic gauche. On efface le deuxième et on affiche le troisième.
Quatrième image : troisième clic gauche. On efface le troisième et on affiche le quatrième.
Quatrième clic gauche : plus aucun itinéraire affiché. On revient à la toute première image (en grand).

A noter : si, à ce moment, on clique DROIT :
Remise à zéro et affichage "aucun itinéraire sélectionné").

Cinquième clic gauche : retour à la première petite image.


 
Je choisi le premier itinéraire par un clic droit. Il devient BLANC.
Je pose le train numéro 3 dessus, il devient VERT. Et ROUGE au début à cause de la présence du train.



Vous retrouvez donc le premier itinéraire VERT.
Je vais créer un deuxième itinéraire pour un autre train qui va passer en grand partie au même endroit.
Le premier itinéraire est VERT et j'affiche au dessus un itinéraire temporaire SABLE.
On voit bien que j'ai sélectionné comme premier point celui vers le milieu et comme deuxième point celui vers le haut à gauche : les feux sont en NOIR.
Je rassure tout le monde : c'est uniquement un affichage.
De même, l'affichage de la position des lames a changé, mais c'est, là aussi, temporaire.
Si le train jaune avançait, il suivrait son itinéraire VERT, avec des lames dans la position de l'image précédente.

Mais on voit très bien le tracé du nouvel itinéraire. C'est le but.



Je clique droit. Le deuxième itinéraire devient BLANC.
Mais là, je ne suis plus en affichage temporaire.
Le premier itinéraire (le VERT) reprend ses droits, sa couleur et ses positions de lames d'aiguilles.
Les feux ne sont plus en NOIR.
En fait, la partie en BLANC est assez limitée.



Je pose le deuxième train, le bleu.
On ne calcule les points que sur une partie de l'itinéraire. Ce n'est pas la peine d'aller plus loin puisque le train bleu ne pourra pas avancer.



Le train jaune avance, efface derrière lui.
Mais remarquez la subtilité :
Au début, il efface la couleur ROUGE et la remplace par la couleur GRIS_FONCE.
Mais quand il arrive sur la future zone de l'itinéraire du train bleu, il met la couleur en BLANC, couleur de la réservation des pavés d'un itinéraire. Et la position des lames suit aussi.



Puis, le train jaune avançant, dès qu'il arrive sur la dernière aiguille qui bloque le train bleu.
Immédiatement, le train bleu est débloqué, ce qui se remarque dans son CagSignal qui passe à RALENTISSEMENT_CLI (= R60). Il était à CARRE depuis le début.
En effet, j'ai déterminé au départ que les deux aiguilles en plein milieu seraient limitées à 60 km/h en position déviée.



Puis on arrive en position finale, chaque train arrêté devant son CARRE.



Poussons un peu plus loin.
Le train jaune a le même itinéraire que précédemment.
Le train bleu a aussi le même itinéraire
Puis on ajoute une suite pour le train jaune (A et B dans les cercles jaunes).



Clic DROIT pour valider. On lance le train jaune jusqu'à ce qu'il libère le train bleu. L'itinéraire du train bleu s'affiche complètement en vert puisqu'il est libre jusqu'au bout (ni occupation, ni réservation).
Vous noterez que, à ce moment, le train jaune a l'AVERTISSEMENT puisque le signal d'après est CARRE.



Le train bleu démarre et dépasse la TJS



Comme le train jaune a atteint la dernière zone de l'itinéraire 1, qui se trouve être la première zone de l'itinéraire 3, il y a transfert du train de l'itinéraire 1 vers l'itinéraire 3 et effacement complet de l'itinéraire 1 dans la liste "tous_iti".
Le train jaune est donc complètement sur son nouvel itinéraire.
Le train bleu n'a pas changé d'itinéraire, mais c'est maintenant le premier itinéraire de la liste.
Le train jaune est sur le deuxième itinéraire.
Quand le train bleu a avancé, il a dépassé la TJS et donc l'a libérée. Elle est maintenant réservée (en BLANC) et dans la bonne position. Le feu du train jaune est maintenant à SEMAPHORE Le train jaune reste bloqué à cause de l'occupation de la zone suivante par le train bleu.
Quand le train bleu aura complètement quitté la zone, le train jaune pourra avancer, mais sera immédiatement bloqué par un SEMAPHORE sur  la zone tant que le train bleu n'aura pas quitté les aiguilles. A noter qu'il peut avancer parce qu'on a, au passage, calculé les nouveaux points jusqu'au SEMAPHORE.



Le train bleu a passé les aiguilles et le train jaune est libéré. Cette fois, les points sont calculés jusqu'au bout. Et donc, en VERT.


 
Maintenant que j'ai tout détaillé, j'arrête ce très long post.
Avec une dernière vidéo (c'est encore plus beau en mouvement) de 3 trains, le troisième faisant navette au milieu des autres…





DDEFF

  • Sr. Member
  • ****
  • Messages: 470
    • Voir le profil
Modélisation logicielle d'un réseau - le système de Denis
« Réponse #62 le: décembre 06, 2018, 09:41:46 pm »
Ça démarre insidieusement par la création d'une variable booléenne pour mémoriser une situation et régler un cas particulier.
Puis une deuxième variable pour régler un autre cas.
Puis on passe à une variable entière pour un troisième cas…
Au bout d'un moment, ça devient suspect  ??? et on se rend compte qu'on vient de lever un lièvre : il faut revoir en profondeur l'analyse du problème.
Les cas singuliers sont en fait des cas particuliers d'une vision plus générale.
J'ai donc revu ma copie et posé les bases d'une nouvelle façon de voir les choses.

La variable "numero_train" :

Le grand changement, c'est d'avoir exploité au maximum la variable "numero_train" dans les pavés.
J'avais déjà entrevu la solution, mais je n'avais pas traité à fond toutes les possibilités de cette variable.
Ce qui a profondément transformé mon programme qui a maintenant moins de variables, moins de lignes, plus de clarté et de lisibilité. 8)

Voilà mon réseau d'essais, avec des numérotations liées à cet article.
Je rappelle qu'on n'a jamais besoin de ces numéros de zone ni dans l'exploitation du réseau, ni dans le programme lui même (voir précédents posts)



En premier, le pupitre avec les numéros de train, qui commencent à 1, pas à 0. C'est important.
En bleu, le train n°2 et on voit son orientation sur le pupitre, orientation qui suivra la vraie orientation du train (merci à Pierre (=Pierre59) pour cette idée).
En jaune, le train n°3.
Voilà comment les numero_train sont présents dans les pavés :



N est le numéro de train.
Si numero_train est négatif, c'est qu'on n'a pas de train sur l'itinéraire
Si numero_train est positif, c'est qu'on a bien un train sur l'itinéraire
Pas de train = -1000, ce qui laisse 999 numéros de trains ! ;D

Ce numero_train existe aussi pour les itinéraires.
Il peut y avoir plusieurs itinéraires qui ont le même numero_train, en négatif : tous les itinéraires suivants, recopiés, (voir plus loin)
Mais il n'y a qu'un seul itinéraire ayant un numero_train positif : celui sur lequel est vraiment le train à un moment donné.

Comme je ne voulais pas détailler tous les pavés, on raisonnera sur les zones dans ce post.
En réalité, ça se passe au niveau des pavés.

Cas particulier de la couleur SABLE des itinéraires (itinéraires temporaires) :

La couleur SABLE ne correspond pas à un numero_train.
Elle est gérée par une variable booléenne "iti_tempo".

Pendant qu'on affiche la couleur SABLE (qui est dessinée au dessus de tous les tracés, avec iti_tempo à true) les autres couleurs continuent leur vie "en dessous", les trains continuent à rouler, etc.
Dès qu'on a choisi un itinéraire, on met iti_tempo à false et on retourne aux couleurs normales qui ne sont désormais plus masquées.
Les couleurs affichées avant qu'on dessine des itinéraires temporaires ont pu évoluer entre temps.
La couleur SABLE ne masque pas les trains.

Évolution des couleurs :

Quand on ouvre le réseau, tous les numero_trains sont à 0 et donc tout est affiché en GRIS.
Ce qui explique pourquoi on démarre les numero_train à 1.

Sur l'exemple précédent, j'ai défini un premier itinéraire.
(Un clic sur le point de départ, un clic sur le point d'arrivée)
iti1 : Z1, Z4, Z5, Z6, Z9, Z10, Z11 pour le train 3.
Puis, toujours pour le train 3, iti2 : Z11, Z6, Z5, Z4, Z2, Z1
Si on regarde bien, ça fait un "8" couché.

Puis, pour le train 2, iti3 : Z3, Z4, Z5, Z6, Z7, Z8.
Là, on a affaire à un point à point.

Pour le train 3, avec, entre parenthèses, le numero_train du pavé :
Z1(3) est en ROUGE à cause de l'occupation.
Z4(3), Z5(3), Z6(3), Z7(3), Z9(3), Z10(3) et Z11(3) sont en VERT. Comme c'est le premier itinéraire demandé, il est complètement VERT car rien ne l'empêchait.

Quand je fais le deuxième itinéraire du train 3, Z11(3) est déjà VERT et le reste.
Z6(3) est déjà VERT, mais on ne peut plus changer la position du branchement, réservée par iti1.
Z5(3) et Z4(3) sans changement, avec les positions du premier itinéraire.
Z2  ne fait pas partie du premier itinéraire et on a donc Z2(-3).
Le signe – signifie qu'il n'y a pas de train dessus. C'est l'itinéraire "suivant" de iti1.
Z1(3) à cause du premier itinéraire.

Pour le train 2 qui vient après les deux autres itinéraires, on a :
Z3(2), Z4(3), Z5(3), Z6(3), Z7(3), Z8(-2)
Le train 2, bloqué par un carré en sortie de Z3 (voir son cab-signal) n'est pas gêné que les numero_train soient d'un numéro différent du sien sur les zones suivantes puisqu'il ne peut pas y aller…

Vous voyez ainsi que, pour un même itinéraire, on peut avoir des pavés ayant des numero_train différents.

En effet, à un instant donné, un pavé ne peut avoir qu'un seul numero_train. ;)
C'est la phrase clé.

Quand on a réservé le pavé P pour le train 3, il reste réservé pour le train 3.
Dans tous les itinéraires utilisant le pavé P, il restera affecté au train 3.

Calcul des points :

Un véhicule (loco ou wagon) ne peut avancer que s'il est sur une zone où on a des points. Il avance par sauts minuscules. Par exemple, l'itinéraire 1 ci-dessus compte … 10 304 points !
Dès le début, on se dit qu'il va falloir calculer les points le moins souvent possible sous peine de saturation processeur.

Autre remarque :
Il ne faut pas, à chaque fois, calculer tous les points d'un itinéraire, mais seulement ceux qui servent.

Exemple :
Pour le premier itinéraire du train 2, je n'ai calculé que les points de Z3. Ce n'est pas la peine d'aller plus loin car il est bloqué par un CARRE.
En fait, je ne m'occupe pas du CARRE, je regarde simplement les numero_train de cet itinéraire :
Z3(2), Z4(3), etc.
Dès l'instant où la Z4 est affectée au train 3, je sais que le train 2 ne pourra pas y aller. Et j'arrête de calculer les points.

Quand a-t-on vraiment besoin de calculer les points ?

Dans seulement 3 cas :

1°) Quand on pose un train :
L'itinéraire était BLANC et devient VERT, puis ROUGE pour les zones occupées.

2°) Quand on relance un train arrêté :

Exemple : le train 2 est actuellement arrêté devant son CARRE.
Quand il pourra rouler, par passage de CARRE à RAPPEL_RALENTISSEMENT_60, il aura fallu, auparavant calculer les points de la suite de l'itinéraire

3°) Lors d'un transfert d'itinéraire :
Ex : quand il sera entièrement sur la Z11, le train 3 sera en train de ralentir devant un CARRE de fin d'itinéraire. Dès que l'itinéraire suivant sera possible, le train passera de dernière zone de l'itinéraire 1 à première zone de l'itinéraire 2. Et, là, il faudra calculer les points de l'itinéraire 2.

Donc le calcule se fait très rarement, en "one shot" (comme disent les Brexitois) à chaque fois.

Depuis le début de l'itinéraire jusqu'à ce qu'on trouve une zone qui n'a pas le bon numero_train.
Pour le train 3, on calcule les points tant que la zone a le numero_train = 3, -3, 0 ou -1000.
3, c'est évident, -3 car on peut le transformer en 3, 0 pour une première affectation d'une zone entièrement vide et -1000 uniquement quand on pose le train la première fois.

Et quand le calcul des points arrive sur un pavé ayant le mauvais numero_train, il s'arrête et décrète que le train est "en attente".
"iti_en_attente = true" pour cet itinéraire.

Quand les numero_train des pavés évoluent-ils ?

Là, par contre, très souvent.
Le moment clé est la sortie d'un train d'une zone. On est en PRS, je le rappelle.

S'il n'y a qu'un seul train sur le réseau, au fur et à mesure que le train avance, on met le numero_train à 0 chaque fois qu'on sort d'une zone.

Mais j'ai voulu améliorer l'aspect visuel quand il y a plusieurs trains. Et aussi améliorer la compréhension de façon "parlante".

Dans l'exemple, seul le train 3 peut avancer.
Il va libérer Z1 qui va passer à 0 (GRIS).
Puis il va libérer Z4 qui va passer à -2 (BLANC). Pourquoi ?
Quand on libère Z1, personne n'en a plus besoin et on la libère complètement en passant à 0.
Par contre, quand on libère la Z4, le train 2, lui, va en avoir besoin et on la lui réserve en la mettant à numero_train = -2.
Puis, en avançant, le train 3 va libérer Z5 qui devrait, par le même raisonnement, passer à -2 et donc apparaitre en BLANC.
Oui, mais, maintenant, le canton formé par Z4 et Z5 est maintenant entièrement libre.

Temps mort : un canton, c'est une ou plusieurs zones avec un feu à chaque bout (en banalisé).
Ne pas confondre zone et canton. Ce n'est pas la même chose.


Donc, le train 2, ayant un canton libre devant lui, va pouvoir avancer.
Calcul des points jusqu'à Z5 inclus, les -2 deviennent des 2, et passage à VERT pour les zones.

Le train 3, sur Z6, empêche le train 2 d'aller plus loin.

Libération de Z6 qui passe à -2 (BLANC), de Z7 qui passe à -2 (BLANC) et Z8 est déjà à -2 (BLANC)

Donc libération totale du train 2, toutes les zones Z6, Z7 et Z8 passent à 2 (VERT) et le train 2 peut aller jusqu'au bout.

A noter aussi que cette libération du train 2 va maintenant bloquer le train 3. C'est lui qui, maintenant, va avoir iti_en_attente à true ! ;)

Quand le train 3 est entièrement sur Z1, abandon du premier itinéraire, transfert du train 3 au début de l'itinéraire 3 qui commence à Z11.

Le train 2 libère Z3 qui passe à 0 (GRIS), puis Z4 qui passe à –3 (BLANC), puis Z5 qui passe à -3 (BLANC), puis Z6 qui passe à -3 (BLANC).
Le train 3 est libéré, calcul des points et on a :
Z11(3), Z6(-3->3), Z5(-3->3), Z4(-3->3), Z2(-3->3), Z1(0->3). Tout est VERT et il peut avancer.

Si vous avez bien saisi cette mécanique, vous remarquerez que les points ne sont calculés que pour les zones VERT et ROUGE.
Pour être plus exact, c'est parce qu'on a des points que les zones sont VERT ou ROUGE.

Signal CARRE :

Je reviens sur le signal le plus complexe : le CARRE.
Complexe parce qu'il peut être modifié manuellement.
Gérer automatiquement une chose manuelle est impossible dans tous les cas.
Par contre, si on y arrive dans trois situations, cela couvre une très grande majorité des cas possibles.

1°) le signal est devant un branchement pris en talon et dans la mauvaise position.
On a le CARRE puisqu'on a pris comme règle que le branchement n'est pas talonnable.
(Je ne désespère pas de gérer les branchements talonnables, mais c'est une autre histoire)

2°) le dernier pavé d'un itinéraire se termine forcément par un CARRE s'il n'a pas d'itinéraire suivant.
Lancer un train, c'est lui trouver un itinéraire suivant.

3°) le pavé suivant dans l'itinéraire n'a pas le même sens.

Ce cas survient si on a deux trains face à face et il faut bien en arrêter un.
A tester car j'ai encore quelques bugs.

Itinéraires répétitifs:

Un itinéraire répétitif, c'est un itinéraire qui se détruit, comme les autres, mais qui se reconstruira plus tard.

A partir du moment où on sait transférer un train d'un itinéraire sur un autre, c'est une suite assez logique.
Il "suffit" de recopier l'itinéraire qu'on est en train de parcourir en bout de liste.
Pour qu'on identifie dès le départ que tel itinéraire sera répétitif, j'ai dû créer un autre bouton au menu.

Dans l'exemple, j'ai crée, avec le bouton de recherche d'itinéraire, un premier itinéraire pour le train 3 qui va de Z1 à Z11, puis un deuxième itinéraire qui va de Z11 à Z1.
On a iti1 = Z1->Z11 et iti2 = Z11->Z1. Et iti2 suivant de iti1.
Le train 3 parcoure iti1, arrive en Z11, effectue un transfert de iti1->iti2 et parcoure iti2 jusqu'à Z1 et il s'arrête.

Si je crée iti1 à partir du bouton "itinéraire répétitif" et iti2 à partir du même bouton, que va-t-il se passer ?
Le train 3 parcoure iti1.
En fait, dès qu'il a démarré, il a recopié iti1' = iti1. Et dit que suivant(iti2) = iti1'.
Il y a maintenant dans "tous_iti" : iti1, iti2, iti1'.
Le train 3 arrive en Z11, sait que suivant(iti1) = iti2, et il y a transfert du train 3 sur iti2.
A cet instant, iti1 a disparu et il reste iti2, iti1'.
Dès que le train 3 a basculé, on ajoute iti2' = iti2 et on dit que suivant(iti1') = iti2'.
Il y a maintenant dans "tous_iti" : iti2, iti1', iti2'
Quand le train 3 arrive en Z1, on efface iti2, on transfère le train sur iti1'.
Il reste iti1' et iti2'.
Dès que le train 3 a basculé, on ajoute iti1" = iti1' et on dit que suivant(iti2') = iti1".
Quand le train 3 arrive en Z11, on efface iti1', on transfère le train sur iti2'.
Etc.

Donc on peut abouter autant d'itinéraires que l'on veut et ils se recopient à l'infini.

Paradoxe :

Après plus de deux ans de recherches et de développement, je suis en mesure de poser un train sur un ovale, mettre le curseur à fond et le regarder tourner !!!
Tout ça pour ça…. :o

Navette :

Comme le transfert peut aussi avoir lieu avec le changement loco en tire -> loco en pousse et réciproquement, on peut faire une navette infinie aussi, sans difficulté particulière.

Exemple sur la vidéo suivante ou j'exploite avec un train les 4 terminaisons possibles.



Et pour arrêter ?

Eh oui, l'infini c'est long (surtout sur la fin) et il faudrait pouvoir arrêter quand on veut.
C'était déjà fait avant (voir mon post du 14 septembre).
On arrête manuellement le train là où on veut.
Un double clic sur l'un des signaux de la zone occupée et tous les itinéraires qui ont le même numero_train, mais en négatif, sont supprimés et le seul itinéraire qui a le numero_train en positif est réduit à la seule zone occupée.

C'est là qu'on voit la puissance des numero_train. Simple et diablement efficace.

Deux itinéraires répétitifs sécants :

Pour bien monter que ce sont les itinéraires répétitifs, je vous montre la vidéo des itinéraires du début, mais en répétition pour chaque train ! Et tout s'enchaîne sans heurts !



Et l'éditeur, dans tout ça ?

Ayant atteint une étape cruciale dans le gestionnaire, je vais faire une pause et m'attaquer à l'éditeur.
Il existe déjà, mais mal programmé.
J'ai fait de gros progrès dans la gestion du temps machine, par contrainte de calculs à faire en temps réel pour le gestionnaire.
Je vais appliquer ces innovations à l'éditeur qui va devenir beaucoup plus rapide. C'est fondamental.

En plus, je vais très vraisemblablement intégrer certaines modifications apportées par Pierre pour le dessin des formes qui composent le réseau dans son article du 14 octobre http://www.locoduino.org/spip.php?article231

Le gestionnaire est fini ?

Que nenni !

Il manque :

1°) La gestion des zones de manœuvre, avec de vraies spécificités

2°) La gestion du nombre de wagons. Là,
    le train 1 a 1 loco et 3 wagons
    le train 2 a 1 loco et 4 wagons
    le train 3 a 1 loco et 8 wagons
    le train 4 est une loco HLP (Haut Le Pied = seule)
On ne peut rien y changer, sauf à "mettre les mains dans le cambouis".
Il faut pouvoir modifier le nombre de wagons très facilement, en détacher un ou plusieurs, etc.

3°) Pouvoir choisir que le pupitre soit en regroupé (comme maintenant) ou tout à droite du réseau (ce doit être facile)

4°) Améliorer l'accélération.
Pour l'instant, la partie pour l'accélération c'est :

void acceleration() {
    vitesse = consigne;
}

Difficile de faire moins…

Alors que l'arrêt, par exemple fait 53 lignes et fait un beau ralenti type décharge de condensateur (voir mon post du 9 août).

Et, surtout, ce n'est pour l'instant qu'un jeu, sophistiqué, certes, mais sans lien avec le monde réel.
Je compte beaucoup sur mes collègues Orléanais pour m'expliquer ce qu'ils ont fait et qui est exactement ce qui me manque.
Complémentaires, je disais. ;D

Piste pour un décor sur mesure :

Comme on peut mettre n'importe quelle image comme fond de décor, je me suis amusé à ajouter deux rectangles. C'est moche, mais ça marche. Mais on peut dessiner ce qu'on veut.

Il suffit d'avoir Paint.net qui gère les calques. C'est gratuit.
1°) Vous faites une copie d'écran de votre réseau
2°) Vous redimensionnez l'image à 1366 x 768 (la définition donnée dans le setup)
3°) Vous ouvrez un nouveau calque
4°) Vous dessinez ce que vous voulez (bâtiments, photos, chemins, …). C'est facile parce que vous avez le réseau en transparence. Vous pouvez être très précis.
5°) Vous ne sauvez QUE le calque (sans le réseau) et vous appelez votre image "Fond ecran.png" rangée dans "data/Icones"

Aucune incidence sur le temps de traitement car elle n'est dessinée qu'une seule fois.



Nota : on ne peut pas prendre une photo de son vrai réseau et la mettre en fond pour une raison toute simple : les rails ne sont pas les mêmes (les branchements, traversées ont un angle de 45°, en particulier). On a fait le maximum pour que ça ressemble, mais c'est un schéma…

Pour ceux que ça intéresse : le lien vers le TCO V7_0 : http://www.locoduino.org/IMG/zip/train_tco_v1_7_0.zip
« Modifié: décembre 07, 2018, 04:12:11 pm par DDEFF »

Pierre59

  • Full Member
  • ***
  • Messages: 142
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Denis
« Réponse #63 le: décembre 07, 2018, 12:17:34 pm »
Bonjour

j'ai, comme d'habitude, quelques remarques à faire.

Concernant les "numero_train" codant des informations en tranches en collaboration avec la couleur, ce me semble une régression dans l'utilisation de la programmation objet. Si on a besoin d'infos sur les trains dans les pavés on ajoute au pavé une référence sur un objet train !

Concernant les carrés (et les carrés violets) c'est certes les seuls signaux sur lesquels il y a action "manuelle" qui est tout à fait normale, deux actions "manuelles" sont possibles ouverture du carré ou fermeture du carré. Ces actions se font souvent indirectement par la création ou la destruction d'itinéraires. La réalisation effective des ces actions  (faites ou pas faisables)  est du ressort des enclenchements qui sont justement là pour empêcher des actions non conformes. Par exemple dans un poste d'aiguillage électromécanique unifié, il y a un levier par signal, la manoeuvre de ce levier (donc du signal) est contrainte par des enclenchements, des enclenchements mécaniques vis à vis des autres leviers (d'aiguille, de signaux, d'autorisations, …) et par des enclenchements électriques (occupations des zones, enclenchements d'approche, …), Dans les postes plus modernes (PRS) les principes d'enclenchement sont les mêmes mais sont tous réalisés électriquement. Ces principes permettent de gérer les carrés dans tous les cas !

Concernant les itinéraires à tracé permanent, ton histoire de "phénix" n'est pas très convaincante. Voici la définition d'un itinéraire permanent, un itinéraire permanent n'est pas détruit après le passage d'un train ce qui implique que les carrés ne soient pas fermés à l'aubination, mais mis au sémaphore.

Amicalement

Pierre
 

DDEFF

  • Sr. Member
  • ****
  • Messages: 470
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Denis
« Réponse #64 le: décembre 07, 2018, 04:04:47 pm »
Merci Pierre,

J'aime bien tes remarques car elles font toujours réfléchir.
Mais sur la première, je ne la comprends pas

Citer
Concernant les "numero_train" codant des informations en tranches en collaboration avec la couleur, ce me semble une régression dans l'utilisation de la programmation objet. Si on a besoin d'infos sur les trains dans les pavés on ajoute au pavé une référence sur un objet train !

J'ai trois objets :
L'objet "Train" qui a une variable numero_train qui est fixée une fois pour toutes quand je choisis le train que je vais poser.
L'objet "Pave" qui a une variable numero_train, très souvent mise à jour.
L'objet "Itineraire" qui, entre autres, est une ArrayList de Pave. Et donc, ordonnée.

Si je parcoure les pavés de l'itinéraire (dans une boucle "for", par exemple), je parcoure aussi les numéro_train des pavés (via pave.numero_train).
Dans la liste des pavés de l'itinéraire, certains sont occupés par un train, d'autre non.
En fonction des numero_train des pavés composant l'itinéraire que je parcoure (dans la boucle "for"), j'ai des actions (avancée, arrêt, ralenti, ...) sur le train qui est sur l'itinéraire. Et je mets à jour la variable numero_train dans le pavé en cours de traitement à ce moment.

En fait je ne mets à jour des infos sur le numero_train des pavés que sur des pavés qui ne contiennent pas de train. Sinon, on pourrait avoir des surprises...

Pour moi, la variable "numero_train" du pavé n'est pas liée (au sens objet) à la variable numero_train du train.
Mais je me trompe peut-être ? Et il y aurait une autre façon de raisonner ?

Concernant les enclenchements, je les gère par les numero_train des pavés.

Dans ma façon de raisonner, un itinéraire peut ne pas avoir de train (avant qu'on l'y pose), mais un train ne peut pas ne pas être sur un itinéraire.

Même quand il a atteint son but (par exemple sur une voie de gare), il est sur un itinéraire.
Cet itinéraire est composé des pavés composant la zone de la voie de gare, tous occupés dans ce cas.
Au sens SNCF, ce n'est pas un itinéraire, c'est une occupation de zone, ni plus, ni moins.

Au passage, comme il est sur la dernière zone d'un itinéraire qui n'a pas de suivant (dans ce cas d'école) il a le CARRE.
Si on lui définit un nouvel itinéraire à partir de cette zone, ce sera considéré comme le "suivant" de l'itinéraire sur lequel il est.
Donc transfert, feu à VOIE_LIBRE et départ du train.

Cet itinéraire suivant est donc composé de pavés.
Supposons qu'on parle du train 2 et que le numero_train de l'un des pavés de l'itinéraire suivant soit 3.
Le train 2 ne pourra franchir cet "obstacle". C'est, pour moi, un exemple de condition d'enclenchement (parmi d'autres).

Je suis bien conscient que ma façon de voir les choses peut surprendre... 8)

Concernant la dernière remarque sur le Tracé Permanent, je vais changer ma dénomination. Je vais parler "d'itinéraires répétitifs". Tu as raison : ce que je fais n'est pas un TP.

Amicalement

Denis

DDEFF

  • Sr. Member
  • ****
  • Messages: 470
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Denis
« Réponse #65 le: mars 22, 2019, 09:03:45 pm »
Bonsoir,



Voici une vue de la nouvelle version du gestionnaire :
1°) Avec une image en arrière plan (on peut mettre ce qu'on veut)
2°) Il y a maintenant une loco
3°) Les voitures sont plus longues et suivent les bogies
4°) Quand on appuie sur F0, ça allume les feux

Mais tout cela sur des trains ... virtuels

Il reste encore du boulot ! ;)

Denis