From 914f5a66427520b52c4912e1d2f4574641b3c571 Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Mon, 18 Feb 2019 14:22:44 -0800 Subject: [PATCH] check for cars too close during the stress test --- docs/design/notes/profiling.md | 2 +- editor/src/plugins/sim/des_model/car.rs | 3 +- editor/src/plugins/sim/des_model/mod.rs | 65 +++++++++++++++++-------- editor/src/plugins/sim/simple_model.rs | 2 +- geom/src/units.rs | 10 ++++ 5 files changed, 60 insertions(+), 22 deletions(-) diff --git a/docs/design/notes/profiling.md b/docs/design/notes/profiling.md index 237d855f65..d0d93edb88 100644 --- a/docs/design/notes/profiling.md +++ b/docs/design/notes/profiling.md @@ -4,7 +4,7 @@ apt-get install google-perftools libgoogle-perftools-dev Follow Usage from https://crates.io/crates/cpuprofiler -Run editor with --enable-profiler +Run editor with --enable_profiler google-pprof --web ../target/debug/editor profile google-pprof --web ../target/release/headless profile diff --git a/editor/src/plugins/sim/des_model/car.rs b/editor/src/plugins/sim/des_model/car.rs index dcbad5a958..d5d4bde6cd 100644 --- a/editor/src/plugins/sim/des_model/car.rs +++ b/editor/src/plugins/sim/des_model/car.rs @@ -16,6 +16,7 @@ pub struct Car { pub start_dist: Distance, pub start_time: Duration, + pub start_speed: Speed, // Distances represent the front of the car pub intervals: Vec, @@ -94,7 +95,7 @@ impl Car { if let Some(i) = self.intervals.last() { (i.end_dist, i.end_speed, i.end_time) } else { - (self.start_dist, Speed::ZERO, self.start_time) + (self.start_dist, self.start_speed, self.start_time) } } diff --git a/editor/src/plugins/sim/des_model/mod.rs b/editor/src/plugins/sim/des_model/mod.rs index 752d921068..5f698182dc 100644 --- a/editor/src/plugins/sim/des_model/mod.rs +++ b/editor/src/plugins/sim/des_model/mod.rs @@ -4,7 +4,7 @@ mod interval; use crate::objects::DrawCtx; use crate::plugins::sim::des_model::car::Car; use ezgui::{GfxCtx, Text}; -use geom::{Acceleration, Distance, Duration, EPSILON_DIST}; +use geom::{Acceleration, Distance, Duration, Speed, EPSILON_DIST}; use map_model::{LaneID, Map}; use sim::{CarID, CarState, DrawCarInput, VehicleType}; @@ -27,6 +27,9 @@ impl World { intervals: Vec::new(), start_dist: Distance::meters(5.0), start_time: Duration::ZERO, + // TODO Enter with some speed + //start_speed: 0.2 * speed_limit, + start_speed: Speed::ZERO, }; leader.start_then_stop(lane.length(), 0.5 * speed_limit); leader.wait(Duration::seconds(5.0)); @@ -43,6 +46,7 @@ impl World { intervals: Vec::new(), start_dist: Distance::meters(5.0), start_time: ((i + 1) as f64) * Duration::seconds(4.0), + start_speed: Speed::ZERO, }; follower.start_then_stop(lane.length(), speed_limit); follower.maybe_follow(cars.last().unwrap()); @@ -64,25 +68,9 @@ impl World { pub fn get_draw_cars(&self, time: Duration, map: &Map) -> Vec { let mut draw = Vec::new(); - let mut max_dist: Option = None; - for (car_idx, follower) in self.cars.iter().enumerate() { - if let Some((d, follower_idx)) = follower.dist_at(time) { - if let Some(max) = max_dist { - if d > max + EPSILON_DIST { - let leader = &self.cars[car_idx - 1]; - let leader_idx = leader.dist_at(time).unwrap().1; - println!("{} is too close to {} at {}", follower.id, leader.id, time); - println!("leader doing: {}", leader.intervals[leader_idx]); - println!("follower doing: {}", follower.intervals[follower_idx]); - println!( - "to repro:\n\n{}.intersection(&{})\n\n", - follower.intervals[follower_idx].repr(), - leader.intervals[leader_idx].repr() - ); - } - } + for follower in &self.cars { + if let Some((d, _)) = follower.dist_at(time) { draw.push(follower.get_draw_car(d, map.get_l(self.lane))); - max_dist = Some(d - follower.car_length - car::FOLLOWING_DISTANCE); } } draw @@ -120,4 +108,43 @@ impl World { } } } + + pub fn sample_for_proximity(&self) { + let mut time = Duration::ZERO; + loop { + let mut max_dist: Option = None; + let mut active_cars = 0; + for (car_idx, follower) in self.cars.iter().enumerate() { + if let Some((d, follower_idx)) = follower.dist_at(time) { + active_cars += 1; + if let Some(max) = max_dist { + if d > max + EPSILON_DIST { + let leader = &self.cars[car_idx - 1]; + let leader_idx = leader.dist_at(time).unwrap().1; + println!("{} is too close to {} at {}", follower.id, leader.id, time); + println!("leader doing: {}", leader.intervals[leader_idx]); + println!("follower doing: {}", follower.intervals[follower_idx]); + panic!( + "to repro:\n\n{}.intersection(&{})\n\n", + follower.intervals[follower_idx].repr(), + leader.intervals[leader_idx].repr() + ); + } + } + max_dist = Some(d - follower.car_length - car::FOLLOWING_DISTANCE); + } + } + // All the cars are done + if max_dist.is_none() { + return; + } + time += Duration::seconds(0.1); + if time.is_multiple_of(Duration::seconds(10.0)) { + println!( + "Checking {}. {} cars at {}...", + self.lane, active_cars, time + ); + } + } + } } diff --git a/editor/src/plugins/sim/simple_model.rs b/editor/src/plugins/sim/simple_model.rs index 743bd9033f..219151c34c 100644 --- a/editor/src/plugins/sim/simple_model.rs +++ b/editor/src/plugins/sim/simple_model.rs @@ -97,7 +97,7 @@ impl BlockingPlugin for SimpleModelController { for l in ctx.primary.map.all_lanes() { if l.is_driving() && l.length() >= Distance::meters(15.0) { println!("Testing {}...", l.id); - des_model::World::new(l.id, &ctx.primary.map); + des_model::World::new(l.id, &ctx.primary.map).sample_for_proximity(); } } } diff --git a/geom/src/units.rs b/geom/src/units.rs index 63cf86306e..7608350350 100644 --- a/geom/src/units.rs +++ b/geom/src/units.rs @@ -183,6 +183,10 @@ impl Duration { pub fn inner_seconds(self) -> f64 { self.0 } + + pub fn is_multiple_of(self, other: Duration) -> bool { + self.inner_seconds() % other.inner_seconds() == 0.0 + } } impl fmt::Display for Duration { @@ -199,6 +203,12 @@ impl ops::Add for Duration { } } +impl ops::AddAssign for Duration { + fn add_assign(&mut self, other: Duration) { + *self = *self + other; + } +} + impl ops::Sub for Duration { type Output = Duration;