Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: design doc for the revamp of the running time calculation #168

Merged
merged 1 commit into from
Jun 19, 2024

Conversation

woshilapin
Copy link
Contributor

@woshilapin woshilapin commented Jan 26, 2024

Réunion du 24/01/2024, notes de @clarani

Objectifs


Quels sont les objectifs de la journée ? Design les nouvelles API du calcul de marche

Quelles contraintes ?

→ pouvoir gérer des contraintes bornées dans le temps (temps système, réaction signalisation)

→ pouvoir rajouter des contraintes dynamiquement, ce qui permettra de faire de la simulation multitrains

Contexte


Caractéristiques du modèle actuel

→ l’état du train se résume à un couple position/vitesse uniquement à un point de la courbe

→ le calcul de marche est calculé par morceaux, mais pas d’une manière non causale

→ recollage un peu bancal entre les morceaux

→ backtracking pour les marges

Quels sont les problèmes du modèle actuel ?

→ impossible d’ajouter des paramètres supplémentaires comme l’état d’une batterie, un temps système…

Marges: les marges de construction vont disparaître. La seule ambiguïtés encore sur le comportement avec les marges, c’est au niveau des transitions entre 2 sections qui ont des pourcentages de marge différentes: où se fait la transition ?

Propositions


Nouvel algo des marges


L’algo actuel des marges “pupet” le calcul de marche: autrement dit, il est à l’extérieur du CDM et le rappelle/itère. Cela complexifie grandement la gestion des marges et l’implémentation des marges marreco.

Nouvel interface de Margin Strategy: le Margin Strategy prend en entrée une portion de chemin (avec ses propriétés), la marche tendue sur cette portion du chemin, le matériel roulant, un coefficient de ralentissement et la vitesse du train au début de la section (pour assurer la continuité de la courbe), et sortira des éléments de ralentissement (des nouvelles limites de vitesse, des contraintes en vitesse (qui remplacent des marches sur l’erre), des nouveaux coeffitients de freinage/accélération).

Avec le résultat du Margin Strategy, on peut relancer un calcul de marche sur la portion concernée uniquement, comparer le nouveau temps de parcours et le temps de parcours de la marche tendue, puis si nécessaire, ajuster le coefficient de ralentissement et relancer Margin Strategy.

Une fois que l’on a atteint un temps de parcours satisfaisant, on passe à la portion suivante du chemin. La transition de marge est donc entièrement prise en charge par le segment suivant (à droite).

Untitled

Dans le nouvel algo, on passera les marges à l’intérieur du CDM et on utilisera le Margin Strategy, avec une boucle de rétroaction pour ajuster les éléments de marges (marches sur l’erre, abaissement du plateau de vitesse du MRSP et nouveaux coefficients d’accélération/de freinage).

Nouveau fonctionnement des marges linéaires actuelles qui ne sont pas physiques: le calcul de marche prendrait un paramètre marges et pourrait lui-même abaisser au fur et à mesure les plateaux de vitesse du MRSP, rajouter des marches sur l’erre et enfin ajuster les coefficients d’accélération/de freinage.

⚠️ ce modèle permettra uniquement de gérer les transitions de marge à droite, et pas à gauche. Gérer les transitions de marges à gauche se répercuterait sur l’ensemble des portions du chemin (on ne pourra plus traiter les segments un par un, mais il faudra calculer les Margins Strategy pour tous les segments du chemin, lancer un CDM et comparer les nouveaux temps de parcours obtenu, puis ajuster tous les coefficients de ralentissement et recommencer). La compléxité algorithmique sera beaucoup plus importante.

Calcul de marche


Points à traiter pour les nouveaux APIs

  • simulation causale
  • contraintes liées à la signalisation statique (dynamique pour plus tard)
    → contraintes qui varient en fonction de la position du train ou du temps
    → sera utile pour les ralens 30, 60 et TIV mobiles, mais aussi les arrêts en gare
  • comportements conducteur
  • temps système du train
  • temps d’arrêt
  • intégration STDCM (calcul incrémental)

Contraintes spécifiques pour STDCM

→ pouvoir reprendre un calcul de marche à un endroit donné

→ pouvoir spécifier des arrêts avec des temps

Réflexions / Débats


→ Doit-on garder le MRSP à l’intérieur du CDM ou le sortir ?
Si on le garde à l’intérieur, on doit l’avoir en output, mais on peut tout simplement le sortir. Autant le sortir finalement car ça réduirait la complexité dans le CDM.

→ Propriétés physiques du chemin et échantillonnage ?

[…]

→ Gestion des courbes de freinage

Le CDM devra prendre en argument le MaxSpeedProfile (qui comprend les courbes de freinage), lui-même obtenu via un CDM. On devra faire du backtracking et refaire la simulation jusqu’à la fin (donc on reste causal, on ne “recolle” pas).

Finalement, on ne prend pas le MaxSpeedProfile en argument, mais uniquement la vitesse finale. On calculerait le MaxSpeedProfile à l’intérieur du CDM.

→ Marges de régularité

Il faudra recalculer tout le trajet.

Résumé


