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

DDEFF

  • Hero Member
  • *****
  • Messages: 738
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Pierre59
« Réponse #60 le: mars 06, 2017, 05:31:31 pm »
De rien, c'est normal  ;)

Donc, on est dans une situation correcte vu de Windows (je ne sais pas pour Mac) :

1°) P2D obligatoire maintenant (depuis Processing 3.2.4) dans TOUS les programmes Processing.
2°) Il faut que java soit bien à jour. En fait, c'était la vraie origine du problème.

Il faut aussi remercier Pierre pour son programme et Gérard31 qui avait aussi gardé les anciennes versions de Processing (une bonne idée).  ;D
"Ce n'est pas le puits qui est trop profond, c'est ta corde qui est trop courte" (proverbe chinois)

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2889
  • 100% Arduino et N
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Pierre59
« Réponse #61 le: mars 06, 2017, 06:05:26 pm »
Sur mon Mac, la version Java est celle d'Apple, donc pas celle d'Oracle :
Java(TM) SE Runtime Environment (build 1.6.0)

Les programmes de Pierre tournent parfaitement et apparemment ceux de Denis aussi.

Je suppose que Processing intègre sont propre Java pour cela (ce serait bien raisonnable !)

Dominique
Cordialement,
Dominique

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2889
  • 100% Arduino et N
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Pierre59
« Réponse #62 le: mars 16, 2017, 05:57:31 pm »
Je vais ici reprendre l'exemple de la mise en oeuvre du gestionnaire de Pierre dans mon réseau.

La description que je vais faire est et sera complétée par mon autre fil http://forum.locoduino.org/index.php?topic=290.0 consacré à mon projet global.

Une petite introduction est cependant nécessaire : Lorsque j'ai commencé la construction de mon réseau, j'étais loin de comprendre comment j'allais arriver à réaliser le gestionnaire. J'ai donc commencé par la réalisation d'un module de traction, puis d'un module de commandes d'aiguilles puis d'un module TCO qui gère les occupations  et les aiguilles. Le gestionnaire était ptévu sous la forme d'un Arduino Due relié aux autres (tous des Arduino Mega) via un bus CAN.

Avec ces modules je peux faire tourner mes trains manuellement sans sécurité (sans cantonnement), sans signaux, sans itinéraires.

Mon gestionnaire a commencé par intégrer un module graphique qui sert à visualiser des tas de choses qui me servent à comprendre où je vais !
Il y  en a un exemple au début de ce fil, lorsque j'ai intégré les zones selon Pierre.

Après le 4ème article du gestionnaire de Pierre, j'ai donc décidé d'intégrer la totalité des ressources qui sont permises, tout simplement en partant de son exemple du Locodrome et en y greffant mes zones, mes aiguilles, mes signaux, mes itinéraires :

Pour les zones, voici un exemple de classe dérivée de la classe de base Zone :

// 6 sortie GC Hor (pair=7, impair=5+aiguilleNdevié=4)
class Z6 : public Zone {
public:
  Z6(int n,Signal* sp,Signal* si):Zone(n,sp,si) {}// constructeur
  virtual Zone* suivantePaire();
  virtual Zone* suivanteImpaire();
  virtual void actions();
  virtual void desactions();
};

J'en ai 47 comme ça, toutes (presque) identiques (parfois sans les methodes actions() et desaction()) !

Pour les signaux, voici quelques exemples de classes dérivées :

class S5:public SemaphoreBAL {
public:
  S5(int n):SemaphoreBAL(n) {} // constructeur mini
  virtual Signal* suivant();
  virtual Signal* precedent();
  virtual boolean cantonOccupe();
};

class CRR3:public CarreAvertissementRappelRalentissement {
public:
  CRR3(int n):CarreAvertissementRappelRalentissement(n) {} // constructeur mini
  virtual Signal* suivant();
  virtual Signal* precedent();
  virtual boolean ralentissement30();
};

class CV1:public CarreViolet {
public:
  CV1(int n):CarreViolet(n) {} // constructeur mini
  virtual Signal* suivant();
  virtual Signal* precedent();
};

