diff --git a/map_model/src/lib.rs b/map_model/src/lib.rs index 3283a8bf87..cb6023d89a 100644 --- a/map_model/src/lib.rs +++ b/map_model/src/lib.rs @@ -30,6 +30,7 @@ mod pathfind; pub mod raw_data; mod road; mod trace; +mod traversable; mod turn; pub use area::{Area, AreaID, AreaType}; @@ -43,6 +44,7 @@ pub use parcel::{Parcel, ParcelID}; pub use pathfind::Pathfinder; pub use road::{Road, RoadID}; pub use trace::Trace; +pub use traversable::Traversable; pub use turn::{Turn, TurnID}; pub const LANE_THICKNESS: f64 = 2.5; diff --git a/map_model/src/traversable.rs b/map_model/src/traversable.rs new file mode 100644 index 0000000000..784c53b7dc --- /dev/null +++ b/map_model/src/traversable.rs @@ -0,0 +1,54 @@ +use dimensioned::si; +use geom::{Angle, Pt2D}; +use {LaneID, Map, TurnID}; + +// TODO also building paths? +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] +pub enum Traversable { + Lane(LaneID), + Turn(TurnID), +} + +impl Traversable { + pub fn as_lane(&self) -> LaneID { + match self { + &Traversable::Lane(id) => id, + &Traversable::Turn(_) => panic!("not a lane"), + } + } + + pub fn as_turn(&self) -> TurnID { + match self { + &Traversable::Turn(id) => id, + &Traversable::Lane(_) => panic!("not a turn"), + } + } + + pub fn maybe_turn(&self) -> Option { + match self { + &Traversable::Turn(id) => Some(id), + &Traversable::Lane(_) => None, + } + } + + pub fn length(&self, map: &Map) -> si::Meter { + match self { + &Traversable::Lane(id) => map.get_l(id).length(), + &Traversable::Turn(id) => map.get_t(id).length(), + } + } + + pub fn dist_along(&self, dist: si::Meter, map: &Map) -> (Pt2D, Angle) { + match self { + &Traversable::Lane(id) => map.get_l(id).dist_along(dist), + &Traversable::Turn(id) => map.get_t(id).dist_along(dist), + } + } + + pub fn speed_limit(&self, map: &Map) -> si::MeterPerSecond { + match self { + &Traversable::Lane(id) => map.get_parent(id).get_speed_limit(), + &Traversable::Turn(id) => map.get_parent(id.dst).get_speed_limit(), + } + } +} diff --git a/sim/src/driving.rs b/sim/src/driving.rs index 4a627c898d..476e87ea2b 100644 --- a/sim/src/driving.rs +++ b/sim/src/driving.rs @@ -6,7 +6,7 @@ use geom::EPSILON_DIST; use intersections::{IntersectionSimState, Request}; use kinematics; use kinematics::Vehicle; -use map_model::{LaneID, Map, Trace, TurnID, LANE_THICKNESS}; +use map_model::{LaneID, Map, Trace, Traversable, TurnID, LANE_THICKNESS}; use multimap::MultiMap; use ordered_float::NotNaN; use parking::ParkingSimState; @@ -17,7 +17,7 @@ use std::collections::BTreeMap; use transit::TransitSimState; use view::{AgentView, WorldView}; use { - Acceleration, AgentID, CarID, CarState, Distance, DrawCarInput, Event, InvariantViolated, On, + Acceleration, AgentID, CarID, CarState, Distance, DrawCarInput, Event, InvariantViolated, ParkedCar, ParkingSpot, Speed, Tick, Time, }; @@ -37,7 +37,7 @@ struct ParkingState { #[derive(Clone, Debug, Serialize, Deserialize)] struct Car { id: CarID, - on: On, + on: Traversable, speed: Speed, dist_along: Distance, vehicle: Vehicle, @@ -45,7 +45,7 @@ struct Car { parking: Option, // TODO should this only be turns? - waiting_for: Option, + waiting_for: Option, debug: bool, // TODO ew? :\ @@ -177,7 +177,7 @@ impl Car { } // Stop for something? - if let On::Lane(id) = current_on { + if let Traversable::Lane(id) = current_on { let maybe_stop_early = current_router.stop_early_at_dist( current_on, current_dist_along, @@ -226,11 +226,11 @@ impl Car { break; } current_on = match current_on { - On::Turn(t) => { + Traversable::Turn(t) => { current_router.advance_to(t.dst); - On::Lane(t.dst) + Traversable::Lane(t.dst) } - On::Lane(l) => On::Turn(current_router.choose_turn(l, map)), + Traversable::Lane(l) => Traversable::Turn(current_router.choose_turn(l, map)), }; current_dist_along = 0.0 * si::M; dist_scanned_ahead += dist_this_step; @@ -285,11 +285,11 @@ impl Car { break; } let next_on = match self.on { - On::Turn(t) => On::Lane(map.get_t(t).dst), - On::Lane(l) => On::Turn(router.choose_turn(l, map)), + Traversable::Turn(t) => Traversable::Lane(map.get_t(t).dst), + Traversable::Lane(l) => Traversable::Turn(router.choose_turn(l, map)), }; - if let On::Turn(t) = self.on { + if let Traversable::Turn(t) = self.on { intersections.on_exit(Request::for_car(self.id, t)); router.advance_to(t.dst); } @@ -303,7 +303,7 @@ impl Car { )); self.waiting_for = None; self.on = next_on; - if let On::Turn(t) = self.on { + if let Traversable::Turn(t) = self.on { intersections .on_enter(Request::for_car(self.id, t)) .context(format!( @@ -319,7 +319,7 @@ impl Car { #[derive(Serialize, Deserialize, Clone)] pub struct SimQueue { - id: On, + id: Traversable, // First element is farthest along the queue; they have the greatest dist_along. // Caching the current dist_along vastly simplifies the API of SimQueue. cars_queue: Vec<(Distance, CarID)>, @@ -338,7 +338,7 @@ impl PartialEq for SimQueue { impl Eq for SimQueue {} impl SimQueue { - fn new(id: On, map: &Map) -> SimQueue { + fn new(id: Traversable, map: &Map) -> SimQueue { SimQueue { id, cars_queue: Vec::new(), @@ -444,14 +444,15 @@ impl DrivingSimState { lanes: map .all_lanes() .iter() - .map(|l| SimQueue::new(On::Lane(l.id), map)) + .map(|l| SimQueue::new(Traversable::Lane(l.id), map)) .collect(), turns: BTreeMap::new(), debug: None, }; for t in map.all_turns().values() { if !t.between_sidewalks { - s.turns.insert(t.id, SimQueue::new(On::Turn(t.id), map)); + s.turns + .insert(t.id, SimQueue::new(Traversable::Turn(t.id), map)); } } s @@ -534,7 +535,8 @@ impl DrivingSimState { } pub fn edit_add_turn(&mut self, id: TurnID, map: &Map) { - self.turns.insert(id, SimQueue::new(On::Turn(id), map)); + self.turns + .insert(id, SimQueue::new(Traversable::Turn(id), map)); } // Note that this populates the view BEFORE the step is applied @@ -621,8 +623,10 @@ impl DrivingSimState { // TODO kind of a weird way to figure out when to fill this out... // duplicated with stop sign's check, also. should check that they're a // leader vehicle... - if On::Lane(req.turn.src) == c.on && c.speed <= kinematics::EPSILON_SPEED { - c.waiting_for = Some(On::Turn(req.turn)); + if Traversable::Lane(req.turn.src) == c.on + && c.speed <= kinematics::EPSILON_SPEED + { + c.waiting_for = Some(Traversable::Turn(req.turn)); } } } @@ -636,13 +640,13 @@ impl DrivingSimState { // TODO could simplify this by only adjusting the SimQueues we need above // Group cars by lane and turn - // TODO ideally, just hash On + // TODO ideally, just hash Traversable let mut cars_per_lane = MultiMap::new(); let mut cars_per_turn = MultiMap::new(); for c in self.cars.values() { match c.on { - On::Lane(id) => cars_per_lane.insert(id, c.id), - On::Turn(id) => cars_per_turn.insert(id, c.id), + Traversable::Lane(id) => cars_per_lane.insert(id, c.id), + Traversable::Turn(id) => cars_per_turn.insert(id, c.id), }; } @@ -722,7 +726,7 @@ impl DrivingSimState { id: car, dist_along: dist_along, speed: 0.0 * si::MPS, - on: On::Lane(start), + on: Traversable::Lane(start), vehicle, waiting_for: None, debug: false, @@ -740,7 +744,7 @@ impl DrivingSimState { self.lanes[start.0].insert_at(car, dist_along); events.push(Event::AgentEntersTraversable( AgentID::Car(car), - On::Lane(start), + Traversable::Lane(start), )); true } diff --git a/sim/src/events.rs b/sim/src/events.rs index 70f897aa41..8ff4ef4c16 100644 --- a/sim/src/events.rs +++ b/sim/src/events.rs @@ -1,6 +1,6 @@ use intersections::Request; -use map_model::{BuildingID, BusStopID}; -use {AgentID, CarID, On, ParkingSpot, PedestrianID}; +use map_model::{BuildingID, BusStopID, Traversable}; +use {AgentID, CarID, ParkingSpot, PedestrianID}; #[derive(Debug, PartialEq, Eq)] pub enum Event { @@ -19,8 +19,8 @@ pub enum Event { PedLeavesBus(PedestrianID, CarID), // TODO split up into cases or not? - AgentEntersTraversable(AgentID, On), - AgentLeavesTraversable(AgentID, On), + AgentEntersTraversable(AgentID, Traversable), + AgentLeavesTraversable(AgentID, Traversable), // TODO maybe AgentRequestsTurn? IntersectionAcceptsRequest(Request), diff --git a/sim/src/lib.rs b/sim/src/lib.rs index d886fc7140..1b8a505ad1 100644 --- a/sim/src/lib.rs +++ b/sim/src/lib.rs @@ -60,7 +60,7 @@ pub use events::Event; use geom::{Angle, Pt2D}; pub use helpers::{load, SimFlags}; pub use instrument::save_backtraces; -use map_model::{LaneID, Map, Trace, TurnID}; +use map_model::{LaneID, Trace, TurnID}; pub use scenario::{Neighborhood, Scenario, SeedParkedCars, SpawnOverTime}; pub use sim::{Benchmark, Sim}; use std::fmt; @@ -254,57 +254,6 @@ fn time_parsing() { assert_eq!(Tick::parse("01:02:03.5"), Some(Tick(35 + 1200 + 36000))); } -// TODO this name isn't quite right :) -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] -pub enum On { - Lane(LaneID), - Turn(TurnID), -} - -impl On { - pub fn as_lane(&self) -> LaneID { - match self { - &On::Lane(id) => id, - &On::Turn(_) => panic!("not a lane"), - } - } - - pub fn as_turn(&self) -> TurnID { - match self { - &On::Turn(id) => id, - &On::Lane(_) => panic!("not a turn"), - } - } - - fn maybe_turn(&self) -> Option { - match self { - &On::Turn(id) => Some(id), - &On::Lane(_) => None, - } - } - - fn length(&self, map: &Map) -> Distance { - match self { - &On::Lane(id) => map.get_l(id).length(), - &On::Turn(id) => map.get_t(id).length(), - } - } - - fn dist_along(&self, dist: Distance, map: &Map) -> (Pt2D, Angle) { - match self { - &On::Lane(id) => map.get_l(id).dist_along(dist), - &On::Turn(id) => map.get_t(id).dist_along(dist), - } - } - - fn speed_limit(&self, map: &Map) -> Speed { - match self { - &On::Lane(id) => map.get_parent(id).get_speed_limit(), - &On::Turn(id) => map.get_parent(id.dst).get_speed_limit(), - } - } -} - pub enum CarState { Moving, Stuck, diff --git a/sim/src/router.rs b/sim/src/router.rs index dbec5e7f6d..ef0d0155e7 100644 --- a/sim/src/router.rs +++ b/sim/src/router.rs @@ -2,13 +2,13 @@ use dimensioned::si; use driving::Action; use kinematics; use kinematics::Vehicle; -use map_model::{BuildingID, LaneID, Map, TurnID}; +use map_model::{BuildingID, LaneID, Map, Traversable, TurnID}; use parking::ParkingSimState; use rand::Rng; use std::collections::VecDeque; use transit::TransitSimState; use view::AgentView; -use {Distance, Event, On, ParkingSpot, Tick}; +use {Distance, Event, ParkingSpot, Tick}; #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] enum Goal { @@ -95,7 +95,7 @@ impl Router { pub fn stop_early_at_dist( &self, // TODO urgh, we cant reuse AgentView here, because lookahead doesn't advance the view :( - on: On, + on: Traversable, dist_along: Distance, vehicle: &Vehicle, map: &Map, diff --git a/sim/src/view.rs b/sim/src/view.rs index e245c92141..475a05ea0b 100644 --- a/sim/src/view.rs +++ b/sim/src/view.rs @@ -1,14 +1,14 @@ use driving::SimQueue; use kinematics::Vehicle; -use map_model::TurnID; +use map_model::{Traversable, TurnID}; use std::collections::{BTreeMap, HashMap}; -use {AgentID, CarID, Distance, On, Speed}; +use {AgentID, CarID, Distance, Speed}; // An immutable view that agents and intersection controllers see of agents. pub struct AgentView { pub id: AgentID, pub debug: bool, - pub on: On, + pub on: Traversable, pub dist_along: Distance, pub speed: Speed, pub vehicle: Option, @@ -38,10 +38,10 @@ impl WorldView { } } - pub fn next_car_in_front_of(&self, on: On, dist: Distance) -> Option<&AgentView> { + pub fn next_car_in_front_of(&self, on: Traversable, dist: Distance) -> Option<&AgentView> { let maybe_id = match on { - On::Lane(id) => self.lanes[id.0].next_car_in_front_of(dist), - On::Turn(id) => self.turns[&id].next_car_in_front_of(dist), + Traversable::Lane(id) => self.lanes[id.0].next_car_in_front_of(dist), + Traversable::Turn(id) => self.turns[&id].next_car_in_front_of(dist), }; maybe_id.map(|id| &self.agents[&AgentID::Car(id)]) } diff --git a/sim/src/walking.rs b/sim/src/walking.rs index 4e21f77fbb..b182f7934c 100644 --- a/sim/src/walking.rs +++ b/sim/src/walking.rs @@ -5,7 +5,9 @@ use failure::Error; use geom::{Line, Pt2D}; use instrument::capture_backtrace; use intersections::{IntersectionSimState, Request}; -use map_model::{BuildingID, BusStopID, IntersectionID, Lane, LaneID, Map, Turn, TurnID}; +use map_model::{ + BuildingID, BusStopID, IntersectionID, Lane, LaneID, Map, Traversable, Turn, TurnID, +}; use multimap::MultiMap; use parking::ParkingSimState; use std; @@ -13,8 +15,8 @@ use std::collections::{BTreeMap, VecDeque}; use trips::TripManager; use view::{AgentView, WorldView}; use { - AgentID, Distance, DrawPedestrianInput, Event, InvariantViolated, On, ParkingSpot, - PedestrianID, Speed, Tick, Time, TIMESTEP, + AgentID, Distance, DrawPedestrianInput, Event, InvariantViolated, ParkingSpot, PedestrianID, + Speed, Tick, Time, TIMESTEP, }; // TODO tune these! @@ -91,22 +93,22 @@ enum Action { StartCrossingPath(BuildingID), KeepCrossingPath, Continue, - Goto(On), - WaitFor(On), + Goto(Traversable), + WaitFor(Traversable), } #[derive(Debug, Clone, Serialize, Deserialize)] struct Pedestrian { id: PedestrianID, - on: On, + on: Traversable, dist_along: Distance, // Traveling along the lane/turn in its original direction or not? contraflow: bool, // Head is the next lane path: VecDeque, - waiting_for: Option, + waiting_for: Option, front_path: Option, goal: SidewalkSpot, @@ -153,7 +155,7 @@ impl Pedestrian { return Action::Continue; } - let desired_on: On = { + let desired_on: Traversable = { if let Some(on) = self.waiting_for { on } else { @@ -164,12 +166,12 @@ impl Pedestrian { } match self.on { - On::Lane(id) => { + Traversable::Lane(id) => { let l = map.get_l(id); let at = if self.contraflow { l.src_i } else { l.dst_i }; - On::Turn(self.choose_turn(id, at, map)) + Traversable::Turn(self.choose_turn(id, at, map)) } - On::Turn(id) => On::Lane(map.get_t(id).dst), + Traversable::Turn(id) => Traversable::Lane(map.get_t(id).dst), } } }; @@ -177,8 +179,8 @@ impl Pedestrian { // Can we actually go there right now? let intersection_req_granted = match desired_on { // Already doing a turn, finish it! - On::Lane(_) => true, - On::Turn(id) => intersections.request_granted(Request::for_ped(self.id, id)), + Traversable::Lane(_) => true, + Traversable::Turn(id) => intersections.request_granted(Request::for_ped(self.id, id)), }; if intersection_req_granted { Action::Goto(desired_on) @@ -247,12 +249,12 @@ impl Pedestrian { fn step_goto( &mut self, events: &mut Vec, - on: On, + on: Traversable, map: &Map, intersections: &mut IntersectionSimState, ) -> Result<(), Error> { // Detect if the ped just warped. Bidirectional sidewalks are confusing. :) - if let On::Lane(l) = self.on { + if let Traversable::Lane(l) = self.on { let l = map.get_l(l); let pt1 = if self.contraflow { l.first_pt() @@ -270,7 +272,7 @@ impl Pedestrian { } let old_on = self.on.clone(); - if let On::Turn(t) = self.on { + if let Traversable::Turn(t) = self.on { intersections.on_exit(Request::for_ped(self.id, t)); assert_eq!(self.path[0], map.get_t(t).dst); self.path.pop_front(); @@ -288,10 +290,10 @@ impl Pedestrian { self.dist_along = 0.0 * si::M; self.contraflow = false; match self.on { - On::Turn(t) => { + Traversable::Turn(t) => { intersections.on_enter(Request::for_ped(self.id, t))?; } - On::Lane(l) => { + Traversable::Lane(l) => { // Which end of the sidewalk are we entering? let turn = map.get_t(old_on.as_turn()); let lane = map.get_l(l); @@ -427,7 +429,7 @@ impl WalkingSimState { } Action::WaitFor(on) => { self.peds.get_mut(&id).unwrap().waiting_for = Some(on); - if let On::Turn(t) = on { + if let Traversable::Turn(t) = on { // Note this is idempotent and does NOT grant the request. intersections.submit_request(Request::for_ped(*id, t))?; } @@ -440,8 +442,8 @@ impl WalkingSimState { self.peds_per_turn.clear(); for p in self.peds.values() { match p.on { - On::Lane(id) => self.peds_per_sidewalk.insert(id, p.id), - On::Turn(id) => self.peds_per_turn.insert(id, p.id), + Traversable::Lane(id) => self.peds_per_sidewalk.insert(id, p.id), + Traversable::Turn(id) => self.peds_per_turn.insert(id, p.id), }; } @@ -526,7 +528,7 @@ impl WalkingSimState { id, path, contraflow, - on: On::Lane(start_lane), + on: Traversable::Lane(start_lane), dist_along: start.dist_along, waiting_for: None, front_path, @@ -537,7 +539,7 @@ impl WalkingSimState { self.peds_per_sidewalk.insert(start_lane, id); events.push(Event::AgentEntersTraversable( AgentID::Pedestrian(id), - On::Lane(start_lane), + Traversable::Lane(start_lane), )); }