instantiate bus routes from GTFS too

This commit is contained in:
Dustin Carlino 2018-09-07 12:47:45 -07:00
parent 143084a8a9
commit 58b01fce9e
6 changed files with 69 additions and 44 deletions

View File

@ -34,3 +34,10 @@ pub use parcel::{Parcel, ParcelID};
pub use pathfind::pathfind;
pub use road::{Road, RoadID};
pub use turn::{Turn, TurnID};
// TODO This sort of doesn't fit in the map layer, but it's quite convenient to store it.
#[derive(Serialize, Deserialize, Debug)]
pub struct BusRoute {
pub name: String,
pub stops: Vec<BusStop>,
}

View File

@ -4,20 +4,23 @@ use gtfs;
use make::sidewalk_finder::find_sidewalk_points;
use multimap::MultiMap;
use ordered_float::NotNaN;
use std::collections::HashSet;
use {BusStop, BusStopDetails, Lane, LaneID, Road};
use std::collections::{HashMap, HashSet};
use {BusRoute, BusStop, BusStopDetails, Lane, LaneID, Road};
pub fn make_bus_stops(
lanes: &mut Vec<Lane>,
roads: &Vec<Road>,
bus_routes: &Vec<gtfs::Route>,
bounds: &Bounds,
) {
) -> Vec<BusRoute> {
let mut bus_stop_pts: HashSet<HashablePt2D> = HashSet::new();
let mut route_lookups: MultiMap<String, HashablePt2D> = MultiMap::new();
for route in bus_routes {
for gps in &route.stops {
if bounds.contains(gps.longitude, gps.latitude) {
bus_stop_pts.insert(Pt2D::from_gps(&gps, bounds).into());
let pt: HashablePt2D = Pt2D::from_gps(&gps, bounds).into();
bus_stop_pts.insert(pt);
route_lookups.insert(route.name.to_string(), pt);
}
}
}
@ -27,23 +30,39 @@ pub fn make_bus_stops(
bus_routes.len()
);
let mut stops_per_sidewalk: MultiMap<LaneID, si::Meter<f64>> = MultiMap::new();
for (lane, dist_along) in find_sidewalk_points(bus_stop_pts, lanes).values() {
stops_per_sidewalk.insert(*lane, *dist_along);
let mut stops_per_sidewalk: MultiMap<LaneID, (si::Meter<f64>, HashablePt2D)> = MultiMap::new();
for (pt, (lane, dist_along)) in find_sidewalk_points(bus_stop_pts, lanes).iter() {
stops_per_sidewalk.insert(*lane, (*dist_along, *pt));
}
let mut point_to_stop_idx: HashMap<HashablePt2D, BusStop> = HashMap::new();
for (id, dists) in stops_per_sidewalk.iter_all_mut() {
// TODO duplicate a little logic from map, and also, this is fragile :)
let road = &roads[lanes[id.0].parent.0];
let parking = road.find_parking_lane(*id).unwrap();
let driving_lane = road.find_driving_lane(parking).unwrap();
dists.sort_by_key(|dist| NotNaN::new(dist.value_unsafe).unwrap());
for (idx, dist_along) in dists.iter().enumerate() {
dists.sort_by_key(|(dist, _)| NotNaN::new(dist.value_unsafe).unwrap());
for (idx, (dist_along, orig_pt)) in dists.iter().enumerate() {
let stop_id = BusStop { sidewalk: *id, idx };
point_to_stop_idx.insert(*orig_pt, stop_id);
lanes[id.0].bus_stops.push(BusStopDetails {
id: BusStop { sidewalk: *id, idx },
id: stop_id,
driving_lane,
dist_along: *dist_along,
});
}
}
let mut results: Vec<BusRoute> = Vec::new();
for (route_name, stop_points) in route_lookups.iter_all() {
if stop_points.len() == 1 {
//println!("Skipping route {} since it only has 1 stop in the slice of the map", route_name);
continue;
}
results.push(BusRoute {
name: route_name.to_string(),
stops: stop_points.iter().map(|pt| point_to_stop_idx[pt]).collect(),
});
}
results
}

View File

@ -1,20 +1,18 @@
// Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0
use abstutil;
use building::{Building, BuildingID};
use edits::Edits;
use geom::{Bounds, HashablePt2D, PolyLine, Pt2D};
use geometry;
use intersection::{Intersection, IntersectionID};
use lane::{BusStop, BusStopDetails, Lane, LaneID, LaneType};
use make;
use parcel::{Parcel, ParcelID};
use raw_data;
use road::{Road, RoadID};
use std::collections::{BTreeMap, HashMap};
use std::io::Error;
use std::path;
use turn::{Turn, TurnID};
use {
Building, BuildingID, BusRoute, BusStop, BusStopDetails, Intersection, IntersectionID, Lane,
LaneID, LaneType, Parcel, ParcelID, Road, RoadID, Turn, TurnID,
};
#[derive(Serialize, Deserialize, Debug)]
pub struct Map {
@ -24,6 +22,7 @@ pub struct Map {
turns: BTreeMap<TurnID, Turn>,
buildings: Vec<Building>,
parcels: Vec<Parcel>,
bus_routes: Vec<BusRoute>,
// TODO maybe dont need to retain GPS stuff later
bounds: Bounds,
@ -57,6 +56,7 @@ impl Map {
turns: BTreeMap::new(),
buildings: Vec::new(),
parcels: Vec::new(),
bus_routes: Vec::new(),
};
let mut pt_to_intersection: HashMap<HashablePt2D, IntersectionID> = HashMap::new();
@ -152,7 +152,7 @@ impl Map {
}
}
make::make_bus_stops(&mut m.lanes, &m.roads, &data.bus_routes, &bounds);
m.bus_routes = make::make_bus_stops(&mut m.lanes, &m.roads, &data.bus_routes, &bounds);
for i in &m.intersections {
for t in make::make_all_turns(i, &m) {
@ -363,4 +363,8 @@ impl Map {
pub fn get_bus_stop(&self, stop: BusStop) -> &BusStopDetails {
&self.get_l(stop.sidewalk).bus_stops[stop.idx]
}
pub fn get_all_bus_routes(&self) -> &Vec<BusRoute> {
&self.bus_routes
}
}

View File

@ -1,6 +1,6 @@
use abstutil;
use control::ControlMap;
use map_model::{BuildingID, BusStop, Edits, LaneID, Map};
use map_model::{BuildingID, BusRoute, BusStop, Edits, LaneID, Map};
use rand::Rng;
use std::collections::VecDeque;
use {CarID, Event, PedestrianID, RouteID, Sim, Tick};
@ -94,16 +94,8 @@ impl Sim {
self.seed_walking_trips(&map, 100);
self.seed_driving_trips(&map, 100);
if self.seed_bus_route(
vec![
map.get_l(LaneID(309)).bus_stops[0].id,
map.get_l(LaneID(325)).bus_stops[0].id,
map.get_l(LaneID(840)).bus_stops[0].id,
],
map,
).len() != 3
{
panic!("Three buses didn't fit");
for route in map.get_all_bus_routes() {
self.seed_bus_route(route, map);
}
// TODO this is introducing nondeterminism, because of slight floating point errors.
// fragile that this causes it, but true. :\
@ -131,13 +123,13 @@ impl Sim {
}
}
pub fn seed_bus_route(&mut self, stops: Vec<BusStop>, map: &Map) -> Vec<CarID> {
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();
let mut result: Vec<CarID> = Vec::new();
for v in self.spawner.seed_bus_route(
&mut events,
stops,
route,
&mut self.rng,
map,
&mut self.driving_state,

View File

@ -1,7 +1,7 @@
use driving::DrivingSimState;
use kinematics::Vehicle;
use map_model;
use map_model::{BuildingID, BusStop, LaneID, Map};
use map_model::{BuildingID, BusRoute, BusStop, LaneID, Map};
use parking::ParkingSimState;
use rand::Rng;
use router::Router;
@ -166,7 +166,7 @@ impl Spawner {
pub fn seed_bus_route<R: Rng + ?Sized>(
&mut self,
events: &mut Vec<Event>,
stops: Vec<BusStop>,
route: &BusRoute,
rng: &mut R,
map: &Map,
driving_sim: &mut DrivingSimState,
@ -174,11 +174,11 @@ impl Spawner {
now: Tick,
properties: &BTreeMap<CarID, Vehicle>,
) -> Vec<Vehicle> {
let route = transit_sim.create_empty_route(stops, map);
let route_id = transit_sim.create_empty_route(route, map);
let mut vehicles: Vec<Vehicle> = Vec::new();
// Try to spawn a bus at each stop
for (next_stop_idx, start_dist_along, mut path) in
transit_sim.get_route_starts(route, map).into_iter()
transit_sim.get_route_starts(route_id, map).into_iter()
{
let id = CarID(self.car_id_counter);
self.car_id_counter += 1;
@ -196,13 +196,13 @@ impl Spawner {
map,
properties,
) {
transit_sim.bus_created(id, route, next_stop_idx);
println!("Spawned bus {} for route {}", id, route);
transit_sim.bus_created(id, route_id, next_stop_idx);
println!("Spawned bus {} for route {} ({})", id, route.name, route_id);
vehicles.push(vehicle);
} else {
println!(
"No room for a bus headed towards stop {} of {}, giving up",
next_stop_idx, route
"No room for a bus headed towards stop {} of {} ({}), giving up",
next_stop_idx, route.name, route_id
);
}
}

View File

@ -3,7 +3,7 @@ use dimensioned::si;
use events::Event;
use instrument::capture_backtrace;
use map_model;
use map_model::{BusStop, BusStopDetails, LaneID, Map};
use map_model::{BusRoute, BusStopDetails, LaneID, Map};
use spawn::Spawner;
use std::collections::{BTreeMap, VecDeque};
use trips::TripManager;
@ -17,6 +17,7 @@ type StopIdx = usize;
#[derive(Serialize, Deserialize, PartialEq, Eq)]
struct Route {
id: RouteID,
name: String,
buses: Vec<CarID>,
stops: Vec<BusStopDetails>,
// TODO info on schedules
@ -65,17 +66,19 @@ impl TransitSimState {
}
}
pub fn create_empty_route(&mut self, stops: Vec<BusStop>, map: &Map) -> RouteID {
assert!(stops.len() > 1);
pub fn create_empty_route(&mut self, route: &BusRoute, map: &Map) -> RouteID {
assert!(route.stops.len() > 1);
let id = RouteID(self.routes.len());
self.routes.insert(
id,
Route {
id,
name: route.name.clone(),
buses: Vec::new(),
stops: stops
.into_iter()
.map(|s| map.get_bus_stop(s).clone())
stops: route
.stops
.iter()
.map(|s| map.get_bus_stop(*s).clone())
.collect(),
},
);