WIP storing per-car properties like accel somewhere

This commit is contained in:
Dustin Carlino 2018-08-20 08:49:59 -07:00
parent e2ee2ecc84
commit 917c3c3ed5
6 changed files with 157 additions and 49 deletions

View File

@ -548,3 +548,11 @@ Some first tests to write:
- a line of cars moving through a stop sign looks jittery right now. correct or not? - a line of cars moving through a stop sign looks jittery right now. correct or not?
Unclear how to nicely let the test inspect stuff every tick. Unclear how to nicely let the test inspect stuff every tick.
## Per-car properties
Need to associate car length between driving and parking sims.
---> could store this in master Sim; after all, there will be some more permanentish stuff like agent/building/trip/owned car soon
- but soon need to bundle things together and pass less params everywhere
- or stash in parking sim, transfer to driving, and back later

View File

@ -85,6 +85,7 @@ impl Car {
sim: &DrivingSimState, sim: &DrivingSimState,
parking_sim: &ParkingSimState, parking_sim: &ParkingSimState,
intersections: &IntersectionSimState, intersections: &IntersectionSimState,
properties: &BTreeMap<CarID, Vehicle>,
) -> Action { ) -> Action {
if self.parking.is_some() { if self.parking.is_some() {
// TODO right place for this check? // TODO right place for this check?
@ -108,7 +109,7 @@ impl Car {
} }
} }
let vehicle = Vehicle::typical_car(); let vehicle = &properties[&self.id];
// TODO could wrap this state up // TODO could wrap this state up
let mut current_speed_limit = self.on.speed_limit(map); let mut current_speed_limit = self.on.speed_limit(map);
@ -153,7 +154,7 @@ impl Car {
let accel = vehicle.accel_to_follow( let accel = vehicle.accel_to_follow(
self.speed, self.speed,
current_speed_limit, current_speed_limit,
&vehicle, &properties[&other.id],
dist_behind_other, dist_behind_other,
other.speed, other.speed,
); );
@ -380,10 +381,16 @@ 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(&self, sim: &DrivingSimState, map: &Map, time: Tick) -> Vec<DrawCar> { fn get_draw_cars(
&self,
sim: &DrivingSimState,
map: &Map,
time: Tick,
properties: &BTreeMap<CarID, Vehicle>,
) -> Vec<DrawCar> {
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).unwrap()) results.push(sim.get_draw_car(*id, time, map, properties).unwrap())
} }
results results
} }
@ -542,11 +549,15 @@ impl DrivingSimState {
parking_sim: &ParkingSimState, parking_sim: &ParkingSimState,
intersections: &mut IntersectionSimState, intersections: &mut IntersectionSimState,
rng: &mut R, rng: &mut R,
properties: &BTreeMap<CarID, Vehicle>,
) -> Result<Vec<CarParking>, InvariantViolated> { ) -> Result<Vec<CarParking>, InvariantViolated> {
// Could be concurrent, since this is deterministic. // Could be concurrent, since this is deterministic.
let mut requested_moves: Vec<(CarID, Action)> = Vec::new(); let mut requested_moves: Vec<(CarID, Action)> = Vec::new();
for c in self.cars.values() { for c in self.cars.values() {
requested_moves.push((c.id, c.react(map, time, self, parking_sim, intersections))); requested_moves.push((
c.id,
c.react(map, time, self, parking_sim, intersections, properties),
));
} }
// In AORTA, there was a split here -- react vs step phase. We're still following the same // In AORTA, there was a split here -- react vs step phase. We're still following the same
@ -648,6 +659,7 @@ impl DrivingSimState {
parking: CarParking, parking: CarParking,
mut path: VecDeque<LaneID>, mut path: VecDeque<LaneID>,
map: &Map, map: &Map,
properties: &BTreeMap<CarID, Vehicle>,
) -> bool { ) -> bool {
let start = path.pop_front().unwrap(); let start = path.pop_front().unwrap();
let dist_along = parking.spot.dist_along; let dist_along = parking.spot.dist_along;
@ -670,11 +682,11 @@ impl DrivingSimState {
return false; return false;
} }
let vehicle = Vehicle::typical_car(); let vehicle = &properties[&car];
let accel_for_other_to_stop = vehicle.accel_to_follow( let accel_for_other_to_stop = vehicle.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(),
&vehicle, &properties[&other],
dist_along - other_dist, dist_along - other_dist,
0.0 * si::MPS, 0.0 * si::MPS,
); );
@ -713,10 +725,16 @@ impl DrivingSimState {
true true
} }
pub fn get_draw_car(&self, id: CarID, time: Tick, map: &Map) -> Option<DrawCar> { pub fn get_draw_car(
&self,
id: CarID,
time: Tick,
map: &Map,
properties: &BTreeMap<CarID, Vehicle>,
) -> Option<DrawCar> {
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 stopping_dist = Vehicle::typical_car().stopping_distance(c.speed); let stopping_dist = properties[&id].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 {
@ -744,13 +762,25 @@ impl DrivingSimState {
)) ))
} }
pub fn get_draw_cars_on_lane(&self, lane: LaneID, time: Tick, map: &Map) -> Vec<DrawCar> { pub fn get_draw_cars_on_lane(
self.lanes[lane.0].get_draw_cars(self, map, time) &self,
lane: LaneID,
time: Tick,
map: &Map,
properties: &BTreeMap<CarID, Vehicle>,
) -> Vec<DrawCar> {
self.lanes[lane.0].get_draw_cars(self, map, time, properties)
} }
pub fn get_draw_cars_on_turn(&self, turn: TurnID, time: Tick, map: &Map) -> Vec<DrawCar> { pub fn get_draw_cars_on_turn(
&self,
turn: TurnID,
time: Tick,
map: &Map,
properties: &BTreeMap<CarID, Vehicle>,
) -> Vec<DrawCar> {
if let Some(queue) = self.turns.get(&turn) { if let Some(queue) = self.turns.get(&turn) {
return queue.get_draw_cars(self, map, time); return queue.get_draw_cars(self, map, time, properties);
} }
return Vec::new(); return Vec::new();
} }

