From 80f6eb95b4106f91a8a73697aff922aaf72842f6 Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Sat, 13 Oct 2018 19:08:15 -0700 Subject: [PATCH] brainstorming edit-invariant trips. initial work to reference TripIDs, which are independent of mode. --- docs/design/sim.md | 20 ++++++++++++++++++++ docs/references.md | 4 ++++ editor/src/objects.rs | 7 ++++++- editor/src/plugins/warp.rs | 5 +++-- editor/src/render/map.rs | 6 ++++-- sim/src/sim.rs | 26 +++++++++++++++++++++++++- sim/src/trips.rs | 10 ++++++++++ 7 files changed, 72 insertions(+), 6 deletions(-) diff --git a/docs/design/sim.md b/docs/design/sim.md index 01a4bc49f4..824a77dfa5 100644 --- a/docs/design/sim.md +++ b/docs/design/sim.md @@ -83,3 +83,23 @@ But let's start super simple: just track total trip time for all agents. What's - note that sum score alone is a bit meaningless, even between population types. need to A/B test to meaningfully compare. - In headless mode, print scores at the end - in UI, have an optional OSD to pop up on the right with scores so far + +## Edit-Invariant + +Back in the day, TurnID went from a number to (Lane, Lane, Intersection), so +that a single edit wouldn't totally throw off all the turn IDs. Now seeing a +similar problem when removing a parking lane -- the same 'seed parked cars' +command has vastly different effects between the same sim, and this tiny change +throws off the RNG and percolates everywhere. Let's think about how to make +more things invariant. + +- should cars be the same? + - maybe peds have to travel farther from home to start driving. + - does the car on the far road belong to anyone in the other sim? +- forget debugability for a moment, what do we actually need to compare? + - entire trips! maybe some use a bus or not btwn two worlds + - warp to trip (using the active mode), compare trips + - problem: ped IDs right now differ wildly because the rng gets offset. maybe those should always be chosen first? maybe they should be calculated independently and stuck in the Scenario? that part of a trip is a sim-invariant ID, a spawn time, and a start/goal building. the details (legs of trip) are calculated per sim. +- the RNG is also used after spawning to later roam around for parking + - small road edits shouldnt affect this. per-car rng in an extreme, or maybe just an RNG for sim and for spawning? + - but as soon as two cars have to wander for parking instead of one, everything gets offset completely. diff --git a/docs/references.md b/docs/references.md index 8b513f943a..579c186517 100644 --- a/docs/references.md +++ b/docs/references.md @@ -1,5 +1,9 @@ # References +## Example use cases + +- https://www.reddit.com/r/SeattleWA/comments/9mtgkh/seven_places_to_add_bus_lanes_now/ + ## Groups that may be eventually interested - Seattle Times Traffic Lab diff --git a/editor/src/objects.rs b/editor/src/objects.rs index 70bcc5ab89..1666546feb 100644 --- a/editor/src/objects.rs +++ b/editor/src/objects.rs @@ -5,7 +5,7 @@ use geom::Pt2D; use kml::ExtraShapeID; use map_model::{AreaID, BuildingID, BusStopID, IntersectionID, LaneID, Map, ParcelID, TurnID}; use render::DrawMap; -use sim::{CarID, PedestrianID, Sim}; +use sim::{CarID, PedestrianID, Sim, TripID}; #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)] pub enum ID { @@ -19,6 +19,7 @@ pub enum ID { Parcel(ParcelID), BusStop(BusStopID), Area(AreaID), + Trip(TripID), } impl ID { @@ -51,6 +52,9 @@ impl ID { ID::Area(id) => { map.get_a(id).dump_debug(); } + ID::Trip(id) => { + sim.debug_trip(id); + } } } @@ -69,6 +73,7 @@ impl ID { .maybe_get_bs(id) .map(|bs| map.get_l(id.sidewalk).dist_along(bs.dist_along).0), ID::Area(id) => map.maybe_get_a(id).map(|a| Pt2D::center(&a.points)), + ID::Trip(id) => sim.get_canonical_point_for_trip(id, map), } } diff --git a/editor/src/plugins/warp.rs b/editor/src/plugins/warp.rs index f0737b1c26..aed1f317a3 100644 --- a/editor/src/plugins/warp.rs +++ b/editor/src/plugins/warp.rs @@ -4,7 +4,7 @@ use objects::{DEBUG, ID}; use piston::input::Key; use plugins::Colorizer; use render::DrawMap; -use sim::{CarID, PedestrianID, Sim}; +use sim::{CarID, PedestrianID, Sim, TripID}; use std::usize; pub enum WarpState { @@ -93,8 +93,9 @@ fn warp( 'e' => ID::Parcel(ParcelID(idx)), 'p' => ID::Pedestrian(PedestrianID(idx)), 'c' => ID::Car(CarID(idx)), + 't' => ID::Trip(TripID(idx)), _ => { - warn!("{} isn't a valid ID; Should be [libepc][0-9]+", line); + warn!("{} isn't a valid ID; Should be [libepct][0-9]+", line); return; } }, diff --git a/editor/src/render/map.rs b/editor/src/render/map.rs index ae4ec4efba..731ea793b3 100644 --- a/editor/src/render/map.rs +++ b/editor/src/render/map.rs @@ -182,7 +182,9 @@ impl DrawMap { ID::BusStop(id) => Box::new(self.get_bs(id)), ID::Parcel(id) => Box::new(self.get_p(id)), ID::Area(id) => Box::new(self.get_a(id)), - ID::Car(_) | ID::Pedestrian(_) => panic!("get_obj doesn't work for dynamic {:?}", id), + ID::Car(_) | ID::Pedestrian(_) | ID::Trip(_) => { + panic!("get_obj doesn't work for dynamic {:?}", id) + } } } @@ -284,7 +286,7 @@ impl DrawMap { ID::ExtraShape(id) => extra_shapes.push(Box::new(self.get_es(*id))), ID::BusStop(id) => bus_stops.push(Box::new(self.get_bs(*id))), - ID::Turn(_) | ID::Car(_) | ID::Pedestrian(_) => { + ID::Turn(_) | ID::Car(_) | ID::Pedestrian(_) | ID::Trip(_) => { panic!("{:?} shouldn't be in the quadtree", id) } } diff --git a/sim/src/sim.rs b/sim/src/sim.rs index 642990fe3c..6a186223ae 100644 --- a/sim/src/sim.rs +++ b/sim/src/sim.rs @@ -5,6 +5,7 @@ use abstutil::Error; use control::ControlMap; use dimensioned::si; use driving::DrivingSimState; +use geom::Pt2D; use instrument::capture_backtrace; use intersections::IntersectionSimState; use map_model::{IntersectionID, LaneID, LaneType, Map, Trace, Turn, TurnID}; @@ -21,7 +22,7 @@ use view::WorldView; use walking::WalkingSimState; use { AgentID, CarID, CarState, Distance, DrawCarInput, DrawPedestrianInput, Event, PedestrianID, - ScoreSummary, Tick, TIMESTEP, + ScoreSummary, Tick, TripID, TIMESTEP, }; #[derive(Serialize, Deserialize, Derivative)] @@ -367,6 +368,29 @@ impl Sim { pub fn get_name(&self) -> &str { &self.run_name } + + // TODO dont toggle state in debug_car + pub fn debug_trip(&mut self, id: TripID) { + match self.trips_state.current_mode(id) { + Some(AgentID::Car(id)) => self.debug_car(id), + Some(AgentID::Pedestrian(id)) => self.debug_ped(id), + None => println!("{} doesn't exist", id), + } + } + + pub fn get_canonical_point_for_trip(&self, id: TripID, map: &Map) -> Option { + // Don't unwrap(); the trip might be registered before the agent has started. + match self.trips_state.current_mode(id) { + Some(AgentID::Car(id)) => self + .driving_state + .get_draw_car(id, self.time, map) + .map(|c| c.front), + Some(AgentID::Pedestrian(id)) => { + self.walking_state.get_draw_ped(id, map).map(|p| p.pos) + } + None => None, + } + } } pub struct Benchmark { diff --git a/sim/src/trips.rs b/sim/src/trips.rs index 4360acbdd0..b2e7403d9a 100644 --- a/sim/src/trips.rs +++ b/sim/src/trips.rs @@ -225,6 +225,16 @@ impl TripManager { pub fn active_agents(&self) -> Vec { self.active_trip_mode.keys().cloned().collect() } + + pub fn current_mode(&self, id: TripID) -> Option { + let trip = self.trips.get(id.0)?; + match trip.legs[0] { + TripLeg::Walk(_) => Some(AgentID::Pedestrian(trip.ped)), + TripLeg::Drive(ref parked, _) => Some(AgentID::Car(parked.car)), + // TODO Should be the bus, but apparently transit sim tracks differently? + TripLeg::RideBus(_, _) => Some(AgentID::Pedestrian(trip.ped)), + } + } } #[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]