J'en ai 30 comme ça, avec pas mal de types de signaux, ce qui n'était pas évident vu mes lacunes en signalisation SNCF (j'ai appris depuis) !!

Pour les itinéraires, voici un exemple de classe dérivée :

//X27a30 = de z27 à z30 avec Carré C1
class X27a30:public Itineraire {
public:
  X27a30(int n):Itineraire(n) {}
  virtual boolean formable();
  virtual void former();
  virtual boolean deformable();
  virtual void deformer();
  virtual void tracer(boolean b);
};

J'en ai 43 comme ça, toutes identiques (seul le nom change)  !

Ensuite je déclare les objets réels :

// declarations des objets réels

SignalBAL* s1=new S1(0);
SignalBAL* s2=new S2(1);
SignalBAL* s3=new S3(2);
SignalBAL* sr4=new SR4(3);
SignalBAL* s5=new S5(4);
SignalBAL* s6=new S6(5);
SignalBAL* s7=new S7(6);
SignalBAL* sr8=new SR8(7);
Signal* c1=new C1(8);
Signal* c2=new C2(9);
Signal* c4=new C4(10);
Signal* crr2=new CRR2(11);
Signal* crr4=new CRR4(12);
Signal* c3=new C3(13);
Signal* c5=new C5(14);
Signal* c6=new C6(15);
Signal* c7=new C7(16);
Signal* c8=new C8(17);
Signal* cr1=new CR1(18);
Signal* cr2=new CR2(19);
Signal* crr1=new CRR1(20);
Signal* crr3=new CRR3(21);
Signal* cv1=new CV1(22);
Signal* cv2=new CV2(23);
Signal* cv3=new CV3(24);
Signal* cv4=new CV4(25);
Signal* cv5=new CV5(26);
Signal* cv6=new CV6(27);
Signal* cv7=new CV7(28);
Signal* cv8=new CV6(29);

#define MaxSignal 30

Signal* tableSignaux[MaxSignal] {s1,s2,s3,sr4,s5,s6,s7,sr8,c1,c2,c4,crr2,crr4,c3,c5,c6,
  c7,c8,cr1,cr2,crr1,crr3,cv1,cv2,cv3,cv4,cv5,cv6,cv7,cv8}; // la table des signaux

/////////////////// DECLARATIONS des ZONES ////////////////////

Zone* z0=new Z0(0,NULL,NULL); // n° / signal-pair / signal-impair
Zone* z1=new Z1(1,NULL,NULL);
Zone* z2=new Z2(2,NULL,NULL);
Zone* z3=new Z3(3,NULL,NULL);
Zone* z4=new Z4(4,c7,NULL);
Zone* z5=new Z5(5,c6,NULL);
Zone* z6=new Z6(6,NULL,NULL);
Zone* z7=new Z7(7,s5,NULL);
Zone* z8=new Z8(8,s6,s5);
Zone* z9=new Z9(9,s7,s6);
Zone* z10=new Z10(10,sr8,s7);
Zone* z11=new Z11(11,crr4,sr8);
Zone* z12=new Z12(12,NULL,NULL);
Zone* z13=new Z13(13,c4,c8); // c8 ou NULL ?
Zone* z14=new Z14(14,c5,c5); // c5 ou NULL ?
Zone* z15=new Z15(15,NULL,NULL);
Zone* z16=new Z16(16,crr3,cv5); // cv5 ou NULL ?
Zone* z17=new Z17(17,NULL,NULL);
Zone* z18=new Z18(18,NULL,cv3);
Zone* z19=new Z19(19,NULL,NULL);
Zone* z20=new Z20(20,NULL,NULL);
Zone* z21=new Z21(21,NULL,NULL);
Zone* z22=new Z22(22,NULL,cr1);
Zone* z23=new Z23(23,NULL,cr2);
Zone* z24=new Z24(24,NULL,NULL);
Zone* z25=new Z25(25,NULL,crr2);
Zone* z26=new Z26(26,NULL,NULL);
Zone* z27=new Z27(27,NULL,c1);
Zone* z28=new Z28(28,cv1,c2);
Zone* z29=new Z29(29,NULL,NULL);
Zone* z30=new Z30(30,cv6,s1);
Zone* z31=new Z31(31,s1,s2);
Zone* z32=new Z32(32,s2,s3);
Zone* z33=new Z33(33,s3,sr4);
Zone* z34=new Z34(34,sr4,crr1);
Zone* z35=new Z35(35,NULL,NULL);
Zone* z36=new Z36(36,NULL,cv2);
Zone* z37=new Z37(37,cv7,cv8);
Zone* z38=new Z38(38,cv4,NULL);
Zone* z39=new Z39(39,NULL,NULL);
Zone* z40=new Z40(40,NULL,NULL);
Zone* z41=new Z41(41,NULL,NULL);
Zone* z42=new Z42(42,NULL,NULL);
Zone* z43=new Z43(43,NULL,NULL);
Zone* z44=new Z44(44,NULL,NULL);
Zone* z45=new Z45(45,NULL,NULL);
Zone* z46=new Z46(46,NULL,NULL);

#define MaxZone  47

Zone* tableZones[MaxZone]=  {   // liste des pointeurs de zone pour la retrosignalisation
    z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13, z14, z15,
    z16, z17, z18, z19, z20, z21, z22, z23, z24, z25, z26, z27, z28, z29, z30,
    z31, z32, z33, z34, z35, z36, z37, z38, z39, z40, z41, z42, z43, z44, z45, z46  };

/////////////////// DECLARATIONS des AIGUILLES //////////////////// 
 
Aiguille* a0=new Aiguille(0,z26);  //dans z26
Aiguille* a1=new Aiguille(1,z26);  //dans z26
Aiguille* a2=new Aiguille(2,z15);  //dans z15
Aiguille* a3=new Aiguille(3,z44);  //dans z44
Aiguille* a4=new Aiguille(4,z15);  //dans z15
Aiguille* a5=new Aiguille(5,z42);  //dans z42
Aiguille* a6=new Aiguille(6,z43);  //dans z43
Aiguille* a7=new Aiguille(7,z12);  //dans z12
Aiguille* a8=new Aiguille(8,z12);  //dans z12
Aiguille* a9=new Aiguille(9,z29);  //dans z29
Aiguille* a10=new Aiguille(10,z38); //dans z38
Aiguille* a11=new Aiguille(11,z29); //dans z29
Aiguille* a12=new Aiguille(12,z38); //dans z38
Aiguille* a13=new Aiguille(13,z39); //dans z39
Aiguille* a14=new Aiguille(14,z35); //dans z35
Aiguille* a15=new Aiguille(15,z2); //dans z2
Aiguille* a16=new Aiguille(16,z6); //dans z6
Aiguille* a17=new Aiguille(17,z17); //dans z17
Aiguille* a18=new Aiguille(18,z24); //dans z24
Aiguille* a19=new Aiguille(19,z45); //dans z45 coté pair
Aiguille* a20=new Aiguille(20,z46); //dans z46 coté impair

#define MaxAig  21

Aiguille* tableAiguilles[MaxAig]= {
  a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
  a12, a13, a14, a15, a16, a17, a18, a19, a20 };

/////////////////

Itineraire *x4a7=new X4a7(0);
Itineraire *x5a7=new X5a7(1);
Itineraire *x7a11=new X7a11(2);
Itineraire *x11a13=new X11a13(3);
Itineraire *x11a14=new X11a14(4);
Itineraire *x13a16=new X13a16(5);
Itineraire *x14a16=new X14a16(6);
Itineraire *x16a4=new X16a4(7);
Itineraire *x16a5=new X16a5(8);
Itineraire *x22a25=new X22a25(9);
Itineraire *x23a25=new X23a25(10);
Itineraire *x25a27=new X25a27(11);
Itineraire *x25a28=new X25a28(12);
Itineraire *x27a30=new X27a30(13);
Itineraire *x28a30=new X28a30(14);
Itineraire *x30a34=new X30a34(15);
Itineraire *x34a22=new X34a22(16);
Itineraire *x34a23=new X34a23(17);
Itineraire *x28a36=new X28a36(18);
Itineraire *x36a28=new X36a28(19);
Itineraire *x14a18=new X14a18(20);
Itineraire *x18a14=new X18a14(21);
Itineraire *x14a38=new X14a38(22);
Itineraire *x38a14=new X38a14(23);
Itineraire *x13a30=new X13a30(24);
Itineraire *x14a30=new X14a30(25);
Itineraire *x25a13=new X25a13(26);
Itineraire *x25a14=new X25a14(27);
Itineraire *x14a11=new X14a11(28);
Itineraire *x13a11=new X13a11(29);
Itineraire *x16a13=new X16a13(30);
Itineraire *x16a14=new X16a14(31);
Itineraire *x30a27=new X30a27(32);
Itineraire *x30a28=new X30a28(33);
Itineraire *x4a3=new X4a3(34);
Itineraire *x3a4=new X3a4(35);
Itineraire *x3a1=new X3a1(36);
Itineraire *x30a13=new X30a13(37);
Itineraire *x30a14=new X30a14(38);
Itineraire *x37a18=new X37a18(39);
Itineraire *x18a37=new X18a37(40);
Itineraire *x37a38=new X37a38(41);
Itineraire *x38a37=new X38a37(42);

#define MaxItineraire 43

Itineraire* tableItineraires[MaxItineraire] {
    x4a7,x5a7,x7a11,x11a13,x11a14,x13a16,x14a16,x16a4,x16a5,x22a25,
    x23a25,x25a27,x25a28,x27a30,x28a30,x30a34,x34a22,x34a23,x28a36,x36a28,
    x14a18,x18a14,x14a38,x38a14,x13a30,x14a30,x25a13,x25a14,x14a11,x13a11,
    x16a13,x16a14,x30a27,x30a28,x4a3,x3a4,x3a1,x30a13,x30a14,x37a18,x18a37,x37a38,x38a37}; // la table des itineraires pour tco

Les tableaux d'objets sont indispensables pour pouvoir ensuite accéder à leurs méthodes et variables à partir de leur numéro.

Jusque là c'est assez simple quand on a bien décortiqué son réseau et réalisé les coupures de zones et les points d'alimentation nécessaire, ce qui n'était pas tout à fait mon cas (je devrai faire quelques modifications).

A partir de là, maintenant, il faut définir les méthodes particuliers qui dépendent de la configuration du réseau (il faut un bon dessin !) :

  • Des zones, exemple :
Zone* Z12::suivantePaire() { return selonAiguille(a7,z13,selonAiguille(a6,NULL,z43)); }
Zone* Z12::suivanteImpaire() { return selonAiguille(a8,z11,selonAiguille(a11,NULL,z29)); } // !! changement de sens sur z30
void Z12::actions() { aubiner(crr4,c8,c6); }
void Z12::desactions() { detruire(x11a13,x13a11,x11a14,x14a11);detruire(x13a30,x30a13,x14a30,x30a14); }

  • Des signaux, exemple :
Signal* CRR2::suivant() { return selonAiguille(a0,selonAiguille(a1,c1,selonAiguille(a3,NULL,c2)),selonAiguille(a2,NULL,selonAiguille(a4,c8,c4))); }
Signal* CRR2::precedent() { return selonAiguille(a18,cr1,cr2); }
boolean CRR2::ralentissement30() { return a1->deviee()?true:false; }

  • Et des itinéraires, exemple :
boolean X4a7::formable() { return libres(x4a7,x3a4,x4a3,x5a7) && libres(z6,z7,z39); }
void X4a7::former() { a16->directer(); a13->devier(); c7->ouvrir(); }
boolean X4a7::deformable() { return libres(z4,z6,z39); }
void X4a7::deformer() { c7->fermer(); }
void X4a7::tracer(boolean b) { trace(b,z4,z6,z39);z7->tracer(b); }

Ce qui fait encore un gros paquet de lignes de code, soit 600 lignes dans mon cas !!!

Au total, l'ensemble des définitions des objets dérivés, les déclarations d'objets réels et les méthodes particulières prennent 1950 lignes de code (dont quelques lignes de commentaires quand même). C'est un gros travail assez fastidieux, mais plein de copier-coller.

Ce qu'il faut mettre dans les méthodes particulières doit suivre un certain nombre de règles que j'ai notées au fur et à mesure. Je vous les donnerai dans une des suites de ce fil.

Maintenant que tout cela est fait, il faut le tester et corriger les anomalies.

Je dois dire que ces tests sont absolument nécessaires car, à ce stade de l'écriture des méthodes particulières des objets, on ne se rend pas bien compte si on bien codé ou pas.

En effet, il n'est pas toujours facile de savoir comment combiner les zones et les aiguilles, comment définir les itinéraires et le meilleur moyen est de simuler un passage de train et de regarder le comportement du gestionnaire.

Ce sera l'objet de la suite qui va suivre !!!

...
« Modifié: avril 09, 2017, 10:23:02 am par Dominique »
Cordialement,
Dominique

DDEFF

  • Hero Member
  • *****
  • Messages: 738
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Pierre59
« Réponse #63 le: mars 16, 2017, 08:58:23 pm »
Bonsoir Dominique,

Ton avancée me plait beaucoup.

On vit "en direct" les déclarations pour transformer un locodrome avec 2 aiguilles en un vrai réseau, le tien.
Comme je le connais bien, je suis avec intérêt.

Bon courage !  ;D

"Ce n'est pas le puits qui est trop profond, c'est ta corde qui est trop courte" (proverbe chinois)

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2889
  • 100% Arduino et N
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Pierre59
« Réponse #64 le: mars 16, 2017, 10:56:58 pm »
Merci Denis,

La suite va t'interesser !

Maintenant je vais aborder la méthode de tests et de mise au point des méthodes particulières des objets !!!

Vous avez remarqué que le Locodrome (V4) est fourni avec un programme écrit en Processsing. Ce programme communique, via un port série de votre ordinateur, avec un Arduino (Uno, Mega, etc..) dans lequel le Gestionnaire a été téléversé (ce qui suppose au préalable que le compilateur soit content :-)).