Le système actuel n’est plus valide car on peut avoir plusieurs MaxSpeeds sur tout le chemin (variation du MaxSpeed avec le temps).

Quel que soit le point sur le chemin où on se trouve, on a au moins une contrainte MaxSpeed, voire plusieures. Toutes ces contraintes sont à minima bornées dans l’espace, et potentiellement dans le temps.

On calcule les courbes de freinage les plus conservatrice associées à chaque contrainte, puis on les ordonne par le point de début de freinage.

Dans la nouvelle implémentation, on propose d’intégrer jusqu’au point de la prochaine contrainte (=tracer le MaxEffort), vérifier si la contrainte est à prendre en compte ou non étant donné l’état du train (temps/position/vitesse). On passe ensuite à la contrainte suivante.

Les types de contraintes sont:

→ un signal qui change

→ les extrémités de LTV

→ les extrémités de zones BP/CC

→ les changements de palier de MRSP

→ les arrêts

Questions


  • Quelles sont les différentes conditions de fin de validité d’une instruction liée à un signal ?
  • Remettre en question le modèle défini
  • ⚠️ comment gérer si 2 contraintes sont très proches, mais avec superposition des contraintes

@woshilapin
Copy link
Contributor Author

Réunion du 31/01/2024.

Que fait STDCM aujourd'hui ?

