1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::imports::*;
#[altrios_api(
#[new]
fn __new__(
force_max_newtons: f64,
ramp_up_time_seconds: f64,
ramp_up_coeff: f64,
// recharge_rate_pa_per_sec: f64,
state: Option<FricBrakeState>,
save_interval: Option<usize>,
) -> Self {
Self::new(
force_max_newtons * uc::N,
ramp_up_time_seconds * uc::S,
ramp_up_coeff * uc::R,
// recharge_rate_pa_per_sec,
state,
save_interval,
)
}
)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, HistoryMethods, SerdeAPI)]
pub struct FricBrake {
/// max static force achievable
pub force_max: si::Force,
/// time to go from zero to max braking force
pub ramp_up_time: si::Time,
/// ramp-up correction factor
pub ramp_up_coeff: si::Ratio,
// commented out. This stuff needs refinement but
// added complexity is probably worthwhile
// /// time to go from max braking force to zero braking force
// pub ramp_down_time: si::Time,
// /// rate at which brakes can be recovered after full release
// pub recharge_rate_pa_per_sec: f64,
// TODO: add in whatever is needed to estimate aux load impact
pub state: FricBrakeState,
#[serde(default)]
/// Custom vector of [Self::state]
pub history: FricBrakeStateHistoryVec,
pub save_interval: Option<usize>,
}
impl Default for FricBrake {
fn default() -> Self {
Self {
force_max: 600_000.0 * uc::LBF,
ramp_up_time: 60.0 * uc::S,
ramp_up_coeff: 0.5 * uc::R,
state: Default::default(),
history: Default::default(),
save_interval: Default::default(),
}
}
}
impl FricBrake {
pub fn new(
force_max: si::Force,
ramp_up_time: si::Time,
ramp_up_coeff: si::Ratio,
// recharge_rate_pa_per_sec: f64,
state: Option<FricBrakeState>,
save_interval: Option<usize>,
) -> Self {
let mut state = state.unwrap_or_default();
state.force_max_curr = force_max;
Self {
force_max,
ramp_up_time,
ramp_up_coeff,
// recharge_rate_pa_per_sec,
state,
history: Default::default(),
save_interval,
}
}
pub fn set_cur_force_max_out(&mut self, dt: si::Time) -> anyhow::Result<()> {
// maybe check parameter values here and propagate any errors
self.state.force_max_curr =
(self.state.force + self.force_max / self.ramp_up_time * dt).min(self.force_max);
Ok(())
}
}
// TODO: figure out a way to make the braking reasonably polymorphic (e.g. for autonomous rail
// vehicles)
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, HistoryVec)]
#[altrios_api(
#[new]
fn __new__(
) -> Self {
Self::new()
}
)]
pub struct FricBrakeState {
/// index counter
pub i: usize,
// actual applied force of brakes
pub force: si::Force,
// time-varying max force of brakes in current time step
pub force_max_curr: si::Force,
// pressure: si::Pressure,
}
impl FricBrakeState {
/// TODO: this method needs to accept arguments
pub fn new() -> Self {
Self::default()
}
}
impl Default for FricBrakeState {
fn default() -> Self {
Self {
i: 1,
force: Default::default(),
force_max_curr: Default::default(),
}
}
}