Ce n'est pas très difficile d'arriver à ce stade où le compilateur voit un "sans faute", quand on part bien du Gestionnaire (V4) et qu'on introduit progressivement tous les objets que j'ai présenté précédemment. Mon conseil est de vérifier très souvent et de corriger les erreurs au fur et à mesure.

Donc le programme Locodrome en Processing ressemble à cela :



Et le principe des échanges entre le Locodrome Processing et le Gestionnaire Arduino est assez simple :

Dans la série des onglets du programme Arduino (Composants.h, Constantes.h, Fonctions.h, Methodes.h, Signaux.h, SignauxBal.h, TCO.h, Train.h), on remarque qu'il y en a un qui s'appelle TCO.h et qui contient cette fonction tco(byte c,byte x,byte n).

// commandes du TCO, des aiguilles et des signaux
// ne sert que pour l'interface avec le TCO virtuel

/////////////////////////////////////////////////////////////////////////////
enum  {CODE_AIGUILLE,CODE_ZONE,CODE_SIGNAL,CODE_CARRE,
       CODE_BOUTON,CODE_BOUTON_CLI,CODE_ERREUR,CODE_INFO,CODE_CAB,CODE_MEM,CODE_TRAIN};

void tco(byte c,byte x,byte n) { byte buf[3]; // code numero info
  if (TCO) { buf[0]=c; buf[1]=n; buf[2]=x; Serial.write(buf,3); return; }
  switch(c) { // mise en forme pour affichage sur le moniteur serie
    case CODE_AIGUILLE:   Serial.print('A'); break; // manoeuvre aiguille
    case CODE_ZONE:       Serial.print('Z'); break; // coloration zone (sur tco)
    case CODE_SIGNAL:     Serial.print('S'); break; // manoeuvre signal (semaphore)
    case CODE_CARRE:      Serial.print('C'); break; // manoeuvre signal (carre)
    case CODE_BOUTON:     Serial.print('B'); break; // coloration bouton (sur tco)
    case CODE_BOUTON_CLI: Serial.print('b'); break; // coloration bouton clignotant (sur tco)
    case CODE_ERREUR:     Serial.print('E'); break; // erreur
    case CODE_INFO:       Serial.print('I'); break; // info
    case CODE_CAB:        Serial.print('s'); break; // cabsignal
    case CODE_MEM:        Serial.print('M'); break; // memoire RAM disponible (borne a 4095)
    case CODE_TRAIN:        Serial.print('T'); break; // suivi des trains
    default:              Serial.print('?');   
  }
  Serial.print(n);
  if (c==CODE_ERREUR || c==CODE_INFO) return;
  Serial.print('=');
  if (c==CODE_AIGUILLE) { if (x) Serial.print('/'); else Serial.print('|'); }
  else { //Serial.println(x);
    switch(x) { // mise en forme des couleurs
      case COULEUR_GRISE:   Serial.print('G'); break;
      case COULEUR_ROUGE:   Serial.print('R'); break;
      case COULEUR_BLANCHE: Serial.print('B'); break;
      case COULEUR_JAUNE:   Serial.print('J'); break;
      case COULEUR_VERTE:   Serial.print('V'); break;
      case COULEUR_ROSE:    Serial.print('r'); break;
      default:              Serial.print('?');   
    }
  }
  Serial.print(' ');
}

