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
//! Travel-time estimation for trapezoidal velocity profiles.
//!
//! Given an elevator's kinematic parameters (max speed, acceleration,
//! deceleration), an initial speed, and a remaining distance to a target,
//! [`travel_time`] returns the seconds required to coast in, brake, and
//! arrive at rest. Used by [`Simulation::eta`](crate::sim::Simulation::eta)
//! and [`Simulation::best_eta`](crate::sim::Simulation::best_eta) to walk a
//! destination queue and sum per-leg travel plus per-stop door dwell.
//!
//! The profile mirrors [`movement::tick_movement`](crate::movement::tick_movement)
//! at the closed-form level — the per-tick integrator and the closed-form
//! solver agree to within a tick on the same inputs. ETAs are estimates,
//! not bit-exact: load/unload time, dispatch reordering, and door commands
//! issued mid-trip will perturb the actual arrival.
/// Closed-form travel time, in seconds, for a trapezoidal/triangular
/// velocity profile from initial speed `v0` to a full stop over `distance`.
///
/// All inputs are unsigned magnitudes. Returns `0.0` for non-positive
/// `distance` or non-positive kinematic parameters (defensive: a degenerate
/// elevator can't reach anywhere, but we'd rather return a finite zero
/// than `NaN` or an infinity).
///
/// `v0` is clamped to `[0.0, v_max]`; an elevator already moving faster
/// than its current `max_speed` (e.g. just after a runtime-upgrade lowered
/// the cap) is treated as cruising at `v_max`.