preps to spawn cars anywhere along the first lane

This commit is contained in:
Dustin Carlino 2019-02-20 12:05:14 -08:00
parent 09af9e6cda
commit 890eb070b0
5 changed files with 77 additions and 47 deletions

View File

@ -3,7 +3,7 @@ use crate::plugins::sim::new_des_model;
use crate::plugins::{BlockingPlugin, PluginCtx};
use crate::render::MIN_ZOOM_FOR_DETAIL;
use ezgui::{EventLoopMode, GfxCtx, Key};
use geom::{Duration, Speed};
use geom::{Distance, Duration, Speed};
use map_model::{LaneID, Map, Traversable};
use rand::seq::SliceRandom;
use rand::{Rng, SeedableRng};
@ -135,6 +135,12 @@ fn populate_world(start: LaneID, map: &Map) -> new_des_model::World {
let mut rng = XorShiftRng::from_seed([42; 16]);
for source in sources {
let len = map.get_l(source).length();
if len < new_des_model::VEHICLE_LENGTH {
println!("Can't spawn cars on {}, it's only {} long", source, len);
continue;
}
for i in 0..10 {
let path = random_path(source, &mut rng, map);
@ -150,6 +156,11 @@ fn populate_world(start: LaneID, map: &Map) -> new_des_model::World {
max_speed,
path.clone(),
Duration::seconds(1.0) * (i as f64),
Distance::meters(rng.gen_range(
new_des_model::VEHICLE_LENGTH.inner_meters(),
len.inner_meters(),
)),
map,
);
}
}
@ -163,7 +174,8 @@ fn densely_populate_world(map: &Map) -> new_des_model::World {
let mut counter = 0;
for l in map.all_lanes() {
if l.is_driving() {
let len = l.length();
if l.is_driving() && len >= new_des_model::VEHICLE_LENGTH {
for i in 0..rng.gen_range(0, 5) {
let path = random_path(l.id, &mut rng, map);
let max_speed = if rng.gen_bool(0.1) {
@ -177,6 +189,11 @@ fn densely_populate_world(map: &Map) -> new_des_model::World {
max_speed,
path,
Duration::seconds(1.0) * (i as f64),
Distance::meters(rng.gen_range(
new_des_model::VEHICLE_LENGTH.inner_meters(),
len.inner_meters(),
)),
map,
);
counter += 1;
}

View File

@ -1,5 +1,4 @@
use crate::plugins::sim::new_des_model::{FREEFLOW, VEHICLE_LENGTH};
use ezgui::Color;
use crate::plugins::sim::new_des_model::VEHICLE_LENGTH;
use geom::{Distance, Duration, PolyLine, Speed};
use map_model::{Map, Traversable};
use sim::{CarID, DrawCarInput};
@ -31,7 +30,7 @@ impl Car {
self.last_steps = keep;
}
pub fn get_draw_car(&self, front: Distance, color: Color, map: &Map) -> Option<DrawCarInput> {
pub fn get_draw_car(&self, front: Distance, map: &Map) -> Option<DrawCarInput> {
assert!(front >= Distance::ZERO);
let body = if front >= VEHICLE_LENGTH {
self.path[0]
@ -69,10 +68,11 @@ impl Car {
id: self.id,
waiting_for_turn: None,
stopping_trace: None,
state: if color == FREEFLOW {
sim::CarState::Moving
} else {
sim::CarState::Stuck
state: match self.state {
// TODO Cars can be Queued behind a slow CrossingLane. Looks kind of weird.
CarState::Queued => sim::CarState::Stuck,
CarState::CrossingLane(_) => sim::CarState::Moving,
CarState::CrossingTurn(_) => sim::CarState::Moving,
},
vehicle_type: self.id.tmp_get_vehicle_type(),
on: self.path[0],

View File

@ -1,4 +1,4 @@
pub use crate::plugins::sim::new_des_model::{Car, CarState, TimeInterval, FREEFLOW};
pub use crate::plugins::sim::new_des_model::{Car, CarState, TimeInterval};
use geom::Duration;
use map_model::{IntersectionID, Map};
use sim::DrawCarInput;
@ -16,7 +16,7 @@ impl IntersectionController {
CarState::CrossingTurn(ref int) => int.percent(time),
_ => unreachable!(),
};
if let Some(d) = car.get_draw_car(percent * t.geom.length(), FREEFLOW, map) {
if let Some(d) = car.get_draw_car(percent * t.geom.length(), map) {
return vec![d];
}
}

View File

@ -20,7 +20,7 @@ pub struct World {
queues: BTreeMap<LaneID, Queue>,
intersections: BTreeMap<IntersectionID, IntersectionController>,
spawn_later: Vec<(CarID, Option<Speed>, Vec<Traversable>, Duration)>,
spawn_later: Vec<(CarID, Option<Speed>, Vec<Traversable>, Duration, Distance)>,
}
impl World {
@ -41,6 +41,7 @@ impl World {
max_capacity: ((l.length() / (VEHICLE_LENGTH + FOLLOWING_DISTANCE)).floor()
as usize)
.max(1),
lane_len: l.length(),
},
);
}
@ -124,7 +125,12 @@ impl World {
pub fn get_all_draw_cars(&self, time: Duration, map: &Map) -> Vec<DrawCarInput> {
let mut result = Vec::new();
for queue in self.queues.values() {
result.extend(queue.get_draw_cars(time, map));
result.extend(
queue
.get_car_positions(time)
.into_iter()
.filter_map(|(car, dist)| car.get_draw_car(dist, map)),
);
}
for i in self.intersections.values() {
result.extend(i.get_draw_cars(time, map));
@ -140,7 +146,11 @@ impl World {
) -> Vec<DrawCarInput> {
match on {
Traversable::Lane(l) => match self.queues.get(&l) {
Some(q) => q.get_draw_cars(time, map),
Some(q) => q
.get_car_positions(time)
.into_iter()
.filter_map(|(car, dist)| car.get_draw_car(dist, map))
.collect(),
None => Vec::new(),
},
Traversable::Turn(t) => self.intersections[&t.parent]
@ -157,14 +167,30 @@ impl World {
max_speed: Option<Speed>,
path: Vec<Traversable>,
start_time: Duration,
start_dist: Distance,
map: &Map,
) {
self.spawn_later.push((id, max_speed, path, start_time));
if start_dist < VEHICLE_LENGTH {
panic!(
"Can't spawn a car at {}; too close to the start",
start_dist
);
}
if start_dist >= path[0].length(map) {
panic!(
"Can't spawn a car at {}; {:?} isn't that long",
start_dist, path[0]
);
}
self.spawn_later
.push((id, max_speed, path, start_time, start_dist));
}
pub fn step_if_needed(&mut self, time: Duration, map: &Map) {
// Spawn cars.
let mut retain_spawn = Vec::new();
for (id, max_speed, path, start_time) in self.spawn_later.drain(..) {
for (id, max_speed, path, start_time, start_dist) in self.spawn_later.drain(..) {
let first_lane = path[0].as_lane();
if time >= start_time
&& !self.queues[&first_lane].is_full()
@ -190,7 +216,7 @@ impl World {
last_steps: VecDeque::new(),
});
} else {
retain_spawn.push((id, max_speed, path, start_time));
retain_spawn.push((id, max_speed, path, start_time, start_dist));
}
}
self.spawn_later = retain_spawn;

View File

@ -1,15 +1,14 @@
use crate::plugins::sim::new_des_model::{
Car, CarState, FOLLOWING_DISTANCE, FREEFLOW, VEHICLE_LENGTH, WAITING,
};
use crate::plugins::sim::new_des_model::{Car, CarState, FOLLOWING_DISTANCE, VEHICLE_LENGTH};
use geom::{Distance, Duration};
use map_model::{LaneID, Map};
use sim::DrawCarInput;
use map_model::LaneID;
use std::collections::VecDeque;
pub struct Queue {
pub id: LaneID,
pub cars: VecDeque<Car>,
pub max_capacity: usize,
pub lane_len: Distance,
}
impl Queue {
@ -21,32 +20,24 @@ impl Queue {
self.cars.len() == self.max_capacity
}
pub fn get_draw_cars(&self, time: Duration, map: &Map) -> Vec<DrawCarInput> {
// May not return all of the cars -- some might be temporarily unable to actually enter the end
// of the road.
pub fn get_car_positions(&self, time: Duration) -> Vec<(&Car, Distance)> {
if self.cars.is_empty() {
return Vec::new();
}
let l = map.get_l(self.id);
let mut result: Vec<DrawCarInput> = Vec::new();
let mut last_car_back: Option<Distance> = None;
let mut result: Vec<(&Car, Distance)> = Vec::new();
for car in &self.cars {
let (front, color) = match car.state {
CarState::Queued => {
if last_car_back.is_none() {
(l.length(), WAITING)
} else {
// TODO If the last car is still CrossingLane, then kinda weird to draw
// us as queued
(last_car_back.unwrap() - FOLLOWING_DISTANCE, WAITING)
}
}
CarState::CrossingLane(ref i) => {
let bound = last_car_back
.map(|b| b - FOLLOWING_DISTANCE)
.unwrap_or_else(|| l.length());
(i.percent(time) * bound, FREEFLOW)
}
let bound = match result.last() {
Some((_, last_dist)) => *last_dist - VEHICLE_LENGTH - FOLLOWING_DISTANCE,
None => self.lane_len,
};
let front = match car.state {
CarState::Queued => bound,
CarState::CrossingLane(ref i) => i.percent(time) * bound,
CarState::CrossingTurn(_) => unreachable!(),
};
@ -59,11 +50,7 @@ impl Queue {
);
return result;
}
if let Some(d) = car.get_draw_car(front, color, map) {
result.push(d);
}
last_car_back = Some(front - VEHICLE_LENGTH);
result.push((car, front));
}
result
}