Cette fonction tco() est appelée à différents endroits du code Arduino, dans les méthodes:
  • Aiguille::manoeuvrer()
  • Zone::occuper()
  • Zone::liberer()
  • Signal::manoeuvrer()
  • Itineraire::formation()
  • Itineraire::detruire()
  • Itineraire::effacer()
  • Et dans les fonctions du cab-signal : signalChange() et signalVu()

Et seulement dans ces méthodes : cela correspond aux ordres qui seraient envoyés vers les organes de commande (visualisation sur un TCO, manoeuvre des signaux et des aiguilles via la formation des itinéraires).

Si on regarde maintenant la fonction tco() qui reçoit 3 arguments :
  • Un code type d'objet
  • Un numéro d'objet
  • Une commande

On voit que cette fonction se contente d'envoyer seulement quelques caractère "imprimables" : A pour aiguille, Z pour Zone, etc... puis un numéro, puis un code de couleur G pour gris, R pour rouge, etc...

C'est simple et cela permet au programme Locodrome Processing de réagir en affichant des changements de couleur de zone (rouge = occupée, grise = libérée, blanche = réservée pour un itinéraire), des basculements d'aiguilles, des couleurs de signaux.

Dans l'autre sens, il faut bien que le Gestionnaire réagisse aux événements du réseau virtuel simulé par le Locodrome :
  • Former, détruire, effaccer un itinéraire
  • Occuper, libérer une zone
  • Indiquer les changement de sens des trains

Je vais laisser de coté la gestion des trains pour le moment, histoire de ne pas trop compliquer la compréhension de l'exposé, mais sachez que le Gestionnaire a quand même besoin de connaître le sens de déplacement des trains pour appliquer les règles d'itinéraires.

Pour réagir, le Gestionnaire fait une traitement dans sa loop() des caractères reçus via le port série :

