mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-29 04:35:51 +03:00
starting a very basic plugin to show differences between trips in parallel worlds
This commit is contained in:
parent
41817d3e91
commit
2c110a58f9
@ -135,13 +135,8 @@ though... Can we fork RNG for that too?
|
||||
|
||||
Problems:
|
||||
- CarIDs are different, could make them be original parking spot
|
||||
- Missing trip ID, different ped IDs
|
||||
= gen_range on different inputs
|
||||
|
||||
|
||||
|
||||
Alright, now how do peds picking a car work?
|
||||
|
||||
## Parked cars and ownership
|
||||
|
||||
Most cars are associated with a household. They usually park close to that
|
||||
@ -155,3 +150,41 @@ Given:
|
||||
Can then seed parked cars kinda greedily.
|
||||
|
||||
But back up, other section.
|
||||
|
||||
Alright, now how do peds picking a car work?
|
||||
- easy case: if the same car is present in both worlds, should use the same
|
||||
- if cars are associated with buildings in a stable way, this should probably
|
||||
help or at least push the problem to a slightly more explicit place
|
||||
- if a parking lane is gone and an agent wouldve used something there, of
|
||||
course they have to walk farther to get to their car. but we want to somehow
|
||||
localize these effects. same number of parked cars in the neighborhood and same
|
||||
assignment to buildings, but maybe some other lane gets more crowded?
|
||||
|
||||
Next thoughts:
|
||||
- scrap the concept of SeedParkedCars. instead say "x% of buildings in this neighborhood have 1 or 2 cars." peds from these buildings will use those specific cars, others wont.
|
||||
- probability of 0 cars = 40, 1 car = 40, 2 cars = 20 <--- thats much nicer
|
||||
- go through each building, find a spot to seed that parked car.
|
||||
- try to be close to building, random jitter to be a little far away
|
||||
- if this process is somewhat stable, then should be fine. doesnt need to be perfectly stable -- removing lanes somewhere might put more pressure on another lane.
|
||||
|
||||
## Traces between worlds
|
||||
|
||||
Alright, now how do we even compare trip progress to show it visually? This is
|
||||
kind of a UI-only problem; total score at the end can be compared way more
|
||||
easily.
|
||||
|
||||
- easy case: if both worlds are using the same mode AND route, trace_route the
|
||||
slower agent with the dist_ahead of the faster agent (difference between the
|
||||
two)
|
||||
- alright, have to track current distance traveled to do this. can keep
|
||||
state per trip leg or something.
|
||||
- if it's unclear who's closer to the goal, could just pathfind to exactly
|
||||
where the other agent is, display in a neutral way
|
||||
- mode changes are potentially weird... but just slide over between sidewalks and driving lanes? mmm...
|
||||
- strawman: dont use the trace route thing, just have a straight arrow to the
|
||||
other agent and green/red based on straight-line distance to goal bldg
|
||||
- progress is non-monotonic -- might walk away from goal to get to car, then get there faster. or maybe get stuck in traffic. so straightline distance to goal is EXPECTED to fluctuate. thats kind of exciting to watch anyway.
|
||||
|
||||
Ah, upon seeing just the line between, I know what would make more sense --
|
||||
show the divergence. The point in the route where one version goes one way, and
|
||||
the second goes another. Two routes shown, symmetric.
|
||||
|
@ -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, TripID};
|
||||
use sim::{AgentID, CarID, PedestrianID, Sim, TripID};
|
||||
|
||||
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
|
||||
pub enum ID {
|
||||
@ -23,6 +23,14 @@ pub enum ID {
|
||||
}
|
||||
|
||||
impl ID {
|
||||
pub fn agent_id(&self) -> Option<AgentID> {
|
||||
match *self {
|
||||
ID::Car(id) => Some(AgentID::Car(id)),
|
||||
ID::Pedestrian(id) => Some(AgentID::Pedestrian(id)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn debug(&self, map: &Map, control_map: &ControlMap, sim: &mut Sim) {
|
||||
match *self {
|
||||
ID::Lane(id) => {
|
||||
|
@ -1,5 +1,6 @@
|
||||
use ezgui::{Canvas, GfxCtx, LogScroller, UserInput, Wizard, WrappedWizard};
|
||||
use map_model::Map;
|
||||
use objects::ID;
|
||||
use objects::SIM_SETUP;
|
||||
use piston::input::Key;
|
||||
use plugins::{choose_edits, choose_scenario, load_ab_test, Colorizer};
|
||||
@ -21,6 +22,7 @@ impl ABTestManager {
|
||||
pub fn event(
|
||||
&mut self,
|
||||
input: &mut UserInput,
|
||||
selected: Option<ID>,
|
||||
map: &Map,
|
||||
kml: &Option<String>,
|
||||
current_flags: &SimFlags,
|
||||
@ -29,7 +31,9 @@ impl ABTestManager {
|
||||
let mut new_state: Option<ABTestManager> = None;
|
||||
match self {
|
||||
ABTestManager::Inactive => {
|
||||
if input.unimportant_key_pressed(Key::B, SIM_SETUP, "manage A/B tests") {
|
||||
if selected.is_none()
|
||||
&& input.unimportant_key_pressed(Key::B, SIM_SETUP, "manage A/B tests")
|
||||
{
|
||||
new_state = Some(ABTestManager::PickABTest(Wizard::new()));
|
||||
}
|
||||
}
|
||||
|
83
editor/src/plugins/diff_worlds.rs
Normal file
83
editor/src/plugins/diff_worlds.rs
Normal file
@ -0,0 +1,83 @@
|
||||
use colors::ColorScheme;
|
||||
use ezgui::{GfxCtx, UserInput};
|
||||
use geom::Line;
|
||||
use map_model::LANE_THICKNESS;
|
||||
use piston::input::Key;
|
||||
use plugins::Colorizer;
|
||||
use sim::TripID;
|
||||
use ui::PerMapUI;
|
||||
|
||||
pub enum DiffWorldsState {
|
||||
Inactive,
|
||||
// The Line just points from the agent in the primary sim to the agent in the secondary.
|
||||
Active(TripID, Line),
|
||||
}
|
||||
|
||||
impl DiffWorldsState {
|
||||
pub fn new() -> DiffWorldsState {
|
||||
DiffWorldsState::Inactive
|
||||
}
|
||||
|
||||
pub fn event(
|
||||
&mut self,
|
||||
input: &mut UserInput,
|
||||
primary: &PerMapUI,
|
||||
secondary: &Option<PerMapUI>,
|
||||
) -> bool {
|
||||
let mut maybe_trip: Option<TripID> = None;
|
||||
match self {
|
||||
DiffWorldsState::Inactive => {
|
||||
if secondary.is_some() {
|
||||
if let Some(id) = primary.current_selection.and_then(|id| id.agent_id()) {
|
||||
let trip = primary.sim.agent_to_trip(id);
|
||||
if input.key_pressed(Key::B, &format!("Show {}'s parallel world", trip)) {
|
||||
maybe_trip = Some(trip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DiffWorldsState::Active(trip, _) => {
|
||||
if input.key_pressed(
|
||||
Key::Return,
|
||||
&format!("Stop showing {}'s parallel world", trip),
|
||||
) {
|
||||
maybe_trip = None;
|
||||
} else {
|
||||
maybe_trip = Some(*trip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(id) = maybe_trip {
|
||||
let pt1 = primary.sim.get_canonical_point_for_trip(id, &primary.map);
|
||||
let pt2 = secondary
|
||||
.as_ref()
|
||||
.and_then(|s| s.sim.get_canonical_point_for_trip(id, &s.map));
|
||||
if pt1.is_some() && pt2.is_some() {
|
||||
*self = DiffWorldsState::Active(id, Line::new(pt1.unwrap(), pt2.unwrap()));
|
||||
} else {
|
||||
warn!(
|
||||
"{} isn't present in both sims, cancelling DiffWorldsState",
|
||||
id
|
||||
);
|
||||
*self = DiffWorldsState::Inactive;
|
||||
}
|
||||
} else {
|
||||
*self = DiffWorldsState::Inactive;
|
||||
}
|
||||
|
||||
match self {
|
||||
DiffWorldsState::Inactive => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(&self, g: &mut GfxCtx, _cs: &ColorScheme) {
|
||||
if let DiffWorldsState::Active(_, ref line) = self {
|
||||
// TODO move constants
|
||||
g.draw_line([1.0, 1.0, 0.0, 1.0], LANE_THICKNESS, line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Colorizer for DiffWorldsState {}
|
@ -3,6 +3,7 @@ pub mod chokepoints;
|
||||
pub mod classification;
|
||||
pub mod color_picker;
|
||||
pub mod debug_objects;
|
||||
pub mod diff_worlds;
|
||||
pub mod draw_neighborhoods;
|
||||
pub mod floodfill;
|
||||
pub mod follow;
|
||||
|
@ -16,6 +16,7 @@ use plugins::chokepoints::ChokepointsFinder;
|
||||
use plugins::classification::OsmClassifier;
|
||||
use plugins::color_picker::ColorPicker;
|
||||
use plugins::debug_objects::DebugObjectsState;
|
||||
use plugins::diff_worlds::DiffWorldsState;
|
||||
use plugins::draw_neighborhoods::DrawNeighborhoodState;
|
||||
use plugins::floodfill::Floodfiller;
|
||||
use plugins::follow::FollowState;
|
||||
@ -80,6 +81,7 @@ impl UIWrapper {
|
||||
color_picker: ColorPicker::new(),
|
||||
ab_test_manager: ABTestManager::new(),
|
||||
logs,
|
||||
diff_worlds: DiffWorldsState::new(),
|
||||
|
||||
active_plugin: None,
|
||||
|
||||
@ -252,6 +254,7 @@ impl UIWrapper {
|
||||
Box::new(|ctx| {
|
||||
let (active, new_ui) = ctx.ui.ab_test_manager.event(
|
||||
ctx.input,
|
||||
ctx.ui.primary.current_selection,
|
||||
&ctx.ui.primary.map,
|
||||
&ctx.ui.kml,
|
||||
&ctx.ui.primary.current_flags,
|
||||
@ -263,6 +266,11 @@ impl UIWrapper {
|
||||
active
|
||||
}),
|
||||
Box::new(|ctx| ctx.ui.logs.event(ctx.input)),
|
||||
Box::new(|ctx| {
|
||||
ctx.ui
|
||||
.diff_worlds
|
||||
.event(ctx.input, &ctx.ui.primary, &ctx.ui.secondary)
|
||||
}),
|
||||
],
|
||||
}
|
||||
}
|
||||
@ -361,6 +369,7 @@ struct UI {
|
||||
color_picker: ColorPicker,
|
||||
ab_test_manager: ABTestManager,
|
||||
logs: DisplayLogs,
|
||||
diff_worlds: DiffWorldsState,
|
||||
|
||||
// An index into UIWrapper.plugins.
|
||||
active_plugin: Option<usize>,
|
||||
@ -550,6 +559,7 @@ impl UI {
|
||||
self.warp.draw(g, &self.canvas);
|
||||
self.sim_ctrl.draw(g, &self.canvas);
|
||||
self.primary.show_route.draw(g, &self.cs);
|
||||
self.diff_worlds.draw(g, &self.cs);
|
||||
|
||||
self.canvas.draw_text(g, osd, BOTTOM_LEFT);
|
||||
}
|
||||
@ -604,6 +614,7 @@ impl UI {
|
||||
19 => Some(Box::new(&self.primary.chokepoints)),
|
||||
20 => Some(Box::new(&self.ab_test_manager)),
|
||||
21 => Some(Box::new(&self.logs)),
|
||||
22 => Some(Box::new(&self.diff_worlds)),
|
||||
_ => panic!("Active plugin {} is too high", idx),
|
||||
}
|
||||
}
|
||||
|
@ -378,6 +378,10 @@ impl Sim {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn agent_to_trip(&self, id: AgentID) -> TripID {
|
||||
self.trips_state.agent_to_trip(id)
|
||||
}
|
||||
|
||||
pub fn get_canonical_point_for_trip(&self, id: TripID, map: &Map) -> Option<Pt2D> {
|
||||
// Don't unwrap(); the trip might be registered before the agent has started.
|
||||
match self.trips_state.current_mode(id) {
|
||||
|
@ -235,6 +235,10 @@ impl TripManager {
|
||||
TripLeg::RideBus(_, _) => Some(AgentID::Pedestrian(trip.ped)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn agent_to_trip(&self, id: AgentID) -> TripID {
|
||||
self.active_trip_mode[&id]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
|
||||
|
Loading…
Reference in New Issue
Block a user