Skip to content

Commit

Permalink
Make the LTN impact prediction work off autogenerated home-to-work sc…
Browse files Browse the repository at this point in the history
…enarios too.

Most of the work is moving proletariat robot to synthpop, so the LTN
crate doesn't depend on sim. That was a refactor that needed to happen
anyway.
  • Loading branch information
dabreegster committed Aug 4, 2022
1 parent 5722c67 commit 3fa6aba
Show file tree
Hide file tree
Showing 11 changed files with 53 additions and 39 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions apps/ltn/Cargo.toml
Expand Up @@ -26,6 +26,8 @@ log = "0.4"
maplit = "1.0.2"
map_gui = { path = "../../map_gui" }
map_model = { path = "../../map_model" }
rand = "0.8.3"
rand_xorshift = "0.3.0"
regex = "1.5.5"
serde = "1.0.123"
serde_json = "1.0.61"
Expand Down
10 changes: 0 additions & 10 deletions apps/ltn/src/browse.rs
Expand Up @@ -3,7 +3,6 @@ use std::collections::HashSet;
use abstutil::Counter;
use geom::Distance;
use map_gui::tools::{ColorNetwork, DrawRoadLabels};
use synthpop::Scenario;
use widgetry::mapspace::{ToggleZoomed, World, WorldOutcome};
use widgetry::{
Choice, Color, DrawBaselayer, EventCtx, GeomBatch, GfxCtx, Key, Line, Outcome, Panel, State,
Expand Down Expand Up @@ -307,19 +306,10 @@ fn impact_widget(ctx: &EventCtx, app: &App) -> Widget {

if &app.session.impact.map != map_name {
// Starting from scratch
let scenario_name = Scenario::default_scenario_for_map(map_name);
if scenario_name == "home_to_work" {
return "This city doesn't have travel demand model data available".text_widget(ctx);
}
let size = abstio::Manifest::load()
.get_entry(&abstio::path_scenario(map_name, &scenario_name))
.map(|entry| abstutil::prettyprint_bytes(entry.compressed_size_bytes))
.unwrap_or_else(|| "???".to_string());
return Widget::col(vec![
Text::from_multiline(vec![
Line("This will take a moment.").small(),
Line("The app may freeze while calculating.").small(),
Line(format!("We need to load a {} file", size)).small(),
])
.into_widget(ctx),
ctx.style().btn_outline.text("Calculate").build_def(ctx),
Expand Down
35 changes: 25 additions & 10 deletions apps/ltn/src/impact/ui.rs
@@ -1,7 +1,11 @@
use std::collections::BTreeSet;

use rand::SeedableRng;
use rand_xorshift::XorShiftRng;

use map_gui::tools::checkbox_per_mode;
use map_model::{Path, NORMAL_LANE_THICKNESS};
use synthpop::make::ScenarioGenerator;
use synthpop::{Scenario, TripMode};
use widgetry::tools::{FileLoader, PopupMsg};
use widgetry::{
Expand All @@ -25,16 +29,27 @@ impl ShowResults {
let map_name = app.map.get_name().clone();
if app.session.impact.map != map_name {
let scenario_name = Scenario::default_scenario_for_map(&map_name);
return FileLoader::<App, Scenario>::new_state(
ctx,
abstio::path_scenario(&map_name, &scenario_name),
Box::new(move |ctx, app, timer, maybe_scenario| {
// TODO Handle corrupt files
let scenario = maybe_scenario.unwrap();
app.session.impact = Impact::from_scenario(ctx, app, scenario, timer);
Transition::Replace(ShowResults::new_state(ctx, app))
}),
);

if scenario_name != "home_to_work" {
return FileLoader::<App, Scenario>::new_state(
ctx,
abstio::path_scenario(&map_name, &scenario_name),
Box::new(move |ctx, app, timer, maybe_scenario| {
// TODO Handle corrupt files
let scenario = maybe_scenario.unwrap();
app.session.impact = Impact::from_scenario(ctx, app, scenario, timer);
Transition::Replace(ShowResults::new_state(ctx, app))
}),
);
}
ctx.loading_screen("synthesize travel demand model", |ctx, timer| {
let scenario = ScenarioGenerator::proletariat_robot(
&app.map,
&mut XorShiftRng::seed_from_u64(42),
timer,
);
app.session.impact = Impact::from_scenario(ctx, app, scenario, timer);
});
}

if app.session.impact.change_key != app.session.modal_filters.get_change_key() {
Expand Down
3 changes: 2 additions & 1 deletion sim/src/lib.rs
Expand Up @@ -37,7 +37,7 @@ pub use crate::render::{
pub use self::analytics::{Analytics, Problem, ProblemType, SlidingWindow, TripPhase};
pub(crate) use self::events::Event;
pub use self::events::{AlertLocation, TripPhaseType};
pub use self::make::{fork_rng, BorderSpawnOverTime, ScenarioGenerator, SimFlags, SpawnOverTime};
pub use self::make::SimFlags;
pub(crate) use self::make::{StartTripArgs, TripSpec};
pub(crate) use self::mechanics::{
DrivingSimState, IntersectionSimState, ParkingSim, ParkingSimState, WalkingSimState,
Expand All @@ -54,6 +54,7 @@ pub use self::sim::{
pub(crate) use self::transit::TransitSimState;
pub use self::trips::{CommutersVehiclesCounts, Person, PersonState, TripInfo, TripResult};
pub(crate) use self::trips::{TripLeg, TripManager};
pub use synthpop::make::{fork_rng, BorderSpawnOverTime, ScenarioGenerator, SpawnOverTime};

mod analytics;
mod events;
Expand Down
13 changes: 0 additions & 13 deletions sim/src/make/mod.rs
@@ -1,20 +1,7 @@
//! Everything needed to setup a simulation.
//! <https://a-b-street.github.io/docs/tech/trafficsim/travel_demand.html> for context.

use rand::{RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;

pub use self::generator::{BorderSpawnOverTime, ScenarioGenerator, SpawnOverTime};
pub use self::load::SimFlags;
pub(crate) use self::spawner::{StartTripArgs, TripSpec};

mod activity_model;
mod generator;
mod load;
mod spawner;

/// Need to explain this trick -- basically keeps consistency between two different simulations when
/// each one might make slightly different sequences of calls to the RNG.
pub fn fork_rng(base_rng: &mut XorShiftRng) -> XorShiftRng {
XorShiftRng::seed_from_u64(base_rng.next_u64())
}
2 changes: 1 addition & 1 deletion sim/src/sim/scenario.rs
Expand Up @@ -7,9 +7,9 @@ use rand_xorshift::XorShiftRng;
use abstutil::{prettyprint_usize, Counter, Timer};
use geom::{Distance, Speed};
use map_model::{BuildingID, Map, OffstreetParking, RoadID};
use synthpop::make::fork_rng;
use synthpop::{PersonSpec, Scenario, TripEndpoint, TripMode};

use crate::make::fork_rng;
use crate::{
ParkingSpot, Sim, StartTripArgs, TripInfo, Vehicle, VehicleSpec, VehicleType, BIKE_LENGTH,
MAX_CAR_LENGTH, MIN_CAR_LENGTH,
Expand Down
1 change: 1 addition & 0 deletions synthpop/src/lib.rs
Expand Up @@ -26,6 +26,7 @@ mod borders;
mod counts;
mod endpoint;
mod external;
pub mod make;
mod modifier;
mod scenario;

Expand Down
Expand Up @@ -11,10 +11,10 @@ use rand_xorshift::XorShiftRng;
use abstutil::{prettyprint_usize, Timer};
use geom::{Distance, Duration, Time};
use map_model::{BuildingID, BuildingType, Map, PathConstraints, PathRequest};
use synthpop::{IndividTrip, PersonSpec, Scenario, TripEndpoint, TripMode, TripPurpose};

use crate::make::fork_rng;
use crate::ScenarioGenerator;
use crate::{IndividTrip, PersonSpec, Scenario, TripEndpoint, TripMode, TripPurpose};

use crate::make::{fork_rng, ScenarioGenerator};

impl ScenarioGenerator {
/// Designed in https://github.com/a-b-street/abstreet/issues/154
Expand Down
3 changes: 2 additions & 1 deletion sim/src/make/generator.rs → synthpop/src/make/generator.rs
Expand Up @@ -11,7 +11,8 @@ use serde::{Deserialize, Serialize};
use abstutil::Timer;
use geom::{Duration, Time};
use map_model::{IntersectionID, Map};
use synthpop::{IndividTrip, PersonSpec, Scenario, TripEndpoint, TripMode, TripPurpose};

use crate::{IndividTrip, PersonSpec, Scenario, TripEndpoint, TripMode, TripPurpose};

// TODO This can be simplified dramatically.

Expand Down
15 changes: 15 additions & 0 deletions synthpop/src/make/mod.rs
@@ -0,0 +1,15 @@
//! <https://a-b-street.github.io/docs/tech/trafficsim/travel_demand.html> for context.

use rand::{RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;

pub use self::generator::{BorderSpawnOverTime, ScenarioGenerator, SpawnOverTime};

mod activity_model;
mod generator;

/// Need to explain this trick -- basically keeps consistency between two different simulations when
/// each one might make slightly different sequences of calls to the RNG.
pub fn fork_rng(base_rng: &mut XorShiftRng) -> XorShiftRng {
XorShiftRng::seed_from_u64(base_rng.next_u64())
}

0 comments on commit 3fa6aba

Please sign in to comment.