void loop() { Itineraire* it; char code=0;
  if (Serial.available()>=1) { // test si retrosignalisation ou commande
    code=Serial.read();
    if (!TCO) { Serial.println(); Serial.print(code); Serial.print(':'); Serial.print(' '); }
    if (code=='X') { // commande de reinitialisation
        reset();
    }
    if (code>='0' && code <='8') { // commande d'itineraire
      it=tableItineraires[code-'0'];
      if (it->enAttente()) it->effacer();   else // destruction
      if (it->libre())     it->formation(); else // essai de formation
      if (it->forme())     it->destruction();    // essai de destruction
      if (!TCO && it->enAttente()) Serial.print('m');
    }
    if (code>='A' && code <='F') { // occupation zone (retrosignalisation)
       tableZones[code-'A']->occuper();
     }
    if (code>='a' && code <='f') { // liberation zone (retrosignalisation)
      tableZones[code-'a']->liberer();
    }
    if (code=='s') train1->invSens();
    if (code=='S') train2->invSens();
    code=0; return;
  }
 
  // test itineraires en attente
  for (int i=0; i<MaxItineraire; i++) {
    it=tableItineraires[i];
    if (it->enAttente()) {
      if (!TCO && it->formable()) { Serial.println('('); Serial.println(i); Serial.print(')'); Serial.print(':'); Serial.print(' '); }
      if (it->formable()) it->formation();
    }
  }
} // fin loop

C'est impressionnant de concision !

Alors la vraie question vous saute aux yeux : ces traitements des échanges pour le Locodrome ne marchent plus pour mon réseau car j'ai 47 zones, 30 signaux, 21 aiguilles, 43 itinéraires !

Pas de panique !

Je n'ai pas changé la présentation des messages dans le sens Gestionnaire -> Locodrome.
Par contre, dans le sens Locodrome -> Gestionnaire, au lieu d'utiliser une lettre de l'alphabet pour chaque d'objet (il n'y en aurait pas assez), j'ai utilisé un simple entier avec la convention suivante :
  • de 0 à i (i<95) il s'agit d'une demande d'itinéraire i
  • de 100 à 1xx il s'agit d'une occupation de zone du numéro xx
  • de 200 à 2yy il s'agit d'une libération de zone du numéro yy
  • de 300 à 30t il s'agit d'une inversion de sens du train t

Ce que j'ai matérialisé dans cette fonction :

void execCode(int c) {
  int code = c;
  Itineraire* it;
  /////////////////  TRAITEMENT ITINERAIRE ////////////
  if (code>=0 && code <MaxItineraire) { // commande d'itineraire
    it=tableItineraires[code];
    if (it->enAttente()) it->effacer();   else // destruction
    if (it->libre())     it->formation(); else // essai de formation
    if (it->forme())     it->destruction();    // essai de destruction
    if (!TCO && it->enAttente()) Serial.print('m');
  }
  /////////////////  TRAITEMENT OCCUPATION ////////////
  if (code>=100 && code <100+MaxZone) { // occupation zone (retrosignalisation)
    tableZones[code-100]->occuper();
  }
  /////////////////  TRAITEMENT LIBERATION ////////////
  if (code>=200 && code <200+MaxZone) { // liberation zone (retrosignalisation)
    tableZones[code-200]->liberer();
  }
  ///////////////// INVERSION DE SENS ////////////
  if (code==300) train1->invSens();
  if (code==301) train2->invSens();
  return;
}

Mais vous avez remarqué aussi une autre GROS problème : le programme Locodrome en Processing ne correspond plus graphiquement à mon réseau

Mais comme Pierre avait tout prévu, on peut tester le gestionnaire sans le Locodrome en Processing, simplement avec les affichages dans le moniteur : c'est beaucoup moins "parlant" mais c'est utile quand même.

Voici un exemple de scenario de simulation fait entièrement avec le moniteur de l'IDE Arduino :

0 A13=/R E46Z4= Z6= Z39= Z7= B0=B
4 A7=/R A6=/R C11=? C6=? Z11= Z12= Z43= Z14= B4=B
104 E202Z4=
106 E46T6=? Z6=
139 T39=? Z39=
107 T7=? Z7=
204 T4=G Z4=
206 Z4= Z6= B0=G T6=G Z6=
239 T39=G Z39=
108 C3=V T8=? Z8=
207 T7=G Z7=
109 C4=V T9=? Z9=
208 C3=B T8=G Z8=
110 C5=V T10=? Z10=
209 C4=B C3=R T9=G Z9=
111 C6=V T11=? Z11=
210 C5=B C4=R T10=G Z10=
112 C11=? T12=? Z12=
143 T43=? Z43=
114 T14=? Z14=
211 C6=B C5=R T11=G Z11=
212 Z11= Z12= B4=G T12=G Z12=
243 T43=G Z43=
6 A5=/R A4=/R C13=B Z42= Z15= Z16= B6=B

La première ligne "0 A13=/R E46Z4= Z6= Z39= Z7= B0=B" signifie :
  • 0 : demande d'itinéraire n° 0
  • A13=/ : manoeuvre de l'aiguille 13 en position déviée

Un peu plus loin "209 C4=B C3=R T9=G Z9=" signifie :
  • 209 : libération de la zone 9
  • C4=B : le signal C4 allume le feu blanc
  • C3=R : le signal C3 allume le feu rouge

Bon c'est fastidieux, il faut le reconnaitre !

Il faut tout de même trouver une solution plus graphique : il y en a deux possibles :

  • Développer un moteur graphique dans le gestionnaire (ou un module séparé, via le bus CAN)
  • Développer un "Locodrome" conforme à mon réseau

La réponse est les deux mon général !

C'est ce que je vais vous présenter dans la suite ...

Stay tuned !
Cordialement,
Dominique

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2889
  • 100% Arduino et N
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Pierre59
« Réponse #65 le: mars 16, 2017, 11:43:14 pm »
Commençons par le moteur graphique intégré au gestionnaire :

J'ai assemblé un Arduino Due avec un écran graphique tactile 5 pouces et un shield adapté.

Voici une image et une video du résultat obtenu avec une simulation de circulation de trains envoyant les codes présentés précédemment via le port série :


https://player.vimeo.com/video/208743931