View File

@ -1,8 +1,9 @@
use dimensioned::si; use dimensioned::si;
use geom::EPSILON_DIST; use geom::EPSILON_DIST;
use models::FOLLOWING_DISTANCE; use models::FOLLOWING_DISTANCE;
use rand::Rng;
use std; use std;
use {Acceleration, Distance, Speed, Time, TIMESTEP}; use {Acceleration, CarID, Distance, Speed, Time, TIMESTEP};
pub const EPSILON_SPEED: Speed = si::MeterPerSecond { pub const EPSILON_SPEED: Speed = si::MeterPerSecond {
value_unsafe: 0.00000001, value_unsafe: 0.00000001,
@ -12,18 +13,31 @@ pub const EPSILON_SPEED: Speed = si::MeterPerSecond {
// 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)]
pub struct Vehicle { pub struct Vehicle {
pub id: CarID,
// > 0 // > 0
max_accel: Acceleration, max_accel: Acceleration,
// < 0 // < 0
pub max_deaccel: Acceleration, pub max_deaccel: Acceleration,
} }
// TODO this is used for verifying sim state determinism, so it should actually check everything.
// the f64 prevents this from being derived.
impl PartialEq for Vehicle {
fn eq(&self, other: &Vehicle) -> bool {
self.id == other.id
}
}
impl Eq for Vehicle {}
impl Vehicle { impl Vehicle {
pub fn typical_car() -> Vehicle { pub fn generate_typical_car<R: Rng + ?Sized>(id: CarID, rng: &mut R) -> Vehicle {
Vehicle { Vehicle {
max_accel: 2.7 * si::MPS2, id,
max_deaccel: -2.7 * si::MPS2, max_accel: rng.gen_range(2.4, 2.8) * si::MPS2,
max_deaccel: rng.gen_range(-2.8, -2.4) * si::MPS2,
} }
} }

View File

@ -194,13 +194,20 @@ 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(&self, time: Tick, sim: &DrivingSimState, map: &Map) -> Vec<DrawCar> { fn get_draw_cars(
&self,
time: Tick,
sim: &DrivingSimState,
map: &Map,
properties: &BTreeMap<CarID, Vehicle>,
) -> Vec<DrawCar> {
if self.cars_queue.is_empty() { if self.cars_queue.is_empty() {
return Vec::new(); return Vec::new();
} }
// TODO base this on actual speed ;) // TODO base this on actual speed and each vehicle ;)
let stopping_dist = Vehicle::typical_car().stopping_distance(self.id.speed_limit(map)); let stopping_dist =
properties[&self.cars_queue[0]].stopping_distance(self.id.speed_limit(map));
let mut results = Vec::new(); let mut results = Vec::new();
let (pos1, angle1, dist_along1) = let (pos1, angle1, dist_along1) =
@ -372,6 +379,7 @@ impl DrivingSimState {
_parking_sim: &ParkingSimState, _parking_sim: &ParkingSimState,
intersections: &mut IntersectionSimState, intersections: &mut IntersectionSimState,
_rng: &mut R, _rng: &mut R,
_properties: &BTreeMap<CarID, Vehicle>,
) -> Result<Vec<CarParking>, InvariantViolated> { ) -> Result<Vec<CarParking>, InvariantViolated> {
// Could be concurrent, since this is deterministic. // Could be concurrent, since this is deterministic.
let mut requested_moves: Vec<(CarID, Action)> = Vec::new(); let mut requested_moves: Vec<(CarID, Action)> = Vec::new();
@ -467,6 +475,7 @@ impl DrivingSimState {
_parking: CarParking, _parking: CarParking,
mut path: VecDeque<LaneID>, mut path: VecDeque<LaneID>,
map: &Map, map: &Map,
_properties: &BTreeMap<CarID, Vehicle>,
) -> bool { ) -> bool {
let start = path.pop_front().unwrap(); let start = path.pop_front().unwrap();
@ -491,21 +500,39 @@ impl DrivingSimState {
true true
} }
pub fn get_draw_car(&self, id: CarID, time: Tick, map: &Map) -> Option<DrawCar> { pub fn get_draw_car(
&self,
id: CarID,
time: Tick,
map: &Map,
properties: &BTreeMap<CarID, Vehicle>,
) -> Option<DrawCar> {
let all = match self.cars.get(&id)?.on { let all = match self.cars.get(&id)?.on {
On::Lane(l) => self.get_draw_cars_on_lane(l, time, map), On::Lane(l) => self.get_draw_cars_on_lane(l, time, map, properties),
On::Turn(t) => self.get_draw_cars_on_turn(t, time, map), On::Turn(t) => self.get_draw_cars_on_turn(t, time, map, properties),
}; };
all.into_iter().find(|c| c.id == id) all.into_iter().find(|c| c.id == id)
} }
pub fn get_draw_cars_on_lane(&self, lane: LaneID, time: Tick, map: &Map) -> Vec<DrawCar> { pub fn get_draw_cars_on_lane(
self.lanes[lane.0].get_draw_cars(time, self, map) &self,
lane: LaneID,
time: Tick,
map: &Map,
properties: &BTreeMap<CarID, Vehicle>,
) -> Vec<DrawCar> {
self.lanes[lane.0].get_draw_cars(time, self, map, properties)
} }
pub fn get_draw_cars_on_turn(&self, turn: TurnID, time: Tick, map: &Map) -> Vec<DrawCar> { pub fn get_draw_cars_on_turn(
&self,
turn: TurnID,
time: Tick,
map: &Map,
properties: &BTreeMap<CarID, Vehicle>,
) -> Vec<DrawCar> {
if let Some(queue) = self.turns.get(&turn) { if let Some(queue) = self.turns.get(&turn) {
return queue.get_draw_cars(time, self, map); return queue.get_draw_cars(time, self, map, properties);
} }
return Vec::new(); return Vec::new();
} }

View File

@ -6,12 +6,13 @@ use draw_car::DrawCar;
use draw_ped::DrawPedestrian; use draw_ped::DrawPedestrian;
use driving; use driving;
use intersections::{AgentInfo, IntersectionSimState}; use intersections::{AgentInfo, IntersectionSimState};
use kinematics::Vehicle;
use map_model::{IntersectionID, LaneID, LaneType, Map, Turn, TurnID}; use map_model::{IntersectionID, LaneID, LaneType, Map, Turn, TurnID};
use parametric_driving; use parametric_driving;
use parking::ParkingSimState; use parking::ParkingSimState;
use rand::{FromEntropy, Rng, SeedableRng, XorShiftRng}; use rand::{FromEntropy, Rng, SeedableRng, XorShiftRng};
use spawn::Spawner; use spawn::Spawner;
use std::collections::{HashMap, HashSet, VecDeque}; use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
use std::f64; use std::f64;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use walking::WalkingSimState; use walking::WalkingSimState;
@ -106,18 +107,19 @@ impl DrivingModel {
delegate!(fn edit_add_lane(&mut self, id: LaneID)); delegate!(fn edit_add_lane(&mut self, id: LaneID));
delegate!(fn edit_remove_turn(&mut self, id: TurnID)); delegate!(fn edit_remove_turn(&mut self, id: TurnID));
delegate!(fn edit_add_turn(&mut self, id: TurnID, map: &Map)); delegate!(fn edit_add_turn(&mut self, id: TurnID, map: &Map));
delegate!(fn step<R: Rng + ?Sized>(&mut self, time: Tick, map: &Map, parking: &ParkingSimState, intersections: &mut IntersectionSimState, rng: &mut R) -> Result<Vec<CarParking>, InvariantViolated>); delegate!(fn step<R: Rng + ?Sized>(&mut self, time: Tick, map: &Map, parking: &ParkingSimState, intersections: &mut IntersectionSimState, rng: &mut R, properties: &BTreeMap<CarID, Vehicle>) -> Result<Vec<CarParking>, InvariantViolated>);
delegate!(pub fn start_car_on_lane( delegate!(pub fn start_car_on_lane(
&mut self, &mut self,
time: Tick, time: Tick,
car: CarID, car: CarID,
parking: CarParking, parking: CarParking,
path: VecDeque<LaneID>, path: VecDeque<LaneID>,
map: &Map map: &Map,
properties: &BTreeMap<CarID, Vehicle>
) -> bool); ) -> bool);
delegate!(fn get_draw_car(&self, id: CarID, time: Tick, map: &Map) -> Option<DrawCar>); delegate!(fn get_draw_car(&self, id: CarID, time: Tick, map: &Map, properties: &BTreeMap<CarID, Vehicle>) -> Option<DrawCar>);
delegate!(fn get_draw_cars_on_lane(&self, lane: LaneID, time: Tick, map: &Map) -> Vec<DrawCar>); delegate!(fn get_draw_cars_on_lane(&self, lane: LaneID, time: Tick, map: &Map, properties: &BTreeMap<CarID, Vehicle>) -> Vec<DrawCar>);
delegate!(fn get_draw_cars_on_turn(&self, turn: TurnID, time: Tick, map: &Map) -> Vec<DrawCar>); delegate!(fn get_draw_cars_on_turn(&self, turn: TurnID, time: Tick, map: &Map, properties: &BTreeMap<CarID, Vehicle>) -> Vec<DrawCar>);
} }
#[derive(Serialize, Deserialize, Derivative)] #[derive(Serialize, Deserialize, Derivative)]
@ -134,6 +136,8 @@ pub struct Sim {
driving_state: DrivingModel, driving_state: DrivingModel,
parking_state: ParkingSimState, parking_state: ParkingSimState,
walking_state: WalkingSimState, walking_state: WalkingSimState,
car_properties: BTreeMap<CarID, Vehicle>,
} }
impl Sim { impl Sim {
@ -157,6 +161,7 @@ impl Sim {
parking_state: ParkingSimState::new(map), parking_state: ParkingSimState::new(map),
walking_state: WalkingSimState::new(), walking_state: WalkingSimState::new(),
time: Tick::zero(), time: Tick::zero(),
car_properties: BTreeMap::new(),
} }
} }
@ -193,13 +198,24 @@ impl Sim {
} }
pub fn seed_parked_cars(&mut self, percent: f64) { pub fn seed_parked_cars(&mut self, percent: f64) {
self.spawner for v in self.spawner
.seed_parked_cars(percent, &mut self.parking_state, &mut self.rng); .seed_parked_cars(percent, &mut self.parking_state, &mut self.rng)
.into_iter()
{
self.car_properties.insert(v.id, v);
}
} }
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 let mut ids = Vec::new();
.seed_specific_parked_cars(lane, spots, &mut self.parking_state) for v in self.spawner
.seed_specific_parked_cars(lane, spots, &mut self.parking_state, &mut self.rng)
.into_iter()
{
ids.push(v.id);
self.car_properties.insert(v.id, v);
}
ids
} }
pub fn start_many_parked_cars(&mut self, map: &Map, num_cars: usize) { pub fn start_many_parked_cars(&mut self, map: &Map, num_cars: usize) {
@ -252,6 +268,7 @@ impl Sim {
&mut self.parking_state, &mut self.parking_state,
&mut self.walking_state, &mut self.walking_state,
&mut self.driving_state, &mut self.driving_state,
&self.car_properties,
); );
let mut cars_parked_this_step: Vec<CarParking> = Vec::new(); let mut cars_parked_this_step: Vec<CarParking> = Vec::new();
@ -261,6 +278,7 @@ impl Sim {
&self.parking_state, &self.parking_state,
&mut self.intersection_state, &mut self.intersection_state,
&mut self.rng, &mut self.rng,
&self.car_properties,
) { ) {
Ok(parked_cars) => for p in parked_cars { Ok(parked_cars) => for p in parked_cars {
cars_parked_this_step.push(p.clone()); cars_parked_this_step.push(p.clone());
@ -298,7 +316,7 @@ impl Sim {
pub fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCar> { pub fn get_draw_car(&self, id: CarID, map: &Map) -> Option<DrawCar> {
self.driving_state self.driving_state
.get_draw_car(id, self.time, map) .get_draw_car(id, self.time, map, &self.car_properties)
.or_else(|| self.parking_state.get_draw_car(id, map)) .or_else(|| self.parking_state.get_draw_car(id, map))
} }
@ -309,7 +327,10 @@ 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<DrawCar> { pub fn get_draw_cars_on_lane(&self, l: LaneID, map: &Map) -> Vec<DrawCar> {
match map.get_l(l).lane_type { match map.get_l(l).lane_type {
LaneType::Driving => self.driving_state.get_draw_cars_on_lane(l, self.time, map), 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, map), LaneType::Parking => self.parking_state.get_draw_cars(l, map),
LaneType::Sidewalk => Vec::new(), LaneType::Sidewalk => Vec::new(),
LaneType::Biking => Vec::new(), LaneType::Biking => Vec::new(),
@ -317,7 +338,8 @@ impl Sim {
} }
pub fn get_draw_cars_on_turn(&self, t: TurnID, map: &Map) -> Vec<DrawCar> { pub fn get_draw_cars_on_turn(&self, t: TurnID, map: &Map) -> Vec<DrawCar> {
self.driving_state.get_draw_cars_on_turn(t, self.time, map) self.driving_state
.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<DrawPedestrian> { pub fn get_draw_peds_on_lane(&self, l: LaneID, map: &Map) -> Vec<DrawPedestrian> {

View File

@ -1,9 +1,10 @@
use kinematics::Vehicle;
use map_model; use map_model;
use map_model::{LaneID, Map}; use map_model::{LaneID, Map};
use parking::ParkingSimState; use parking::ParkingSimState;
use rand::Rng; use rand::Rng;
use sim::{CarParking, DrivingModel}; use sim::{CarParking, DrivingModel};
use std::collections::VecDeque; use std::collections::{BTreeMap, VecDeque};
use std::time::Instant; use std::time::Instant;
use walking::WalkingSimState; use walking::WalkingSimState;
use {AgentID, CarID, PedestrianID, Tick}; use {AgentID, CarID, PedestrianID, Tick};
@ -47,6 +48,7 @@ impl Spawner {
parking_sim: &mut ParkingSimState, parking_sim: &mut ParkingSimState,
walking_sim: &mut WalkingSimState, walking_sim: &mut WalkingSimState,
driving_sim: &mut DrivingModel, driving_sim: &mut DrivingModel,
properties: &BTreeMap<CarID, Vehicle>,
) { ) {
for p in self.spawn_parked_cars.drain(0..) { for p in self.spawn_parked_cars.drain(0..) {
parking_sim.add_parked_car(p); parking_sim.add_parked_car(p);
@ -95,6 +97,7 @@ impl Spawner {
CarParking::new(*car, spot), CarParking::new(*car, spot),
VecDeque::from(path), VecDeque::from(path),
map, map,
properties,
) { ) {
parking_sim.remove_parked_car(parking_lane, *car); parking_sim.remove_parked_car(parking_lane, *car);
spawned_agents += 1; spawned_agents += 1;
@ -134,36 +137,40 @@ impl Spawner {
percent_capacity_to_fill: f64, percent_capacity_to_fill: f64,
parking_sim: &mut ParkingSimState, parking_sim: &mut ParkingSimState,
rng: &mut R, rng: &mut R,
) { ) -> Vec<Vehicle> {
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);
assert!(self.spawn_parked_cars.is_empty()); assert!(self.spawn_parked_cars.is_empty());
let mut total_capacity = 0; let mut total_capacity = 0;
let mut new_cars = 0; let mut new_cars: Vec<Vehicle> = Vec::new();
for spot in parking_sim.get_all_free_spots() { for spot in parking_sim.get_all_free_spots() {
total_capacity += 1; total_capacity += 1;
if rng.gen_bool(percent_capacity_to_fill) { if rng.gen_bool(percent_capacity_to_fill) {
new_cars += 1; let id = 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(CarParking::new(CarID(self.car_id_counter), spot)); parking_sim.add_parked_car(CarParking::new(id, spot));
//self.spawn_parked_cars.push(CarParking::new(CarID(self.car_id_counter), spot)); //self.spawn_parked_cars.push(CarParking::new(CarID(self.car_id_counter), spot));
new_cars.push(Vehicle::generate_typical_car(id, rng));
self.car_id_counter += 1; self.car_id_counter += 1;
} }
} }
println!( println!(
"Seeded {} of {} parking spots with cars", "Seeded {} of {} parking spots with cars",
new_cars, total_capacity new_cars.len(),
total_capacity
); );
new_cars
} }
pub fn seed_specific_parked_cars( pub fn seed_specific_parked_cars<R: Rng + ?Sized>(
&mut self, &mut self,
lane: LaneID, lane: LaneID,
spot_indices: Vec<usize>, spot_indices: Vec<usize>,
parking_sim: &mut ParkingSimState, parking_sim: &mut ParkingSimState,
) -> Vec<CarID> { rng: &mut R,
) -> Vec<Vehicle> {
assert!(self.spawn_parked_cars.is_empty()); assert!(self.spawn_parked_cars.is_empty());
let spots = parking_sim.get_all_spots(lane); let spots = parking_sim.get_all_spots(lane);
spot_indices spot_indices
@ -173,7 +180,7 @@ impl Spawner {
parking_sim.add_parked_car(CarParking::new(id, spots[idx].clone())); parking_sim.add_parked_car(CarParking::new(id, spots[idx].clone()));
// TODO push onto spawn_parked_cars? // TODO push onto spawn_parked_cars?
self.car_id_counter += 1; self.car_id_counter += 1;
id Vehicle::generate_typical_car(id, rng)
}) })
.collect() .collect()
} }