plumb car properties between driving and parking sims. seems simpler...

This commit is contained in:
Dustin Carlino 2018-10-05 11:12:22 -07:00
parent 9150ea3f6a
commit 478d12aecb
12 changed files with 110 additions and 149 deletions

View File

@ -88,6 +88,11 @@ around the precomputed front of the spot, used for drawing and for cars to line
up their front in the sim. I think we need to plumb the true start of the spot up their front in the sim. I think we need to plumb the true start of the spot
and have a method to interpolate and pick the true front. and have a method to interpolate and pick the true front.
Now trying the other way -- plumbing back and forth. How do we represent this for parked cars?
- store Vehicle in ParkedCar
- I remember there was some reason this refactor broke last time, but let's try it again
- and store ParkedCar's directly in ParkingLane
## Logging ## Logging
Libraries will do it too -- that's fine Libraries will do it too -- that's fine

View File

@ -40,6 +40,7 @@ struct Car {
on: On, on: On,
speed: Speed, speed: Speed,
dist_along: Distance, dist_along: Distance,
vehicle: Vehicle,
parking: Option<ParkingState>, parking: Option<ParkingState>,
@ -82,7 +83,6 @@ impl Car {
// State transitions might be indicated // State transitions might be indicated
transit_sim: &mut TransitSimState, transit_sim: &mut TransitSimState,
intersections: &IntersectionSimState, intersections: &IntersectionSimState,
properties: &BTreeMap<CarID, Vehicle>,
) -> Result<Action, Error> { ) -> Result<Action, Error> {
if self.parking.is_some() { if self.parking.is_some() {
// TODO right place for this check? // TODO right place for this check?
@ -90,7 +90,7 @@ impl Car {
return Ok(Action::WorkOnParking); return Ok(Action::WorkOnParking);
} }
let vehicle = &properties[&self.id]; let vehicle = &self.vehicle;
if let Some(act) = orig_router.react_before_lookahead( if let Some(act) = orig_router.react_before_lookahead(
events, events,
@ -148,7 +148,7 @@ impl Car {
if let Some(other) = view.next_car_in_front_of(current_on, current_dist_along) { if let Some(other) = view.next_car_in_front_of(current_on, current_dist_along) {
assert!(self.id != other.id.as_car()); assert!(self.id != other.id.as_car());
assert!(current_dist_along < other.dist_along); assert!(current_dist_along < other.dist_along);
let other_vehicle = &properties[&other.id.as_car()]; let other_vehicle = other.vehicle.as_ref().unwrap();
let dist_behind_other = let dist_behind_other =
dist_scanned_ahead + (other.dist_along - current_dist_along); dist_scanned_ahead + (other.dist_along - current_dist_along);
// If our lookahead doesn't even hit the lead vehicle (plus following distance!!!), then ignore them. // If our lookahead doesn't even hit the lead vehicle (plus following distance!!!), then ignore them.
@ -350,12 +350,7 @@ impl SimQueue {
// TODO it'd be cool to contribute tooltips (like number of cars currently here, capacity) to // TODO it'd be cool to contribute tooltips (like number of cars currently here, capacity) to
// tooltip // tooltip
fn reset( fn reset(&mut self, ids: &Vec<CarID>, cars: &BTreeMap<CarID, Car>) -> Result<(), Error> {
&mut self,
ids: &Vec<CarID>,
cars: &BTreeMap<CarID, Car>,
properties: &BTreeMap<CarID, Vehicle>,
) -> Result<(), Error> {
let old_queue = self.cars_queue.clone(); let old_queue = self.cars_queue.clone();
let new_queue: Vec<(Distance, CarID)> = let new_queue: Vec<(Distance, CarID)> =
ids.iter().map(|id| (cars[id].dist_along, *id)).collect(); ids.iter().map(|id| (cars[id].dist_along, *id)).collect();
@ -375,7 +370,7 @@ impl SimQueue {
// assert here we're not squished together too much // assert here we're not squished together too much
for slice in self.cars_queue.windows(2) { for slice in self.cars_queue.windows(2) {
let ((dist1, c1), (dist2, c2)) = (slice[0], slice[1]); let ((dist1, c1), (dist2, c2)) = (slice[0], slice[1]);
let following_dist = properties[&c1].following_dist(); let following_dist = cars[&c1].vehicle.following_dist();
if dist1 - dist2 < following_dist { if dist1 - dist2 < following_dist {
bail!(InvariantViolated::new(format!("uh oh! on {:?}, reset to {:?} broke. min following distance is {}, but we have {} at {} and {} at {}. dist btwn is just {}. prev queue was {:?}", self.id, self.cars_queue, following_dist, c1, dist1, c2, dist2, dist1 - dist2, old_queue))); bail!(InvariantViolated::new(format!("uh oh! on {:?}, reset to {:?} broke. min following distance is {}, but we have {} at {} and {} at {}. dist btwn is just {}. prev queue was {:?}", self.id, self.cars_queue, following_dist, c1, dist1, c2, dist2, dist1 - dist2, old_queue)));
} }
@ -389,16 +384,10 @@ impl SimQueue {
// TODO this starts cars with their front aligned with the end of the lane, sticking their back // TODO this starts cars with their front aligned with the end of the lane, sticking their back
// into the intersection. :( // into the intersection. :(
fn get_draw_cars( fn get_draw_cars(&self, sim: &DrivingSimState, map: &Map, time: Tick) -> Vec<DrawCarInput> {
&self,
sim: &DrivingSimState,
map: &Map,
time: Tick,
properties: &BTreeMap<CarID, Vehicle>,
) -> Vec<DrawCarInput> {
let mut results = Vec::new(); let mut results = Vec::new();
for (_, id) in &self.cars_queue { for (_, id) in &self.cars_queue {
results.push(sim.get_draw_car(*id, time, map, properties).unwrap()) results.push(sim.get_draw_car(*id, time, map).unwrap())
} }
results results
} }
@ -560,7 +549,6 @@ impl DrivingSimState {
intersections: &mut IntersectionSimState, intersections: &mut IntersectionSimState,
transit_sim: &mut TransitSimState, transit_sim: &mut TransitSimState,
rng: &mut R, rng: &mut R,
properties: &BTreeMap<CarID, Vehicle>,
) -> Result<Vec<ParkedCar>, Error> { ) -> Result<Vec<ParkedCar>, Error> {
self.populate_view(view); self.populate_view(view);
@ -580,7 +568,6 @@ impl DrivingSimState {
parking_sim, parking_sim,
transit_sim, transit_sim,
intersections, intersections,
properties,
)?, )?,
)); ));
} }
@ -599,7 +586,7 @@ impl DrivingSimState {
c.parking = Some(ParkingState { c.parking = Some(ParkingState {
is_parking: true, is_parking: true,
started_at: time, started_at: time,
tuple: ParkedCar::new(*id, *spot), tuple: ParkedCar::new(*id, *spot, c.vehicle.clone()),
}); });
} }
Action::WorkOnParking => { Action::WorkOnParking => {
@ -662,16 +649,16 @@ impl DrivingSimState {
// Reset all queues // Reset all queues
for l in &mut self.lanes { for l in &mut self.lanes {
if let Some(v) = cars_per_lane.get_vec(&l.id.as_lane()) { if let Some(v) = cars_per_lane.get_vec(&l.id.as_lane()) {
l.reset(v, &self.cars, properties)?; l.reset(v, &self.cars)?;
} else { } else {
l.reset(&Vec::new(), &self.cars, properties)?; l.reset(&Vec::new(), &self.cars)?;
} }
} }
for t in self.turns.values_mut() { for t in self.turns.values_mut() {
if let Some(v) = cars_per_turn.get_vec(&t.id.as_turn()) { if let Some(v) = cars_per_turn.get_vec(&t.id.as_turn()) {
t.reset(v, &self.cars, properties)?; t.reset(v, &self.cars)?;
} else { } else {
t.reset(&Vec::new(), &self.cars, properties)?; t.reset(&Vec::new(), &self.cars)?;
} }
} }
@ -685,11 +672,11 @@ impl DrivingSimState {
time: Tick, time: Tick,
car: CarID, car: CarID,
maybe_parked_car: Option<ParkedCar>, maybe_parked_car: Option<ParkedCar>,
vehicle: Vehicle,
dist_along: Distance, dist_along: Distance,
start: LaneID, start: LaneID,
router: Router, router: Router,
map: &Map, map: &Map,
properties: &BTreeMap<CarID, Vehicle>,
) -> bool { ) -> bool {
// If not, we have a parking lane much longer than a driving lane... // If not, we have a parking lane much longer than a driving lane...
assert!(dist_along <= map.get_l(start).length()); assert!(dist_along <= map.get_l(start).length());
@ -710,12 +697,12 @@ impl DrivingSimState {
return false; return false;
} }
let other_vehicle = &properties[&other]; let other_vehicle = &self.cars[&other].vehicle;
let accel_for_other_to_stop = other_vehicle let accel_for_other_to_stop = other_vehicle
.accel_to_follow( .accel_to_follow(
self.cars[&other].speed, self.cars[&other].speed,
map.get_parent(start).get_speed_limit(), map.get_parent(start).get_speed_limit(),
&properties[&car], &vehicle,
dist_along - other_dist, dist_along - other_dist,
0.0 * si::MPS, 0.0 * si::MPS,
).unwrap(); ).unwrap();
@ -736,6 +723,7 @@ impl DrivingSimState {
dist_along: dist_along, dist_along: dist_along,
speed: 0.0 * si::MPS, speed: 0.0 * si::MPS,
on: On::Lane(start), on: On::Lane(start),
vehicle,
waiting_for: None, waiting_for: None,
debug: false, debug: false,
is_bus: !maybe_parked_car.is_some(), is_bus: !maybe_parked_car.is_some(),
@ -757,17 +745,10 @@ impl DrivingSimState {
true true
} }
pub fn get_draw_car( pub fn get_draw_car(&self, id: CarID, time: Tick, map: &Map) -> Option<DrawCarInput> {
&self,
id: CarID,
time: Tick,
map: &Map,
properties: &BTreeMap<CarID, Vehicle>,
) -> Option<DrawCarInput> {
let c = self.cars.get(&id)?; let c = self.cars.get(&id)?;
let (base_pos, angle) = c.on.dist_along(c.dist_along, map); let (base_pos, angle) = c.on.dist_along(c.dist_along, map);
let vehicle = &properties[&id]; let stopping_dist = c.vehicle.stopping_distance(c.speed);
let stopping_dist = vehicle.stopping_distance(c.speed);
// TODO arguably, this math might belong in DrawCar. // TODO arguably, this math might belong in DrawCar.
let pos = if let Some(ref parking) = c.parking { let pos = if let Some(ref parking) = c.parking {
@ -787,7 +768,7 @@ impl DrivingSimState {
Some(DrawCarInput { Some(DrawCarInput {
id: c.id, id: c.id,
vehicle_length: vehicle.length, vehicle_length: c.vehicle.length,
waiting_for_turn: c.waiting_for.and_then(|on| on.maybe_turn()), waiting_for_turn: c.waiting_for.and_then(|on| on.maybe_turn()),
front: pos, front: pos,
angle, angle,
@ -795,25 +776,13 @@ impl DrivingSimState {
}) })
} }
pub fn get_draw_cars_on_lane( pub fn get_draw_cars_on_lane(&self, lane: LaneID, time: Tick, map: &Map) -> Vec<DrawCarInput> {
&self, self.lanes[lane.0].get_draw_cars(self, map, time)
lane: LaneID,
time: Tick,
map: &Map,
properties: &BTreeMap<CarID, Vehicle>,
) -> Vec<DrawCarInput> {
self.lanes[lane.0].get_draw_cars(self, map, time, properties)
} }
pub fn get_draw_cars_on_turn( pub fn get_draw_cars_on_turn(&self, turn: TurnID, time: Tick, map: &Map) -> Vec<DrawCarInput> {
&self,
turn: TurnID,
time: Tick,
map: &Map,
properties: &BTreeMap<CarID, Vehicle>,
) -> Vec<DrawCarInput> {
if let Some(queue) = self.turns.get(&turn) { if let Some(queue) = self.turns.get(&turn) {
return queue.get_draw_cars(self, map, time, properties); return queue.get_draw_cars(self, map, time);
} }
return Vec::new(); return Vec::new();
} }
@ -831,6 +800,7 @@ impl DrivingSimState {
on: c.on, on: c.on,
dist_along: c.dist_along, dist_along: c.dist_along,
speed: c.speed, speed: c.speed,
vehicle: Some(c.vehicle.clone()),
}, },
); );
} }

View File

@ -1,12 +1,12 @@
use intersections::Request; use intersections::Request;
use map_model::{BuildingID, BusStopID}; use map_model::{BuildingID, BusStopID};
use {AgentID, CarID, On, ParkedCar, ParkingSpot, PedestrianID}; use {AgentID, CarID, On, ParkingSpot, PedestrianID};
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum Event { pub enum Event {
// TODO CarFinishedParking // TODO CarFinishedParking
// TODO and the pedestrian / trip associated with it? // TODO and the pedestrian / trip associated with it?
CarReachedParkingSpot(ParkedCar), CarReachedParkingSpot(CarID, ParkingSpot),
// TODO and the car / trip? // TODO and the car / trip?
PedReachedParkingSpot(PedestrianID, ParkingSpot), PedReachedParkingSpot(PedestrianID, ParkingSpot),
// TODO CarFinishedUnparking // TODO CarFinishedUnparking

View File

@ -169,13 +169,8 @@ impl Sim {
} }
pub fn seed_parked_cars(&mut self, in_poly: Option<&Polygon>, percent: f64) { pub fn seed_parked_cars(&mut self, in_poly: Option<&Polygon>, percent: f64) {
self.spawner.seed_parked_cars( self.spawner
percent, .seed_parked_cars(percent, in_poly, &mut self.parking_state, &mut self.rng);
in_poly,
&mut self.parking_state,
&mut self.car_properties,
&mut self.rng,
);
} }
pub fn seed_bus_route(&mut self, route: &BusRoute, map: &Map) -> Vec<CarID> { pub fn seed_bus_route(&mut self, route: &BusRoute, map: &Map) -> Vec<CarID> {
@ -189,18 +184,12 @@ impl Sim {
&mut self.driving_state, &mut self.driving_state,
&mut self.transit_state, &mut self.transit_state,
self.time, self.time,
&mut self.car_properties,
) )
} }
pub fn seed_specific_parked_cars(&mut self, lane: LaneID, spots: Vec<usize>) -> Vec<CarID> { pub fn seed_specific_parked_cars(&mut self, lane: LaneID, spots: Vec<usize>) -> Vec<CarID> {
self.spawner.seed_specific_parked_cars( self.spawner
lane, .seed_specific_parked_cars(lane, spots, &mut self.parking_state, &mut self.rng)
spots,
&mut self.parking_state,
&mut self.car_properties,
&mut self.rng,
)
} }
pub fn seed_driving_trips(&mut self, map: &Map, num_cars: usize) { pub fn seed_driving_trips(&mut self, map: &Map, num_cars: usize) {
@ -253,7 +242,8 @@ impl Sim {
let parked = self let parked = self
.parking_state .parking_state
.lookup_car(car) .lookup_car(car)
.expect("Car isn't parked"); .expect("Car isn't parked")
.clone();
let road = map.get_parent(parked.spot.lane); let road = map.get_parent(parked.spot.lane);
let sidewalk = road let sidewalk = road
.find_sidewalk(parked.spot.lane) .find_sidewalk(parked.spot.lane)

View File

@ -35,7 +35,7 @@ const FOLLOWING_DISTANCE: Distance = si::Meter {
// TODO unit test all of this // TODO unit test all of this
// TODO handle floating point issues uniformly here // TODO handle floating point issues uniformly here
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Vehicle { pub struct Vehicle {
pub id: CarID, pub id: CarID,

View File

@ -356,11 +356,12 @@ impl ParkingSpot {
pub struct ParkedCar { pub struct ParkedCar {
pub car: CarID, pub car: CarID,
pub spot: ParkingSpot, pub spot: ParkingSpot,
pub vehicle: kinematics::Vehicle,
} }
impl ParkedCar { impl ParkedCar {
pub fn new(car: CarID, spot: ParkingSpot) -> ParkedCar { pub fn new(car: CarID, spot: ParkingSpot, vehicle: kinematics::Vehicle) -> ParkedCar {
ParkedCar { car, spot } ParkedCar { car, spot, vehicle }
} }
} }

View File

@ -3,7 +3,6 @@ use geom::{Angle, Polygon, Pt2D};
use kinematics::Vehicle; use kinematics::Vehicle;
use map_model; use map_model;
use map_model::{Lane, LaneID, LaneType, Map}; use map_model::{Lane, LaneID, LaneType, Map};
use std::collections::BTreeMap;
use std::iter; use std::iter;
use {CarID, Distance, DrawCarInput, ParkedCar, ParkingSpot}; use {CarID, Distance, DrawCarInput, ParkedCar, ParkingSpot};
@ -52,8 +51,8 @@ impl ParkingSimState {
pub fn get_all_free_spots(&self, in_poly: Option<&Polygon>) -> Vec<ParkingSpot> { pub fn get_all_free_spots(&self, in_poly: Option<&Polygon>) -> Vec<ParkingSpot> {
let mut spots: Vec<ParkingSpot> = Vec::new(); let mut spots: Vec<ParkingSpot> = Vec::new();
for l in &self.lanes { for l in &self.lanes {
for (idx, occupant) in l.occupants.iter().enumerate() { for (idx, maybe_occupant) in l.occupants.iter().enumerate() {
if occupant.is_none() { if maybe_occupant.is_none() {
// Just match based on the front of the spot // Just match based on the front of the spot
if in_poly if in_poly
.map(|p| p.contains_pt(l.spots[idx].pos)) .map(|p| p.contains_pt(l.spots[idx].pos))
@ -68,43 +67,36 @@ impl ParkingSimState {
} }
pub fn remove_parked_car(&mut self, p: ParkedCar) { pub fn remove_parked_car(&mut self, p: ParkedCar) {
self.lanes[p.spot.lane.0].remove_parked_car(p.car); self.lanes[p.spot.lane.0].remove_parked_car(p);
self.total_count -= 1; self.total_count -= 1;
} }
pub fn add_parked_car(&mut self, p: ParkedCar) { pub fn add_parked_car(&mut self, p: ParkedCar) {
assert_eq!(self.lanes[p.spot.lane.0].occupants[p.spot.idx], None); let spot = p.spot;
self.lanes[p.spot.lane.0].occupants[p.spot.idx] = Some(p.car); assert_eq!(self.lanes[spot.lane.0].occupants[spot.idx], None);
self.lanes[spot.lane.0].occupants[spot.idx] = Some(p);
self.total_count += 1; self.total_count += 1;
} }
pub fn get_draw_cars( pub fn get_draw_cars(&self, id: LaneID) -> Vec<DrawCarInput> {
&self, self.lanes[id.0].get_draw_cars()
id: LaneID,
properties: &BTreeMap<CarID, Vehicle>,
) -> Vec<DrawCarInput> {
self.lanes[id.0].get_draw_cars(properties)
} }
pub fn get_draw_car( pub fn get_draw_car(&self, id: CarID) -> Option<DrawCarInput> {
&self,
id: CarID,
properties: &BTreeMap<CarID, Vehicle>,
) -> Option<DrawCarInput> {
// TODO this is so horrendously slow :D // TODO this is so horrendously slow :D
for l in &self.lanes { for l in &self.lanes {
if l.occupants.contains(&Some(id)) { if l.occupants.iter().find(|x| is_car(x, id)).is_some() {
return l.get_draw_cars(properties).into_iter().find(|c| c.id == id); return l.get_draw_cars().into_iter().find(|c| c.id == id);
} }
} }
None None
} }
pub fn lookup_car(&self, id: CarID) -> Option<ParkedCar> { pub fn lookup_car(&self, id: CarID) -> Option<&ParkedCar> {
// TODO this is so horrendously slow :D // TODO this is so horrendously slow :D
for l in &self.lanes { for l in &self.lanes {
if let Some(idx) = l.occupants.iter().position(|x| *x == Some(id)) { if let Some(p) = l.occupants.iter().find(|x| is_car(x, id)) {
return Some(ParkedCar::new(id, ParkingSpot::new(l.id, idx))); return p.as_ref();
} }
} }
None None
@ -113,14 +105,14 @@ impl ParkingSimState {
pub fn get_all_parked_cars(&self, in_poly: Option<&Polygon>) -> Vec<ParkedCar> { pub fn get_all_parked_cars(&self, in_poly: Option<&Polygon>) -> Vec<ParkedCar> {
let mut result = Vec::new(); let mut result = Vec::new();
for l in &self.lanes { for l in &self.lanes {
for (idx, maybe_car) in l.occupants.iter().enumerate() { for maybe_occupant in &l.occupants {
if let Some(car) = maybe_car { if let Some(occupant) = maybe_occupant {
// Just match based on the front of the spot // Just match based on the front of the spot
if in_poly if in_poly
.map(|p| p.contains_pt(l.spots[idx].pos)) .map(|p| p.contains_pt(l.spots[occupant.spot.idx].pos))
.unwrap_or(true) .unwrap_or(true)
{ {
result.push(ParkedCar::new(*car, ParkingSpot::new(l.id, idx))); result.push(occupant.clone());
} }
} }
} }
@ -140,7 +132,7 @@ impl ParkingSimState {
pub fn get_car_at_spot(&self, spot: ParkingSpot) -> Option<ParkedCar> { pub fn get_car_at_spot(&self, spot: ParkingSpot) -> Option<ParkedCar> {
let l = &self.lanes[spot.lane.0]; let l = &self.lanes[spot.lane.0];
l.occupants[spot.idx].and_then(|car| Some(ParkedCar::new(car, spot))) l.occupants[spot.idx].clone()
} }
pub fn dist_along_for_car(&self, spot: ParkingSpot, vehicle: &Vehicle) -> Distance { pub fn dist_along_for_car(&self, spot: ParkingSpot, vehicle: &Vehicle) -> Distance {
@ -160,7 +152,7 @@ impl ParkingSimState {
struct ParkingLane { struct ParkingLane {
id: LaneID, id: LaneID,
spots: Vec<ParkingSpotGeometry>, spots: Vec<ParkingSpotGeometry>,
occupants: Vec<Option<CarID>>, occupants: Vec<Option<ParkedCar>>,
} }
// TODO the f64's prevent derivation // TODO the f64's prevent derivation
@ -198,22 +190,25 @@ impl ParkingLane {
} }
} }
fn remove_parked_car(&mut self, car: CarID) { fn remove_parked_car(&mut self, p: ParkedCar) {
let idx = self.occupants.iter().position(|x| *x == Some(car)).unwrap(); let match_against = Some(p.clone());
let idx = self
.occupants
.iter()
.position(|x| *x == match_against)
.unwrap();
self.occupants[idx] = None; self.occupants[idx] = None;
} }
fn get_draw_cars(&self, properties: &BTreeMap<CarID, Vehicle>) -> Vec<DrawCarInput> { fn get_draw_cars(&self) -> Vec<DrawCarInput> {
self.occupants self.occupants
.iter() .iter()
.enumerate() .filter_map(|maybe_occupant| {
.filter_map(|(idx, maybe_id)| { maybe_occupant.as_ref().and_then(|p| {
maybe_id.and_then(|id| { let (front, angle) = self.spots[p.spot.idx].front_of_car(&p.vehicle);
let vehicle = &properties[&id];
let (front, angle) = self.spots[idx].front_of_car(vehicle);
Some(DrawCarInput { Some(DrawCarInput {
id: id, id: p.car,
vehicle_length: vehicle.length, vehicle_length: p.vehicle.length,
waiting_for_turn: None, waiting_for_turn: None,
front: front, front: front,
angle: angle, angle: angle,
@ -224,7 +219,7 @@ impl ParkingLane {
} }
fn is_empty(&self) -> bool { fn is_empty(&self) -> bool {
!self.occupants.iter().find(|&&x| x.is_some()).is_some() !self.occupants.iter().find(|x| x.is_some()).is_some()
} }
} }
@ -261,3 +256,10 @@ impl ParkingSpotGeometry {
) )
} }
} }
fn is_car(maybe_occupant: &&Option<ParkedCar>, car: CarID) -> bool {
match maybe_occupant {
Some(p) => p.car == car,
None => false,
}
}

View File

@ -7,13 +7,11 @@ use driving::DrivingSimState;
use failure::Error; use failure::Error;
use instrument::capture_backtrace; use instrument::capture_backtrace;
use intersections::IntersectionSimState; use intersections::IntersectionSimState;
use kinematics::Vehicle;
use map_model::{IntersectionID, LaneID, LaneType, Map, Turn, TurnID}; use map_model::{IntersectionID, LaneID, LaneType, Map, Turn, TurnID};
use parking::ParkingSimState; use parking::ParkingSimState;
use rand::{FromEntropy, SeedableRng, XorShiftRng}; use rand::{FromEntropy, SeedableRng, XorShiftRng};
use spawn::Spawner; use spawn::Spawner;
use std; use std;
use std::collections::BTreeMap;
use std::f64; use std::f64;
use std::process; use std::process;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
@ -50,8 +48,6 @@ pub struct Sim {
pub(crate) walking_state: WalkingSimState, pub(crate) walking_state: WalkingSimState,
pub(crate) transit_state: TransitSimState, pub(crate) transit_state: TransitSimState,
pub(crate) trips_state: TripManager, pub(crate) trips_state: TripManager,
pub(crate) car_properties: BTreeMap<CarID, Vehicle>,
} }
impl Sim { impl Sim {
@ -80,7 +76,6 @@ impl Sim {
map_name: map.get_name().to_string(), map_name: map.get_name().to_string(),
run_name, run_name,
savestate_every, savestate_every,
car_properties: BTreeMap::new(),
} }
} }
@ -156,7 +151,6 @@ impl Sim {
&mut self.walking_state, &mut self.walking_state,
&mut self.driving_state, &mut self.driving_state,
&mut self.trips_state, &mut self.trips_state,
&self.car_properties,
); );
for p in self.driving_state.step( for p in self.driving_state.step(
@ -168,9 +162,8 @@ impl Sim {
&mut self.intersection_state, &mut self.intersection_state,
&mut self.transit_state, &mut self.transit_state,
&mut self.rng, &mut self.rng,
&self.car_properties,
)? { )? {
events.push(Event::CarReachedParkingSpot(p.clone())); events.push(Event::CarReachedParkingSpot(p.car, p.spot));
capture_backtrace("CarReachedParkingSpot"); capture_backtrace("CarReachedParkingSpot");
self.parking_state.add_parked_car(p.clone()); self.parking_state.add_parked_car(p.clone());
self.spawner.car_reached_parking_spot( self.spawner.car_reached_parking_spot(
@ -232,8 +225,8 @@ impl Sim {
pub fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput> { pub fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput> {
self.driving_state self.driving_state
.get_draw_car(id, self.time, map, &self.car_properties) .get_draw_car(id, self.time, map)
.or_else(|| self.parking_state.get_draw_car(id, &self.car_properties)) .or_else(|| self.parking_state.get_draw_car(id))
} }
pub fn get_draw_ped(&self, id: PedestrianID, map: &Map) -> Option<DrawPedestrianInput> { pub fn get_draw_ped(&self, id: PedestrianID, map: &Map) -> Option<DrawPedestrianInput> {
@ -243,19 +236,15 @@ impl Sim {
// TODO maybe just DrawAgent instead? should caller care? // TODO maybe just DrawAgent instead? should caller care?
pub fn get_draw_cars_on_lane(&self, l: LaneID, map: &Map) -> Vec<DrawCarInput> { pub fn get_draw_cars_on_lane(&self, l: LaneID, map: &Map) -> Vec<DrawCarInput> {
match map.get_l(l).lane_type { match map.get_l(l).lane_type {
LaneType::Driving => { LaneType::Driving => self.driving_state.get_draw_cars_on_lane(l, self.time, map),
self.driving_state LaneType::Parking => self.parking_state.get_draw_cars(l),
.get_draw_cars_on_lane(l, self.time, map, &self.car_properties)
}
LaneType::Parking => self.parking_state.get_draw_cars(l, &self.car_properties),
LaneType::Sidewalk => Vec::new(), LaneType::Sidewalk => Vec::new(),
LaneType::Biking => Vec::new(), LaneType::Biking => Vec::new(),
} }
} }
pub fn get_draw_cars_on_turn(&self, t: TurnID, map: &Map) -> Vec<DrawCarInput> { pub fn get_draw_cars_on_turn(&self, t: TurnID, map: &Map) -> Vec<DrawCarInput> {
self.driving_state self.driving_state.get_draw_cars_on_turn(t, self.time, map)
.get_draw_cars_on_turn(t, self.time, map, &self.car_properties)
} }
pub fn get_draw_peds_on_lane(&self, l: LaneID, map: &Map) -> Vec<DrawPedestrianInput> { pub fn get_draw_peds_on_lane(&self, l: LaneID, map: &Map) -> Vec<DrawPedestrianInput> {

View File

@ -5,7 +5,7 @@ use map_model::{BuildingID, BusRoute, BusStopID, LaneID, Map, Pathfinder};
use parking::ParkingSimState; use parking::ParkingSimState;
use rand::Rng; use rand::Rng;
use router::Router; use router::Router;
use std::collections::{BTreeMap, VecDeque}; use std::collections::VecDeque;
use std::time::Instant; use std::time::Instant;
use transit::TransitSimState; use transit::TransitSimState;
use trips::{TripLeg, TripManager}; use trips::{TripLeg, TripManager};
@ -77,7 +77,6 @@ impl Spawner {
walking_sim: &mut WalkingSimState, walking_sim: &mut WalkingSimState,
driving_sim: &mut DrivingSimState, driving_sim: &mut DrivingSimState,
trips: &mut TripManager, trips: &mut TripManager,
properties: &BTreeMap<CarID, Vehicle>,
) { ) {
let mut commands: Vec<Command> = Vec::new(); let mut commands: Vec<Command> = Vec::new();
let mut requested_paths: Vec<(LaneID, LaneID)> = Vec::new(); let mut requested_paths: Vec<(LaneID, LaneID)> = Vec::new();
@ -111,18 +110,18 @@ impl Spawner {
// TODO this looks like it jumps when the parking and driving lanes are different lengths // TODO this looks like it jumps when the parking and driving lanes are different lengths
// due to diagonals // due to diagonals
let dist_along = let dist_along =
parking_sim.dist_along_for_car(parked_car.spot, &properties[&car]); parking_sim.dist_along_for_car(parked_car.spot, &parked_car.vehicle);
let start = path.pop_front().unwrap(); let start = path.pop_front().unwrap();
if driving_sim.start_car_on_lane( if driving_sim.start_car_on_lane(
events, events,
now, now,
car, car,
Some(parked_car.clone()), Some(parked_car.clone()),
parked_car.vehicle.clone(),
dist_along, dist_along,
start, start,
Router::make_router_to_park(path, goal_bldg), Router::make_router_to_park(path, goal_bldg),
map, map,
properties,
) { ) {
trips.agent_starting_trip_leg(AgentID::Car(car), trip); trips.agent_starting_trip_leg(AgentID::Car(car), trip);
parking_sim.remove_parked_car(parked_car.clone()); parking_sim.remove_parked_car(parked_car.clone());
@ -161,7 +160,6 @@ impl Spawner {
driving_sim: &mut DrivingSimState, driving_sim: &mut DrivingSimState,
transit_sim: &mut TransitSimState, transit_sim: &mut TransitSimState,
now: Tick, now: Tick,
car_properties: &mut BTreeMap<CarID, Vehicle>,
) -> Vec<CarID> { ) -> Vec<CarID> {
let route_id = transit_sim.create_empty_route(route, map); let route_id = transit_sim.create_empty_route(route, map);
let mut results: Vec<CarID> = Vec::new(); let mut results: Vec<CarID> = Vec::new();
@ -179,15 +177,14 @@ impl Spawner {
now, now,
id, id,
None, None,
vehicle,
start_dist_along, start_dist_along,
start, start,
Router::make_router_for_bus(path), Router::make_router_for_bus(path),
map, map,
car_properties,
) { ) {
transit_sim.bus_created(id, route_id, next_stop_idx); transit_sim.bus_created(id, route_id, next_stop_idx);
info!("Spawned bus {} for route {} ({})", id, route.name, route_id); info!("Spawned bus {} for route {} ({})", id, route.name, route_id);
car_properties.insert(id, vehicle);
results.push(id); results.push(id);
} else { } else {
warn!( warn!(
@ -205,7 +202,6 @@ impl Spawner {
percent_capacity_to_fill: f64, percent_capacity_to_fill: f64,
in_poly: Option<&Polygon>, in_poly: Option<&Polygon>,
parking_sim: &mut ParkingSimState, parking_sim: &mut ParkingSimState,
car_properties: &mut BTreeMap<CarID, Vehicle>,
rng: &mut R, rng: &mut R,
) { ) {
assert!(percent_capacity_to_fill >= 0.0 && percent_capacity_to_fill <= 1.0); assert!(percent_capacity_to_fill >= 0.0 && percent_capacity_to_fill <= 1.0);
@ -219,8 +215,11 @@ impl Spawner {
let car = CarID(self.car_id_counter); let car = CarID(self.car_id_counter);
// TODO since spawning applies during the next step, lots of stuff breaks without // TODO since spawning applies during the next step, lots of stuff breaks without
// this :( // this :(
parking_sim.add_parked_car(ParkedCar::new(car, spot)); parking_sim.add_parked_car(ParkedCar::new(
car_properties.insert(car, Vehicle::generate_typical_car(car, rng)); car,
spot,
Vehicle::generate_typical_car(car, rng),
));
self.car_id_counter += 1; self.car_id_counter += 1;
} }
} }
@ -236,7 +235,6 @@ impl Spawner {
lane: LaneID, lane: LaneID,
spot_indices: Vec<usize>, spot_indices: Vec<usize>,
parking_sim: &mut ParkingSimState, parking_sim: &mut ParkingSimState,
car_properties: &mut BTreeMap<CarID, Vehicle>,
rng: &mut R, rng: &mut R,
) -> Vec<CarID> { ) -> Vec<CarID> {
let spots = parking_sim.get_all_spots(lane); let spots = parking_sim.get_all_spots(lane);
@ -244,9 +242,12 @@ impl Spawner {
.into_iter() .into_iter()
.map(|idx| { .map(|idx| {
let car = CarID(self.car_id_counter); let car = CarID(self.car_id_counter);
parking_sim.add_parked_car(ParkedCar::new(car, spots[idx])); parking_sim.add_parked_car(ParkedCar::new(
car,
spots[idx],
Vehicle::generate_typical_car(car, rng),
));
self.car_id_counter += 1; self.car_id_counter += 1;
car_properties.insert(car, Vehicle::generate_typical_car(car, rng));
car car
}).collect() }).collect()
} }

View File

@ -1,4 +1,5 @@
use driving::SimQueue; use driving::SimQueue;
use kinematics::Vehicle;
use map_model::TurnID; use map_model::TurnID;
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
use {AgentID, CarID, Distance, On, Speed}; use {AgentID, CarID, Distance, On, Speed};
@ -10,6 +11,7 @@ pub struct AgentView {
pub on: On, pub on: On,
pub dist_along: Distance, pub dist_along: Distance,
pub speed: Speed, pub speed: Speed,
pub vehicle: Option<Vehicle>,
} }
pub struct WorldView { pub struct WorldView {

View File

@ -556,6 +556,7 @@ impl WalkingSimState {
} else { } else {
SPEED SPEED
}, },
vehicle: None,
}, },
); );
} }

View File

@ -24,10 +24,10 @@ fn park_on_goal_st() {
sim.run_until_expectations_met( sim.run_until_expectations_met(
&map, &map,
&control_map, &control_map,
vec![sim::Event::CarReachedParkingSpot(sim::ParkedCar::new( vec![sim::Event::CarReachedParkingSpot(
car, car,
sim::ParkingSpot::new(parking2, 4), sim::ParkingSpot::new(parking2, 4),
))], )],
sim::Tick::from_minutes(1), sim::Tick::from_minutes(1),
); );
sim.run_until_done(&map, &control_map, Box::new(|_sim| {})); sim.run_until_done(&map, &control_map, Box::new(|_sim| {}));
@ -49,10 +49,10 @@ fn wander_around_for_parking() {
sim.run_until_expectations_met( sim.run_until_expectations_met(
&map, &map,
&control_map, &control_map,
vec![sim::Event::CarReachedParkingSpot(sim::ParkedCar::new( vec![sim::Event::CarReachedParkingSpot(
car, car,
sim::ParkingSpot::new(parking1, 0), sim::ParkingSpot::new(parking1, 0),
))], )],
sim::Tick::from_minutes(2), sim::Tick::from_minutes(2),
); );
sim.run_until_done(&map, &control_map, Box::new(|_sim| {})); sim.run_until_done(&map, &control_map, Box::new(|_sim| {}));
@ -60,7 +60,7 @@ fn wander_around_for_parking() {
fn setup(run_name: &str, map: map_model::Map) -> (map_model::Map, control::ControlMap, sim::Sim) { fn setup(run_name: &str, map: map_model::Map) -> (map_model::Map, control::ControlMap, sim::Sim) {
let rng_seed = 123; let rng_seed = 123;
let control_map = control::ControlMap::new(&map, &BTreeMap::new(), &BTreeMap::new()); let control_map = control::ControlMap::new(&map, BTreeMap::new(), BTreeMap::new());
let sim = sim::Sim::new(&map, run_name.to_string(), Some(rng_seed), None); let sim = sim::Sim::new(&map, run_name.to_string(), Some(rng_seed), None);
(map, control_map, sim) (map, control_map, sim)
} }