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

Use consists parameters to train simulation request #9660

Merged
merged 3 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -4741,6 +4741,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 @@ -5960,6 +5961,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
39 changes: 22 additions & 17 deletions editoast/src/views/path/pathfinding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ 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 itertools::Itertools;
use ordered_float::OrderedFloat;
use serde::Deserialize;
use serde::Serialize;
Expand Down Expand Up @@ -336,24 +338,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_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 +360,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 +387,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(),
physics_consist: 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(),
physics_consist: 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
Loading