diff --git a/docs/design/biking.md b/docs/design/biking.md index a46722f83c..c2bb671dda 100644 --- a/docs/design/biking.md +++ b/docs/design/biking.md @@ -3,3 +3,31 @@ ## Bike lanes How do we model bikes merging to a driving lane to make a left? + +## General modeling + +Bikes are just like cars and can use all the same code, right? Except... + +- different speeds +- can use bike or driving lanes +- they dont park or unpark + - actually, how does a ped start/stop using a bike? + - modeling bike lockup locations is overkill. in practice not a + problem. fixed 60s penalty to start/stop biking. penalty happens on + the sidewalk, then they spawn onto the bike/driving lane at the very end +- they can _maybe_ overtake on a bike lane? + - nah, that should be modeled as two bike lanes (or a bike and driving lane) and normal lanechanging behavior +- different rendering +- dont want to use CarID; could maybe rename it VehicleID, but then bike-specific code (like rendering) gets weird + +Because of the orchestration with walking/biking models, I'm tempted to try to share some common code, but keep things a bit separate. However, if they're separate... + +- driving lookahead needs to see bikes and vice versa + - do the SimQueues need to be state that both models can access? + + +Do this in a branch for sure. Roughly: +- introduce BikeID, the rendering, stubs for spawning +- lift SimQueues into Sim +- refactor lookahead +- add biking model diff --git a/docs/design/sim.md b/docs/design/sim.md index 87a7acbec3..02fba12bda 100644 --- a/docs/design/sim.md +++ b/docs/design/sim.md @@ -17,6 +17,8 @@ currently begin departing, it'll keep trying every tick. - serde tricks - unit tests +- https://gafferongames.com/post/deterministic_lockstep/ +- https://gafferongames.com/post/floating_point_determinism/ ## Modeling choices diff --git a/docs/project/references.md b/docs/project/references.md index f9e5e4727b..e46705f759 100644 --- a/docs/project/references.md +++ b/docs/project/references.md @@ -10,6 +10,9 @@ - Seattle Times Traffic Lab - https://www.citylab.com/transportation/2018/08/is-it-time-to-rethink-what-a-bike-lane-is/568483/ +- http://openseattle.org/ +- https://igniteseattle.com/ +- http://seattlegreenways.org/ ## Similar projects diff --git a/sim/src/fsm.rs b/sim/src/fsm.rs new file mode 100644 index 0000000000..eea76945e7 --- /dev/null +++ b/sim/src/fsm.rs @@ -0,0 +1,80 @@ +use dimensioned::si; +use geom::Pt2D; +use map_model::{BuildingID, BusStopID, LaneID, Map, TurnID}; +use {CarID, Distance, ParkingSpot, RouteID, Time}; + +// This is experimental for now, but it might subsume the entire design of the sim crate. + +// TODO From a conversation with Julian: have to prune the search dramatically. After hopping in a +// car, we do have the option of parking anywhere, but we really only want to try to park close to +// the goal, which we can't plan in advance anyway. +// +// Possibly want a high- and low-level plan. The high-level one roughly plans TripLegs. + +// TODO It's very tempting to have a different action for each modality. CrossDrivingLane, +// CrossSidewalk. +enum Action { + // Cars (including buses) and pedestrians + CrossLane(LaneID), + CrossTurn(TurnID), + + // Only cars + ParkingCar(CarID, ParkingSpot), + UnparkingCar(CarID, ParkingSpot), + // TODO Lanechanging + + // Only pedestrians + CrossLaneContraflow(LaneID), + CrossPathFromBuildingToSidewalk(BuildingID), + CrossPathFromSidewalkToBuilding(BuildingID), + WaitForBus(BusStopID, RouteID), + // (from, to) + RideBus(BusStopID, BusStopID), + + // Only buses + DeboardPassengers(BusStopID), + BoardPassengers(BusStopID), +} + +impl Action { + // These are always lower bounds, aka, the best case. + fn cost(&self, map: &Map) -> Time { + // TODO driving speed limits and these could depend on preferences of the individual + // ped/vehicle + let ped_speed = 3.9 * si::MPS; + + match *self { + // TODO wait, we need to know if a ped or car is crossing something + Action::CrossLane(id) => map.get_l(id).length() / map.get_parent(id).get_speed_limit(), + Action::CrossTurn(id) => { + map.get_t(id).length() / map.get_parent(id.dst).get_speed_limit() + } + Action::ParkingCar(_, _) => 20.0 * si::S, + Action::UnparkingCar(_, _) => 10.0 * si::S, + Action::CrossLaneContraflow(id) => map.get_l(id).length() / ped_speed, + Action::CrossPathFromBuildingToSidewalk(id) + | Action::CrossPathFromSidewalkToBuilding(id) => { + map.get_b(id).front_path.line.length() / ped_speed + } + // TODO Could try lots of things here... + Action::WaitForBus(_, _) => 60.0 * si::S, + // TODO Cache the expected time to travel between stops + Action::RideBus(_stop1, _stop2) => 300.0 * si::S, + + _ => panic!("TODO"), + } + } + + // After completing this action, how far will we be from the goal? + // Does this need to be admissible? + // TODO hard to convert distance and time + fn heuristic(&self, goal: Pt2D) -> Distance { + // TODO + 0.0 * si::M + } + + fn next_steps(&self) -> Vec { + // TODO + Vec::new() + } +} diff --git a/sim/src/lib.rs b/sim/src/lib.rs index 2ff3661ef8..30a1976f97 100644 --- a/sim/src/lib.rs +++ b/sim/src/lib.rs @@ -32,6 +32,7 @@ mod macros; mod driving; mod events; +//mod fsm; mod helpers; mod instrument; mod intersections;