From 56c885e7ab9ff3bc9de363588f08df97cff42f77 Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Mon, 26 Nov 2018 10:09:53 -0800 Subject: [PATCH] revive the first parking test. make helpers to look up labeled stuff from synthetic maps. make helpers to seed specific parked cars and start certain trips again. --- .../{parking test.json => parking_test.json} | 2 +- map_model/src/map.rs | 33 ++++ sim/src/helpers.rs | 41 ++++- sim/src/make/load.rs | 14 +- sim/src/spawn.rs | 28 ++++ tests/Cargo.toml | 1 + tests/src/main.rs | 1 + tests/src/parking.rs | 145 ++++-------------- 8 files changed, 148 insertions(+), 117 deletions(-) rename data/synthetic_maps/{parking test.json => parking_test.json} (97%) diff --git a/data/synthetic_maps/parking test.json b/data/synthetic_maps/parking_test.json similarity index 97% rename from data/synthetic_maps/parking test.json rename to data/synthetic_maps/parking_test.json index 7bc564499b..03eeaf9e5a 100644 --- a/data/synthetic_maps/parking test.json +++ b/data/synthetic_maps/parking_test.json @@ -1,5 +1,5 @@ { - "name": "parking test", + "name": "parking_test", "intersections": [ [ 0, diff --git a/map_model/src/map.rs b/map_model/src/map.rs index d202b70708..7303bb2b62 100644 --- a/map_model/src/map.rs +++ b/map_model/src/map.rs @@ -545,6 +545,39 @@ impl Map { let from = self.get_b(bldg).front_path.sidewalk; self.find_closest_lane(from, types) } + + // TODO reconsider names, or put somewhere else? + pub fn bldg(&self, label: &str) -> BuildingID { + for b in &self.buildings { + if b.osm_tags.get("label") == Some(&label.to_string()) { + return b.id; + } + } + panic!("No building has label {}", label); + } + + pub fn parking_lane(&self, label: &str, expected_spots: usize) -> LaneID { + for l in &self.lanes { + if !l.is_parking() { + continue; + } + let r = self.get_parent(l.id); + if (r.is_forwards(l.id) && r.osm_tags.get("fwd_label") == Some(&label.to_string())) + || (r.is_backwards(l.id) + && r.osm_tags.get("back_label") == Some(&label.to_string())) + { + let actual_spots = l.number_parking_spots(); + if expected_spots != actual_spots { + panic!( + "Parking lane {} (labeled {}) has {} spots, not {}", + l.id, label, actual_spots, expected_spots + ); + } + return l.id; + } + } + panic!("No parking lane has label {}", label); + } } fn is_border(intersection: &Intersection, map: &Map) -> bool { diff --git a/sim/src/helpers.rs b/sim/src/helpers.rs index db6285668b..19893b1cdd 100644 --- a/sim/src/helpers.rs +++ b/sim/src/helpers.rs @@ -1,6 +1,7 @@ use abstutil::WeightedUsizeChoice; use control::ControlMap; -use map_model::{BuildingID, BusRoute, Map, RoadID}; +use driving::DrivingGoal; +use map_model::{BuildingID, BusRoute, LaneID, Map, RoadID}; use std::collections::{BTreeSet, VecDeque}; use std::panic; use { @@ -155,6 +156,44 @@ impl Sim { ); } + // TODO This is for tests; rename or move it? + pub fn seed_specific_parked_cars( + &mut self, + lane: LaneID, + owner_building: BuildingID, + spots: Vec, + ) -> Vec { + self.spawner.seed_specific_parked_cars( + lane, + owner_building, + spots, + &mut self.parking_state, + &mut self.rng, + ) + } + + // TODO This is for tests; rename or move it? + pub fn seed_trip_using_parked_car( + &mut self, + from_bldg: BuildingID, + to_bldg: BuildingID, + car: CarID, + map: &Map, + ) { + self.spawner.start_trip_using_parked_car( + Tick::zero(), + map, + self.parking_state + .lookup_car(car) + .map(|p| p.clone()) + .unwrap(), + &self.parking_state, + from_bldg, + DrivingGoal::ParkNear(to_bldg), + &mut self.trips_state, + ); + } + pub fn seed_bus_route(&mut self, route: &BusRoute, map: &Map) -> Vec { // TODO throw away the events? :( let mut events: Vec = Vec::new(); diff --git a/sim/src/make/load.rs b/sim/src/make/load.rs index 5056c9ac94..f19a616129 100644 --- a/sim/src/make/load.rs +++ b/sim/src/make/load.rs @@ -24,9 +24,14 @@ pub struct SimFlags { } impl SimFlags { + // TODO rename seattle_test pub fn for_test(run_name: &str) -> SimFlags { + SimFlags::synthetic_test("montlake", run_name) + } + + pub fn synthetic_test(map: &str, run_name: &str) -> SimFlags { SimFlags { - load: "../data/raw_maps/montlake.abst".to_string(), + load: format!("../data/raw_maps/{}.abst", map), rng_seed: Some(42), run_name: run_name.to_string(), edits_name: "no_edits".to_string(), @@ -105,8 +110,8 @@ pub fn load( .to_string(); info!("Loading map {}", flags.load); let edits = load_edits(&map_name, &flags); - let map = - Map::new(&flags.load, edits.road_edits.clone(), timer).expect("Couldn't load map"); + let map = Map::new(&flags.load, edits.road_edits.clone(), timer) + .expect(&format!("Couldn't load map from {}", flags.load)); let control_map = ControlMap::new(&map, edits.stop_signs, edits.traffic_signals); timer.start("create sim"); let sim = Sim::new(&map, flags.run_name, flags.rng_seed, savestate_every); @@ -116,7 +121,8 @@ pub fn load( assert_eq!(flags.edits_name, "no_edits"); info!("Loading map {}", flags.load); - let map: Map = abstutil::read_binary(&flags.load, timer).expect("Couldn't load map"); + let map: Map = abstutil::read_binary(&flags.load, timer) + .expect(&format!("Couldn't load map from {}", flags.load)); // TODO Bit sad to load edits to reconstitute ControlMap, but this is necessary right now let edits: MapEdits = abstutil::read_json(&format!( "../data/edits/{}/{}.json", diff --git a/sim/src/spawn.rs b/sim/src/spawn.rs index a3d59ac8c6..0eec5038cd 100644 --- a/sim/src/spawn.rs +++ b/sim/src/spawn.rs @@ -339,6 +339,32 @@ impl Spawner { results } + // This happens immediately; it isn't scheduled. + // TODO This is for tests; rename or move it? + // TODO duplication of code, weird responsibilities here... + pub fn seed_specific_parked_cars( + &mut self, + lane: LaneID, + owner_building: BuildingID, + spots: Vec, + parking_sim: &mut ParkingSimState, + base_rng: &mut XorShiftRng, + ) -> Vec { + let mut results: Vec = Vec::new(); + for idx in spots.into_iter() { + let car = CarID(self.car_id_counter); + parking_sim.add_parked_car(ParkedCar::new( + car, + ParkingSpot::new(lane, idx), + Vehicle::generate_car(car, base_rng), + Some(owner_building), + )); + self.car_id_counter += 1; + results.push(car); + } + results + } + // This happens immediately; it isn't scheduled. pub fn seed_parked_cars( &mut self, @@ -458,6 +484,8 @@ impl Spawner { return; } + assert_eq!(parked.owner, Some(start_bldg)); + let ped_id = PedestrianID(self.ped_id_counter); self.ped_id_counter += 1; diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 65bcf85464..e74bbb37ba 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -9,6 +9,7 @@ convert_osm = { path = "../convert_osm" } dimensioned = { git = "https://github.com/paholg/dimensioned", rev = "0e1076ebfa5128d1ee544bdc9754c948987b6fe3", features = ["serde"] } gag = "0.1.10" geom = { path = "../geom" } +map_model = { path = "../map_model" } sim = { path = "../sim" } structopt = "0.2" yansi = "0.4.0" diff --git a/tests/src/main.rs b/tests/src/main.rs index c06a8e972d..52eed8e560 100644 --- a/tests/src/main.rs +++ b/tests/src/main.rs @@ -3,6 +3,7 @@ extern crate convert_osm; extern crate dimensioned; extern crate gag; extern crate geom; +extern crate map_model; extern crate sim; extern crate structopt; extern crate yansi; diff --git a/tests/src/parking.rs b/tests/src/parking.rs index 7d3a48bed8..f4fe80f072 100644 --- a/tests/src/parking.rs +++ b/tests/src/parking.rs @@ -1,33 +1,45 @@ +use abstutil::Timer; use runner::TestRunner; +use sim; -pub fn run(_t: &mut TestRunner) {} +pub fn run(t: &mut TestRunner) { + t.run_slow( + "park_on_goal_st", + Box::new(|h| { + let (map, control_map, mut sim) = sim::load( + sim::SimFlags::synthetic_test("parking_test", "park_on_goal_st"), + None, + &mut Timer::new("setup test"), + ); -/* -#[test] -fn park_on_goal_st() { - let (map, control_map, mut sim) = setup("park_on_goal_st", make_test_map()); - let (south_parking, north_parking) = (LaneID(1), LaneID(4)); - let (north_bldg, south_bldg) = (BuildingID(0), BuildingID(1)); + let north_bldg = map.bldg("north"); + let south_bldg = map.bldg("south"); + let north_parking = map.parking_lane("north", 18); + let south_parking = map.parking_lane("south", 18); - assert_eq!(map.get_l(south_parking).number_parking_spots(), 8); - assert_eq!(map.get_l(north_parking).number_parking_spots(), 8); - let car = sim.seed_specific_parked_cars(south_parking, south_bldg, (0..8).collect())[2]; - sim.seed_specific_parked_cars(north_parking, north_bldg, (0..4).collect()); - sim.seed_specific_parked_cars(north_parking, north_bldg, (5..8).collect()); - sim.make_ped_using_car(&map, car, north_bldg); + let car = sim.seed_specific_parked_cars(south_parking, south_bldg, vec![2])[0]; + // Fill up some of the first spots, forcing parking to happen at spot 4 + sim.seed_specific_parked_cars(north_parking, north_bldg, (0..4).collect()); + sim.seed_specific_parked_cars(north_parking, north_bldg, (5..10).collect()); + // TODO I just want to say (south_bldg, north_bldg), not mode... + sim.seed_trip_using_parked_car(south_bldg, north_bldg, car, &map); + h.setup_done(&sim); - sim.run_until_expectations_met( - &map, - &control_map, - vec![sim::Event::CarReachedParkingSpot( - car, - sim::ParkingSpot::new(north_parking, 4), - )], - sim::Tick::from_minutes(1), + sim.run_until_expectations_met( + &map, + &control_map, + vec![sim::Event::CarReachedParkingSpot( + car, + sim::ParkingSpot::new(north_parking, 4), + )], + 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| {})); } +/* #[test] fn wander_around_for_parking() { let (map, control_map, mut sim) = setup("wander_around_for_parking", make_test_map()); @@ -53,93 +65,4 @@ fn wander_around_for_parking() { ); sim.run_until_done(&map, &control_map, Box::new(|_sim| {})); } - -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 sim = sim::Sim::new(&map, run_name.to_string(), Some(rng_seed), None); - (map, control_map, sim) -} - -// Creates a test map with a single two-way road -fn make_test_map() -> map_model::Map { - use dimensioned::si; - use map_model::{raw_data, LaneType}; - - let left = geom::LonLat::new(100.0, 50.0); - let right = geom::LonLat::new(200.0, 50.0); - - let north_pts = triangle_around(150.0, 10.0); - let south_pts = triangle_around(150.0, 90.0); - - let map = map_model::Map::create_from_raw( - "test_map".to_string(), - raw_data::Map { - roads: vec![raw_data::Road { - points: vec![left, right], - osm_tags: BTreeMap::new(), - osm_way_id: 123, - }], - intersections: vec![ - raw_data::Intersection { - point: left, - elevation: 0.0 * si::M, - has_traffic_signal: false, - }, - raw_data::Intersection { - point: right, - elevation: 0.0 * si::M, - has_traffic_signal: false, - }, - ], - buildings: vec![ - raw_data::Building { - points: north_pts, - osm_tags: BTreeMap::new(), - osm_way_id: 456, - }, - raw_data::Building { - points: south_pts, - osm_tags: BTreeMap::new(), - osm_way_id: 789, - }, - ], - parcels: Vec::new(), - bus_routes: Vec::new(), - areas: Vec::new(), - coordinates_in_world_space: true, - }, - map_model::RoadEdits::new(), - &mut abstutil::Timer::new("setup test"), - ); - - assert_eq!(map.all_roads().len(), 1); - // The south side, unless I'm backwards >< - assert_eq!( - map.get_r(map_model::RoadID(0)).children_forwards, - vec![ - (LaneID(0), LaneType::Driving), - (LaneID(1), LaneType::Parking), - (LaneID(2), LaneType::Sidewalk), - ] - ); - // The north side - assert_eq!( - map.get_r(map_model::RoadID(0)).children_backwards, - vec![ - (LaneID(3), LaneType::Driving), - (LaneID(4), LaneType::Parking), - (LaneID(5), LaneType::Sidewalk), - ] - ); - map -} - -fn triangle_around(x: f64, y: f64) -> Vec { - vec![ - geom::LonLat::new(x - 5.0, y - 5.0), - geom::LonLat::new(x + 5.0, y - 5.0), - geom::LonLat::new(x, y + 5.0), - ] -} */