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
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
Libraries will do it too -- that's fine

View File

@ -40,6 +40,7 @@ struct Car {
on: On,
speed: Speed,
dist_along: Distance,
vehicle: Vehicle,
parking: Option<ParkingState>,
@ -82,7 +83,6 @@ impl Car {
// State transitions might be indicated
transit_sim: &mut TransitSimState,
intersections: &IntersectionSimState,
properties: &BTreeMap<CarID, Vehicle>,
) -> Result<Action, Error> {
if self.parking.is_some() {
// TODO right place for this check?
@ -90,7 +90,7 @@ impl Car {
return Ok(Action::WorkOnParking);
}
let vehicle = &properties[&self.id];
let vehicle = &self.vehicle;
if let Some(act) = orig_router.react_before_lookahead(
events,
@ -148,7 +148,7 @@ impl Car {
if let Some(other) = view.next_car_in_front_of(current_on, current_dist_along) {
assert!(self.id != other.id.as_car());
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 =
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.
@ -350,12 +350,7 @@ impl SimQueue {
// TODO it'd be cool to contribute tooltips (like number of cars currently here, capacity) to
// tooltip
fn reset(
&mut self,
ids: &Vec<CarID>,
cars: &BTreeMap<CarID, Car>,
properties: &BTreeMap<CarID, Vehicle>,
) -> Result<(), Error> {
fn reset(&mut self, ids: &Vec<CarID>, cars: &BTreeMap<CarID, Car>) -> Result<(), Error> {
let old_queue = self.cars_queue.clone();
let new_queue: Vec<(Distance, CarID)> =
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
for slice in self.cars_queue.windows(2) {
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 {
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
// into the intersection. :(
fn get_draw_cars(
&self,
sim: &DrivingSimState,
map: &Map,
time: Tick,
properties: &BTreeMap<CarID, Vehicle>,
) -> Vec<DrawCarInput> {
fn get_draw_cars(&self, sim: &DrivingSimState, map: &Map, time: Tick) -> Vec<DrawCarInput> {
let mut results = Vec::new();
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
}
@ -560,7 +549,6 @@ impl DrivingSimState {
intersections: &mut IntersectionSimState,
transit_sim: &mut TransitSimState,
rng: &mut R,
properties: &BTreeMap<CarID, Vehicle>,
) -> Result<Vec<ParkedCar>, Error> {
self.populate_view(view);
@ -580,7 +568,6 @@ impl DrivingSimState {
parking_sim,
transit_sim,
intersections,
properties,
)?,
));
}
@ -599,7 +586,7 @@ impl DrivingSimState {
c.parking = Some(ParkingState {
is_parking: true,
started_at: time,
tuple: ParkedCar::new(*id, *spot),
tuple: ParkedCar::new(*id, *spot, c.vehicle.clone()),
});
}
Action::WorkOnParking => {
@ -662,16 +649,16 @@ impl DrivingSimState {
// Reset all queues
for l in &mut self.lanes {
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 {
l.reset(&Vec::new(), &self.cars, properties)?;
l.reset(&Vec::new(), &self.cars)?;
}
}
for t in self.turns.values_mut() {
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 {
t.reset(&Vec::new(), &self.cars, properties)?;
t.reset(&Vec::new(), &self.cars)?;
}
}
@ -685,11 +672,11 @@ impl DrivingSimState {
time: Tick,
car: CarID,
maybe_parked_car: Option<ParkedCar>,
vehicle: Vehicle,
dist_along: Distance,
start: LaneID,
router: Router,
map: &Map,
properties: &BTreeMap<CarID, Vehicle>,
) -> bool {
// If not, we have a parking lane much longer than a driving lane...
assert!(dist_along <= map.get_l(start).length());
@ -710,12 +697,12 @@ impl DrivingSimState {
return false;
}
let other_vehicle = &properties[&other];
let other_vehicle = &self.cars[&other].vehicle;
let accel_for_other_to_stop = other_vehicle
.accel_to_follow(
self.cars[&other].speed,
map.get_parent(start).get_speed_limit(),
&properties[&car],
&vehicle,
dist_along - other_dist,
0.0 * si::MPS,
).unwrap();
@ -736,6 +723,7 @@ impl DrivingSimState {
dist_along: dist_along,
speed: 0.0 * si::MPS,
on: On::Lane(start),
vehicle,
waiting_for: None,
debug: false,
is_bus: !maybe_parked_car.is_some(),
@ -757,17 +745,10 @@ impl DrivingSimState {
true
}
pub fn get_draw_car(
&self,
id: CarID,
time: Tick,
map: &Map,
properties: &BTreeMap<CarID, Vehicle>,
) -> Option<DrawCarInput> {
pub fn get_draw_car(&self, id: CarID, time: Tick, map: &Map) -> Option<DrawCarInput> {
let c = self.cars.get(&id)?;
let (base_pos, angle) = c.on.dist_along(c.dist_along, map);
let vehicle = &properties[&id];
let stopping_dist = vehicle.stopping_distance(c.speed);
let stopping_dist = c.vehicle.stopping_distance(c.speed);
// TODO arguably, this math might belong in DrawCar.
let pos = if let Some(ref parking) = c.parking {
@ -787,7 +768,7 @@ impl DrivingSimState {
Some(DrawCarInput {
id: c.id,
vehicle_length: vehicle.length,
vehicle_length: c.vehicle.length,
waiting_for_turn: c.waiting_for.and_then(|on| on.maybe_turn()),
front: pos,
angle,
@ -795,25 +776,13 @@ impl DrivingSimState {
})
}
pub fn get_draw_cars_on_lane(
&self,
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_lane(&self, lane: LaneID, time: Tick, map: &Map) -> Vec<DrawCarInput> {
self.lanes[lane.0].get_draw_cars(self, map, time)
}
pub fn get_draw_cars_on_turn(
&self,
turn: TurnID,
time: Tick,
map: &Map,
properties: &BTreeMap<CarID, Vehicle>,
) -> Vec<DrawCarInput> {
pub fn get_draw_cars_on_turn(&self, turn: TurnID, time: Tick, map: &Map) -> Vec<DrawCarInput> {
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();
}
@ -831,6 +800,7 @@ impl DrivingSimState {
on: c.on,
dist_along: c.dist_along,
speed: c.speed,
vehicle: Some(c.vehicle.clone()),
},
);
}

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,6 @@ use geom::{Angle, Polygon, Pt2D};
use kinematics::Vehicle;
use map_model;
use map_model::{Lane, LaneID, LaneType, Map};
use std::collections::BTreeMap;
use std::iter;
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> {
let mut spots: Vec<ParkingSpot> = Vec::new();
for l in &self.lanes {
for (idx, occupant) in l.occupants.iter().enumerate() {
if occupant.is_none() {
for (idx, maybe_occupant) in l.occupants.iter().enumerate() {
if maybe_occupant.is_none() {
// Just match based on the front of the spot
if in_poly
.map(|p| p.contains_pt(l.spots[idx].pos))
@ -68,43 +67,36 @@ impl ParkingSimState {
}
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;
}
pub fn add_parked_car(&mut self, p: ParkedCar) {
assert_eq!(self.lanes[p.spot.lane.0].occupants[p.spot.idx], None);
self.lanes[p.spot.lane.0].occupants[p.spot.idx] = Some(p.car);
let spot = p.spot;
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;
}
pub fn get_draw_cars(
&self,
id: LaneID,
properties: &BTreeMap<CarID, Vehicle>,
) -> Vec<DrawCarInput> {
self.lanes[id.0].get_draw_cars(properties)
pub fn get_draw_cars(&self, id: LaneID) -> Vec<DrawCarInput> {
self.lanes[id.0].get_draw_cars()
}
pub fn get_draw_car(
&self,
id: CarID,
properties: &BTreeMap<CarID, Vehicle>,
) -> Option<DrawCarInput> {
pub fn get_draw_car(&self, id: CarID) -> Option<DrawCarInput> {
// TODO this is so horrendously slow :D
for l in &self.lanes {
if l.occupants.contains(&Some(id)) {
return l.get_draw_cars(properties).into_iter().find(|c| c.id == id);
if l.occupants.iter().find(|x| is_car(x, id)).is_some() {
return l.get_draw_cars().into_iter().find(|c| c.id == id);
}
}
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
for l in &self.lanes {
if let Some(idx) = l.occupants.iter().position(|x| *x == Some(id)) {
return Some(ParkedCar::new(id, ParkingSpot::new(l.id, idx)));
if let Some(p) = l.occupants.iter().find(|x| is_car(x, id)) {
return p.as_ref();
}
}
None
@ -113,14 +105,14 @@ impl ParkingSimState {
pub fn get_all_parked_cars(&self, in_poly: Option<&Polygon>) -> Vec<ParkedCar> {
let mut result = Vec::new();
for l in &self.lanes {
for (idx, maybe_car) in l.occupants.iter().enumerate() {
if let Some(car) = maybe_car {
for maybe_occupant in &l.occupants {
if let Some(occupant) = maybe_occupant {
// Just match based on the front of the spot
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)
{
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> {
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 {
@ -160,7 +152,7 @@ impl ParkingSimState {
struct ParkingLane {
id: LaneID,
spots: Vec<ParkingSpotGeometry>,
occupants: Vec<Option<CarID>>,
occupants: Vec<Option<ParkedCar>>,
}
// TODO the f64's prevent derivation
@ -198,22 +190,25 @@ impl ParkingLane {
}
}
fn remove_parked_car(&mut self, car: CarID) {
let idx = self.occupants.iter().position(|x| *x == Some(car)).unwrap();
fn remove_parked_car(&mut self, p: ParkedCar) {
let match_against = Some(p.clone());
let idx = self
.occupants
.iter()
.position(|x| *x == match_against)
.unwrap();
self.occupants[idx] = None;
}
fn get_draw_cars(&self, properties: &BTreeMap<CarID, Vehicle>) -> Vec<DrawCarInput> {
fn get_draw_cars(&self) -> Vec<DrawCarInput> {
self.occupants
.iter()
.enumerate()
.filter_map(|(idx, maybe_id)| {
maybe_id.and_then(|id| {
let vehicle = &properties[&id];
let (front, angle) = self.spots[idx].front_of_car(vehicle);
.filter_map(|maybe_occupant| {
maybe_occupant.as_ref().and_then(|p| {
let (front, angle) = self.spots[p.spot.idx].front_of_car(&p.vehicle);
Some(DrawCarInput {
id: id,
vehicle_length: vehicle.length,
id: p.car,
vehicle_length: p.vehicle.length,
waiting_for_turn: None,
front: front,
angle: angle,
@ -224,7 +219,7 @@ impl ParkingLane {
}
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 instrument::capture_backtrace;
use intersections::IntersectionSimState;
use kinematics::Vehicle;
use map_model::{IntersectionID, LaneID, LaneType, Map, Turn, TurnID};
use parking::ParkingSimState;
use rand::{FromEntropy, SeedableRng, XorShiftRng};
use spawn::Spawner;
use std;
use std::collections::BTreeMap;
use std::f64;
use std::process;
use std::time::{Duration, Instant};
@ -50,8 +48,6 @@ pub struct Sim {
pub(crate) walking_state: WalkingSimState,
pub(crate) transit_state: TransitSimState,
pub(crate) trips_state: TripManager,
pub(crate) car_properties: BTreeMap<CarID, Vehicle>,
}
impl Sim {
@ -80,7 +76,6 @@ impl Sim {
map_name: map.get_name().to_string(),
run_name,
savestate_every,
car_properties: BTreeMap::new(),
}
}
@ -156,7 +151,6 @@ impl Sim {
&mut self.walking_state,
&mut self.driving_state,
&mut self.trips_state,
&self.car_properties,
);
for p in self.driving_state.step(
@ -168,9 +162,8 @@ impl Sim {
&mut self.intersection_state,
&mut self.transit_state,
&mut self.rng,
&self.car_properties,
)? {
events.push(Event::CarReachedParkingSpot(p.clone()));
events.push(Event::CarReachedParkingSpot(p.car, p.spot));
capture_backtrace("CarReachedParkingSpot");
self.parking_state.add_parked_car(p.clone());
self.spawner.car_reached_parking_spot(
@ -232,8 +225,8 @@ impl Sim {
pub fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCarInput> {
self.driving_state
.get_draw_car(id, self.time, map, &self.car_properties)
.or_else(|| self.parking_state.get_draw_car(id, &self.car_properties))
.get_draw_car(id, self.time, map)
.or_else(|| self.parking_state.get_draw_car(id))
}
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?
pub fn get_draw_cars_on_lane(&self, l: LaneID, map: &Map) -> Vec<DrawCarInput> {
match map.get_l(l).lane_type {
LaneType::Driving => {
self.driving_state
.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::Driving => self.driving_state.get_draw_cars_on_lane(l, self.time, map),
LaneType::Parking => self.parking_state.get_draw_cars(l),
LaneType::Sidewalk => Vec::new(),
LaneType::Biking => Vec::new(),
}
}
pub fn get_draw_cars_on_turn(&self, t: TurnID, map: &Map) -> Vec<DrawCarInput> {
self.driving_state
.get_draw_cars_on_turn(t, self.time, map, &self.car_properties)
self.driving_state.get_draw_cars_on_turn(t, self.time, map)
}
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 rand::Rng;
use router::Router;
use std::collections::{BTreeMap, VecDeque};
use std::collections::VecDeque;
use std::time::Instant;
use transit::TransitSimState;
use trips::{TripLeg, TripManager};
@ -77,7 +77,6 @@ impl Spawner {
walking_sim: &mut WalkingSimState,
driving_sim: &mut DrivingSimState,
trips: &mut TripManager,
properties: &BTreeMap<CarID, Vehicle>,
) {
let mut commands: Vec<Command> = 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
// due to diagonals
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();
if driving_sim.start_car_on_lane(
events,
now,
car,
Some(parked_car.clone()),
parked_car.vehicle.clone(),
dist_along,
start,
Router::make_router_to_park(path, goal_bldg),
map,
properties,
) {
trips.agent_starting_trip_leg(AgentID::Car(car), trip);
parking_sim.remove_parked_car(parked_car.clone());
@ -161,7 +160,6 @@ impl Spawner {
driving_sim: &mut DrivingSimState,
transit_sim: &mut TransitSimState,
now: Tick,
car_properties: &mut BTreeMap<CarID, Vehicle>,
) -> Vec<CarID> {
let route_id = transit_sim.create_empty_route(route, map);
let mut results: Vec<CarID> = Vec::new();
@ -179,15 +177,14 @@ impl Spawner {
now,
id,
None,
vehicle,
start_dist_along,
start,
Router::make_router_for_bus(path),
map,
car_properties,
) {
transit_sim.bus_created(id, route_id, next_stop_idx);
info!("Spawned bus {} for route {} ({})", id, route.name, route_id);
car_properties.insert(id, vehicle);
results.push(id);
} else {
warn!(
@ -205,7 +202,6 @@ impl Spawner {
percent_capacity_to_fill: f64,
in_poly: Option<&Polygon>,
parking_sim: &mut ParkingSimState,
car_properties: &mut BTreeMap<CarID, Vehicle>,
rng: &mut R,
) {
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);
// TODO since spawning applies during the next step, lots of stuff breaks without
// this :(
parking_sim.add_parked_car(ParkedCar::new(car, spot));
car_properties.insert(car, Vehicle::generate_typical_car(car, rng));
parking_sim.add_parked_car(ParkedCar::new(
car,
spot,
Vehicle::generate_typical_car(car, rng),
));
self.car_id_counter += 1;
}
}
@ -236,7 +235,6 @@ impl Spawner {
lane: LaneID,
spot_indices: Vec<usize>,
parking_sim: &mut ParkingSimState,
car_properties: &mut BTreeMap<CarID, Vehicle>,
rng: &mut R,
) -> Vec<CarID> {
let spots = parking_sim.get_all_spots(lane);
@ -244,9 +242,12 @@ impl Spawner {
.into_iter()
.map(|idx| {
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;
car_properties.insert(car, Vehicle::generate_typical_car(car, rng));
car
}).collect()
}

View File

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

View File

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

View File

@ -24,10 +24,10 @@ fn park_on_goal_st() {
sim.run_until_expectations_met(
&map,
&control_map,
vec![sim::Event::CarReachedParkingSpot(sim::ParkedCar::new(
vec![sim::Event::CarReachedParkingSpot(
car,
sim::ParkingSpot::new(parking2, 4),
))],
)],
sim::Tick::from_minutes(1),
);
sim.run_until_done(&map, &control_map, Box::new(|_sim| {}));
@ -49,10 +49,10 @@ fn wander_around_for_parking() {
sim.run_until_expectations_met(
&map,
&control_map,
vec![sim::Event::CarReachedParkingSpot(sim::ParkedCar::new(
vec![sim::Event::CarReachedParkingSpot(
car,
sim::ParkingSpot::new(parking1, 0),
))],
)],
sim::Tick::from_minutes(2),
);
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) {
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);
(map, control_map, sim)
}