diff --git a/editoast/Cargo.lock b/editoast/Cargo.lock index 40ae11cf323..4d751d565e8 100644 --- a/editoast/Cargo.lock +++ b/editoast/Cargo.lock @@ -1483,6 +1483,7 @@ dependencies = [ "chrono", "derivative", "editoast_common", + "editoast_derive", "enum-map", "geojson", "iso8601", diff --git a/editoast/editoast_common/src/hash_rounded_float.rs b/editoast/editoast_common/src/hash_rounded_float.rs index c011a62b28a..0e4d1fae2f6 100644 --- a/editoast/editoast_common/src/hash_rounded_float.rs +++ b/editoast/editoast_common/src/hash_rounded_float.rs @@ -1,8 +1,17 @@ use std::hash::{Hash, Hasher}; use uom::si::{ acceleration::meter_per_second_squared, - f64::{Acceleration, Length, Velocity}, + f64::{ + Acceleration, Force, Frequency, Length, LinearMassDensity, LinearNumberDensity, Mass, + MassRate, Velocity, + }, + force::newton, + frequency::hertz, length::meter, + linear_mass_density::kilogram_per_meter, + linear_number_density::per_meter, + mass::kilogram, + mass_rate::kilogram_per_second, velocity::meter_per_second, }; @@ -30,6 +39,36 @@ pub fn hash_velocity(value: &Velocity, state: &mut H) { hash_float::(&value.get::(), state); } +/// Hash a force through a rounded integer value +/// `hash_force<3,_>` means that the value is rounded to the nearest thousandth +pub fn hash_force(value: &Force, state: &mut H) { + hash_float::(&value.get::(), state); +} + +pub fn hash_mass(value: &Mass, state: &mut H) { + hash_float::(&value.get::(), state); +} + +/// Hash a mass rate through a rounded integer value +/// `hash_mass_rate<3,_>` means that the value is rounded to the nearest thousandth +pub fn hash_mass_rate(value: &MassRate, state: &mut H) { + hash_float::(&value.get::(), state); +} + +pub fn hash_frequency(value: &Frequency, state: &mut H) { + hash_float::(&value.get::(), state); +} + +pub fn hash_linear_mass_density(value: &LinearMassDensity, state: &mut H) { + hash_float::(&value.get::(), state); +} + +pub fn hash_linear_number_density( + value: &LinearNumberDensity, + state: &mut H, +) { + hash_float::(&value.get::(), state); +} /// Hash a list of floats through a list of rounded integer value /// `hash_float_slice<3,_>` means that the values are rounded to the nearest thousandth pub fn hash_float_slice(value: &[f64], state: &mut H) { diff --git a/editoast/editoast_common/src/lib.rs b/editoast/editoast_common/src/lib.rs index dac28d76abf..8c51442b162 100644 --- a/editoast/editoast_common/src/lib.rs +++ b/editoast/editoast_common/src/lib.rs @@ -7,7 +7,13 @@ pub mod units; pub use hash_rounded_float::hash_acceleration; pub use hash_rounded_float::hash_float; pub use hash_rounded_float::hash_float_slice; +pub use hash_rounded_float::hash_force; +pub use hash_rounded_float::hash_frequency; pub use hash_rounded_float::hash_length; +pub use hash_rounded_float::hash_linear_mass_density; +pub use hash_rounded_float::hash_linear_number_density; +pub use hash_rounded_float::hash_mass; +pub use hash_rounded_float::hash_mass_rate; pub use hash_rounded_float::hash_velocity; schemas! { diff --git a/editoast/editoast_common/src/units.rs b/editoast/editoast_common/src/units.rs index 62792f930e1..7abc4cdc5c5 100644 --- a/editoast/editoast_common/src/units.rs +++ b/editoast/editoast_common/src/units.rs @@ -35,7 +35,10 @@ //! ``` /// Re-export the Quantities that are used in OSRD -pub use uom::si::f64::{Acceleration, Length, Velocity}; +pub use uom::si::f64::{ + Acceleration, Force, Frequency, Length, LinearMassDensity, LinearNumberDensity, Mass, MassRate, + Velocity, +}; macro_rules! quantity_to_path { (Length, $unit:ident) => { @@ -47,6 +50,24 @@ macro_rules! quantity_to_path { (Acceleration, $unit:ident) => { uom::si::acceleration::$unit }; + (Mass, $unit:ident) => { + uom::si::mass::$unit + }; + (Force, $unit:ident) => { + uom::si::force::$unit + }; + (MassRate, $unit:ident) => { + uom::si::mass_rate::$unit + }; + (Frequency, $unit:ident) => { + uom::si::frequency::$unit + }; + (LinearMassDensity, $unit:ident) => { + uom::si::linear_mass_density::$unit + }; + (LinearNumberDensity, $unit:ident) => { + uom::si::linear_number_density::$unit + }; } macro_rules! define_unit { @@ -104,8 +125,15 @@ macro_rules! define_unit { }; } +// Any new value here must also be added in editoast_derive/src/annotate_units.rs define_unit!(meter, Length); define_unit!(millimeter, Length); define_unit!(meter_per_second, Velocity); define_unit!(kilometer_per_hour, Velocity); define_unit!(meter_per_second_squared, Acceleration); +define_unit!(kilogram, Mass); +define_unit!(newton, Force); +define_unit!(kilogram_per_second, MassRate); +define_unit!(hertz, Frequency); +define_unit!(kilogram_per_meter, LinearMassDensity); +define_unit!(per_meter, LinearNumberDensity); diff --git a/editoast/editoast_derive/src/annotate_units.rs b/editoast/editoast_derive/src/annotate_units.rs index 17930fa6edb..0ae53065604 100644 --- a/editoast/editoast_derive/src/annotate_units.rs +++ b/editoast/editoast_derive/src/annotate_units.rs @@ -4,12 +4,18 @@ use quote::quote; use syn::{parse_quote, DeriveInput, LitStr}; pub fn get_abbreviation(value: String) -> Option<&'static str> { + // Any new value here must also be added in editoast_common/src/units.rs match value.replace("::option", "").as_str() { "meter" => Some("Length in m"), "millimeter" => Some("Length in mm"), "meter_per_second" => Some("Velocity in m·s⁻¹"), "kilometer_per_hour" => Some("Velocity in km·h⁻¹"), "meter_per_second_squared" => Some("Acceleration in m·s⁻²"), + "kilogram" => Some("Mass in kg"), + "newton" => Some("Force in N"), + "hertz" => Some("Viscosity friction in N/(m·s⁻1) = s⁻¹"), + "kilogram_per_meter" => Some("Aerodynamic drag in N/(m·s⁻1)² = kg·m⁻¹"), + "per_meter" => Some("Aerodynamic drag per kg in (N/kg)/(m/s)² = m⁻¹"), _ => None, } } diff --git a/editoast/editoast_schemas/Cargo.toml b/editoast/editoast_schemas/Cargo.toml index e033bfdf4fe..154a97ec6c4 100644 --- a/editoast/editoast_schemas/Cargo.toml +++ b/editoast/editoast_schemas/Cargo.toml @@ -8,6 +8,7 @@ edition.workspace = true chrono.workspace = true derivative.workspace = true editoast_common.workspace = true +editoast_derive.workspace = true enum-map.workspace = true geojson.workspace = true iso8601 = "0.6.1" diff --git a/editoast/editoast_schemas/src/rolling_stock.rs b/editoast/editoast_schemas/src/rolling_stock.rs index e64a3bcd108..2a9e381f0d5 100644 --- a/editoast/editoast_schemas/src/rolling_stock.rs +++ b/editoast/editoast_schemas/src/rolling_stock.rs @@ -67,8 +67,8 @@ pub struct RollingStock { // under ETCS/ERTMS signaling system in m/s^2 pub const_gamma: f64, pub inertia_coefficient: f64, - /// In kg - pub mass: f64, + #[serde(with = "kilogram")] + pub mass: Mass, pub rolling_resistance: RollingResistance, pub loading_gauge: LoadingGaugeType, /// Mapping of power restriction code to power class diff --git a/editoast/editoast_schemas/src/rolling_stock/rolling_resistance.rs b/editoast/editoast_schemas/src/rolling_stock/rolling_resistance.rs index 781c1b37caf..8a19a840f45 100644 --- a/editoast/editoast_schemas/src/rolling_stock/rolling_resistance.rs +++ b/editoast/editoast_schemas/src/rolling_stock/rolling_resistance.rs @@ -1,4 +1,5 @@ use derivative::Derivative; +use editoast_common::units::*; use serde::Deserialize; use serde::Serialize; use utoipa::ToSchema; @@ -8,6 +9,7 @@ editoast_common::schemas! { RollingResistancePerWeight, } +#[editoast_derive::annotate_units] #[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize, ToSchema, Derivative)] #[derivative(Hash)] #[serde(deny_unknown_fields)] @@ -16,16 +18,20 @@ pub struct RollingResistance { #[serde(rename = "type")] pub rolling_resistance_type: String, /// Solid friction in N - #[derivative(Hash(hash_with = "editoast_common::hash_float::<5,_>"))] - pub A: f64, - /// Viscosity friction in N/(m/s) - #[derivative(Hash(hash_with = "editoast_common::hash_float::<5,_>"))] - pub B: f64, - /// Aerodynamic drag in N/(m/s)² - #[derivative(Hash(hash_with = "editoast_common::hash_float::<5,_>"))] - pub C: f64, + #[derivative(Hash(hash_with = "editoast_common::hash_force::<5,_>"))] + #[serde(with = "newton")] + pub A: Force, + /// Viscosity friction in N/(m/s) - N = kg⋅m⋅s−2 => viscosity friction kg/s + #[derivative(Hash(hash_with = "editoast_common::hash_mass_rate::<5,_>"))] + #[serde(with = "kilogram_per_second")] + pub B: MassRate, + /// Aerodynamic drag in N/(m/s)² => kg·m⁻¹ + #[derivative(Hash(hash_with = "editoast_common::hash_linear_mass_density::<5,_>"))] + #[serde(with = "kilogram_per_meter")] + pub C: LinearMassDensity, } +#[editoast_derive::annotate_units] #[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize, ToSchema, Derivative)] #[derivative(Hash)] #[serde(deny_unknown_fields)] @@ -33,13 +39,16 @@ pub struct RollingResistance { pub struct RollingResistancePerWeight { #[serde(rename = "type")] pub rolling_resistance_type: String, - /// Solid friction in N/kg - #[derivative(Hash(hash_with = "editoast_common::hash_float::<5,_>"))] - pub A: f64, - /// Viscosity friction in (N/kg)/(m/s) - #[derivative(Hash(hash_with = "editoast_common::hash_float::<5,_>"))] - pub B: f64, - /// Aerodynamic drag in (N/kg)/(m/s)² - #[derivative(Hash(hash_with = "editoast_common::hash_float::<5,_>"))] - pub C: f64, + /// Solid friction in N/kg -- N = kg⋅m⋅s⁻² + #[derivative(Hash(hash_with = "editoast_common::hash_acceleration::<5,_>"))] + #[serde(with = "meter_per_second_squared")] + pub A: Acceleration, + /// Viscosity friction in (N/kg)/(m/s) — N = kg⋅m⋅s−2 => 1/s + #[derivative(Hash(hash_with = "editoast_common::hash_frequency::<5,_>"))] + #[serde(with = "hertz")] + pub B: Frequency, + /// Aerodynamic drag per kg in (N/kg)/(m/s)² => m⁻¹ + #[derivative(Hash(hash_with = "editoast_common::hash_linear_number_density::<5,_>"))] + #[serde(with = "per_meter")] + pub C: LinearNumberDensity, } diff --git a/editoast/editoast_schemas/src/rolling_stock/towed_rolling_stock.rs b/editoast/editoast_schemas/src/rolling_stock/towed_rolling_stock.rs index 21221776eff..369ff761dcc 100644 --- a/editoast/editoast_schemas/src/rolling_stock/towed_rolling_stock.rs +++ b/editoast/editoast_schemas/src/rolling_stock/towed_rolling_stock.rs @@ -6,8 +6,8 @@ pub struct TowedRollingStock { pub name: String, pub label: String, pub railjson_version: String, - /// In kg - pub mass: f64, + #[serde(with = "kilogram")] + pub mass: Mass, #[serde(with = "meter")] pub length: Length, #[serde(with = "meter_per_second_squared")] @@ -19,6 +19,6 @@ pub struct TowedRollingStock { /// The constant gamma braking coefficient used when NOT circulating /// under ETCS/ERTMS signaling system in m/s^2 pub const_gamma: f64, - #[serde(with = "meter_per_second::option")] + #[serde(default, with = "meter_per_second::option")] pub max_speed: Option, } diff --git a/editoast/src/core/simulation.rs b/editoast/src/core/simulation.rs index b6e95206d5d..dd66c9bc08f 100644 --- a/editoast/src/core/simulation.rs +++ b/editoast/src/core/simulation.rs @@ -48,7 +48,7 @@ pub struct PhysicsConsist { #[serde(with = "meter_per_second")] pub max_speed: Velocity, // Time in ms - pub startup_time: u64, + pub startup_time: u64, //TODOUOM #[derivative(Hash(hash_with = "editoast_common::hash_acceleration::<5,_>"))] #[serde(with = "meter_per_second_squared")] pub startup_acceleration: Acceleration, @@ -61,8 +61,10 @@ pub struct PhysicsConsist { pub const_gamma: f64, #[derivative(Hash(hash_with = "editoast_common::hash_float::<5,_>"))] pub inertia_coefficient: f64, - /// Mass of the rolling stock in kg - pub mass: u64, + /// Mass of the rolling stock + #[derivative(Hash(hash_with = "editoast_common::hash_mass::<5,_>"))] + #[serde(with = "kilogram")] + pub mass: Mass, pub rolling_resistance: RollingResistance, /// Mapping of power restriction code to power class #[serde(default)] @@ -77,11 +79,8 @@ pub struct PhysicsConsist { #[derive(Debug, Clone)] pub struct PhysicsConsistParameters { - /// In kg - pub total_mass: Option, - /// In m + pub total_mass: Option, pub total_length: Option, - /// In m/s pub max_speed: Option, pub towed_rolling_stock: Option, pub traction_engine: RollingStock, @@ -156,23 +155,21 @@ impl PhysicsConsistParameters { let traction_engine_inertia = self.traction_engine.mass * self.traction_engine.inertia_coefficient; let towed_inertia = towed_mass * towed_rolling_stock.inertia_coefficient; - (traction_engine_inertia + towed_inertia) / total_mass + ((traction_engine_inertia + towed_inertia) / total_mass).get::() } else { self.traction_engine.inertia_coefficient } } - pub fn compute_mass(&self) -> u64 { + pub fn compute_mass(&self) -> Mass { let traction_engine_mass = self.traction_engine.mass; let towed_rolling_stock_mass = self .towed_rolling_stock .as_ref() .map(|trs| trs.mass) - .unwrap_or(0.0); - let mass = self - .total_mass - .unwrap_or(traction_engine_mass + towed_rolling_stock_mass); - mass.round() as u64 + .unwrap_or_default(); + self.total_mass + .unwrap_or(traction_engine_mass + towed_rolling_stock_mass) } pub fn compute_rolling_resistance(&self) -> RollingResistance { @@ -520,7 +517,7 @@ mod tests { fn create_physics_consist() -> PhysicsConsistParameters { PhysicsConsistParameters { total_length: Some(meter::new(100.0)), - total_mass: Some(50000.0), + total_mass: Some(kilogram::new(50000.0)), max_speed: Some(meter_per_second::new(22.0)), towed_rolling_stock: Some(create_towed_rolling_stock()), traction_engine: create_simple_rolling_stock(), @@ -549,20 +546,20 @@ mod tests { #[test] fn physics_consist_compute_mass() { let mut physics_consist = create_physics_consist(); - physics_consist.total_mass = Some(50000.0); // kg - physics_consist.traction_engine.mass = 15000.0; // kg + physics_consist.total_mass = Some(kilogram::new(50000.0)); + physics_consist.traction_engine.mass = kilogram::new(15000.0); // We always take total_mass - assert_eq!(physics_consist.compute_mass(), 50000); + assert_eq!(physics_consist.compute_mass(), kilogram::new(50000.)); physics_consist.total_mass = None; // When no total_mass we take towed mass + traction_engine mass - assert_eq!(physics_consist.compute_mass(), 65000); + assert_eq!(physics_consist.compute_mass(), kilogram::new(65000.)); physics_consist.total_mass = None; physics_consist.towed_rolling_stock = None; // When no user specified mass and towed rolling stock, we take traction_engine mass - assert_eq!(physics_consist.compute_mass(), 15000); + assert_eq!(physics_consist.compute_mass(), kilogram::new(15000.)); } #[test] @@ -592,16 +589,16 @@ mod tests { meter_per_second::new(24.0) ); - physics_consist.traction_engine.max_speed = Velocity::new::(40.0); // m/s + physics_consist.traction_engine.max_speed = meter_per_second::new(40.0); // m/s assert_eq!( physics_consist.compute_max_speed(), - Velocity::new::(35.0) + meter_per_second::new(35.0) ); physics_consist.towed_rolling_stock = None; assert_eq!( physics_consist.compute_max_speed(), - Velocity::new::(40.0) + meter_per_second::new(40.0) ); } @@ -657,9 +654,9 @@ mod tests { physics_consist.compute_rolling_resistance(), RollingResistance { rolling_resistance_type: "davis".to_string(), - A: 35001.0, - B: 350.01, - C: 7.0005, + A: newton::new(35001.0), + B: kilogram_per_second::new(350.01), + C: kilogram_per_meter::new(7.0005), } ); diff --git a/editoast/src/models/fixtures.rs b/editoast/src/models/fixtures.rs index 1eff6415e47..ca5f13af3e5 100644 --- a/editoast/src/models/fixtures.rs +++ b/editoast/src/models/fixtures.rs @@ -228,16 +228,16 @@ pub fn create_towed_rolling_stock() -> TowedRollingStock { TowedRollingStock { name: "TOWED_ROLLING_STOCK".to_string(), label: "towed".to_string(), - mass: 50000.0, // kg + mass: kilogram::new(50000.0), length: meter::new(30.0), comfort_acceleration: meter_per_second_squared::new(0.2), startup_acceleration: meter_per_second_squared::new(0.06), inertia_coefficient: 1.05, rolling_resistance: RollingResistancePerWeight { rolling_resistance_type: "davis".to_string(), - A: 1.0, // In N - B: 0.01, // In N/(m/s) - C: 0.0002, // In N/(m/s)² + A: meter_per_second_squared::new(1.0), // In N/kg + B: hertz::new(0.01), // In N/kg/(m/s) + C: per_meter::new(0.0002), // In N/kg/(m/s)² }, const_gamma: 0.5, max_speed: Some(meter_per_second::new(35.0)), @@ -266,12 +266,12 @@ pub fn create_simple_rolling_stock() -> RollingStock { railjson_version: "12".to_string(), rolling_resistance: RollingResistance { rolling_resistance_type: "davis".to_string(), - A: 1.0, // In N - B: 0.01, // In N/(m/s) - C: 0.0005, // In N/(m/s)² + A: newton::new(1.0), // In N + B: kilogram_per_second::new(0.01), // In N/(m/s) + C: kilogram_per_meter::new(0.0005), // In N/(m/s)² }, length: meter::new(140.0), - mass: 15000.0, // kg + mass: kilogram::new(15000.0), max_speed: meter_per_second::new(20.0), } } diff --git a/editoast/src/models/rolling_stock_model.rs b/editoast/src/models/rolling_stock_model.rs index a5effdf9266..5e21acc2e5d 100644 --- a/editoast/src/models/rolling_stock_model.rs +++ b/editoast/src/models/rolling_stock_model.rs @@ -57,7 +57,9 @@ pub struct RollingStockModel { pub inertia_coefficient: f64, #[schema(required)] pub base_power_class: Option, - pub mass: f64, + #[serde(with = "kilogram")] + #[model(uom_unit = "uom::si::mass::kilogram")] + pub mass: Mass, #[model(json)] pub rolling_resistance: RollingResistance, #[model(to_enum)] diff --git a/editoast/src/models/towed_rolling_stock.rs b/editoast/src/models/towed_rolling_stock.rs index c0336948059..d55ad4865e6 100644 --- a/editoast/src/models/towed_rolling_stock.rs +++ b/editoast/src/models/towed_rolling_stock.rs @@ -23,10 +23,10 @@ pub struct TowedRollingStockModel { pub railjson_version: String, pub locked: bool, - /// In kg - pub mass: f64, - pub length: f64, - /// In km/h + #[serde(with = "kilogram")] + #[model(uom_unit = "uom::si::mass::kilogram")] + pub mass: Mass, + pub length: f64, //TODOUOM pub max_speed: Option, pub comfort_acceleration: f64, pub startup_acceleration: f64, diff --git a/editoast/src/views/rolling_stock/form.rs b/editoast/src/views/rolling_stock/form.rs index 7a833ba0989..b5dc9f68ba7 100644 --- a/editoast/src/views/rolling_stock/form.rs +++ b/editoast/src/views/rolling_stock/form.rs @@ -38,7 +38,8 @@ pub struct RollingStockForm { pub comfort_acceleration: Acceleration, pub const_gamma: f64, pub inertia_coefficient: f64, - pub mass: f64, + #[serde(with = "kilogram")] + pub mass: Mass, pub rolling_resistance: RollingResistance, pub loading_gauge: LoadingGaugeType, /// Mapping of power restriction code to power class diff --git a/editoast/src/views/rolling_stock/light.rs b/editoast/src/views/rolling_stock/light.rs index 10eb00eeb53..ca361eae9f7 100644 --- a/editoast/src/views/rolling_stock/light.rs +++ b/editoast/src/views/rolling_stock/light.rs @@ -227,7 +227,8 @@ struct LightRollingStock { comfort_acceleration: Acceleration, const_gamma: f64, inertia_coefficient: f64, - mass: f64, + #[serde(with = "kilogram")] + mass: Mass, rolling_resistance: RollingResistance, loading_gauge: LoadingGaugeType, metadata: Option, diff --git a/editoast/src/views/rolling_stock/towed.rs b/editoast/src/views/rolling_stock/towed.rs index fa4a9eea694..d9307f14b9b 100644 --- a/editoast/src/views/rolling_stock/towed.rs +++ b/editoast/src/views/rolling_stock/towed.rs @@ -15,6 +15,7 @@ use axum::Extension; use axum::Json; use diesel_async::scoped_futures::ScopedFutureExt as _; use editoast_authz::BuiltinRole; +use editoast_common::units::*; use editoast_derive::EditoastError; use editoast_models::DbConnectionPoolV2; use editoast_schemas::rolling_stock::RollingResistancePerWeight; @@ -44,6 +45,7 @@ editoast_common::schemas! { TowedRollingStockLockedForm, } +#[editoast_derive::annotate_units] #[derive(Debug, Serialize, ToSchema)] #[cfg_attr(test, derive(serde::Deserialize, PartialEq))] struct TowedRollingStock { @@ -53,9 +55,10 @@ struct TowedRollingStock { railjson_version: String, locked: bool, - mass: f64, + #[serde(with = "kilogram")] + mass: Mass, length: f64, - comfort_acceleration: f64, + comfort_acceleration: f64, //TODOUOM startup_acceleration: f64, inertia_coefficient: f64, rolling_resistance: RollingResistancePerWeight, @@ -94,13 +97,15 @@ pub enum TowedRollingStockError { IsLocked { towed_rolling_stock_id: i64 }, } +#[editoast_derive::annotate_units] #[derive(Debug, Clone, Deserialize, Serialize, ToSchema)] pub struct TowedRollingStockForm { pub name: String, pub label: String, pub locked: bool, - pub mass: f64, + #[serde(with = "kilogram")] + pub mass: Mass, pub length: f64, pub comfort_acceleration: f64, pub startup_acceleration: f64, @@ -360,6 +365,7 @@ mod tests { use crate::views::test_app::TestApp; use crate::views::test_app::TestAppBuilder; use axum::http::StatusCode; + use editoast_common::units::*; use rstest::rstest; use serde_json::json; use uuid::Uuid; @@ -463,7 +469,7 @@ mod tests { let mut towed_rolling_stock = create_towed_rolling_stock(&app, &name, UNLOCKED); let id = towed_rolling_stock.id; - towed_rolling_stock.mass = 13000.0; + towed_rolling_stock.mass = kilogram::new(13000.0); let updated_towed_rolling_stock: TowedRollingStock = app .fetch( app.patch(&format!("/towed_rolling_stock/{id}")) @@ -473,7 +479,7 @@ mod tests { .json_into(); assert_eq!(updated_towed_rolling_stock.name, name); - assert_eq!(updated_towed_rolling_stock.mass, 13000.0); + assert_eq!(updated_towed_rolling_stock.mass, kilogram::new(13000.0)); } #[rstest] @@ -496,7 +502,7 @@ mod tests { let mut towed_rolling_stock = create_towed_rolling_stock(&app, &name, LOCKED); let id = towed_rolling_stock.id; - towed_rolling_stock.mass = 13000.0; + towed_rolling_stock.mass = kilogram::new(13000.0); app.fetch( app.patch(&format!("/towed_rolling_stock/{id}")) .json(&towed_rolling_stock), @@ -512,7 +518,7 @@ mod tests { let mut towed_rolling_stock = create_towed_rolling_stock(&app, &name, LOCKED); let id = towed_rolling_stock.id; - towed_rolling_stock.mass = 13000.0; + towed_rolling_stock.mass = kilogram::new(13000.0); app.fetch( app.patch(&format!("/towed_rolling_stock/{id}/locked")) .json(&json!({ "locked": false })), diff --git a/editoast/src/views/timetable/stdcm.rs b/editoast/src/views/timetable/stdcm.rs index 5ff71bfaecd..f7604caa84c 100644 --- a/editoast/src/views/timetable/stdcm.rs +++ b/editoast/src/views/timetable/stdcm.rs @@ -484,11 +484,6 @@ mod tests { use rstest::rstest; use serde_json::json; use std::str::FromStr; - use uom::si::acceleration::meter_per_second_squared; - use uom::si::f64::{Acceleration, Length, Velocity}; - use uom::si::length::meter; - use uom::si::length::millimeter; - use uom::si::velocity::meter_per_second; use uuid::Uuid; use crate::core::conflict_detection::Conflict; @@ -514,21 +509,21 @@ mod tests { #[test] fn simulation_with_towed_rolling_stock_parameters() { let mut rolling_stock = create_simple_rolling_stock(); - rolling_stock.mass = 100000.0; + rolling_stock.mass = kilogram::new(100000.0); rolling_stock.length = meter::new(20.0); rolling_stock.inertia_coefficient = 1.10; // m/s² rolling_stock.comfort_acceleration = meter_per_second_squared::new(0.1); rolling_stock.startup_acceleration = meter_per_second_squared::new(0.04); rolling_stock.rolling_resistance = RollingResistance { rolling_resistance_type: "davis".to_string(), - A: 1.0, - B: 0.01, - C: 0.0005, + A: newton::new(1.0), + B: kilogram_per_second::new(0.01), + C: kilogram_per_meter::new(0.0005), }; let towed_rolling_stock = create_towed_rolling_stock(); - let total_mass = 200000.0; + let total_mass = kilogram::new(200000.0); let simulation_parameters = PhysicsConsistParameters { total_length: None, @@ -540,7 +535,7 @@ mod tests { let physics_consist: PhysicsConsist = simulation_parameters.into(); - assert_eq!(physics_consist.mass, total_mass as u64); + assert_eq!(physics_consist.mass, total_mass); assert_eq!(physics_consist.inertia_coefficient, 1.075_f64); @@ -548,9 +543,9 @@ mod tests { physics_consist.rolling_resistance, RollingResistance { rolling_resistance_type: "davis".to_string(), - A: 100001.0, - B: 1000.01, - C: 20.0005 + A: newton::new(100001.0), + B: kilogram_per_second::new(1000.01), + C: kilogram_per_meter::new(20.0005), } ); } @@ -558,7 +553,7 @@ mod tests { #[test] fn simulation_with_parameters() { let simulation_parameters = PhysicsConsistParameters { - total_mass: Some(123.0), + total_mass: Some(kilogram::new(123.0)), total_length: Some(meter::new(455.0)), max_speed: Some(meter_per_second::new(10.0)), towed_rolling_stock: None, @@ -567,7 +562,7 @@ mod tests { let physics_consist: PhysicsConsist = simulation_parameters.into(); - assert_eq!(physics_consist.mass, 123_u64); + assert_eq!(physics_consist.mass, kilogram::new(123.0)); assert_eq!(physics_consist.length, millimeter::new(455000.0)); // It should be converted in mm assert_eq!(physics_consist.max_speed, meter_per_second::new(10_f64)); // It should be in m/s } @@ -579,7 +574,7 @@ mod tests { let physics_consist: PhysicsConsist = simulation_parameters.into(); - assert_eq!(physics_consist.mass, 15000_u64); + assert_eq!(physics_consist.mass, kilogram::new(15000.0)); assert_eq!(physics_consist.length, millimeter::new(140000.)); // It should be converted in mm assert_eq!(physics_consist.max_speed, meter_per_second::new(20_f64)); } diff --git a/editoast/src/views/timetable/stdcm/request.rs b/editoast/src/views/timetable/stdcm/request.rs index e7d854b1e77..72945b9608d 100644 --- a/editoast/src/views/timetable/stdcm/request.rs +++ b/editoast/src/views/timetable/stdcm/request.rs @@ -104,14 +104,15 @@ pub(super) struct Request { #[serde(default)] #[schema(value_type = Option, example = json!(["5%", "2min/100km"]))] pub(super) margin: Option, - /// Total mass of the consist in kg - #[validate(range(exclusive_min = 0.0))] - pub(super) total_mass: Option, + /// Total mass of the consist + //#[validate(range(exclusive_min = 0.0))] TODOUOM + #[serde(default, with = "kilogram::option")] + pub(super) total_mass: Option, /// Total length of the consist in meters - #[serde(with = "meter::option")] + #[serde(default, with = "meter::option")] pub(super) total_length: Option, /// Maximum speed of the consist in km/h - #[serde(with = "kilometer_per_hour::option")] + #[serde(default, with = "kilometer_per_hour::option")] pub(super) max_speed: Option, pub(super) loading_gauge_type: Option, }