4 manières différentes d'interagir avec le CDM :

  1. simulation incrémentale au plus vite
  • chemin + une vitesse de départ (marche tendue, pas réelle) : on va au plus vite
  • les sections du chemin sont simulées dans un ordre non-causal (mais tentative d'être optimal)
  1. simulation à l'envers (freinage)
  • seulement utilisé lorsque la vitesse d'arrivée est plus faible que le résultat de la simulation incrémentale ci-dessus
  • chemin + vitesse de fin + courbe de vitesse existante : on calcule le freinage jusqu'à intersection à la courbe existante
  1. marge de construction : on ajoute x secondes
  • seulement utilisé s'il y a un conflit avec d'autres trains
  • on cherche à déterminer si le train peut passer en adaptant la marge
  • chemin + courbe de vitesse existante + temps de marge : on ajoute le temps en tentant de conserver les vitesses de début et de fin
  • dans l'hypothèse d'une simulation causale, la vitesse de fin n'a pas plus besoin d'être une contrainte
  • si les contraintes de vitesse de début et de fin ne sont pas atteignables, le chemin est rejeté
  1. marge de régularité : calcul final
  • on récupère tous les morceaux des différentes itérations des étapes 1, 2 et 3
  • on ajoute la marge de régularité, avec une simulation de bout en bout
  • on vérifie que le trajet est toujours possible

Exemple déroulé d'un appel de calcul de marche

Informations d'entrée au calcul de marche

  • chemins sous forme de cantons
  • états des signaux en fonction du temps
  • propriétés physique du chemin
    • dénivelé
    • courbure
    • vitesse maximum (MRSP)
    • vitesse maximum en fonction du temps (LTV)
  • arrêts
    • position
    • temps d'arrêt ou heure de départ
  • état initial
    • vitesse de départ
  • contrainte de temps
    • marges
    • points horairisés

20240131_175255
20240131_175226
20240131_175210

@woshilapin
Copy link
Contributor Author

Réunion du 07/02/2024

IMG_0004

IMG_0005

@multun multun force-pushed the wsl/dd/running-time-calculation branch from 0d8a629 to ab29546 Compare February 12, 2024 17:02
@woshilapin
Copy link
Contributor Author

Réunion du 21/02/2024, pseudo-implémentation
fn filter_by_range -> fastoche
fn margin_driver -> mareco
fn merge_sets -> fastoche
fn find_most_restrictive_action(t, dt, pos, driving_instructions) -> pas fastoche mais bon courage au développeur

// simulation de base (tendue) -> target_schedule vide (simplement une relaxed_time_section), margin_driver == noop
// simulation finale (détendue/mareco) -> target_schedule avec contraintes (utilisant les résultats de marche tendue)
fn cdm_simulation(target_schedule: &[(Horaire, Position)] + d'autres trucs, abstract_driving_instructions, path_physics_properties, rolling_stock, train_init_state, margin_driver) {
  concrete_driving_instructions = compiler(abstract_driving_instructions, path_physics_properties, rolling_stock);
  state_log = [train_init_state];
  for (margin in target_schedule.margins) {
    filtered_concrete_driving_instructions = filter_by_range(margin.range, concrete_driving_instructions);
    for (v1 in search) {
      margin_concrete_driving_instructions = margin_driver(v1, filtered_concrete_driving_instructions, path_physics_properties);
      instructions = merge_sets(filtered_concrete_driving_instructions, margin_concrete_driving_instructions);
	  new_state_log = simulation(margin.range, state_log[len(state_log) - 1], instructions, path_physics_properties, rolling_stock);
    }
	state_log.extend(new_state_log);
  }
  if let Some(range) = target_schedule.relaxed_time_section {
	new_state_log = simulation(range, state_log[len(state_log) - 1], concrete_driving_instructions, path_physics_properties, rolling_stock)
	state_log.extend(new_state_log);
  }
  state_log
}

fn compiler(abstract_driving_instruction, path_physics_properties, rolling_stock) -> ConcreteDrivingInstruction;
struct AbstractDrivingInstruction { /* voir séance du 14/02/2024 */ }
struct ConcreteDrivingInstruction {
  curve: EspaceTempsVitesse,
  abstract_driving_instruction: AbstractDrivingInstruction,
}

fn simulation(range, train_state, driving_instructions, path_physics_properties, rolling_stock) {
  simulation_output = []
  for (t = start_time ; pos < range.max; t += dt) {
    train_state, driving_instructions = update_driving_instructions(train_state, driving_instructions);
    action = find_most_restrictive_action(t, dt, pos, train_state.active);
    simulation_output.extend(integration(action));
    pos = simulation_output.positions[len(simulation_output.positions) - 1];
    dt = cursed_whatever_function();
  }
  simulation_output
}

// pending instructions -> driving_instructions
// received instructions -> train_state.received_instructions
// active instructions -> train_state.active_instructions
// retired instructions -> garbage collected
// train_state contient les instructions reçues et actives
// driving_instructions contient les instructions pas encore reçues
fn update_driving_instructions(train_state, driving_instructions) {
  for (instruction in driving_instructions) {
    if instruction.received {
      train_state.received(instruction);
      driving_instructions -= instruction;
    }
  }
  for (instruction in train_state.received_instructions) {
    if instruction is now active {
      // make obsolete (retired) some instructions
      // transfer from receive to active the 'instruction'
      train_state.activate(instruction);
    }
  }
  for (instruction in train_state.active_instructions) {
    if instruction.end_of_application is on {
      train_state.active_instructions -= instruction;
    }
  }
  train_state, driving_instructions
}

@multun multun force-pushed the wsl/dd/running-time-calculation branch from c9a7bd1 to e3c82eb Compare March 4, 2024 09:57
Copy link
Contributor Author

@woshilapin woshilapin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few typos that I'll push directly (but leaving the comment so they can be seen). A few other comments that may need to be discussed. The last section, in its current state is relatively well explained, let's see if this afternoon meeting helps to clear a path.

@multun multun force-pushed the wsl/dd/running-time-calculation branch from 0469607 to 4d8c4bd Compare March 28, 2024 15:23
@multun multun marked this pull request as ready for review March 28, 2024 15:23
@multun multun force-pushed the wsl/dd/running-time-calculation branch from 4d8c4bd to fe825fe Compare March 28, 2024 15:53
Copy link
Contributor

@Castavo Castavo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quite a neat documentation !

I have several remarks but overall the doc is pretty clear and easy to read to me.
The diagrams help a lot

It's missing a Franch counterpart tho

@multun
Copy link
Contributor

multun commented May 7, 2024

@woshilapin @Castavo can someone pick up the branch / the review?

@Castavo Castavo mentioned this pull request Jun 3, 2024
20 tasks
@leovalais
Copy link
Contributor

As discussed today, maybe we should consider moving the state reconciliation logic into the driver behavior module. The current process is:

// At simulation step T:

// Driving instructions
let instructions = [DI1, DI2, DI3]

// Driver behavior PER INSTRUCTION
let candidates = [db(DI1), db(DI2), db(DI3)]

// Reconciliation
let final_curve = speeding_curves_reconciliation(candidates)

The reconciliation part is tricky because it operates on a list of curves. We can defer the reconciliation step to the driver behavior which would operate on a list of driving instructions instead.

// At simulation step T:

// Driving instructions
let instructions = [DI1, DI2, DI3]

// Driver behavior application, which is now responsible of the reconciliation of the instructions
let final_curve = driver_behavior([DI1, DI2, DI3])

This way, if two instructions are conflicting, the driver behavior can reconciliate these by matching on these two instructions instead of operating on abstract curves. Symbolic decision making is probably easier and more maintainable rather than working with conflicting curves.

Caution

To be further discussed.

@Castavo Castavo force-pushed the wsl/dd/running-time-calculation branch from 7f186af to 133b699 Compare June 7, 2024 14:57
@Castavo
Copy link
Contributor

Castavo commented Jun 14, 2024

When picking up this PR, we were tempted to change the model described. We then realized we did not have enough time so we simply settled for clarifying the description of the model.

We planned on adding examples of driving instructions generated from constraints, but none of us can afford the time, so we'll just add the photos we took from the workshop in this thread

Pictures

@Castavo Castavo force-pushed the wsl/dd/running-time-calculation branch 2 times, most recently from 9ce5786 to d9248a9 Compare June 14, 2024 15:28
@woshilapin
Copy link
Contributor Author

Looks good to me, thanks for the clarifications and the work on these last week. I can't approve (since I opened the PR).

Copy link
Contributor

@Erashin Erashin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Minor details below.

@Castavo Castavo force-pushed the wsl/dd/running-time-calculation branch from 3f19d36 to 7ce4442 Compare June 18, 2024 22:15
@Castavo Castavo merged commit 4c26222 into master Jun 19, 2024
2 checks passed
@Castavo Castavo deleted the wsl/dd/running-time-calculation branch June 19, 2024 13:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants