Make the LTN impact prediction work off autogenerated home-to-work scenarios 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.
This commit is contained in:
Dustin Carlino 2022-08-04 10:35:18 +01:00
parent 5722c67011
commit 3fa6aba9c8
11 changed files with 53 additions and 39 deletions

2
Cargo.lock generated
View File

@ -2245,6 +2245,8 @@ dependencies = [
"map_gui",
"map_model",
"maplit",
"rand",
"rand_xorshift",
"regex",
"serde",
"serde_json",

View File

@ -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"

View File

@ -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,
@ -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),

View File

@ -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::{
@ -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() {

View File

@ -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,
@ -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;

View File

@ -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())
}

View File

@ -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,

View File

@ -26,6 +26,7 @@ mod borders;
mod counts;
mod endpoint;
mod external;
pub mod make;
mod modifier;
mod scenario;

View File

@ -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

View File

@ -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.

15
synthpop/src/make/mod.rs Normal file
View File

@ -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())
}