2020-08-11 00:57:11 +03:00
<!DOCTYPE HTML>
< html lang = "en" class = "sidebar-visible no-js light" >
< head >
<!-- Book generated using mdBook -->
< meta charset = "UTF-8" >
< title > Importing a new city - A/B Street< / title >
< meta content = "text/html; charset=utf-8" http-equiv = "Content-Type" >
< meta name = "description" content = "" >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
< meta name = "theme-color" content = "#ffffff" / >
< link rel = "shortcut icon" href = "../favicon.png" >
< link rel = "stylesheet" href = "../css/variables.css" >
< link rel = "stylesheet" href = "../css/general.css" >
< link rel = "stylesheet" href = "../css/chrome.css" >
< link rel = "stylesheet" href = "../css/print.css" media = "print" >
<!-- Fonts -->
< link rel = "stylesheet" href = "../FontAwesome/css/font-awesome.css" >
< link href = "https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel = "stylesheet" type = "text/css" >
< link href = "https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel = "stylesheet" type = "text/css" >
<!-- Highlight.js Stylesheets -->
< link rel = "stylesheet" href = "../highlight.css" >
< link rel = "stylesheet" href = "../tomorrow-night.css" >
< link rel = "stylesheet" href = "../ayu-highlight.css" >
<!-- Custom theme stylesheets -->
< / head >
< body >
<!-- Provide site root to javascript -->
< script type = "text/javascript" >
var path_to_root = "../";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "light" : "light";
< / script >
<!-- Work around some values being stored in localStorage wrapped in quotes -->
< script type = "text/javascript" >
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') & & theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') & & sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
< / script >
<!-- Set the theme before any content is loaded, prevents flash -->
< script type = "text/javascript" >
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('js');
< / script >
<!-- Hide / unhide sidebar before it is displayed -->
< script type = "text/javascript" >
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
< / script >
< nav id = "sidebar" class = "sidebar" aria-label = "Table of contents" >
< div class = "sidebar-scrollbox" >
2020-12-21 01:19:16 +03:00
< ol class = "chapter" > < li class = "chapter-item expanded " > < a href = "../index.html" > < strong aria-hidden = "true" > 1.< / strong > Overview< / a > < / li > < li class = "chapter-item expanded " > < a href = "../howto/index.html" > < strong aria-hidden = "true" > 2.< / strong > Instructions< / a > < / li > < li > < ol class = "section" > < li class = "chapter-item expanded " > < a href = "../howto/new_city.html" class = "active" > < strong aria-hidden = "true" > 2.1.< / strong > Importing a new city< / a > < / li > < / ol > < / li > < li class = "chapter-item expanded " > < a href = "../how_it_works.html" > < strong aria-hidden = "true" > 3.< / strong > How it works< / a > < / li > < li class = "chapter-item expanded " > < a href = "../case_studies/index.html" > < strong aria-hidden = "true" > 4.< / strong > Case studies< / a > < / li > < li > < ol class = "section" > < li class = "chapter-item expanded " > < a href = "../case_studies/lake_wash.html" > < strong aria-hidden = "true" > 4.1.< / strong > Lake Washington Blvd Stay Healthy Street< / a > < / li > < li class = "chapter-item expanded " > < a href = "../case_studies/west_seattle.html" > < strong aria-hidden = "true" > 4.2.< / strong > West Seattle mitigations< / a > < / li > < li class = "spacer" > < / li > < / ol > < / li > < li class = "chapter-item expanded " > < a href = "../dev/index.html" > < strong aria-hidden = "true" > 5.< / strong > Developer guide< / a > < / li > < li > < ol class = "section" > < li class = "chapter-item expanded " > < a href = "../dev/misc_tricks.html" > < strong aria-hidden = "true" > 5.1.< / strong > Misc developer tricks< / a > < / li > < li class = "chapter-item expanded " > < a href = "../dev/api.html" > < strong aria-hidden = "true" > 5.2.< / strong > API< / a > < / li > < li class = "chapter-item expanded " > < a href = "../dev/testing.html" > < strong aria-hidden = "true" > 5.3.< / strong > Testing< / a > < / li > < li class = "chapter-item expanded " > < a href = "../dev/mass_import.html" > < strong aria-hidden = "true" > 5.4.< / strong > Importing many maps< / a > < / li > < li class = "chapter-item expanded " > < a href = "../dev/data.html" > < strong aria-hidden = "true" > 5.5.< / strong > Data organization< / a > < / li > < / ol > < / li > < li class = "chapter-item expanded " > < a href = "../map/index.html" > < strong aria-hidden = "true" > 6.< / strong > Map model< / a > < / li > < li > < ol class = "section" > < li class = "chapter-item expanded " > < a href = "../map/details.html" > < strong aria-hidden = "true" > 6.1.< / strong > Details< / a > < / li > < li class = "chapter-item expanded " > < a href = "../map/importing/index.html" > < strong aria-hidden = "true" > 6.2.< / strong > Importing< / a > < / li > < li > < ol class = "section" > < li class = "chapter-item expanded " > < a href = "../map/importing/convert_osm.html" > < strong aria-hidden = "true" > 6.2.1.< / strong > convert_osm< / a > < / li > < li class = "chapter-item expanded " > < a href = "../map/importing/geometry.html" > < strong aria-hidden = "true" > 6.2.2.< / strong > Road/intersection geometry< / a > < / li > < li class = "chapter-item expanded " > < a href = "../map/importing/rest.html" > < strong aria-hidden = "true" > 6.2.3.< / strong > The rest< / a > < / li > < li class = "chapter-item expanded " > < a href = "../map/importing/misc.html" > < strong aria-hidden = "true" > 6.2.4.< / strong > Misc< / a > < / li > < / ol > < / li > < li class = "chapter-item expanded " > < a href = "../map/edits.html" > < strong aria-hidden = "true" > 6.3.< / strong > Live edits< / a > < / li > < li class = "chapter-item expanded " > < a href = "../map/platform.html" > < strong aria-hidden = "true" > 6.4.< / strong > Exporting< / a > < / li > < / ol > < / li > < li class = "chapter-item expanded " > < a href = "../trafficsim/index.html" > < strong aria-hidden = "true" > 7.< / strong > Traffic simulation< / a > < / li > < li > < ol class = "section" > < li class = "chapter-item expanded " > < a href = "../trafficsim/discrete_event.html" > < strong aria-hidden = "true" > 7.1.< / strong > Discrete event simulation< / a > < / li > < li class = "chapter-item expanded " > < a href = "../trafficsim/travel_demand.html" > < strong aria-hidden = "true" > 7.2.< / strong > Travel demand< / a > < / li > < li class = "chapter-item expanded " > < a href = "../trafficsim/gridlock.html" > < strong aria-hidden = "true" > 7.3.< / strong > Gridlock< / a > < / li > < li class = "chapter-item expanded " > < a href = "../trafficsim/trips.html" > < 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 = "chapter-item expanded " > < a href = "../trafficsim/parking.html" > < strong aria-hidde
2020-08-11 00:57:11 +03:00
< / div >
< div id = "sidebar-resize-handle" class = "sidebar-resize-handle" > < / div >
< / nav >
< div id = "page-wrapper" class = "page-wrapper" >
< div class = "page" >
< div id = "menu-bar-hover-placeholder" > < / div >
< div id = "menu-bar" class = "menu-bar sticky bordered" >
< div class = "left-buttons" >
< button id = "sidebar-toggle" class = "icon-button" type = "button" title = "Toggle Table of Contents" aria-label = "Toggle Table of Contents" aria-controls = "sidebar" >
< i class = "fa fa-bars" > < / i >
< / button >
< button id = "theme-toggle" class = "icon-button" type = "button" title = "Change theme" aria-label = "Change theme" aria-haspopup = "true" aria-expanded = "false" aria-controls = "theme-list" >
< i class = "fa fa-paint-brush" > < / i >
< / button >
< ul id = "theme-list" class = "theme-popup" aria-label = "Themes" role = "menu" >
< li role = "none" > < button role = "menuitem" class = "theme" id = "light" > Light (default)< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "rust" > Rust< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "coal" > Coal< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "navy" > Navy< / button > < / li >
< li role = "none" > < button role = "menuitem" class = "theme" id = "ayu" > Ayu< / button > < / li >
< / ul >
< button id = "search-toggle" class = "icon-button" type = "button" title = "Search. (Shortkey: s)" aria-label = "Toggle Searchbar" aria-expanded = "false" aria-keyshortcuts = "S" aria-controls = "searchbar" >
< i class = "fa fa-search" > < / i >
< / button >
< / div >
< h1 class = "menu-title" > A/B Street< / h1 >
< div class = "right-buttons" >
< a href = "../print.html" title = "Print this book" aria-label = "Print this book" >
< i id = "print-button" class = "fa fa-print" > < / i >
< / a >
< / div >
< / div >
< div id = "search-wrapper" class = "hidden" >
< form id = "searchbar-outer" class = "searchbar-outer" >
< input type = "search" name = "search" id = "searchbar" name = "searchbar" placeholder = "Search this book ..." aria-controls = "searchresults-outer" aria-describedby = "searchresults-header" >
< / form >
< div id = "searchresults-outer" class = "searchresults-outer hidden" >
< div id = "searchresults-header" class = "searchresults-header" > < / div >
< ul id = "searchresults" >
< / ul >
< / div >
< / div >
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
< script type = "text/javascript" >
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
< / script >
< div id = "content" class = "content" >
< main >
< h1 > < a class = "header" href = "#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 >
2020-08-30 01:37:16 +03:00
< p > This process isn't easy yet. Please email < a href = "mailto:dabreegster@gmail.com" > dabreegster@gmail.com< / a > or
2020-08-11 00:57:11 +03:00
< 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
2020-09-25 05:55:09 +03:00
< a href = "../dev/index.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 >
2020-08-11 00:57:11 +03:00
< / li >
< / ul >
2020-12-15 23:55:48 +03:00
< p > The oneshot importer will generate a new file in < code > data/system/oneshot/maps< / code >
2020-11-06 01:24:14 +03:00
that you can then load in the game. If you have an Osmosis polygon filter (see
2020-08-11 00:57:11 +03:00
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 >
2020-09-12 00:38:58 +03:00
< p > By default, driving on the right is assumed. Use < code > --oneshot_drive_on_left< / code > to
invert.< / p >
2020-08-11 00:57:11 +03:00
< 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 " export" tool on
2020-08-28 00:57:37 +03:00
< 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 > ,
2020-09-12 00:38:58 +03:00
then clip them to a smaller area. Use < a href = "http://geojson.io/" > geojson.io< / a > or
2020-09-03 01:46:11 +03:00
< a href = "https://geoman.io/geojson-editor" > geoman.io< / a > to draw a boundary around the
2020-11-14 03:49:26 +03:00
region you want to simulate and save the GeoJSON locally. Use
< code > cargo run --bin geojson_to_osmosis < boundary.geojson< / code > to convert that GeoJSON
to the
2020-09-12 00:38:58 +03:00
< a href = "https://wiki.openstreetmap.org/wiki/Osmosis/Polygon_Filter_File_Format" > Osmosis format< / a >
2020-09-03 01:46:11 +03:00
required by osmconvert.< / p >
2020-10-15 23:28:44 +03:00
< p > Note that you may hit problems if you use JOSM to download additional data to a
.osm file. Unless it updates the < code > < bounds/> < / code > element, A/B Street will clip out
anything extra. The best approach is to explicitly specify the boundary with
< code > --oneshot_clip< / code > .< / p >
2020-08-11 00:57:11 +03:00
< 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
2020-09-25 05:55:09 +03:00
< a href = "../dev/index.html#building-map-data" > the instructions< / a > . You'll need Rust,
osmconvert, gdal, etc.< / p >
2020-08-11 00:57:11 +03:00
< / li >
< li >
2020-11-06 21:31:21 +03:00
< p > Create a new directory: < code > mkdir importer/config/your_city< / code > < / p >
2020-08-11 00:57:11 +03:00
< / li >
< li >
2020-09-03 01:46:11 +03:00
< 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 >
2020-08-11 00:57:11 +03:00
< / li >
< li >
2020-11-14 03:49:26 +03:00
< p > Use < code > cargo run --bin geojson_to_osmosis < boundary.geojson< / code > to convert that
geojson to the
2020-09-12 00:38:58 +03:00
< a href = "https://wiki.openstreetmap.org/wiki/Osmosis/Polygon_Filter_File_Format" > Osmosis format< / a >
2020-11-14 03:49:26 +03:00
required by osmconvert. This tool writes one file per feature in the input,
so you'd then
< code > mv boundary0.poly importer/config/your_city/region_name.poly< / code > , repeating if
you drew multiple polygons.< / p >
2020-08-11 00:57:11 +03:00
< / li >
< li >
2020-11-06 22:15:32 +03:00
< p > Copy < code > importer/config/tel_aviv/cfg.json< / code > to
< code > importer/config/your_city/cfg.json< / code > and edit this file. See
< a href = "https://github.com/dabreegster/abstreet/blob/master/importer/src/generic.rs" > here< / a >
for details on the different fields. The defaults are a reasonable start;
the only thing you need to change is < code > osm_url< / code > .< / p >
2020-08-11 00:57:11 +03:00
< / li >
< li >
< p > Run it: < code > ./import.sh --city=your_city --raw --map< / code > < / p >
< / li >
< li >
2020-12-10 05:41:50 +03:00
< p > Update < code > .gitignore< / code > and < code > data/regen.sh< / code > , following < code > tel_aviv< / code > as an example.< / p >
2020-08-11 00:57:11 +03:00
< / li >
2020-12-15 17:22:50 +03:00
< li >
< p > Fill out < code > nice_map_name< / code > in < code > map_gui/src/tools/mod.rs< / code > .< / p >
< / li >
2020-08-11 00:57:11 +03:00
< / 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 >
2020-11-06 21:31:21 +03:00
< p > Also, you can divide the city into multiple regions, repeating step 4 and
declaring more polygon boundaries. The boundaries may overlap each other, and
they don't have to cover all of the space. Picking good boundaries may take
trial-and-error; the goal is to keep the resulting map file size small, so that
it loads quickly, while capturing all of the area needed to simulate something
interesting. This is easiest when you have some local knowledge of the area, and
at least a vague goal in mind for what you want to study.< / p >
2020-08-11 00:57:11 +03:00
< 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 >
2020-08-28 00:57:37 +03:00
< 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 >
2020-12-18 23:34:01 +03:00
< li > < a href = "../side_projects/parking_mapper.html" > Mapping parking< / a > < / li >
2020-08-11 00:57:11 +03:00
< / ul >
< / main >
< nav class = "nav-wrapper" aria-label = "Page navigation" >
<!-- Mobile navigation buttons -->
2020-12-18 23:34:01 +03:00
< a rel = "prev" href = "../howto/index.html" class = "mobile-nav-chapters previous" title = "Previous chapter" aria-label = "Previous chapter" aria-keyshortcuts = "Left" >
2020-08-11 00:57:11 +03:00
< i class = "fa fa-angle-left" > < / i >
< / a >
2020-08-26 22:53:16 +03:00
< a rel = "next" href = "../how_it_works.html" class = "mobile-nav-chapters next" title = "Next chapter" aria-label = "Next chapter" aria-keyshortcuts = "Right" >
2020-08-11 00:57:11 +03:00
< i class = "fa fa-angle-right" > < / i >
< / a >
< div style = "clear: both" > < / div >
< / nav >
< / div >
< / div >
< nav class = "nav-wide-wrapper" aria-label = "Page navigation" >
2020-12-18 23:34:01 +03:00
< a rel = "prev" href = "../howto/index.html" class = "nav-chapters previous" title = "Previous chapter" aria-label = "Previous chapter" aria-keyshortcuts = "Left" >
2020-08-11 00:57:11 +03:00
< i class = "fa fa-angle-left" > < / i >
< / a >
2020-08-26 22:53:16 +03:00
< a rel = "next" href = "../how_it_works.html" class = "nav-chapters next" title = "Next chapter" aria-label = "Next chapter" aria-keyshortcuts = "Right" >
2020-08-11 00:57:11 +03:00
< i class = "fa fa-angle-right" > < / i >
< / a >
< / nav >
< / div >
< script type = "text/javascript" >
window.playpen_copyable = true;
< / script >
< script src = "../elasticlunr.min.js" type = "text/javascript" charset = "utf-8" > < / script >
< script src = "../mark.min.js" type = "text/javascript" charset = "utf-8" > < / script >
< script src = "../searcher.js" type = "text/javascript" charset = "utf-8" > < / script >
< script src = "../clipboard.min.js" type = "text/javascript" charset = "utf-8" > < / script >
< script src = "../highlight.js" type = "text/javascript" charset = "utf-8" > < / script >
< script src = "../book.js" type = "text/javascript" charset = "utf-8" > < / script >
<!-- Custom JS scripts -->
< / body >
< / html >