Skip to content

Commit

Permalink
editoast: lmr use consists parameters for train simulation
Browse files Browse the repository at this point in the history
Signed-off-by: Egor Berezovskiy <[email protected]>
  • Loading branch information
Wadjetz committed Dec 19, 2024
1 parent 465d3d1 commit db47b16
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 108 deletions.
12 changes: 12 additions & 0 deletions editoast/editoast_schemas/src/rolling_stock/effort_curves.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,21 @@ impl EffortCurves {
self.modes.values().any(|mode| mode.is_electric)
}

pub fn has_thermal_curves(&self) -> bool {
self.modes.values().any(|mode| !mode.is_electric)
}

pub fn is_electric(&self) -> bool {
self.has_electric_curves()
}

pub fn supported_electrification(&self) -> Vec<String> {
self.modes
.iter()
.filter(|(_, mode)| mode.is_electric)
.map(|(key, _)| key.clone())
.collect()
}
}

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, ToSchema, Hash)]
Expand Down
20 changes: 20 additions & 0 deletions editoast/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4519,6 +4519,7 @@ components:
- $ref: '#/components/schemas/EditoastStdcmErrorRollingStockNotFound'
- $ref: '#/components/schemas/EditoastStdcmErrorTimetableNotFound'
- $ref: '#/components/schemas/EditoastStdcmErrorTowedRollingStockNotFound'
- $ref: '#/components/schemas/EditoastStdcmErrorTrainSimulationFail'
- $ref: '#/components/schemas/EditoastStudyErrorNotFound'
- $ref: '#/components/schemas/EditoastStudyErrorStartDateAfterEndDate'
- $ref: '#/components/schemas/EditoastTemporarySpeedLimitErrorNameAlreadyUsed'
Expand Down Expand Up @@ -5690,6 +5691,25 @@ components:
type: string
enum:
- editoast:stdcm_v2:TowedRollingStockNotFound
EditoastStdcmErrorTrainSimulationFail:
type: object
required:
- type
- status
- message
properties:
context:
type: object
message:
type: string
status:
type: integer
enum:
- 400
type:
type: string
enum:
- editoast:stdcm_v2:TrainSimulationFail
EditoastStudyErrorNotFound:
type: object
required:
Expand Down
8 changes: 4 additions & 4 deletions editoast/src/core/simulation.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use std::collections::BTreeMap;
use std::collections::HashMap;
use std::hash::Hash;

use derivative::Derivative;
use editoast_schemas::primitives::Identifier;
use editoast_schemas::rolling_stock::EffortCurves;
use editoast_schemas::rolling_stock::RollingResistance;
use editoast_schemas::rolling_stock::RollingStock;
Expand All @@ -18,9 +21,6 @@ use super::pathfinding::TrackRange;
use crate::core::{AsCoreRequest, Json};
use crate::error::InternalError;
use crate::views::path::pathfinding::PathfindingFailure;
use derivative::Derivative;
use editoast_schemas::primitives::Identifier;
use std::hash::Hash;

