Skip to content
Draft
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
54 changes: 31 additions & 23 deletions altrios-core/src/consist/consist_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,8 @@ impl Consist {
pub fn solve_energy_consumption(
&mut self,
pwr_out_req: si::Power,
train_mass: Option<si::Mass>,
train_speed: Option<si::Velocity>,
train_mass: si::Mass,
train_speed: si::Velocity,
dt: si::Time,
engine_on: Option<bool>,
) -> anyhow::Result<()> {
Expand Down Expand Up @@ -567,18 +567,24 @@ impl Default for Consist {
impl LocoTrait for Consist {
fn set_curr_pwr_max_out(
&mut self,
pwr_aux: Option<si::Power>,
pwr_aux: si::Power,
elev_and_temp: Option<(si::Length, si::ThermodynamicTemperature)>,
train_mass: Option<si::Mass>,
train_speed: Option<si::Velocity>,
train_mass: si::Mass,
train_speed: si::Velocity,
speed_limit_lookahead: (si::Velocity, si::Velocity),
elev_lookahead: (si::Length, si::Length),
dt: si::Time,
) -> anyhow::Result<()> {
// TODO: this will need to account for catenary power
// TODO: need to be able to configure regen to go to catenary or not
// TODO: make sure that self.state includes catenary effects so that `solve_energy_consumption`
// is operating with the same catenary power availability at the train position for which this
// method is called
ensure!(pwr_aux.is_none(), format_dbg!(pwr_aux.is_none()));
ensure!(
pwr_aux == si::Power::ZERO,
"{} should be zero",
format_dbg!(pwr_aux)
);

// calculate mass assigned to each locomotive such that the buffer
// calculations can be based on mass weighted proportionally to the
Expand All @@ -591,25 +597,27 @@ impl LocoTrait for Consist {
});
for (i, loco) in self.loco_vec.iter_mut().enumerate() {
// assign locomotive-specific mass for hybrid controls
let mass: Option<si::Mass> = if res_total_usable_energy > si::Energy::ZERO {
train_mass.map(|tm| {
loco.reversible_energy_storage()
.map(|res| res.energy_capacity_usable())
.unwrap_or(si::Energy::ZERO)
/ res_total_usable_energy
* tm
})
let mass: si::Mass = if res_total_usable_energy > si::Energy::ZERO {
loco.reversible_energy_storage()
.map(|res| res.energy_capacity_usable())
.unwrap_or(si::Energy::ZERO)
/ res_total_usable_energy
* train_mass
} else {
None
si::Mass::ZERO
};
loco.set_curr_pwr_max_out(None, elev_and_temp, mass, train_speed, dt)
.map_err(|err| {
err.context(format!(
"loco idx: {} loco type: {}",
i,
loco.loco_type.to_string()
))
})?;
loco.set_curr_pwr_max_out(
Default::default(),
elev_and_temp,
mass,
train_speed,
speed_limit_lookahead,
elev_lookahead,
dt,
)
.with_context(|| {
format!("loco idx: {} loco type: {}", i, loco.loco_type.to_string())
})?;
}
self.state.pwr_out_max.update(
{
Expand Down
20 changes: 14 additions & 6 deletions altrios-core/src/consist/consist_sim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,24 @@ impl ConsistSimulation {
self.loco_con
.set_pwr_aux(Some(true))
.with_context(|| format_dbg!())?;
let train_mass = self.power_trace.train_mass;
let train_mass = self.power_trace.train_mass.unwrap_or_default();
let i = *self.loco_con.state.i.get_fresh(|| format_dbg!())?;
let train_speed = if !self.power_trace.train_speed.is_empty() {
Some(self.power_trace.train_speed[i])
self.power_trace.train_speed[i]
} else {
None
Default::default()
};
let dt = self.power_trace.dt_at_i(i).with_context(|| format_dbg!())?;
self.loco_con
.set_curr_pwr_max_out(None, None, train_mass, train_speed, dt)
.set_curr_pwr_max_out(
Default::default(),
Default::default(),
train_mass,
train_speed,
Default::default(), // TODO: make arrays so that this value can be piped in
Default::default(), // TODO: make arrays so that this value can be piped in
dt,
)
.with_context(|| format_dbg!())?;
self.solve_energy_consumption(
self.power_trace.pwr[*self.loco_con.state.i.get_fresh(|| format_dbg!())?],
Expand Down Expand Up @@ -132,8 +140,8 @@ impl ConsistSimulation {
pub fn solve_energy_consumption(
&mut self,
pwr_out_req: si::Power,
train_mass: Option<si::Mass>,
train_speed: Option<si::Velocity>,
train_mass: si::Mass,
train_speed: si::Velocity,
dt: si::Time,
) -> anyhow::Result<()> {
self.loco_con.solve_energy_consumption(
Expand Down
54 changes: 29 additions & 25 deletions altrios-core/src/consist/consist_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ pub trait LocoTrait {
/// - `elev_and_temp`: elevation and temperature
/// - `train_speed`: current train speed
/// - `train_mass`: portion of total train mass handled by `self`
/// - `speed_limit_lookahead`: min anx max speed limit within lookahead distance,
/// - `elev_lookahead`: min anx max elevation within lookahead distance,
/// - `dt`: time step size
fn set_curr_pwr_max_out(
&mut self,
pwr_aux: Option<si::Power>,
pwr_aux: si::Power,
elev_and_temp: Option<(si::Length, si::ThermodynamicTemperature)>,
train_mass: Option<si::Mass>,
train_speed: Option<si::Velocity>,
train_mass: si::Mass,
train_speed: si::Velocity,
speed_limit_lookahead: (si::Velocity, si::Velocity),
elev_lookahead: (si::Length, si::Length),
dt: si::Time,
) -> anyhow::Result<()>;
/// Get energy loss in components
Expand Down Expand Up @@ -58,15 +62,15 @@ pub trait SolvePower {
&mut self,
loco_vec: &[Locomotive],
state: &ConsistState,
train_mass: Option<si::Mass>,
train_speed: Option<si::Velocity>,
train_mass: si::Mass,
train_speed: si::Velocity,
) -> anyhow::Result<Vec<si::Power>>;
fn solve_negative_traction(
&mut self,
loco_vec: &[Locomotive],
state: &ConsistState,
train_mass: Option<si::Mass>,
train_speed: Option<si::Velocity>,
train_mass: si::Mass,
train_speed: si::Velocity,
) -> anyhow::Result<Vec<si::Power>>;
}

Expand All @@ -80,8 +84,8 @@ impl SolvePower for RESGreedy {
&mut self,
loco_vec: &[Locomotive],
state: &ConsistState,
_train_mass: Option<si::Mass>,
_train_speed: Option<si::Velocity>,
_train_mass: si::Mass,
_train_speed: si::Velocity,
) -> anyhow::Result<Vec<si::Power>> {
let loco_pwr_out_vec: Vec<si::Power> = if *state
.pwr_out_deficit
Expand Down Expand Up @@ -152,8 +156,8 @@ impl SolvePower for RESGreedy {
&mut self,
loco_vec: &[Locomotive],
state: &ConsistState,
train_mass: Option<si::Mass>,
train_speed: Option<si::Velocity>,
train_mass: si::Mass,
train_speed: si::Velocity,
) -> anyhow::Result<Vec<si::Power>> {
solve_negative_traction(loco_vec, state, train_mass, train_speed)
}
Expand Down Expand Up @@ -187,8 +191,8 @@ fn get_pwr_regen_vec(
fn solve_negative_traction(
loco_vec: &[Locomotive],
consist_state: &ConsistState,
_train_mass: Option<si::Mass>,
_train_speed: Option<si::Velocity>,
_train_mass: si::Mass,
_train_speed: si::Velocity,
) -> anyhow::Result<Vec<si::Power>> {
// positive during any kind of negative traction event
let pwr_brake_req = -*consist_state.pwr_out_req.get_fresh(|| format_dbg!())?;
Expand Down Expand Up @@ -262,8 +266,8 @@ impl SolvePower for Proportional {
&mut self,
loco_vec: &[Locomotive],
state: &ConsistState,
_train_mass: Option<si::Mass>,
_train_speed: Option<si::Velocity>,
_train_mass: si::Mass,
_train_speed: si::Velocity,
) -> anyhow::Result<Vec<si::Power>> {
todo!("this need some attention to make sure it handles the hybrid correctly");
let mut loco_pwr_vec: Vec<si::Power> = vec![];
Expand All @@ -282,8 +286,8 @@ impl SolvePower for Proportional {
&mut self,
loco_vec: &[Locomotive],
state: &ConsistState,
train_mass: Option<si::Mass>,
train_speed: Option<si::Velocity>,
train_mass: si::Mass,
train_speed: si::Velocity,
) -> anyhow::Result<Vec<si::Power>> {
todo!("this need some attention to make sure it handles the hybrid correctly");
solve_negative_traction(loco_vec, state, train_mass, train_speed)
Expand All @@ -300,8 +304,8 @@ impl SolvePower for FrontAndBack {
&mut self,
_loco_vec: &[Locomotive],
_state: &ConsistState,
_train_mass: Option<si::Mass>,
_train_speed: Option<si::Velocity>,
_train_mass: si::Mass,
_train_speed: si::Velocity,
) -> anyhow::Result<Vec<si::Power>> {
todo!() // not needed urgently
}
Expand All @@ -310,8 +314,8 @@ impl SolvePower for FrontAndBack {
&mut self,
_loco_vec: &[Locomotive],
_state: &ConsistState,
_train_mass: Option<si::Mass>,
_train_speed: Option<si::Velocity>,
_train_mass: si::Mass,
_train_speed: si::Velocity,
) -> anyhow::Result<Vec<si::Power>> {
todo!() // not needed urgently
}
Expand All @@ -331,8 +335,8 @@ impl SolvePower for PowerDistributionControlType {
&mut self,
loco_vec: &[Locomotive],
state: &ConsistState,
train_mass: Option<si::Mass>,
train_speed: Option<si::Velocity>,
train_mass: si::Mass,
train_speed: si::Velocity,
) -> anyhow::Result<Vec<si::Power>> {
match self {
Self::RESGreedy(res_greedy) => {
Expand All @@ -351,8 +355,8 @@ impl SolvePower for PowerDistributionControlType {
&mut self,
loco_vec: &[Locomotive],
state: &ConsistState,
train_mass: Option<si::Mass>,
train_speed: Option<si::Velocity>,
train_mass: si::Mass,
train_speed: si::Velocity,
) -> anyhow::Result<Vec<si::Power>> {
match self {
Self::RESGreedy(res_greedy) => {
Expand Down
Loading
Loading