use interp::interp;
use ndarray::Array1;
pub fn rate_limit(new_value: f64, last_value: f64, dw_step: f64, up_step: f64) -> f64 {
new_value
.max(last_value + dw_step)
.min(last_value + up_step)
}
pub fn learn_angle_offset(
lateral_control: bool,
v_ego: f64,
angle_offset: f64,
d_poly: &Array1<f64>,
y_des: f64,
steer_override: bool,
) -> f64 {
const MIN_OFFSET: f64 = -1.0; const MAX_OFFSET: f64 = 1.0; const ALPHA: f64 = 1.0 / 36000.0; const MIN_LEARN_SPEED: f64 = 1.0;
let alpha_v = ALPHA * (v_ego - MIN_LEARN_SPEED).max(0.0) / (1.0 + 0.5 * f64::abs(y_des));
let mut new_angle_offset = angle_offset + d_poly[3] * alpha_v;
new_angle_offset = new_angle_offset.max(MIN_OFFSET).min(MAX_OFFSET);
if lateral_control && !steer_override {
new_angle_offset
} else {
angle_offset
}
}
pub fn actuator_hystereses(
final_brake: f64,
braking: bool,
brake_steady: f64,
v_ego: f64,
civic: bool,
) -> (f64, bool, f64) {
let brake_hyst_on = if civic { 0.055 } else { 0.1 }; let brake_hyst_off = 0.005; let brake_hyst_gap = 0.01;
let (mut new_final_brake, new_braking, mut new_brake_steady) =
if (final_brake < brake_hyst_on && !braking) || final_brake < brake_hyst_off {
(0.0, false, 0.0)
} else {
(final_brake, true, brake_steady)
};
if final_brake == 0.0 {
new_brake_steady = 0.0;
} else if final_brake > new_brake_steady + brake_hyst_gap {
new_brake_steady = final_brake - brake_hyst_gap;
} else if final_brake < new_brake_steady - brake_hyst_gap {
new_brake_steady = final_brake + brake_hyst_gap;
}
if !civic {
let brake_on_offset_v = [0.25, 0.15]; let brake_on_offset_bp = [15.0, 30.0]; let brake_on_offset = interp(&brake_on_offset_v, &brake_on_offset_bp, v_ego);
let brake_offset = brake_on_offset - brake_hyst_on;
if new_final_brake > 0.0 {
new_final_brake += brake_offset;
}
}
(new_final_brake, new_braking, new_brake_steady)
}
#[cfg(test)]
mod tests {
use super::*;
use approx::assert_abs_diff_eq;
#[test]
fn test_rate_limit() {
let new_value = rate_limit(1.5, 1.0, 0.1, 0.2);
assert!((new_value - 1.2).abs() < f64::EPSILON);
}
#[test]
fn test_learn_angle_offset() {
let lateral_control = true;
let v_ego = 20.0;
let angle_offset = 0.1;
let d_poly = Array1::from(vec![1.0, 2.0, 3.0, 4.0]);
let y_des = 0.5;
let steer_override = false;
let new_angle_offset = learn_angle_offset(
lateral_control,
v_ego,
angle_offset,
&d_poly,
y_des,
steer_override,
);
assert_abs_diff_eq!(new_angle_offset, 0.1016, epsilon = 1e-4);
}
#[test]
fn test_actuator_hystereses() {
let final_brake = 0.2;
let braking = true;
let brake_steady = 0.1;
let v_ego = 30.0;
let civic = false;
let (new_final_brake, new_braking, new_brake_steady) =
actuator_hystereses(final_brake, braking, brake_steady, v_ego, civic);
assert_abs_diff_eq!(new_final_brake, -4447.4, epsilon = 1e-4);
assert_eq!(new_braking, true);
assert!((new_brake_steady - 0.19).abs() < f64::EPSILON);
}
}