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.

This commit is contained in:
Dustin Carlino 2018-11-26 10:09:53 -08:00
parent a9ff1906ad
commit 56c885e7ab
8 changed files with 148 additions and 117 deletions

View File

@ -1,5 +1,5 @@
{
"name": "parking test",
"name": "parking_test",
"intersections": [
[
0,

View File

@ -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 {

View File

@ -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<usize>,
) -> Vec<CarID> {
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<CarID> {
// TODO throw away the events? :(
let mut events: Vec<Event> = Vec::new();

View File

@ -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",

View File

@ -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<usize>,
parking_sim: &mut ParkingSimState,
base_rng: &mut XorShiftRng,
) -> Vec<CarID> {
let mut results: Vec<CarID> = 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;

View File

@ -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"

View File

@ -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;

View File

@ -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<geom::LonLat> {
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),
]
}
*/