mirror of
https://github.com/a-b-street/abstreet.git
synced 2025-01-04 12:36:46 +03:00
moving interval validations around. no point in doing them up-front.
remove useless hit_speed.
This commit is contained in:
parent
43dad4090a
commit
b8fc610997
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user