Cet affichage graphique montre la topographie du réseau, les aiguilles et les zones, avec leur différents états, mais pas encore les signaux.
Ce programme est ajouté au gestionnaire et écrit en langage Arduino, en utilisant la bibliothèque UTFT.
On voit sur la vidéo que les affichages ne sont pas instantanés. J'ai ajouté un onglet "Graphiques.h" qui contient 1350 lignes de code !

Mais la représentation des aiguilles et des zones, les formations et destructions d'itinéraires, les occupations et libérations sont maintenant parfaites : les tests m'ont permis de mettre au point les methodes des zones et des itinéraires. Pour les signaux cela reste à faire.

Ce n'est pas un TCO utilisable pour le fonctionnement du réseau, mais seulement pour la mise au point.
Sa description sera donnée plus tard.

Ensuite, voici la version Locodrome adaptée à mon réseau, mais c'est Pierre qui l'a faite ! Je n'ai aucun mérite !



Pour le moment ce Locodrome ne communique pas  encore avec le Gestionnaire. Mais c'est autrement plus sympathique.

Je vous en dirai plus un peu plus tard car cela ouvre des perspectives et on peut imaginer tout le potentiel des travaux de Denis qui développe un générateur de réseau !

A suire...
« Modifié: mars 17, 2017, 12:17:21 am par Dominique »
Cordialement,
Dominique

DDEFF

  • Hero Member
  • *****
  • Messages: 738
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Pierre59
« Réponse #66 le: mars 17, 2017, 01:38:12 pm »
Merci Dominique pour ces encouragements.
Je prépare un scoop (à ma connaissance, une fonctionnalité inédite) et je peaufine en ce moment la plaque tournante.

