abstreet/print.html
2020-09-13 23:47:09 +00:00

3342 lines
185 KiB
HTML

<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>A/B Street</title>
<meta name="robots" content="noindex" />
<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">
<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></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/importing/index.html"><strong aria-hidden="true">6.1.</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.1.1.</strong> convert_osm</a></li><li class="chapter-item expanded "><a href="map/importing/geometry.html"><strong aria-hidden="true">6.1.2.</strong> Road/intersection geometry</a></li><li class="chapter-item expanded "><a href="map/importing/rest.html"><strong aria-hidden="true">6.1.3.</strong> The rest</a></li></ol></li><li class="chapter-item expanded "><a href="map/edits.html"><strong aria-hidden="true">6.2.</strong> Live edits</a></li><li class="chapter-item expanded "><a href="map/misc.html"><strong aria-hidden="true">6.3.</strong> Misc</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"><strong aria-hidden="true">7.4.</strong> Multi-modal trips</a></li><li class="chapter-item expanded "><a href="trafficsim/live_edits.html"><strong aria-hidden="true">7.5.</strong> Live edits</a></li><li class="spacer"></li></ol></li><li class="chapter-item expanded "><a href="project/index.html"><strong aria-hidden="true">8.</strong> Project</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="project/roadmap.html"><strong aria-hidden="true">8.1.</strong> Roadmap</a></li><li class="chapter-item expanded "><a href="project/motivations.html"><strong aria-hidden="true">8.2.</strong> Motivations</a></li><li class="chapter-item expanded "><a href="project/history/index.html"><strong aria-hidden="true">8.3.</strong> History</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="project/history/backstory.html"><strong aria-hidden="true">8.3.1.</strong> Backstory</a></li><li class="chapter-item expanded "><a href="project/history/year1.html"><strong aria-hidden="true">8.3.2.</strong> Year 1</a></li><li class="chapter-item expanded "><a href="project/history/year2.html"><strong aria-hidden="true">8.3.3.</strong> Year 2</a></li><li class="chapter-item expanded "><a href="project/history/year3.html"><strong aria-hidden="true">8.3.4.</strong> Year 3</a></li></ol></li><li class="chapter-item expanded "><a href="project/CHANGELOG.html"><strong aria-hidden="true">8.4.</strong> Full CHANGELOG</a></li><li class="chapter-item expanded "><a href="project/references.html"><strong aria-hidden="true">8.5.</strong> References</a></li><li class="chapter-item expanded "><a href="project/collaborations.html"><strong aria-hidden="true">8.6.</strong> Collaborations</a></li></ol></li></ol>
</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="#ab-street" id="ab-street">A/B Street</a></h1>
<p>All documentation lives here. Some chapters are only intended for a technical
audience.</p>
<h1><a class="header" href="#ab-street-instructions" id="ab-street-instructions">A/B Street Instructions</a></h1>
<p>This is an alpha-quality demo. Please email <a href="mailto:howto/dabreegster@gmail.com">dabreegster@gmail.com</a> or
<a href="https://github.com/dabreegster/abstreet/issues/">file a Github issue</a> if you
hit problems.</p>
<h2><a class="header" href="#installing-the-game" id="installing-the-game">Installing the game</a></h2>
<p>Grab a pre-built binary release -- updated every Sunday, announced at
<a href="http://old.reddit.com/r/abstreet">r/abstreet</a>:</p>
<ul>
<li><a href="https://github.com/dabreegster/abstreet/releases/download/v0.2.11/abstreet_windows_v0_2_11.zip">Windows</a>
<ul>
<li>Unzip the folder, then run <code>play_abstreet.bat</code>. You'll probably getting a
warning about running software from an unknown publisher.</li>
</ul>
</li>
<li><a href="https://github.com/dabreegster/abstreet/releases/download/v0.2.11/abstreet_mac_v0_2_11.zip">Mac</a>
<ul>
<li>Unzip the directory, then run <code>play_abstreet.sh</code>.</li>
<li>If you get an error about the developer unverified,
<a href="https://support.apple.com/guide/mac-help/open-a-mac-app-from-an-unidentified-developer-mh40616/mac">follow this</a>.
Help needed to start
<a href="https://github.com/dabreegster/abstreet/issues/107">signing the release</a>!</li>
<li>If that just opens a text file instead of running the game, then instead
open terminal, <code>cd</code> to the directory you just unzipped. Then do:
<code>cd game; RUST_BACKTRACE=1 ./game 1&gt; ../output.txt 2&gt;&amp;1</code></li>
<li><a href="https://github.com/dabreegster/abstreet/issues/77">Help needed</a> to package
this as a Mac .app, to make this process simpler</li>
</ul>
</li>
<li><a href="https://github.com/dabreegster/abstreet/releases/download/v0.2.11/abstreet_linux_v0_2_11.zip">Linux</a>
<ul>
<li>Unzip the directory, then run <code>play_abstreet.sh</code>.</li>
</ul>
</li>
<li><a href="https://www.freshports.org/games/abstreet/">FreeBSD</a>, thanks to
<a href="https://github.com/yurivict">Yuri</a></li>
</ul>
<p>Or you can <a href="howto//docs/dev.html">compile from source</a>.</p>
<h2><a class="header" href="#playing-the-game" id="playing-the-game">Playing the game</a></h2>
<ul>
<li>Use the <strong>tutorial</strong> to learn the controls.</li>
<li>Play the <strong>challenges</strong> for directed gameplay.</li>
<li>Try out any ideas in the <strong>sandbox</strong>.</li>
</ul>
<h2><a class="header" href="#data-source-licensing" id="data-source-licensing">Data source licensing</a></h2>
<p>A/B Street binary releases contain pre-built maps that combine data from:</p>
<ul>
<li>OpenStreetMap (<a href="https://www.openstreetmap.org/copyright">https://www.openstreetmap.org/copyright</a>)</li>
<li>King County metro
(<a href="https://www.kingcounty.gov/depts/transportation/metro/travel-options/bus/app-center/terms-of-use.aspx">https://www.kingcounty.gov/depts/transportation/metro/travel-options/bus/app-center/terms-of-use.aspx</a>)</li>
<li>City of Seattle GIS program
(<a href="https://www.opendatacommons.org/licenses/pddl/1.0/">https://www.opendatacommons.org/licenses/pddl/1.0/</a>)</li>
<li><a href="https://github.com/seattleio/seattle-boundaries-data">https://github.com/seattleio/seattle-boundaries-data</a>
(<a href="https://creativecommons.org/publicdomain/zero/1.0/">https://creativecommons.org/publicdomain/zero/1.0/</a>)</li>
<li>Puget Sound Regional Council
(<a href="https://www.psrc.org/activity-based-travel-model-soundcast">https://www.psrc.org/activity-based-travel-model-soundcast</a>)</li>
<li>USGS SRTM</li>
</ul>
<p>Other binary data bundled in:</p>
<ul>
<li>Overpass font (<a href="https://fonts.google.com/specimen/Overpass">https://fonts.google.com/specimen/Overpass</a>, Open Font
License)</li>
<li>Bungee fonts (<a href="https://fonts.google.com/specimen/Bungee">https://fonts.google.com/specimen/Bungee</a>, Open Font License)</li>
<li>Material Design icons (<a href="https://material.io/resources/icons">https://material.io/resources/icons</a>, Apache license)</li>
</ul>
<h1><a class="header" href="#help-map-out-on-street-parking" id="help-map-out-on-street-parking">Help map out on-street parking</a></h1>
<p><img src="howto/parking_mapper.gif" alt="parking_mapper" /></p>
<p>This guide assumes you've edited OSM before. Contact <a href="mailto:howto/dabreegster@gmail.com">dabreegster@gmail.com</a> if
you have any trouble. Also give me a heads up when you make some edits, so I can
regenerate the maps!</p>
<ol>
<li><a href="https://github.com/dabreegster/abstreet/blob/master/docs/INSTRUCTIONS.md">Install A/B Street</a></li>
<li>Choose <strong>Contribute parking data</strong> on the main screen</li>
<li>Change the map if you'd like to focus somewhere in particular</li>
<li>Click a road with unknown parking</li>
<li>Select what kind of on-street parking the road has</li>
<li>Repeat</li>
<li>Click <strong>Generate OsmChange file</strong></li>
<li>Upload the diff.osc file by adding a layer in JOSM (or send it to me)</li>
</ol>
<p>Like all edits to OSM, to figure out ground-truth, you can survey in-person or
use
<a href="https://wiki.openstreetmap.org/wiki/Bing_Maps#Streetside_imagery">Bing Streetside</a>.
<strong>Do not use data from Google Maps to edit OSM.</strong></p>
<h2><a class="header" href="#faq" id="faq">FAQ</a></h2>
<h3><a class="header" href="#why" id="why">Why?</a></h3>
<p>I'm trying to build a realistic traffic simulation of Seattle using OSM data,
then use it to strengthen proposals for
<a href="https://dabreegster.github.io/abstreet/lake_wash/proposal.html">pedestrianized streets</a>,
<a href="https://www.glwstreets.org/45th-st-bridge-overview">improving the bike network</a>,
and
<a href="https://dabreegster.github.io/abstreet/west_seattle/proposal.html">mitigating the West Seattle bridge closure</a>.
A/B Street is only as good as its data, and parking is one of the biggest gaps.
Missing data means unrealistic traffic as vehicles contend for few parking
spots, and roads that look much wider than they are in reality.</p>
<h3><a class="header" href="#why-put-this-data-in-osm" id="why-put-this-data-in-osm">Why put this data in OSM?</a></h3>
<p>Why can't I just grab parking data from
<a href="http://web6.seattle.gov/SDOT/seattleparkingmap/">SDOT's map</a>, using the
<a href="http://data-seattlecitygis.opendata.arcgis.com/datasets/blockface">blockface</a>
dataset? Well, I'm trying -- when you see a parking lane in the tool, it's
coming from blockface, unless that road in OSM is tagged. But the blockface
dataset is comically wrong in many places -- for example, the Montlake bridge
apparently has unrestricted parking?! King County GIS has confirmed the dataset
isn't meant to be used for this level of detail.</p>
<p>Plus, if the data is in OSM, anybody else can make use of it.</p>
<h3><a class="header" href="#how-does-the-tool-work" id="how-does-the-tool-work">How does the tool work?</a></h3>
<p>A/B Street attempts to render individual lanes and intersections from OSM data.
This makes it useful to audit the lane tags in OSM, including
<a href="https://wiki.openstreetmap.org/wiki/Key:parking:lane">parking:lane</a>. The tool
tracks your edits and when you generate the OsmChange file, it grabs modified
ways from the OSM API to generate a diff. You can inspect the diff, load it in
JOSM, and upload.</p>
<p><strong>Your changes won't immediately be reflected in A/B Street.</strong> Let me know when
you've done some amount of mapping, and I'll regenerate the maps from fresh
data.</p>
<h3><a class="header" href="#why-use-this-tool" id="why-use-this-tool">Why use this tool?</a></h3>
<p>You don't have to; <a href="https://zlant.github.io/parking-lanes/">this tool</a> or ID or
JOSM all work. But the UI is clunky for this specific purpose. (Also, if you
find this tool clunky in any way, let me know and I'll fix it.) There's also a
proposed
<a href="https://github.com/westnordost/StreetComplete/issues/771">StreetComplete quest</a>.</p>
<h3><a class="header" href="#what-about-parking-restrictions" id="what-about-parking-restrictions">What about parking restrictions?</a></h3>
<p>There are many
<a href="https://wiki.openstreetmap.org/wiki/Key:parking:lane">parking:lane</a> tags to
indicate restricted parking zones, time restrictions, etc. Feel free to map that
in ID or JOSM, but I'm just looking to make a first pass over a wide area.</p>
<h3><a class="header" href="#what-about-off-street-parking" id="what-about-off-street-parking">What about off-street parking?</a></h3>
<p>Ideally I'd also like to know how many private parking spots are available to
residents of each building. But I don't know of an OSM schema for mapping this,
or a practical way to collect this data. Let me know if you have ideas.</p>
<h3><a class="header" href="#what-about-long-roads-where-parking-appears-and-disappears" id="what-about-long-roads-where-parking-appears-and-disappears">What about long roads where parking appears and disappears?</a></h3>
<p>The tool won't help. Use your favorite editor to split the way when the lane
configuration changes. Also feel free to just skip these areas.</p>
<h3><a class="header" href="#how-to-coordinate-with-other-mappers" id="how-to-coordinate-with-other-mappers">How to coordinate with other mappers?</a></h3>
<p>If somebody wants to set up HOT tasking, that'd be great, but I don't expect so
many people to jump on this.</p>
<h3><a class="header" href="#i-noticed-weird-roads-in-the-tool" id="i-noticed-weird-roads-in-the-tool">I noticed weird roads in the tool</a></h3>
<p>Welcome to my world. ;) If the number of lanes seems wrong, select the road and
check the OSM tags. I'm inferring lanes from that. Feel free to make manual OSM
edits to fix any problems you see. (I'd like to extend this tool to make that
easier; let me know if you have ideas how to do this.)</p>
<h3><a class="header" href="#i-want-to-map-an-area-but-theres-no-option-for-it" id="i-want-to-map-an-area-but-theres-no-option-for-it">I want to map an area, but there's no option for it</a></h3>
<p>To keep the release size small, I'm not including all maps yet. Let me know what
you'd like to see included.</p>
<p>Or if you have a <code>.osm</code> file, try the <a href="howto/new_city.html">quick start guide</a>.</p>
<h1><a class="header" href="#importing-a-new-city-into-ab-street" id="importing-a-new-city-into-ab-street">Importing a new city into A/B Street</a></h1>
<p>This process isn't easy yet. Please email <a href="mailto:howto/dabreegster@gmail.com">dabreegster@gmail.com</a> or
<a href="https://github.com/dabreegster/abstreet/issues/">file a Github issue</a> if you
hit problems. I'd really appreciate help and PRs to improve this.</p>
<h2><a class="header" href="#quick-start" id="quick-start">Quick start</a></h2>
<p>Use this if you want to import a city on your computer without making it
available to other users yet.</p>
<ul>
<li>
<p>If you're using the <strong>binary release</strong> and have a <code>.osm</code> file, just do:
<code>./importer --oneshot=map.osm</code>.</p>
</li>
<li>
<p>If you're building <strong>from source</strong>, do: <code>./import.sh --oneshot=map.osm</code>. If
you can't run <code>import.sh</code>, make sure you have all
<a href="howto/dev.html#building-map-data">dependencies</a>. If you're using Windows and the
console logs appear in a new window, try running the command from <code>import.sh</code>
directly, changing the <code>$@</code> at the end to <code>--oneshot=map.osm</code> or whatever
arguments you're passing in.</p>
</li>
</ul>
<p>The oneshot importer will will generate a new file in <code>data/system/maps</code> that
you can then load in the game. If you have an Osmosis polygon filter (see
below), you can also pass <code>--oneshot_clip=clip.poly</code> to improve the result. You
should first make sure your .osm has been clipped:
<code>osmconvert large_map.osm -B=clipping.poly --complete-ways -o=smaller_map.osm</code>.</p>
<p>By default, driving on the right is assumed. Use <code>--oneshot_drive_on_left</code> to
invert.</p>
<h3><a class="header" href="#how-to-get-osm-files" id="how-to-get-osm-files">How to get .osm files</a></h3>
<p>If the area is small enough, try the &quot;export&quot; tool on
<a href="https://www.openstreetmap.org">https://www.openstreetmap.org</a>. You can download larger areas from
<a href="https://download.bbbike.org/">https://download.bbbike.org/</a> or <a href="http://download.geofabrik.de/index.html">http://download.geofabrik.de/index.html</a>,
then clip them to a smaller area. Use <a href="http://geojson.io/">geojson.io</a> or
<a href="https://geoman.io/geojson-editor">geoman.io</a> to draw a boundary around the
region you want to simulate and save the geojson locally. Use
<code>cargo run --bin geojson_to_osmosis &lt; boundary.geojson &gt; clipping.poly</code> to
convert that geojson to the
<a href="https://wiki.openstreetmap.org/wiki/Osmosis/Polygon_Filter_File_Format">Osmosis format</a>
required by osmconvert.</p>
<h2><a class="header" href="#including-the-city-to-ab-street-more-permanently" id="including-the-city-to-ab-street-more-permanently">Including the city to A/B street more permanently</a></h2>
<p>Follow this guide to add a new city to A/B street by default so other users can
use it as well.</p>
<ol>
<li>
<p>Make sure you can run <code>import.sh</code> -- see
<a href="howto/dev.html#building-map-data">the instructions</a>. You'll need Rust, osmconvert,
gdal, etc.</p>
</li>
<li>
<p>Create a new directory: <code>mkdir -p data/input/your_city/polygons</code></p>
</li>
<li>
<p>Use <a href="http://geojson.io/">geojson.io</a> or
<a href="https://geoman.io/geojson-editor">geoman.io</a> to draw a boundary around the
region you want to simulate and save the geojson locally.</p>
</li>
<li>
<p>Use <code>cargo run --bin geojson_to_osmosis &lt; boundary.geojson &gt; clipping.poly</code>
to convert that geojson to the
<a href="https://wiki.openstreetmap.org/wiki/Osmosis/Polygon_Filter_File_Format">Osmosis format</a>
required by osmconvert.</p>
</li>
<li>
<p>Create a new module in <code>importer/src/</code> for your city, copying
<code>importer/src/krakow.rs</code> as a guide. Edit that file in the obvious way. The
main thing you'll need is a .osm or .osm.pbf file to download that contains
your city. The clipping polygon will be applied to that.</p>
</li>
<li>
<p>Update <code>importer/src/main.rs</code> to reference your new module, following
<code>krakow</code> as an example.</p>
</li>
<li>
<p>Update <code>map_belongs_to_city</code> in <code>updater/src/main.rs</code></p>
</li>
<li>
<p>Run it: <code>./import.sh --city=your_city --raw --map</code></p>
</li>
<li>
<p>Update <code>.gitignore</code>, following <code>krakow</code> as an example.</p>
</li>
</ol>
<p>Send a PR with your changes! I'll generate everything and make it work with
<code>updater</code>, so most people don't have to build everything from scratch.</p>
<h2><a class="header" href="#next-steps" id="next-steps">Next steps</a></h2>
<p>OpenStreetMap isn't the only data source we need. If you look at the import
pipeline for Seattle, you'll see many more sources for parking, GTFS bus
schedules, person/trip demand data for scenarios, etc. Most of these aren't
standard between cities. If you want to make your city more realistic, we'll
have to import more data. Get in touch.</p>
<p>You may notice issues with OSM data while using A/B Street. Some of these are
bugs in A/B Street itself, but others are incorrectly tagged lanes. Some
resources for fixing OSM:</p>
<ul>
<li><a href="https://learnosm.org">https://learnosm.org</a></li>
<li><a href="https://wiki.openstreetmap.org/wiki/StreetComplete">https://wiki.openstreetmap.org/wiki/StreetComplete</a></li>
<li><a href="https://dabreegster.github.io/abstreet/map_parking.html">https://dabreegster.github.io/abstreet/map_parking.html</a></li>
</ul>
<h1><a class="header" href="#how-ab-street-works" id="how-ab-street-works">How A/B Street works</a></h1>
<p>The overview:</p>
<ol>
<li>A detailed map of Seattle is built from
<a href="https://www.openstreetmap.org/about">OpenStreetMap (OSM)</a></li>
<li>A realistic set of daily trips by car, bike, foot, and bus are simulated</li>
<li>You make small changes to roads and intersections</li>
<li>You explore how these changes affect the trips</li>
</ol>
<p>Details below. Many limitations are mentioned; improvements are ongoing. I'll
add pictures to explain better when I get time.</p>
<!--ts-->
<ul>
<li><a href="how_it_works.html#how-ab-street-works">How A/B Street works</a>
<ul>
<li><a href="how_it_works.html#driving">Driving</a></li>
<li><a href="how_it_works.html#parking">Parking</a></li>
<li><a href="how_it_works.html#biking">Biking</a></li>
<li><a href="how_it_works.html#walking">Walking</a></li>
<li><a href="how_it_works.html#transit">Transit</a></li>
<li><a href="how_it_works.html#intersections">Intersections</a></li>
<li><a href="how_it_works.html#people-and-trips">People and trips</a></li>
<li><a href="how_it_works.html#map-edits">Map edits</a></li>
</ul>
</li>
</ul>
<!-- Added by: dabreegster, at: Mon Jun 8 12:17:13 PDT 2020 -->
<!--te-->
<h2><a class="header" href="#driving" id="driving">Driving</a></h2>
<ul>
<li>Movement: no acceleration, go the full speed limit of the road unless there's
a slower vehicle in front</li>
<li>Lanes
<ul>
<li>No over-taking or lane-changing in the middle of a road, only at
intersections</li>
<li>Strange choice of lanes -- the least full at the time of arrival</li>
<li>Narrow two-way neighborhood roads where, in practice, only one car at a time
can go are currently full two-way roads</li>
</ul>
</li>
<li>Routing is based on fastest time assuming no traffic
<ul>
<li>No rerouting if the driver encounters a traffic jam</li>
</ul>
</li>
</ul>
<h2><a class="header" href="#parking" id="parking">Parking</a></h2>
<ul>
<li>Types
<ul>
<li>On-street: parallel parking lanes from
<a href="http://data-seattlecitygis.opendata.arcgis.com/datasets/blockface">GeoData blockface dataset</a>
and
<a href="https://dabreegster.github.io/abstreet/map_parking.html">manually mapped</a></li>
<li>Off-street: most buildings have at least a few parking spots in a driveway
or carport
<ul>
<li>Currently experimenting in the downtown map: set the number of available
spots based on number of cars seeded at midnight</li>
</ul>
</li>
<li>Parking lots: the number of spots is inferred</li>
</ul>
</li>
<li>Restrictions
<ul>
<li>All spots are public except for the few spots associated with each building</li>
<li>No time restrictions or modeling of payment</li>
</ul>
</li>
<li>How cars park
<ul>
<li>Drivers won't look for parking until they first reach their destination
building. Then they'll drive to the nearest open parking spot (magically
knowing what spots are open, even if they're a few blocks away). If somebody
else has taken the spot when they arrive, they'll try again.</li>
<li>Once a driver finds an open spot, they'll take 10-15 seconds to park. They
block the road behind them in the meantime. There are no conflicts between
pedestrians and cars when using a driveway. Cars won't make left turns into
or out of driveways.</li>
</ul>
</li>
<li>Some parking along the boundary of the map is &quot;blackholed&quot;, meaning it's
impossible to actually reach it. Nobody will use these spots.</li>
</ul>
<h2><a class="header" href="#biking" id="biking">Biking</a></h2>
<ul>
<li>Choice of lane
<ul>
<li>Multi-use trails like the Burke Gilman and separated cycle-tracks like the
one along Broadway are currently missing</li>
<li>Cyclists won't use an empty parking lane</li>
<li>On roads without a bike lane, cyclists currently won't stick to the
rightmost lane</li>
<li>No over-taking yet, so cars can get stuck behind a bike even if there's a
passing lane</li>
</ul>
</li>
<li>Elevation change isn't factored into route choice or speed yet; pretend
everybody has an e-bike</li>
<li>Beginning or ending a cycling trip takes 30-45 seconds. Locking up at bike
racks with limited capacity isn't modeled; in practice, it's always easy in
Seattle to find a place to lock up.</li>
</ul>
<h2><a class="header" href="#walking" id="walking">Walking</a></h2>
<ul>
<li>Not using sidewalk and crosswalk data from OSM yet</li>
<li>No jay-walking, even on empty residential streets</li>
<li>Pedestrians can't use roads without sidewalks at all
<ul>
<li>When a road only has a sidewalk on one side, driveways will cross the road</li>
</ul>
</li>
<li>Pedestrians can &quot;ghost&quot; through each other; crowds of people can grow to any
size</li>
</ul>
<h2><a class="header" href="#transit" id="transit">Transit</a></h2>
<ul>
<li>The modeling of buses is extremely simple and buggy; I'll work on this soon</li>
<li>No light rail yet</li>
</ul>
<h2><a class="header" href="#intersections" id="intersections">Intersections</a></h2>
<ul>
<li>Conflicting movements are coarse: a second vehicle won't start a conflicting
turn, even if the first vehicle is physically out of the way but still
partially in the intersection</li>
<li>Most of the time, vehicles won't &quot;block the box&quot; -- if there's no room in the
target lane, a vehicle won't start turning and risk getting stuck in the
intersection</li>
<li>Traffic signals
<ul>
<li>Only fixed timers; no actuated signals or
<a href="https://www.seattle.gov/transportation/projects-and-programs/programs/technology-program/mercer-scoot">centralized control</a>
yet</li>
<li>The timing and stages are automatically guessed, except some intersections
are
<a href="https://docs.google.com/document/d/1Od_7WvBVYsvpY4etRI0sKmYmZnwXMAXcJxVmm8Iwdcg/edit?usp=sharing">manually mapped</a></li>
<li>No pedestrian beg buttons; walk signals always come on</li>
<li>The signal doesn't change for rush hour or weekday/weekend traffic; there's
one pattern all day</li>
</ul>
</li>
<li>Turn restrictions from OSM are applied
<ul>
<li>Per lane (left turn only from leftmost lane), entire roads, multiple
intersections</li>
</ul>
</li>
</ul>
<h2><a class="header" href="#people-and-trips" id="people-and-trips">People and trips</a></h2>
<ul>
<li>A &quot;synthetic population&quot; of ~700,000 people come from
<a href="https://www.psrc.org/activity-based-travel-model-soundcast">PSRC's Soundcast model</a>
<ul>
<li>Soundcast uses census, land-use, vehicle counts, and commuter surveys. The
current data is from 2014.</li>
<li>All driving trips are currently single-occupancy; no car-pooling or
ridesharing</li>
<li>Parked cars are initially placed at midnight based on the number of trips
between buildings</li>
</ul>
</li>
<li>Each person's schedule never changes
<ul>
<li>Your changes to the map won't yet convince somebody to take a bus or walk
instead of drive</li>
</ul>
</li>
</ul>
<h2><a class="header" href="#map-edits" id="map-edits">Map edits</a></h2>
<ul>
<li>Types of edits
<ul>
<li>Change types of lanes. Sometimes this is unrealistic based on actual road
width, but data for this is unavailable.</li>
<li>Reversing direction of lanes</li>
<li>Changing stop signs</li>
<li>Changing traffic signal timing</li>
<li>Closing roads and intersections for construction, forcing rerouting</li>
</ul>
</li>
<li>Disconnecting the map
<ul>
<li>Generally you can't close sidewalks or make changes to make buildings
unreachable</li>
<li>You shouldn't be able to make bus stops unreachable, but currently this is
buggy</li>
</ul>
</li>
</ul>
<h1><a class="header" href="#case-studies" id="case-studies">Case studies</a></h1>
<p>Note: Most of these still aren't started, because the baseline simulation in the
relevant area isn't working. Unknown traffic signal timing, bad guesses at the
amount of off-street parking, lanes tagged incorrectly in OpenStreetMap, and
simulation bugs cause unrealistic gridlock. It's hard to evaluate a change
without a realistic baseline.</p>
<p>In progress:</p>
<ul>
<li><a href="case_studies/lake_wash.html">Stay Healthy Streets: Lake Washington Blvd</a></li>
<li><a href="case_studies/west_seattle.html">West Seattle mitigations</a></li>
<li>Simplify where the Burke Gilman crosses Corliss and Pacific
<ul>
<li>No write-up yet, but the proposal is included in A/B Street</li>
</ul>
</li>
</ul>
<p>TODO:</p>
<ul>
<li>Close Broadway and Pine to through-traffic
<ul>
<li>proposed
<a href="https://old.reddit.com/r/SeattleWA/comments/gr4dsi/its_time_for_mayor_durkan_to_bring_stay_healthy/">here</a></li>
<li>partly <a href="https://www.openstreetmap.org/way/814244753">happening already</a></li>
<li>another
<a href="https://twitter.com/pushtheneedle/status/1270757771802103809/photo/1">proposal</a></li>
</ul>
</li>
<li>Traffic signal timing at Montlake/520 and Montlake/Pacific
<ul>
<li>Walking around here is frustrating, and pre-COVID, vehicle traffic got
fairly stuck</li>
</ul>
</li>
<li>Pedestrianizing the Ave (u-district)
<ul>
<li>I can't find the proposal anymore; maybe
<a href="http://www.udistrictmobility.com/">this</a>?</li>
</ul>
</li>
<li>Eastlake bike lanes / RapidRide J
<ul>
<li>See
<a href="https://www.seattle.gov/transportation/projects-and-programs/programs/bike-program/protected-bike-lanes/eastlake-avenue-protected-bike-lanes">here</a>
and
<a href="http://www.seattle.gov/transportation/projects-and-programs/programs/transit-program/transit-plus-multimodal-corridor-program/rapidride-roosevelt">here</a></li>
<li>Need to audit lanes in OSM along Eastlake</li>
<li>Especially with the Fairview Ave bridge out, detouring to the Cheshiahud
loop isn't as useful</li>
</ul>
</li>
<li>Madison / RapidRide G
<ul>
<li>See
<a href="http://www.seattle.gov/transportation/projects-and-programs/programs/transit-program/transit-plus-multimodal-corridor-program/madison-street-bus-rapid-transit">here</a></li>
</ul>
</li>
<li>Bus lanes on Denny
<ul>
<li>Proposed
<a href="https://twitter.com/transitrunner/status/1175068582142599168">here</a></li>
</ul>
</li>
<li>Bike Master Plan
<ul>
<li>Prototype the
<a href="https://www.seattle.gov/transportation/document-library/citywide-plans/modal-plans/bicycle-master-plan">planned network</a></li>
</ul>
</li>
<li>Downtown one-way snake
<ul>
<li>An old crazy idea I've always wanted to try</li>
</ul>
</li>
<li>Unsorted ideas
<ul>
<li><a href="https://www.reddit.com/r/SeattleWA/comments/cr1r1l/why_the_fuck_does_the_right_lane_convert_to/">Parking</a></li>
<li><a href="https://seattletransitblog.com/2018/10/05/seven-places-to-add-bus-lanes-now/">Bus lanes</a></li>
<li><a href="https://old.reddit.com/r/SeattleWA/comments/83h4ri/the_intersection_at_john_and_broadway_desperately/">John and Broadway</a></li>
<li><a href="https://old.reddit.com/r/Seattle/comments/4z3ewl/what_are_seattles_worst_intersections/">Bad intersections</a></li>
<li><a href="https://old.reddit.com/r/SeattleWA/comments/5rvss5/what_changes_would_you_make_to_seattles_bus/">Bus routes</a></li>
</ul>
</li>
</ul>
<h1><a class="header" href="#lake-washington-blvd-stay-healthy-street" id="lake-washington-blvd-stay-healthy-street">Lake Washington Blvd Stay Healthy Street</a></h1>
<p><em>Draft, updated May 7, 2020 by Dustin Carlino (<a href="mailto:case_studies/dabreegster@gmail.com">dabreegster@gmail.com</a>)</em></p>
<p>In April 2020, Seattle Department of Transportation started rolling out
<a href="https://sdotblog.seattle.gov/2020/04/16/announcing-stay-healthy-streets/">Stay Healthy Streets</a>,
restricting roads to through-traffic to give people walking and biking more
space for social distancing.
<a href="http://seattlegreenways.org/socialdistancingstreets/">Seattle Neighborhood Greenways</a>
soon proposed extending this to a
<a href="https://drive.google.com/open?id=1HQMnagRf8EbS1nouqCMLl4LZr0QE8VrC&amp;usp=sharing">130-mile network</a>.</p>
<p>Selecting the streets requires some planning:</p>
<blockquote>
<p>These streets were selected to amplify outdoor exercise opportunities for
areas with limited open space options, low car ownership and routes connecting
people to essential services and food take out. We also ensured street
closures did not impact newly opened food pick up loading zones, parking
around hospitals for service for health care professionals, and bus routes.</p>
</blockquote>
<p>I've spent the last two years building <a href="https://abstreet.org">A/B Street</a>,
software to explore the impacts of changes like this on different modes of
transportation. So, let's try implementing part of the proposed network and see
what happens!</p>
<blockquote>
<p><strong><em>NOTE:</em></strong> You might want to read
<a href="https://github.com/dabreegster/abstreet/blob/master/old_docs/how_it_works.md">how A/B Street works</a>
first.</p>
</blockquote>
<h2><a class="header" href="#lake-washington-blvd" id="lake-washington-blvd">Lake Washington Blvd</a></h2>
<p>Let's start with one part of the proposal, closing Lake Washington Blvd to cars
through the Arboretum. There's already a multi-use trail alongside this stretch,
but its width makes it difficult to maintain 6 feet from people. There are some
parking lots that become inaccessible with this proposal, but they're currently
closed anyway.</p>
<p><img src="case_studies/edits.gif" alt="edits" /></p>
<h3><a class="header" href="#first-attempt" id="first-attempt">First attempt</a></h3>
<iframe width="560" height="315" src="https://www.youtube.com/embed/PU0iT-_3-es" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
<p>Let's get started! If you want to follow along,
<a href="https://github.com/dabreegster/abstreet/blob/master/old_docs/INSTRUCTIONS.md">install A/B Street</a>,
open sandbox mode, and switch the map to Lake Washington corridor. Zoom in on
the southern tip of the Arboretum and hop into edit mode. We can see Lake
Washington Blvd just has one travel lane in each direction here. Click each
lane, convert it to a bike lane, and repeat north until Foster Island Road.</p>
<p>When we leave edit mode, the traffic simulation resets to midnight. Nothing
really interesting happens until 5 or 6am, so we'll speed up time. Watching the
section of road we edited, we'll only see pedestrians and bikes use this stretch
of road. If we want, we can click an individual person and follow along their
journey.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/LSCHeDi5484" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
<p>Something's weird though. There's lots of traffic cutting northbound through the
neighborhood, along 29th, Ward, and 28th. We can open up the throughput layer to
find which roads have the most traffic. More usefully, we can select &quot;compare
before edits&quot; to see what roads are getting more or less traffic because of the
road we modified. As expected, there's much less traffic along Lake Wash Blvd,
but it's also clear that lots of cars are now cutting through 26th Ave E.</p>
<h3><a class="header" href="#traffic-calming" id="traffic-calming">Traffic calming</a></h3>
<iframe width="560" height="315" src="https://www.youtube.com/embed/qAf5IAMbpcU" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
<p>Let's say you want to nudge traffic to use 23rd Ave, the nearest north/south
arterial, instead. (A/B Street is an unopinionated tool; if you have a different
goal in mind, try using it for that instead.) In this simulation, drivers pick
the fastest route, so we could try lowering speed limits or make some of the
residential streets connecting to Madison one-way, discouraging through-traffic.
In reality, the speed limit changes could be implemented through
<a href="https://streetsillustrated.seattle.gov/design-standards/trafficcalming/">traffic calming</a>
or cheap, temporary alternatives.</p>
<h2><a class="header" href="#next-steps-1" id="next-steps-1">Next steps</a></h2>
<p>I'm working to model &quot;local access only&quot; roads in A/B Street, and I'll describe
how to measure the impact on travel times. Stay tuned to see more of the
<a href="https://drive.google.com/open?id=1HQMnagRf8EbS1nouqCMLl4LZr0QE8VrC&amp;usp=sharing">proposed network</a>
simulated, and get in touch if you'd like to help out!</p>
<h1><a class="header" href="#west-seattle-mitigations" id="west-seattle-mitigations">West Seattle mitigations</a></h1>
<p><em>Draft, updated June 23, 2020 by Dustin Carlino (<a href="mailto:case_studies/dabreegster@gmail.com">dabreegster@gmail.com</a>)</em></p>
<p>In March 2020, the West Seattle bridge was closed due to cracks forming. As of
May, COVID-19's impact on commuting means the area still hasn't seen how the
area will handle losing the main route to the rest of Seattle. A local group,
HPAC, published a list of
<a href="https://www.westsideseattle.com/robinson-papers/2020/05/04/highland-park-action-coalition-calls-seattle-officials-traffic">requests to SDOT</a>
to prepare the area for these changes.</p>
<p>This page will try to explore some of the problems and solutions from HPAC's
document using <a href="https://abstreet.org">A/B Street</a>, a traffic simulator designed
to explore the impacts of changes like this on different modes of
transportation.</p>
<blockquote>
<p><strong><em>NOTE:</em></strong> You might want to read
<a href="https://github.com/dabreegster/abstreet/blob/master/old_docs/how_it_works.md">how A/B Street works</a>
first.</p>
</blockquote>
<h2><a class="header" href="#16th-ave-sw-and-sw-holden-st" id="16th-ave-sw-and-sw-holden-st">16th Ave SW and SW Holden St</a></h2>
<p>HPAC has been asking for a protected left-turn stage at this intersection. I'm
unfamiliar with this intersection and currently unable to scout in-person, so
I'm blindly guessing the traffic signal currently has just two stages:</p>
<p><img src="case_studies/existing_diagram.gif" alt="existing_diagram" /></p>
<p>From watching the traffic, it seems like the east/west direction is busier, with
lots of eastbound traffic headed towards WA-509. Holden St has no turn lanes, so
a protected left turn stage makes sense. Let's make the change and see what
happens:</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/6tooJaZLa0Q" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
<p>Unfortuately, we can't evaluate the change yet, because the simulation gets
stuck with unrealistic traffic jams in other parts of the map. This is mostly
due to data quality issues in OpenStreetMap and incorrectly guessed traffic
signal timings. These problems can be fixed with the help of somebody familiar
with the area.</p>
<h2><a class="header" href="#re-evaluate-arterials" id="re-evaluate-arterials">Re-evaluate arterials</a></h2>
<p>The 9th item from HPAC's list asks for measuring the amount of east-west traffic
to figure out what streets people are using as arterials. That's an easy
analysis, using the <em>throughput</em> layer.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/yzp9c7gHhOI" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
<p>By 6am, the busiest streets include Admiral Way, S Charlestown, SW Genesee, SW
Alaska, SW Holden, and SW Roxbury St. Again, it's necessary to first fix data
quality problems and run a full day before doing more analysis.</p>
<p>Once the simulation is running smoothly, A/B Street can be used to make changes
-- like lowering speed limits, adding a protected left turn stage, or converting
part of the road into a bus lane -- and evaluate the effects on individual trips
and aggregate groups.</p>
<h2><a class="header" href="#repair-the-bridge" id="repair-the-bridge">Repair the bridge</a></h2>
<p>Community proposals now includes a &quot;repair the bridge&quot; option, which should
restore things to how they were before March 2020. This is useful as a baseline,
to explore what traffic patterns were like before the closure.</p>
<h1><a class="header" href="#developer-guide" id="developer-guide">Developer guide</a></h1>
<h2><a class="header" href="#getting-started" id="getting-started">Getting started</a></h2>
<p>You will first need:</p>
<ul>
<li>Stable Rust, at least 1.46. <a href="https://www.rust-lang.org/tools/install">https://www.rust-lang.org/tools/install</a>.
<ul>
<li>On Windows, you may need
<a href="https://visualstudio.microsoft.com/de/downloads/">Visual Studio 2019</a>.</li>
</ul>
</li>
<li>On Linux, <code>sudo apt-get install xorg-dev libxcb-shape0-dev libxcb-xfixes0-dev</code>
or the equivalent for your distro</li>
</ul>
<p>One-time setup:</p>
<ol>
<li>
<p>Download the repository:
<code>git clone https://github.com/dabreegster/abstreet.git</code></p>
</li>
<li>
<p>Grab the minimal amount of data to get started: <code>cargo run --bin updater</code></p>
</li>
<li>
<p>Run the game: <code>RUST_BACKTRACE=1 cargo run --bin game --release</code>. On Windows,
set environment variables like this:
<code>set RUST_BACKTRACE=1 &amp;&amp; cargo run --bin game --release</code></p>
</li>
</ol>
<h2><a class="header" href="#development-tips" id="development-tips">Development tips</a></h2>
<ul>
<li><a href="https://dabreegster.github.io/abstreet/rustdoc/map_model/index.html">Generated API documentation</a></li>
<li>Compile faster by just doing <code>cargo run</code>. The executable will have debug stack
traces and run more slowly. You can do <code>cargo run --release</code> to build in
optimized release mode; compilation will be slower, but the executable much
faster.</li>
<li>Some in-game features are turned off by default or don't have a normal menu to
access them. The list:
<ul>
<li>To toggle developer mode: press <strong>Control+S</strong> in game, or
<code>cargo run -- --dev</code></li>
<li>To warp to an object by numeric ID: press <strong>Control+j</strong></li>
<li>To enter debug mode with all sorts of goodies: press <strong>Control+D</strong></li>
</ul>
</li>
<li>You can start the game in different modes using flags:
<ul>
<li><code>cargo run --bin game -- --dev data/system/maps/downtown.bin</code> starts on a
particular map</li>
<li><code>cargo run --bin game -- data/system/scenarios/downtown/weekday.bin</code> starts
with a scenario (which is tied to a certain map)</li>
<li><code>cargo run --bin game -- --challenge=trafficsig/tut2</code> starts on a particular
challenge. See the list of aliases by passing in a bad value here.</li>
<li><code>cargo run --bin game -- data/player/saves/montlake/no_edits_unnamed/00h00m20.3s.bin</code>
restores an exact simulation state. Savestates are found in debug mode
(<strong>Control+D</strong>) -- they're probably confusing for the normal player
experience, so they're hidden for now.</li>
<li><code>cargo run --bin game -- --tutorial=12</code> starts somewhere in the tutorial</li>
<li>Adding <code>--edits='name of edits'</code> starts with edits applied to the map.</li>
</ul>
</li>
</ul>
<h2><a class="header" href="#downloading-more-cities" id="downloading-more-cities">Downloading more cities</a></h2>
<p>As data formats change over time, things in the <code>data/</code> directory not under
version control will get out of date. At any time, you can run
<code>cargo run --bin updater</code> from the main repository directory to update only the
files that have changed.</p>
<p>You can also opt into downloading updates for more cities by editing
<code>data/config</code>. Opting into everything looks like this:</p>
<pre><code>runtime: seattle,huge_seattle,krakow,berlin,xian,tel_aviv,london
input: seattle,huge_seattle,krakow,berlin,xian,tel_aviv,london
</code></pre>
<p><code>runtime</code> downloads new maps and scenarios in <code>data/system/</code>. <code>input</code> is used
for building those maps -- see below.</p>
<h2><a class="header" href="#building-map-data" id="building-map-data">Building map data</a></h2>
<p>You can skip this section if you're just touching code in <code>game</code>, <code>widgetry</code>,
and <code>sim</code>.</p>
<p>To run all pieces of the importer, you'll need some extra dependencies:</p>
<ul>
<li><code>osmconvert</code>: See <a href="https://wiki.openstreetmap.org/wiki/Osmconvert#Download">https://wiki.openstreetmap.org/wiki/Osmconvert#Download</a> or
<a href="https://github.com/interline-io/homebrew-planetutils#installation">https://github.com/interline-io/homebrew-planetutils#installation</a> for Mac</li>
<li><code>libgdal-dev</code>: See <a href="https://gdal.org">https://gdal.org</a> if your OS package manager doesn't have
this. If you keep hitting linking errors, then just remove
<code>--features scenarios</code> from <code>import.sh</code>. You won't be able to build the
Seattle scenarios.</li>
<li>Standard Unix utilities: <code>curl</code>, <code>unzip</code>, <code>gunzip</code></li>
</ul>
<p>The first stage of the importer, <code>--raw</code>, will download input files from OSM,
King County GIS, and so on. If the mirrors are slow or the files vanish, you
could fill out <code>data/config</code> and use the <code>updater</code> described above to grab the
latest input.</p>
<p>You can rerun specific stages of the importer:</p>
<ul>
<li>If you're modifying the initial OSM data -&gt; RawMap conversion in
<code>convert_osm</code>, you need <code>./import.sh --raw --map</code>.</li>
<li>If you're modifying <code>map_model</code> but not the OSM -&gt; RawMap conversion, then you
just need <code>./import.sh --map</code>.</li>
<li>If you're modifying the demand model for Seattle, you can add <code>--scenario</code> to regenerate.</li>
<li>By default, all maps are regenerated. You can also specify a single map:
<code>./import.sh --map downtown</code>.</li>
<li>By default, Seattle is assumed as the city. You have to specify otherwise:
<code>./import.sh --city=los_angeles --map downtown_la</code>.</li>
</ul>
<p>You can also make the importer <a href="dev/new_city.html">import a new city</a>.</p>
<h2><a class="header" href="#understanding-stuff" id="understanding-stuff">Understanding stuff</a></h2>
<p>The docs listed at <a href="https://github.com/dabreegster/abstreet#documentation">https://github.com/dabreegster/abstreet#documentation</a>
explain things like map importing and how the traffic simulation works.</p>
<h3><a class="header" href="#code-organization" id="code-organization">Code organization</a></h3>
<p>If you're going to dig into the code, it helps to know what all the crates are.
The most interesting crates are <code>map_model</code>, <code>sim</code>, and <code>game</code>.</p>
<p>Constructing the map:</p>
<ul>
<li><code>convert_osm</code>: extract useful data from OpenStreetMap and other data sources,
emit intermediate map format</li>
<li><code>kml</code>: extract shapes from KML shapefiles</li>
<li><code>map_model</code>: the final representation of the map, also conversion from the
intermediate map format into the final format</li>
<li><code>map_editor</code>: GUI for modifying geometry of maps and creating maps from
scratch. pretty abandoned as of June 2020</li>
<li><code>importer</code>: tool to run the entire import pipeline</li>
<li><code>updater</code>: tool to download/upload large files used in the import pipeline</li>
</ul>
<p>Traffic simulation:</p>
<ul>
<li><code>sim</code>: all of the agent-based simulation logic</li>
<li><code>headless</code>: tool to run a simulation without any visualization</li>
</ul>
<p>Graphics:</p>
<ul>
<li><code>game</code>: the GUI and main gameplay</li>
<li><code>widgetry</code>: a GUI and 2D OpenGL rendering library, using glium + winit +
glutin</li>
</ul>
<p>Common utilities:</p>
<ul>
<li><code>abstutil</code>: a grab-bag of IO helpers, timing and logging utilities, etc</li>
<li><code>geom</code>: types for GPS and map-space points, lines, angles, polylines,
polygons, circles, durations, speeds</li>
</ul>
<h2><a class="header" href="#code-conventions" id="code-conventions">Code conventions</a></h2>
<p>All code is automatically formatted using
<a href="https://github.com/rust-lang/rustfmt">https://github.com/rust-lang/rustfmt</a>; please run <code>cargo +nightly fmt</code> before
sending a PR. (You have to install the nightly toolchain just for fmt)</p>
<p>The error handling is unfortunately inconsistent. The goal is to gracefully
degrade instead of crashing the game. If a crash does happen, make sure the logs
will have enough context to reproduce and debug. For example, giving up when
some geometry problem happens isn't ideal, but at least make sure to print the
road / agent IDs or whatever will help find the problem. It's fine to crash
during map importing, since the player won't deal with this, and loudly stopping
problems is useful. It's also fine to crash when initially constructing all of
the renderable map objects, because this crash will consistently happen at
startup-time and be noticed by somebody developing before a player gets to it.</p>
<p>Regarding Testing: You'll surely note the lack of unit tests. If it bothers you,
let's talk about what tests should exist. In the meantime, note lots of
validation does happen via importing maps, running the prebaked scenarios, and
screenshot diffing. Please read more in depth in the
<a href="https://dabreegster.github.io/abstreet/dev/testing.html">testing strategy</a> doc.</p>
<h1><a class="header" href="#development-notes" id="development-notes">Development notes</a></h1>
<p>Find packages to upgrade: <code>cargo outdated -R</code></p>
<p>Deal with compile tile: <code>cargo bloat --time</code></p>
<p>Find why two binary crates aren't sharing dependencies:
<a href="https://old.reddit.com/r/rust/comments/cqceu4/common_crates_in_cargo_workspace_recompiled/">https://old.reddit.com/r/rust/comments/cqceu4/common_crates_in_cargo_workspace_recompiled/</a></p>
<p>Where's a dependency coming from? <code>cargo tree -i -p syn</code></p>
<p>Diff screencaps: <a href="http://www.imagemagick.org/Usage/compare/#methods">http://www.imagemagick.org/Usage/compare/#methods</a></p>
<p>Debug OpenGL calls:</p>
<pre><code>apitrace trace --api gl ../target/debug/game
qapitrace game.trace
apitrace dump game.trace
</code></pre>
<p>Understand XML: just use firefox</p>
<h2><a class="header" href="#profiling" id="profiling">Profiling</a></h2>
<p>Actually, <a href="https://github.com/flamegraph-rs/flamegraph">https://github.com/flamegraph-rs/flamegraph</a> is pretty cool too.</p>
<p><code>apt-get install google-perftools libgoogle-perftools-dev</code></p>
<p>Follow Usage from <a href="https://crates.io/crates/cpuprofiler">https://crates.io/crates/cpuprofiler</a></p>
<p>Modify <code>game/Cargo.toml</code> to include the <code>abstutil/profiler</code> feature. Then run
game or headless with <code>--enable_profiler</code></p>
<pre><code>google-pprof --no_strip_temp ../target/debug/game profile
google-pprof --no_strip_temp ../target/release/headless profile
top30 --cum
</code></pre>
<p>Why aren't the columns labelled?
<a href="https://groups.google.com/d/msg/golang-nuts/qkDWqFKj8og/tWfYAaWRYqkJ">https://groups.google.com/d/msg/golang-nuts/qkDWqFKj8og/tWfYAaWRYqkJ</a></p>
<h2><a class="header" href="#building-releases" id="building-releases">Building releases</a></h2>
<p>Cross-compilation notes: <a href="https://github.com/rust-embedded/cross">https://github.com/rust-embedded/cross</a> Or use
<a href="https://github.com/japaric/trust">https://github.com/japaric/trust</a></p>
<p>Initially have to:</p>
<pre><code class="language-shell">cargo install cross
sudo apt-get install docker.io
sudo usermod -aG docker ${USER}
</code></pre>
<p>Then:</p>
<pre><code>sudo systemctl start docker
cross build --release --target x86_64-pc-windows-gnu --bin game
wine target/x86_64-pc-windows-gnu/release/game.exe data/system/maps/montlake.bin
</code></pre>
<h2><a class="header" href="#markdown" id="markdown">Markdown</a></h2>
<p>For formatting:</p>
<pre><code>sudo apt-get install npm
cd ~; mkdir npm; cd npm
npm init --yes
npm install prettier --save-dev --save-exact
</code></pre>
<h2><a class="header" href="#videos" id="videos">Videos</a></h2>
<pre><code># Fullscreen
ffmpeg -f x11grab -r 25 -s 1920x960 -i :0.0+0,55 -vcodec huffyuv raw.avi
ffmpeg -ss 10.0 -t 5.0 -i raw.avi -f gif -filter_complex &quot;[0:v] fps=12,scale=1024:-1,split [a][b];[a] palettegen [p];[b][p] paletteuse&quot; screencast.gif
</code></pre>
<h2><a class="header" href="#faster-linking" id="faster-linking">Faster linking</a></h2>
<pre><code>sudo apt-get install lld
</code></pre>
<p>Stick this in ~/.cargo/config:</p>
<pre><code>[target.x86_64-unknown-linux-gnu]
rustflags = [
&quot;-C&quot;, &quot;link-arg=-fuse-ld=lld&quot;,
]
</code></pre>
<h2><a class="header" href="#git" id="git">git</a></h2>
<p>Keep a fork up to date:</p>
<pre><code># Once
git remote add upstream https://github.com/rust-windowing/glutin/
git fetch upstream
git merge upstream/master
git diff upstream/master
</code></pre>
<h2><a class="header" href="#refactoring" id="refactoring">Refactoring</a></h2>
<pre><code>perl -pi -e 's/WrappedComposite::text_button\(ctx, (.+?), (.+?)\)/Btn::text_fg(\1).build_def\(ctx, \2\)/' `find|grep rs|xargs`
</code></pre>
<h2><a class="header" href="#stack-overflow" id="stack-overflow">Stack overflow</a></h2>
<p>rust-gdb --args ../target/release/game --dev</p>
<h2><a class="header" href="#drawing-diagrams" id="drawing-diagrams">Drawing diagrams</a></h2>
<p>draw.io</p>
<h2><a class="header" href="#mapping" id="mapping">Mapping</a></h2>
<p>xodo on Android for annotating maps in the field</p>
<h2><a class="header" href="#osm-tools" id="osm-tools">OSM tools</a></h2>
<p>osmcha.org for recent changes</p>
<p>To upload diffs:</p>
<pre><code>java -jar ~/Downloads/josm-tested.jar ~/abstreet/map_editor/diff.osc
</code></pre>
<p>JOSM: Press (and release T), then click to pan. Download a relevant layer,
select the .osc, merge, then upload.</p>
<h2><a class="header" href="#fonts" id="fonts">Fonts</a></h2>
<p>fontdrop.info</p>
<h2><a class="header" href="#release-checklist" id="release-checklist">Release checklist</a></h2>
<p>What things are sensitive to changes in map data and simulation rules?</p>
<ul>
<li>tutorial</li>
<li>optimize commute challenges</li>
</ul>
<p>What things do I always forget to test?</p>
<ul>
<li>DPI issues, use <code>--scale_factor</code></li>
</ul>
<h1><a class="header" href="#api" id="api">API</a></h1>
<p>Suppose you're tired of manually fiddling with traffic signals, and you want to
use machine learning to do it. You can run A/B Street without graphics and
automatically control it through an API.</p>
<h2><a class="header" href="#examples" id="examples">Examples</a></h2>
<p>This
<a href="https://github.com/dabreegster/abstreet/blob/master/headless/examples/python_client.py">Python example</a>
has everything you need to get started.</p>
<p>Also check out the
<a href="https://github.com/dabreegster/abstreet/blob/master/headless/examples/go_client.go">Go example</a>,
which demonstrates just a few of the API calls.</p>
<h2><a class="header" href="#api-details" id="api-details">API details</a></h2>
<blockquote>
<p><strong>Under construction</strong>: The API will keep changing. There are no backwards
compatibility guarantees yet. Please make sure I know about your project, so I
don't break your client code.</p>
</blockquote>
<p>For now, the API is JSON over HTTP. The exact format is unspecified, error codes
are missing, etc. A summary of the commands available so far:</p>
<ul>
<li><strong>/sim</strong>
<ul>
<li><strong>GET /sim/reset</strong>: Reset all map edits and the simulation state. The trips
that will run don't change; they're determined by the scenario file you
initially pass to <code>headless</code>.</li>
<li><strong>POST /sim/load</strong>: Switch the scenario being simulated. Takes a
<a href="https://dabreegster.github.io/abstreet/rustdoc/sim/struct.SimFlags.html">SimFlags</a>
as a JSON POST body.</li>
<li><strong>GET /sim/get-time</strong>: Returns the current simulation time.</li>
<li><strong>GET /sim/goto-time?t=06:30:00</strong>: Simulate until 6:30 AM. If the time you
specify is before the current time, you have to call <strong>/sim/reset</strong> first.</li>
<li><strong>POST /sim/new-person</strong>: The POST body must be an
<a href="https://dabreegster.github.io/abstreet/rustdoc/sim/struct.ExternalPerson.html">ExternalPerson</a>
in JSON format.</li>
</ul>
</li>
<li><strong>/traffic-signals</strong>
<ul>
<li><strong>GET /traffic-signals/get?id=42</strong>: Returns the traffic signal of
intersection #42 in JSON.</li>
<li><strong>POST /traffic-signals/set</strong>: The POST body must be a
<a href="https://dabreegster.github.io/abstreet/rustdoc/map_model/struct.ControlTrafficSignal.html">ControlTrafficSignal</a>
in JSON format.</li>
<li><strong>GET /traffic-signals/get-delays?id=42&amp;t1=03:00:00&amp;t2=03:30:00</strong>: Returns
the delay experienced by every agent passing through intersection #42 from
3am to 3:30, grouped by direction of travel.</li>
<li><strong>GET /traffic-signals/get-cumulative-thruput?id=42</strong>: Returns the number of
agents passing through intersection #42 since midnight, grouped by direction
of travel.</li>
</ul>
</li>
<li><strong>/data</strong>
<ul>
<li><strong>GET /data/get-finished-trips</strong>: Returns a JSON list of all finished trips.
Each tuple is (time the trip finished in seconds after midnight, trip ID,
mode, duration of trip in seconds). The mode is either a string like &quot;Walk&quot;
or &quot;Drive&quot;, or null if the trip was aborted (due to a simulation bug or
disconnected map).</li>
<li><strong>GET /data/get-agent-positions</strong>: Returns a JSON list of all active agents.
Vehicle type (or pedestrian), person ID, and position is included.</li>
</ul>
</li>
<li><strong>/map</strong>
<ul>
<li><strong>GET /map/get-edits</strong>: Returns the current map edits in JSON. You can save
this to a file in <code>data/player/edits/map_name/</code> and later use it in-game
normally. You can also later run the <code>headless</code> server with
<code>--edits=name_of_edits</code>.</li>
</ul>
</li>
</ul>
<h2><a class="header" href="#working-with-the-map-model" id="working-with-the-map-model">Working with the map model</a></h2>
<p>If you need to deeply inspect the map, you can dump it to JSON:</p>
<pre><code>cargo run --bin dump_map data/system/maps/montlake.bin &gt; montlake.json
</code></pre>
<p>The format of the map isn't well-documented yet. See the
<a href="https://dabreegster.github.io/abstreet/rustdoc/map_model/index.html">generated API docs</a>
and <a href="https://dabreegster.github.io/abstreet/map/index.html">the map model docs</a>
in the meantime.</p>
<h2><a class="header" href="#working-with-individual-trips" id="working-with-individual-trips">Working with individual trips</a></h2>
<p>You can use the <strong>/sim/new-person</strong> API in the middle of a simulation, if
needed. If possible, it's simpler to create a Scenario as input.</p>
<h2><a class="header" href="#working-with-scenarios" id="working-with-scenarios">Working with Scenarios</a></h2>
<p>You can
<a href="https://dabreegster.github.io/abstreet/trafficsim/travel_demand.html#custom-import">import trips from your own data</a>.</p>
<p>You can also generate different variations of one of the
<a href="https://dabreegster.github.io/abstreet/trafficsim/travel_demand.html#proletariat-robot">demand models</a>
by specifying an RNG seed:</p>
<pre><code>cargo run --bin random_scenario -- --rng=123 --map=data/system/maps/montlake.bin &gt; data/system/scenarios/montlake/home_to_work.json
</code></pre>
<p>You can also dump Scenarios (the file that defines all of the people and trips)
to JSON:</p>
<pre><code>cargo run --bin dump_scenario data/system/scenarios/montlake/weekday.bin &gt; montlake_weekday.json
</code></pre>
<p>You can modify the JSON, then put the file back in the appropriate directory and
use it in-game:</p>
<pre><code>cargo run --bin game data/system/scenarios/montlake/modified_scenario.json
</code></pre>
<p>The Scenario format is also undocumented, but see the
<a href="https://dabreegster.github.io/abstreet/rustdoc/sim/struct.Scenario.html">generated API docs</a>
anyway.</p>
<h1><a class="header" href="#testing-strategy" id="testing-strategy">Testing strategy</a></h1>
<h2><a class="header" href="#unit-tests" id="unit-tests">Unit tests</a></h2>
<p>As you've probably noticed, there aren't many. Lots of the interesting behavior
in A/B Street - UI interactions, details of the simulation, map importing --
would take lots of infrastructure to specify a setup and expected outcomes. If
you have ideas for new tests, contributions always welcome! In the meantime, one
useful test covers how
<a href="https://github.com/dabreegster/abstreet/blob/master/map_model/src/make/initial/lane_specs.rs">OSM tags translate into individual lanes</a>.</p>
<h2><a class="header" href="#screenshot-diffs" id="screenshot-diffs">Screenshot diffs</a></h2>
<p>Downloading fresh OSM data or modifying any part of the map importing pipeline
could easily break things. Expressing invariants about the map output is hard,
because importing is far from perfect, and OSM data is often quite buggy. So the
approach to preventing regressions here is to look for visual changes to the
final rendered map.</p>
<ol>
<li>When a new map is opted into this type of test, somebody manually squints
carefully at it and sanity checks that it works to some degree.</li>
<li>They use the screen capture tool in debug mode to tile the map into 1920x960
chunks and screengrab everything.</li>
<li>Later, somebody regenerates the map with some possible changes.</li>
<li>They grab screenshots again, then use <code>compare_screenshots.sh</code> to quickly
look at the visual diff. Changes to intersection geometry, number of lanes,
rendering, etc are all easy to spot.</li>
<li>If this manual inspection of the diff is good, they commit the new
screenshots as the new goldenfiles.</li>
</ol>
<h2><a class="header" href="#dataregensh" id="dataregensh">data/regen.sh</a></h2>
<p>This tool regenerates all maps and scenarios from scratch.
<code>cargo run --bin updater -- --dry</code> then reveals what files have changed.</p>
<p>Additionally, this script does a few more tests:</p>
<ul>
<li><code>--prebake</code> runs the full weekday scenario on two maps that've previously been
coerced into being gridlock-free</li>
<li><code>--smoketest</code> simulates one hour on all maps, flushing out bugs with bus
spawning, agents hitting odd parts of the map, etc</li>
<li><code>--check_proposals</code> makes sure the edits shipped with the game still load
properly</li>
</ul>
<h2><a class="header" href="#old-tests" id="old-tests">Old tests</a></h2>
<p>Once upon a time, I made a little test harness that would run the simulation
headlessly (without graphics), set up certain situations forcing a car to park
in a certain spot, and asserted that different <code>sim/src/events.rs</code> were produced
in the right order. The <code>map_editor</code> tool was used to manually draw really
simple maps for these situations. I deleted everything, because the effort to
specify the input and expected output were too tedious to maintain, and this
never really helped catch bugs. There was a way to label roads and buildings in
the synthetic maps, so the test code could assert person 2 made it to the
&quot;house&quot; building, but even with all of this, it was pretty hard.</p>
<p>This approach is maybe worth reviving, though.</p>
<h1><a class="header" href="#map-model" id="map-model">Map model</a></h1>
<p>A/B Street builds a rich representation of a city map using OpenStreetMap (OSM)
and other sources. This chapter describes how.</p>
<p>TODO: Integrate pictures from
<a href="https://docs.google.com/presentation/d/1cF7qFtjAzkXL_r62CjxBvgQnLvuQ9I2WTE2iX_5tMCY/edit?usp=sharing">these slides</a>.</p>
<p><a href="https://youtu.be/chYd5I-5oyc?t=439">This recorded presentation</a> covers some of
this.</p>
<h2><a class="header" href="#the-map" id="the-map">The map</a></h2>
<p>A single city is broken down into different pieces...</p>
<p>A/B Street comes with a few maps, each defined by a bounding/clipping polygon
for some portion of Seattle. Each map has these objects:</p>
<ul>
<li><strong>Roads</strong>: A single road connects two intersections, carrying OSM metadata and
containing some child lanes.</li>
<li><strong>Lanes</strong>: An individual lane of traffic. Driving (any vehicle), bus-only, and
bike-only lanes have a direction. On-street parking lanes don't allow any
movement, and they have some number of parking spots. Sidewalks are
bidirectional.</li>
<li><strong>Intersections</strong>: An intersection has references to all of the incoming and
outgoing lanes. Most intersections have a stop sign or traffic signal policy
controlling movement through it.
<ul>
<li><strong>Border</strong> intersections on the edge of the map are special places where
agents may appear or disappear.</li>
</ul>
</li>
<li><strong>Turns</strong>: A turn connects one lane to another, via some intersection.
(Sidewalks are bidirectional, so specifying the intersection is necessary to
distinguish crosswalks at each end of a sidewalk.)</li>
<li><strong>Buildings</strong>: A building has a position, OSM metadata, and a <strong>front path</strong>
connecting the edge of the building to the nearest sidewalk. Most trips in A/B
Street begin and end at buildings. Some buildings also contain a number of
off-street parking spots.</li>
<li><strong>Area</strong>: An area has geometry and OSM metadata and represents a body of
water, forest, park, etc. They're just used for drawing.</li>
<li><strong>Bus stop</strong>: A bus stop is placed some distance along a sidewalk, with a
pointer to the position on the adjacent driving or bus lane where a bus stops
for pick-up.</li>
<li><strong>Bus route</strong>: A bus route has a name and a list of stops that buses will
cycle between. In the future, they'll include information about the
frequency/schedule of the route.</li>
<li><strong>Parking lot</strong>: A parking lot is connected to a road, has a shape, and has
some internal driving &quot;aisles.&quot; The number and position of individual parking
spots is auto-generated.</li>
</ul>
<h2><a class="header" href="#coordinate-system" id="coordinate-system">Coordinate system</a></h2>
<p>A/B Street converts (longitude, latitude) coordinates into a simpler form.</p>
<ul>
<li>An (x, y) point starts with the top-left of the bounding polygon as the
origin. Note this is screen drawing order, not a Cartesian plane (with Y
increasing upwards) -- so angle calculations account for this.</li>
<li>The (x, y) values are f64's trimmed to a few decimal places, with way more
precision than is really needed. These might become actual fixed-point
integers later, but for now, a <code>Pt2D</code> skirts around Rust's limits on f64's by
guaranteeing no NaN's or infinities and thus providing the full <code>Eq</code> trait.</li>
<li>A few places in map conversion compare points using different thresholds,
usually below 1 meter. Ideally these epsilon comparisons could be eliminated
in favor of a fixed-point integer representation, but for now, explicit
thresholds are useful.</li>
</ul>
<h2><a class="header" href="#invariants" id="invariants">Invariants</a></h2>
<p>Ideally, the finalized maps would satisfy a list of invariants, simplifying the
traffic simulation and drawing code built on top. But the input data is quite
messy and for now, most of these aren't quite guaranteed to be true.</p>
<ul>
<li>Some minimum length for lanes and turns. Very small lanes can't be drawn, tend
to break intersection polygons, and may lead to gridlocked traffic.</li>
<li>Some guarantees that positions along adjacent lanes actually match up, even
though different lanes on the same road may have different lengths. Examples
include the position of a bus stop on the sidewalk and bus lane matching up.
<ul>
<li>Additionally, parking lanes without an adjacent driving lane or bus stops
without any driving or bus lanes make no sense and should never occur.</li>
</ul>
</li>
<li>Connectivity -- any sidewalk should be reachable from any other, and most
driving lanes should be accessible from any others. There are exceptions due
to border intersections -- if a car spawns on a highway along the border of
the map, it may be forced to disappear on the opposite border of the map, if
the highway happens to not have any exits within the map boundary.</li>
</ul>
<h2><a class="header" href="#connectivity" id="connectivity">Connectivity</a></h2>
<p>For a single mode, each lane is connected to two intersections. Turns connect
two lanes. There are no turns between sidewalks and driving/bike/bus lanes.</p>
<p>All buildings and parking lots have driveways. This must connect to a sidewalk,
allowing pedestrians to enter/exit that object. The driveway OPTIONALLY connects
to the nearest driveable lane. This allows cars to enter/exit that object for
parking.</p>
<p>Public transit stops are located somewhere on a sidewalk. They're associated
with a driveable position where the bus or train stops. In the future, this will
need to account for dedicated surface-level platforms and for underground
transit stations, likely associated with a building.</p>
<p>There's a concept of &quot;parking blackholes.&quot; If you treat every road as
bidirectional without access restrictions, then the graph is connected. But the
more detailed view has to factor in one-way roads and things near the map
border. These blackholes influence where cars will try to look for parking
(since we don't want them entering a blackhole and getting stuck) and also, for
temporary/unintentional reasons, where pedestrian&lt;-&gt;bicycle transitions will
happen.</p>
<h1><a class="header" href="#importing" id="importing">Importing</a></h1>
<p>Overview of the process. The importer tool.</p>
<p>Don't be afraid of how complicated this seems. It started simple -- just bring
in OSM roads, chop into pieces, generate turns.</p>
<h1><a class="header" href="#from-osm-to-rawmap-convert_osm-crate" id="from-osm-to-rawmap-convert_osm-crate">From OSM to RawMap (<code>convert_osm</code> crate)</a></h1>
<p>The first phase of map building reads in data from OSM files and a few others,
producing a serialized <code>RawMap</code>. Importing all maps (one for each pre-defined
bounding polygon) takes a few minutes. Players don't see this cost; it only
takes a few seconds to load a serialized map.</p>
<ul>
<li><code>osm.rs</code>: Read .osm, extracting the points for road-like ways, buildings, and
areas
<ul>
<li>Areas usually come from a relation of multiple ways, with the points out of
order. Gluing all the points together fails when the .osm has some ways
clipped out. In that case, try to trace along the map boundary if the
partial area intersects the boundary in a clear way. Otherwise, just use a
straight line to try to close off the polygon.</li>
<li>Also read traffic signal locations and turn restrictions between OSM ways</li>
</ul>
</li>
<li><code>split_ways.rs</code>: Split OSM ways into road segments
<ul>
<li>OSM ways cross many intersections, so treat points with multiple ways and
the points at the beginning and end of a way as intersections, then split
the way into road segments between two intersections.</li>
<li>This phase remembers which road segment is the beginning and end of the OSM
way, for per-lane turn restrictions later</li>
<li>Apply turn restrictions between roads here. Since OSM ways cross many
intersections, the turn restrictions only apply to one particular road
segment that gets created from the way. Make sure the destination of the
restriction is actually incident to a particular source road.</li>
</ul>
</li>
<li><code>clip.rs</code>: Clip the map to the boundary polygon
<ul>
<li>Osmosis options in <code>import.sh</code> preserve ways that cross the boundary</li>
<li>Trim roads that cross the boundary. There may be cases where a road dips out
of bounds, then immediately comes back in. Disconnecting it isn't ideal, but
it's better to manually tune the boundary polygon when this happens than try
to preserve lots of out-of-bounds geometry.</li>
<li>Area polygons are intersected with the boundary polygon using the <code>clipping</code>
crate</li>
</ul>
</li>
<li><code>lib.rs</code>: Remove cul-de-sacs (roads that begin and end at the same
intersection), because they mess up parking hints and pathfinding.</li>
<li><code>lib.rs</code>: Apply parking hints from a King County GIS blockface dataset
<ul>
<li>Match each blockface to the nearest edge of a road</li>
<li>Interpret the metadata to assign on-street parking there or not</li>
</ul>
</li>
<li><code>lib.rs</code>: Apply offstreet parking hints from a King County GIS dataset
<ul>
<li>Match each point to the building containing it, plumbing through the number
of spots</li>
</ul>
</li>
<li><code>lib.rs</code>: <strong>Disabled</strong>: Apply sidewalk presence hints from a King County GIS
dataset
<ul>
<li>Match each sidewalk line to the nearest edge of a road</li>
<li>Update the road to have a sidewalk on none, one, or both sides</li>
</ul>
</li>
<li><code>lib.rs</code> using the <code>srtm</code> module: Load (extremely poor quality) elevation data</li>
</ul>
<h1><a class="header" href="#roadintersection-geometry-rawmap-to-initialmap" id="roadintersection-geometry-rawmap-to-initialmap">Road/intersection geometry: RawMap to InitialMap</a></h1>
<p>The remainder of map construction is done in the <code>map_model</code> crate. There's one
intermediate structure between <code>RawMap</code> and <code>Map</code>, called <code>InitialMap</code>.</p>
<ul>
<li><code>make/remove_disconnected.rs</code>: Remove disconnected roads
<ul>
<li>Just floodfill from some road, assuming all roads are bidirectional, to get
different partitions.</li>
<li>Remove roads from all but the largest partition</li>
</ul>
</li>
<li><code>make/initial/mod.rs</code> and <code>make/initial/lane_specs.rs</code>: Interpret OSM tags to
figure out what lanes are on each side of each road, also figuring out the
total width of the road.</li>
<li><code>make/initial/geometry.rs</code>: Figure out the polygon for each intersection, and
trim back road center-lines to end at a face of the polygon.
<ul>
<li>For every road touching the intersection, get the polyline of each side,
based on the road's width
<ul>
<li>See appendix for how to shift polylines</li>
</ul>
</li>
<li>Sort all the polylines by the angle to the intersection's shared point</li>
<li>Intersect every polyline with every other polyline
<ul>
<li>More specifically -- the second half of each polyline, to get the correct
collision point</li>
<li>Look at the perpendicular infinite line to the collision point on the
shifted polyline, then find where it hits the original center line. Trim
back the center line by the max distance from these collisions.</li>
</ul>
</li>
<li>Compute the intersection's polygon by considering collisions between
adjacent roads' polylines</li>
<li>Deal with short roads and floating point issues by deduping any adjacent
points closer than 0.1m</li>
</ul>
</li>
</ul>
<h1><a class="header" href="#initialmap-to-map" id="initialmap-to-map">InitialMap to Map</a></h1>
<p>Still in the <code>map_model</code> crate.</p>
<ul>
<li><code>map.rs</code>'s <code>make_half_map</code>: Expand roads to lanes, using the list of lane
types from before</li>
<li><code>make/turns.rs</code>: Generate turns for every intersection.
<ul>
<li>Vehicle turns (for cars, bikes, buses)
<ul>
<li>Consider every pair of roads in the intersection. Try to match up lane
types -- if there's a bike lane on both roads, don't add a turn from
driving-&gt;bike or bike-&gt;driving. If there's not, then fallback to
transitions between different lane types.</li>
<li>Classify the turn based on the difference between the angle of the
incoming lane's last line and the outgoing lane's first line
<ul>
<li>For straight turns, use the Cartesian product to link every incoming
with every outgoing lane. If the indices dont match up, the turn becomes
a <code>LaneChangeLeft</code> or <code>LaneChangeRight</code> turn. This is used later for
intersection policies to prioritize turns appropriately.</li>
<li>Right and left turns only originate from the one lane on the appropriate
side</li>
</ul>
</li>
</ul>
</li>
<li>Walking turns for pedestrians
<ul>
<li>Consider pairs of adjacent roads around the intersection
<ul>
<li>Make a crosswalk to the other side of the road, assuming there's a
sidewalk on both sides</li>
<li>Make a shared sidewalk corner over to the adjacent road</li>
<li>If the adjacent road doesn't have a sidewalk on the close side, then
consider skipping that road and making a crosswalk over to the next
road. An example of this is a crosswalk over a highway on/off ramp.</li>
</ul>
</li>
</ul>
</li>
<li>Verify all the turns so far are unique</li>
<li>Filter by the OSM turn restrictions (&quot;only straight&quot; between road1 and
road2)</li>
<li>Try to apply the OSM per-lane restrictions (&quot;straight or left&quot; from lane 3)
<ul>
<li>The number of lanes in the OSM metadata might not match up with how many
lanes created</li>
<li>Some of these OSM tags are just completely wrong sometimes. If the filter
makes an incoming lane lose all of its turns, then ignore that tag.</li>
</ul>
</li>
</ul>
</li>
<li><code>make/parking_blackholes.rs</code>: Find well-connected roads near &quot;blackhole&quot;
lanes.
<ul>
<li>Starting from most driving/biking lanes, most other lanes are reachable.
Some aren't -- such as one-way highways inevitably leading from or to a
border. These are &quot;blackholes&quot; -- pathfinding to or from here may fail.</li>
<li>Find the largest strongly-connected component (SCC) in the driving graph.
From every other lane (a blackhole), floodfill both forwards and backwards
to find the nearest driving lane part of the main SCC.</li>
<li>Later, if a car needs to park by a building on a blackhole road, it'll
instead start searching for parking at the redirect. This prevents it from
being forced to instead exit the map through a border.</li>
</ul>
</li>
<li><code>make/buildings.rs</code>: Match buildings up with sidewalks
<ul>
<li>Find the closest sidewalk polyline to each building's center. Then draw a
straight line for the front path between the edge of the building and the
sidewalk point.</li>
<li>Filter out buildings too far away from any sidewalk</li>
<li>The front path might cross through other buildings; this is probably not
worth fixing.</li>
</ul>
</li>
<li><code>make/buildings.rs</code>: Same for parking lots
<ul>
<li>Similar process to match parking lots to nearest sidewalk and driving lane</li>
<li>Try to place parking spots along both sides of parking aisles</li>
<li>Filter out overlapping spots</li>
</ul>
</li>
<li><code>make/bridges.rs</code>: Find what roads lie beneath bridges, and update their
Z-order accordingly for later drawing.</li>
<li><code>stop_signs.rs</code>: Instantiate default stop sign policies
<ul>
<li>Rank incoming roads by OSM priority (arterial beats residential)</li>
<li>If there's only one rank, then make an all-way stop</li>
<li>Otherwise, the highest rank gets priority and others stop
<ul>
<li>Check if there are any conflicts based on this. If so, then fall-back to
an all way stop.</li>
</ul>
</li>
</ul>
</li>
<li><code>traffic_signals.rs</code>: Instantiate default traffic signal policies
<ul>
<li>Apply the first predefined policy that works.
<ul>
<li>4-way 4 stage, 4-way 2 stage, 3-way 3-stage, degenerate policy for 2
roads, 2-stage for 4 one-ways</li>
<li>Fallback to a greedy assignment that just randomly starts a new stage,
adds all compatible turns, and repeats until all turns are present
priority in some stage.</li>
</ul>
</li>
</ul>
</li>
<li><code>pathfind/mod.rs</code>: Prepare pathfinding
<ul>
<li>A/B Street uses contraction hierarchies (CH) for fast routing, using the
<code>fast_paths</code> crate.</li>
<li><code>pathfind/vehicle.rs</code>: For cars, bikes, buses
<ul>
<li>There's a separate CH for cars, buses, and bikes, since they can use
slightly different sets of lanes.</li>
<li>Building the CH for buses and bikes is much faster than the one for cars,
because the algorithm can re-use the node ordering from the first CH.</li>
<li>Every lane is a node in the graph, even if it's not an appropriate lane
type -- it might change later, and reusing orderings is vital for speed.</li>
<li>If two lanes are connected by a turn, then there's an edge in the graph.
<ul>
<li>The edge weight is the length of the lane and turn. Later this could
take into account speed limit, penalize lane-changing and left turns,
etc.</li>
</ul>
</li>
</ul>
</li>
<li><code>pathfind/walking.rs</code>: For pedestrians
<ul>
<li>Only sidewalk lanes are nodes in the graph -- sidewalks can't ever be
changed in A/B Street, so there's no concern about reusing node orderings.</li>
<li>All turns between two sidewalks become edges, again using length</li>
<li>When actually pathfinding, we get back a list of sidewalks. The actual
paths used in the traffic simulation specify forwards or backwards on a
sidewalk. Looking at adjacent pairs of sidewalks lets us easily stitch
together exact directions.</li>
</ul>
</li>
</ul>
</li>
<li><code>make/bus_stops.rs</code>: Match bus stops with a sidewalk
<ul>
<li>Also precompute the position where the bus stops on the adjacent driving or
bus lane.</li>
<li>This &quot;equivalent position on another lane&quot; process has a few weird cases,
since two lanes on the same road might have different lengths. Right now,
the same distance from the start of the lane is used, with clamping for
shorter lanes. Ideally, the position would be found by projecting a
perpendicular line out from one lane to the other.</li>
</ul>
</li>
<li><code>make/bus_stops.rs</code>: Finalize the list of bus routes
<ul>
<li>Between each pair of adjacent bus stops, run pathfinding to verify there's
actually a path for the bus to follow. If any are disconnected, remove the
bus route</li>
<li>Remove bus stops that have no routes serving them.</li>
</ul>
</li>
<li><code>pathfind/walking.rs</code>: Precompute the CH for pedestrians who will use buses
<ul>
<li>Nodes in the graph are sidewalks and every bus stop</li>
<li>There's an edge with weight 0 between a bus stop and its sidewalk</li>
<li>There's also an edge with weight 0 between bus stops that're adjacent via
some route. Ideally this weight would account for the time until the next
bus and the time spent on the bus, etc.</li>
<li>Later when figuring out which bus to use for a pedestrian, the resulting
list of nodes is scanned for the first and last bus stop along the same
route.</li>
</ul>
</li>
</ul>
<h1><a class="header" href="#live-edits" id="live-edits">Live edits</a></h1>
<p>A key feature of A/B Street is the player editing the map and seeing how traffic
responds. The possible edits include:</p>
<ul>
<li>Change lane types (driving, bus, bike, parking -- sidewalks are fixed)</li>
<li>Change speed limits</li>
<li>Reverse a lane</li>
<li>Change a stop sign policy (which roads have a stop sign and which have
priority)</li>
<li>Change a traffic signal policy</li>
</ul>
<p>The map conversion process outlined above takes a few minutes, so reusing this
process directly to compute a map with edits wouldn't work at all for real
gameplay. Instead, the process for applying edits is incremental:</p>
<ul>
<li>Figure out the actual diff between edits and the current map
<ul>
<li>This is necessary for correctness, but also speeds up a sequence of edits
made in the UI -- only one or two lanes or intersections actually changes
each time. Of course when loading some saved edits, lots of things might
change.</li>
</ul>
</li>
<li>For any changed roads, make sure any bus stop on it have a good pointer to
their equivalent driving position for the bus.</li>
<li>For any modified intersections, recompute turns and the default intersection
policies</li>
<li>Recompute all the CHs for cars, buses, and bikes -- note sidewalks and bus
stops never change
<ul>
<li>This is the slowest step. Critically, the <code>fast_paths</code> crate lets a previous
node ordering be reused. If just a few edge weights change, then recomputing
is much faster than starting from scratch.</li>
<li>While making edits in the UI, we don't actually need to recompute the CH
after every little tweak. When the player exits edit mode, only then do we
recompute everything.</li>
</ul>
</li>
</ul>
<p>A list of lanes and intersections actually modified is then returned to the
drawing layer, which uploads new geometry to the GPU accordingly.</p>
<h1><a class="header" href="#development-tricks" id="development-tricks">Development tricks</a></h1>
<ul>
<li>Separate phases for fast incremental development
<ul>
<li>Don't reimport all data from OSM every time there's a change to part of the
map construction code!</li>
<li>For slow steps that don't change often, make them separate binaries -- hence
<code>convert_osm</code> being separate from the rest.</li>
</ul>
</li>
<li>Don't be afraid of manual intervention
<ul>
<li>The data isn't perfect. It's easy to spend lots of time fiddling with code
to automatically handle all problems</li>
<li>Instead of automatically resolving problems, prefer good tooling for finding
and specifying fixes</li>
<li>Be careful of derivative structures that could get out of sync with OSM.
Prefer contributing real fixes to OSM.</li>
</ul>
</li>
<li>Screenshot diff testing
<ul>
<li>When working on the code for intersection geometry, it's easy to check a few
example cases get fixed by some change. But what if another part of the map
regresses somehow?</li>
<li>Take screenshots of the entire map, keep the checksums under version
control, look at the diffs visually, and manually verify any changes.</li>
<li>Implementation details: One huge gif or png is too slow to read and write,
so take a bunch of tiled screenshots covering everything. Amusingly,
rendering to a file with <code>glium</code> is slow unless compiling in release mode
(which isn't an option for quick incremental development). So instead, pan
to each section of the map, render it, call an external screenshot utility,
and move on -- just don't wiggle the mouse during this process!</li>
</ul>
</li>
<li>Different IDs for objects make sense during different phases
<ul>
<li>For the final product, lanes and such are just a contiguous array, indexed
by numeric IDs.</li>
<li>But sometimes, we need IDs that're the same between different boundary
polygons of maps, so that player edits can be applied anywhere. Using
(longitude, latitude) pairs hits floating-point serialization and comparison
issues, so referring to roads as (OSM way ID, OSM node ID 1, OSM node ID 2)
works instead.</li>
</ul>
</li>
</ul>
<h2><a class="header" href="#appendix-polylines" id="appendix-polylines">Appendix: PolyLines</a></h2>
<p>Add some pictures here to demonstrate how polyline shifting works, the
explode-to-infinity problem, and the bevel/miter fix.</p>
<h1><a class="header" href="#ab-streets-traffic-simulation" id="ab-streets-traffic-simulation">A/B Street's Traffic Simulation</a></h1>
<p>This article describes how cars, bikes, buses, and pedestrians are modeled in
A/B Street. All code lives in the <code>sim</code> crate.</p>
<p><a href="https://youtu.be/chYd5I-5oyc?t=1086">This recorded presentation</a> covers some of
this.</p>
<h1><a class="header" href="#discrete-event-simulation" id="discrete-event-simulation">Discrete-event simulation</a></h1>
<p>The traffic simulation models different agents (cars, bikes, buses, pedestrians,
and intersections) over time. Agents don't constantly sense and react to the
world every second; instead, they remain in some state until something
interesting happens. This is a discrete-event architecture -- events are
scheduled for some time in the future, and handling them changes the state of
some agents. The core simulation loop simply processes events in order -- see
<code>scheduler.rs</code> and the <code>step</code> method in <code>sim.rs</code>.</p>
<h2><a class="header" href="#cars" id="cars">Cars</a></h2>
<p>(Note: Cars, bikes, and buses are all modeled the same way -- bikes just have a
max speed, and buses/bikes can use restricted lanes.)</p>
<p>Cars move through a sequence of lanes and turns (movements through an
intersection). They queue and can't over-take a slow lead vehicle. The main
simplifying assumption in A/B Street is that cars can instantly accelerate and
decelerate. This wouldn't model highway driving at all, where things like jam
waves are important, but it's reasonable for in-city driving. The essence of
scarcity is the capacity on lanes and the contention at intersections. What
happens in between isn't vital to get exactly right.</p>
<p>A car has a few states (<code>mechanics/car.rs</code>):</p>
<ul>
<li><strong>Crossing</strong> some distance of a lane/turn over some time interval</li>
<li><strong>Queued</strong> behind another car on a lane/turn</li>
<li><strong>WaitingToAdvance</strong> at the end of a lane, blocked on an intersection</li>
<li>A few states where the car stays in one place: <strong>Parking</strong>, <strong>Unparking</strong>, and
<strong>Idling</strong> (for buses at a stop)</li>
</ul>
<p>State transitions happen in <code>mechanics/driving.rs</code>. This is best explained by an
example sequence:</p>
<ul>
<li>A car enters the Unparking state, taking a fixed 30s to exit a parking spot
and enter the adjacent driving lane. The driving lane is blocked during this
time, to mimic somebody pulling out from a parallel parking spot.</li>
<li>The car is now fully somewhere on the driving lane. It enters the Crossing
state, covering the remaining distance to the end of the road. The time
interval is calculated assuming the car travels at the max speed limit of the
road.</li>
<li>After that time, the car checks if there's anybody in the queue before it.
Nope? Then it attempts to initiate a turn through the intersection, but the
stop sign says no, so the car enters the WaitingToAdvance state.</li>
<li>Some time later, the stop sign wakes up the car. The car starts the turn,
entering the Crossing state again.</li>
<li>After finishing the turn, the car starts Crossing the next lane. When it's
finished, it turns out there are a few cars ahead of it, so it enters the
Queued state.</li>
<li>When the lead vehicle directly in front of the car exits the lane, it wakes up
the car, putting it in the Crossing state, starting at the appropriate
following distance behind the lead vehicle. This prevents the car from
immediately warping to the end of the lane when the lead vehicle is out of the
way.</li>
<li>And so on...</li>
</ul>
<h3><a class="header" href="#exact-positions" id="exact-positions">Exact positions</a></h3>
<p>For a discrete-event simulation, we don't usually care exactly where on a lane a
car is at some time. But we do need to know for drawing and for a few cases
during simulation, such as determining when a bus is lined up with a bus stop in
the middle of a lane. <code>mechanics/queue.rs</code> handles this, computing the distance
of every car in a lane. For cars in the <code>Crossing</code> state, we linearly
interpolate distance based on the current time. Of course, cars have to remain
in order, so Queued cars are limited by the lead vehicle's position + the lead
vehicle's length + a fixed following distance of 1m.</p>
<p>Another case where we need to know exact positions of cars is to prevent the
first vehicle on a lane from hitting the back of a car who just left the lane.
All vehicles have length, and position is tracked by the front of the car. When
a car's front leaves a lane, its back is still partly in the lane. Logically,
the new lead car in the lane still needs to act like it's Queued. So each lane
keeps a &quot;laggy head&quot;, pointing to the car with its back partly in the lane.
After the laggy head has made it sufficient distance along its new turn or lane,
the laggy head on the old lane can be erased, unblocking the lead vehicle. This
requires calculating exact distances and some occasionally expensive cases where
we have to schedule frequent events to check when a laggy head is clear.</p>
<h2><a class="header" href="#lane-changing" id="lane-changing">Lane-changing</a></h2>
<p>Lane-changing (LCing) deserves special mention. A/B Street cheats by not
allowing it on lanes themselves. Instead, at intersections, cars can perform
turns that shift them over any number of lanes. These LCing turns conflict with
other turns appropriately, so the contention is still modeled. Why do it this
way? In a
<a href="http://apps.cs.utexas.edu/tech_reports/reports/tr/TR-2157.pdf">previous project</a>,
I tried opportunistic LCing. If a car had room to warp to the equivalent
distance on the adjacent lane without causing a crash, it would start LCing,
then take a fixed time to slide over, blocking both lanes throughout. This meant
cars often failed to LC when they needed to, forcing them to reroute, botching
their trip times. In many cases the cars would be permanently stuck, because
pathfinding would return paths requiring LCing that couldn't be pulled off in
practice due to really short roads. Why not try making the car slow down if
needed? Eventually it might have to stop, which could lead to unrealistic
gridlock. This LCing model was using a detailed discrete-time model with cars
accelerating properly; maybe it's easier with A/B Street's simplified movement
model.</p>
<p>Currently in A/B Street, cars will pick the least backed-up lane when there's a
choice. They make this decision once when they reach the front of a queue; look
for <code>opportunistically_lanechange</code> in <code>router.rs</code>. The decision could be
improved.</p>
<h2><a class="header" href="#pedestrians" id="pedestrians">Pedestrians</a></h2>
<p>Pedestrian modeling -- in <code>mechanics/walking.rs</code> is way simpler. Pedestrians
don't need to queue on sidewalks; they can &quot;ghost&quot; through each other. In
Seattle, there aren't huge crowds of people walking and slowing down, except for
niche cases like Pike Place Market. So in A/B Street, the only scarce resource
modeled is the time spent waiting to cross intersections.</p>
<h2><a class="header" href="#intersections-1" id="intersections-1">Intersections</a></h2>
<p>I need to flesh this section out. See <code>mechanics/intersections.rs</code> for how stop
signs and traffic signals work. Two things I need to fix before making this
section interesting:</p>
<ul>
<li>Only wake up relevant agents when a previous agent finishes a turn.</li>
<li>Don't let an agent start a low-priority turn (like an unprotected left) if
it'll force a high-priority vehicle approaching to wait. The approaching
vehicle is still in the Crossing state, so we need to notify intersections
ahead of time of intended turns and an ETA.</li>
</ul>
<p>One contributor to permanent gridlock is cars and bikes being stuck in an
intersection, preventing conflicting turns from being performed. To help avoid
this, one of the last checks that stop signs and traffic signals perform before
accepting a new turn request is that the target lane has enough space for the
new vehicle. This is &quot;reserved&quot; space, not necessarily currently occupied by
vehicles in that lane. This accounts for other vehicles performing a turn bound
for that lane. See <code>try_to_reserve_entry</code> in <code>mechanics/queue.rs</code>. When a car
completely leaves a lane (determined by the &quot;laggy head&quot; described above), this
space is freed, and blocked cars are woken up.</p>
<h2><a class="header" href="#appendix-discrete-time-simulation" id="appendix-discrete-time-simulation">Appendix: discrete-time simulation</a></h2>
<p>A/B Street's first traffic model was discrete-time, meaning that every agent
reacted to the world every 0.1s. Cars had a more realistic kinematics model,
accelerating to change speed and gradually come to a halt. Cars did a worst-case
estimation of how far ahead they need to lookahead in order to satisfy different
constraints:</p>
<ul>
<li>Don't exceed any speed limits</li>
<li>Don't hit the lead vehicle (which might suddenly slam on its brakes)</li>
<li>Stop at the end of a lane, unless the intersection says to go</li>
</ul>
<p>After fighting with this approach for a long time, I eventually scrapped it in
favor of the simpler discrete-event model because:</p>
<ul>
<li>It's fundamentally slow; there's lots of busy work where cars in freeflow with
nothing blocking them or stopped in a long queue constantly check to see if
anything has changed.</li>
<li>Figuring out the acceleration to apply for the next 0.1s in order to satisfy
all of the constraints is really complicated. Floating point inaccuracies
cause ugly edge cases with speeds that wind up slightly negative and with cars
coming to a complete stop slightly past the end of a lane. I wound up storing
the &quot;intent&quot; of an action to auto-correct these errors.</li>
<li>The realism of having cars accelerate smoothly didn't add value to the core
idea in A/B Street, which is to model points of contention like parking
capacity and intersections. (This is the same reason why I don't model bike
racks for parking bikes -- in Seattle, it's never hard to find something to
lock to -- this would be very different if Copenhagen was the target.)
Additionally, the kinematics model made silly assumptions about driving anyway
-- cars would smash on their accelerators and brakes as hard as possible
within all of the constraints.</li>
</ul>
<h1><a class="header" href="#travel-demand" id="travel-demand">Travel demand</a></h1>
<p>A/B Street simulates people following a schedule of trips over a day. A single
<em>trip</em> has a start and endpoint, a departure time, and a mode. Most trips go
between buildings, but the start or endpoint may also be a border intersection
to represent something outside the map boundaries. The mode specifies whether
the person will walk, bike, drive, or use transit. Without a good set of people
and trips, evaluating some changes to a map is hard -- what if the traffic
patterns near the change aren't realistic to begin with? This chapter describes
where the travel demand data comes from.</p>
<h2><a class="header" href="#scenarios" id="scenarios">Scenarios</a></h2>
<p>A <em>scenario</em> encodes the people and trips taken over a day. See the
<a href="https://github.com/dabreegster/abstreet/blob/master/sim/src/make/scenario.rs">code</a>.</p>
<p>TODO:</p>
<ul>
<li>talk about vehicle assignment / parked car seeding</li>
</ul>
<h2><a class="header" href="#data-sources" id="data-sources">Data sources</a></h2>
<h3><a class="header" href="#seattle-soundcast" id="seattle-soundcast">Seattle: Soundcast</a></h3>
<p>Seattle luckily has the Puget Sound Regional Council, which has produced the
<a href="https://www.psrc.org/activity-based-travel-model-soundcast">Soundcast model</a>.
They use census stats, land parcel records, observed vehicle counts, travel
diaries, and lots of other things I don't understand to produce a detailed model
of the region. We're currently using their 2014 model; the 2018 one should be
available sometime in 2020. See the
<a href="https://github.com/dabreegster/abstreet/tree/master/importer/src/soundcast">code</a>
for importing their data.</p>
<p>TODO:</p>
<ul>
<li>talk about how trips beginning/ending off-map are handled</li>
</ul>
<h3><a class="header" href="#berlin" id="berlin">Berlin</a></h3>
<p>This work is <a href="https://github.com/dabreegster/abstreet/issues/119">ongoing</a>. See
the
<a href="https://github.com/dabreegster/abstreet/blob/master/importer/src/berlin.rs">code</a>.
So far, we've found a population count per planning area and are randomly
distributing the number of residents to all residential buildings in each area.</p>
<h3><a class="header" href="#proletariat-robot" id="proletariat-robot">Proletariat robot</a></h3>
<p>What if we just want to generate a reasonable model without any city-specific
data? One of the simplest approaches is just to spawn people beginning at
residential buildings, make them go to some workplace in the morning, then
return in the evening. OpenStreetMap building tags can be used to roughly
classify building types and distinguish small houses from large apartments. See
the <code>proletariat_robot</code>
<a href="https://github.com/dabreegster/abstreet/blob/master/sim/src/make/activity_model.rs">code</a>
for an implementation of this.</p>
<p>This is <a href="https://github.com/dabreegster/abstreet/issues/154">ongoing</a> work
spearheaded by Mateusz. Some of the ideas for next steps are to generate
different types of people (students, workers), give them a set of activities
with durations (go to school for 7 hours, 1 hour lunch break), and then further
pick specfic buildings to travel to using more OSM tags.</p>
<h3><a class="header" href="#custom-import" id="custom-import">Custom import</a></h3>
<p>If you have your own data, you can import it. The input format is JSON -- an
example:</p>
<pre><code>{
&quot;scenario_name&quot;: &quot;monday&quot;,
&quot;people&quot;: [
{
&quot;origin&quot;: {
&quot;longitude&quot;: -122.303723,
&quot;latitude&quot;: 47.6372834
},
&quot;trips&quot;: [
{
&quot;departure&quot;: 10800.0,
&quot;position&quot;: {
&quot;longitude&quot;: -122.3075948,
&quot;latitude&quot;: 47.6394773
},
&quot;mode&quot;: &quot;Drive&quot;
}
]
}
]
}
</code></pre>
<p>Run the tool:</p>
<pre><code>cargo run --bin import_traffic -- --map=data/system/maps/montlake.bin --input=/path/to/input.json
</code></pre>
<p>The tool matches input positions to the nearest building or border intersection,
within 100 meters. The <code>departure</code> time is seconds since midnight. The tool will
fail if any point doesn't match to a building, or if any of the specified trips
can't be created (due to graph connectivity problems, for example). If your
requirements are different or you have any trouble using this format/tool,
please file a Github issue -- just consider this tool and format a prototype.</p>
<h2><a class="header" href="#modifying-demand" id="modifying-demand">Modifying demand</a></h2>
<p>The travel demand model is extremely fixed; the main effect of a different
random number seed is currently to initially place parked cars in specific
spots. When the player makes changes to the map, exactly the same people and
trips are simulated, and we just measure how trip time changes. This is a very
short-term prediction. If it becomes much more convenient to bike or bus
somewhere, then more people will do it over time. How can we transform the
original demand model to respond to these changes?</p>
<p>Right now, there's very preliminary work in sandbox mode for Seattle weekday
scenarios. You can cancel all trips for some people (simulating lockdown) or
modify the mode for some people (change 50% of all driving trips between 7 and
9am to use transit).</p>
<h2><a class="header" href="#research" id="research">Research</a></h2>
<ul>
<li><a href="https://github.com/replicahq/doppelganger">https://github.com/replicahq/doppelganger</a></li>
<li><a href="https://github.com/stasmix/popsynth">https://github.com/stasmix/popsynth</a></li>
<li><a href="https://zephyrtransport.github.io/zephyr-directory/projects/">https://zephyrtransport.github.io/zephyr-directory/projects/</a></li>
<li><a href="https://activitysim.github.io">https://activitysim.github.io</a></li>
<li><a href="https://github.com/BayAreaMetro/travel-model-one">https://github.com/BayAreaMetro/travel-model-one</a></li>
<li><a href="https://github.com/RSGInc/DaySim">https://github.com/RSGInc/DaySim</a></li>
<li><a href="https://github.com/arup-group/pam">https://github.com/arup-group/pam</a></li>
</ul>
<h1><a class="header" href="#gridlock" id="gridlock">Gridlock</a></h1>
<p>Here &quot;gridlock&quot; refers to the general problem of trips getting permanently
stuck, preventing the full simulation from completing. Most of the work is
tracked <a href="https://github.com/dabreegster/abstreet/issues/114">here</a>.</p>
<p>My general approach right now to get a map working is to cancel some percent of
all trips, look for individual problems, fix them, and repeat. Once the full day
works, cancel less trips. It's easier to isolate the root cause of problems when
there are less of them erupting simultaneously.</p>
<p>The general lesson is: you can't code your way around all edge cases. The data
in OSM often needs manual fixes. It's often useful to spend coding effort on
tools to detect and fix OSM problems.</p>
<h2><a class="header" href="#problems" id="problems">Problems</a></h2>
<p>The choices in the movement model matter. Some gridlock is inherent to any
system with queueing and conflicting turns. But in reality, people wiggle around
partly blocked turns. And some of this comes from the treatment of the
front/back of vehicles.</p>
<ul>
<li>Short roads in OSM causing very weird geometry</li>
<li>Intersection geometry being too large, requiring too much time to cross</li>
<li>Unrealistic traffic patterns caused by everyone trying to park in one big
garage (downtown) or take some alley (the UW soundcast issue)</li>
<li>Too many people try to take an unprotected left turn (often at a stop sign)</li>
<li>Bad individual traffic signals, usually at 5- or 6-ways</li>
<li>Groups of traffic signals logically acting as a single intersection</li>
<li>Separate traffic signals along a corridor being unsynchronized</li>
<li>Vehicles performing illegal sequences of turns</li>
<li>Vehicles are stuck with their plan and not reacting to traffic by changing
route</li>
<li>Real traffic would result in a gridlock without a deliberate actions to avoid
it. Such actions range from individual decisions of drivers to police manually
controlling traffic. Intelligent avoidance of gridlock is not simulated and is
extremely hard to simulate.</li>
<li>Vehicles will wait in lane filled with already waiting vehicles, even if there
is a completely empty lane allowing travel in desired direction. It makes
easier for entire lane between crossings to fill, contributing to gridlocks.
Note that while this and other clearly stupid behaviors are clearly
unrealistic, it is not trivial to implement more realistic and more efficient
decisions.</li>
<li>Issues caused by the unrealistic
<a href="https://github.com/dabreegster/abstreet/blob/master/docs/articles/trafficsim/article.md#lane-changing">lane-changing model</a>
<ul>
<li>Two turns that go to the same lane (one going &quot;straight&quot;, the other often a
lane-change) conflict. The conflict is coarse, at the granularity of the
entire intersection. So if vehicles are piled up in two lanes trying to
merge into one, then one group is likely to go through as expected, but the
second group will wait for the first to completely clear the intersection.
Until then, it looks like a conflicting turn is being done.</li>
</ul>
</li>
</ul>
<h2><a class="header" href="#solutions" id="solutions">Solutions</a></h2>
<p>Divide into implemented or not.</p>
<ul>
<li>Synchronizing pairs of signals</li>
<li>Uber-turns
<ul>
<li>for interpreting OSM turn restrictions</li>
<li>for synchronizing a group of signals</li>
<li>for locking turn sequences
<ul>
<li>Once a vehicle starts an uber-turn, prevent others from starting
conflicting turns on nearby intersections. Until groups of traffic signals
are configured as one, this is necessary to prevent somebody from making
it halfway through a sequence then getting blocked.</li>
</ul>
</li>
</ul>
</li>
<li>Cycle detector</li>
<li>block-the-box protection
<ul>
<li>the manual list of overrides</li>
<li>likely shouldn't apply during uber-turns</li>
<li>is it always fine to block the box at degenerate intersections?</li>
</ul>
</li>
<li>hacks to allow conflicting turns at really broken intersections</li>
<li>manually timing signals</li>
<li>penalties for lane choice to make lane usage realistic</li>
</ul>
<h3><a class="header" href="#not-implemented" id="not-implemented">Not implemented</a></h3>
<ul>
<li>Dynamic rerouting</li>
<li>Allow multiple vehicles through intersection at once if there is enough space
on lane where given vehicle is going. Currrently vehicles travel through
crossings one by one (or, with <code>--disable_block_the_box</code> enabled - will enter
crossing even if leaving it will be impossible).</li>
<li>Last resort: if someone's waiting on a turn &gt;5m, just go.</li>
<li>Uber-turns
<ul>
<li>Group both stop sign and traffic signal intersections when looking for
uber-turns. Even a single traffic signal surrounded by tiny roads with stop
signs is causing problems.</li>
</ul>
</li>
</ul>
<h2><a class="header" href="#fixing-data-used-in-simulation" id="fixing-data-used-in-simulation">Fixing data used in simulation</a></h2>
<p>Give more examples of changesets.</p>
<ul>
<li>upstreaming turn restrictions into OSM to prevent invalid U-turns and other
crazy movements
<ul>
<li>ex: <a href="https://www.openstreetmap.org/changeset/87945050">https://www.openstreetmap.org/changeset/87945050</a></li>
</ul>
</li>
<li>upstreaming lane count fixes into OSM to improve geometry</li>
</ul>
<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>
<p><img src="trafficsim/../mdbook-plantuml-img/bbf8881e880a261530dd998679b4f47108dfc748.svg" alt="" /></p>
<h2><a class="header" href="#trips-starting-from-a-border" id="trips-starting-from-a-border">Trips starting from a border</a></h2>
<p><img src="trafficsim/../mdbook-plantuml-img/1cd9d730c8982c5ba59b825b427e712fab82e681.svg" alt="" /></p>
<h2><a class="header" href="#trips-starting-from-a-building" id="trips-starting-from-a-building">Trips starting from a building</a></h2>
<p><img src="trafficsim/../mdbook-plantuml-img/92ec1d5cbfccd87df09b67ac1a2b26aebf81eee8.svg" alt="" /></p>
<h1><a class="header" href="#live-edits-1" id="live-edits-1">Live edits</a></h1>
<p>When the player edits the map, there's an
<a href="https://dabreegster.github.io/abstreet/map/edits.html">efficient process</a> for
applying the edits at the map model and rendering layer. In the middle of a
simulation, it's less obvious how to apply all edits. Most of the time
currently, edits cause the simulation to reset to midnight. Applying edits to
the sim without reset is important for running machine learning experiments and
for improving the gameplay experience (by having more immediate feedback about
the consequences of a change).</p>
<p>The UI has a <code>dirty_from_edits</code> bit to track when changes have been applied
without reset. This lets us tell the player that by the end of the day, any
score / results are tentative, because their edits might have a different effect
earlier in the day.</p>
<h2><a class="header" href="#what-works-today" id="what-works-today">What works today</a></h2>
<p>Changes to traffic signals are simple -- <code>incremental_edit_traffic_signal</code>
happens at the map layer, and then <code>handle_live_edited_traffic_signals</code> at the
sim layer just resets the current stage to 0 if the previous configuration had
more stages.</p>
<h2><a class="header" href="#todo-recalculating-paths" id="todo-recalculating-paths">TODO: Recalculating paths</a></h2>
<p>Many of the edits will influence routes. For trips that haven't started yet, as
long as <code>pathfinding_upfront</code> is disabled (currently the default), there's
nothing to do. For currently active trips, in some cases, rerouting would be
ideal but not necessary (like if speed limits changed). In other cases -- like
changing access restrictions, modifying lane types, closing intersections -- the
route must be recomputed. As a simple first attempt, we could just abort all
active trips whose path crosses an edited road or intersection. Later, we can
figure out rerouting.</p>
<p>And actually, the only other case to handle is <code>ChangeRouteSchedule</code>, which
should just be rescheduling the <code>StartBus</code> commands.</p>
<h2><a class="header" href="#todo-parking" id="todo-parking">TODO: Parking</a></h2>
<p>What happens if you modify a parking lane while there are cars on it? For now,
just delete them. Trips later making use of them will just act as if the car
never had room to be spawned at all and be aborted or fallback to walking.</p>
<p>A better resolution would be to relocate them to other parking spots. If the
owner is home, it'd be neat to have them walk outside, move the car, and go back
in. But this greatly complicates the simulation -- the edited lane is in a
transition state for a while, it modifies schedules, the person might not be
around, etc.</p>
<h1><a class="header" href="#project-logistics" id="project-logistics">Project logistics</a></h1>
<p>This has some background/logistics about the project.</p>
<h1><a class="header" href="#roadmap" id="roadmap">Roadmap</a></h1>
<p>A/B Street has been under active development since June 2018. That's a long time
-- what work is happening now and how can you contribute?</p>
<h2><a class="header" href="#next-steps-summer-2020" id="next-steps-summer-2020">Next steps, summer 2020</a></h2>
<p>Afer the alpha launch in June, I plan to focus on:</p>
<ul>
<li>shared biking/walking trails like the Burke Gilman</li>
<li>light rail</li>
<li>more score functions besides trip time, like safety/comfort</li>
<li>changing trip mode choice (if you make a bus route more desirable, switch some
trips)</li>
<li>web support (so people can try out proposals without installing anything)</li>
</ul>
<h2><a class="header" href="#ongoing-work" id="ongoing-work">Ongoing work</a></h2>
<p>If I had resources to hire a team, this is roughly how I'd organize different
roles. If you're interested in helping, these aren't strictly defined positions,
just ideas of related tasks.</p>
<h3><a class="header" href="#ui-and-data-visualization" id="ui-and-data-visualization">UI and data visualization</a></h3>
<p>We've got a UX designer, but implementing all of the new designs takes time.
Also:</p>
<ul>
<li>improve color schemes for colorblind players, implement night mode, rain
effects, etc</li>
<li>refactor and clean up the GUI library for other Rust users</li>
<li>lots of data viz design / implementation needed</li>
</ul>
<h3><a class="header" href="#game-design" id="game-design">Game design</a></h3>
<ul>
<li>the tutorial mode needs attention</li>
<li>many ideas for challenge/story modes, but playtesting, tuning, and game design
needed</li>
</ul>
<h3><a class="header" href="#map-data--gis" id="map-data--gis">Map data / GIS</a></h3>
<p>Support more cities:</p>
<ul>
<li>write docs/tools to help people add new cities without programming experience</li>
<li>add support for non-OpenStreetMap input: GeoJSON for parking in Perth, other
trip demand sources, etc</li>
<li>fix bugs for driving on the left side of the road</li>
</ul>
<p>Improve the quality of map geometry derived from OpenStreetMap:</p>
<ul>
<li>try new algorithms to generate intersection polygons</li>
<li>make tools for easily improving relevant data in OSM</li>
<li>use ML and lidar/satellite data to get extremely accurate curb / planter /
sidewalk geometry</li>
</ul>
<p>Build tools and organize community mapping:</p>
<ul>
<li>organize an effort to map how traffic signals are timed (partly started)</li>
<li>divide and track work for distributed mapathons</li>
</ul>
<p>Bring in new data to understand more about cities:</p>
<ul>
<li>PM2.5 pollution</li>
<li>Tax / land value (is there inequitable access to transit?)</li>
</ul>
<h3><a class="header" href="#simulation--modeling" id="simulation--modeling">Simulation / modeling</a></h3>
<p>Totally new areas:</p>
<ul>
<li>light rail</li>
<li>shared bike/pedestrian paths</li>
<li>ridesharing</li>
<li>micromobility (scooters, floating bikeshare)</li>
<li>more score functions (elevation gain, biking safety)</li>
<li>generating trip demand / activity models from scratch or modifying existing
ones</li>
</ul>
<p>Improve existing models:</p>
<ul>
<li>overtaking / lane-changing</li>
<li>pedestrian crowds</li>
<li>instant vehicle acceleration</li>
<li>pedestrians walking on road shoulders (some streets have no sidewalks)</li>
<li>buses: transfers, proper schedules, multiple buses per route</li>
</ul>
<h3><a class="header" href="#web" id="web">Web</a></h3>
<p>A/B Street runs on the web via WASM and WebGL; just waiting on vector text
support. Besides that:</p>
<ul>
<li>Share community proposals online, discuss them, vote, etc</li>
</ul>
<h2><a class="header" href="#contributing-for-non-programmers" id="contributing-for-non-programmers">Contributing for non-programmers</a></h2>
<p>There's plenty to do besides programming!</p>
<ul>
<li>Mapping, most of which directly contributes to OpenStreetMap:
<ul>
<li>sidewalks and crosswalks</li>
<li><a href="https://dabreegster.github.io/abstreet/map_parking.html">on-street parking</a></li>
<li><a href="https://docs.google.com/document/d/1Od_7WvBVYsvpY4etRI0sKmYmZnwXMAXcJxVmm8Iwdcg/edit?usp=sharing">traffic signal timing</a></li>
</ul>
</li>
<li>Playtesting by attempting to implement real proposals would also be helpful,
to expose where it's awkward for A/B Street to edit the map and to write up
problems encountered.</li>
<li>Advocacy: I'm not great at finding the right people to to get ideas
implemented for real. Maybe you are?</li>
</ul>
<h2><a class="header" href="#long-term-vision" id="long-term-vision">Long-term vision</a></h2>
<p>Longer term, I'd like to take lots of the work in generating and interacting
with high-detail OpenStreetMap-based maps and generalize it, possibly as a new
OSM viewer/editor.</p>
<p>More generally, I'd like to see how simulation can help individuals understand
and explore other policy decisions related to cities. Domains I'm vaguely
interested in, but not at all knowledgable about, include land-use / zoning,
housing, and supply chains. In late March 2020, a new collaborator started a
pandemic model using the existing simulation of people occupying shared spaces.
What are other domains could benefit from the rich agent-based model we're
building?</p>
<h1><a class="header" href="#project-motivations" id="project-motivations">Project motivations</a></h1>
<p>I thought it'd be helpful to explain what motivates my work in A/B Street. These
are just my personal values; I don't intend to make a careful argument about
these here. In no particular order:</p>
<ul>
<li>
<p><strong>Transparency and reproducibility</strong>: if city government uses data, modeling,
or simulation to inform a decision affecting the general public, then anybody
ought to be able to repeat that analysis.</p>
<ul>
<li>This means code and data should be open.</li>
<li>Businesses like <a href="https://replicahq.com/">Sidewalk Lab's Replica</a> and
<a href="https://www.remix.com/solutions/streets">Remix</a> still need to generate
income, but it's unclear why governments use taxes to pay for something only
they see.</li>
<li>Decision making should be documented clearly. Why were the
<a href="https://www.seattle.gov/transportation/projects-and-programs/programs/maintenance-and-paving/current-paving-projects/35th-ave-ne">35th Ave bike lanes</a>
scrapped? Was the amount of on-street parking on nearby residential roads
factored in? Was there analysis of how trip time is impacted by parking in
the neighborhood and walking a few blocks to a business on the arterial?</li>
<li>I'm personally inspired by approaches like
<a href="https://info.vtaiwan.tw/">vTaiwan</a> and
<a href="https://po.pdis.nat.gov.tw/en/opengov/">PDIS</a></li>
</ul>
</li>
<li>
<p><strong>Accessibility leads to participation</strong>: There's overhead to taking small
ideas to advocacy groups or inconveniently timed public meetings. If the
planning process is easier to interact with, more people will participate.</p>
<ul>
<li>Seattle's
<a href="https://www.seattle.gov/neighborhoods/programs-and-services/your-voice-your-choice">Your Voice, Your Choice</a>
program is maybe an example of this</li>
</ul>
</li>
<li>
<p><strong>Short-term changes</strong>: <a href="https://en.wikipedia.org/wiki/Sound_Transit_3">ST3</a>
is exciting, but 2040 isn't close. There are much cheaper changes that can be
implemented sooner.</p>
<ul>
<li>Most of the edits in A/B Street are inspired by tactical urbanism; they
could be prototyped with signs and paint.</li>
</ul>
</li>
<li>
<p><strong>The US is too dependent on cars</strong>: This has an unacceptable impact on the
environment. Even ignoring that, many cities are out of room to build more
roads. We can't keep scaling population like this.</p>
</li>
<li>
<p><strong>Autonomous vehicles will NOT save the day</strong>: They can squeeze more
throughput out of existing infrastructure, but only up to a point. They might
encourage people to move and tolerate longer commutes. Mass transit and dense
land-use patterns handle population growth better.</p>
</li>
<li>
<p><strong>Compromise and trade-offs</strong>: I see lots of rhetoric calling for extreme,
sudden change. I don't want to ban all cars from downtown Seattle, because
that's not realistic. I want to focus on immediate steps forward. I want to
come up with estimates about impacting drivers by a median 3 minutes in order
to save a bus route 1 minute, and to shift public discourse towards that.</p>
</li>
</ul>
<h1><a class="header" href="#project-history" id="project-history">Project history</a></h1>
<p>As of June 2020.</p>
<p>tldr: A/B Street has been in active development since June 2018, but the idea
has been festering since I was about 16.</p>
<h2><a class="header" href="#retrospective" id="retrospective">Retrospective</a></h2>
<p>What poor judgments have cost me the most time?</p>
<ul>
<li>UI churn: I should've studied some UX on my own and started with a clear idea
of how to organize everything</li>
<li>OSM data quality: I should've gained the confidence to upstream fixes earlier</li>
<li>Intersection geometry: I should've realized sooner that simulation robustness
is more important than nice appearance.</li>
<li>Geometry primitives: I sunk too much time into the polyline problem and f64
precision.</li>
</ul>
<h2><a class="header" href="#trivia" id="trivia">Trivia</a></h2>
<ul>
<li>The name was almost &quot;Unstreet&quot; or &quot;Superban&quot; (superb urban)</li>
<li>I hope you enjoy and/or are baffled by the
<a href="https://github.com/dabreegster/abstreet/releases">release names</a></li>
</ul>
<h1><a class="header" href="#backstory" id="backstory">Backstory</a></h1>
<p>I originally wanted to tell a much longer story here of how I came to work on
A/B Street, but I'm not sure this is the right time yet. So consider this the
quick version.</p>
<p>I grew up in Baton Rouge, where driving is effectively the only mode of
transport. (I've gone back and made a point of taking long walks to confirm how
antagonistically the city is designed towards walking.) Very early on, I fell in
love with a Nintendo 64 game called Banjo Kazooie, which led me to the online
fan communities of the early 2000's. I wanted to create games too, so I started
learning programming via library books and lots of questions on IRC. Because I
never had any confidence in art, I wound up working on
<a href="https://github.com/dabreegster/mnemonicrl/">roguelikes</a>, which led to a fervent
interest in pathfinding algorithms and
<a href="http://www.cs.colorado.edu/%7Eralex/papers/PDF/OOPSLA06antiobjects.pdf">collaborative diffusion</a>.
When I started driving in high school, I quickly realized how bad people were at
it. I remember being stuck at the intersection of
<a href="https://www.openstreetmap.org/node/1279204989">Florida Blvd and Cloud</a> and
first wondering if the pathfinding algorithms could help with traffic. Can you
see where this is going?</p>
<p><img src="project/history/cloud_florida.jpg" alt="Impatience is a virtue" /></p>
<p>I moved to Austin for college. One of the first days of class, I shuffled down
the stairs of Gearing Hall past a crackly old speaker apocalyptically announcing
the weather forecast (details add color, right?) into a seminar demanding a
totally open-ended first assignment to do something interesting. After I left,
somebody stopped to ask me for directions, but I didn't know campus well yet. I
thought about how Google Maps gave really silly walking directions. So I decided
I'd hand-draw a map of campus, showing all of the construction, how to cut
through the labryinth that is Welch Hall on hot days, and where to find the 24/7
robot coffee machines, and hack together a routing engine to help people find
the shortest path between their classes. The feedback I got on this assignment
included something along the lines of, &quot;I was really pretty impressed first that
you would be so stupid as to actually try to do this...&quot;</p>
<p><img src="project/history/ut_map.png" alt="Hand-mapping UT Austin" /></p>
<p>But I did, and that led me to discovering OpenStreetMap, which it turns out was
pretty pivotal. (The first version of my campus map was seeded vaguely off an
official paper map, but mostly I walked around and invented half-assed surveying
methods on the spot.) Next semester, I joined a freshman research stream with
somebody who had worked on <a href="http://www.cs.utexas.edu/%7Eaim/">AIM</a>, UT's
demonstration that autonomous vehicles wouldn't need traffic lights. Everything
came together, and I started a 3 year journey of building
<a href="https://github.com/dabreegster/aorta/">AORTA</a>, a traffic simulator for AVs.
Guided by the research lab, I explored the really bizarre idea of letting AVs
<a href="http://www.cs.utexas.edu/%7Eaim/papers/ITSC13-dcarlino.pdf">bid to turn lights green sooner</a>
and micro-tolling all roads to disincentivize congestion. Both of these
mechanisms would be incredibly unfair to people without the spare cash to back
up their high value-of-time, but I brushed this off by saying the currency could
be based on carpooling, EVs, etc.</p>
<p><img src="project/history/aorta.gif" alt="Approximately Orchestrated Routing and Transportation Analyzer" /></p>
<p>It was great to try research in college; I learned I <em>really</em> dislike munging
data and compressing my work into 6 pages of conference paper LaTeX. So I moved
to Seattle to work in industry instead, on something completely unrelated to
transportation. Lots of things began unravelling for me in Seattle, but one of
them was biking. In Austin, I had picked up mountain biking, and all but stopped
driving; it was an amazing place to explore and commute by bike. Seattle was
different. There were many more cyclists around, but the experience felt more
stressful, the drivers more aggressive. I had plenty of near-misses. I kept
commuting by bike, but the joy of it was gone. I started noticing how many cars
were parked on narrow arterials and wondering why that was a fair use of space.
I started paying attention to the public discourse around bike infrastructure in
Seattle and feeling like the conversation was... chaotic.</p>
<p><img src="project/history/manhattan.jpg" alt="Manhattan took walkability seriously" /></p>
<p>Fast forward to late 2017. This is where I'll omit chunks of the story. I
visited London, my first experience with a city that took public transit
seriously. When I returned, lots of latent ideas stopped fermenting and started
exploding. I threw together a prototype of A/B Street and started the arduous
process at work of open-sourcing it and applying to a program to let me work it
on for a few quarters. A few months later, I wound up quitting instead, and
began to work on A/B Street in earnest.</p>
<h1><a class="header" href="#year-1-june-2018-2019" id="year-1-june-2018-2019">Year 1 (June 2018-2019)</a></h1>
<p>I skimmed through git and summarized roughly what I was working on each month,
calling out milestones. &quot;UI churn&quot; is pretty much constantly happening.</p>
<ul>
<li>
<p>June: polyline geometry and lanes, building paths, protobuf -&gt; serde</p>
</li>
<li>
<p>July: pedestrians, bikes, parked cars, lane edits</p>
</li>
<li>
<p>August: porting AORTA's discrete-time driving model</p>
</li>
<li>
<p>September: multi-leg trips, buses, the first ezgui wizard, randomized
scenarios</p>
</li>
<li>
<p>October: A/B test mode (and so per-map plugins), forking RNG for
edit-invariance, intersection geometry</p>
</li>
<li>
<p>November: clipping / borders, using blockface for parking, time travel mode,
test runner framework</p>
</li>
<li>
<p>December: bezier curves for turns, traffic signal editor, a first attempt at
merging intersections, right-click menus, a top menu, modal menus</p>
<ul>
<li>the grand colorscheme refactor: a python script scraped <code>cs.get_def</code> calls
at build-time</li>
</ul>
</li>
<li>
<p>January: careful f64 resolution, ezgui screencapping, synthetic map editor</p>
<ul>
<li><strong>grand refactor</strong>: piston to glium</li>
</ul>
</li>
<li>
<p>February: attempting to use time-space intervals for a new driving model, new
discrete-event model instead</p>
<ul>
<li><strong>Feb 19-27</strong>: conceiving and cutting over to the new discrete event model</li>
</ul>
</li>
<li>
<p>March: fleshing out DES model (laggy heads), first attempt to build on
windows, gridlock detection</p>
</li>
<li>
<p>April: first public releases, splash screen and rearranging game modes</p>
</li>
<li>
<p>May: fancier agent rendering, attempting to use census tracts, finding real
demand data</p>
<ul>
<li><strong>milestone</strong>: discovered PSRC Soundcast data, much more realistic trips</li>
</ul>
</li>
</ul>
<h1><a class="header" href="#year-2-june-2019-2020" id="year-2-june-2019-2020">Year 2 (June 2019-2020)</a></h1>
<p><img src="project/history/oct_2019.png" alt="Circa October 2019" /></p>
<ul>
<li>
<p>June: contraction hierarchies for pathfinding, stackable game states</p>
</li>
<li>
<p>July: OSM turn restrictions, misc (I think I was in Europe?)</p>
</li>
<li>
<p>August: pedestrian crowds, agent color schemes, parking blackholes, a big
<code>raw_data</code> refactor to store <code>Pt2D</code>, attended first hackathon</p>
</li>
<li>
<p>September: offstreet parking, associating parked cars with buildings using
Soundcast (before that, anybody could use any car!), implemented texture
support for some reason, doing manual <code>MapFixes</code> at scale to fix OSM bugs</p>
<ul>
<li><strong>milestone</strong>: got the smallest montlake map to run without gridlock</li>
</ul>
</li>
<li>
<p>October: parking sim fixes, opportunistic lane-changing, starting challenge
modes</p>
</li>
<li>
<p>November: prebaked sim results, time-series plots, undo for edit mode, traffic
signal editor grouping turns</p>
<ul>
<li><strong>milestone</strong>: Yuwen joins project</li>
</ul>
</li>
<li>
<p>December: the UI reform begins (flexbox, minimap, trip timelines, cutting over
to SVGs, info panels, scrolling), started naming releases sensibly</p>
<ul>
<li>Project leaked to <a href="https://news.ycombinator.com/item?id=21763636">HN</a>, woops</li>
</ul>
</li>
<li>
<p>January: UI reform continues, the modern tutorial mode appears</p>
</li>
<li>
<p>Feburary: UI and tutorial, all text now pure vectors, port to glow+WASM</p>
</li>
<li>
<p>March: lockdowns start in US, start grouping trips as a person, population
heatmap, left-hand driving, info panel and typography overhauls. started
engaging with Greenways, started effort to map traffic signals</p>
</li>
<li>
<p>April: Orestis joins and starts the pandemic model, trip tables, the optimize
commute challenge, refactor for people's schedules and owned vehicles, trip
time dat viz, MAJOR progress fixing gridlock at the sim layer</p>
</li>
<li>
<p>May: gridlock progress, upstreaming fixes in OSM, differential throughput and
first real write-up, long-lasting player edits, dedicated parking mapper,
maybe vanquished the HiDPI bugs, multi-step turn restrictions, random bios for
people, and docs like this to prep for launch ;)</p>
<ul>
<li><strong>milestone</strong>: relying on pure OSM, no more <code>MapFixes</code></li>
</ul>
</li>
</ul>
<h1><a class="header" href="#year-3-june-2020-2021" id="year-3-june-2020-2021">Year 3 (June 2020-2021)</a></h1>
<ul>
<li>June: parking lots, real minimap controls, road labels
<ul>
<li><strong>June 22</strong>: alpha launch!
<a href="https://old.reddit.com/r/Seattle/comments/hdtucd/ab_street_think_you_can_fix_seattles_traffic/">r/Seattle</a>,
<a href="https://old.reddit.com/r/SeattleWA/comments/hdttu8/ab_street_think_you_can_fix_seattles_traffic/">r/SeattleWA</a>,
<a href="https://old.reddit.com/r/urbanplanning/comments/hdylmo/ab_street_a_traffic_simulation_game/">r/UrbanPlanning</a>,
<a href="https://news.ycombinator.com/item?id=23605048#23608365">HN</a>,
<a href="https://www.geekwire.com/2020/want-fix-seattle-traffic-redditor-makes-game-allows-players-tweak-city-streets/">GeekWire</a>,
<a href="https://www.thestranger.com/slog/2020/06/29/43999454/ab-streets-game-lets-you-create-the-seattle-street-grid-of-your-dreams">The Stranger</a></li>
</ul>
</li>
<li>July: loads of bugfixes, map geometry improvements, UI cleanups,
access-restricted zones for private neighborhoods and no-through-traffic,
better traffic generation between home&lt;-&gt;work for new maps, complete overhaul
to bus routes and introduction of light rail, commute pattern explorer,
importing Krakow and Berlin, smarter lane-changing, walkable shoulders for
roads without sidewalks
<ul>
<li><a href="https://www.youtube.com/watch?v=Pk8V-egsUxU">KING 5 Evening</a> interview</li>
</ul>
</li>
<li>August: Michael joins, multiple traffic signals can be edited together,
started a headless JSON API, support for other languages in OSM data, started
congestion capping, backwards-compatible and more robust map edits, two-way
cycletracks, more cities imported, slurry of bugfixes and performance
improvements
<ul>
<li><a href="https://bikesiliconvalley.org/2020/07/poster_dustin-carlino/">Silicon Valley Bike Summit</a>,
<a href="https://www.seattlepi.com/local/transportation/slideshow/solve-Seattles-traffic-problem-in-this-video-game-205839.php">Seattle PI</a></li>
</ul>
</li>
</ul>
<h1><a class="header" href="#changelog" id="changelog">CHANGELOG</a></h1>
<p>Every time I upload a new <a href="https://github.com/dabreegster/abstreet/releases">binary
release</a>, I'll list major
changes here.</p>
<p>0.1.0</p>
<ul>
<li>First binary release</li>
</ul>
<p>0.1.1</p>
<ul>
<li>drawing arrows better</li>
<li>start with a splash screen, make it easy to change maps in-game</li>
</ul>
<p>0.1.2</p>
<ul>
<li>totally revamp GUI by organizing everything into distinct gameplay modes</li>
</ul>
<p>0.1.3</p>
<ul>
<li>new warp tool that autocompletes street names</li>
<li>hideable menus, place context menus better, remove top menu bar, add a simple OSD</li>
<li>loading screens reflect what's printed to the terminal</li>
<li>depict pedestrians and bikes with more detail</li>
<li>tool to scroll through an agent's route</li>
<li>make simulation speed controls actually work</li>
</ul>
<p>0.1.4</p>
<ul>
<li>improve stop sign editor UI (toggle entire roads)</li>
<li>better mouseover / selection rendering</li>
<li>better traffic signal rendering (show time left, use outlines for yields)</li>
<li>make cars actually stop and briefly wait at stop signs</li>
<li>improve edit mode diff visualization (cross-hatching)</li>
<li>render actual stop signs, not just red lines</li>
<li>fix intersection policies confused by conflicting straight turns with lane-changing</li>
<li>fix mac scrolling</li>
<li>better turn indicators</li>
<li>nicer unzoomed view of roads, with different colors for big/small roads</li>
</ul>
<p>0.1.5</p>
<p>(release file size jumped from ~15MB to ~70MB because of new PSRC trips)</p>
<ul>
<li>improve UX of intersection editors</li>
<li>define a better set of maps included by default</li>
<li>improve drawing speed by batching more stuff</li>
<li>better default traffic signal policies for many cases</li>
<li>import and visualize census data</li>
<li>fix missing sidewalks on downtown one-ways</li>
<li>import and visualize PSRC trip data</li>
</ul>
<p>0.1.6</p>
<ul>
<li>slider widget for controlling time and speed</li>
<li>fixing bad polyline geometry in most cases; visualizing routes should no longer be buggy</li>
<li>handle PSRC trips that begin or end out-of-bounds</li>
<li>draw agents in unzoomed mode in a way simpler way</li>
<li>improve edit mode: detect reverts to original, easier lane type switching</li>
<li>lots of fixes for buses: handle edits better, read sequence of stops correctly from GTFS</li>
<li>set up A/B tests faster</li>
</ul>
<p>0.1.7</p>
<ul>
<li>bulk and revert tools in edit mode</li>
<li>improve turns and default intersection policies when bike/bus lanes involved</li>
<li>new tool to manually hint for short roads and weird intersections. some problems have now been manually fixed</li>
<li>scoreboard of trip results for sandbox and A/B test mode</li>
<li>reduce lag when sim is running at full speeds, but system is too slow</li>
<li>switch to easbar's contraction hierarchy crate, making all pathfinding INSANELY fast</li>
<li>remove weird rules about the world freezing when traffic signals are in &quot;overtime&quot;</li>
</ul>
<p>0.1.8</p>
<ul>
<li>edit mode: convert to a ped scramble cycle, simplify stop sign editor by removing individual turns</li>
<li>ui: put labels next to sliders, organize modal menus into sections, add a minimize/maximize icon</li>
<li>A/B test mode: savestate, include time controls and agent following/route tools here</li>
<li>use more OSM data for turn lanes, turn restrictions from lanes, turn restrictions between entire roads</li>
<li>dont attempt to cross a traffic signal if there's absolutely no hope</li>
<li>improve bus route UI tools and make routes using transit more sane</li>
<li>user-defined shortcuts for jumping between views of a map</li>
</ul>
<p>0.1.9</p>
<ul>
<li>sliders to pick times in wizards</li>
<li>fix hidpi scaling</li>
<li>traffic signal diagram scrolls properly</li>
<li>easier to instantiate a scenario, show all trips involving a building for a scenario</li>
<li>colorschemes to show trip duration or time blocked</li>
<li>label buses with route number</li>
<li>represent overlapping pedestrians as a labeled crowd</li>
<li>massive performance boost via real priority queue</li>
<li>prevent cars from &quot;blocking the box&quot;</li>
<li>prevent all? aborted trips (due to parking blackholes mostly)</li>
<li>smarter roam-around-for-parking router</li>
</ul>
<p>0.1.10</p>
<ul>
<li>sim
<ul>
<li>parking in off-street garages and on-street lanes on the off-side of oneways now mostly works</li>
<li>detect and handle parking blackholes; cars should never get stuck looking for parking now</li>
<li>let lower-priority turns happen at traffic signals when higher-priority ones blocked</li>
<li>get closer to FCFS ordering at stop signs</li>
<li>basic opportunistic lane-changing</li>
<li>a bus should be seeded for every route now</li>
</ul>
</li>
<li>demand data
<ul>
<li>show trips to/from buildings and borders</li>
<li>make PSRC trips seed and attempt to use parked cars</li>
</ul>
</li>
<li>UI
<ul>
<li>different heatmap overlays, like parking availability and busiest areas</li>
<li>show colorscheme legends when relevant</li>
<li>interactively seed parked cars, spawn more types of trips</li>
<li>fix major A/B test mode bug (mismatched scenarios and map edits)</li>
<li>adjusting sliders, menu placement, dynamic items</li>
<li>consolidating different tools into a single info panel for objects</li>
<li>bus route explorer shows entire route, current bus location</li>
</ul>
</li>
<li>map quality
<ul>
<li>degenerate intersections only have one crosswalk now</li>
<li>revamped the map editor for fixing geometry problems, used it in many places</li>
<li>nicer yellow center lines (dashed when appropriate)</li>
<li>handling OSM turn restriction relations properly</li>
<li>fix empty traffic signal phases</li>
<li>handling bike lanes on certain sides of the road</li>
<li>starting to upstream manually-verified parking lanes into OSM</li>
</ul>
</li>
<li>new gameplay: reverse direction of lanes</li>
</ul>
<p>0.1.11</p>
<ul>
<li>small UI fixes: fixed width traffic signal diagram, skip info phase of menus when empty</li>
<li>start drawing (but not using) shared left-turn lanes from OSM</li>
<li>fix OSM polylines with redundant points (fixing an issue in ballard)</li>
<li>improved traffic signal policies in some cases</li>
<li>started upstreaming some sidewalk tags in OSM to fix inference issues</li>
<li>fixed misclassified right turns</li>
<li>adjusting map colors</li>
<li>handling lakes/ocean polygons from OSM way better</li>
<li>reorganized sim analytics, added stuff for bus arrivals</li>
<li>adding new internal road points to map editor. almost ready to really aggressively use it</li>
<li>skipping parking lanes with no nearby sidewalks, since they're unusable</li>
<li>fix z-order of bridges/tunnels in unzoomed view</li>
<li>allow unzooming indefinitely</li>
<li>move lots of sandbox mode controls (and other modes) to menus under buttons and dedicated buttons</li>
<li>basic support for marking a lane closed for construction</li>
<li>improved geometry of sidewalks at dead-ends</li>
</ul>
<p>0.1.12</p>
<ul>
<li>reorganize everything as different challenge modes. start implementing 3: optimizing a bus route, speeding up all trips, or causing as much gridlock as possible</li>
<li>improved bus route explorer</li>
<li>some UI fixes (popup messages in a few places, moving mouse tooltips to the OSD)</li>
<li>lots of analytics and time-series plots</li>
</ul>
<p>0.1.13</p>
<ul>
<li>analytics: prebake baseline results properly. hover over plot series. some new modes to see bus network, throughput of a road/intersection over time</li>
<li>log scale for the speed slider</li>
<li>add a bulk spawner in freeform mode (F2 on a lane)</li>
<li>rendering: nicer routes, crosswalks, zoomed car colors</li>
<li>map data: better stop sign and sidewalk heuristics</li>
<li>fixed the mac hidpi text rendering issue once and for all?!</li>
</ul>
<p>0.1.14</p>
<ul>
<li>better crosswalk generation when there's only a sidewalk on one side of a road</li>
<li>edit mode UI revamp: paintbrush-style buttons to apply changes to lanes</li>
<li>show error messages and prevent edits, like disconnecting sidewalks</li>
<li>properly ban bikes from highways (revamped rules for vehicles using a lane)</li>
<li>new freeform mode tool to spawn bikes</li>
<li>WIP (not working yet): make bikes prefer bike lanes. some debug heatmaps for path cost</li>
<li>edit mode has proper undo support</li>
</ul>
<p>0.1.15</p>
<ul>
<li>minor bugfixes with reverting lane types, preserving stop signs</li>
<li>incorporate edits into the challenge splash screen, make sure edits are reset when appropriate</li>
<li>starting a new challenge mode, just focused on traffic signals</li>
<li>can't leave traffic signal editor with missing turns</li>
<li>render pedestrian crowds on building front paths</li>
<li>traffic signals support an offset parameter</li>
<li>traffic signal visualization and editing revamped to group related turns together</li>
<li>can preview traffic using a signal from the editor</li>
<li>actually apply priority at intersections, so protected turns get first dibs over yield turns</li>
</ul>
<p>0.1.16</p>
<ul>
<li>fix Mac crashing with texture limit bug by switching to texture arrays</li>
<li>fix crashing simulation when a border intersection was used</li>
<li>started to implement a new UI design for starting the game</li>
</ul>
<p>0.1.17</p>
<ul>
<li>more work on the pre-game UI, with some flexbox layouting</li>
<li>prototype a minimap in sandbox mode. doesn't pan or scroll yet.</li>
<li>prototype a new speed/time control panel from the mockup</li>
<li>nicer time warp loading screen</li>
<li>record and show detailed trip timeline, including time to park</li>
</ul>
<p>0.1.18</p>
<ul>
<li>map data: infer more building addresses</li>
<li>some analytics on how long people spend parking and intersection delay over time</li>
<li>create an options panel, allowing runtime customization of color scheme, traffic signal rendering, etc</li>
<li>internal changes to map building pipeline to make it much easier for new devs to onboard</li>
<li>organizing challenges into sub-stages, starting to flesh out specifics for the fix traffic signal track</li>
<li>much more realistic pedestrian pathfinding</li>
<li>fix minimap on mac (dpi issues)</li>
<li>visual tweaks to cars to make front/back easier to distinguish</li>
<li>internal change to switch most assets from PNG to SVG</li>
</ul>
<p>0.1.19</p>
<ul>
<li>some challenge modes show a histogram for counting faster/slower trips</li>
<li>new visualization of current demand per direction at a traffic signal</li>
<li>implementing some of Yuwen's UI changes: agent counter, split time/speed panel, moved functionality out of the old drop-down menus into a bottom-left tool panel, hiding debug functionality</li>
<li>replaced right-click context menus with left click to open info panels</li>
<li>fixed random issues reported by people from HN</li>
</ul>
<p>0.1.20</p>
<ul>
<li>moved some UI functionality around, pulling graphs into info panel</li>
<li>interactive legend for the minimap, toggle visibility of different agents</li>
<li>nicer colors and shapes for cars</li>
<li>misc simulation bugfixes that might help huge_seattle</li>
<li>pedestrians choose to use transit more realistically, factoring in time for the bus to drive</li>
</ul>
<p>0.1.21</p>
<ul>
<li>switch some analytics dashboards to use buttons, not old non-scrolling menus</li>
<li>scrollbars... at least a start</li>
<li>preview traffic signal changes from live sim as the base</li>
<li>traffic signal preview has normal time/speed controls</li>
<li>traffic signal editor has undo support</li>
<li>minimap has buttons to pan</li>
</ul>
<p>0.1.22</p>
<ul>
<li>minimap zoom controls</li>
<li>traffic signal rendering overhaul</li>
<li>heatmap colors improved, heatmap appears on minimap</li>
<li>bus info panel, a start to live delay analytics</li>
</ul>
<p>0.1.23</p>
<ul>
<li>UI revamps: speed panel, minimap controls, heatmap chooser</li>
<li>bus timeline</li>
<li>hide internal IDs normally</li>
<li>limit map zoom</li>
<li>fix bugs with crosswalks conflicting with vehicle turns</li>
</ul>
<p>0.1.24</p>
<ul>
<li>overhaul traffic signal editor UI, and add redo support</li>
<li>update main edit mode UI, and add redo support</li>
<li>limit max unzoom</li>
<li>fix the infamous HiDPI bug once and for all; minimaps should work everywhere</li>
<li>almost bug-free support for floating, horizontally and vertically scrolling panels</li>
<li>overhaul top-center panel, rename scenarios to be less confusing</li>
<li>expose bus analytics outside of challenge mode</li>
<li>live info panel can exist during a running simulation</li>
<li>consolidated agent route/trip information into info panel</li>
</ul>
<p>0.1.25</p>
<ul>
<li>overhauled the tutorial</li>
<li>tuned top-center panel for sandbox and challenge modes</li>
<li>make bike and bus lanes more obvious</li>
<li>show map edits as an overlay anywhere</li>
<li>tune info panel contents, and show relationships between parked cars and buildings</li>
<li>fixes to traffic signal editor, like making all-walk conversion idempotent</li>
<li>nicer throughput and delay plots (sliding windows, grid lines)</li>
</ul>
<p>0.1.26</p>
<ul>
<li>tutorial improved in a few places</li>
<li>map data: thinner sidewalks, associate buildings with named amenities</li>
<li>traffic model: vehicles can spawn on all lanes from a border</li>
<li>much better gameplay speed (previously was too fast)</li>
<li>UI tuning: lane editor, minimap, signal editor, heatmap legends don't overwrite minimap</li>
<li>traffic signal challenge communicates score more clearly</li>
</ul>
<p>0.1.27</p>
<ul>
<li>edit mode revamped: click to edit stuff. no more lane paintbrushes. autosaving and save as.</li>
<li>tutorial: can quit and resume tutorial now</li>
<li>challenge picking flow simplified</li>
<li>UI: layouting fixes to full-screen / into stuff, popup menus go beneath buttons, plots improved</li>
<li>internal change to render all text using vector graphics. other than a few text layouting issues, shouldn't be noticeable, except now tooltips in plots don't get covered up</li>
<li>misc perf improvements (cache SVGs, drawing many circles for unzoomed agents, dont reload prebaked data)</li>
<li>upgraded winit, glutin, glium -- hopefully no new bugs introduced on any platforms</li>
</ul>
<p>0.1.27a</p>
<ul>
<li>patch to fix a crash with empty text dimensions on things like building info panels</li>
</ul>
<p>0.1.28</p>
<ul>
<li>all info panels revamped</li>
<li>some tutorial stages are much more clear, with an updating goal</li>
<li>traffic signal scorecard generalized to work for some tutorial too</li>
<li>adjust how selected agents look</li>
<li>X button on popup menus</li>
</ul>
<p>0.1.29</p>
<ul>
<li>new tool to convert between stop signs and traffic signals</li>
<li>lane editor easier to edit multiple lanes</li>
<li>info panels: IDs, mostly avoid horizontal scrolling, better info about trips to/from somewhere, move buttons up</li>
<li>traffic signal editor UI overhaul</li>
<li>different data in top-right agent meters panel</li>
<li>tooltips to communicate keybindings better</li>
<li>new jump-to-time panel, showing when rush hours occur</li>
<li>speed controls use more useful speeds</li>
<li>include ongoing trips in measured trip times</li>
<li>jump to next challenge after completing one</li>
<li>lots of tutorial tweaks</li>
</ul>
<p>0.1.30</p>
<ul>
<li>show additional info about traffic patterns and buggy maps</li>
<li>revamp tutorial UI to group tasks and messages better</li>
<li>handle different mode transitions when info panel open on an agent</li>
<li>select entire roads in unzoomed edit mode</li>
<li>show total time an agent has spent moving / blocked</li>
<li>use 2-phase traffic signals by default, making the 23rd map successfully complete!</li>
<li>jump-to-time now optionally points out traffic jams forming</li>
<li>challenge splash screen improved</li>
</ul>
<p>0.1.31</p>
<ul>
<li>overhauled trip timeline in agent info panels</li>
<li>overhauled traffic signal details panel and the per-lane turn explorer</li>
<li>settings page: show all options at once. add way to scale up text/UI elements for high-DPI displays, and an alternate pan/zoom control scheme</li>
<li>traffic signal edits can now be exported and used in any slice of Seattle. will be using this to hand-map many of them.</li>
<li>many small tutorial fixes</li>
</ul>
<p>0.1.32</p>
<ul>
<li>some UI work on giving focus to textboxes, improving dropdown menus</li>
<li>road/intersection plots display baseline sim data too</li>
<li>start associating people with multiple trips, exposing this a little in the UI</li>
<li>bring back elevation data, introduce a new overlay. the elevation data is still really bad.</li>
</ul>
<p>0.1.33</p>
<ul>
<li>new &quot;population&quot; overlay, showing people (not just current trips). heatmap and dot map to visualize.</li>
<li>improved the &quot;delay&quot; overlay to handle roads and intersections</li>
<li>removed the confusing and useless alternate color schemes for agents</li>
<li>initial left-hand driving side, tested in Perth, also drawing more arrows for all one-way roads</li>
<li>loads of internal GUI code refactorings, preparing for a standalone release of the library</li>
<li>fixed z-buffering and alpha values for web backend</li>
</ul>
<p>0.1.34</p>
<ul>
<li>info panels have been totally overhauled again. multiple tabs, way more clear representation of agents, trips, and people.</li>
<li>draw people inside of a building</li>
<li>applied consistent typography everywhere</li>
<li>lots of internal refactoring</li>
</ul>
<p>0.1.35</p>
<ul>
<li>more info panel work, particularly for trips and buses. change plot settings live.</li>
<li>prototype of a SEIR pandemic model based on time spent in shared spaces, by orestis</li>
<li>slight heatmap improvements, more coming</li>
<li>more typography changes</li>
<li>mouse cursor now changes for buttons and dragging!</li>
<li>overhaul minimap controls, make layers behavior zoomed in a little better</li>
<li>new speed panel and jump-to-time modal</li>
</ul>
<p>0.1.36</p>
<ul>
<li>overhauled simulation data page, with a table to find slow trips and some initial summary visualizations</li>
<li>plots can change windowing and show/hide series</li>
<li>layers: fade map to contrast more, better scales/legends</li>
<li>show relative trip times in info panels</li>
<li>tools to rewind/ffw to watch particular trips</li>
<li>refocusing efforts on challenge modes; level 1 of a new one is pretty much ready</li>
<li>some simulation fixes around parking and a corner case of cars temporarily forming a cycle</li>
<li>orestis improved the population/pandemic heatmaps</li>
</ul>
<p>0.1.37</p>
<ul>
<li>optimize commute challenge: high score, live sentiment, second stage</li>
<li>parked cars are owned by people, not buildings</li>
<li>info panel improvements for trips</li>
<li>bike layer suggests places where bike lanes could be helpful</li>
<li>many improvements to scatter plot</li>
<li>a new histogram-ish thing for understanding faster/slower trips</li>
<li>handling scenarios longer than 24 hours better (for pandemic model)</li>
<li>prototype of commute visualization, grouping buildings by blocks</li>
<li>sim bugfixes: crosswalk / vehicle turn conflicts, start bikes in bike lanes from borders</li>
</ul>
<p>0.1.38</p>
<ul>
<li>major internal changes to ensure people's schedules don't have impossible gaps, to associate fixed bikes/cars to a eprson, handle delayed starts to trips</li>
<li>parking changes: show path to closest free spot, utilization of a lane over time, every building includes at least 1 offstreet spot by default</li>
<li>progress on removing unrealistic gridlock: detect turn conflict cycles and temporarily allow conflicts, trim last steps of a laggy head</li>
<li>internal sim alert system. speeds up debugging, could be used for player-facing &quot;traffic jam!&quot; alerts</li>
</ul>
<p>0.1.39</p>
<ul>
<li>switched to proper OSM-based maps; no more brittle, manual geometry fixes</li>
<li>more sorting and filtering options in trip table and parking overhead tables</li>
<li>improve offstreet parking rendering. park closer to destination buildings</li>
<li>easier process for importing new cities. introducing Los Angeles, Austin, Barranquilla.</li>
<li>new data updater tool so people can opt-in to new cities</li>
<li>many internal fixes to prevent gridlock. smarter cycle detection, manual OSM fixes and traffic signal timings</li>
</ul>
<p>0.1.40</p>
<ul>
<li>differential throughput layer to understand routing diversions</li>
<li>map edits now reference longer-lasting OSM IDs, can work cross-map</li>
<li>basemap updates: new areas for west seattle, mt baker, lots of upstreamed fixes in OSM and traffic signals, smarter border matching</li>
<li>parking: optionally filter on/off-street spots in the layer, allow disconnecting spots via edits</li>
<li>render some tunnels with lower opacity</li>
<li>new feature to change speed limits and bulk road selection tools</li>
<li>first write-up of a real use case (closing lake wash through arboretum)</li>
<li>make the traffic signal challenge act like a game, with a failure/win state and scoring</li>
</ul>
<p>0.1.40a</p>
<ul>
<li>added a mode to map parking</li>
</ul>
<p>0.1.41</p>
<ul>
<li>new parking mapper tool</li>
<li>include a one-shot .osm importer in the release</li>
<li>new layer to find different types of amenities / businesses</li>
<li>adjust traffic signal rendering style</li>
<li>bulk lane editor for changing speed limits and lane types</li>
<li>including west seattle and udistrict maps</li>
<li>include some OSM buildings that were being skipped</li>
<li>dont pause after opening something from sandbox mode</li>
<li>adjust turn signals for lane-changing cars</li>
<li>lots of fixes for monitors with different DPIs, enabled by default</li>
</ul>
<p>0.1.42</p>
<ul>
<li>many misc UI bugfixes, especially for high-DPI screens</li>
<li>managing turns across multiple nearby intersections: tool to visualize, handling multi-way OSM turn restrictions, using this to ban illegal movements at the pathfinding layer, starting a traffic signal editor variant to edit these</li>
<li>rendering improvements: unzoomed agent size, visualizing routes on trip table, transparent roads beneath bridges, draw harbor island</li>
<li>overhauled street/address finder</li>
<li>parking mapper: shortcut to open bing</li>
</ul>
<p>0.1.43</p>
<ul>
<li>new map picker!</li>
<li>UI polish: traffic signal editor, layers, bus stops, delay plots</li>
<li>generate more interesting biographies for people</li>
<li>tuned all the map boundaries</li>
<li>fleshing out lots of docs in preparation for the alpha release...</li>
</ul>
<p>0.1.44</p>
<ul>
<li>spawner UI revamped</li>
<li>model parking lots! and finally model public/private parking</li>
<li>fix up tutorial</li>
<li>starting a story map mode</li>
</ul>
<p>0.1.45</p>
<ul>
<li>overhauled challenge cutscenes and hints</li>
<li>traffic signal challenge: fix score detection, add meter, much faster startup, no reset-to-midnight required</li>
<li>layers: use gradient for a few, delay comparison, new UI for picker</li>
<li>overhauled minimap controls, should be intuitive now</li>
<li>edit mode changelist UI started</li>
</ul>
<p>0.2.0 (alpha launch)</p>
<ul>
<li>road names now shown by default, in a new style</li>
<li>all layers now use gradients and show up zoomed in. worst traffic jam layer revamped.</li>
<li>scatter and line plot improvements</li>
<li>internal UI fixes: proper word wrap</li>
<li>bugfixes for following people riding the bus</li>
<li>rainbow crosswalks in one neighborhood</li>
<li>final polishing for launch</li>
</ul>
<p>0.2.1</p>
<ul>
<li>busy week due to launch, but many new features in the pipeline</li>
<li>many bug fixes</li>
<li>edit mode: proper autosave, load proposals, jump between lane/intersection editors</li>
<li>very first steps on light rail... importing the tracks</li>
<li>starting a new traffic scenario modifier system, to repeat entire scenario or outright cancel trips for some people. many more ideas for filters and actions coming soon.</li>
<li>starting to represent private roads</li>
<li>add a very simple actuated traffic signal</li>
</ul>
<p>0.2.2</p>
<ul>
<li>the default traffic signal configuration is much smarter now, handling roads with some sidewalks missing and automatically synchronizing pairs of adjacent lights</li>
<li>much faster startup time for large maps</li>
<li>better UX for handling unsaved edits</li>
<li>access-restricted zones: changing existing zones almost completely works, except for granting new access to pedestrians</li>
<li>new sidewalk corner rendering, more rounded</li>
<li>ui style standardized for margins, padding</li>
<li>Javed got camera panning when your cursor is at the edge of the screen to work; enable it in settings</li>
<li>pulling bus stop/route info from OSM, not GTFS. steps towards light rail.</li>
<li>experimenting with controls for hiding bridges to see roads underneath; try them in dev mode (ctrl+S)</li>
<li>many bug fixes</li>
</ul>
<p>0.2.3</p>
<ul>
<li>lane geometry is dramatically fixed, especially for one-ways</li>
<li>importing lanes from OSM improved</li>
<li>UI: bulk select includes select-along-a-route, show all bus routes in the layer, unzoomed zordering for roads/intersections</li>
<li>traffic scenario modifier can now convert trip modes</li>
<li>slight progress on light rail, although the train only makes one stop</li>
<li>vehicles moving through complex intersections with multiple traffic signals will now make it through multiple lights, even if they're unsynchronized</li>
<li>new random traffic scenario generator that makes people go between houses and workplaces</li>
<li>access-restricted zones: granular editing of individual roads now mostly works</li>
<li>removing the hardcoded relative directories, which many people have been having problems with</li>
<li>many many bug fixes, and some optimizations to reduce release file size</li>
</ul>
<p>0.2.4</p>
<ul>
<li>bus/train routes overhauled; they're now one-way, regularly spawn every hour, and may begin or end at a border</li>
<li>new commute pattern explorer tool</li>
<li>new character art to give cutscenes a bit more personaliy</li>
<li>some progress on gridlocking maps, both from manual fixes and an attempt to reduce conflicts in multi-turn sequences</li>
<li>misc UI: show cars seeking parking in unzoomed mode, plot arrival rate at border intersections, consolidate bulk selection controls</li>
<li>trips modified by an experiment can now be filtered in summaries</li>
<li>buses, trains, and passengers on them are now properly distinguished in different stats</li>
<li>include krakow and berlin in release</li>
<li>buildings with holes in the middle are now rendered properly</li>
</ul>
<p>0.2.5</p>
<ul>
<li>cars pick lanes better</li>
<li>overhaul bus/stop/route info panels</li>
<li>UI: better autocomplete, commuter pattern improvements by Michael, toggles instead of checkboxes, contours for heatmaps, edit mode loader revamp</li>
<li>internal refactors: turn creation, osm tags, osm parsing</li>
<li>import living streets from OSM as restricted-access zones, and other importer tweaks for berlin, krakow, san jose, sydney</li>
</ul>
<p>0.2.6</p>
<ul>
<li>many roads without sidewalks now have a tiny shoulder lane, still enabling pedestrian movement, but with a penalty</li>
<li>bike trips will stop/start at a better position along the sidewalk now</li>
<li>support parking lanes on the off-side of a one-way</li>
<li>UI: search by building names, commuter patterns shows borders better</li>
<li>transit: make people ride off-map, spawn buses on short roads</li>
<li>internal cleanups for buttons</li>
</ul>
<p>0.2.7</p>
<ul>
<li>many intersections with on/off ramps have much better geometry</li>
<li>lane-changing banned on turn lanes</li>
<li>lots more work matching bus stops/routes to the map. some progress, also some regressions.</li>
<li>fixing spawning on tiny borders</li>
<li>bus spawn rates from GTFS for seattle. started an editor for the schedule.</li>
<li>internal ezgui refactorings</li>
</ul>
<p>0.2.8</p>
<ul>
<li>multiple traffic signals can now be synchronized and edited together</li>
<li>new dashboard for &quot;traffic signal demand&quot; over the entire day and map</li>
<li>started experimenting with controlling the headless runner via a JSON API</li>
<li>epic ezgui fix by Michael to consolidate handling of HiDPI scaling</li>
<li>got a bunch of huge cities importing and loading quickly</li>
<li>you can now save the trips you manually spawn in freeform mode, then replay them later</li>
</ul>
<p>0.2.9</p>
<ul>
<li>import Xi'an, add a Chinese font, and add a tool for that group to import their external demand data</li>
<li>control A/B Street through a graphics-less API, with a Python example</li>
<li>improve UI for per-direction traffic signal demand</li>
<li>on/off ramp geometry fixed in a few more cases</li>
<li>fix some missing parking lot aisles, handle parking lots with 0 spots, and extract parking garages from OSM</li>
<li>switch road/building language in settings, if OSM data exists</li>
<li>congestion capping prototype: declare a max number of vehicles that can pass through a zone per hour, view/edit it, and very simple implementation in the sim layer</li>
<li>add custom-drawn trips to the main scenario, for exploring new demand from a new building</li>
<li>mkirk fixed up the glow/wasm ezgui backends, letting us remove glium</li>
<li>make map edit JSON backwards compatible</li>
<li>better lane/turn markings</li>
</ul>
<p>0.2.10</p>
<ul>
<li>two-way cycletracks and arbitrary direction changes for roads</li>
<li>fix map editing for lane reversals, make edits backwards compatible, and massively speed up applying edits</li>
<li>fleshing out the headless API and tooling for controlling the simulation from any language</li>
<li>import a few more places, redo left-hand driving support so far</li>
<li>various bug/performance fixes</li>
</ul>
<p>0.2.11</p>
<ul>
<li>disabled support for editing the map without resetting the simulation. needs more work, but solid start.</li>
<li>improvements to API, activity model, congestion capping</li>
<li>small UI tweaks for parking, editing multiple signals</li>
<li>fixed last bugs for left-handed driving, should work just as well now</li>
<li>lots of graphics experiments from the hackathon, not merged yet</li>
</ul>
<h1><a class="header" href="#references" id="references">References</a></h1>
<h2><a class="header" href="#example-use-cases" id="example-use-cases">Example use cases</a></h2>
<ul>
<li><a href="https://www.reddit.com/r/SeattleWA/comments/9mtgkh/seven_places_to_add_bus_lanes_now/">https://www.reddit.com/r/SeattleWA/comments/9mtgkh/seven_places_to_add_bus_lanes_now/</a></li>
<li><a href="https://www.reddit.com/r/SeattleWA/comments/9oqkz9/how_traffic_patterns_will_change_after_seattles/">https://www.reddit.com/r/SeattleWA/comments/9oqkz9/how_traffic_patterns_will_change_after_seattles/</a></li>
<li><a href="https://www.reddit.com/r/Seattle/comments/9orqne/4_fresh_ideas_to_ease_seattles_coming_traffic/">https://www.reddit.com/r/Seattle/comments/9orqne/4_fresh_ideas_to_ease_seattles_coming_traffic/</a></li>
<li><a href="https://www.reddit.com/r/SeattleWA/comments/cr1r1l/why_the_fuck_does_the_right_lane_convert_to/">https://www.reddit.com/r/SeattleWA/comments/cr1r1l/why_the_fuck_does_the_right_lane_convert_to/</a></li>
<li><a href="https://twitter.com/transitrunner/status/1175068582142599168">https://twitter.com/transitrunner/status/1175068582142599168</a></li>
</ul>
<h2><a class="header" href="#groups-that-may-be-eventually-interested" id="groups-that-may-be-eventually-interested">Groups that may be eventually interested</a></h2>
<ul>
<li>Seattle Times Traffic Lab</li>
<li><a href="https://www.citylab.com/transportation/2018/08/is-it-time-to-rethink-what-a-bike-lane-is/568483/">https://www.citylab.com/transportation/2018/08/is-it-time-to-rethink-what-a-bike-lane-is/568483/</a></li>
<li><a href="http://openseattle.org/">http://openseattle.org/</a></li>
<li><a href="https://igniteseattle.com/">https://igniteseattle.com/</a></li>
<li><a href="http://seattlegreenways.org/">http://seattlegreenways.org/</a></li>
<li><a href="https://www.livablecities.org/">https://www.livablecities.org/</a></li>
<li><a href="https://www.reddit.com/r/openstreetmap/comments/a39uv0/ok_so/">https://www.reddit.com/r/openstreetmap/comments/a39uv0/ok_so/</a></li>
<li><a href="https://mic.comotion.uw.edu/">https://mic.comotion.uw.edu/</a></li>
<li><a href="https://www.seattleinprogress.com/">https://www.seattleinprogress.com/</a></li>
<li><a href="http://www.seattle.gov/seattle-pedestrian-advisory-board">http://www.seattle.gov/seattle-pedestrian-advisory-board</a></li>
<li>Socrata</li>
<li><a href="http://transportationcamp.org/">http://transportationcamp.org/</a></li>
<li><a href="https://www.seattle.gov/transportation/projects-and-programs/programs/neighborhood-street-fund">https://www.seattle.gov/transportation/projects-and-programs/programs/neighborhood-street-fund</a></li>
<li><a href="https://www.seattle.gov/neighborhoods/programs-and-services/your-voice-your-choice">https://www.seattle.gov/neighborhoods/programs-and-services/your-voice-your-choice</a></li>
<li><a href="https://commuteseattle.com/">https://commuteseattle.com/</a></li>
<li><a href="https://www.theurbanist.org/">https://www.theurbanist.org/</a></li>
<li><a href="https://humantransit.org/2019/03/notes-on-simcity-at-30.html">https://humantransit.org/2019/03/notes-on-simcity-at-30.html</a></li>
<li><a href="https://mynorthwest.com/category/chokepoints/">https://mynorthwest.com/category/chokepoints/</a></li>
<li><a href="https://blogs.uw.edu/ceadvice/2019/05/08/infrastructure-week-2019-welcome-uw-cee-students-and-faculty/">https://blogs.uw.edu/ceadvice/2019/05/08/infrastructure-week-2019-welcome-uw-cee-students-and-faculty/</a></li>
<li><a href="https://escience.washington.edu/dssg/">https://escience.washington.edu/dssg/</a></li>
<li>josie kresner from transport foundry</li>
<li><a href="https://www.citylab.com/transportation/2019/08/city-planning-transportation-oakland-community-engagement/596050/">https://www.citylab.com/transportation/2019/08/city-planning-transportation-oakland-community-engagement/596050/</a>
<ul>
<li>tweeting small problems -&gt; bug tracker</li>
</ul>
</li>
<li><a href="https://www.the74million.org/article/building-a-smarter-and-cheaper-school-bus-system-how-a-boston-mit-partnership-led-to-new-routes-that-are-20-more-efficient-use-400-fewer-buses-save-5-million/">https://www.the74million.org/article/building-a-smarter-and-cheaper-school-bus-system-how-a-boston-mit-partnership-led-to-new-routes-that-are-20-more-efficient-use-400-fewer-buses-save-5-million/</a></li>
<li><a href="https://www.citylab.com/perspective/2019/10/micromobility-urban-design-car-free-infrastruture-futurama/600163/">https://www.citylab.com/perspective/2019/10/micromobility-urban-design-car-free-infrastruture-futurama/600163/</a></li>
<li><a href="https://www.sanjorn.com/">https://www.sanjorn.com/</a></li>
<li><a href="https://ui.kpf.com/">https://ui.kpf.com/</a></li>
</ul>
<h2><a class="header" href="#similar-projects" id="similar-projects">Similar projects</a></h2>
<ul>
<li>Urban Footprint (<a href="https://news.ycombinator.com/item?id=17895739">https://news.ycombinator.com/item?id=17895739</a>)</li>
</ul>
<h2><a class="header" href="#seattle-specific" id="seattle-specific">Seattle-specific</a></h2>
<p>SDOT asking for feedback:</p>
<ul>
<li><a href="http://sdotblog.seattle.gov/2017/02/08/from-signals-to-signs/">http://sdotblog.seattle.gov/2017/02/08/from-signals-to-signs/</a></li>
<li><a href="https://www.seattle.gov/transportation/projects-and-programs/programs/bike-program/protected-bike-lanes/n-34th-st-mobility-improvements">https://www.seattle.gov/transportation/projects-and-programs/programs/bike-program/protected-bike-lanes/n-34th-st-mobility-improvements</a></li>
<li><a href="https://www.seattle.gov/transportation/projects-and-programs/programs/transportation-planning/north-downtown-mobility-action-plan">https://www.seattle.gov/transportation/projects-and-programs/programs/transportation-planning/north-downtown-mobility-action-plan</a></li>
<li><a href="https://www.seattlebikeblog.com/2016/12/01/check-out-seattles-12-winning-neighborhood-led-transportation-ideas/">https://www.seattlebikeblog.com/2016/12/01/check-out-seattles-12-winning-neighborhood-led-transportation-ideas/</a></li>
</ul>
<p>Seattlites with opinions and ideas:</p>
<ul>
<li>
<p><a href="http://seattlegreenways.org/">http://seattlegreenways.org/</a></p>
</li>
<li>
<p><a href="https://www.seattlebikeblog.com/2018/01/19/a-roosevelt-junior-redesigned-the-streets-around-his-high-school-and-his-plan-is-better-than-sdots/">https://www.seattlebikeblog.com/2018/01/19/a-roosevelt-junior-redesigned-the-streets-around-his-high-school-and-his-plan-is-better-than-sdots/</a></p>
</li>
<li>
<p><a href="https://www.reddit.com/r/SeattleWA/comments/5rvss5/what_changes_would_you_make_to_seattles_bus/">https://www.reddit.com/r/SeattleWA/comments/5rvss5/what_changes_would_you_make_to_seattles_bus/</a></p>
</li>
<li>
<p><a href="https://www.seattletimes.com/seattle-news/transportation/congestion-tolling-could-finally-break-seattles-working-poor-heres-a-better-idea/">https://www.seattletimes.com/seattle-news/transportation/congestion-tolling-could-finally-break-seattles-working-poor-heres-a-better-idea/</a></p>
</li>
<li>
<p><a href="https://www.reddit.com/r/SeattleWA/comments/86g3p9/id_get_back_an_hour_and_a_half_a_week/">https://www.reddit.com/r/SeattleWA/comments/86g3p9/id_get_back_an_hour_and_a_half_a_week/</a></p>
</li>
<li>
<p><a href="https://www.reddit.com/r/Seattle/comments/4z3ewl/what_are_seattles_worst_intersections/">https://www.reddit.com/r/Seattle/comments/4z3ewl/what_are_seattles_worst_intersections/</a></p>
</li>
<li>
<p><a href="https://www.reddit.com/r/SeattleWA/comments/83h4ri/the_intersection_at_john_and_broadway_desperately/">https://www.reddit.com/r/SeattleWA/comments/83h4ri/the_intersection_at_john_and_broadway_desperately/</a></p>
</li>
<li>
<p><a href="http://www.seattle.gov/transportation/sdot-document-library/citywide-plans/move-seattle">http://www.seattle.gov/transportation/sdot-document-library/citywide-plans/move-seattle</a></p>
</li>
</ul>
<h2><a class="header" href="#other-projects" id="other-projects">Other projects</a></h2>
<ul>
<li><a href="https://github.com/uwescience/TrafficCruising-DSSG2017">https://github.com/uwescience/TrafficCruising-DSSG2017</a></li>
<li><a href="http://sharedstreets.io/">http://sharedstreets.io/</a></li>
<li><a href="https://github.com/twpol/osm-tiles">https://github.com/twpol/osm-tiles</a> attempting to infer nice road geometry
too</li>
</ul>
<h2><a class="header" href="#notes-from-related-work" id="notes-from-related-work">Notes from related work</a></h2>
<h3><a class="header" href="#smarts-a-hrefhttpspeopleengunimelbeduauetanintist17pdfhttpspeopleengunimelbeduauetanintist17pdfa" id="smarts-a-hrefhttpspeopleengunimelbeduauetanintist17pdfhttpspeopleengunimelbeduauetanintist17pdfa">SMARTS (<a href="https://people.eng.unimelb.edu.au/etanin/tist17.pdf">https://people.eng.unimelb.edu.au/etanin/tist17.pdf</a>)</a></h3>
<ul>
<li>Split map into sections, simulate in parallel, load-balance</li>
<li>has an IDM equation</li>
<li>tests against real TomTom data of average speed per link</li>
</ul>
<h3><a class="header" href="#games" id="games">Games</a></h3>
<p>SimCity, Cities: Skylines
<a href="https://steamcommunity.com/sharedfiles/filedetails/?id=583429740">https://steamcommunity.com/sharedfiles/filedetails/?id=583429740</a>
<a href="https://github.com/fegennari/3DWorld">https://github.com/fegennari/3DWorld</a></p>
<h3><a class="header" href="#open-source-urban-planning" id="open-source-urban-planning">Open source urban planning</a></h3>
<p>UrbanSim</p>
<h3><a class="header" href="#proprietary" id="proprietary">Proprietary</a></h3>
<p>Sidewalk Labs Model</p>
<h3><a class="header" href="#maps-for-people" id="maps-for-people">Maps for people</a></h3>
<p><a href="https://arxiv.org/pdf/1811.01147.pdf">https://arxiv.org/pdf/1811.01147.pdf</a></p>
<h3><a class="header" href="#gammacsunceduroadnetworkwilkie_tvcgpdf" id="gammacsunceduroadnetworkwilkie_tvcgpdf">gamma.cs.unc.edu/RoadNetwork/wilkie_TVCG.pdf</a></h3>
<p>section 6.3 talks about offset polylines <a href="http://gamma.cs.unc.edu/RoadNetwork">http://gamma.cs.unc.edu/RoadNetwork</a></p>
<h3><a class="header" href="#citybound" id="citybound">CityBound</a></h3>
<p><a href="https://github.com/aeickhoff/descartes">https://github.com/aeickhoff/descartes</a></p>
<h3><a class="header" href="#discrete-event-simulation-papers" id="discrete-event-simulation-papers">Discrete Event Simulation papers</a></h3>
<ul>
<li>
<p>section 5.1 of Advanced tutorial on microscopic discrete-event traffic
simulation refers to some DES systems</p>
<ul>
<li>Florian, Mahut, and Tremblay 2008</li>
<li>Sumaryo, Halim, and Ramli 2013</li>
<li>Salimifard and Ansari 2013</li>
<li>Burghout, Koutsopoulos, and Andreasson 2006</li>
<li>Thulasidasan, Kasiviswanathan, Eidenbenz, Galli, Mniszewski, and Romero 2009</li>
</ul>
</li>
<li>
<p>A Dynamic Traffic Assignment Model for Highly Congested Urban Networks</p>
<ul>
<li>section 2.2 models lanes as a moving and queueing part, references other
possibly useful papers</li>
<li>dont worry about multiple lanes for the moving part, just the turn queues at
the end</li>
</ul>
</li>
</ul>
<h2><a class="header" href="#tactical-urbanism" id="tactical-urbanism">Tactical urbanism</a></h2>
<ul>
<li><a href="https://www.vice.com/en_us/article/pajgyz/rogue-coder-turned-a-parking-spot-into-a-coworking-space">https://www.vice.com/en_us/article/pajgyz/rogue-coder-turned-a-parking-spot-into-a-coworking-space</a></li>
</ul>
<h1><a class="header" href="#collaborations" id="collaborations">Collaborations</a></h1>
<p>We're working with a few different groups on projects using A/B Street.</p>
<h2><a class="header" href="#glt" id="glt">GLT</a></h2>
<p>Active as of Sept 2020</p>
<p><a href="https://www.greenlightstrading.com">Green Lights Trading</a> is applying dynamic
congestion caps to encourage drivers to find alternate routes, not drive during
rush hour, or take public transit instead. I'm actively implementing a
proof-of-concept in A/B Street. It could also be used to explore ideas like a
downtown congestion charging zone for Seattle.</p>
<h2><a class="header" href="#xian" id="xian">Xi'an</a></h2>
<p>Active as of Sept 2020</p>
<p>A group (with their own demand data!) is studying traffic signal optimization in
Xi'an. They're using the
<a href="https://dabreegster.github.io/abstreet/dev/api.html">API</a>.</p>
<h2><a class="header" href="#forecasting-group" id="forecasting-group">Forecasting group</a></h2>
<p>Active as of Sept 2020</p>
<p>A research group is making a bunch of live map edits and scheduling new trips in
the middle of a simulation and using their system to try to predict system-wide
effects. They're also using the API.</p>
<h2><a class="header" href="#cityengine" id="cityengine">CityEngine</a></h2>
<p>Stalled as of Sept 2020</p>
<p>Edits in A/B Street could be exported to the
<a href="https://github.com/d-wasserman/shared-row/">shared-row</a> format, then rendered
in 3D using
<a href="https://github.com/d-wasserman/Complete_Street_Rule">ArcGIS CityEngine</a>. Not
blocked on us.</p>
<h2><a class="header" href="#berlin-1" id="berlin-1">Berlin</a></h2>
<p>Stalled as of Sept 2020</p>
<p>A group wants to use A/B Street for various public engagement projects in
<a href="https://github.com/dabreegster/abstreet/issues/119">Berlin</a>. Mostly blocked on
getting a reasonable travel demand model.</p>
<h2><a class="header" href="#manchester" id="manchester">Manchester</a></h2>
<p>Stalled as of Sept 2020</p>
<p>A group tentatively wants to engage the public about preventing rat runs and
making no-through-access zones in Manchester suburbs. Not really blocked on us
yet.</p>
<h2><a class="header" href="#pandemic-model" id="pandemic-model">Pandemic model</a></h2>
<p>Stalled as of Sept 2020</p>
<p>A group from the Uni of Geneva started a
<a href="https://github.com/dabreegster/abstreet/tree/master/sim/src/pandemic">COVID-19 model</a>
that figures out how long people spend in shared indoor spaces.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
</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 -->
<script type="text/javascript">
window.addEventListener('load', function() {
window.setTimeout(window.print, 100);
});
</script>
</body>
</html>