2020-08-24 00:32:20 +03:00
<!DOCTYPE HTML>
< html lang = "en" class = "sidebar-visible no-js light" >
< head >
<!-- Book generated using mdBook -->
< meta charset = "UTF-8" >
< title > Multi-modal trips - A/B Street< / title >
< meta content = "text/html; charset=utf-8" http-equiv = "Content-Type" >
< meta name = "description" content = "" >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
< meta name = "theme-color" content = "#ffffff" / >
< link rel = "shortcut icon" href = "../favicon.png" >
< link rel = "stylesheet" href = "../css/variables.css" >
< link rel = "stylesheet" href = "../css/general.css" >
< link rel = "stylesheet" href = "../css/chrome.css" >
< link rel = "stylesheet" href = "../css/print.css" media = "print" >
<!-- Fonts -->
< link rel = "stylesheet" href = "../FontAwesome/css/font-awesome.css" >
< link href = "https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel = "stylesheet" type = "text/css" >
< link href = "https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel = "stylesheet" type = "text/css" >
<!-- Highlight.js Stylesheets -->
< link rel = "stylesheet" href = "../highlight.css" >
< link rel = "stylesheet" href = "../tomorrow-night.css" >
< link rel = "stylesheet" href = "../ayu-highlight.css" >
<!-- Custom theme stylesheets -->
< / head >
< body >
<!-- Provide site root to javascript -->
< script type = "text/javascript" >
var path_to_root = "../";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "light" : "light";
< / script >
<!-- Work around some values being stored in localStorage wrapped in quotes -->
< script type = "text/javascript" >
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') & & theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') & & sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
< / script >
<!-- Set the theme before any content is loaded, prevents flash -->
< script type = "text/javascript" >
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('js');
< / script >
<!-- Hide / unhide sidebar before it is displayed -->
< script type = "text/javascript" >
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
< / script >
< nav id = "sidebar" class = "sidebar" aria-label = "Table of contents" >
< div class = "sidebar-scrollbox" >
2020-11-09 22:42:58 +03:00
< ol class = "chapter" > < li class = "chapter-item expanded " > < a href = "../index.html" > < strong aria-hidden = "true" > 1.< / strong > Overview< / a > < / li > < li class = "chapter-item expanded " > < a href = "../howto/index.html" > < strong aria-hidden = "true" > 2.< / strong > Instructions< / a > < / li > < li > < ol class = "section" > < li class = "chapter-item expanded " > < a href = "../howto/map_parking.html" > < strong aria-hidden = "true" > 2.1.< / strong > How to map on-street parking< / a > < / li > < li class = "chapter-item expanded " > < a href = "../howto/new_city.html" > < strong aria-hidden = "true" > 2.2.< / strong > Importing a new city< / a > < / li > < / ol > < / li > < li class = "chapter-item expanded " > < a href = "../how_it_works.html" > < strong aria-hidden = "true" > 3.< / strong > How it works< / a > < / li > < li class = "chapter-item expanded " > < a href = "../case_studies/index.html" > < strong aria-hidden = "true" > 4.< / strong > Case studies< / a > < / li > < li > < ol class = "section" > < li class = "chapter-item expanded " > < a href = "../case_studies/lake_wash.html" > < strong aria-hidden = "true" > 4.1.< / strong > Lake Washington Blvd Stay Healthy Street< / a > < / li > < li class = "chapter-item expanded " > < a href = "../case_studies/west_seattle.html" > < strong aria-hidden = "true" > 4.2.< / strong > West Seattle mitigations< / a > < / li > < li class = "spacer" > < / li > < / ol > < / li > < li class = "chapter-item expanded " > < a href = "../dev/index.html" > < strong aria-hidden = "true" > 5.< / strong > Developer guide< / a > < / li > < li > < ol class = "section" > < li class = "chapter-item expanded " > < a href = "../dev/misc_tricks.html" > < strong aria-hidden = "true" > 5.1.< / strong > Misc developer tricks< / a > < / li > < li class = "chapter-item expanded " > < a href = "../dev/api.html" > < strong aria-hidden = "true" > 5.2.< / strong > API< / a > < / li > < li class = "chapter-item expanded " > < a href = "../dev/testing.html" > < strong aria-hidden = "true" > 5.3.< / strong > Testing< / a > < / li > < li class = "chapter-item expanded " > < a href = "../dev/mass_import.html" > < strong aria-hidden = "true" > 5.4.< / strong > Importing many maps< / a > < / li > < li class = "chapter-item expanded " > < a href = "../dev/data.html" > < strong aria-hidden = "true" > 5.5.< / strong > Data organization< / a > < / li > < / ol > < / li > < li class = "chapter-item expanded " > < a href = "../map/index.html" > < strong aria-hidden = "true" > 6.< / strong > Map model< / a > < / li > < li > < ol class = "section" > < li class = "chapter-item expanded " > < a href = "../map/details.html" > < strong aria-hidden = "true" > 6.1.< / strong > Details< / a > < / li > < li class = "chapter-item expanded " > < a href = "../map/importing/index.html" > < strong aria-hidden = "true" > 6.2.< / strong > Importing< / a > < / li > < li > < ol class = "section" > < li class = "chapter-item expanded " > < a href = "../map/importing/convert_osm.html" > < strong aria-hidden = "true" > 6.2.1.< / strong > convert_osm< / a > < / li > < li class = "chapter-item expanded " > < a href = "../map/importing/geometry.html" > < strong aria-hidden = "true" > 6.2.2.< / strong > Road/intersection geometry< / a > < / li > < li class = "chapter-item expanded " > < a href = "../map/importing/rest.html" > < strong aria-hidden = "true" > 6.2.3.< / strong > The rest< / a > < / li > < li class = "chapter-item expanded " > < a href = "../map/importing/misc.html" > < strong aria-hidden = "true" > 6.2.4.< / strong > Misc< / a > < / li > < / ol > < / li > < li class = "chapter-item expanded " > < a href = "../map/edits.html" > < strong aria-hidden = "true" > 6.3.< / strong > Live edits< / a > < / li > < li class = "chapter-item expanded " > < a href = "../map/platform.html" > < strong aria-hidden = "true" > 6.4.< / strong > Exporting< / a > < / li > < / ol > < / li > < li class = "chapter-item expanded " > < a href = "../trafficsim/index.html" > < strong aria-hidden = "true" > 7.< / strong > Traffic simulation< / a > < / li > < li > < ol class = "section" > < li class = "chapter-item expanded " > < a href = "../trafficsim/discrete_event.html" > < strong aria-hidden = "true" > 7.1.< / strong > Discrete event simulation< / a > < / li > < li class = "chapter-item expanded " > < a href = "../trafficsim/travel_demand.html" > < strong aria-hidden = "true" > 7.2.< / strong > Travel demand< / a > < / li > < li class = "chapter-item expanded " > < a href = "../trafficsim/gridlock.html" > < strong aria-hidden = "true" > 7.3.< / strong > Gridlock< / a > < / li > < li class = "chapter-item expanded " > < a href = "../trafficsim/trips.html" class = "active" > < strong aria-hidden = "true" > 7.4.< / strong > Multi-modal trips< / a > < / li > < li class = "chapter-item expanded " > < a href = "../trafficsim/live_edits.html" > <
2020-08-24 00:32:20 +03:00
< / div >
< div id = "sidebar-resize-handle" class = "sidebar-resize-handle" > < / div >
< / nav >
< div id = "page-wrapper" class = "page-wrapper" >
< div class = "page" >
< div id = "menu-bar-hover-placeholder" > < / div >
< div id = "menu-bar" class = "menu-bar sticky bordered" >
< div class = "left-buttons" >
< button id = "sidebar-toggle" class = "icon-button" type = "button" title = "Toggle Table of Contents" aria-label = "Toggle Table of Contents" aria-controls = "sidebar" >
< i class = "fa fa-bars" > < / i >
< / button >
< button id = "theme-toggle" class = "icon-button" type = "button" title = "Change theme" aria-label = "Change theme" aria-haspopup = "true" aria-expanded = "false" aria-controls = "theme-list" >
< i class = "fa fa-paint-brush" > < / i >
< / button >
< ul id = "theme-list" class = "theme-popup" aria-label = "Themes" role = "menu" >
< li role = "none" > < button role = "menuitem" class = "theme" id = "light" > Light (default)< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "rust" > Rust< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "coal" > Coal< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "navy" > Navy< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "ayu" > Ayu< / button > < / li >
< / ul >
< button id = "search-toggle" class = "icon-button" type = "button" title = "Search. (Shortkey: s)" aria-label = "Toggle Searchbar" aria-expanded = "false" aria-keyshortcuts = "S" aria-controls = "searchbar" >
< i class = "fa fa-search" > < / i >
< / button >
< / div >
< h1 class = "menu-title" > A/B Street< / h1 >
< div class = "right-buttons" >
< a href = "../print.html" title = "Print this book" aria-label = "Print this book" >
< i id = "print-button" class = "fa fa-print" > < / i >
< / a >
< / div >
< / div >
< div id = "search-wrapper" class = "hidden" >
< form id = "searchbar-outer" class = "searchbar-outer" >
< input type = "search" name = "search" id = "searchbar" name = "searchbar" placeholder = "Search this book ..." aria-controls = "searchresults-outer" aria-describedby = "searchresults-header" >
< / form >
< div id = "searchresults-outer" class = "searchresults-outer hidden" >
< div id = "searchresults-header" class = "searchresults-header" > < / div >
< ul id = "searchresults" >
< / ul >
< / div >
< / div >
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
< script type = "text/javascript" >
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
< / script >
< div id = "content" class = "content" >
< main >
< h1 > < a class = "header" href = "#multi-modal-trips" id = "multi-modal-trips" > Multi-modal trips< / a > < / h1 >
< p > A single trip consists of a sequence of < code > TripLegs< / code > -- walking, operating a
vehicle (car or bike), and riding the bus. Depending whether a trip begins or
ends at a border or building, there are many combinations of these sequences.
This is a way to categorize them into three groups. I'm not sure it's the
simplest way to express all the state transitons.< / p >
< h2 > < a class = "header" href = "#walking-only-trips" id = "walking-only-trips" > Walking-only trips< / a > < / h2 >
2020-08-30 01:37:16 +03:00
< p > < img src = "../mdbook-plantuml-img/bbf8881e880a261530dd998679b4f47108dfc748.svg" alt = "" / > < / p >
2020-08-24 00:32:20 +03:00
< h2 > < a class = "header" href = "#trips-starting-from-a-border" id = "trips-starting-from-a-border" > Trips starting from a border< / a > < / h2 >
2020-08-30 01:37:16 +03:00
< p > < img src = "../mdbook-plantuml-img/1cd9d730c8982c5ba59b825b427e712fab82e681.svg" alt = "" / > < / p >
2020-08-24 00:32:20 +03:00
< h2 > < a class = "header" href = "#trips-starting-from-a-building" id = "trips-starting-from-a-building" > Trips starting from a building< / a > < / h2 >
2020-08-30 01:37:16 +03:00
< p > < img src = "../mdbook-plantuml-img/92ec1d5cbfccd87df09b67ac1a2b26aebf81eee8.svg" alt = "" / > < / p >
2020-11-19 01:51:55 +03:00
< h2 > < a class = "header" href = "#spawning-code-overview" id = "spawning-code-overview" > Spawning code overview< / a > < / h2 >
< p > As of November 2020, starting a traffic simulation works like this:< / p >
< ol >
< li > Something creates a < code > Scenario< / code > , which defines a bunch of people. Each person
has a schedule of trips, carrying them between < code > TripEndpoints< / code > via some
< code > TripMode< / code > , leaving at some < code > Time< / code > .< / li >
< li > When a scenario is instantiated, every trip for every person passes through
< code > TripSpec::maybe_new< / code > . This transforms the origin, destination, and mode into
a < code > TripSpec< / code > .< / li >
2020-11-19 02:30:14 +03:00
< li > < code > TripSpec::to_plan< / code > further validates these and attempts to repair impossible
plans. Each < code > TripSpec< / code > is turned into a list of < code > TripLegs< / code > . The < code > TripSpec< / code > is
then passed to the discrete-event scheduler inside a < code > Command::StartTrip< / code > .
This way, < code > TripManager< / code > knows about all trips immediately, and at the right
time, each trip can be initiated.< / li >
2020-11-19 01:51:55 +03:00
< li > Later, the scheduler gets one of these commands, and calls
< code > TripManager::start_trip< / code > with the < code > TripSpec< / code > . Each type of trip has its own
initialization logic to kick off the first leg of the trip.< / li >
< li > Most trips have multiple legs. When the first car, bike, or pedestrian
reaches their goal, < code > TripManager< / code > gets called with some sort of transition
function to initiate the next leg of the trip, or declare the trip finished.
These transition functions also record stats from that leg of the trip, like
total blocked time.< / li >
< / ol >
< p > What're the different < code > TripSpec< / code > cases, and what < code > TripLegs< / code > do they get turned
into?< / p >
< ul >
< li > < code > VehicleAppearing< / code > : Starts at a border. Drive, then maybe walk to the
destination building.< / li >
< li > < code > SpawningFailure< / code > : No trip legs; just create and immediately cancel the trip.< / li >
< li > < code > UsingParkedCar< / code > : Starts at a building. Walk (to the parked car), drive, then
maybe walk to the destination building (after parking again).< / li >
< li > < code > JustWalking< / code > : Just walk between two buildings/borders.< / li >
< li > < code > UsingBike< / code > : Starts at a building. Walk to the nearest bikeable lane, drive,
then maybe walk to the destination building. (Note that starting a bike from a
border uses < code > VehicleAppearing< / code > .)< / li >
< li > < code > UsingTransit< / code > : Walk, ride the bus, maybe walk again. No transfers yet; only
rides one bus between two stops.< / li >
< / ul >
< p > < code > TripManager< / code > has a whole bunch of transition functions:< / p >
< ul >
< li > < code > car_reached_parking_spot< / code > : drive -> walk, unless the destination building is
where we parked< / li >
< li > < code > ped_reached_parking_spot< / code > : walk -> drive< / li >
< li > < code > ped_ready_to_bike< / code > : walk -> bike< / li >
< li > < code > bike_reached_end< / code > : bike -> walk< / li >
< li > < code > ped_reached_building< / code > : walk -> done< / li >
< li > < code > ped_reached_bus_stop< / code > : walk -> wait or ride bus< / li >
< li > < code > ped_boarded_bus< / code > : waiting -> ride bus< / li >
< li > < code > person_left_bus< / code > : riding bus -> walk< / li >
< li > < code > ped_reached_border< / code > : walk -> done< / li >
< li > < code > transit_rider_reached_border< / code > : ride bus -> done< / li >
< li > < code > car_or_bike_reached_border< / code > : drive -> done< / li >
< / ul >
< p > There are at least a few use cases motivating the cleanup of all of this
structure:< / p >
< ul >
< li > Capping trips through congested areas. Sometimes this just changes the driving
route, but sometimes it needs to cancel trips, convert driving trips to
walking/transit, or delay the trip's start.< / li >
< li > Multiple public transit rides in a single trip, aka transferring< / li >
< li > Handling live map edits in the middle of a trip< / li >
< / ul >
2020-08-24 00:32:20 +03:00
< / main >
< nav class = "nav-wrapper" aria-label = "Page navigation" >
<!-- Mobile navigation buttons -->
< a rel = "prev" href = "../trafficsim/gridlock.html" class = "mobile-nav-chapters previous" title = "Previous chapter" aria-label = "Previous chapter" aria-keyshortcuts = "Left" >
< i class = "fa fa-angle-left" > < / i >
< / a >
2020-09-03 21:41:03 +03:00
< a rel = "next" href = "../trafficsim/live_edits.html" class = "mobile-nav-chapters next" title = "Next chapter" aria-label = "Next chapter" aria-keyshortcuts = "Right" >
2020-08-24 00:32:20 +03:00
< i class = "fa fa-angle-right" > < / i >
< / a >
< div style = "clear: both" > < / div >
< / nav >
< / div >
< / div >
< nav class = "nav-wide-wrapper" aria-label = "Page navigation" >
< a rel = "prev" href = "../trafficsim/gridlock.html" class = "nav-chapters previous" title = "Previous chapter" aria-label = "Previous chapter" aria-keyshortcuts = "Left" >
< i class = "fa fa-angle-left" > < / i >
< / a >
2020-09-03 21:41:03 +03:00
< a rel = "next" href = "../trafficsim/live_edits.html" class = "nav-chapters next" title = "Next chapter" aria-label = "Next chapter" aria-keyshortcuts = "Right" >
2020-08-24 00:32:20 +03:00
< i class = "fa fa-angle-right" > < / i >
< / a >
< / nav >
< / div >
< script type = "text/javascript" >
window.playpen_copyable = true;
< / script >
< script src = "../elasticlunr.min.js" type = "text/javascript" charset = "utf-8" > < / script >
< script src = "../mark.min.js" type = "text/javascript" charset = "utf-8" > < / script >
< script src = "../searcher.js" type = "text/javascript" charset = "utf-8" > < / script >
< script src = "../clipboard.min.js" type = "text/javascript" charset = "utf-8" > < / script >
< script src = "../highlight.js" type = "text/javascript" charset = "utf-8" > < / script >
< script src = "../book.js" type = "text/javascript" charset = "utf-8" > < / script >
<!-- Custom JS scripts -->
< / body >
< / html >