moving interval validations around. no point in doing them up-front.

remove useless hit_speed.
This commit is contained in:
Dustin Carlino 2019-02-17 18:22:42 -08:00
parent 43dad4090a
commit b8fc610997
2 changed files with 55 additions and 97 deletions

View File

@ -10,8 +10,7 @@ pub struct Car {
// Hack used for different colors
pub state: CarState,
pub car_length: Distance,
// TODO All of this looks jerky because we're accelerating and decelerating as fast as
// possible!
// Note that if we always used these, things would look quite jerky.
pub max_accel: Acceleration,
pub max_deaccel: Acceleration,
@ -61,36 +60,7 @@ impl Car {
);
}
// Now that distance isn't linear, we actually never directly use end_dist -- so sanity
// check that the interval works at all!
let actual_end_dist = i.dist(i.end_time);
if !actual_end_dist.epsilon_eq(i.end_dist) {
panic!(
"{} has an interval where they want to end at {}, but they really end at {}",
self.id, i.end_dist, actual_end_dist
);
}
if i.end_dist > lane_len + EPSILON_DIST {
panic!(
"{} ends {} past the lane end",
self.id,
i.end_dist - lane_len
);
}
if i.end_dist < i.start_dist {
panic!(
"{} goes backwards from {} to {}",
self.id, i.start_dist, i.end_dist
);
}
if i.end_time < i.start_time {
panic!(
"{} goes backwards IN TIME from {} to {}",
self.id, i.start_time, i.end_time
);
}
i.validate(lane_len);
}
}
@ -156,7 +126,7 @@ impl Car {
}
// Returns interval indices too.
fn find_earliest_hit(&self, leader: &Car) -> Option<(Duration, Distance, Speed, usize, usize)> {
fn find_earliest_hit(&self, leader: &Car) -> Option<(Duration, Distance, usize, usize)> {
let dist_behind = leader.car_length + FOLLOWING_DISTANCE;
// TODO Do we ever have to worry about having the same intervals? I think this should
@ -168,8 +138,8 @@ impl Car {
shifted_i2.start_dist -= dist_behind;
shifted_i2.end_dist -= dist_behind;
if let Some((time, dist, speed)) = i1.intersection(&shifted_i2) {
return Some((time, dist, speed, idx1, idx2));
if let Some((time, dist)) = i1.intersection(&shifted_i2) {
return Some((time, dist, idx1, idx2));
}
}
}
@ -209,14 +179,14 @@ impl Car {
impl Car {
fn next_state(&mut self, dist_covered: Distance, final_speed: Speed, time_needed: Duration) {
let (dist1, speed1, time1) = self.last_state();
self.intervals.push(Interval::new(
dist1,
dist1 + dist_covered,
time1,
time1 + time_needed,
speed1,
final_speed,
));
self.intervals.push(Interval {
start_dist: dist1,
end_dist: dist1 + dist_covered,
start_time: time1,
end_time: time1 + time_needed,
start_speed: speed1,
end_speed: final_speed,
});
}
pub fn accel_from_rest_to_speed_limit(&mut self, speed: Speed) {
@ -257,19 +227,11 @@ impl Car {
}
let needed_speed = self.find_speed_to_accel_then_asap_deaccel(dist_to_cover);
/*println!(
"{} would need to do {} to accel then deaccel and cover lane",
self.id, needed_speed
);*/
if needed_speed <= speed_limit {
// Alright, do that then
self.accel_from_rest_to_speed_limit(needed_speed);
self.deaccel_to_rest();
} else {
/*println!(
" But speed limit is {}, so accel->freeflow->deaccel",
speed_limit
);*/
self.accel_from_rest_to_speed_limit(speed_limit);
let stopping_dist = self.whatif_stop_from_speed(speed_limit).dist;
self.freeflow_to_cross(
@ -280,15 +242,15 @@ impl Car {
}
pub fn maybe_follow(&mut self, leader: &Car) {
let (hit_time, hit_dist, hit_speed, idx1, idx2) = match self.find_earliest_hit(leader) {
let (hit_time, hit_dist, idx1, idx2) = match self.find_earliest_hit(leader) {
Some(hit) => hit,
None => {
return;
}
};
println!(
"Collision at {}, {}, {}. follower interval {}, leader interval {}",
hit_time, hit_dist, hit_speed, idx1, idx2
"Collision at {}, {}. follower interval {}, leader interval {}",
hit_time, hit_dist, idx1, idx2
);
self.intervals.split_off(idx1 + 1);
@ -298,7 +260,6 @@ impl Car {
{
let them = &leader.intervals[idx2];
let mut fix1 = self.intervals.pop().unwrap();
// TODO hit speed is useless, we dont care about OUR speed at that time
fix1.end_speed = them.speed(hit_time);
fix1.end_dist = hit_dist;
fix1.fix_end_time();
@ -311,7 +272,7 @@ impl Car {
fix2.fix_end_time();
println!("adjusted interval 1: {}", fix1);
println!("adjusted interval 2: {}", fix2);
println!("adjusted interval 2: {}\n", fix2);
self.intervals.push(fix1);
self.intervals.push(fix2);
}

View File

@ -14,43 +14,6 @@ pub struct Interval {
}
impl Interval {
pub fn new(
start_dist: Distance,
end_dist: Distance,
start_time: Duration,
end_time: Duration,
start_speed: Speed,
end_speed: Speed,
) -> Interval {
if start_dist < Distance::ZERO {
panic!("Interval start_dist: {}", start_dist);
}
if start_time < Duration::ZERO {
panic!("Interval start_time: {}", start_time);
}
// TODO And the epsilons creep in...
if start_dist > end_dist + Distance::EPSILON {
panic!("Interval {} .. {}", start_dist, end_dist);
}
if start_time >= end_time {
panic!("Interval {} .. {}", start_time, end_time);
}
if start_speed < Speed::ZERO {
panic!("Interval start_speed: {}", start_speed);
}
if end_speed < Speed::ZERO {
panic!("Interval end_speed: {}", end_speed);
}
Interval {
start_dist,
end_dist,
start_time,
end_time,
start_speed,
end_speed,
}
}
fn raw_accel(&self) -> f64 {
(self.end_speed - self.start_speed).inner_meters_per_second()
/ (self.end_time - self.start_time).inner_seconds()
@ -81,9 +44,8 @@ impl Interval {
(t - self.start_time) / (self.end_time - self.start_time)
}
// Also returns the speed of self at the time of collision. Adjustments already made for slight
// OOBness.
pub fn intersection(&self, leader: &Interval) -> Option<(Duration, Distance, Speed)> {
// Adjustments already made for slight OOBness.
pub fn intersection(&self, leader: &Interval) -> Option<(Duration, Distance)> {
if !overlap(
(self.start_time, self.end_time),
(leader.start_time, leader.end_time),
@ -147,7 +109,7 @@ impl Interval {
}
// Adjust solved collision distance a bit.
Some((t, dist1.min(leader.end_dist), self.speed(t)))
Some((t, dist1.min(leader.end_dist)))
}
pub fn fix_end_time(&mut self) {
@ -170,6 +132,41 @@ impl Interval {
panic!("After fixing end time, got {}", self);
}
}
pub fn validate(&self, lane_len: Distance) {
if self.start_dist < Distance::ZERO {
panic!("Weird interval {}", self);
}
if self.start_time < Duration::ZERO {
panic!("Weird interval {}", self);
}
// TODO And the epsilons creep in...
if self.start_dist > self.end_dist + Distance::EPSILON {
panic!("Weird interval {}", self);
}
if self.start_time >= self.end_time {
panic!("Weird interval {}", self);
}
if self.start_speed < Speed::ZERO {
panic!("Weird interval {}", self);
}
if self.end_speed < Speed::ZERO {
panic!("Weird interval {}", self);
}
let actual_end_dist = self.dist(self.end_time);
if !actual_end_dist.epsilon_eq(self.end_dist) {
panic!("{} actually ends at {}", self, actual_end_dist);
}
if self.end_dist > lane_len + EPSILON_DIST {
panic!(
"{} ends {} past the lane end",
self,
self.end_dist - lane_len
);
}
}
}
impl fmt::Display for Interval {