La suite va être moins visuelle, parce que, justement, ça consistera à automatiser ce que tu fais en ce moment !! ;)
Ce qui serait bien, c'est que tu puisses regrouper la totalité des spécificités de ton réseau dans un seul onglet de l'Arduino (qui s'appelerait specifs.h).

Ceux qui ont bien suivi ce que j'ai fait dans TCO comprendront que l'onglet "Routes" de mon TCO en Processing sert justement à créer les spécificités d'un réseau.
Pour l'instant, ça crée les spécifs du système de Jean-Luc, vouée à gérer les itinéraires (et cette automatisation fonctionne parfaitement).
Par la suite, justement, cet onglet devra servir à créer les spécificités d'un "locodrome" (terme générique), basé sur les préceptes de Pierre.

Mais tu avances bien, c'est motivant.  ;D

Denis
"Ce n'est pas le puits qui est trop profond, c'est ta corde qui est trop courte" (proverbe chinois)

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2889
  • 100% Arduino et N
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Pierre59
« Réponse #67 le: mars 17, 2017, 03:01:59 pm »
Définir toutes les méthodes dans un fichier specif.h ne va pas être chose facile  >:( >:( >:(

Pour arriver à modéliser un réseau jusqu'au point où le Gestionnaire pourra exercer ses différentes méthodes, j'ai rassemblé un certain nombre de réflexions et de règles à observer, qui sont probablement évidentes pour les modélistes baignant la dedans depuis longtemps et connaissant bien le fonctionnement de la SNCF.

Je vous soumets donc le fruit de mes cogitations qui s'appliquent à mon tracé de réseau représenté sur cette image :


Pour utiliser le Gestionnaire il faut se conformer aux règles de la SNCF.
  • On se placera donc du point de vue du conducteur qui doit respecter les signaux
  • On s'appuiera par exemple sur le règlement IN1482 - S1A "SIGNAUX - Signalisation au sol"

Après le tracé du réseau il faut faire le découpage en zones (ne pas confondre avec les cantons).
  • Une zone est un élément de réseau indivisible : segment de voie avec ou sans appareil de voie.
  • Certaines zones sont constituées seulement d'un segment de voie qui peut être parcouru dans un seul sens ou dans les deux sens.
  • Certaines zones peuvent contenir une ou plusieurs aiguilles.
  • Un canton est une suite de zones entre deux signaux pouvant présenter le sémaphore, pour faire du cantonnement.
  • Un canton doit pouvoir contenir entièrement le train le plus long.
   
La topographie du réseau (sa modélisation) est décrite dans les méthodes suivantePaire(), suivanteImpaire() des zones qui définissent les connexions entre zones en fonction des positions des aiguilles.

Le découpage en zones permet ensuite de délfinir les signaux et les itinéraires.
  • Les signaux conditionnent le déplacement des trains qui doivent les respecter via le CabSignal envoyé aux trains.
  • Les itinéraires définissent un chemin entre une zone de départ et une zone d'arrivée.
  • Les itinéraires considérés ici sont de petits itinéraires (élémentaires) qui définissent tous les chemins possibles à travers chaque zone avec aiguille(s).
  • Il ne s'agit pas de grands itinéraires reliant n'importe quel point de départ avec n'importe quel point d'arrivée.
  • Ce type de grand itinéraire sera possible par assemblage d'itinéraires élémentaires tels que ci-dessus.
   
La formation d'un itinéraire positionne les aiguilles et les signaux et autorise donc le passage du train.
  • Elle n'est possible que si toutes les zones traversées sont libres.
  • Chaque zone doit donc disposer d'un détecteur d'occupation (rétrosignalisation).
  • Certaines zones (quais de gare) doivent avoir en plus un dispositif d'arrêt des trains avant le signal de la zone suivante (zone d'arrêt ou détecteur équivalent).
  • La libération d'une zone est acquise lorsque tous les wagons/voitures du train ont quitté la zone (par ex. avec feu rouge de wagon de queue)
   
      
Le placement des signaux commence par les sémaphore de BAL sur les trajets (cantons) sans aiguilles:
  • Un sémaphore protège le canton qui le suit (dans le sens de déplacement du train).
  • Le signal qui précède fait l'avertissement du sémaphore suivant.
   
Le placement des signaux continue par les carrés avant aiguilles (ou croisements, TJDs, etc..):
  • En sortie de gare quand la voie s'est divisée en plusieurs voies, coté talons d'aiguille.
  • En entrée de gare avant les aiguilles d'orientation vers les voies coté pointe d'aiguille.
  • Le signal qui précède ce carré, doit pouvoir présenter un avertissement.
  • Avant une aiguille déviée, le signal doit présenter un rappel de ralentissement.
  • Le signal précédant un rappel de ralentissement doit présenter un ralentissement (en plus de l'avertissement).
   
Le placement des signaux continue enfin par les signaux de manoeuvre:
  • En sortie d'une zone de manoeuvre, il y a un carré violet ou un feu blanc (marche en manoeuvre).
  • Le carré violet s'impose devant les aiguilles prises dans le sens contraire au sens normal.
   
Une fois que les signaux sont placés et les itinéraires définis, on peut programmer les methodes paticulières
  • des zones
  • des signaux
  • des itinéraires
  • des aiguilles

1) En sachant que les methodes appelées par la rétrosignalisation dans la LOOP  sont les commandes venant de la rétrosignalisation:
  • si occupation :  actions()
  • si liberation :    desactions()
  • occuper(), liberer(), tracer() : pour afficher le retour au TCO
  • En plus évidemment des methodes de la modélisation:
       - suivantePaire()
       - suivanteImpaire()

2) Les commandes des signaux (appellées par les commandes d'itinéraires, depuis le TCO) sont :
  • suivant(),
  • precedent(),
  • ralentissement30(), ralentissement60(), si signal le nécessite,
  • manoeuvrer() :  interface avec le matériel pour commander les signaux réels et l'affichage sur le TCO

3) Les commandes des Itinéraires (venant du TCO) sont:
  • formable(),
  • former(),
  • deformable(),
  • deformer(),
  • formation(), destruction(), tracer()  :  interface avec le matériel pour afficher le retour au TCO

4) Les commandes d'aiguilles:
  • manoeuvrer() :  interface avec le matériel pour commander les aiguilles

Règles concernant le découpage en zones

Sur une zone il ne peut y avoir qu’un seul train à la fois, en conséquence s’il peut y avoir deux trains (ou plus) sur une zone sans risques de collision alors la zone doit être scindé en deux zones (ou plus).

Un canton est une suite de zones (avec ou sans aiguille) entre deux signaux pouvant présenter le sémaphore (BAL)
Par exemple Z16-Z4 est un canton si on fait du BAL, sinon c’est deux zones !
Mais comme un train doit tenir entièrement dans la zone z4 (car c'est une gare cachée) la zone z16 doit pouvoir être libre quand un train occupe z4, pour permettre à un autre train d'entrer dans la zone z5. Donc ici, c'est bien 2 zones.

Un canton ne peut être libre que si toutes les zones sont libres. (il ne suffit pas que le seule zone suivante soit libre, sauf si le canton n’a qu’une seule zone)


Règles concernant les signaux

La méthode suivant() d’un signal concerne le signal suivant dans le sens de la marche du train

Un signal est aubiné par l’occupation de la zone suivante (celle tout juste après le signal, quelques mètres après le signal à la SNCF) dans la methode actions() de la zone.
Normalement on ne devrait aubiner que le signal ouvert (s’il existe) mais on peut aussi aubiner tous les signaux autour à la fois, car ils sont déjà fermés.
Lors du parcours d’un itinéraire le signal est aubiné lors de l’occupation de la zone qui suit la zone d’origine (regle précédente)

REGLE : desaubiner() et cantonOccupe() ne servent que pour les signaux de BAL
Dans le cas de signaux de BAL (pouvant présenter le sémaphore) le signal est désaubiné  à la libération de toute les zones qui suivent le signal (souvent il n’y en a qu’une seule, dans ce cas c’est la même zone qui aubine et désaubine le signal de BAL).

REGLE : desaction() ne sert que pour les signaux avec BAL, c’est inutile pour les autres

REGLE : Le ralentissement se fait par un signal d’avertissement (ou de ralentissement)


Règles concernant les itinéraires

Un itinéraire a une zone d’origine et une zone de destination (généralement sans aiguilles),. Entre les deux il peut y avoir plusieurs zones avec ou sans aiguilles.
En partant de la zone d’origine vers la zone de destination toutes les zones traversées font partie de l’itinéraire (+celle origine et celle de destination).

L’itinéraire est détruit lors de la libération de l‘avant dernière zone !
En transit rigide, la zone qui détruit un itinéraire est l'avant-dernière zone juste avant la zone de destination.
Exemple, l'itinéraire z16-z17-z4 est détruit quand un train est entièrement entré dans la zone z4 et a donc libéré la zone d'aiguille z17.
Ainsi, un nouvel itinéraire z16-z17-z5 peut être formé.

Le gestionnaire ne traite pas des aiguilles prises en talon, le suivant de C1 c’est S1 ! (cela ne sert pas dans le gestionnaire contrairement aux zones)
« Modifié: mars 17, 2017, 03:06:46 pm par Dominique »
Cordialement,
Dominique

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2889
  • 100% Arduino et N
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Pierre59
« Réponse #68 le: mars 19, 2017, 07:18:01 pm »
Ce dimanche est à marquer d'un pierre blanche  ;D

Je viens de brancher ce mini-TCO, construit sur un Due avec un écran 5" et qui contient à la fois :
  • Le Gestionnaire de Pierre adapté à mon réseau.
  • Le module graphique qui représente le réseau et ses états, et commande les aiguilles par des boutons tactiles.
  • L'interface CAN, un simple copier-coller de ce que j'avais développé précédemment. Evidemment je n'ai pas changé les messages CAN qui sont échangés entres modules.



Je mets sous tension et... miracle, tout marche nickel 8)

Les commandes d'aiguilles sont possible soit du TCO physique soit du TCO graphique (les lampes des positions s'allument en conséquence sur le TCO physique et la représentation de l'aiguille change sur le TCO graphique.

Les occupations et libérations sont parfaitement représentée.

Je m'attendais à ce que la surcharge graphique conduise à des pertes de messages... Mais non ! Vraiment balaise ce Due  >:(

Prochaines étapes : je remplace les commandes d'aiguilles par les boutons tactiles, qui font double emploi avec les clés du TCO physique, par des commandes d'itinéraires, les 20 à 24 itinéraires les plus pertinents avec formation ou mise en attente par les boutons tactles et destructions  automatique lors du passage des trains.

Vive le bus CAN et la souplesse qu'il permet, ainsi que sa fiabilité  ;)
Cordialement,
Dominique

DDEFF

  • Hero Member
  • *****
  • Messages: 738
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Pierre59
« Réponse #69 le: mars 19, 2017, 07:34:24 pm »
YESSS !!!!!! ;D ;D ;D ;D ;D

Un grand bravo !
Je suis vraiment content pour toi.
Et ça montre à ceux qui en douteraient encore que le locodrome de Pierre est vraiment une belle invention.
Et qu'on peut l'adapter à n'importe quel réseau.

Sans compter ton TCO, tout petit, mais costaud ! 8) 8) 8)

