traffic_sim/vehicle/
acceleration.rs1use std::cell::Cell;
2
3use serde::{Deserialize, Serialize};
4
5const MIN_GAP: f64 = 2.5; const MAX_DECEL: f64 = -6.0; #[derive(Clone, Serialize, Deserialize, Debug)]
13pub struct AccelerationModel {
14 max_acc: f64,
15 comf_dec: f64,
16 acc: Cell<f64>,
17}
18
19pub struct ModelParams {
21 pub max_acceleration: f64,
23 pub comf_deceleration: f64,
25}
26
27impl AccelerationModel {
28 pub fn new(params: &ModelParams) -> Self {
30 AccelerationModel {
31 max_acc: params.max_acceleration,
32 comf_dec: params.comf_deceleration,
33 acc: Cell::new(params.max_acceleration),
34 }
35 }
36
37 pub fn reset(&self) {
39 self.acc.set(self.max_acc);
40 }
41
42 pub fn acc(&self) -> f64 {
44 f64::max(self.acc.get(), MAX_DECEL)
45 }
46
47 pub fn emergency_stop(&self) {
49 self.acc.set(MAX_DECEL);
50 }
51
52 pub fn min_reach_time(&self, vel: f64, dist: f64, max_vel: f64) -> f64 {
55 let discr = 2.0 * self.max_acc * dist + vel.powi(2);
56 if discr < max_vel.powi(2) {
57 (discr.sqrt() - vel) / self.max_acc
58 } else {
59 let t = (max_vel - vel) / self.max_acc; let d = 0.5 * (vel + max_vel) * t;
61 t + (dist - d) / max_vel
62 }
63 }
64
65 pub fn apply_current_speed_limit(&self, vel: f64, speed_limit: f64) {
70 let max_acc = self.max_acc;
71 let this_acc = max_acc * (1. - (vel / speed_limit).powi(4));
72 self.acc.set(f64::min(self.acc.get(), this_acc));
73 }
74
75 pub fn apply_speed_limit(&self, vel: f64, speed_limit: f64, distance: f64) {
82 if distance <= 0.0 {
83 return self.apply_current_speed_limit(vel, speed_limit);
84 }
85
86 let comf_acc = -self.comf_dec;
87 let this_acc = (speed_limit.powi(2) - vel.powi(2)) / (2. * distance);
88 if this_acc <= comf_acc {
89 let this_acc = f64::max(2.0 * comf_acc, this_acc);
90 self.acc.set(f64::min(self.acc.get(), this_acc));
91 }
92 }
93
94 pub fn stop_at_line(&self, net_dist: f64, my_vel: f64) {
100 let acc = self.idm(net_dist, my_vel, 0.0);
101 self.acc.set(f64::min(self.acc.get(), acc));
102 }
103
104 pub fn follow_vehicle(&self, net_dist: f64, my_vel: f64, their_vel: f64) {
111 let acc = self.idm(net_dist, my_vel, their_vel);
112 self.acc.set(f64::min(self.acc.get(), acc));
113 }
114
115 pub fn stopping_distance(&self, my_vel: f64) -> f64 {
117 let min_dist = 2.5; let t = my_vel / self.comf_dec;
119 0.5 * my_vel * t + min_dist
120 }
121
122 fn idm(&self, net_dist: f64, my_vel: f64, their_vel: f64) -> f64 {
124 let headway = 1.5; let comf_dec = self.comf_dec; let max_acc = self.max_acc; if net_dist <= MIN_GAP {
129 -10. * max_acc
130 } else {
131 let appr = my_vel - their_vel;
132 let factor = 1. / (2. * (max_acc * comf_dec).sqrt());
133 let ss = MIN_GAP + (my_vel * headway) + (my_vel * appr * factor);
134 let term = ss / net_dist;
135 max_acc * (1. - (term * term))
136 }
137 }
138}
139
140#[cfg(test)]
141mod test {
142 use super::*;
143 use assert_approx_eq::assert_approx_eq;
144
145 #[test]
146 fn min_reach_time() {
147 let acc = AccelerationModel::new(&ModelParams {
148 max_acceleration: 2.0,
149 comf_deceleration: 2.0,
150 });
151
152 assert_approx_eq!(acc.min_reach_time(0.0, 25.0, 50.0), 5.0);
153 assert_approx_eq!(acc.min_reach_time(0.0, 25.0, 10.0), 5.0);
154 assert_approx_eq!(acc.min_reach_time(0.0, 25.0, 9.0), 5.027777777777);
155
156 assert_approx_eq!(acc.min_reach_time(5.0, 50.0, 50.0), 5.0);
157 assert_approx_eq!(acc.min_reach_time(5.0, 50.0, 15.0), 5.0);
158 assert_approx_eq!(acc.min_reach_time(5.0, 50.0, 14.0), 5.01785714285);
159 }
160}