Skip to content

Commit

Permalink
Merge pull request #103 from NREL/fix/make-make_est_times-adaptive
Browse files Browse the repository at this point in the history
`make_est_times` now has adaptive completing threshold
  • Loading branch information
calbaker authored Jan 3, 2025
2 parents ce04dfc + 19c5678 commit ddd1fd3
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 30 deletions.
11 changes: 8 additions & 3 deletions rust/altrios-core/src/meet_pass/est_times/est_time_structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,13 @@ pub(super) struct SavedSim {
impl SavedSim {
/// Step the train sim forward and save appropriate state data in the movement
pub fn update_movement(&mut self, movement: &mut Vec<SimpleState>) -> anyhow::Result<()> {
let condition = |train_sim: &SpeedLimitTrainSim| -> bool {
train_sim.state.offset < train_sim.offset_end() - uc::MI * 5.0
let condition = |train_sim: &mut SpeedLimitTrainSim| -> bool {
let (_, speed_target) = train_sim.braking_points.calc_speeds(
train_sim.state.offset,
train_sim.state.speed,
train_sim.fric_brake.ramp_up_time * train_sim.fric_brake.ramp_up_coeff,
);
speed_target > si::Velocity::ZERO
|| (
train_sim.is_finished()
// this needs to be reconsidered. The issue is determining when SpeedLimitTrainSim is finished.
Expand All @@ -62,7 +67,7 @@ impl SavedSim {
movement.clear();
movement.push(SimpleState::from_train_state(&self.train_sim.state));
// TODO: Tighten up this bound using braking points.
while condition(&self.train_sim) {
while condition(&mut self.train_sim) {
self.train_sim.step()?;
movement.push(SimpleState::from_train_state(&self.train_sim.state));
}
Expand Down
45 changes: 27 additions & 18 deletions rust/altrios-core/src/meet_pass/est_times/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ fn add_new_join_paths(
}

pub fn make_est_times<N: AsRef<[Link]>>(
mut speed_limit_train_sim: SpeedLimitTrainSim,
mut speed_limit_train_sim: SpeedLimitTrainSim,
network: N,
) -> anyhow::Result<(EstTimeNet, Consist)> {
speed_limit_train_sim.set_save_interval(None);
Expand Down Expand Up @@ -667,28 +667,37 @@ pub fn make_est_times<N: AsRef<[Link]>>(
"Link idx next cannot be fake when making est times! link_idx_prev={link_idx_prev:?}"
);

if !link_idx_options.contains(&link_idx_next) {
ensure!(
link_idx_options.contains(&link_idx_next_alt),
"Unexpected end of path reached! prev={link_idx_prev:?}, next={link_idx_next:?}, next_alt={link_idx_next_alt:?}"
);
sim.train_sim
.extend_path(network, &[link_idx_next_alt])
.with_context(|| format_dbg!())?;
} else {
if link_idx_options.contains(&link_idx_next_alt) {
// all of the next links that will allow reaching destination
let link_idxs_next_valid = [link_idx_next, link_idx_next_alt]
.into_iter()
.filter(|link_idx| link_idx_options.contains(link_idx))
.collect::<Vec<_>>();
let link_idx_next = match link_idxs_next_valid[..] {
// extract out the next link that this train will travel on
[link_idx_next] => link_idx_next,
// extract out the next link thit this train will travel on
// and create a new train sim that will travel the alternate branch
[link_idx_next, link_idx_next_alt] => {
let mut new_sim = sim.clone();
new_sim
.train_sim
.extend_path(network, &[link_idx_next_alt])
.with_context(|| format_dbg!())?;
new_sim.check_dests(dests);
saved_sims.push(new_sim);
link_idx_next
}
sim.train_sim
.extend_path(network, &[link_idx_next])
.with_context(|| format_dbg!())?;
}
_ => {
bail!(
"{}
Unexpected end of path reached! prev={link_idx_prev:?}, next={link_idx_next:?}, next_alt={link_idx_next_alt:?}",
format_dbg!()
);
}
};
sim.train_sim
.extend_path(network, &[link_idx_next])
.with_context(|| format_dbg!())?;
sim.check_dests(dests);
}
}
Expand Down Expand Up @@ -733,16 +742,16 @@ pub fn make_est_times<N: AsRef<[Link]>>(
let est_time_next = est_times[est_time.idx_next.idx()];
let est_idx = idx as EstIdx;
// Verify that prev est time is linked to current est time
assert!(est_time_prev.idx_next == est_idx || est_time_prev.idx_next_alt == est_idx);
ensure!(est_time_prev.idx_next == est_idx || est_time_prev.idx_next_alt == est_idx);
// Verify that next est time is linked to current est time
assert!(
ensure!(
est_time_next.idx_prev == est_idx
|| est_time_next.idx_prev_alt == est_idx
|| idx == est_times.len() - 1
);

// Verify that current est time is not the alternate of both the previous and next est times
assert!(
ensure!(
est_time_prev.idx_next_alt != est_idx
|| est_time_next.idx_prev_alt != est_idx
|| idx == 0
Expand Down
1 change: 1 addition & 0 deletions rust/altrios-core/src/track/link/link_idx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use std::io::prelude::*;
/// See [supplementary documentation.](https://nrel.github.io/altrios/doc/rail-network.html)
pub struct LinkIdx {
#[api(skip_set)]
/// index of link within network
idx: u32,
}
pub const LINK_IDX_NA: LinkIdx = LinkIdx { idx: 0 };
Expand Down
13 changes: 7 additions & 6 deletions rust/altrios-core/src/train/braking_point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,16 @@ impl ObjState for BrakingPoint {
#[altrios_api]
pub struct BrakingPoints {
points: Vec<BrakingPoint>,
/// index within [Self::points]
idx_curr: usize,
}

impl BrakingPoints {
/// TODO: complete this doc string
/// Arguments:
/// - offset: si::Length -- ???
/// - speed: si::Velocity -- ???
/// - adj_ramp_up_time: si::Time -- corrected ramp up time to account
/// for approximately linear brake build up
/// - offset: location along the current TPC path since train started moving
/// - speed: current train speed
/// - adj_ramp_up_time: corrected ramp up time to account for approximately
/// linear brake build up
pub fn calc_speeds(
&mut self,
offset: si::Length,
Expand Down Expand Up @@ -64,6 +63,8 @@ impl BrakingPoints {

(self.points[self.idx_curr].speed_limit, speed_target)
}

/// Any time [PathTpc] is updated, everything is recalculated
pub fn recalc(
&mut self,
train_state: &TrainState,
Expand Down
5 changes: 3 additions & 2 deletions rust/altrios-core/src/train/resistance/kind/path_res.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ fn calc_res_val(res_coeff: si::Ratio, state: &TrainState) -> si::Force {
#[altrios_api]
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default, PartialEq, Eq, SerdeAPI)]
pub struct Point {
/// index within corresponding [PathResCoeff]
idx: usize,
}
impl Point {
Expand Down Expand Up @@ -68,9 +69,9 @@ impl [PathResCoeff] {
#[altrios_api]
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default, PartialEq, Eq, SerdeAPI)]
pub struct Strap {
// TODO: figure out if `idx` is reference to link index
// within Network, offset index within Link, or index within PathTpc
/// index of front of train within corresponding [PathResCoeff]
idx_front: usize,
/// index of back of train within corresponding [PathResCoeff]
idx_back: usize,
}

Expand Down
2 changes: 1 addition & 1 deletion rust/altrios-core/src/train/speed_limit_train_sim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ impl SpeedLimitTrainSim {

// calculate the max positive tractive effort. this is the same as set_speed_train_sim
let pwr_pos_max = self.loco_con.state.pwr_out_max.min(si::Power::ZERO.max(
// TODO: the effect of rate may already be accounted for in this snippet
// NOTE: the effect of rate may already be accounted for in this snippet
// from fuel_converter.rs:

// ```
Expand Down

0 comments on commit ddd1fd3

Please sign in to comment.