Amicalement
Denis
"Ce n'est pas le puits qui est trop profond, c'est ta corde qui est trop courte" (proverbe chinois)

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2889
  • 100% Arduino et N
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Pierre59
« Réponse #70 le: mars 19, 2017, 09:02:35 pm »
Merci Denis,

Ce n'est qu'une étape car j'ai 2 TJDs à remplacer par 4 aiguilles, mon TCO physique à modifier (le tracé des voies a légèrement changé), le contrôleur d'aiguilles à modifier, le module de traction à refaire complètement sur la base de DCC++ avec le Cab Signal pour piloter les trains à partir de la signalisation, et le module contrôleur de signaux à faire... puis le décor  :P

Ce module de traction présentera des trains virtuels "normalisés" vis à vis du Gestionnaire : les échanges concernant la vitesse seront en vitesse réelle.
Il assurera l'étalonnage des trains, et détectera la position des trains à la mise sous tension (voir http://forum.locoduino.org/index.php?topic=245.msg2928#msg2928).

Grâce à DCC++, les paramètres des décodeurs de tout mon matériel roulant seront gérés dans une base de donnée pour permettre la mise en place et la suppression dynamique de trains vis à vis du Gestionnaire.

J'ai encore du pain sur la planche et ce sera décrit dans mon projet http://forum.locoduino.org/index.php?topic=290.0 mais seulement quand ce sera réalisé.

Patience !

Bien amicalement
Dominique
Cordialement,
Dominique

DDEFF

  • Hero Member
  • *****
  • Messages: 738
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Pierre59
« Réponse #71 le: mars 22, 2017, 07:03:08 pm »
Bonjour Dominique,

J'ai résolu une partie de ton problème (la plus simple) :
Voici le programme locodrome original (l'ovale et 2 aiguilles) pour l'Arduino.
J'ai créé un onglet Specifs.h dans ce programme Arduino et j'y ai mis tout ce qui est spécifique à ce réseau.
C'était d'autant plus simple que Pierre avait tout bien groupé. Merci Pierre  ;)

Au passage, il faut aussi déplacer les #include du .ino dans cet onglet.

Et, pour finir, on met un #include "Specifs.h" dans l'onglet .ino, justement pour pouvoir accéder à tout ce qu'on vient de déplacer.

L'onglet que je viens de créer correspond au réseau locodrome original. C'est pour l'exemple.
Pour ton réseau, on crée un autre onglet "Specif.h"... spécifique à ton réseau.

Le programme Arduino reste le même, quel que soit le réseau : il n'y a que l'onglet "Specifs.h" qui change.  8)

Mais pourquoi est-ce important ?

Parce qu'un onglet "Specifs.h", finalement, c'est un simple fichier texte.
Et, un fichier texte, on sait le générer dans Processing.

C'est ce que j'ai fait avec un "Specifs.h" pour la description de réseau de Jean-Luc (voir le fil correspondant).
Il "suffit" de faire pareil avec la description type locodrome...
Bon, mais, ça, c'est mon problème. Là, effectivement, ça n'est plus simple, mais j'y arriverais.

yapuka  :P

Denis
"Ce n'est pas le puits qui est trop profond, c'est ta corde qui est trop courte" (proverbe chinois)

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2889
  • 100% Arduino et N
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Pierre59
« Réponse #72 le: mars 24, 2017, 11:11:26 pm »
C'est un bon début  :D

Si tu arrives à génèrer (sous forme de texte) les lignes de programme des méthodes des objets, alors tu auras gagné !

Amicalement
Dominique
Cordialement,
Dominique

DDEFF

  • Hero Member
  • *****
  • Messages: 738
    • Voir le profil
Re : Modélisation logicielle d'un réseau - le système de Pierre59
« Réponse #73 le: mars 25, 2017, 10:02:08 am »
Bonjour Pierre,

Je n'y ai jamais bien réfléchi, mais les boucles de retournement posent-elles un problème pour le déplacement des trains sur le locodrome ?

Amicalement
Denis
"Ce n'est pas le puits qui est trop profond, c'est ta corde qui est trop courte" (proverbe chinois)

Pierre59

  • Sr. Member
  • ****
  • Messages: 321
    • Voir le profil
Re : Re : Modélisation logicielle d'un réseau - le système de Pierre59
« Réponse #74 le: mars 27, 2017, 05:32:26 pm »
Je n'y ai jamais bien réfléchi, mais les boucles de retournement posent-elles un problème pour le déplacement des trains sur le locodrome ?

Bonjour

Sur la base du Locodrome je n'ai écrit que deux TCOs, le mien et celui de Dominique, ni l'un ni l'autre n'ont de boucles de retournement, donc je n'ai pas trop réfléchi au problème.

Bien que revenant à peine de vacances à la montagne, j'ai écrit un "démonstrateur" pour faire des tests dans le cas le plus simple. Il reste encore pas mal de petits problèmes techniques.

Amicalement

Pierre