editoast_common::schemas! {
CompleteReportTrain,
Expand Down Expand Up @@ -84,7 +84,7 @@ pub struct PhysicsConsistParameters {
}

impl PhysicsConsistParameters {
pub fn with_traction_engine(traction_engine: RollingStock) -> Self {
pub fn from_traction_engine(traction_engine: RollingStock) -> Self {
PhysicsConsistParameters {
max_speed: None,
total_length: None,
Expand Down
18 changes: 0 additions & 18 deletions editoast/src/models/rolling_stock_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,24 +72,6 @@ pub struct RollingStockModel {
pub supported_signaling_systems: RollingStockSupportedSignalingSystems,
}

impl RollingStockModel {
pub fn has_thermal_curves(&self) -> bool {
self.effort_curves
.modes
.values()
.any(|mode| !mode.is_electric)
}

pub fn supported_electrification(&self) -> Vec<String> {
self.effort_curves
.modes
.iter()
.filter(|(_, mode)| mode.is_electric)
.map(|(key, _)| key.clone())
.collect()
}
}

impl RollingStockModelChangeset {
pub fn validate_imported_rolling_stock(&self) -> std::result::Result<(), ValidationErrors> {
self.validate()?;
Expand Down
38 changes: 21 additions & 17 deletions editoast/src/views/path/pathfinding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use axum::extract::State;
use axum::Extension;
use editoast_authz::BuiltinRole;
use editoast_schemas::rolling_stock::LoadingGaugeType;
use editoast_schemas::rolling_stock::RollingStock;
use editoast_schemas::train_schedule::PathItemLocation;
use ordered_float::OrderedFloat;
use serde::Deserialize;
Expand Down Expand Up @@ -336,24 +337,19 @@ pub async fn pathfinding_from_train(
infra: &Infra,
train_schedule: TrainSchedule,
) -> Result<PathfindingResult> {
let rolling_stocks =
let rolling_stock: Vec<RollingStock> =
RollingStockModel::retrieve(conn, train_schedule.rolling_stock_name.clone())
.await?
.into_iter()
.map(|rs| (rs.name.clone(), rs))
.map(|rs| rs.into())
.collect();

Ok(pathfinding_from_train_batch(
conn,
valkey,
core,
infra,
&[train_schedule],
&rolling_stocks,
Ok(
pathfinding_from_train_batch(conn, valkey, core, infra, &[train_schedule], &rolling_stock)
.await?
.pop()
.unwrap(),
)
.await?
.pop()
.unwrap())
}

/// Compute a path given a batch of trainschedule and an infrastructure.
Expand All @@ -363,20 +359,23 @@ pub async fn pathfinding_from_train_batch(
core: Arc<CoreClient>,
infra: &Infra,
train_schedules: &[TrainSchedule],
rolling_stocks: &HashMap<String, RollingStockModel>,
rolling_stocks: &[RollingStock],
) -> Result<Vec<PathfindingResult>> {
let mut results = vec![
PathfindingResult::Failure(PathfindingFailure::PathfindingInputError(
PathfindingInputError::NotEnoughPathItems
));
train_schedules.len()
];

let rolling_stocks: HashMap<_, _> = rolling_stocks.iter().map(|rs| (&rs.name, rs)).collect();

let mut to_compute = vec![];
let mut to_compute_index = vec![];
for (index, train_schedule) in train_schedules.iter().enumerate() {
// Retrieve rolling stock
let rolling_stock_name = &train_schedule.rolling_stock_name;
let Some(rolling_stock) = rolling_stocks.get(rolling_stock_name).cloned() else {
let Some(rolling_stock) = rolling_stocks.get(rolling_stock_name) else {
let rolling_stock_name = rolling_stock_name.clone();
results[index] = PathfindingResult::Failure(PathfindingFailure::PathfindingInputError(
PathfindingInputError::RollingStockNotFound { rolling_stock_name },
Expand All @@ -387,9 +386,14 @@ pub async fn pathfinding_from_train_batch(
// Create the path input
let path_input = PathfindingInput {
rolling_stock_loading_gauge: rolling_stock.loading_gauge,
rolling_stock_is_thermal: rolling_stock.has_thermal_curves(),
rolling_stock_supported_electrifications: rolling_stock.supported_electrification(),
rolling_stock_supported_signaling_systems: rolling_stock.supported_signaling_systems.0,
rolling_stock_is_thermal: rolling_stock.effort_curves.has_thermal_curves(),
rolling_stock_supported_electrifications: rolling_stock
.effort_curves
.supported_electrification(),
rolling_stock_supported_signaling_systems: rolling_stock
.supported_signaling_systems
.0
.clone(),
rolling_stock_maximum_speed: OrderedFloat(rolling_stock.max_speed),
rolling_stock_length: OrderedFloat(rolling_stock.length),
path_items: train_schedule
Expand Down
53 changes: 31 additions & 22 deletions editoast/src/views/timetable/stdcm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use crate::models::train_schedule::TrainSchedule;
use crate::models::Infra;
use crate::models::RollingStockModel;
use crate::views::path::pathfinding::PathfindingResult;
use crate::views::train_schedule::train_simulation;
use crate::views::train_schedule::consist_train_simulation_batch;
use crate::views::train_schedule::train_simulation_batch;
use crate::views::AuthenticationExt;
use crate::views::AuthorizationError;
Expand Down Expand Up @@ -92,6 +92,8 @@ enum StdcmError {
RollingStockNotFound { rolling_stock_id: i64 },
#[error("Towed rolling stock {towed_rolling_stock_id} does not exist")]
TowedRollingStockNotFound { towed_rolling_stock_id: i64 },
#[error("Train simulation fail")]
TrainSimulationFail,
#[error("Path items are invalid")]
InvalidPathItems { items: Vec<InvalidPathItem> },
}
Expand Down Expand Up @@ -167,7 +169,19 @@ async fn stdcm(
rolling_stock_id: stdcm_request.rolling_stock_id,
}
})
.await?;
.await?
.into();

let physics_consist_parameters = PhysicsConsistParameters {
max_speed: stdcm_request.max_speed,
total_length: stdcm_request.total_length,
total_mass: stdcm_request.total_mass,
towed_rolling_stock: stdcm_request
.get_towed_rolling_stock(&mut conn)
.await?
.map(From::from),
traction_engine: rolling_stock,
};

// 2. Compute the earliest start time and maximum departure delay
let virtual_train_run = VirtualTrainRun::simulate(
Expand All @@ -176,7 +190,7 @@ async fn stdcm(
core_client.clone(),
&stdcm_request,
&infra,
&rolling_stock,
&physics_consist_parameters,
timetable_id,
)
.await?;
Expand Down Expand Up @@ -219,21 +233,12 @@ async fn stdcm(
let stdcm_request = crate::core::stdcm::Request {
infra: infra.id,
expected_version: infra.version.clone(),
rolling_stock_loading_gauge: rolling_stock.loading_gauge,
rolling_stock_supported_signaling_systems: rolling_stock
rolling_stock_loading_gauge: physics_consist_parameters.traction_engine.loading_gauge,
rolling_stock_supported_signaling_systems: physics_consist_parameters
.traction_engine
.supported_signaling_systems
.clone(),
rolling_stock: PhysicsConsistParameters {
max_speed: stdcm_request.max_speed,
total_length: stdcm_request.total_length,
total_mass: stdcm_request.total_mass,
towed_rolling_stock: stdcm_request
.get_towed_rolling_stock(&mut conn)
.await?
.map(From::from),
traction_engine: rolling_stock.into(),
}
.into(),
rolling_stock: physics_consist_parameters.into(),
temporary_speed_limits: stdcm_request
.get_temporary_speed_limits(&mut conn, simulation_run_time)
.await?,
Expand Down Expand Up @@ -407,7 +412,7 @@ impl VirtualTrainRun {
core_client: Arc<CoreClient>,
stdcm_request: &Request,
infra: &Infra,
rolling_stock: &RollingStockModel,
consist_parameters: &PhysicsConsistParameters,
timetable_id: i64,
) -> Result<Self> {
// Doesn't matter for now, but eventually it will affect tmp speed limits
Expand All @@ -420,7 +425,7 @@ impl VirtualTrainRun {
id: 0,
train_name: "".to_string(),
labels: vec![],
rolling_stock_name: rolling_stock.name.clone(),
rolling_stock_name: consist_parameters.traction_engine.name.clone(),
timetable_id,
start_time: approx_start_time,
schedule: vec![ScheduleItem {
Expand All @@ -441,15 +446,19 @@ impl VirtualTrainRun {
options: Default::default(),
};

let (simulation, pathfinding) = train_simulation(
// Compute simulation of a train schedule
let (simulation, pathfinding) = consist_train_simulation_batch(
&mut db_pool.get().await?,
valkey_client,
core_client,
train_schedule.clone(),
infra,
&[train_schedule.clone()],
&[consist_parameters.clone()],
None,
)
.await?;
.await?
.pop()
.ok_or(StdcmError::TrainSimulationFail)?;

Ok(Self {
train_schedule,
Expand Down Expand Up @@ -569,7 +578,7 @@ mod tests {
#[test]
fn simulation_without_parameters() {
let rolling_stock = create_simple_rolling_stock();
let simulation_parameters = PhysicsConsistParameters::with_traction_engine(rolling_stock);
let simulation_parameters = PhysicsConsistParameters::from_traction_engine(rolling_stock);

let physics_consist: PhysicsConsist = simulation_parameters.into();

Expand Down
Loading

0 comments on commit db47b16

Please sign in to comment.