Gearing as development, physics-derived load model, 105kg rider
Gears are metres per crank revolution rather than gradient offsets, and resistive_force_n exposes what the road is doing at a given speed so load can be computed directly instead of servoed. The load model is tested but not yet commanded: FTMS sim mode has the trainer compute rolling and aero itself, so sending a gradient that already contains them would double-count. Needs Crr/Cw zeroed and a ride to verify. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -250,6 +250,27 @@ pub fn equilibrium_speed_mps(power_w: f32, gradient_pct: f32, cfg: &RiderConfig)
|
||||
0.5 * (lo + hi)
|
||||
}
|
||||
|
||||
/// Total resistive force at a given speed and gradient, newtons.
|
||||
///
|
||||
/// This is what the road is doing to the rider: gravity down the slope, rolling
|
||||
/// resistance, and aerodynamic drag rising with the square of speed. It is the
|
||||
/// force a trainer must reproduce at the wheel for the ride to feel real, and
|
||||
/// therefore the basis for virtual gearing (see `crate::gearing`).
|
||||
pub fn resistive_force_n(speed_mps: f32, gradient_pct: f32, cfg: &RiderConfig) -> f32 {
|
||||
let forces = Forces::new(0.0, gradient_pct, cfg);
|
||||
let v = if speed_mps.is_finite() {
|
||||
speed_mps.clamp(0.0, MAX_SPEED_MPS)
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
let f = forces.resistive_n + forces.drag_k * v * v;
|
||||
if f.is_finite() {
|
||||
f
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user