Delete mdbook. It's been split out to https://github.com/a-b-street/docs
21
.github/workflows/book.yml
vendored
@ -1,5 +1,4 @@
|
||||
# From https://github.com/rust-lang/mdBook/pull/1248
|
||||
name: Book
|
||||
name: Rust docs
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
@ -12,26 +11,13 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install mdbook
|
||||
uses: peaceiris/actions-mdbook@v1
|
||||
with:
|
||||
mdbook-version: "0.3.7"
|
||||
|
||||
- name: Install Rust
|
||||
uses: hecrj/setup-rust-action@v1
|
||||
|
||||
- name: Update apt
|
||||
run: sudo apt-get update
|
||||
- name: Install plantuml and ALSA
|
||||
run: sudo apt-get install plantuml libasound2-dev
|
||||
|
||||
- name: Install mdbook-plantuml
|
||||
run: cargo install mdbook-plantuml
|
||||
|
||||
- name: Generate book from markdown
|
||||
run: |
|
||||
cd book
|
||||
mdbook build
|
||||
- name: Install ALSA
|
||||
run: sudo apt-get install libasound2-dev
|
||||
|
||||
- name: Generate rustdoc
|
||||
run: |
|
||||
@ -39,6 +25,7 @@ jobs:
|
||||
cd widgetry
|
||||
cargo doc --no-deps --document-private-items --features native-backend
|
||||
cd ..
|
||||
mkdir -p book/book
|
||||
mv target/doc book/book/rustdoc
|
||||
|
||||
- name: Publish HTML
|
||||
|
@ -23,15 +23,15 @@ pedestrians.
|
||||
|
||||
Find a problem:
|
||||
|
||||
![exploring_traffic](book/exploring_traffic.gif)
|
||||
![exploring_traffic](videos/exploring_traffic.gif)
|
||||
|
||||
Make some changes:
|
||||
|
||||
![editing_map](book/editing_map.gif)
|
||||
![editing_map](videos/editing_map.gif)
|
||||
|
||||
Measure the effects:
|
||||
|
||||
![evaluating_impacts](book/evaluating_impacts.gif)
|
||||
![evaluating_impacts](videos/evaluating_impacts.gif)
|
||||
|
||||
## Documentation
|
||||
|
||||
|
@ -1,15 +0,0 @@
|
||||
[book]
|
||||
authors = ["Dustin Carlino"]
|
||||
language = "en"
|
||||
multilingual = false
|
||||
src = "src"
|
||||
title = "A/B Street"
|
||||
|
||||
[preprocessor.plantuml]
|
||||
|
||||
[output.html]
|
||||
|
||||
# TODO: Enable linkcheck. But first, deal with email addresses
|
||||
# (https://github.com/Michael-F-Bryan/mdbook-linkcheck/issues/40) and the
|
||||
# README.md -> index.md rewriting
|
||||
#[output.linkcheck]
|
@ -1,4 +0,0 @@
|
||||
# A/B Street
|
||||
|
||||
All documentation lives here. Some chapters are only intended for a technical
|
||||
audience.
|
@ -1,53 +0,0 @@
|
||||
# Summary
|
||||
|
||||
- [Overview](README.md)
|
||||
- [Instructions](howto/README.md)
|
||||
- [Importing a new city](howto/new_city.md)
|
||||
- [How it works](how_it_works.md)
|
||||
- [Case studies](case_studies/README.md)
|
||||
- [Lake Washington Blvd Stay Healthy Street](case_studies/lake_wash.md)
|
||||
- [West Seattle mitigations](case_studies/west_seattle.md)
|
||||
|
||||
---
|
||||
|
||||
- [Developer guide](dev/README.md)
|
||||
- [Misc developer tricks](dev/misc_tricks.md)
|
||||
- [API](dev/api.md)
|
||||
- [Testing](dev/testing.md)
|
||||
- [Importing many maps](dev/mass_import.md)
|
||||
- [Data organization](dev/data.md)
|
||||
- [Map model](map/README.md)
|
||||
- [Details](map/details.md)
|
||||
- [Importing](map/importing/README.md)
|
||||
- [convert_osm](map/importing/convert_osm.md)
|
||||
- [Road/intersection geometry](map/importing/geometry.md)
|
||||
- [The rest](map/importing/rest.md)
|
||||
- [Misc](map/importing/misc.md)
|
||||
- [Live edits](map/edits.md)
|
||||
- [Exporting](map/platform.md)
|
||||
- [Traffic simulation](trafficsim/README.md)
|
||||
- [Discrete event simulation](trafficsim/discrete_event.md)
|
||||
- [Travel demand](trafficsim/travel_demand.md)
|
||||
- [Gridlock](trafficsim/gridlock.md)
|
||||
- [Multi-modal trips](trafficsim/trips.md)
|
||||
- [Live edits](trafficsim/live_edits.md)
|
||||
- [Parking](trafficsim/parking.md)
|
||||
|
||||
---
|
||||
|
||||
- [Project](project/README.md)
|
||||
- [Roadmap](project/roadmap.md)
|
||||
- [Motivations](project/motivations.md)
|
||||
- [History](project/history/README.md)
|
||||
- [Backstory](project/history/backstory.md)
|
||||
- [Year 1](project/history/year1.md)
|
||||
- [Year 2](project/history/year2.md)
|
||||
- [Year 3](project/history/year3.md)
|
||||
- [Full CHANGELOG](project/CHANGELOG.md)
|
||||
- [References](project/references.md)
|
||||
- [Collaborations](project/collaborations.md)
|
||||
- [Side projects](side_projects/README.md)
|
||||
- [15-minute Santa](side_projects/santa.md)
|
||||
- [Mapping on-street parking](side_projects/parking_mapper.md)
|
||||
- [OpenStreetMap viewer](side_projects/osm_viewer.md)
|
||||
- [15-minute neighborhoods explorer](side_projects/fifteen_min.md)
|
@ -1,54 +0,0 @@
|
||||
# Case studies
|
||||
|
||||
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.
|
||||
|
||||
In progress:
|
||||
|
||||
- [Stay Healthy Streets: Lake Washington Blvd](lake_wash.md)
|
||||
- [West Seattle mitigations](west_seattle.md)
|
||||
- Simplify where the Burke Gilman crosses Corliss and Pacific
|
||||
- No write-up yet, but the proposal is included in A/B Street
|
||||
|
||||
TODO:
|
||||
|
||||
- Close Broadway and Pine to through-traffic
|
||||
- proposed
|
||||
[here](https://old.reddit.com/r/SeattleWA/comments/gr4dsi/its_time_for_mayor_durkan_to_bring_stay_healthy/)
|
||||
- partly [happening already](https://www.openstreetmap.org/way/814244753)
|
||||
- another
|
||||
[proposal](https://twitter.com/pushtheneedle/status/1270757771802103809/photo/1)
|
||||
- Traffic signal timing at Montlake/520 and Montlake/Pacific
|
||||
- Walking around here is frustrating, and pre-COVID, vehicle traffic got
|
||||
fairly stuck
|
||||
- Pedestrianizing the Ave (u-district)
|
||||
- I can't find the proposal anymore; maybe
|
||||
[this](http://www.udistrictmobility.com/)?
|
||||
- Eastlake bike lanes / RapidRide J
|
||||
- See
|
||||
[here](https://www.seattle.gov/transportation/projects-and-programs/programs/bike-program/protected-bike-lanes/eastlake-avenue-protected-bike-lanes)
|
||||
and
|
||||
[here](http://www.seattle.gov/transportation/projects-and-programs/programs/transit-program/transit-plus-multimodal-corridor-program/rapidride-roosevelt)
|
||||
- Need to audit lanes in OSM along Eastlake
|
||||
- Especially with the Fairview Ave bridge out, detouring to the Cheshiahud
|
||||
loop isn't as useful
|
||||
- Madison / RapidRide G
|
||||
- See
|
||||
[here](http://www.seattle.gov/transportation/projects-and-programs/programs/transit-program/transit-plus-multimodal-corridor-program/madison-street-bus-rapid-transit)
|
||||
- Bus lanes on Denny
|
||||
- Proposed
|
||||
[here](https://twitter.com/transitrunner/status/1175068582142599168)
|
||||
- Bike Master Plan
|
||||
- Prototype the
|
||||
[planned network](https://www.seattle.gov/transportation/document-library/citywide-plans/modal-plans/bicycle-master-plan)
|
||||
- Downtown one-way snake
|
||||
- An old crazy idea I've always wanted to try
|
||||
- Unsorted ideas
|
||||
- [Parking](https://www.reddit.com/r/SeattleWA/comments/cr1r1l/why_the_fuck_does_the_right_lane_convert_to/)
|
||||
- [Bus lanes](https://seattletransitblog.com/2018/10/05/seven-places-to-add-bus-lanes-now/)
|
||||
- [John and Broadway](https://old.reddit.com/r/SeattleWA/comments/83h4ri/the_intersection_at_john_and_broadway_desperately/)
|
||||
- [Bad intersections](https://old.reddit.com/r/Seattle/comments/4z3ewl/what_are_seattles_worst_intersections/)
|
||||
- [Bus routes](https://old.reddit.com/r/SeattleWA/comments/5rvss5/what_changes_would_you_make_to_seattles_bus/)
|
Before Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 92 KiB |
@ -1,83 +0,0 @@
|
||||
# Lake Washington Blvd Stay Healthy Street
|
||||
|
||||
_Draft, updated May 7, 2020 by Dustin Carlino (<dabreegster@gmail.com>)_
|
||||
|
||||
In April 2020, Seattle Department of Transportation started rolling out
|
||||
[Stay Healthy Streets](https://sdotblog.seattle.gov/2020/04/16/announcing-stay-healthy-streets/),
|
||||
restricting roads to through-traffic to give people walking and biking more
|
||||
space for social distancing.
|
||||
[Seattle Neighborhood Greenways](http://seattlegreenways.org/socialdistancingstreets/)
|
||||
soon proposed extending this to a
|
||||
[130-mile network](https://drive.google.com/open?id=1HQMnagRf8EbS1nouqCMLl4LZr0QE8VrC&usp=sharing).
|
||||
|
||||
Selecting the streets requires some planning:
|
||||
|
||||
> 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.
|
||||
|
||||
I've spent the last two years building [A/B Street](https://abstreet.org),
|
||||
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!
|
||||
|
||||
> **_NOTE:_** You might want to read [how A/B Street works](../how_it_works.md)
|
||||
> first.
|
||||
|
||||
## Lake Washington Blvd
|
||||
|
||||
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.
|
||||
|
||||
![edits](edits.gif)
|
||||
|
||||
### First attempt
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/PU0iT-_3-es" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
|
||||
|
||||
Let's get started! If you want to follow along,
|
||||
[install A/B Street](../howto/index.md), 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.
|
||||
|
||||
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.
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/LSCHeDi5484" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
|
||||
|
||||
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 "compare
|
||||
before edits" 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.
|
||||
|
||||
### Traffic calming
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/qAf5IAMbpcU" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
|
||||
|
||||
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
|
||||
[traffic calming](https://streetsillustrated.seattle.gov/design-standards/trafficcalming/)
|
||||
or cheap, temporary alternatives.
|
||||
|
||||
## Next steps
|
||||
|
||||
I'm working to model "local access only" roads in A/B Street, and I'll describe
|
||||
how to measure the impact on travel times. Stay tuned to see more of the
|
||||
[proposed network](https://drive.google.com/open?id=1HQMnagRf8EbS1nouqCMLl4LZr0QE8VrC&usp=sharing)
|
||||
simulated, and get in touch if you'd like to help out!
|
@ -1,62 +0,0 @@
|
||||
# West Seattle mitigations
|
||||
|
||||
_Draft, updated June 23, 2020 by Dustin Carlino (<dabreegster@gmail.com>)_
|
||||
|
||||
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
|
||||
[requests to SDOT](https://www.westsideseattle.com/robinson-papers/2020/05/04/highland-park-action-coalition-calls-seattle-officials-traffic)
|
||||
to prepare the area for these changes.
|
||||
|
||||
This page will try to explore some of the problems and solutions from HPAC's
|
||||
document using [A/B Street](https://abstreet.org), a traffic simulator designed
|
||||
to explore the impacts of changes like this on different modes of
|
||||
transportation.
|
||||
|
||||
> **_NOTE:_** You might want to read [how A/B Street works](../how_it_works.md)
|
||||
> first.
|
||||
|
||||
## 16th Ave SW and SW Holden St
|
||||
|
||||
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:
|
||||
|
||||
![existing_diagram](existing_diagram.gif)
|
||||
|
||||
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:
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/6tooJaZLa0Q" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
|
||||
|
||||
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.
|
||||
|
||||
## Re-evaluate arterials
|
||||
|
||||
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 _throughput_ layer.
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/yzp9c7gHhOI" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
## Repair the bridge
|
||||
|
||||
Community proposals now includes a "repair the bridge" 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.
|
@ -1,222 +0,0 @@
|
||||
# Developer guide
|
||||
|
||||
## Getting started
|
||||
|
||||
You will first need:
|
||||
|
||||
- Stable Rust, at least 1.47. <https://www.rust-lang.org/tools/install>.
|
||||
- On Windows, you may need
|
||||
[Visual Studio 2019](https://visualstudio.microsoft.com/en/downloads/).
|
||||
- On Linux, `sudo apt-get install xorg-dev libxcb-shape0-dev libxcb-xfixes0-dev`
|
||||
or the equivalent for your distro
|
||||
|
||||
One-time setup:
|
||||
|
||||
1. Download the repository:
|
||||
`git clone https://github.com/dabreegster/abstreet.git`
|
||||
|
||||
2. Grab the minimal amount of data to get started: `cargo run --bin updater`
|
||||
|
||||
3. Run the game: `RUST_BACKTRACE=1 cargo run --bin game --release`. On Windows,
|
||||
set environment variables like this:
|
||||
`set RUST_BACKTRACE=1 && cargo run --bin game --release`
|
||||
|
||||
## Development tips
|
||||
|
||||
- [Generated API documentation](https://dabreegster.github.io/abstreet/rustdoc/map_model/index.html)
|
||||
- Compile faster by just doing `cargo run`. The executable will have debug stack
|
||||
traces and run more slowly. You can do `cargo run --release` to build in
|
||||
optimized release mode; compilation will be slower, but the executable much
|
||||
faster.
|
||||
- Some in-game features are turned off by default or don't have a normal menu to
|
||||
access them. The list:
|
||||
- To toggle developer mode: press **Control+S** in game, or
|
||||
`cargo run -- --dev`
|
||||
- To warp to an object by numeric ID: press **Control+j**
|
||||
- To enter debug mode with all sorts of goodies: press **Control+D**
|
||||
- You can start the game in different modes using flags:
|
||||
- `cargo run --bin game -- --dev data/system/seattle/maps/downtown.bin` starts
|
||||
on a particular map
|
||||
- `cargo run --bin game -- data/system/seattle/scenarios/downtown/weekday.bin`
|
||||
starts with a scenario (which is tied to a certain map)
|
||||
- `cargo run --bin game -- --challenge=trafficsig/tut2` starts on a particular
|
||||
challenge. See the list of aliases by passing in a bad value here.
|
||||
- `cargo run --bin game -- data/player/saves/montlake/no_edits_unnamed/00h00m20.3s.bin`
|
||||
restores an exact simulation state. Savestates are found in debug mode
|
||||
(**Control+D**) -- they're probably confusing for the normal player
|
||||
experience, so they're hidden for now.
|
||||
- `cargo run --bin game -- --tutorial=12` starts somewhere in the tutorial
|
||||
- Adding `--edits='name of edits'` starts with edits applied to the map.
|
||||
|
||||
## Downloading more cities
|
||||
|
||||
As data formats change over time, things in the `data/` directory not under
|
||||
version control will get out of date. At any time, you can run
|
||||
`cargo run --bin updater` from the main repository directory to update only the
|
||||
files that have changed.
|
||||
|
||||
You can also opt into downloading updates for more cities by editing
|
||||
`data/player/data.json`. In the main UI, there's a button to download more
|
||||
cities that will help you manage this config file.
|
||||
|
||||
## Building map data
|
||||
|
||||
You can skip this section if you're just touching code in `game`, `widgetry`,
|
||||
and `sim`.
|
||||
|
||||
To run all pieces of the importer, you'll need some extra dependencies:
|
||||
|
||||
- `osmconvert`: See <https://wiki.openstreetmap.org/wiki/Osmconvert#Download> or
|
||||
<https://github.com/interline-io/homebrew-planetutils#installation> for Mac
|
||||
- `libgdal-dev`: See <https://gdal.org> if your OS package manager doesn't have
|
||||
this. If you keep hitting linking errors, then just remove
|
||||
`--features scenarios` from `import.sh`. You won't be able to build the
|
||||
Seattle scenarios.
|
||||
- Standard Unix utilities: `curl`, `unzip`, `gunzip`
|
||||
|
||||
The first stage of the importer, `--raw`, 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 `data/config` and use the `updater` described above to grab the
|
||||
latest input.
|
||||
|
||||
Building contraction hierarchies for pathfinding occurs in the --map stage. It
|
||||
can take a few minutes for larger maps. To view occasional progress updates, you
|
||||
can run the importer with
|
||||
|
||||
RUST_LOG="fast_paths=debug/contracted node [0-9]+0000 "
|
||||
|
||||
You can rerun specific stages of the importer:
|
||||
|
||||
- If you're modifying the initial OSM data -> RawMap conversion in
|
||||
`convert_osm`, you need `./import.sh --raw --map`.
|
||||
- If you're modifying `map_model` but not the OSM -> RawMap conversion, then you
|
||||
just need `./import.sh --map`.
|
||||
- If you're modifying the demand model for Seattle, you can add `--scenario` to
|
||||
regenerate.
|
||||
- By default, all maps are regenerated. You can also specify a single map:
|
||||
`./import.sh --map downtown`.
|
||||
- By default, Seattle is assumed as the city. You have to specify otherwise:
|
||||
`./import.sh --city=los_angeles --map downtown_la`.
|
||||
|
||||
You can also make the importer [import a new city](../howto/new_city.md).
|
||||
|
||||
## Understanding stuff
|
||||
|
||||
The docs listed at <https://github.com/dabreegster/abstreet#documentation>
|
||||
explain things like map importing and how the traffic simulation works.
|
||||
|
||||
### Code organization
|
||||
|
||||
If you're going to dig into the code, it helps to know what all the crates are.
|
||||
The most interesting crates are `map_model`, `sim`, and `game`.
|
||||
|
||||
Constructing the map:
|
||||
|
||||
- `convert_osm`: extract useful data from OpenStreetMap and other data sources,
|
||||
emit intermediate map format
|
||||
- `kml`: extract shapes from KML and CSV shapefiles
|
||||
- `map_model`: the final representation of the map, also conversion from the
|
||||
intermediate map format into the final format
|
||||
- `map_editor`: GUI for modifying geometry of maps and creating maps from
|
||||
scratch. pretty abandoned as of June 2020
|
||||
- `importer`: tool to run the entire import pipeline
|
||||
- `updater`: tool to download/upload large files used in the import pipeline
|
||||
|
||||
Traffic simulation:
|
||||
|
||||
- `sim`: all of the agent-based simulation logic
|
||||
- `headless`: tool to run a simulation without any visualization
|
||||
|
||||
Graphics:
|
||||
|
||||
- `game`: the GUI and main gameplay
|
||||
- `map_gui`: common code to interact with `map_model` maps
|
||||
- `widgetry`: a GUI and 2D OpenGL rendering library, using glium + winit +
|
||||
glutin
|
||||
|
||||
Common utilities:
|
||||
|
||||
- `abstutil`: a grab-bag timing and logging utilities
|
||||
- `abstio`: Reading/writing files on native/web
|
||||
- `geom`: types for GPS and map-space points, lines, angles, polylines,
|
||||
polygons, circles, durations, speeds
|
||||
|
||||
Other:
|
||||
|
||||
- `collisions`: an experimental data format for real-world collision data
|
||||
- `traffic_seitan`: a bug-finding tool that randomly generates live map edits
|
||||
- `tests`: integration tests
|
||||
- `santa`: 15-minute Santa, an arcade game about delivering and zoning
|
||||
- `parking_mapper`: a standalone tool to help map street parking in OSM
|
||||
- `osm_viewer`: a standalone tool to render OSM in detail
|
||||
- `fifteen_min`: a standalone tool to explore 15-minute neighborhoods
|
||||
- `popdat`: use census data to produce traffic simulation input
|
||||
- `traffic_signal_data`: manual timing overrides for some traffic signals
|
||||
- `sumo`: interoperability with [SUMO](https://www.eclipse.org/sumo)
|
||||
|
||||
## Code conventions
|
||||
|
||||
All code is automatically formatted using
|
||||
<https://github.com/rust-lang/rustfmt>; please run `cargo +nightly fmt` before
|
||||
sending a PR. (You have to install the nightly toolchain just for fmt)
|
||||
|
||||
cargo fmt can't yet organize imports, but we follow a convention to minimize
|
||||
conflict with what some IDEs do. Follow existing code to group imports: std,
|
||||
external crates, other crates in the project, the current crate, then finally
|
||||
any module declarations.
|
||||
|
||||
See the [testing strategy](testing.md) page.
|
||||
|
||||
## Error handling
|
||||
|
||||
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.
|
||||
|
||||
Since almost none of the code ever needs to distinguish error cases, use
|
||||
[anyhow](https://crates.io/crates/anyhow). Most of the errors generated within
|
||||
A/B Street are just strings anyway; the `bail!` macro is a convenient way to
|
||||
return them.
|
||||
|
||||
## Logging
|
||||
|
||||
Prefer using `info!`, `warn!`, `error!`, etc from the `log` crate rather than
|
||||
`println`.
|
||||
|
||||
Adjust the log level without recompiling via the `RUST_LOG` env variable.
|
||||
|
||||
RUST_LOG=debug cargo run --bin game
|
||||
|
||||
This can be done on a per lib basis:
|
||||
|
||||
RUST_LOG=my_lib=debug cargo run --bin game
|
||||
|
||||
Or a module-by-module basis:
|
||||
|
||||
RUST_LOG=my_lib::module=debug cargo run --bin game
|
||||
|
||||
You can mix and match:
|
||||
|
||||
# error logging by default, except the foo:bar module at debug level
|
||||
# and the entire baz crate at info level
|
||||
RUST_LOG=error,foo::bar=debug,baz=info cargo run --bin game
|
||||
|
||||
For some special cases, you might want to use regex matching by specifying a
|
||||
pattern with the "/":
|
||||
|
||||
# only log once every 10k
|
||||
RUST_LOG="fast_paths=debug/contracted node [0-9]+0000 " mike import_la
|
||||
|
||||
See the [env_logger documentation](https://docs.rs/env_logger/0.8.2/env_logger/)
|
||||
for more usage examples.
|
||||
|
||||
## Profiling
|
||||
|
||||
Use <https://github.com/flamegraph-rs/flamegraph>, just running it on the
|
||||
binaries you build normally.
|
@ -1,169 +0,0 @@
|
||||
# API
|
||||
|
||||
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.
|
||||
|
||||
## Examples
|
||||
|
||||
This
|
||||
[Python example](https://github.com/dabreegster/abstreet/blob/master/headless/examples/python_client.py)
|
||||
has everything you need to get started.
|
||||
|
||||
See
|
||||
[all example code](https://github.com/dabreegster/abstreet/tree/master/headless/examples)
|
||||
-- there are different experiments in Go and Python that automate running a
|
||||
simulation, measuring some metric, and making a change to improve the metric.
|
||||
|
||||
## Control flow
|
||||
|
||||
The `headless` API server that you run contains a single map and simulation at a
|
||||
time. Even though you can theoretically have multiple clients make requests to
|
||||
it simultaneously, the server will only execute one at a time. If you're trying
|
||||
to do something other than use one script to make API calls in sequence, please
|
||||
get in touch, so we can figure out something better suited to your use case.
|
||||
|
||||
When you start the `headless` server, it always loads the `montlake` map with
|
||||
the `weekday` scenario. The only way you can change this is by calling
|
||||
`/sim/load`. For example:
|
||||
|
||||
```
|
||||
curl http://localhost:1234/sim/load -d '{ "scenario": "data/system/seattle/scenarios/downtown/monday.bin", "modifiers": [], "edits": null }' -X POST`
|
||||
```
|
||||
|
||||
You can also pass flags like `--infinite_parking` to the server to control
|
||||
[SimOptions](https://dabreegster.github.io/abstreet/rustdoc/sim/struct.SimOptions.html).
|
||||
These settings will apply for the entire lifetime of the server; you can't
|
||||
change them later.
|
||||
|
||||
## API details
|
||||
|
||||
> **Under construction**: 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.
|
||||
|
||||
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:
|
||||
|
||||
- **/sim**
|
||||
- **GET /sim/reset**: Reset all temporary map edits and the simulation state.
|
||||
The trips that will run don't change; they're determined by the scenario
|
||||
specified by the last call to `/sim/load`. If you made live map edits using
|
||||
things like `/traffic-signals/set`, they'll be reset to the `edits` from
|
||||
`/sim/load`.
|
||||
- **POST /sim/load**: Switch the scenario being simulated, and also optionally
|
||||
sets the map edits.
|
||||
- **GET /sim/get-time**: Returns the current simulation time.
|
||||
- **GET /sim/goto-time?t=06:30:00**: Simulate until 6:30 AM. If the time you
|
||||
specify is before the current time, you have to call **/sim/reset** first.
|
||||
- **POST /sim/new-person**: The POST body must be an
|
||||
[ExternalPerson](https://dabreegster.github.io/abstreet/rustdoc/sim/struct.ExternalPerson.html)
|
||||
in JSON format.
|
||||
- **/traffic-signals**
|
||||
- **GET /traffic-signals/get?id=42**: Returns the traffic signal of
|
||||
intersection #42 in JSON.
|
||||
- **POST /traffic-signals/set**: The POST body must be a
|
||||
[ControlTrafficSignal](https://dabreegster.github.io/abstreet/rustdoc/map_model/struct.ControlTrafficSignal.html)
|
||||
in JSON format.
|
||||
- **GET /traffic-signals/get-delays?id=42&t1=03:00:00&t2=03:30:00**: Returns
|
||||
the delay experienced by every agent passing through intersection #42 from
|
||||
3am to 3:30, grouped by direction of travel.
|
||||
- **GET /traffic-signals/get-cumulative-thruput?id=42**: Returns the number of
|
||||
agents passing through intersection #42 since midnight, grouped by direction
|
||||
of travel.
|
||||
- **GET /traffic-signals/get-all-current-state**: Returns the current state of
|
||||
all traffic signals, including the stage timing, waiting, and accepted
|
||||
agents.
|
||||
- **/data**
|
||||
- **GET /data/get-finished-trips**: 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 a string like "Walk" or
|
||||
"Drive". If the trip was cancelled for any reason, duration will be null.
|
||||
- **GET /data/get-agent-positions**: Returns a JSON list of all active agents.
|
||||
Vehicle type (or pedestrian), person ID, and position is included.
|
||||
- **GET /data/get-road-thruput**: Returns a JSON list of (road, agent type,
|
||||
hour since midnight, throughput for that one hour period).
|
||||
- **GET /data/get-blocked-by-graph**: Returns a mapping from agent IDs to how
|
||||
long they've been waiting and why they're blocked.
|
||||
- **GET /data/trip-time-lower-bound?id=123**: Returns a reasonable lower bound
|
||||
for the total duration of trip 123, in seconds. The time is calculated
|
||||
assuming no delay at intersections, travelling full speed along every road,
|
||||
and using the primary mode for the entire trip (so just driving).
|
||||
- **GET /data/all-trip-time-lower-bounds**: The faster equivalent of calling
|
||||
`/data/trip-time-lower-bound` for every trip in the simulation.
|
||||
- **/map**
|
||||
- **GET /map/get-edits**: Returns the current map edits in JSON. You can save
|
||||
this to a file in `data/player/edits/city_name/map_name/` and later use it
|
||||
in-game normally. You can also later run the `headless` server with
|
||||
`--edits=name_of_edits`.
|
||||
- **GET /map/get-edit-road-command?id=123**: Returns an object that can be
|
||||
modified and then added to map edits.
|
||||
- **GET /map/get-intersection-geometry?id=123**: Returns a GeoJSON object with
|
||||
one feature for the intersection and a feature for all connecting roads. The
|
||||
polygon coordinates are measured in meters, with the origin centered at the
|
||||
intersection's center.
|
||||
- **GET /map/get-all-geometry**: Returns a huge GeoJSON object with one
|
||||
feature per road and intersection in the map. The coordinate space is WGS84.
|
||||
|
||||
## Working with the map model
|
||||
|
||||
If you need to deeply inspect the map, you can dump it to JSON:
|
||||
|
||||
```
|
||||
cargo run --bin dump_map data/system/seattle/maps/montlake.bin > montlake.json
|
||||
```
|
||||
|
||||
See some example code that
|
||||
[reads this JSON and finds buildings](https://github.com/dabreegster/abstreet/blob/master/headless/examples/generate_traffic.py).
|
||||
|
||||
You could also edit the map JSON, convert it back to binary, and use it in the
|
||||
simulation. This isn't recommended generally, but one possible use case could be
|
||||
tuning the amount of offstreet parking per building. The map JSON has a list
|
||||
called `buildings`, and each object there has a field `parking`. You coud set
|
||||
this object to `{ "Private": [100, false] }` to indicate 100 parking spots, for
|
||||
a building not explicitly designated in OpenStreetMap as a garage. After editing
|
||||
the JSON, you have to convert it back to the binary format:
|
||||
|
||||
```
|
||||
cargo run --bin json_to_binary_map -- --input=montlake.json out=data/system/seattle/maps/montlake_modified.bin`
|
||||
```
|
||||
|
||||
The format of the map isn't well-documented yet. See the
|
||||
[generated API docs](https://dabreegster.github.io/abstreet/rustdoc/map_model/index.html)
|
||||
and [the map model docs](../map/index.md) in the meantime.
|
||||
|
||||
## Working with individual trips
|
||||
|
||||
You can use the **/sim/new-person** API in the middle of a simulation, if
|
||||
needed. If possible, it's simpler to create a Scenario as input.
|
||||
|
||||
## Working with Scenarios
|
||||
|
||||
You can
|
||||
[import trips from your own data](../trafficsim/travel_demand.md#custom-import).
|
||||
|
||||
You can also generate different variations of one of the
|
||||
[demand models](../trafficsim/travel_demand.md#proletariat-robot) by specifying
|
||||
an RNG seed:
|
||||
|
||||
```
|
||||
cargo run --bin random_scenario -- --rng=123 --map=data/system/seattle/maps/montlake.bin --scenario_name=home_to_work
|
||||
```
|
||||
|
||||
You can also dump Scenarios (the file that defines all of the people and trips)
|
||||
to JSON:
|
||||
|
||||
```
|
||||
cargo run --bin dump_scenario data/system/seattle/scenarios/montlake/weekday.bin > montlake_weekday.json
|
||||
```
|
||||
|
||||
You can modify the JSON, then put the file back in the appropriate directory and
|
||||
use it in-game:
|
||||
|
||||
```
|
||||
cargo run --bin game data/system/seattle/scenarios/montlake/modified_scenario.json
|
||||
```
|
||||
|
||||
The Scenario format is also undocumented, but see the
|
||||
[generated API docs](https://dabreegster.github.io/abstreet/rustdoc/sim/struct.Scenario.html)
|
||||
anyway.
|
@ -1,87 +0,0 @@
|
||||
# Data organization
|
||||
|
||||
A/B Street includes lots of large binary files to represent converted maps,
|
||||
scenarios, and prebaked simulation results. The files are too large to store in
|
||||
git, but the files are still logically tied to a version of the code, since the
|
||||
format sometimes changes. Additionally, all of the files are too large to
|
||||
include in the .zip release that most people use, but it should still be
|
||||
possible for players to download the optional content. Also, there are different
|
||||
versions of the game floating around, on native and web, that have to be
|
||||
associated with the proper version of these files.
|
||||
|
||||
It's all slightly confusing, so this page describes how it all works.
|
||||
|
||||
## The data itself
|
||||
|
||||
If you peek into the `data/` directory, it's mainly split into 3 subdirectories.
|
||||
`system/` is used when running the game and is the subject of this page.
|
||||
`input/` is used to store input and intermediate files for importing maps, and
|
||||
only developers running the importer should care about it. `player/` contains
|
||||
local settings, map edits, and other data created in-game.
|
||||
|
||||
`data/MANIFEST.json` is a listing of all files in `data/system/`, along with
|
||||
their size and md5sum. Different tools compare this manifest to the local
|
||||
filesystem to figure out what to do.
|
||||
|
||||
There are also some other scripts and files in `data/`, but they should probably
|
||||
be moved.
|
||||
|
||||
## Where the data is stored
|
||||
|
||||
`data/system/` and `data/input/` are stored in Amazon S3, at
|
||||
http://abstreet.s3-website.us-east-2.amazonaws.com. This S3 bucket is organized
|
||||
into versions: `dev`, `0.2.17`, `0.2.18`, etc. `dev` represents the latest
|
||||
version of all data files. The numbered versions correspond to
|
||||
[releases](https://github.com/dabreegster/abstreet/releases) and only contain
|
||||
`data/system/`, not `data/input/`. Depending how large these directories grow
|
||||
over time, I'll commit to keeping around at least 3 of the previous numbered
|
||||
versions, but I might delete older ones after that.
|
||||
|
||||
In lieu of a proper document for the release process, the commands used to make
|
||||
a versioned copy of the data are something like:
|
||||
|
||||
```
|
||||
aws s3 cp --recursive s3://abstreet/dev/data/system s3://abstreet/0.2.17/data/system
|
||||
```
|
||||
|
||||
## Native, running from source
|
||||
|
||||
For people building the game [from source](index.md), the process to keep data
|
||||
files fresh is to `cargo run --bin updater`. This tool calculates md5sums of all
|
||||
local files, then compares it with the checked-in `data/MANIFEST.json`. Any
|
||||
difference results in a local file being deleted or a new file from S3 being
|
||||
downloaded. By editing `data/player/data.json` manually or using the UI in the
|
||||
game (found by loading a map, then choosing to download more maps), somebody can
|
||||
opt into downloading "extra/optional" cities.
|
||||
|
||||
## Native, running from a release .zip
|
||||
|
||||
When the weekly .zip binary release for Mac, Linux, and Windows is produced, the
|
||||
`game` crate is built with `--features release_s3`. When the downloader UI is
|
||||
opened in-game, this causes downloads to occur from a versioned S3 directory,
|
||||
like `0.2.17`, depending on the version string compiled into the game at that
|
||||
time. So somebody can run off the weekly release, opt into more cities, and get
|
||||
the correct version of the files, even if the format has changed in `/dev/`
|
||||
since then.
|
||||
|
||||
## Web, running locally
|
||||
|
||||
The strategy for managing files gets more interested when the game is compiled
|
||||
to WebAssembly, since browsers can't read from the local filesystem.
|
||||
`game/src/load.rs` contains some crazy tricks to instead make asynchronous HTTP
|
||||
requests through the browser. When using `game/run_web.sh`, the files are served
|
||||
through a local HTTP server and symlinked to the local copy of `data/system/`.
|
||||
|
||||
Not all files are loaded through HTTP; some are actually statically compiled
|
||||
into the `.wasm` file itself! `abstutil/src/io_web.rs` does this magic using the
|
||||
`include_dir` crate. Only a few critical large files, needed at startup, are
|
||||
included. There's an IO layer for listing and reading files that, on web, merges
|
||||
results from the bundled-in files and the remote files that're declared to exist
|
||||
in the bundled-in copy of `data/MANIFEST.json`.
|
||||
|
||||
## Web, from S3
|
||||
|
||||
Everything's the same, except building with `--features wasm_s3` causes the game
|
||||
to make HTTP requests to the S3 bucket, instead of localhost. The web version
|
||||
always pins to `/dev`, never a release version of the data, since the web client
|
||||
is always updated along with the data, for now.
|
@ -1,42 +0,0 @@
|
||||
# Mass importing many maps
|
||||
|
||||
For <https://github.com/dabreegster/abstreet/issues/326>, I'm starting to figure
|
||||
out how to import hundreds of maps into A/B Street. There are many issues with
|
||||
scaling up the number of supported maps. This document just focuses on
|
||||
importing.
|
||||
|
||||
## The current approach
|
||||
|
||||
<https://download.bbbike.org/> conveniently has 200 OSM extracts for major
|
||||
cities world-wide. The `data/bbike.sh` script downloads these. Then
|
||||
`data/mass_import.sh` attempts to import them into A/B Street.
|
||||
|
||||
The bbike extracts, however, cover huge areas surrounding major cities.
|
||||
Importing such large areas is slow, and the result is too large to work well in
|
||||
A/B Street or the OSM viewer. Ideally, we want just the area concentrated around
|
||||
the "core" of each city.
|
||||
|
||||
<https://github.com/dabreegster/abstreet/blob/master/convert_osm/src/bin/extract_cities.rs>
|
||||
transforms a huge .osm file into smaller pieces, each focusing on one city core.
|
||||
This tool looks for administrative boundary relations tagged as cities, produces
|
||||
a clipping polygon covering the city, and uses `osmconvert` to produce a smaller
|
||||
`.osm` file. The tool has two strategies for generating clipping polygons. One
|
||||
is to locate the `admin_centre` or `label` node for the region, then generate a
|
||||
circle of fixed radius around that point. Usually this node is located in the
|
||||
city core, so it works reasonably, except for "narrow" cities along a coast. The
|
||||
other strategy glues together the relation's multipolygon boundary, then
|
||||
simplifies the shape (usually with thousands of points) using a convex hull.
|
||||
This strategy tends to produce results that're too large, because city limits
|
||||
are often really huge.
|
||||
|
||||
## Problems
|
||||
|
||||
- Outside the US, administrative boundaries don't always have a "city" defined.
|
||||
In Tokyo in particular, this name isn't used. I'm not sure which boundary
|
||||
level to use yet.
|
||||
- The tool assumes driving on the right everywhere. OSM has
|
||||
<https://wiki.openstreetmap.org/wiki/Key:driving_side>, but this is usually
|
||||
tagged at the country level, which isn't included in the bbike extracts.
|
||||
- The resulting maps are all "flattened" in A/B Street's list, so you can't see
|
||||
any hierarchy of areas. Two cities with the same name from different areas
|
||||
will arbitrarily collide.
|
@ -1,137 +0,0 @@
|
||||
# Development notes
|
||||
|
||||
Find packages to upgrade: `cargo outdated -R`
|
||||
|
||||
Deal with compile tile: `cargo bloat --time`
|
||||
|
||||
Find why two binary crates aren't sharing dependencies:
|
||||
<https://old.reddit.com/r/rust/comments/cqceu4/common_crates_in_cargo_workspace_recompiled/>
|
||||
|
||||
Where's a dependency coming from? `cargo tree -i -p syn`
|
||||
|
||||
Diff screencaps: <http://www.imagemagick.org/Usage/compare/#methods>
|
||||
|
||||
Debug OpenGL calls:
|
||||
|
||||
```
|
||||
apitrace trace --api gl ../target/debug/game
|
||||
qapitrace game.trace
|
||||
apitrace dump game.trace
|
||||
```
|
||||
|
||||
Understand XML: just use firefox
|
||||
|
||||
## Building releases
|
||||
|
||||
Cross-compilation notes: <https://github.com/rust-embedded/cross> Or use
|
||||
<https://github.com/japaric/trust>
|
||||
|
||||
Initially have to:
|
||||
|
||||
```shell
|
||||
cargo install cross
|
||||
sudo apt-get install docker.io
|
||||
sudo usermod -aG docker ${USER}
|
||||
```
|
||||
|
||||
Then:
|
||||
|
||||
```
|
||||
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/seattle/maps/montlake.bin
|
||||
```
|
||||
|
||||
## Markdown
|
||||
|
||||
For formatting:
|
||||
|
||||
```
|
||||
sudo apt-get install npm
|
||||
cd ~; mkdir npm; cd npm
|
||||
npm init --yes
|
||||
npm install prettier --save-dev --save-exact
|
||||
```
|
||||
|
||||
## Videos
|
||||
|
||||
```
|
||||
# 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 "[0:v] fps=12,scale=1024:-1,split [a][b];[a] palettegen [p];[b][p] paletteuse" screencast.gif
|
||||
```
|
||||
|
||||
## Faster linking
|
||||
|
||||
```
|
||||
sudo apt-get install lld
|
||||
```
|
||||
|
||||
Stick this in ~/.cargo/config:
|
||||
|
||||
```
|
||||
[target.x86_64-unknown-linux-gnu]
|
||||
rustflags = [
|
||||
"-C", "link-arg=-fuse-ld=lld",
|
||||
]
|
||||
```
|
||||
|
||||
## git
|
||||
|
||||
Keep a fork up to date:
|
||||
|
||||
```
|
||||
# Once
|
||||
git remote add upstream https://github.com/rust-windowing/glutin/
|
||||
|
||||
git fetch upstream
|
||||
git merge upstream/master
|
||||
git diff upstream/master
|
||||
```
|
||||
|
||||
## Refactoring
|
||||
|
||||
```
|
||||
perl -pi -e 's/WrappedComposite::text_button\(ctx, (.+?), (.+?)\)/Btn::text_fg(\1).build_def\(ctx, \2\)/' `find|grep rs|xargs`
|
||||
```
|
||||
|
||||
## Stack overflow
|
||||
|
||||
rust-gdb --args ../target/release/game --dev
|
||||
|
||||
## Drawing diagrams
|
||||
|
||||
draw.io
|
||||
|
||||
## Mapping
|
||||
|
||||
xodo on Android for annotating maps in the field
|
||||
|
||||
## OSM tools
|
||||
|
||||
osmcha.org for recent changes
|
||||
|
||||
To upload diffs:
|
||||
|
||||
```
|
||||
java -jar ~/Downloads/josm-tested.jar ~/abstreet/map_editor/diff.osc
|
||||
```
|
||||
|
||||
JOSM: Press (and release T), then click to pan. Download a relevant layer,
|
||||
select the .osc, merge, then upload.
|
||||
|
||||
## Fonts
|
||||
|
||||
fontdrop.info
|
||||
|
||||
## Release checklist
|
||||
|
||||
What things are sensitive to changes in map data and simulation rules?
|
||||
|
||||
- tutorial
|
||||
- optimize commute challenges
|
||||
|
||||
What things do I always forget to test?
|
||||
|
||||
- DPI issues, use `--scale_factor`
|
@ -1,67 +0,0 @@
|
||||
# Testing strategy
|
||||
|
||||
## Unit tests
|
||||
|
||||
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
|
||||
[OSM tags translate into individual lanes](https://github.com/dabreegster/abstreet/blob/master/map_model/src/make/initial/lane_specs.rs).
|
||||
|
||||
## Screenshot diffs
|
||||
|
||||
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.
|
||||
|
||||
1. 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.
|
||||
2. They use the screen capture tool in debug mode to tile the map into 1920x960
|
||||
chunks and screengrab everything.
|
||||
3. Later, somebody regenerates the map with some possible changes.
|
||||
4. They grab screenshots again, then use `compare_screenshots.sh` to quickly
|
||||
look at the visual diff. Changes to intersection geometry, number of lanes,
|
||||
rendering, etc are all easy to spot.
|
||||
5. If this manual inspection of the diff is good, they commit the new
|
||||
screenshots as the new goldenfiles.
|
||||
|
||||
## data/regen.sh
|
||||
|
||||
This tool regenerates all maps and scenarios from scratch.
|
||||
`cargo run --bin updater -- --dry` then reveals what files have changed.
|
||||
|
||||
Additionally, this script does a few more tests:
|
||||
|
||||
- `--prebake` runs the full weekday scenario on two maps that've previously been
|
||||
coerced into being gridlock-free
|
||||
|
||||
## Integration tests
|
||||
|
||||
The `tests` crate contains some integration tests.
|
||||
|
||||
One part runs the full importer against really simple `.osm` files. To iterate
|
||||
rapidly on interpreting turn restrictions, it produces goldenfiles describing
|
||||
all turns in the tiny map.
|
||||
|
||||
The "smoke-test" section simulates one hour on all maps, flushing out bugs with
|
||||
bus spawning, agents hitting odd parts of the map, etc
|
||||
|
||||
The "check proposals" section makes sure the edits shipped with the game still
|
||||
load properly.
|
||||
|
||||
## Old tests
|
||||
|
||||
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 `sim/src/events.rs` were produced
|
||||
in the right order. The `map_editor` 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
|
||||
"house" building, but even with all of this, it was pretty hard.
|
||||
|
||||
This approach is maybe worth reviving, though.
|
@ -1,148 +0,0 @@
|
||||
# How A/B Street works
|
||||
|
||||
The overview:
|
||||
|
||||
1. A detailed map of Seattle is built from
|
||||
[OpenStreetMap (OSM)](https://www.openstreetmap.org/about)
|
||||
2. A realistic set of daily trips by car, bike, foot, and bus are simulated
|
||||
3. You make small changes to roads and intersections
|
||||
4. You explore how these changes affect the trips
|
||||
|
||||
Details below. Many limitations are mentioned; improvements are ongoing. I'll
|
||||
add pictures to explain better when I get time.
|
||||
|
||||
<!--ts-->
|
||||
|
||||
- [How A/B Street works](#how-ab-street-works)
|
||||
- [Driving](#driving)
|
||||
- [Parking](#parking)
|
||||
- [Biking](#biking)
|
||||
- [Walking](#walking)
|
||||
- [Transit](#transit)
|
||||
- [Intersections](#intersections)
|
||||
- [People and trips](#people-and-trips)
|
||||
- [Map edits](#map-edits)
|
||||
|
||||
<!-- Added by: dabreegster, at: Mon Jun 8 12:17:13 PDT 2020 -->
|
||||
|
||||
<!--te-->
|
||||
|
||||
## Driving
|
||||
|
||||
- Movement: no acceleration, go the full speed limit of the road unless there's
|
||||
a slower vehicle in front
|
||||
- Lanes
|
||||
- No over-taking or lane-changing in the middle of a road, only at
|
||||
intersections
|
||||
- Strange choice of lanes -- the least full at the time of arrival
|
||||
- Narrow two-way neighborhood roads where, in practice, only one car at a time
|
||||
can go are currently full two-way roads
|
||||
- Routing is based on fastest time assuming no traffic
|
||||
- No rerouting if the driver encounters a traffic jam
|
||||
|
||||
## Parking
|
||||
|
||||
- Types
|
||||
- On-street: parallel parking lanes from
|
||||
[GeoData blockface dataset](http://data-seattlecitygis.opendata.arcgis.com/datasets/blockface)
|
||||
and [manually mapped](side_projects/parking_mapper.md)
|
||||
- Off-street: most buildings have at least a few parking spots in a driveway
|
||||
or carport
|
||||
- Currently experimenting in the downtown map: set the number of available
|
||||
spots based on number of cars seeded at midnight
|
||||
- Parking lots: the number of spots is inferred
|
||||
- Restrictions
|
||||
- All spots are public except for the few spots associated with each building
|
||||
- No time restrictions or modeling of payment
|
||||
- How cars park
|
||||
- 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.
|
||||
- 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.
|
||||
- Some parking along the boundary of the map is "blackholed", meaning it's
|
||||
impossible to actually reach it. Nobody will use these spots.
|
||||
|
||||
## Biking
|
||||
|
||||
- Choice of lane
|
||||
- Multi-use trails like the Burke Gilman and separated cycle-tracks like the
|
||||
one along Broadway are currently missing
|
||||
- Cyclists won't use an empty parking lane
|
||||
- On roads without a bike lane, cyclists currently won't stick to the
|
||||
rightmost lane
|
||||
- No over-taking yet, so cars can get stuck behind a bike even if there's a
|
||||
passing lane
|
||||
- Elevation change isn't factored into route choice or speed yet; pretend
|
||||
everybody has an e-bike
|
||||
- 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.
|
||||
|
||||
## Walking
|
||||
|
||||
- Not using sidewalk and crosswalk data from OSM yet
|
||||
- No jay-walking, even on empty residential streets
|
||||
- Pedestrians can't use roads without sidewalks at all
|
||||
- When a road only has a sidewalk on one side, driveways will cross the road
|
||||
- Pedestrians can "ghost" through each other; crowds of people can grow to any
|
||||
size
|
||||
|
||||
## Transit
|
||||
|
||||
- The modeling of buses is extremely simple and buggy; I'll work on this soon
|
||||
- No light rail yet
|
||||
|
||||
## Intersections
|
||||
|
||||
- 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
|
||||
- Most of the time, vehicles won't "block the box" -- if there's no room in the
|
||||
target lane, a vehicle won't start turning and risk getting stuck in the
|
||||
intersection
|
||||
- Traffic signals
|
||||
- Only fixed timers; no actuated signals or
|
||||
[centralized control](https://www.seattle.gov/transportation/projects-and-programs/programs/technology-program/mercer-scoot)
|
||||
yet
|
||||
- The timing and stages are automatically guessed, except some intersections
|
||||
are
|
||||
[manually mapped](https://docs.google.com/document/d/1Od_7WvBVYsvpY4etRI0sKmYmZnwXMAXcJxVmm8Iwdcg/edit?usp=sharing)
|
||||
- No pedestrian beg buttons; walk signals always come on
|
||||
- The signal doesn't change for rush hour or weekday/weekend traffic; there's
|
||||
one pattern all day
|
||||
- Turn restrictions from OSM are applied
|
||||
- Per lane (left turn only from leftmost lane), entire roads, multiple
|
||||
intersections
|
||||
|
||||
## People and trips
|
||||
|
||||
- A "synthetic population" of ~700,000 people come from
|
||||
[PSRC's Soundcast model](https://www.psrc.org/activity-based-travel-model-soundcast)
|
||||
- Soundcast uses census, land-use, vehicle counts, and commuter surveys. The
|
||||
current data is from 2014.
|
||||
- All driving trips are currently single-occupancy; no car-pooling or
|
||||
ridesharing
|
||||
- Parked cars are initially placed at midnight based on the number of trips
|
||||
between buildings
|
||||
- Each person's schedule never changes
|
||||
- Your changes to the map won't yet convince somebody to take a bus or walk
|
||||
instead of drive
|
||||
|
||||
## Map edits
|
||||
|
||||
- Types of edits
|
||||
- Change types of lanes. Sometimes this is unrealistic based on actual road
|
||||
width, but data for this is unavailable.
|
||||
- Reversing direction of lanes
|
||||
- Changing stop signs
|
||||
- Changing traffic signal timing
|
||||
- Closing roads and intersections for construction, forcing rerouting
|
||||
- Disconnecting the map
|
||||
- Generally you can't close sidewalks or make changes to make buildings
|
||||
unreachable
|
||||
- You shouldn't be able to make bus stops unreachable, but currently this is
|
||||
buggy
|
@ -1,77 +0,0 @@
|
||||
# A/B Street Instructions
|
||||
|
||||
This is an alpha-quality demo. Please email <dabreegster@gmail.com> or
|
||||
[file a Github issue](https://github.com/dabreegster/abstreet/issues/) if you
|
||||
hit problems.
|
||||
|
||||
## Installing the game
|
||||
|
||||
Grab a pre-built binary release -- updated every Sunday, announced at
|
||||
[r/abstreet](http://old.reddit.com/r/abstreet):
|
||||
|
||||
- [Windows](https://github.com/dabreegster/abstreet/releases/download/v0.2.29/abstreet_windows_v0_2_29.zip)
|
||||
- Unzip the folder, then run `play_abstreet.bat`. You'll probably getting a
|
||||
warning about running software from an unknown publisher.
|
||||
- [Mac](https://github.com/dabreegster/abstreet/releases/download/v0.2.29/abstreet_mac_v0_2_29.zip)
|
||||
- Unzip the directory, then run `play_abstreet.sh`.
|
||||
- If you get an error about the developer unverified,
|
||||
[follow this](https://support.apple.com/guide/mac-help/open-a-mac-app-from-an-unidentified-developer-mh40616/mac).
|
||||
Help needed to start
|
||||
[signing the release](https://github.com/dabreegster/abstreet/issues/107)!
|
||||
- If that just opens a text file instead of running the game, then instead
|
||||
open terminal, `cd` to the directory you just unzipped. Then do:
|
||||
`cd game; RUST_BACKTRACE=1 ./game 1> ../output.txt 2>&1`
|
||||
- [Help needed](https://github.com/dabreegster/abstreet/issues/77) to package
|
||||
this as a Mac .app, to make this process simpler
|
||||
- [Linux](https://github.com/dabreegster/abstreet/releases/download/v0.2.29/abstreet_linux_v0_2_29.zip)
|
||||
- Unzip the directory, then run `play_abstreet.sh`.
|
||||
- [FreeBSD](https://www.freshports.org/games/abstreet/), thanks to
|
||||
[Yuri](https://github.com/yurivict)
|
||||
|
||||
Or you can try playing
|
||||
[directly in your web browser](http://abstreet.s3-website.us-east-2.amazonaws.com/dev/game)
|
||||
-- still experimental for now.
|
||||
|
||||
Or you can [compile from source](../dev/index.md).
|
||||
|
||||
## Playing the game
|
||||
|
||||
- Use the **tutorial** to learn the controls.
|
||||
- Play the **challenges** for directed gameplay.
|
||||
- Try out any ideas in the **sandbox**.
|
||||
|
||||
## Common issues
|
||||
|
||||
If the size of text and panels
|
||||
[seems very strange](https://github.com/dabreegster/abstreet/issues/381), you
|
||||
can try editing `play_abstreet.sh` or `play_abstreet.bat` and passing
|
||||
`--scale_factor=1` on the command line. This value is detected from your monitor
|
||||
settings, so if you have a Retina or other HiDPI display, things may be too big
|
||||
or small.
|
||||
|
||||
## Data source licensing
|
||||
|
||||
A/B Street binary releases contain pre-built maps that combine data from:
|
||||
|
||||
- OpenStreetMap (<https://www.openstreetmap.org/copyright>)
|
||||
- King County metro
|
||||
(<https://www.kingcounty.gov/depts/transportation/metro/travel-options/bus/app-center/terms-of-use.aspx>)
|
||||
- City of Seattle GIS program
|
||||
(<https://www.opendatacommons.org/licenses/pddl/1.0/>)
|
||||
- <https://github.com/seattleio/seattle-boundaries-data>
|
||||
(<https://creativecommons.org/publicdomain/zero/1.0/>)
|
||||
- Puget Sound Regional Council
|
||||
(<https://www.psrc.org/activity-based-travel-model-soundcast>)
|
||||
- USGS SRTM
|
||||
|
||||
Other binary data bundled in:
|
||||
|
||||
- Overpass font (<https://fonts.google.com/specimen/Overpass>, Open Font
|
||||
License)
|
||||
- Bungee fonts (<https://fonts.google.com/specimen/Bungee>, Open Font License)
|
||||
- Material Design icons (<https://material.io/resources/icons>, Apache license)
|
||||
- Some Graphics textures (<https://www.kenney.nl/>, CC0 1.0 Universal)
|
||||
- Snowflake SVG (<https://www.svgrepo.com/page/licensing>, CC0)
|
||||
- Music from
|
||||
[various sources](https://github.com/dabreegster/abstreet/tree/master/data/system/assets/music/sources.md)
|
||||
with Creative Commons licenses
|
@ -1,109 +0,0 @@
|
||||
# Importing a new city into A/B Street
|
||||
|
||||
This process isn't easy yet. Please email <dabreegster@gmail.com> or
|
||||
[file a Github issue](https://github.com/dabreegster/abstreet/issues/) if you
|
||||
hit problems. I'd really appreciate help and PRs to improve this.
|
||||
|
||||
## Quick start
|
||||
|
||||
Use this if you want to import a city on your computer without making it
|
||||
available to other users yet.
|
||||
|
||||
- If you're using the **binary release** and have a `.osm` file, just do:
|
||||
`./importer --oneshot=map.osm`.
|
||||
|
||||
- If you're building **from source**, do: `./import.sh --oneshot=map.osm`. If
|
||||
you can't run `import.sh`, make sure you have all
|
||||
[dependencies](../dev/index.md#building-map-data). If you're using Windows and
|
||||
the console logs appear in a new window, try running the command from
|
||||
`import.sh` directly, changing the `$@` at the end to `--oneshot=map.osm` or
|
||||
whatever arguments you're passing in.
|
||||
|
||||
The oneshot importer will generate a new file in `data/system/oneshot/maps`
|
||||
that you can then load in the game. If you have an Osmosis polygon filter (see
|
||||
below), you can also pass `--oneshot_clip=clip.poly` to improve the result. You
|
||||
should first make sure your .osm has been clipped:
|
||||
`osmconvert large_map.osm -B=clipping.poly --complete-ways -o=smaller_map.osm`.
|
||||
|
||||
By default, driving on the right is assumed. Use `--oneshot_drive_on_left` to
|
||||
invert.
|
||||
|
||||
### How to get .osm files
|
||||
|
||||
If the area is small enough, try the "export" tool on
|
||||
<https://www.openstreetmap.org>. You can download larger areas from
|
||||
<https://download.bbbike.org/> or <http://download.geofabrik.de/index.html>,
|
||||
then clip them to a smaller area. Use [geojson.io](http://geojson.io/) or
|
||||
[geoman.io](https://geoman.io/geojson-editor) to draw a boundary around the
|
||||
region you want to simulate and save the GeoJSON locally. Use
|
||||
`cargo run --bin geojson_to_osmosis < boundary.geojson` to convert that GeoJSON
|
||||
to the
|
||||
[Osmosis format](https://wiki.openstreetmap.org/wiki/Osmosis/Polygon_Filter_File_Format)
|
||||
required by osmconvert.
|
||||
|
||||
Note that you may hit problems if you use JOSM to download additional data to a
|
||||
.osm file. Unless it updates the `<bounds/>` element, A/B Street will clip out
|
||||
anything extra. The best approach is to explicitly specify the boundary with
|
||||
`--oneshot_clip`.
|
||||
|
||||
## Including the city to A/B street more permanently
|
||||
|
||||
Follow this guide to add a new city to A/B street by default so other users can
|
||||
use it as well.
|
||||
|
||||
1. Make sure you can run `import.sh` -- see
|
||||
[the instructions](../dev/index.md#building-map-data). You'll need Rust,
|
||||
osmconvert, gdal, etc.
|
||||
|
||||
2. Create a new directory: `mkdir importer/config/your_city`
|
||||
|
||||
3. Use [geojson.io](http://geojson.io/) or
|
||||
[geoman.io](https://geoman.io/geojson-editor) to draw a boundary around the
|
||||
region you want to simulate and save the geojson locally.
|
||||
|
||||
4. Use `cargo run --bin geojson_to_osmosis < boundary.geojson` to convert that
|
||||
geojson to the
|
||||
[Osmosis format](https://wiki.openstreetmap.org/wiki/Osmosis/Polygon_Filter_File_Format)
|
||||
required by osmconvert. This tool writes one file per feature in the input,
|
||||
so you'd then
|
||||
`mv boundary0.poly importer/config/your_city/region_name.poly`, repeating if
|
||||
you drew multiple polygons.
|
||||
|
||||
5. Copy `importer/config/tel_aviv/cfg.json` to
|
||||
`importer/config/your_city/cfg.json` and edit this file. See
|
||||
[here](https://github.com/dabreegster/abstreet/blob/master/importer/src/generic.rs)
|
||||
for details on the different fields. The defaults are a reasonable start;
|
||||
the only thing you need to change is `osm_url`.
|
||||
|
||||
6. Run it: `./import.sh --city=your_city --raw --map`
|
||||
|
||||
7. Update `.gitignore` and `importer/src/main.rs`, following `tel_aviv` as an example.
|
||||
|
||||
8. Fill out `nice_map_name` in `map_gui/src/tools/mod.rs`.
|
||||
|
||||
Send a PR with your changes! I'll generate everything and make it work with
|
||||
`updater`, so most people don't have to build everything from scratch.
|
||||
|
||||
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.
|
||||
|
||||
## Next steps
|
||||
|
||||
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.
|
||||
|
||||
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:
|
||||
|
||||
- <https://learnosm.org>
|
||||
- <https://wiki.openstreetmap.org/wiki/StreetComplete>
|
||||
- [Mapping parking](../side_projects/parking_mapper.md)
|
@ -1,130 +0,0 @@
|
||||
# Map model
|
||||
|
||||
A/B Street transforms OpenStreetMap (OSM) data into a detailed geometric and
|
||||
semantic representation of the world for traffic simulation. This chapter
|
||||
describes that map model, with the hopes that it'll be useful for purposes
|
||||
beyond this project.
|
||||
|
||||
## Overview
|
||||
|
||||
A `Map` covers everything inside some hand-drawn boundary, usually scoped to a
|
||||
city or a few of a city's districts. Unlike OSM, it doesn't cover the entire
|
||||
world; it only has areas specifically extracted for some purpose.
|
||||
|
||||
A map consists of many objects. Mainly, there are roads, broken down into
|
||||
individual lanes, and intersections. A road is a single segment connecting
|
||||
exactly two intersections (as opposed to OSM, where a single "way" may span many
|
||||
intersections). Lanes within a road have a specific type, which dictates their
|
||||
direction of travel (or lack of travel, like on-street parking) and uses.
|
||||
Sidewalks are represented as bidirectional lanes. Roads connect at
|
||||
intersections, which contain an explicit set of turns, each linking a source
|
||||
lane to a destination lane.
|
||||
|
||||
Maps also contain parking lots and buildings, which connect to the nearest
|
||||
driveable lane and a sidewalk. Maps have water and park areas, only used for
|
||||
drawing. They also represent public transit stops and routes.
|
||||
|
||||
## How is a map used?
|
||||
|
||||
Unlike some GIS systems, maps don't use any kind of database -- they're just a
|
||||
file, anywhere from 1 to ~500MB (depending on the size of their boundary). Once
|
||||
loaded into memory, different objects from the map can be accessed directly,
|
||||
along with a large API to perform various queries.
|
||||
|
||||
Most of the map's API is read-only; once built, a map doesn't change until
|
||||
user-created edits are applied.
|
||||
|
||||
The pipeline to import a map from OSM data (and also optional supplementary,
|
||||
city-specific data) is complex and may take a few minutes to run, but it happens
|
||||
once offline. Applications using maps just read the final file.
|
||||
|
||||
## Features
|
||||
|
||||
Why use A/B Street's map model instead of processing OSM directly?
|
||||
|
||||
TODO: Order these better. For each one, show before/after pictures
|
||||
|
||||
### Area clipping
|
||||
|
||||
Bodies of water, forests, parks, and other areas are represented in OSM as
|
||||
relations, requiring the user to stitch together multiple polylines in undefined
|
||||
orders and handle inner holes. A/B Street maps handle all of that, and also clip
|
||||
the area's polygon to the boundary of the entire map -- including coastlines.
|
||||
|
||||
### Road and intersection geometry
|
||||
|
||||
OSM represents roads as a polyline of the physical center of the road. A/B
|
||||
Street infers the number and type of lanes from OSM metadata, then creates
|
||||
individual lanes of appropriate width, each with a center-line and polygon for
|
||||
geometry. At intersections, the roads and lanes are "trimmed back" to avoid
|
||||
overlapping, and the "common area" becomes the intersection's polygon. This
|
||||
heuristic process is reasonably robust to complex shapes, with special treatment
|
||||
of highway on/off-ramps, although it does still have some bugs.
|
||||
|
||||
### Turns
|
||||
|
||||
At each intersection, A/B Street infers all legal movements between vehicle
|
||||
lanes and sidewalks. This process makes use of OSM metadata about turn lanes,
|
||||
inferring reasonable defaults for multi-lane roads. OSM turn restriction
|
||||
relations, which may span a sequence of several roads to describe U-turns around
|
||||
complex intersections, are also used.
|
||||
|
||||
### Parking lots
|
||||
|
||||
OSM models parking lots as areas along with the driveable aisles. Usually the
|
||||
capacity of a lot isn't tagged. A/B Street automatically fills paring lots with
|
||||
individual stalls along the aisles, estimating the capacity just from this
|
||||
geometry.
|
||||
|
||||
### Stop signs
|
||||
|
||||
At unsignalized intersections, A/B Street infers which roads have to stop, and
|
||||
which have right-of-way.
|
||||
|
||||
### Traffic signals
|
||||
|
||||
OSM has no way to describe how traffic signals are configured. A/B Street models
|
||||
fixed-timer signals, automatically inferring the number of stages, their
|
||||
duration, and the movements that are prioritized and permitted during each
|
||||
stage.
|
||||
|
||||
### Pathfinding
|
||||
|
||||
A/B Street can determine routes along lanes and turns for vehicles and
|
||||
pedestrians. These routes obey OSM's turn restriction relations that span
|
||||
multiple road segments. They also avoid roads that're tagged as not allowing
|
||||
through-traffic, depending on the route's origin and destination and vehicle
|
||||
type. The pathfinding optionally makes use of contraction hierarchies to greatly
|
||||
speed up query performance, at the cost of a slower offline importing process.
|
||||
|
||||
### Bridge z-ordering
|
||||
|
||||
OSM tags bridges and tunnels, but the roads that happen to pass underneath
|
||||
bridges aren't mapped. A/B Street detects these and represents the z-order for
|
||||
drawing.
|
||||
|
||||
### Buildings
|
||||
|
||||
Similar to areas, A/B Street consolidates the geometry of OSM buildings, which
|
||||
may be split into multiple polygons. Each building is also associated with the
|
||||
nearest driveable lane and sidewalk, and metadata is used to infer a land-use
|
||||
(like residential and commercial) and commercial amenities available.
|
||||
|
||||
### Experimental: public transit
|
||||
|
||||
A/B Street uses bus stops and route relations from OSM to build a model of
|
||||
public transit routes. OSM makes few guarantees about how the specifics of the
|
||||
route are specified, but A/B Street produces specific paths, handling clipping
|
||||
to the map boundary.
|
||||
|
||||
... All of this isn't the case yet, but it's a WIP!
|
||||
|
||||
### Experimental: separated cyclepaths, tramways, and walking paths
|
||||
|
||||
Some cyclepaths, tram lines, and footpaths in OSM are tagged as separate ways,
|
||||
with no association to a "main" road. Sometimes this is true -- they're
|
||||
independent trails that only occasionally cross roads. But often they run
|
||||
alongside a road. A/B Street attempts to detect these and "snap" them to the
|
||||
main road as extra lanes.
|
||||
|
||||
... But this doesn't work yet at all.
|
@ -1,105 +0,0 @@
|
||||
# Map model details
|
||||
|
||||
A/B Street builds a rich representation of a city map using OpenStreetMap (OSM)
|
||||
and other sources. This chapter describes how.
|
||||
|
||||
TODO: Integrate pictures from
|
||||
[these slides](https://docs.google.com/presentation/d/1cF7qFtjAzkXL_r62CjxBvgQnLvuQ9I2WTE2iX_5tMCY/edit?usp=sharing).
|
||||
|
||||
[This recorded presentation](https://youtu.be/chYd5I-5oyc?t=439) covers some of
|
||||
this.
|
||||
|
||||
## The map
|
||||
|
||||
A single city is broken down into different pieces...
|
||||
|
||||
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:
|
||||
|
||||
- **Roads**: A single road connects two intersections, carrying OSM metadata and
|
||||
containing some child lanes.
|
||||
- **Lanes**: 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.
|
||||
- **Intersections**: 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.
|
||||
- **Border** intersections on the edge of the map are special places where
|
||||
agents may appear or disappear.
|
||||
- **Turns**: 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.)
|
||||
- **Buildings**: A building has a position, OSM metadata, and a **front path**
|
||||
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.
|
||||
- **Area**: An area has geometry and OSM metadata and represents a body of
|
||||
water, forest, park, etc. They're just used for drawing.
|
||||
- **Bus stop**: 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.
|
||||
- **Bus route**: 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.
|
||||
- **Parking lot**: A parking lot is connected to a road, has a shape, and has
|
||||
some internal driving "aisles." The number and position of individual parking
|
||||
spots is auto-generated.
|
||||
|
||||
## Coordinate system
|
||||
|
||||
A/B Street converts (longitude, latitude) coordinates into a simpler form.
|
||||
|
||||
- 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.
|
||||
- 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 `Pt2D` skirts around Rust's limits on f64's by
|
||||
guaranteeing no NaN's or infinities and thus providing the full `Eq` trait.
|
||||
- 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.
|
||||
|
||||
## Invariants
|
||||
|
||||
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.
|
||||
|
||||
- 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.
|
||||
- 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.
|
||||
- Additionally, parking lanes without an adjacent driving lane or bus stops
|
||||
without any driving or bus lanes make no sense and should never occur.
|
||||
- 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.
|
||||
|
||||
## Connectivity
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
There's a concept of "parking blackholes." 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<->bicycle transitions will
|
||||
happen.
|
@ -1,36 +0,0 @@
|
||||
# Live edits
|
||||
|
||||
A key feature of A/B Street is the player editing the map and seeing how traffic
|
||||
responds. The possible edits include:
|
||||
|
||||
- Change lane types (driving, bus, bike, parking -- sidewalks are fixed)
|
||||
- Change speed limits
|
||||
- Reverse a lane
|
||||
- Change a stop sign policy (which roads have a stop sign and which have
|
||||
priority)
|
||||
- Change a traffic signal policy
|
||||
|
||||
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:
|
||||
|
||||
- Figure out the actual diff between edits and the current map
|
||||
- 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.
|
||||
- For any changed roads, make sure any bus stop on it have a good pointer to
|
||||
their equivalent driving position for the bus.
|
||||
- For any modified intersections, recompute turns and the default intersection
|
||||
policies
|
||||
- Recompute all the CHs for cars, buses, and bikes -- note sidewalks and bus
|
||||
stops never change
|
||||
- This is the slowest step. Critically, the `fast_paths` crate lets a previous
|
||||
node ordering be reused. If just a few edge weights change, then recomputing
|
||||
is much faster than starting from scratch.
|
||||
- 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.
|
||||
|
||||
A list of lanes and intersections actually modified is then returned to the
|
||||
drawing layer, which uploads new geometry to the GPU accordingly.
|
@ -1,23 +0,0 @@
|
||||
# Importing
|
||||
|
||||
This chapter describes the process of transforming OSM extracts into A/B
|
||||
Street's map model. The steps are:
|
||||
|
||||
1. A large .osm file is clipped to a hand-drawn boundary region, using
|
||||
`osmconvert`
|
||||
2. The `convert_osm` crate reads the clipped `.osm`, and a bunch of optional
|
||||
supplementary files, and produces a `RawMap`
|
||||
3. Part of the `map_model` crate transforms the `RawMap` into the final `Map`
|
||||
4. Other applications read and use the `Map` file
|
||||
|
||||
The `importer` crate orchestrates these steps, along with automatically
|
||||
downloading any missing input data.
|
||||
|
||||
The rest of these sections describe each step in a bit more detail. Keeping the
|
||||
docs up-to-date is hard; the best reference is the code, which is hopefully
|
||||
organized clearly.
|
||||
|
||||
Don't be afraid of how complicated this pipeline seems -- each step is
|
||||
relatively simple. If it helps, imagine how this started -- just chop up OSM
|
||||
ways into road segments, infer lanes for each road, and infer turns between the
|
||||
lanes.
|
@ -1,43 +0,0 @@
|
||||
# From OSM to RawMap (`convert_osm` crate)
|
||||
|
||||
The first phase of map building reads in data from OSM files and a few others,
|
||||
producing a serialized `RawMap`.
|
||||
|
||||
Only major steps are described; see the code for the rest.
|
||||
|
||||
## extract.rs
|
||||
|
||||
Read .osm, extracting the points for road-like ways, buildings, and areas
|
||||
|
||||
- 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.
|
||||
- Also read traffic signal locations and turn restrictions between OSM ways
|
||||
|
||||
## split_ways.rs
|
||||
|
||||
Split OSM ways into road segments
|
||||
|
||||
- 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.
|
||||
- This phase remembers which road segment is the beginning and end of the OSM
|
||||
way, for per-lane turn restrictions later
|
||||
- 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.
|
||||
|
||||
## clip
|
||||
|
||||
Clip the map to the boundary polygon
|
||||
|
||||
- `osmconvert` options preserve ways that cross the boundary
|
||||
- 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.
|
||||
- Area polygons are intersected with the boundary polygon using the `clipping`
|
||||
crate
|
@ -1,28 +0,0 @@
|
||||
# Road/intersection geometry: RawMap to InitialMap
|
||||
|
||||
The remainder of map construction is done in the `map_model` crate. There's one
|
||||
intermediate structure between `RawMap` and `Map`, called `InitialMap`.
|
||||
|
||||
- `make/remove_disconnected.rs`: Remove disconnected roads
|
||||
- Just floodfill from some road, assuming all roads are bidirectional, to get
|
||||
different partitions.
|
||||
- Remove roads from all but the largest partition
|
||||
- `make/initial/mod.rs` and `make/initial/lane_specs.rs`: Interpret OSM tags to
|
||||
figure out what lanes are on each side of each road, also figuring out the
|
||||
total width of the road.
|
||||
- `make/initial/geometry.rs`: Figure out the polygon for each intersection, and
|
||||
trim back road center-lines to end at a face of the polygon.
|
||||
- For every road touching the intersection, get the polyline of each side,
|
||||
based on the road's width
|
||||
- See appendix for how to shift polylines
|
||||
- Sort all the polylines by the angle to the intersection's shared point
|
||||
- Intersect every polyline with every other polyline
|
||||
- More specifically -- the second half of each polyline, to get the correct
|
||||
collision point
|
||||
- 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.
|
||||
- Compute the intersection's polygon by considering collisions between
|
||||
adjacent roads' polylines
|
||||
- Deal with short roads and floating point issues by deduping any adjacent
|
||||
points closer than 0.1m
|
@ -1,39 +0,0 @@
|
||||
# Development tricks
|
||||
|
||||
- Separate phases for fast incremental development
|
||||
- Don't reimport all data from OSM every time there's a change to part of the
|
||||
map construction code!
|
||||
- For slow steps that don't change often, make them separate binaries -- hence
|
||||
`convert_osm` being separate from the rest.
|
||||
- Don't be afraid of manual intervention
|
||||
- The data isn't perfect. It's easy to spend lots of time fiddling with code
|
||||
to automatically handle all problems
|
||||
- Instead of automatically resolving problems, prefer good tooling for finding
|
||||
and specifying fixes
|
||||
- Be careful of derivative structures that could get out of sync with OSM.
|
||||
Prefer contributing real fixes to OSM.
|
||||
- Screenshot diff testing
|
||||
- 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?
|
||||
- Take screenshots of the entire map, keep the checksums under version
|
||||
control, look at the diffs visually, and manually verify any changes.
|
||||
- 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 `glium` 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!
|
||||
- Different IDs for objects make sense during different phases
|
||||
- For the final product, lanes and such are just a contiguous array, indexed
|
||||
by numeric IDs.
|
||||
- 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.
|
||||
|
||||
## Appendix: PolyLines
|
||||
|
||||
Add some pictures here to demonstrate how polyline shifting works, the
|
||||
explode-to-infinity problem, and the bevel/miter fix.
|
@ -1,117 +0,0 @@
|
||||
# InitialMap to Map
|
||||
|
||||
Still in the `map_model` crate.
|
||||
|
||||
- `map.rs`'s `make_half_map`: Expand roads to lanes, using the list of lane
|
||||
types from before
|
||||
- `make/turns.rs`: Generate turns for every intersection.
|
||||
- Vehicle turns (for cars, bikes, buses)
|
||||
- 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->bike or bike->driving. If there's not, then fallback to
|
||||
transitions between different lane types.
|
||||
- Classify the turn based on the difference between the angle of the
|
||||
incoming lane's last line and the outgoing lane's first line
|
||||
- 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 `LaneChangeLeft` or `LaneChangeRight` turn. This is used later for
|
||||
intersection policies to prioritize turns appropriately.
|
||||
- Right and left turns only originate from the one lane on the appropriate
|
||||
side
|
||||
- Walking turns for pedestrians
|
||||
- Consider pairs of adjacent roads around the intersection
|
||||
- Make a crosswalk to the other side of the road, assuming there's a
|
||||
sidewalk on both sides
|
||||
- Make a shared sidewalk corner over to the adjacent road
|
||||
- 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.
|
||||
- Verify all the turns so far are unique
|
||||
- Filter by the OSM turn restrictions ("only straight" between road1 and
|
||||
road2)
|
||||
- Try to apply the OSM per-lane restrictions ("straight or left" from lane 3)
|
||||
- The number of lanes in the OSM metadata might not match up with how many
|
||||
lanes created
|
||||
- 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.
|
||||
- `make/parking_blackholes.rs`: Find well-connected roads near "blackhole"
|
||||
lanes.
|
||||
- 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 "blackholes" -- pathfinding to or from here may fail.
|
||||
- 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.
|
||||
- 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.
|
||||
- `make/buildings.rs`: Match buildings up with sidewalks
|
||||
- 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.
|
||||
- Filter out buildings too far away from any sidewalk
|
||||
- The front path might cross through other buildings; this is probably not
|
||||
worth fixing.
|
||||
- `make/buildings.rs`: Same for parking lots
|
||||
- Similar process to match parking lots to nearest sidewalk and driving lane
|
||||
- Try to place parking spots along both sides of parking aisles
|
||||
- Filter out overlapping spots
|
||||
- `make/bridges.rs`: Find what roads lie beneath bridges, and update their
|
||||
Z-order accordingly for later drawing.
|
||||
- `stop_signs.rs`: Instantiate default stop sign policies
|
||||
- Rank incoming roads by OSM priority (arterial beats residential)
|
||||
- If there's only one rank, then make an all-way stop
|
||||
- Otherwise, the highest rank gets priority and others stop
|
||||
- Check if there are any conflicts based on this. If so, then fall-back to
|
||||
an all way stop.
|
||||
- `traffic_signals.rs`: Instantiate default traffic signal policies
|
||||
- Apply the first predefined policy that works.
|
||||
- 4-way 4 stage, 4-way 2 stage, 3-way 3-stage, degenerate policy for 2
|
||||
roads, 2-stage for 4 one-ways
|
||||
- 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.
|
||||
- `pathfind/mod.rs`: Prepare pathfinding
|
||||
- A/B Street uses contraction hierarchies (CH) for fast routing, using the
|
||||
`fast_paths` crate.
|
||||
- `pathfind/vehicle.rs`: For cars, bikes, buses
|
||||
- There's a separate CH for cars, buses, and bikes, since they can use
|
||||
slightly different sets of lanes.
|
||||
- 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.
|
||||
- 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.
|
||||
- If two lanes are connected by a turn, then there's an edge in the graph.
|
||||
- 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.
|
||||
- `pathfind/walking.rs`: For pedestrians
|
||||
- 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.
|
||||
- All turns between two sidewalks become edges, again using length
|
||||
- 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.
|
||||
- `make/bus_stops.rs`: Match bus stops with a sidewalk
|
||||
- Also precompute the position where the bus stops on the adjacent driving or
|
||||
bus lane.
|
||||
- This "equivalent position on another lane" 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.
|
||||
- `make/bus_stops.rs`: Finalize the list of bus routes
|
||||
- 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
|
||||
- Remove bus stops that have no routes serving them.
|
||||
- `pathfind/walking.rs`: Precompute the CH for pedestrians who will use buses
|
||||
- Nodes in the graph are sidewalks and every bus stop
|
||||
- There's an edge with weight 0 between a bus stop and its sidewalk
|
||||
- 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.
|
||||
- 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.
|
@ -1,121 +0,0 @@
|
||||
# A/B Street's map model as a platform
|
||||
|
||||
A/B Street's representation of a city, built mostly from OSM and lots of
|
||||
heuristics, is likely useful to other projects. This doc brainstorms what it
|
||||
would look like to properly expose it to other users.
|
||||
|
||||
To sum up what the map model provides: geometry + semantics.
|
||||
|
||||
## Use cases
|
||||
|
||||
- Different UIs (particularly 3D / VR) for exploring cities as they are or as
|
||||
they could be, like Streetmix 3D and Complete Street Rule
|
||||
- Importing slices of a city as assets into a game engine like Godot
|
||||
- Imagine a hackathon where people easily build games based on the real world
|
||||
- Like <https://developers.google.com/maps/documentation/gaming/overview_musk>
|
||||
but open
|
||||
- A new OSM viewer/editor, particularly focused on POIs
|
||||
- Something focusing on 15-minute neighborhoods, with isochrones and nearby
|
||||
amenities
|
||||
|
||||
TODO: Give a quick Python example of what interacting with the end goal could
|
||||
look like.
|
||||
|
||||
## Just data is not enough
|
||||
|
||||
At first glance, the existing `Map` structure could be written to some format
|
||||
with a nicely documented schema. This would certainly be useful, but it's not
|
||||
nearly enough. Interpreting the data sometimes requires lots of code, which
|
||||
already exists -- so why not expose it to users as well?
|
||||
|
||||
Examples in OSM where I wish "standard libraries" existed to interpret the data:
|
||||
|
||||
- The simple task of detecting intersections between ways
|
||||
- [Figuring out what lanes a road has from tags](https://github.com/dabreegster/abstreet/blob/master/map_model/src/make/initial/lane_specs.rs)
|
||||
- Gluing multipolygons together
|
||||
- Inferring turns at an intersection, subject to the several types of turn
|
||||
restrictions
|
||||
|
||||
A/B Street solves these problems (or at least it tries to), but by itself, the
|
||||
resulting data isn't always useful. So some examples of where a library would be
|
||||
needed too:
|
||||
|
||||
- Pathfinding. ABST does lots of work especially to handle "live" map edits and
|
||||
cheaply regenerate contraction hierarchies. Also, pathfinding requires obeying
|
||||
OSM turn restrictions that span multiple roads -- this prevents even plain old
|
||||
Dijkstra's from working correctly.
|
||||
- Getting geometry in different forms. Lanes are stored as a `PolyLine`, but
|
||||
what if a consumer wants the thickened `Polygon`, either as points, or maybe
|
||||
even pre-triangulated vertices and indices?
|
||||
|
||||
## How would an API/library work?
|
||||
|
||||
The traditional approach is to link against part of A/B Street as a library and
|
||||
call it through language-specific bindings. The more language-agnostic option is
|
||||
defining an API (maybe JSON or protobuf) and having clients run a local A/B
|
||||
Street server, making HTTP requests to it. This is like the "sidecar" pattern in
|
||||
microservice-land.
|
||||
|
||||
## Compatibility
|
||||
|
||||
Really have to think through this carefully. Some examples of big changes on the
|
||||
horizon:
|
||||
|
||||
- Additive: separate cycleways and tramways. Likely no schema change.
|
||||
- Modify: traffic signals will get
|
||||
[more complex](https://github.com/dabreegster/abstreet/issues/295)
|
||||
- Modify: we'll likely try again to merge tiny intersections together, which
|
||||
would get rid of the current guarantees that a road/intersection is associated
|
||||
to one particular OSM object
|
||||
|
||||
## Layering
|
||||
|
||||
Clients should be able to opt into different data layers. For example, A/B
|
||||
Street strips out OSM building tags right now to keep filesizes small. But an
|
||||
OSM viewer would want to keep this (and likely discard the large contraction
|
||||
hierarchies). So some pieces of the map model need to be teased apart into
|
||||
optional pieces, and probably loaded in as separate files.
|
||||
|
||||
## The bigger vision
|
||||
|
||||
Depending what other open source projects are on board, the general idea is to
|
||||
start assembling an ecosystem of libraries/tooling to make it easier to build
|
||||
new things off of open GIS data.
|
||||
|
||||
The end state might look like this. A few separate applications would exist, all
|
||||
running both natively and in the browser:
|
||||
|
||||
- A/B Street the game, more or less in its current form
|
||||
- A new OpenStreetMap viewer, likely focused on visualizing roads and
|
||||
points-of-interest in detail
|
||||
- The street parking OSM editor, and other OSM editors specialized for mapping
|
||||
certain things
|
||||
- A new app focusing on 15-minute neighborhoods, using isochrones to show
|
||||
amenities available nearby
|
||||
- Ideally, allow editing current land use / zoning, to let people explore how
|
||||
new policies might get closer to a 15-minute neighborhood.
|
||||
- Possibly [GOAT](https://www.open-accessibility.org) does all of this
|
||||
already, and this new thing shouldn't be built
|
||||
- A new app for creating story maps, showing events that occur over time, with
|
||||
lots of detail about the surrounding environment
|
||||
|
||||
All of these would make use of some common libraries, which should be extracted
|
||||
out cleanly from A/B Street today:
|
||||
|
||||
- the map model and OSM importer
|
||||
- the widgetry UI library
|
||||
- some common code for specifically interacting with maps in widgetry
|
||||
- a tool to generate a traffic demand model from OSM data, optional census data,
|
||||
etc
|
||||
- This has been initially
|
||||
[prototyped](https://dabreegster.github.io/abstreet/trafficsim/travel_demand.html#proletariat-robot)
|
||||
- the discrete-event traffic simulation that A/B Street uses today
|
||||
- core geometry/utility libraries
|
||||
|
||||
But note only the first application would use things like the simulation
|
||||
library. The point of more cleanly modularizing these pieces is to make it
|
||||
easier for new people to build different pieces, without having to understand
|
||||
and be coupled to everything else. Also, as appropriate, these pieces should use
|
||||
common data formats (like
|
||||
[shared-row](https://github.com/d-wasserman/shared-row/)) to be interoperable
|
||||
with Streetmix, Complete Streets, etc.
|
@ -1,735 +0,0 @@
|
||||
# CHANGELOG
|
||||
|
||||
Every time I upload a new [binary
|
||||
release](https://github.com/dabreegster/abstreet/releases), I'll list major
|
||||
changes here.
|
||||
|
||||
0.1.0
|
||||
|
||||
- First binary release
|
||||
|
||||
0.1.1
|
||||
|
||||
- drawing arrows better
|
||||
- start with a splash screen, make it easy to change maps in-game
|
||||
|
||||
0.1.2
|
||||
|
||||
- totally revamp GUI by organizing everything into distinct gameplay modes
|
||||
|
||||
0.1.3
|
||||
|
||||
- new warp tool that autocompletes street names
|
||||
- hideable menus, place context menus better, remove top menu bar, add a simple OSD
|
||||
- loading screens reflect what's printed to the terminal
|
||||
- depict pedestrians and bikes with more detail
|
||||
- tool to scroll through an agent's route
|
||||
- make simulation speed controls actually work
|
||||
|
||||
0.1.4
|
||||
|
||||
- improve stop sign editor UI (toggle entire roads)
|
||||
- better mouseover / selection rendering
|
||||
- better traffic signal rendering (show time left, use outlines for yields)
|
||||
- make cars actually stop and briefly wait at stop signs
|
||||
- improve edit mode diff visualization (cross-hatching)
|
||||
- render actual stop signs, not just red lines
|
||||
- fix intersection policies confused by conflicting straight turns with lane-changing
|
||||
- fix mac scrolling
|
||||
- better turn indicators
|
||||
- nicer unzoomed view of roads, with different colors for big/small roads
|
||||
|
||||
0.1.5
|
||||
|
||||
(release file size jumped from ~15MB to ~70MB because of new PSRC trips)
|
||||
|
||||
- improve UX of intersection editors
|
||||
- define a better set of maps included by default
|
||||
- improve drawing speed by batching more stuff
|
||||
- better default traffic signal policies for many cases
|
||||
- import and visualize census data
|
||||
- fix missing sidewalks on downtown one-ways
|
||||
- import and visualize PSRC trip data
|
||||
|
||||
0.1.6
|
||||
|
||||
- slider widget for controlling time and speed
|
||||
- fixing bad polyline geometry in most cases; visualizing routes should no longer be buggy
|
||||
- handle PSRC trips that begin or end out-of-bounds
|
||||
- draw agents in unzoomed mode in a way simpler way
|
||||
- improve edit mode: detect reverts to original, easier lane type switching
|
||||
- lots of fixes for buses: handle edits better, read sequence of stops correctly from GTFS
|
||||
- set up A/B tests faster
|
||||
|
||||
0.1.7
|
||||
|
||||
- bulk and revert tools in edit mode
|
||||
- improve turns and default intersection policies when bike/bus lanes involved
|
||||
- new tool to manually hint for short roads and weird intersections. some problems have now been manually fixed
|
||||
- scoreboard of trip results for sandbox and A/B test mode
|
||||
- reduce lag when sim is running at full speeds, but system is too slow
|
||||
- switch to easbar's contraction hierarchy crate, making all pathfinding INSANELY fast
|
||||
- remove weird rules about the world freezing when traffic signals are in "overtime"
|
||||
|
||||
0.1.8
|
||||
|
||||
- edit mode: convert to a ped scramble cycle, simplify stop sign editor by removing individual turns
|
||||
- ui: put labels next to sliders, organize modal menus into sections, add a minimize/maximize icon
|
||||
- A/B test mode: savestate, include time controls and agent following/route tools here
|
||||
- use more OSM data for turn lanes, turn restrictions from lanes, turn restrictions between entire roads
|
||||
- dont attempt to cross a traffic signal if there's absolutely no hope
|
||||
- improve bus route UI tools and make routes using transit more sane
|
||||
- user-defined shortcuts for jumping between views of a map
|
||||
|
||||
0.1.9
|
||||
|
||||
- sliders to pick times in wizards
|
||||
- fix hidpi scaling
|
||||
- traffic signal diagram scrolls properly
|
||||
- easier to instantiate a scenario, show all trips involving a building for a scenario
|
||||
- colorschemes to show trip duration or time blocked
|
||||
- label buses with route number
|
||||
- represent overlapping pedestrians as a labeled crowd
|
||||
- massive performance boost via real priority queue
|
||||
- prevent cars from "blocking the box"
|
||||
- prevent all? aborted trips (due to parking blackholes mostly)
|
||||
- smarter roam-around-for-parking router
|
||||
|
||||
0.1.10
|
||||
|
||||
- sim
|
||||
- parking in off-street garages and on-street lanes on the off-side of oneways now mostly works
|
||||
- detect and handle parking blackholes; cars should never get stuck looking for parking now
|
||||
- let lower-priority turns happen at traffic signals when higher-priority ones blocked
|
||||
- get closer to FCFS ordering at stop signs
|
||||
- basic opportunistic lane-changing
|
||||
- a bus should be seeded for every route now
|
||||
- demand data
|
||||
- show trips to/from buildings and borders
|
||||
- make PSRC trips seed and attempt to use parked cars
|
||||
- UI
|
||||
- different heatmap overlays, like parking availability and busiest areas
|
||||
- show colorscheme legends when relevant
|
||||
- interactively seed parked cars, spawn more types of trips
|
||||
- fix major A/B test mode bug (mismatched scenarios and map edits)
|
||||
- adjusting sliders, menu placement, dynamic items
|
||||
- consolidating different tools into a single info panel for objects
|
||||
- bus route explorer shows entire route, current bus location
|
||||
- map quality
|
||||
- degenerate intersections only have one crosswalk now
|
||||
- revamped the map editor for fixing geometry problems, used it in many places
|
||||
- nicer yellow center lines (dashed when appropriate)
|
||||
- handling OSM turn restriction relations properly
|
||||
- fix empty traffic signal phases
|
||||
- handling bike lanes on certain sides of the road
|
||||
- starting to upstream manually-verified parking lanes into OSM
|
||||
- new gameplay: reverse direction of lanes
|
||||
|
||||
0.1.11
|
||||
|
||||
- small UI fixes: fixed width traffic signal diagram, skip info phase of menus when empty
|
||||
- start drawing (but not using) shared left-turn lanes from OSM
|
||||
- fix OSM polylines with redundant points (fixing an issue in ballard)
|
||||
- improved traffic signal policies in some cases
|
||||
- started upstreaming some sidewalk tags in OSM to fix inference issues
|
||||
- fixed misclassified right turns
|
||||
- adjusting map colors
|
||||
- handling lakes/ocean polygons from OSM way better
|
||||
- reorganized sim analytics, added stuff for bus arrivals
|
||||
- adding new internal road points to map editor. almost ready to really aggressively use it
|
||||
- skipping parking lanes with no nearby sidewalks, since they're unusable
|
||||
- fix z-order of bridges/tunnels in unzoomed view
|
||||
- allow unzooming indefinitely
|
||||
- move lots of sandbox mode controls (and other modes) to menus under buttons and dedicated buttons
|
||||
- basic support for marking a lane closed for construction
|
||||
- improved geometry of sidewalks at dead-ends
|
||||
|
||||
0.1.12
|
||||
|
||||
- reorganize everything as different challenge modes. start implementing 3: optimizing a bus route, speeding up all trips, or causing as much gridlock as possible
|
||||
- improved bus route explorer
|
||||
- some UI fixes (popup messages in a few places, moving mouse tooltips to the OSD)
|
||||
- lots of analytics and time-series plots
|
||||
|
||||
0.1.13
|
||||
|
||||
- analytics: prebake baseline results properly. hover over plot series. some new modes to see bus network, throughput of a road/intersection over time
|
||||
- log scale for the speed slider
|
||||
- add a bulk spawner in freeform mode (F2 on a lane)
|
||||
- rendering: nicer routes, crosswalks, zoomed car colors
|
||||
- map data: better stop sign and sidewalk heuristics
|
||||
- fixed the mac hidpi text rendering issue once and for all?!
|
||||
|
||||
0.1.14
|
||||
|
||||
- better crosswalk generation when there's only a sidewalk on one side of a road
|
||||
- edit mode UI revamp: paintbrush-style buttons to apply changes to lanes
|
||||
- show error messages and prevent edits, like disconnecting sidewalks
|
||||
- properly ban bikes from highways (revamped rules for vehicles using a lane)
|
||||
- new freeform mode tool to spawn bikes
|
||||
- WIP (not working yet): make bikes prefer bike lanes. some debug heatmaps for path cost
|
||||
- edit mode has proper undo support
|
||||
|
||||
0.1.15
|
||||
|
||||
- minor bugfixes with reverting lane types, preserving stop signs
|
||||
- incorporate edits into the challenge splash screen, make sure edits are reset when appropriate
|
||||
- starting a new challenge mode, just focused on traffic signals
|
||||
- can't leave traffic signal editor with missing turns
|
||||
- render pedestrian crowds on building front paths
|
||||
- traffic signals support an offset parameter
|
||||
- traffic signal visualization and editing revamped to group related turns together
|
||||
- can preview traffic using a signal from the editor
|
||||
- actually apply priority at intersections, so protected turns get first dibs over yield turns
|
||||
|
||||
0.1.16
|
||||
|
||||
- fix Mac crashing with texture limit bug by switching to texture arrays
|
||||
- fix crashing simulation when a border intersection was used
|
||||
- started to implement a new UI design for starting the game
|
||||
|
||||
0.1.17
|
||||
|
||||
- more work on the pre-game UI, with some flexbox layouting
|
||||
- prototype a minimap in sandbox mode. doesn't pan or scroll yet.
|
||||
- prototype a new speed/time control panel from the mockup
|
||||
- nicer time warp loading screen
|
||||
- record and show detailed trip timeline, including time to park
|
||||
|
||||
0.1.18
|
||||
|
||||
- map data: infer more building addresses
|
||||
- some analytics on how long people spend parking and intersection delay over time
|
||||
- create an options panel, allowing runtime customization of color scheme, traffic signal rendering, etc
|
||||
- internal changes to map building pipeline to make it much easier for new devs to onboard
|
||||
- organizing challenges into sub-stages, starting to flesh out specifics for the fix traffic signal track
|
||||
- much more realistic pedestrian pathfinding
|
||||
- fix minimap on mac (dpi issues)
|
||||
- visual tweaks to cars to make front/back easier to distinguish
|
||||
- internal change to switch most assets from PNG to SVG
|
||||
|
||||
0.1.19
|
||||
|
||||
- some challenge modes show a histogram for counting faster/slower trips
|
||||
- new visualization of current demand per direction at a traffic signal
|
||||
- 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
|
||||
- replaced right-click context menus with left click to open info panels
|
||||
- fixed random issues reported by people from HN
|
||||
|
||||
0.1.20
|
||||
|
||||
- moved some UI functionality around, pulling graphs into info panel
|
||||
- interactive legend for the minimap, toggle visibility of different agents
|
||||
- nicer colors and shapes for cars
|
||||
- misc simulation bugfixes that might help huge_seattle
|
||||
- pedestrians choose to use transit more realistically, factoring in time for the bus to drive
|
||||
|
||||
0.1.21
|
||||
|
||||
- switch some analytics dashboards to use buttons, not old non-scrolling menus
|
||||
- scrollbars... at least a start
|
||||
- preview traffic signal changes from live sim as the base
|
||||
- traffic signal preview has normal time/speed controls
|
||||
- traffic signal editor has undo support
|
||||
- minimap has buttons to pan
|
||||
|
||||
0.1.22
|
||||
|
||||
- minimap zoom controls
|
||||
- traffic signal rendering overhaul
|
||||
- heatmap colors improved, heatmap appears on minimap
|
||||
- bus info panel, a start to live delay analytics
|
||||
|
||||
0.1.23
|
||||
|
||||
- UI revamps: speed panel, minimap controls, heatmap chooser
|
||||
- bus timeline
|
||||
- hide internal IDs normally
|
||||
- limit map zoom
|
||||
- fix bugs with crosswalks conflicting with vehicle turns
|
||||
|
||||
0.1.24
|
||||
|
||||
- overhaul traffic signal editor UI, and add redo support
|
||||
- update main edit mode UI, and add redo support
|
||||
- limit max unzoom
|
||||
- fix the infamous HiDPI bug once and for all; minimaps should work everywhere
|
||||
- almost bug-free support for floating, horizontally and vertically scrolling panels
|
||||
- overhaul top-center panel, rename scenarios to be less confusing
|
||||
- expose bus analytics outside of challenge mode
|
||||
- live info panel can exist during a running simulation
|
||||
- consolidated agent route/trip information into info panel
|
||||
|
||||
0.1.25
|
||||
|
||||
- overhauled the tutorial
|
||||
- tuned top-center panel for sandbox and challenge modes
|
||||
- make bike and bus lanes more obvious
|
||||
- show map edits as an overlay anywhere
|
||||
- tune info panel contents, and show relationships between parked cars and buildings
|
||||
- fixes to traffic signal editor, like making all-walk conversion idempotent
|
||||
- nicer throughput and delay plots (sliding windows, grid lines)
|
||||
|
||||
0.1.26
|
||||
|
||||
- tutorial improved in a few places
|
||||
- map data: thinner sidewalks, associate buildings with named amenities
|
||||
- traffic model: vehicles can spawn on all lanes from a border
|
||||
- much better gameplay speed (previously was too fast)
|
||||
- UI tuning: lane editor, minimap, signal editor, heatmap legends don't overwrite minimap
|
||||
- traffic signal challenge communicates score more clearly
|
||||
|
||||
0.1.27
|
||||
|
||||
- edit mode revamped: click to edit stuff. no more lane paintbrushes. autosaving and save as.
|
||||
- tutorial: can quit and resume tutorial now
|
||||
- challenge picking flow simplified
|
||||
- UI: layouting fixes to full-screen / into stuff, popup menus go beneath buttons, plots improved
|
||||
- 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
|
||||
- misc perf improvements (cache SVGs, drawing many circles for unzoomed agents, dont reload prebaked data)
|
||||
- upgraded winit, glutin, glium -- hopefully no new bugs introduced on any platforms
|
||||
|
||||
0.1.27a
|
||||
|
||||
- patch to fix a crash with empty text dimensions on things like building info panels
|
||||
|
||||
0.1.28
|
||||
|
||||
- all info panels revamped
|
||||
- some tutorial stages are much more clear, with an updating goal
|
||||
- traffic signal scorecard generalized to work for some tutorial too
|
||||
- adjust how selected agents look
|
||||
- X button on popup menus
|
||||
|
||||
0.1.29
|
||||
|
||||
- new tool to convert between stop signs and traffic signals
|
||||
- lane editor easier to edit multiple lanes
|
||||
- info panels: IDs, mostly avoid horizontal scrolling, better info about trips to/from somewhere, move buttons up
|
||||
- traffic signal editor UI overhaul
|
||||
- different data in top-right agent meters panel
|
||||
- tooltips to communicate keybindings better
|
||||
- new jump-to-time panel, showing when rush hours occur
|
||||
- speed controls use more useful speeds
|
||||
- include ongoing trips in measured trip times
|
||||
- jump to next challenge after completing one
|
||||
- lots of tutorial tweaks
|
||||
|
||||
0.1.30
|
||||
|
||||
- show additional info about traffic patterns and buggy maps
|
||||
- revamp tutorial UI to group tasks and messages better
|
||||
- handle different mode transitions when info panel open on an agent
|
||||
- select entire roads in unzoomed edit mode
|
||||
- show total time an agent has spent moving / blocked
|
||||
- use 2-phase traffic signals by default, making the 23rd map successfully complete!
|
||||
- jump-to-time now optionally points out traffic jams forming
|
||||
- challenge splash screen improved
|
||||
|
||||
0.1.31
|
||||
|
||||
- overhauled trip timeline in agent info panels
|
||||
- overhauled traffic signal details panel and the per-lane turn explorer
|
||||
- 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
|
||||
- traffic signal edits can now be exported and used in any slice of Seattle. will be using this to hand-map many of them.
|
||||
- many small tutorial fixes
|
||||
|
||||
0.1.32
|
||||
|
||||
- some UI work on giving focus to textboxes, improving dropdown menus
|
||||
- road/intersection plots display baseline sim data too
|
||||
- start associating people with multiple trips, exposing this a little in the UI
|
||||
- bring back elevation data, introduce a new overlay. the elevation data is still really bad.
|
||||
|
||||
0.1.33
|
||||
|
||||
- new "population" overlay, showing people (not just current trips). heatmap and dot map to visualize.
|
||||
- improved the "delay" overlay to handle roads and intersections
|
||||
- removed the confusing and useless alternate color schemes for agents
|
||||
- initial left-hand driving side, tested in Perth, also drawing more arrows for all one-way roads
|
||||
- loads of internal GUI code refactorings, preparing for a standalone release of the library
|
||||
- fixed z-buffering and alpha values for web backend
|
||||
|
||||
0.1.34
|
||||
|
||||
- info panels have been totally overhauled again. multiple tabs, way more clear representation of agents, trips, and people.
|
||||
- draw people inside of a building
|
||||
- applied consistent typography everywhere
|
||||
- lots of internal refactoring
|
||||
|
||||
0.1.35
|
||||
|
||||
- more info panel work, particularly for trips and buses. change plot settings live.
|
||||
- prototype of a SEIR pandemic model based on time spent in shared spaces, by orestis
|
||||
- slight heatmap improvements, more coming
|
||||
- more typography changes
|
||||
- mouse cursor now changes for buttons and dragging!
|
||||
- overhaul minimap controls, make layers behavior zoomed in a little better
|
||||
- new speed panel and jump-to-time modal
|
||||
|
||||
0.1.36
|
||||
|
||||
- overhauled simulation data page, with a table to find slow trips and some initial summary visualizations
|
||||
- plots can change windowing and show/hide series
|
||||
- layers: fade map to contrast more, better scales/legends
|
||||
- show relative trip times in info panels
|
||||
- tools to rewind/ffw to watch particular trips
|
||||
- refocusing efforts on challenge modes; level 1 of a new one is pretty much ready
|
||||
- some simulation fixes around parking and a corner case of cars temporarily forming a cycle
|
||||
- orestis improved the population/pandemic heatmaps
|
||||
|
||||
0.1.37
|
||||
|
||||
- optimize commute challenge: high score, live sentiment, second stage
|
||||
- parked cars are owned by people, not buildings
|
||||
- info panel improvements for trips
|
||||
- bike layer suggests places where bike lanes could be helpful
|
||||
- many improvements to scatter plot
|
||||
- a new histogram-ish thing for understanding faster/slower trips
|
||||
- handling scenarios longer than 24 hours better (for pandemic model)
|
||||
- prototype of commute visualization, grouping buildings by blocks
|
||||
- sim bugfixes: crosswalk / vehicle turn conflicts, start bikes in bike lanes from borders
|
||||
|
||||
0.1.38
|
||||
|
||||
- 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
|
||||
- parking changes: show path to closest free spot, utilization of a lane over time, every building includes at least 1 offstreet spot by default
|
||||
- progress on removing unrealistic gridlock: detect turn conflict cycles and temporarily allow conflicts, trim last steps of a laggy head
|
||||
- internal sim alert system. speeds up debugging, could be used for player-facing "traffic jam!" alerts
|
||||
|
||||
0.1.39
|
||||
|
||||
- switched to proper OSM-based maps; no more brittle, manual geometry fixes
|
||||
- more sorting and filtering options in trip table and parking overhead tables
|
||||
- improve offstreet parking rendering. park closer to destination buildings
|
||||
- easier process for importing new cities. introducing Los Angeles, Austin, Barranquilla.
|
||||
- new data updater tool so people can opt-in to new cities
|
||||
- many internal fixes to prevent gridlock. smarter cycle detection, manual OSM fixes and traffic signal timings
|
||||
|
||||
0.1.40
|
||||
|
||||
- differential throughput layer to understand routing diversions
|
||||
- map edits now reference longer-lasting OSM IDs, can work cross-map
|
||||
- basemap updates: new areas for west seattle, mt baker, lots of upstreamed fixes in OSM and traffic signals, smarter border matching
|
||||
- parking: optionally filter on/off-street spots in the layer, allow disconnecting spots via edits
|
||||
- render some tunnels with lower opacity
|
||||
- new feature to change speed limits and bulk road selection tools
|
||||
- first write-up of a real use case (closing lake wash through arboretum)
|
||||
- make the traffic signal challenge act like a game, with a failure/win state and scoring
|
||||
|
||||
0.1.40a
|
||||
|
||||
- added a mode to map parking
|
||||
|
||||
0.1.41
|
||||
|
||||
- new parking mapper tool
|
||||
- include a one-shot .osm importer in the release
|
||||
- new layer to find different types of amenities / businesses
|
||||
- adjust traffic signal rendering style
|
||||
- bulk lane editor for changing speed limits and lane types
|
||||
- including west seattle and udistrict maps
|
||||
- include some OSM buildings that were being skipped
|
||||
- dont pause after opening something from sandbox mode
|
||||
- adjust turn signals for lane-changing cars
|
||||
- lots of fixes for monitors with different DPIs, enabled by default
|
||||
|
||||
0.1.42
|
||||
|
||||
- many misc UI bugfixes, especially for high-DPI screens
|
||||
- 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
|
||||
- rendering improvements: unzoomed agent size, visualizing routes on trip table, transparent roads beneath bridges, draw harbor island
|
||||
- overhauled street/address finder
|
||||
- parking mapper: shortcut to open bing
|
||||
|
||||
0.1.43
|
||||
|
||||
- new map picker!
|
||||
- UI polish: traffic signal editor, layers, bus stops, delay plots
|
||||
- generate more interesting biographies for people
|
||||
- tuned all the map boundaries
|
||||
- fleshing out lots of docs in preparation for the alpha release...
|
||||
|
||||
0.1.44
|
||||
|
||||
- spawner UI revamped
|
||||
- model parking lots! and finally model public/private parking
|
||||
- fix up tutorial
|
||||
- starting a story map mode
|
||||
|
||||
0.1.45
|
||||
|
||||
- overhauled challenge cutscenes and hints
|
||||
- traffic signal challenge: fix score detection, add meter, much faster startup, no reset-to-midnight required
|
||||
- layers: use gradient for a few, delay comparison, new UI for picker
|
||||
- overhauled minimap controls, should be intuitive now
|
||||
- edit mode changelist UI started
|
||||
|
||||
0.2.0 (alpha launch)
|
||||
|
||||
- road names now shown by default, in a new style
|
||||
- all layers now use gradients and show up zoomed in. worst traffic jam layer revamped.
|
||||
- scatter and line plot improvements
|
||||
- internal UI fixes: proper word wrap
|
||||
- bugfixes for following people riding the bus
|
||||
- rainbow crosswalks in one neighborhood
|
||||
- final polishing for launch
|
||||
|
||||
0.2.1
|
||||
|
||||
- busy week due to launch, but many new features in the pipeline
|
||||
- many bug fixes
|
||||
- edit mode: proper autosave, load proposals, jump between lane/intersection editors
|
||||
- very first steps on light rail... importing the tracks
|
||||
- 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.
|
||||
- starting to represent private roads
|
||||
- add a very simple actuated traffic signal
|
||||
|
||||
0.2.2
|
||||
|
||||
- the default traffic signal configuration is much smarter now, handling roads with some sidewalks missing and automatically synchronizing pairs of adjacent lights
|
||||
- much faster startup time for large maps
|
||||
- better UX for handling unsaved edits
|
||||
- access-restricted zones: changing existing zones almost completely works, except for granting new access to pedestrians
|
||||
- new sidewalk corner rendering, more rounded
|
||||
- ui style standardized for margins, padding
|
||||
- Javed got camera panning when your cursor is at the edge of the screen to work; enable it in settings
|
||||
- pulling bus stop/route info from OSM, not GTFS. steps towards light rail.
|
||||
- experimenting with controls for hiding bridges to see roads underneath; try them in dev mode (ctrl+S)
|
||||
- many bug fixes
|
||||
|
||||
0.2.3
|
||||
|
||||
- lane geometry is dramatically fixed, especially for one-ways
|
||||
- importing lanes from OSM improved
|
||||
- UI: bulk select includes select-along-a-route, show all bus routes in the layer, unzoomed zordering for roads/intersections
|
||||
- traffic scenario modifier can now convert trip modes
|
||||
- slight progress on light rail, although the train only makes one stop
|
||||
- vehicles moving through complex intersections with multiple traffic signals will now make it through multiple lights, even if they're unsynchronized
|
||||
- new random traffic scenario generator that makes people go between houses and workplaces
|
||||
- access-restricted zones: granular editing of individual roads now mostly works
|
||||
- removing the hardcoded relative directories, which many people have been having problems with
|
||||
- many many bug fixes, and some optimizations to reduce release file size
|
||||
|
||||
0.2.4
|
||||
|
||||
- bus/train routes overhauled; they're now one-way, regularly spawn every hour, and may begin or end at a border
|
||||
- new commute pattern explorer tool
|
||||
- new character art to give cutscenes a bit more personaliy
|
||||
- some progress on gridlocking maps, both from manual fixes and an attempt to reduce conflicts in multi-turn sequences
|
||||
- misc UI: show cars seeking parking in unzoomed mode, plot arrival rate at border intersections, consolidate bulk selection controls
|
||||
- trips modified by an experiment can now be filtered in summaries
|
||||
- buses, trains, and passengers on them are now properly distinguished in different stats
|
||||
- include krakow and berlin in release
|
||||
- buildings with holes in the middle are now rendered properly
|
||||
|
||||
0.2.5
|
||||
|
||||
- cars pick lanes better
|
||||
- overhaul bus/stop/route info panels
|
||||
- UI: better autocomplete, commuter pattern improvements by Michael, toggles instead of checkboxes, contours for heatmaps, edit mode loader revamp
|
||||
- internal refactors: turn creation, osm tags, osm parsing
|
||||
- import living streets from OSM as restricted-access zones, and other importer tweaks for berlin, krakow, san jose, sydney
|
||||
|
||||
0.2.6
|
||||
|
||||
- many roads without sidewalks now have a tiny shoulder lane, still enabling pedestrian movement, but with a penalty
|
||||
- bike trips will stop/start at a better position along the sidewalk now
|
||||
- support parking lanes on the off-side of a one-way
|
||||
- UI: search by building names, commuter patterns shows borders better
|
||||
- transit: make people ride off-map, spawn buses on short roads
|
||||
- internal cleanups for buttons
|
||||
|
||||
0.2.7
|
||||
|
||||
- many intersections with on/off ramps have much better geometry
|
||||
- lane-changing banned on turn lanes
|
||||
- lots more work matching bus stops/routes to the map. some progress, also some regressions.
|
||||
- fixing spawning on tiny borders
|
||||
- bus spawn rates from GTFS for seattle. started an editor for the schedule.
|
||||
- internal ezgui refactorings
|
||||
|
||||
0.2.8
|
||||
|
||||
- multiple traffic signals can now be synchronized and edited together
|
||||
- new dashboard for "traffic signal demand" over the entire day and map
|
||||
- started experimenting with controlling the headless runner via a JSON API
|
||||
- epic ezgui fix by Michael to consolidate handling of HiDPI scaling
|
||||
- got a bunch of huge cities importing and loading quickly
|
||||
- you can now save the trips you manually spawn in freeform mode, then replay them later
|
||||
|
||||
0.2.9
|
||||
|
||||
- import Xi'an, add a Chinese font, and add a tool for that group to import their external demand data
|
||||
- control A/B Street through a graphics-less API, with a Python example
|
||||
- improve UI for per-direction traffic signal demand
|
||||
- on/off ramp geometry fixed in a few more cases
|
||||
- fix some missing parking lot aisles, handle parking lots with 0 spots, and extract parking garages from OSM
|
||||
- switch road/building language in settings, if OSM data exists
|
||||
- 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
|
||||
- add custom-drawn trips to the main scenario, for exploring new demand from a new building
|
||||
- mkirk fixed up the glow/wasm ezgui backends, letting us remove glium
|
||||
- make map edit JSON backwards compatible
|
||||
- better lane/turn markings
|
||||
|
||||
0.2.10
|
||||
|
||||
- two-way cycletracks and arbitrary direction changes for roads
|
||||
- fix map editing for lane reversals, make edits backwards compatible, and massively speed up applying edits
|
||||
- fleshing out the headless API and tooling for controlling the simulation from any language
|
||||
- import a few more places, redo left-hand driving support so far
|
||||
- various bug/performance fixes
|
||||
|
||||
0.2.11
|
||||
|
||||
- disabled support for editing the map without resetting the simulation. needs more work, but solid start.
|
||||
- improvements to API, activity model, congestion capping
|
||||
- small UI tweaks for parking, editing multiple signals
|
||||
- fixed last bugs for left-handed driving, should work just as well now
|
||||
- lots of graphics experiments from the hackathon, not merged yet
|
||||
|
||||
0.2.12
|
||||
|
||||
- new textured color scheme and isometric buildings, in settings
|
||||
- new layer to show how far away people parked
|
||||
- Massive UI overhauls: jump to time/delay, edit mode, traffic signal editor (now with offsets), lane editor, bulk lane edit, traffic signal demand (individual intersections and all), loading screen
|
||||
- the Go API example compares trip times and detects gridlock
|
||||
- infinite parking mode
|
||||
- show how long a car has been parked in one spot
|
||||
- bugfix for some pathfinding costs around uber-turns
|
||||
- start to show a trip's purpose
|
||||
|
||||
0.2.13
|
||||
|
||||
- alleyways from OSM imported
|
||||
- traffic signal minimum time now constrained by crosswalks; thanks Sam!
|
||||
- UI changes in progress for trip tables, summaries, bulk edit
|
||||
- more API / Python example work for congestion capping
|
||||
- bug fixes: isometric buildings, documentation links, dropdown widgets, turn restrictions
|
||||
|
||||
0.2.14
|
||||
|
||||
- improve turn generation, with goldenfile tests
|
||||
- UI adjustments: unzoomed routes, better delay layer, include reasons for cancelled trips, throughput layer counts
|
||||
- small map importing fixes: multipolygon parking lots
|
||||
- fix infinite parking and blackholed buildings
|
||||
|
||||
0.2.15
|
||||
|
||||
- large internal change allowing asynchronously loading extra files over HTTP for web
|
||||
- the release of the first web version!
|
||||
- cars looking for parking now have a "thought bubble" showing this, by Michael
|
||||
- slow sections of a trip are now shown in the info panel, by Sam
|
||||
- fix by Michael for handling window resizing in panels
|
||||
- fix original routes on edited maps
|
||||
- internal code organization and documentation
|
||||
|
||||
0.2.16
|
||||
|
||||
- UI: click unzoomed agents, switch between metric/imperial units, show reason for cancelled trips, new "faded zoom" color scheme based on mapbox, more detailed agent counts in the top-right panel's tooltips
|
||||
- started a new dedicated OpenStreetMap viewer, will split out from A/B Street later
|
||||
- fix alpha colors on web
|
||||
- bugfixes for the new asynchronous map loading
|
||||
- some substantial simulation performance gains (168s to 90s on one benchmark!)
|
||||
- lots of progress towards editing the map without resetting the simulation to midnight. please test with --live_map_edits and report any issues
|
||||
- internal refactoring and code documentation
|
||||
|
||||
0.2.17
|
||||
|
||||
- tooling to automatically extract different shapes around cities without an explicit bounding polygon
|
||||
- imported many maps for an OSM viewer demo
|
||||
- misc bug fixes, UI tweaks, and perf improvements, especially for the web version
|
||||
- start using OSM sidewalks data properly in krakow -- more work needed, but better start
|
||||
|
||||
0.2.18
|
||||
|
||||
- overhaul data/system management: switch from Dropbox to S3, reorganize files, add an in-game updater
|
||||
- started a UI for collision dataviz, with data in the UK and Seattle
|
||||
- improve turns between separate footways
|
||||
- simplify the process of importing a new city
|
||||
|
||||
0.2.19
|
||||
|
||||
- added experimental day/night support; run with --day_night
|
||||
- slight performance improvements by avoiding applying no-op edits
|
||||
- new tests for lane-changing behavior, used to more safely allow more realistic behavior blocking "degenerate" intersections
|
||||
- experimenting with filling in gaps between one-way roads, to represent medians
|
||||
|
||||
0.2.20
|
||||
|
||||
- prototyped a new 15-minute neighborhood tool
|
||||
- overhaul internal simulation input code -- better performance, way simpler
|
||||
- debug tool to record traffic around a few intersections and replay later
|
||||
|
||||
0.2.21
|
||||
|
||||
- split separate tools into their own executables
|
||||
- misc bug fixes and other refactoring, focused on GUI code mostly
|
||||
- most of a prototype done for an experiment
|
||||
- map added for north seattle
|
||||
|
||||
0.2.22
|
||||
|
||||
- vehicles will lane-change less erratically during uber-turns (sequences of turns through multiple traffic signals close together)
|
||||
- debug mode has a "blocked-by graph" tool to understand dependencies between waiting agents
|
||||
- try multiple OpenGL video mode options if the first choice fails (thanks Michael!)
|
||||
- refactoring trip starting code and the minimap
|
||||
- non-Latin fonts now supported on web too, thanks to rustybuzz release
|
||||
- new small maps in Seattle included in the release, and NYC added to optional cities
|
||||
- saving some player state on the web (mostly camera position per map, for the main game)
|
||||
- partial prototype of a new census-based scenario generator, thanks to help from the Amazon SSPA hackathon
|
||||
- significant progress on the experiment, about one week left...
|
||||
|
||||
0.2.23
|
||||
|
||||
- released the 15-minute Santa experiment!
|
||||
- trip info panels now show more continuous progress along a route
|
||||
- fixing inactive buttons stretching too much
|
||||
|
||||
0.2.24
|
||||
|
||||
- variable traffic signal timing, thanks to Bruce
|
||||
- 15 min explorer: more walking options (require shoulders, change speed), more organized business search
|
||||
- 15 min santa: remember upzoning choices
|
||||
- misc bugfixes and refactoring
|
||||
- 2021 roadmap drafted
|
||||
|
||||
0.2.25
|
||||
|
||||
- huge breakthrough on merging intersections to handle short roads. applied to just a few places so far
|
||||
- support one-way roads with default traffic signal heuristics
|
||||
- 15 min explorer: find residences close to user-specified businesses, see unwalkable roads
|
||||
- bugfix from Bruce to prevent sim from crashing when a short road is over capacity
|
||||
- automatically fetch census data for any US map and use for scenario generation, from Michael
|
||||
- some initial experiments to bring A/B Street's lane rendering to the web using Leaflet
|
||||
|
||||
0.2.26
|
||||
|
||||
- dramatically improve initial web loading and be able to start with any map
|
||||
- city picker UI now better organizes other regions with many maps
|
||||
- new tool to convert SUMO networks into A/B Street maps
|
||||
- taking screenshots of the entire map now much faster, portable. trying to use for Leaflet raster tiles, but not working yet.
|
||||
- widgetry UI library now doesn't depend on anything specific to A/B Street
|
||||
- internal refactoring for error handling
|
||||
|
||||
0.2.27
|
||||
|
||||
- dramatically speed up starting scenarios by deferring when public transit riders pick their route
|
||||
- start importing separate cyclepaths and pedestrian plazas for Cambridge, many adjustments to make these start working
|
||||
- full panel for picking a scenario to start
|
||||
- import trip data from the actdev project for Cambridge
|
||||
- improve inferred map elements (stop signs and crosswalks) near short roads
|
||||
- heuristics for automatically finding and merging short roads. disabled, but solid start
|
||||
|
||||
0.2.28
|
||||
|
||||
- massive button overhaul by Yuwen and Michael
|
||||
- the color scheme automatically switches between day/night based on simulation time!
|
||||
- significant progress on editing the map without resetting the simulation
|
||||
- various bugfixes, new maps, improvements to running the importer, faster updater
|
||||
|
||||
0.2.29
|
||||
|
||||
- new map, Rainier Valley, is the 3rd ever to finish without gridlock! One of the fixes was collapsing traffic circles into a normal intersecton
|
||||
- bugfixes for map importing: cycleways with left-handed driving, matching traffic signals, odd number of lanes, u-turns
|
||||
- further fixes after the great button refactor
|
@ -1,3 +0,0 @@
|
||||
# Project logistics
|
||||
|
||||
This has some background/logistics about the project.
|
@ -1,62 +0,0 @@
|
||||
# Collaborations
|
||||
|
||||
We're working with a few different groups on projects using A/B Street.
|
||||
|
||||
## GLT
|
||||
|
||||
Active as of Sept 2020
|
||||
|
||||
[Green Lights Trading](https://www.greenlightstrading.com) 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.
|
||||
|
||||
## Xi'an
|
||||
|
||||
Active as of Sept 2020
|
||||
|
||||
A group (with their own demand data!) is studying traffic signal optimization in
|
||||
Xi'an. They're using the [API](../dev/api.md).
|
||||
|
||||
## Forecasting group
|
||||
|
||||
Active as of Sept 2020
|
||||
|
||||
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.
|
||||
|
||||
## CityEngine
|
||||
|
||||
Stalled as of Sept 2020
|
||||
|
||||
Edits in A/B Street could be exported to the
|
||||
[shared-row](https://github.com/d-wasserman/shared-row/) format, then rendered
|
||||
in 3D using
|
||||
[ArcGIS CityEngine](https://github.com/d-wasserman/Complete_Street_Rule). Not
|
||||
blocked on us.
|
||||
|
||||
## Berlin
|
||||
|
||||
Stalled as of Sept 2020
|
||||
|
||||
A group wants to use A/B Street for various public engagement projects in
|
||||
[Berlin](https://github.com/dabreegster/abstreet/issues/119). Mostly blocked on
|
||||
getting a reasonable travel demand model.
|
||||
|
||||
## Manchester
|
||||
|
||||
Stalled as of Sept 2020
|
||||
|
||||
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.
|
||||
|
||||
## Pandemic model
|
||||
|
||||
Stalled as of Sept 2020
|
||||
|
||||
A group from the Uni of Geneva started a
|
||||
[COVID-19 model](https://github.com/dabreegster/abstreet/tree/master/sim/src/pandemic)
|
||||
that figures out how long people spend in shared indoor spaces.
|
@ -1,24 +0,0 @@
|
||||
# Project history
|
||||
|
||||
As of June 2020.
|
||||
|
||||
tldr: A/B Street has been in active development since June 2018, but the idea
|
||||
has been festering since I was about 16.
|
||||
|
||||
## Retrospective
|
||||
|
||||
What poor judgments have cost me the most time?
|
||||
|
||||
- UI churn: I should've studied some UX on my own and started with a clear idea
|
||||
of how to organize everything
|
||||
- OSM data quality: I should've gained the confidence to upstream fixes earlier
|
||||
- Intersection geometry: I should've realized sooner that simulation robustness
|
||||
is more important than nice appearance.
|
||||
- Geometry primitives: I sunk too much time into the polyline problem and f64
|
||||
precision.
|
||||
|
||||
## Trivia
|
||||
|
||||
- The name was almost "Unstreet" or "Superban" (superb urban)
|
||||
- I hope you enjoy and/or are baffled by the
|
||||
[release names](https://github.com/dabreegster/abstreet/releases)
|
Before Width: | Height: | Size: 133 KiB |
@ -1,78 +0,0 @@
|
||||
# Backstory
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
[roguelikes](https://github.com/dabreegster/mnemonicrl/), which led to a fervent
|
||||
interest in pathfinding algorithms and
|
||||
[collaborative diffusion](http://www.cs.colorado.edu/~ralex/papers/PDF/OOPSLA06antiobjects.pdf).
|
||||
When I started driving in high school, I quickly realized how bad people were at
|
||||
it. I remember being stuck at the intersection of
|
||||
[Florida Blvd and Cloud](https://www.openstreetmap.org/node/1279204989) and
|
||||
first wondering if the pathfinding algorithms could help with traffic. Can you
|
||||
see where this is going?
|
||||
|
||||
![Impatience is a virtue](cloud_florida.jpg)
|
||||
|
||||
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, "I was really pretty impressed first that
|
||||
you would be so stupid as to actually try to do this..."
|
||||
|
||||
![Hand-mapping UT Austin](ut_map.png)
|
||||
|
||||
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 [AIM](http://www.cs.utexas.edu/~aim/), UT's
|
||||
demonstration that autonomous vehicles wouldn't need traffic lights. Everything
|
||||
came together, and I started a 3 year journey of building
|
||||
[AORTA](https://github.com/dabreegster/aorta/), a traffic simulator for AVs.
|
||||
Guided by the research lab, I explored the really bizarre idea of letting AVs
|
||||
[bid to turn lights green sooner](http://www.cs.utexas.edu/~aim/papers/ITSC13-dcarlino.pdf)
|
||||
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.
|
||||
|
||||
![Approximately Orchestrated Routing and Transportation Analyzer](aorta.gif)
|
||||
|
||||
It was great to try research in college; I learned I _really_ 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.
|
||||
|
||||
![Manhattan took walkability seriously](manhattan.jpg)
|
||||
|
||||
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.
|
Before Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 295 KiB |
Before Width: | Height: | Size: 24 KiB |
@ -1,34 +0,0 @@
|
||||
# Year 1 (June 2018-2019)
|
||||
|
||||
I skimmed through git and summarized roughly what I was working on each month,
|
||||
calling out milestones. "UI churn" is pretty much constantly happening.
|
||||
|
||||
- June: polyline geometry and lanes, building paths, protobuf -> serde
|
||||
|
||||
- July: pedestrians, bikes, parked cars, lane edits
|
||||
- August: porting AORTA's discrete-time driving model
|
||||
- September: multi-leg trips, buses, the first ezgui wizard, randomized
|
||||
scenarios
|
||||
|
||||
- October: A/B test mode (and so per-map plugins), forking RNG for
|
||||
edit-invariance, intersection geometry
|
||||
- November: clipping / borders, using blockface for parking, time travel mode,
|
||||
test runner framework
|
||||
- December: bezier curves for turns, traffic signal editor, a first attempt at
|
||||
merging intersections, right-click menus, a top menu, modal menus
|
||||
|
||||
- the grand colorscheme refactor: a python script scraped `cs.get_def` calls
|
||||
at build-time
|
||||
|
||||
- January: careful f64 resolution, ezgui screencapping, synthetic map editor
|
||||
- **grand refactor**: piston to glium
|
||||
- February: attempting to use time-space intervals for a new driving model, new
|
||||
discrete-event model instead
|
||||
- **Feb 19-27**: conceiving and cutting over to the new discrete event model
|
||||
- March: fleshing out DES model (laggy heads), first attempt to build on
|
||||
windows, gridlock detection
|
||||
|
||||
- April: first public releases, splash screen and rearranging game modes
|
||||
- May: fancier agent rendering, attempting to use census tracts, finding real
|
||||
demand data
|
||||
- **milestone**: discovered PSRC Soundcast data, much more realistic trips
|
@ -1,39 +0,0 @@
|
||||
# Year 2 (June 2019-2020)
|
||||
|
||||
![Circa October 2019](oct_2019.png)
|
||||
|
||||
- June: contraction hierarchies for pathfinding, stackable game states
|
||||
|
||||
- July: OSM turn restrictions, misc (I think I was in Europe?)
|
||||
- August: pedestrian crowds, agent color schemes, parking blackholes, a big
|
||||
`raw_data` refactor to store `Pt2D`, attended first hackathon
|
||||
- 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 `MapFixes` at scale to fix OSM bugs
|
||||
|
||||
- **milestone**: got the smallest montlake map to run without gridlock
|
||||
|
||||
- October: parking sim fixes, opportunistic lane-changing, starting challenge
|
||||
modes
|
||||
- November: prebaked sim results, time-series plots, undo for edit mode, traffic
|
||||
signal editor grouping turns
|
||||
- **milestone**: Yuwen joins project
|
||||
- December: the UI reform begins (flexbox, minimap, trip timelines, cutting over
|
||||
to SVGs, info panels, scrolling), started naming releases sensibly
|
||||
|
||||
- Project leaked to [HN](https://news.ycombinator.com/item?id=21763636), woops
|
||||
|
||||
- January: UI reform continues, the modern tutorial mode appears
|
||||
- Feburary: UI and tutorial, all text now pure vectors, port to glow+WASM
|
||||
- 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
|
||||
|
||||
- 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
|
||||
- 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 ;)
|
||||
- **milestone**: relying on pure OSM, no more `MapFixes`
|
@ -1,41 +0,0 @@
|
||||
# Year 3 (June 2020-2021)
|
||||
|
||||
- June: parking lots, real minimap controls, road labels
|
||||
- **June 22**: alpha launch!
|
||||
[r/Seattle](https://old.reddit.com/r/Seattle/comments/hdtucd/ab_street_think_you_can_fix_seattles_traffic/),
|
||||
[r/SeattleWA](https://old.reddit.com/r/SeattleWA/comments/hdttu8/ab_street_think_you_can_fix_seattles_traffic/),
|
||||
[r/UrbanPlanning](https://old.reddit.com/r/urbanplanning/comments/hdylmo/ab_street_a_traffic_simulation_game/),
|
||||
[HN](https://news.ycombinator.com/item?id=23605048#23608365),
|
||||
[GeekWire](https://www.geekwire.com/2020/want-fix-seattle-traffic-redditor-makes-game-allows-players-tweak-city-streets/),
|
||||
[The Stranger](https://www.thestranger.com/slog/2020/06/29/43999454/ab-streets-game-lets-you-create-the-seattle-street-grid-of-your-dreams)
|
||||
- July: loads of bugfixes, map geometry improvements, UI cleanups,
|
||||
access-restricted zones for private neighborhoods and no-through-traffic,
|
||||
better traffic generation between home<->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
|
||||
- [KING 5 Evening](https://www.youtube.com/watch?v=Pk8V-egsUxU) interview
|
||||
- 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
|
||||
- [Silicon Valley Bike Summit](https://bikesiliconvalley.org/2020/07/poster_dustin-carlino/),
|
||||
[Seattle PI](https://www.seattlepi.com/local/transportation/slideshow/solve-Seattles-traffic-problem-in-this-video-game-205839.php)
|
||||
- September: full support for driving on the left, textured color scheme,
|
||||
rendering isometric buildings, editing traffic signal offsets, a big round of
|
||||
UI changes, infinite parking mode, trip purpose, alleyways
|
||||
- [SeattleMet](https://www.seattlemet.com/news-and-city-life/2020/09/a-new-game-allows-you-to-redesign-seattle-streets)
|
||||
- October: unit tested turn generation, web version launched with async file
|
||||
loading, thought bubbles showing agent goals, slow parts of a trip
|
||||
highlighted, more UI overhauls, dedicated OSM viewer mode started, major
|
||||
simulation performance optimizations, major progress towards live map edits,
|
||||
automatically picking boundaries for arbitrary cities
|
||||
- November: switched from Dropbox to S3, download new maps in-game, collision
|
||||
dataviz UI, day/night color switching, unit testing lane changing behavior,
|
||||
starting the 15 min walkshed tool, simplified simulation spawning code,
|
||||
recording and replaying traffic around a few intersections, refactoring to
|
||||
split out separate tools
|
||||
- December: lane-changing fixes, blocked-by explorer in debug mode, non-Latin
|
||||
font support on web, saving player state on web, census-based scenario
|
||||
generation started, 15 minute Santa
|
@ -1,53 +0,0 @@
|
||||
# Project motivations
|
||||
|
||||
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:
|
||||
|
||||
- **Transparency and reproducibility**: 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.
|
||||
|
||||
- This means code and data should be open.
|
||||
- Businesses like [Sidewalk Lab's Replica](https://replicahq.com/) and
|
||||
[Remix](https://www.remix.com/solutions/streets) still need to generate
|
||||
income, but it's unclear why governments use taxes to pay for something only
|
||||
they see.
|
||||
- Decision making should be documented clearly. Why were the
|
||||
[35th Ave bike lanes](https://www.seattle.gov/transportation/projects-and-programs/programs/maintenance-and-paving/current-paving-projects/35th-ave-ne)
|
||||
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?
|
||||
- I'm personally inspired by approaches like
|
||||
[vTaiwan](https://info.vtaiwan.tw/) and
|
||||
[PDIS](https://po.pdis.nat.gov.tw/en/opengov/)
|
||||
|
||||
- **Accessibility leads to participation**: 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.
|
||||
|
||||
- Seattle's
|
||||
[Your Voice, Your Choice](https://www.seattle.gov/neighborhoods/programs-and-services/your-voice-your-choice)
|
||||
program is maybe an example of this
|
||||
|
||||
- **Short-term changes**: [ST3](https://en.wikipedia.org/wiki/Sound_Transit_3)
|
||||
is exciting, but 2040 isn't close. There are much cheaper changes that can be
|
||||
implemented sooner.
|
||||
|
||||
- Most of the edits in A/B Street are inspired by tactical urbanism; they
|
||||
could be prototyped with signs and paint.
|
||||
|
||||
- **The US is too dependent on cars**: 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.
|
||||
|
||||
- **Autonomous vehicles will NOT save the day**: 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.
|
||||
|
||||
- **Compromise and trade-offs**: 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.
|
@ -1,126 +0,0 @@
|
||||
# References
|
||||
|
||||
## Example use cases
|
||||
|
||||
- <https://www.reddit.com/r/SeattleWA/comments/9mtgkh/seven_places_to_add_bus_lanes_now/>
|
||||
- <https://www.reddit.com/r/SeattleWA/comments/9oqkz9/how_traffic_patterns_will_change_after_seattles/>
|
||||
- <https://www.reddit.com/r/Seattle/comments/9orqne/4_fresh_ideas_to_ease_seattles_coming_traffic/>
|
||||
- <https://www.reddit.com/r/SeattleWA/comments/cr1r1l/why_the_fuck_does_the_right_lane_convert_to/>
|
||||
- <https://twitter.com/transitrunner/status/1175068582142599168>
|
||||
|
||||
## Groups that may be eventually interested
|
||||
|
||||
- Seattle Times Traffic Lab
|
||||
- <https://www.citylab.com/transportation/2018/08/is-it-time-to-rethink-what-a-bike-lane-is/568483/>
|
||||
- <http://openseattle.org/>
|
||||
- <https://igniteseattle.com/>
|
||||
- <http://seattlegreenways.org/>
|
||||
- <https://www.livablecities.org/>
|
||||
- <https://www.reddit.com/r/openstreetmap/comments/a39uv0/ok_so/>
|
||||
- <https://mic.comotion.uw.edu/>
|
||||
- <https://www.seattleinprogress.com/>
|
||||
- <http://www.seattle.gov/seattle-pedestrian-advisory-board>
|
||||
- Socrata
|
||||
- <http://transportationcamp.org/>
|
||||
- <https://www.seattle.gov/transportation/projects-and-programs/programs/neighborhood-street-fund>
|
||||
- <https://www.seattle.gov/neighborhoods/programs-and-services/your-voice-your-choice>
|
||||
- <https://commuteseattle.com/>
|
||||
- <https://www.theurbanist.org/>
|
||||
- <https://humantransit.org/2019/03/notes-on-simcity-at-30.html>
|
||||
- <https://mynorthwest.com/category/chokepoints/>
|
||||
- <https://blogs.uw.edu/ceadvice/2019/05/08/infrastructure-week-2019-welcome-uw-cee-students-and-faculty/>
|
||||
- <https://escience.washington.edu/dssg/>
|
||||
- josie kresner from transport foundry
|
||||
- <https://www.citylab.com/transportation/2019/08/city-planning-transportation-oakland-community-engagement/596050/>
|
||||
- tweeting small problems -> bug tracker
|
||||
- <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.citylab.com/perspective/2019/10/micromobility-urban-design-car-free-infrastruture-futurama/600163/>
|
||||
- <https://www.sanjorn.com/>
|
||||
- <https://ui.kpf.com/>
|
||||
|
||||
## Similar projects
|
||||
|
||||
- Urban Footprint (<https://news.ycombinator.com/item?id=17895739>)
|
||||
|
||||
## Seattle-specific
|
||||
|
||||
SDOT asking for feedback:
|
||||
|
||||
- <http://sdotblog.seattle.gov/2017/02/08/from-signals-to-signs/>
|
||||
- <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/transportation-planning/north-downtown-mobility-action-plan>
|
||||
- <https://www.seattlebikeblog.com/2016/12/01/check-out-seattles-12-winning-neighborhood-led-transportation-ideas/>
|
||||
|
||||
Seattlites with opinions and ideas:
|
||||
|
||||
- <http://seattlegreenways.org/>
|
||||
- <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.reddit.com/r/SeattleWA/comments/5rvss5/what_changes_would_you_make_to_seattles_bus/>
|
||||
- <https://www.seattletimes.com/seattle-news/transportation/congestion-tolling-could-finally-break-seattles-working-poor-heres-a-better-idea/>
|
||||
- <https://www.reddit.com/r/SeattleWA/comments/86g3p9/id_get_back_an_hour_and_a_half_a_week/>
|
||||
- <https://www.reddit.com/r/Seattle/comments/4z3ewl/what_are_seattles_worst_intersections/>
|
||||
- <https://www.reddit.com/r/SeattleWA/comments/83h4ri/the_intersection_at_john_and_broadway_desperately/>
|
||||
|
||||
- <http://www.seattle.gov/transportation/sdot-document-library/citywide-plans/move-seattle>
|
||||
|
||||
## Other projects
|
||||
|
||||
- <https://github.com/uwescience/TrafficCruising-DSSG2017>
|
||||
- <http://sharedstreets.io/>
|
||||
- <https://github.com/twpol/osm-tiles> attempting to infer nice road geometry
|
||||
too
|
||||
|
||||
## Notes from related work
|
||||
|
||||
### SMARTS (<https://people.eng.unimelb.edu.au/etanin/tist17.pdf>)
|
||||
|
||||
- Split map into sections, simulate in parallel, load-balance
|
||||
- has an IDM equation
|
||||
- tests against real TomTom data of average speed per link
|
||||
|
||||
### Games
|
||||
|
||||
SimCity, Cities: Skylines
|
||||
<https://steamcommunity.com/sharedfiles/filedetails/?id=583429740>
|
||||
<https://github.com/fegennari/3DWorld>
|
||||
|
||||
### Open source urban planning
|
||||
|
||||
UrbanSim
|
||||
|
||||
### Proprietary
|
||||
|
||||
Sidewalk Labs Model
|
||||
|
||||
### Maps for people
|
||||
|
||||
<https://arxiv.org/pdf/1811.01147.pdf>
|
||||
|
||||
### gamma.cs.unc.edu/RoadNetwork/wilkie_TVCG.pdf
|
||||
|
||||
section 6.3 talks about offset polylines <http://gamma.cs.unc.edu/RoadNetwork>
|
||||
|
||||
### CityBound
|
||||
|
||||
<https://github.com/aeickhoff/descartes>
|
||||
|
||||
### Discrete Event Simulation papers
|
||||
|
||||
- section 5.1 of Advanced tutorial on microscopic discrete-event traffic
|
||||
simulation refers to some DES systems
|
||||
|
||||
- Florian, Mahut, and Tremblay 2008
|
||||
- Sumaryo, Halim, and Ramli 2013
|
||||
- Salimifard and Ansari 2013
|
||||
- Burghout, Koutsopoulos, and Andreasson 2006
|
||||
- Thulasidasan, Kasiviswanathan, Eidenbenz, Galli, Mniszewski, and Romero 2009
|
||||
|
||||
- A Dynamic Traffic Assignment Model for Highly Congested Urban Networks
|
||||
- section 2.2 models lanes as a moving and queueing part, references other
|
||||
possibly useful papers
|
||||
- dont worry about multiple lanes for the moving part, just the turn queues at
|
||||
the end
|
||||
|
||||
## Tactical urbanism
|
||||
|
||||
- <https://www.vice.com/en_us/article/pajgyz/rogue-coder-turned-a-parking-spot-into-a-coworking-space>
|
@ -1,122 +0,0 @@
|
||||
# Roadmap
|
||||
|
||||
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?
|
||||
|
||||
[See this doc](https://docs.google.com/document/d/1oV4mdtb0ve-wf0HqbEvR9IwXLIkTeDu8a3UnJxnr2F0/edit?usp=sharing)
|
||||
for the 2021 roadmap. The rest of this page was written in June 2020. After this
|
||||
year's plans firm up a bit, I'll update this page.
|
||||
|
||||
## Next steps, summer 2020
|
||||
|
||||
Afer the alpha launch in June, I plan to focus on:
|
||||
|
||||
- shared biking/walking trails like the Burke Gilman
|
||||
- light rail
|
||||
- more score functions besides trip time, like safety/comfort
|
||||
- changing trip mode choice (if you make a bus route more desirable, switch some
|
||||
trips)
|
||||
- web support (so people can try out proposals without installing anything)
|
||||
|
||||
## Ongoing work
|
||||
|
||||
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.
|
||||
|
||||
### UI and data visualization
|
||||
|
||||
We've got a UX designer, but implementing all of the new designs takes time.
|
||||
Also:
|
||||
|
||||
- improve color schemes for colorblind players, implement night mode, rain
|
||||
effects, etc
|
||||
- refactor and clean up the GUI library for other Rust users
|
||||
- lots of data viz design / implementation needed
|
||||
|
||||
### Game design
|
||||
|
||||
- the tutorial mode needs attention
|
||||
- many ideas for challenge/story modes, but playtesting, tuning, and game design
|
||||
needed
|
||||
|
||||
### Map data / GIS
|
||||
|
||||
Support more cities:
|
||||
|
||||
- write docs/tools to help people add new cities without programming experience
|
||||
- add support for non-OpenStreetMap input: GeoJSON for parking in Perth, other
|
||||
trip demand sources, etc
|
||||
- fix bugs for driving on the left side of the road
|
||||
|
||||
Improve the quality of map geometry derived from OpenStreetMap:
|
||||
|
||||
- try new algorithms to generate intersection polygons
|
||||
- make tools for easily improving relevant data in OSM
|
||||
- use ML and lidar/satellite data to get extremely accurate curb / planter /
|
||||
sidewalk geometry
|
||||
|
||||
Build tools and organize community mapping:
|
||||
|
||||
- organize an effort to map how traffic signals are timed (partly started)
|
||||
- divide and track work for distributed mapathons
|
||||
|
||||
Bring in new data to understand more about cities:
|
||||
|
||||
- PM2.5 pollution
|
||||
- Tax / land value (is there inequitable access to transit?)
|
||||
|
||||
### Simulation / modeling
|
||||
|
||||
Totally new areas:
|
||||
|
||||
- light rail
|
||||
- shared bike/pedestrian paths
|
||||
- ridesharing
|
||||
- micromobility (scooters, floating bikeshare)
|
||||
- more score functions (elevation gain, biking safety)
|
||||
- generating trip demand / activity models from scratch or modifying existing
|
||||
ones
|
||||
|
||||
Improve existing models:
|
||||
|
||||
- overtaking / lane-changing
|
||||
- pedestrian crowds
|
||||
- instant vehicle acceleration
|
||||
- pedestrians walking on road shoulders (some streets have no sidewalks)
|
||||
- buses: transfers, proper schedules, multiple buses per route
|
||||
|
||||
### Web
|
||||
|
||||
A/B Street runs on the web via WASM and WebGL; just waiting on vector text
|
||||
support. Besides that:
|
||||
|
||||
- Share community proposals online, discuss them, vote, etc
|
||||
|
||||
## Contributing for non-programmers
|
||||
|
||||
There's plenty to do besides programming!
|
||||
|
||||
- Mapping, most of which directly contributes to OpenStreetMap:
|
||||
- sidewalks and crosswalks
|
||||
- [on-street parking](../side_projects/parking_mapper.md)
|
||||
- [traffic signal timing](https://docs.google.com/document/d/1Od_7WvBVYsvpY4etRI0sKmYmZnwXMAXcJxVmm8Iwdcg/edit?usp=sharing)
|
||||
- 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.
|
||||
- Advocacy: I'm not great at finding the right people to to get ideas
|
||||
implemented for real. Maybe you are?
|
||||
|
||||
## Long-term vision
|
||||
|
||||
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.
|
||||
|
||||
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?
|
@ -1,6 +0,0 @@
|
||||
# Side projects
|
||||
|
||||
The scope of A/B Street has gradually expanded, resulting in related tools and
|
||||
efforts using lots of the same data and code. In winter 2020, some of these
|
||||
projects were more deliberately separated from A/B Street the traffic simulation
|
||||
game.
|
@ -1,25 +0,0 @@
|
||||
# 15-minute neighborhood explorer
|
||||
|
||||
![walkshed](walkshed.gif)
|
||||
|
||||
- [Web version](http://abstreet.s3-website.us-east-2.amazonaws.com/dev/fifteen_min)
|
||||
- To run locally, get the
|
||||
[latest release](https://github.com/dabreegster/abstreet/releases) for
|
||||
Windows, Mac, or Linux. After unzipping, run `fifteen_min.exe` or
|
||||
`fifteen_min`.
|
||||
|
||||
In a
|
||||
[15-minute city](https://crosscut.com/focus/2020/11/seattle-could-become-next-15-minute-city),
|
||||
most residents can reach a variety of stores, restaurants, parks, and jobs
|
||||
within about a 15 minute walk or bike ride. Part of advocating for a
|
||||
bike-friendly city is evaluating the zoning laws and understanding where people
|
||||
live in relation to where they work, shop, and meet friends. This tool is a
|
||||
prototype letting you see what's 15 minutes away from a starting point. You can
|
||||
explore the shops and estimate how much street parking and how many people live
|
||||
within a walkshed.
|
||||
|
||||
## Feedback
|
||||
|
||||
The tool is quite simple right now. If you have an idea how this could be used
|
||||
for advocacy, please
|
||||
[get in touch](https://github.com/dabreegster/abstreet/issues/393).
|
@ -1,12 +0,0 @@
|
||||
# OpenStreetMap viewer
|
||||
|
||||
- [Web version](http://abstreet.s3-website.us-east-2.amazonaws.com/dev/osm_viewer)
|
||||
- To run locally, get the
|
||||
[latest release](https://github.com/dabreegster/abstreet/releases) for
|
||||
Windows, Mac, or Linux. After unzipping, run `osm_viewer.exe` or `osm_viewer`.
|
||||
|
||||
A separate tool that visualizes OpenStreetMap data, with details on lanes, turn
|
||||
restrictions, parking lot capacity, and road width. It's also very convenient to
|
||||
explore the raw attributes on roads. The
|
||||
[OSM Connect 2020 talk](https://www.youtube.com/watch?v=JUN5GWfb4Qo) talks about
|
||||
possible directions for this viewer.
|
Before Width: | Height: | Size: 71 KiB |
@ -1,106 +0,0 @@
|
||||
# Mapping on-street parking in OpenStreetMap
|
||||
|
||||
![parking_mapper](parking_mapper.gif)
|
||||
|
||||
This guide assumes you've edited OSM before. Contact <dabreegster@gmail.com> if
|
||||
you have any trouble. Also give me a heads up when you make some edits, so I can
|
||||
regenerate the maps!
|
||||
|
||||
1. [Install A/B Street](index.md)
|
||||
2. Choose **Contribute parking data** on the main screen
|
||||
3. Change the map if you'd like to focus somewhere in particular
|
||||
4. Click a road with unknown parking
|
||||
5. Select what kind of on-street parking the road has
|
||||
6. Repeat
|
||||
7. Click **Generate OsmChange file**
|
||||
8. Upload the diff.osc file by adding a layer in JOSM (or send it to me)
|
||||
|
||||
Like all edits to OSM, to figure out ground-truth, you can survey in-person or
|
||||
use
|
||||
[Bing Streetside](https://wiki.openstreetmap.org/wiki/Bing_Maps#Streetside_imagery).
|
||||
**Do not use data from Google Maps to edit OSM.**
|
||||
|
||||
## FAQ
|
||||
|
||||
### Why?
|
||||
|
||||
I'm trying to build a realistic traffic simulation of Seattle using OSM data,
|
||||
then use it to strengthen proposals for
|
||||
[pedestrianized streets](../case_studies/lake_wash.md),
|
||||
[improving the bike network](https://www.glwstreets.org/45th-st-bridge-overview),
|
||||
and
|
||||
[mitigating the West Seattle bridge closure](../case_studies/west_seattle.md).
|
||||
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.
|
||||
|
||||
### Why put this data in OSM?
|
||||
|
||||
Why can't I just grab parking data from
|
||||
[SDOT's map](http://web6.seattle.gov/SDOT/seattleparkingmap/), using the
|
||||
[blockface](http://data-seattlecitygis.opendata.arcgis.com/datasets/blockface)
|
||||
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.
|
||||
|
||||
Plus, if the data is in OSM, anybody else can make use of it.
|
||||
|
||||
### How does the tool work?
|
||||
|
||||
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
|
||||
[parking:lane](https://wiki.openstreetmap.org/wiki/Key:parking:lane). 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.
|
||||
|
||||
**Your changes won't immediately be reflected in A/B Street.** Let me know when
|
||||
you've done some amount of mapping, and I'll regenerate the maps from fresh
|
||||
data.
|
||||
|
||||
### Why use this tool?
|
||||
|
||||
You don't have to; [this tool](https://zlant.github.io/parking-lanes/) 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
|
||||
[StreetComplete quest](https://github.com/westnordost/StreetComplete/issues/771).
|
||||
|
||||
### What about parking restrictions?
|
||||
|
||||
There are many
|
||||
[parking:lane](https://wiki.openstreetmap.org/wiki/Key:parking:lane) 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.
|
||||
|
||||
### What about off-street parking?
|
||||
|
||||
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.
|
||||
|
||||
### What about long roads where parking appears and disappears?
|
||||
|
||||
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.
|
||||
|
||||
### How to coordinate with other mappers?
|
||||
|
||||
If somebody wants to set up HOT tasking, that'd be great, but I don't expect so
|
||||
many people to jump on this.
|
||||
|
||||
### I noticed weird roads in the tool
|
||||
|
||||
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.)
|
||||
|
||||
### I want to map an area, but there's no option for it
|
||||
|
||||
To keep the release size small, I'm not including all maps yet. Let me know what
|
||||
you'd like to see included.
|
||||
|
||||
Or if you have a `.osm` file, try the [quick start guide](new_city.md).
|
@ -1,76 +0,0 @@
|
||||
# 15-minute Santa
|
||||
|
||||
Created by [Dustin Carlino](https://abstreet.org),
|
||||
[Yuwen Li](https://www.yuwen-li.com/), &
|
||||
[Michael Kirk](https://michaelkirk.github.io/)
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/mrIsVMLZ_yc" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
|
||||
|
||||
15-minute Santa is a game where you deliver presents across Seattle. You earn
|
||||
more points delivering to high-density housing, and you need to refuel from
|
||||
shops, so you'll have to understand where people live in relation to where they
|
||||
work and shop.
|
||||
|
||||
Contact <dabreegster@gmail.com> with any feedback or
|
||||
[file an issue on Github](https://github.com/dabreegster/abstreet/issues/new).
|
||||
|
||||
## Play it
|
||||
|
||||
- [Play online](http://abstreet.s3-website.us-east-2.amazonaws.com/dev/santa)
|
||||
(slower and no music -- download below if possible)
|
||||
- [Windows](https://github.com/dabreegster/abstreet/releases/download/v0.2.29/abstreet_windows_v0_2_29.zip)
|
||||
- [Mac](https://github.com/dabreegster/abstreet/releases/download/v0.2.29/abstreet_mac_v0_2_29.zip)
|
||||
- [Linux](https://github.com/dabreegster/abstreet/releases/download/v0.2.29/abstreet_linux_v0_2_29.zip)
|
||||
|
||||
Unzip, then run `santa.exe` or `santa`. No mobile/tablet support, sorry -- you need a keyboard.
|
||||
|
||||
## FAQ
|
||||
|
||||
### Why did y'all make this?
|
||||
|
||||
We normally work on [A/B Street](https://abstreet.org), a traffic simulation
|
||||
that lets the general public explore a future prioritizing more sustainable
|
||||
modes of transportation. All of the recent
|
||||
[talk](https://crosscut.com/focus/2020/11/seattle-could-become-next-15-minute-city)
|
||||
about 15-minute cities prompted us to explore how Seattle's zoning causes many
|
||||
people to live far from where they get groceries. After experimenting with a
|
||||
[more serious](fifteen_min.md) tool to understand walk-sheds, we decided to
|
||||
spend a few weeks on something a bit more light-hearted.
|
||||
|
||||
### Realism
|
||||
|
||||
The map of Seattle and location of shops comes from
|
||||
[OpenStreetMap](https://www.openstreetmap.org/about). We only consider shops if
|
||||
they sell food or drinks -- let us know if the map seems to be missing your
|
||||
favorite restaurant. The number of housing units is based on
|
||||
[Seattle GIS data](https://data-seattlecitygis.opendata.arcgis.com/datasets/current-land-use-zoning-detail).
|
||||
Mixed-use buildings with both commercial and residential units aren't
|
||||
represented. The game lets you upzone any house to place a new store; obviously
|
||||
this is a vast simplification of how complex a real conversation about changing
|
||||
zoning codes should be.
|
||||
|
||||
We rigorously evaluated the speed and carrying capacity of different cargo bikes
|
||||
and sleighs on the market to tune the vehicles in the game.
|
||||
|
||||
### Modding the game
|
||||
|
||||
Native versions only -- sorry, not easy to do on the web.
|
||||
|
||||
You can adjust the difficulty of the levels or give yourself all the upzoning
|
||||
power you want by editing `data/player/santa.json`. You first have to set
|
||||
`"enable_modding": true`. The format should mostly be self-explanatory; also see
|
||||
[here](https://github.com/dabreegster/abstreet/blob/be589f7ef4f649bb5a35bfe8de0bc81a9deeb029/santa/src/session.rs#L13)
|
||||
as a reference. If you break something, just delete the file to start over. If
|
||||
you come up with a better gameplay progression, please share -- tuning a game is
|
||||
hard!
|
||||
|
||||
### Adding new maps
|
||||
|
||||
Missing your slice of Seattle, or want to run somewhere else? If you have a bit
|
||||
of technical experience,
|
||||
[follow this guide](https://dabreegster.github.io/abstreet/howto/new_city.html)
|
||||
and then the above instructions for modding the game. Otherwise, draw the map
|
||||
boundaries in <http://geojson.io> and
|
||||
[send it to us](https://github.com/dabreegster/abstreet/issues/new) along with a
|
||||
time limit, goal, and starting point on the map. If you have a public data
|
||||
source for the number of housing units per building, please include it!
|
Before Width: | Height: | Size: 171 KiB |
@ -1,7 +0,0 @@
|
||||
# A/B Street's Traffic Simulation
|
||||
|
||||
This article describes how cars, bikes, buses, and pedestrians are modeled in
|
||||
A/B Street. All code lives in the `sim` crate.
|
||||
|
||||
[This recorded presentation](https://youtu.be/chYd5I-5oyc?t=1086) covers some of
|
||||
this.
|
@ -1,164 +0,0 @@
|
||||
# Discrete-event simulation
|
||||
|
||||
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
|
||||
`scheduler.rs` and the `step` method in `sim.rs`.
|
||||
|
||||
## Cars
|
||||
|
||||
(Note: Cars, bikes, and buses are all modeled the same way -- bikes just have a
|
||||
max speed, and buses/bikes can use restricted lanes.)
|
||||
|
||||
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.
|
||||
|
||||
A car has a few states (`mechanics/car.rs`):
|
||||
|
||||
- **Crossing** some distance of a lane/turn over some time interval
|
||||
- **Queued** behind another car on a lane/turn
|
||||
- **WaitingToAdvance** at the end of a lane, blocked on an intersection
|
||||
- A few states where the car stays in one place: **Parking**, **Unparking**, and
|
||||
**Idling** (for buses at a stop)
|
||||
|
||||
State transitions happen in `mechanics/driving.rs`. This is best explained by an
|
||||
example sequence:
|
||||
|
||||
- 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.
|
||||
- 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.
|
||||
- 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.
|
||||
- Some time later, the stop sign wakes up the car. The car starts the turn,
|
||||
entering the Crossing state again.
|
||||
- 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.
|
||||
- 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.
|
||||
- And so on...
|
||||
|
||||
### Exact positions
|
||||
|
||||
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. `mechanics/queue.rs` handles this, computing the distance
|
||||
of every car in a lane. For cars in the `Crossing` 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.
|
||||
|
||||
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 "laggy head", 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.
|
||||
|
||||
## Lane-changing
|
||||
|
||||
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
|
||||
[previous project](http://apps.cs.utexas.edu/tech_reports/reports/tr/TR-2157.pdf),
|
||||
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.
|
||||
|
||||
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 `opportunistically_lanechange` in `router.rs`. The decision could be
|
||||
improved.
|
||||
|
||||
## Pedestrians
|
||||
|
||||
Pedestrian modeling -- in `mechanics/walking.rs` is way simpler. Pedestrians
|
||||
don't need to queue on sidewalks; they can "ghost" 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.
|
||||
|
||||
## Intersections
|
||||
|
||||
I need to flesh this section out. See `mechanics/intersections.rs` for how stop
|
||||
signs and traffic signals work. Two things I need to fix before making this
|
||||
section interesting:
|
||||
|
||||
- Only wake up relevant agents when a previous agent finishes a turn.
|
||||
- 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.
|
||||
|
||||
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 "reserved" space, not necessarily currently occupied by
|
||||
vehicles in that lane. This accounts for other vehicles performing a turn bound
|
||||
for that lane. See `try_to_reserve_entry` in `mechanics/queue.rs`. When a car
|
||||
completely leaves a lane (determined by the "laggy head" described above), this
|
||||
space is freed, and blocked cars are woken up.
|
||||
|
||||
## Appendix: discrete-time simulation
|
||||
|
||||
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:
|
||||
|
||||
- Don't exceed any speed limits
|
||||
- Don't hit the lead vehicle (which might suddenly slam on its brakes)
|
||||
- Stop at the end of a lane, unless the intersection says to go
|
||||
|
||||
After fighting with this approach for a long time, I eventually scrapped it in
|
||||
favor of the simpler discrete-event model because:
|
||||
|
||||
- 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.
|
||||
- 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 "intent" of an action to auto-correct these errors.
|
||||
- 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.
|
@ -1,450 +0,0 @@
|
||||
# Traffic Simulation from scratch
|
||||
|
||||
The goal of this article is to explain the traffic simulation model that A/B
|
||||
Street uses. There's a large amount of traffic simulation research in academia,
|
||||
but the papers are often paywalled or require background knowledge. This article
|
||||
is meant to be accessible to anybody with a basic background in software
|
||||
engineering and high-school kinematics.
|
||||
|
||||
Disclaimers... my background is in software engineering, not civil engineering.
|
||||
The design space that A/B Street explores is absolutely massive; there are so
|
||||
many alternate ways of doing everything from modeling the map, to representing
|
||||
agents and their movement and conflict... Please send any critique/feedback/etc
|
||||
|
||||
## Introduction
|
||||
|
||||
My other goal with this article is to explain what I work on to my friends and
|
||||
family. It's very easy to say "I'm not a computer programmer or a math expert,
|
||||
there's no way I could understand this," and despite how frustrating this is,
|
||||
I've previously accepted this. But today I want more. Driving, moving around a
|
||||
city, and getting stuck in traffic are common experiences, and I think they can
|
||||
help...
|
||||
|
||||
Imagine there's an incredibly rainy afternoon and we've got lots of paper. I
|
||||
draw a to-scale map of your hometown, showing details like how many lanes are on
|
||||
every road, noting the speed limits, and marking all the stop signs and traffic
|
||||
lights. Then I place a bunch of color-coded Hot Wheels and, I don't know, bits
|
||||
of paper around the map. Each of the cars will start somewhere and wants to go
|
||||
to their colored square. To make it easy, let's pretend they all start driving
|
||||
at the same time. My challenge for you is to show me exactly where the cars are
|
||||
30 seconds after starting to drive, then 5 minutes in, and then an hour later.
|
||||
Maybe I'm interested in figuring out where the traffic jams happen. Or maybe we
|
||||
throw in some buses and little toy soldiers, and I want to know how long people
|
||||
after waiting for their bus because it's delayed in traffic. Or maybe I'm just
|
||||
sadistic and want to watch you squirm.
|
||||
|
||||
How would you figure out what happens to all of the cars after some amount of
|
||||
time? You'll probably start by figuring out the route each of them will take to
|
||||
their destination -- probably some approximation of the shortest path (by pure
|
||||
distance) or fastest (a longer route on a highway might be faster than a short
|
||||
one through residential roads). You'll inch the cars forward on their lane, not
|
||||
moving them (too much) faster than the speed limit. When two cars are near each
|
||||
other, you'll make one follow the other at a reasonable distance, or maybe
|
||||
change lanes and try to overtake them if there's room. You'll make the cars stop
|
||||
at stop signs and for red lights. When you accidentally push too many cars
|
||||
through a green light turned feisty yellow then somber red, you'll make the
|
||||
opposing lane's cars angrily honk at the jerk blocking the box by making odd
|
||||
little squeaks out of the corner of your mouth. (And I will laugh at you, of
|
||||
course.)
|
||||
|
||||
Of course, you won't be able to tell me with perfect accuracy where all the cars
|
||||
are 45.2 seconds into our little game. There are potholes that'll slow some cars
|
||||
down a bit that aren't marked on the map, and some drivers that take a little
|
||||
longer to accelerate or notice the light's green. That's fine -- complete
|
||||
realism isn't so important, as long as things look reasonable.
|
||||
|
||||
For this to be interesting for me to watch, there have to be a realistic number
|
||||
of cars -- 10 little Hot Wheels squeaking around all of Seattle won't tell me
|
||||
anything interesting about how the city flows. By now, you might be thinking
|
||||
this is going to be slightly tedious. Your fingers are going to get a bit
|
||||
cramped from budging 500,000 cars around a bit at a time. So I'll cut you a deal
|
||||
-- if you'll describe rules for how to move each of the cars forward a bit in
|
||||
sufficient detail, then I'll make a computer do all of the tedious bits.
|
||||
|
||||
And that's all programming a traffic simulator is. You don't need to know what
|
||||
arrays and entity-component systems and trans-finite agent-based cellular RAM
|
||||
drives are (I made up that last one maybe). Let's get started!
|
||||
|
||||
## The map
|
||||
|
||||
Let's start with deciding exactly what our map of Seattle looks like. One of the
|
||||
trickiest and most satisfying parts about computer programming is figuring out
|
||||
what parts of the world to represent. Too much irrelevant detail makes it harder
|
||||
to... Yes, a tree partly blocking a tight corner might make people slow down,
|
||||
but it's probably a bit too much detail to worry about. Your choice of
|
||||
abstraction should, it turns out, depend on what you're actually trying to do.
|
||||
In this case, I'll cheat momentarily and describe how we should model the map.
|
||||
Later, I'll explain what I want A/B Street to be and how that led to including
|
||||
some things while omitting others.
|
||||
|
||||
Let's also clear up terminology. Diagram goes here...
|
||||
|
||||
Let's start with **roads**. A road goes between exactly two **intersections**.
|
||||
You might think of 2nd Ave as a long road through all of downtown, but we'll
|
||||
chop it up as 2nd Ave between Bell St and Lenora, 2nd Ave from Lenora to Seneca,
|
||||
etc. Most intersections have two or more roads connected to them, but of course,
|
||||
we might also have dead-ends and cul-de-sacs. Each road has individual **lanes**
|
||||
going in some direction. Most roads have lanes going both directions, but a few
|
||||
one-ways only have lanes going in one direction. Cars will travel along a lane
|
||||
in single file and, to keep things simple, never change lanes in the middle of a
|
||||
road. When the car reaches the end of a lane, it can perform one of several
|
||||
**turns** through the intersection. After finishing the turn, the car will be at
|
||||
the beginning of a lane in another road. Some turns conflict, meaning it's not
|
||||
safe for two cars to do them simultaneously, while others don't conflict.
|
||||
|
||||
If cars can't ever change lanes, couldn't they get stuck? Maybe a car starts on
|
||||
the rightmost lane and is only allowed to turn right, but actually needs to be
|
||||
in a middle lane to go straight through the intersection. Don't worry -- you can
|
||||
assume that there's a path between any two lanes. Instead of changing lanes in
|
||||
the middle of a road, cars in our game will change lanes when they turn. EXAMPLE
|
||||
PIC. I'll describe later why this is a good idea.
|
||||
|
||||
For now, let's assume cars start on some lane. When their front bumper hits
|
||||
their colored square on their destination, they just immediately vanish. The
|
||||
colored square could be at the end of their destination lane, or somewhere in
|
||||
the middle.
|
||||
|
||||
(could mention borders or not, maybe footnote)
|
||||
|
||||
Don't worry about parking, pedestrians, bicycles, or buses. These things are all
|
||||
important to A/B Street, but we'll add them in later.
|
||||
|
||||
## Disrete-time model
|
||||
|
||||
Whoa, fancy name! Ignore it for a moment.
|
||||
|
||||
How do people drive? Very roughly, they look at things around them, take an
|
||||
action (press the gas some amount, press the brake some amount, turn the wheel a
|
||||
bit), and then do the same thing a half-second (or so) later. That's the essence
|
||||
of agent-based modeling -- sense the environment, plan what to do next, do it,
|
||||
then repeat some time later. We'll call the amount of time between each choice
|
||||
the **timestep** and say it's about 0.1 seconds. Let's try simulating traffic
|
||||
roughly this way -- every single car will take an action every 0.1 seconds that
|
||||
advances them through the world. Breaking up time in these regular 0.1s
|
||||
intervals is how we get the term "discrete-time model."
|
||||
|
||||
What kind of controls do we want to give each driver? If we let them turn the
|
||||
steering wheel a few degrees left or right and apply some pressure to the gas
|
||||
pedal, then we have to figure out how this affects the position of the car and
|
||||
worry about how to make sure cars stay in their lane. That's way too
|
||||
complicated, and not interesting for our purposes. So let's say that for every
|
||||
car, we keep track of a few details:
|
||||
|
||||
- current lane or turn
|
||||
- **dist_along**: distance of the front bumper along that lane or turn (starting
|
||||
at 0 for the beginning of the lane)
|
||||
- current speed
|
||||
- the remaining path to the goal (lane1, turn2, lane3, turn5, ..., lane10)
|
||||
- vehicle length
|
||||
- maximum acceleration (some cars can start more quickly)
|
||||
- maximum deceleration (some cars can slam on their brakes and stop faster)
|
||||
|
||||
The first four will change every 0.1s, while the last three don't ever change.
|
||||
|
||||
So what controls can a driver do? Accelerate (or decelerate) some amount. That's
|
||||
all. When the dist_along is bigger than the current lane/turn's length, we make
|
||||
the new current lane be the first thing from the remaining path, discard the
|
||||
path, and reset the dist_along to 0.
|
||||
|
||||
(this section got weird -- talk about controls first, brief bit of kinematics,
|
||||
then state. follow along curve of lanes automatically.)
|
||||
|
||||
### Constraints
|
||||
|
||||
What kind of things influence a driver's decision each timestep, and what do
|
||||
they need to be able to sense about their environment to use the rule? I can
|
||||
think of three:
|
||||
|
||||
1. Don't exceed the speed limit of the current road
|
||||
|
||||
- so the driver needs to be able to look at the speed limit of the current road
|
||||
|
||||
2. Don't hit the car in front of me
|
||||
|
||||
- need to see the current dist_along, speed, length, accel and deaccel of the
|
||||
next car in the queue
|
||||
- actually, humans can't eyeball another car and know how quickly it can speed
|
||||
up or slow down. maybe they just assume some reasonable safe estimate.
|
||||
|
||||
3. Maybe stop at the end of the lane
|
||||
|
||||
- for stop signs or red/yellow lights
|
||||
|
||||
And of course, whatever acceleration the driver picks gets clamped by their
|
||||
physical limits. Other than these constraints, let's assume every driver will
|
||||
want to go as fast as possible and isn't trying to drive smoothly or in a
|
||||
fuel-efficient manner. Not realistic, but makes our lives easier. So if each of
|
||||
these three constraints gives an acceleration, we have to pick the smallest one
|
||||
to be safe. Rule 1 says hit the gas and go 5m/s^2, but rule 2 says we can safely
|
||||
go 2m/s^2 and not hit the next car and rule 3 actually says wait, we need to hit
|
||||
the brakes and go -1m/s^2 right now. Have to go with rule 3.
|
||||
|
||||
### Some math
|
||||
|
||||
Skip this section freely. The takeaways are:
|
||||
|
||||
- there's a way to figure out the acceleration to obey the 3 constraints
|
||||
- the math gets tricky because (1) the car will only be doing that acceleration
|
||||
for 0.1s and then getting to act again, and (2) floating point math is tricky
|
||||
|
||||
### Lookahead
|
||||
|
||||
lookahead (worst case analyses), cover multiple lane->turn->lanes maybe
|
||||
|
||||
### Retrospective
|
||||
|
||||
1. It's fundamentally slow; there's lots of busy work. Cars in freeflow with
|
||||
nothing blocking them yet, or cars
|
||||
|
||||
2. Figuring out acceleration in order to do something for the next tick is
|
||||
complicated.
|
||||
|
||||
- floating pt bugs, apply accel but make sure speed doesnt go negative or dist
|
||||
doesnt exceed end of lane if they were supposed to stop... wind up storing an
|
||||
intent of what they wanted to do, make corrections based on that. hacky.
|
||||
|
||||
3. The realism of having cars accel and deaccel doesnt really add much, and
|
||||
since the approach has silly assumptions anyway (slam on brakes and
|
||||
accelerator as much as possible), unrealistic
|
||||
|
||||
## Discrete-event model take 1: time-space intervals
|
||||
|
||||
things that were not finished / still hard:
|
||||
|
||||
- cover a short lane
|
||||
- real quadratic distance over time was breaking stuff
|
||||
- impossible accel/deaccel happened
|
||||
- faster lead car made adjusting follower very hard
|
||||
|
||||
## Discrete-event model take 2
|
||||
|
||||
Let's try again, but even simpler and more incremental this time.
|
||||
|
||||
(make sure to explain the premise of parametric time and events)
|
||||
|
||||
### v0: one car
|
||||
|
||||
Forget about speed, acceleration, and even multiple cars momentarily. What is a
|
||||
car's basic state machine? They enter a lane, travel across it, maybe stop and
|
||||
wait for the intersection, execute a turn through the intersection, and then
|
||||
enter the next lane. We could assign reasonable times for each of these --
|
||||
crossing a lane takes lane_distance / min(road's speed limit, car's max speed)
|
||||
at minimum. Intersections could become responsible for telling cars when to move
|
||||
-- stop signs would keep a FIFO queue of waiting cars and wake up each car as
|
||||
the last one completes their turn, while traffic signals could wake up all
|
||||
relevant cars when the cycle changes.
|
||||
|
||||
### v1: queueing
|
||||
|
||||
Alright, but what about multiple cars? In one lane, they form a queue -- no
|
||||
over-taking or lane-changing. The FSM doesn't get much more complicated: a car
|
||||
enters a lane, spends at least the freeflow_time to cross it, and then either
|
||||
winds up front of the queue or behind somebody else. If they're in the front,
|
||||
similar logic from before applies -- except they first need to make sure the
|
||||
target lane they want to turn to has room. Maybe cars are already backed up all
|
||||
the way there. If so, they could just wait until that target lane has at least
|
||||
one car leave. When the car is queued behind another, they don't have anything
|
||||
interesting to do until they become the queue's lead vehicle.
|
||||
|
||||
Another way to understand this system is to picture every lane as having two
|
||||
parts -- the empty portion where cars cross in freeflow and a queue at the end.
|
||||
Cars have to pay a minimum amount of time to cross the lane, and then they wind
|
||||
up in the queue. The time to go from the end of the queue to the front requires
|
||||
crunching through the queue front-to-back, figuring out when each successive
|
||||
lead vehicle can start their turn and get out of the way.
|
||||
|
||||
### Drawing
|
||||
|
||||
An intermission -- we haven't pinned down exactly where cars are at some point
|
||||
in time, so how do we draw them? The idea for this DES model began without
|
||||
worrying about this too much -- when the map is zoomed out, individual cars are
|
||||
hard to see anyway; the player probably just wants to know roughly where lots of
|
||||
cars are moving and stuck waiting. This can be calculated easily at any time --
|
||||
just count the number of cars in each queue and see if they're in the Crossing
|
||||
or Queued state.
|
||||
|
||||
But when zoomed in, we do want to draw individual cars at exact positions
|
||||
through time! Luckily, this isn't hard at all. The only change from the timestep
|
||||
model is that we have to process a queue at a time; we can't randomly query an
|
||||
individual car. This is fine from a performance perspective -- we almost always
|
||||
want to draw all cars on lanes visible on-screen anyway.
|
||||
|
||||
So how does it work? First consider the queue's lead vehicle. If they're Queued,
|
||||
then the front of the car must be at the end of the lane waiting to turn. If
|
||||
they're Crossing, then we can just linearly interpolate their front position
|
||||
from (0, lane_length) using the time-interval of their crossing and the current
|
||||
time. Then we consider the queue's second car. In an ideal world where they're
|
||||
the lead car, we do the same calculation based on Queued or Crossing state. But
|
||||
the second car is limited by the first. So as we process the queue, we track the
|
||||
bound -- a car's front position + the car's length + a fixed following distance
|
||||
of 1m. The second car might be farther back, or directly following the first and
|
||||
blocked by them. We just take min(ideal distance, bound), and repeat for the
|
||||
third car.
|
||||
|
||||
### v2: preventing discontinuities
|
||||
|
||||
There's an obvious problem happening when the lead vehicle of a queue leaves the
|
||||
queue -- everybody queued behind them suddenly jump forward. Discontinuities
|
||||
like this are of course unrealistic, but more importantly for A/B St's purpose,
|
||||
looks confusing to watch. So let's try a simple fix: when a lead car exits a
|
||||
queue, update its follower to know to cross the remaining distance properly. The
|
||||
follower might be Queued right behind the lead, or they might still be Crossing.
|
||||
If they're still Crossing, no worries -- they'll continue to smoothly Cross to
|
||||
the end of the lane. But if they're Queued, then reset the follower to Crossing,
|
||||
but instead make them cover a smaller distance -- (lane_length - lead car's
|
||||
length - FOLLOWING_DISTANCE, lane_length), using the usual min(lane speed limit,
|
||||
car's max speed). Since they're Queued, we know that's exactly where the
|
||||
follower must be.
|
||||
|
||||
This smoothness comes at a price -- instead of a car taking one event to cross a
|
||||
lane, it now might go through a bunch of Crossing states -- the lane's max
|
||||
capacity for vehicles, at worst. That's not so bad, and it's worth it though.
|
||||
|
||||
### v3: starting and stopping early
|
||||
|
||||
The basic traffic model is now in-place. As we add more elements of A/B Street
|
||||
in, we need one last tweak to the driving model. Cars don't always enter a lane
|
||||
at the beginning or exit at the very end. Cars sometimes start in the middle of
|
||||
a lane by exiting an adjacent parking spot. They sometimes end in the middle of
|
||||
a lane, by parking somewhere. And buses will idle in the middle of a lane,
|
||||
waiting at a bus stop for some amount of time.
|
||||
|
||||
When we update a car, so far we've never needed to calculate exact distances of
|
||||
everybody on the queue at that time. That's just for drawing. But now, we'll
|
||||
actually need those distances in two cases: when a car is finished parking or
|
||||
when a car is somewhere along their last lane. (Note that buses idling at a stop
|
||||
satisfy this second case -- when they leave the stop, they start following a new
|
||||
path to the next stop.) When the lead car vanishes from the driving lane (by
|
||||
shifting into the adjacent parking spot, for example), we simply update the
|
||||
follower to the Crossing state, starting at the exact position they are at that
|
||||
time (because we calculated it). If they were Queued behind the vanishing car,
|
||||
we know their exact position without having to calculate all of them. But
|
||||
Crossing cars still paying the minimum time to cross the lane might jump forward
|
||||
when the car in front vanishes. To prevent this, we refresh the Crossing state
|
||||
to explicitly start from where they became unblocked.
|
||||
|
||||
### Remaining work
|
||||
|
||||
There's one more discontinuity remaining. Since cars have length, they can
|
||||
occupy more than one lane at a time. When the lead car leaves a queue, the
|
||||
follower is updated to cross the remaining distance to the end. But if the
|
||||
leader is moving slowly through their turn, then the follower will actually hit
|
||||
the back end of the lead vehicle! We need a way to mark that the back of a
|
||||
vehicle is still in the queue. Maybe just tracking the back of cars would make
|
||||
more sense? But intersections need to know when a car has started a turn, and
|
||||
cars spawning on the next lane might care when the front (but not back) of a car
|
||||
is on the new lane. So maybe we just need to explicitly stick a car in multiple
|
||||
queues at a time and know when to update the follower on the old lane. Except
|
||||
knowing when the lead car has advanced some minimum distance into the new lane
|
||||
seemingly requires calculating exact distances frequently!
|
||||
|
||||
This jump bug also happens when a lead car vanishes at a border node. They
|
||||
vanish when their front hits the border, even though they should really only
|
||||
vanish when their back makes it through.
|
||||
|
||||
The other big thing to fix is blind retries. In almost all cases, we can
|
||||
calculate exactly when to update a car. Except for three:
|
||||
|
||||
1. Car initially spawning, but maybe not room to start. Describe the rules for
|
||||
that anyway.
|
||||
|
||||
2. Car on the last lane, but haven't reached end_distance yet. Tried a more
|
||||
accurate prediction thing, but it caused more events than a blind retry of
|
||||
5s.
|
||||
|
||||
3. Cars waiting to turn, but not starting because target lane is full. Could
|
||||
register a dependency and get waked up when that queue's size falls below its
|
||||
max capacity. Could use this also for gridlock detection. Oops, but can't
|
||||
start because of no room_at_end. That's different than target lane being
|
||||
full, and it's hard to predict when there'll be room to inch forward at the
|
||||
end.
|
||||
|
||||
#### Notes on fixing the jump bug
|
||||
|
||||
- can track a laggy leader per queue. there's 0 or 1 of these, impossible to be
|
||||
more.
|
||||
- a car can be a laggy leader in several queues, like long bus on short lanes.
|
||||
last_steps is kinda equivalent to this.
|
||||
|
||||
is it possible for get_car_positions to think something should still be blocked
|
||||
but the rest of the state machine to not? - dont change somebody to
|
||||
WaitingToAdvance until theres no laggy leader.
|
||||
|
||||
TODO impl:
|
||||
|
||||
- get_car_positions needs to recurse
|
||||
- trim_last_steps needs to do something different
|
||||
|
||||
the eager impl:
|
||||
|
||||
- anytime we update a Car with last_steps, try to go erase those. need full
|
||||
distances. when we successfully erase, update followers that are Queued. - -
|
||||
follower only starts moving once the laggy lead is totally out. wrong. they
|
||||
were Queued, so immediately promote them to WaitingToAdvance. smoothly draw in
|
||||
the meantime by recursing
|
||||
- optimistic check in the middle of Crossing, but use a different event for this
|
||||
to be clear. the retry should only be expensive in gridlocky cases. -
|
||||
BLIND_RETRY after... similar to end_dist checking. - note other routines dont
|
||||
even do checks that could hit numerical precision, we just assume events are
|
||||
scheduled for correct time.
|
||||
- maybe v1: dont recurse in get_car_positions, just block off entire laggy
|
||||
leader length until they're totally out.
|
||||
- v2: do have to recurse. :(
|
||||
|
||||
the lazy impl:
|
||||
|
||||
- when we become WaitingToAdvance on a queue of length > vehicle len, clean up
|
||||
last_steps if needed
|
||||
- when we vanish, clean up all last_steps
|
||||
- when a follower gets to ithin laggy leader length of the queue end, need to
|
||||
resolve earlier - resolving early needs to get exact distances. expensive, but
|
||||
common case is theyre clear. if somebody gets stuck fully leaving a queue,
|
||||
then this will spam, but thats also gridlocky and we want to avoid that anyway
|
||||
|
||||
other ideas:
|
||||
|
||||
- can we cheat and ensure that we only clip into laggy leaders briefly? - if
|
||||
laggy leaders never get stuck at end of their next queue...
|
||||
- alt: store front and back of each car in queues separately - compute crossing
|
||||
state and stuff for those individually? double the work?
|
||||
|
||||
## A/B Street's full simulation architecture
|
||||
|
||||
start from step(), the master event queue, how each event is dispatched, each
|
||||
agent's states
|
||||
|
||||
FSM for intersections, cars, peds (need to represent stuff like updating a
|
||||
follower, or being updated by a leader)
|
||||
|
||||
## Appendix
|
||||
|
||||
pedestrian, transit, bikes, buses, etc limits... overtaking (especially cars and
|
||||
bikes on roads)
|
||||
|
||||
Traffic modeling is a complex space, but for the purposes of this article, a
|
||||
traffic simulation is a computer program that takes a map with roads and
|
||||
intersections and a list of trips (depart from here at this time, go there using
|
||||
a car or bus or by foot) and shows where all of the moving agents wind up over
|
||||
time. I'm sure you can imagine a great many uses for them both professional and
|
||||
nefarious, but our mission today is to understand one particular traffic
|
||||
simulation works. A/B Street is a computer game I've been building to experiment
|
||||
with the traffic in Seattle. My goal for A/B Street is to make it easy for
|
||||
anybody to ask what-if questions.
|
||||
|
||||
a/b st is a game, needs performance (city scale -- X road segments, X
|
||||
intersections, X agents total), determinism, not complete realism agent-based,
|
||||
rule out others complex maps
|
||||
|
||||
cars, buses, bikes only (things on the road in a queue)
|
||||
|
||||
abst is a game, what's the essence of scarcity? contention at intersections,
|
||||
lanes restricting usage, parking. NOT modeling pedestrians queueing on a
|
||||
sidewalk, bc in practice, doesnt happen (except maybe around pike place or at
|
||||
festivals). not modeling bike racks at all -- in practice, can lock up within a
|
||||
block of destination without effort.
|
||||
|
||||
if modeling big highways, this wouldnt be great. but we're focused on intra-city
|
||||
seattle -- modeling phenomena like jam waves not so important. if the player
|
||||
does parking->bus lane and the bus moves faster, but more cars circle around
|
||||
looking for parking, then the model is sufficiently interesting to answer the
|
||||
questions i want. dont need to model stopping distance for that.
|
@ -1,117 +0,0 @@
|
||||
# Gridlock
|
||||
|
||||
Here "gridlock" refers to the general problem of trips getting permanently
|
||||
stuck, preventing the full simulation from completing. Most of the work is
|
||||
tracked [here](https://github.com/dabreegster/abstreet/issues/114).
|
||||
|
||||
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.
|
||||
|
||||
## Problems
|
||||
|
||||
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.
|
||||
|
||||
- Short roads in OSM causing very weird geometry
|
||||
- Intersection geometry being too large, requiring too much time to cross
|
||||
- Unrealistic traffic patterns caused by everyone trying to park in one big
|
||||
garage (downtown) or take some alley (the UW soundcast issue)
|
||||
- Too many people try to take an unprotected left turn (often at a stop sign)
|
||||
- Bad individual traffic signals, usually at 5- or 6-ways
|
||||
- Groups of traffic signals logically acting as a single intersection
|
||||
- Separate traffic signals along a corridor being unsynchronized
|
||||
- Vehicles performing illegal sequences of turns
|
||||
- Vehicles are stuck with their plan and not reacting to traffic by changing
|
||||
route
|
||||
- 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.
|
||||
- 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.
|
||||
- Issues caused by the unrealistic
|
||||
[lane-changing model](discrete_event.md#lane-changing)
|
||||
- Two turns that go to the same lane (one going "straight", 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.
|
||||
|
||||
## Solutions
|
||||
|
||||
Divide into implemented or not.
|
||||
|
||||
- Synchronizing pairs of signals
|
||||
- Uber-turns
|
||||
- for interpreting OSM turn restrictions
|
||||
- for synchronizing a group of signals
|
||||
- for locking turn sequences
|
||||
- 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.
|
||||
- Cycle detector
|
||||
- block-the-box protection
|
||||
- the manual list of overrides
|
||||
- likely shouldn't apply during uber-turns
|
||||
- is it always fine to block the box at degenerate intersections?
|
||||
- hacks to allow conflicting turns at really broken intersections
|
||||
- manually timing signals
|
||||
- penalties for lane choice to make lane usage realistic
|
||||
|
||||
### Not implemented
|
||||
|
||||
- Dynamic rerouting
|
||||
- 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 `--disable_block_the_box` enabled - will enter
|
||||
crossing even if leaving it will be impossible).
|
||||
- Last resort: if someone's waiting on a turn >5m, just go.
|
||||
- Uber-turns
|
||||
- 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.
|
||||
|
||||
## Strategy for resolving
|
||||
|
||||
Because there are so many different causes all tangled together, my approach is
|
||||
to simplify the simulation as much as possible. A problem is much easier to
|
||||
understand and fix when it's isolated. I've been trying this to get the downtown
|
||||
weekday scenario to complete. A list of different techniques to simplify, in no
|
||||
particular order:
|
||||
|
||||
- Use the `--infinite_parking` flag to just let everyone park directly in their
|
||||
destination buildings. This is useful since downtown has many large parking
|
||||
garages with high capacity, but I don't have a data source describing them.
|
||||
- Use the `--disable_turn_conflicts` flag, which greatly reduces realism, but
|
||||
lets conflicting turns happen simultaneously. (Even with this and other flags,
|
||||
downtown still gridlocks!) It also disables traffic signals, so bad inferred
|
||||
timing isn't an issue.
|
||||
- Use the `--disable_block_the_box` flag to workaround short roads.
|
||||
- If you notice problems forming from cars stacking up behind slower cyclists,
|
||||
there's no over-taking implemented yet. Use the scenario modifiers to convert
|
||||
all biking trip to driving:
|
||||
`--scenario_modifiers='[{"ChangeMode":{"to_mode":"Drive","pct_ppl":100,"departure_filter":[0.0,86400.0],"from_modes":["Bike"]}}]'`
|
||||
- If all else fails, use the scenario modifiers to bluntly cancel some
|
||||
percentage of all trips.
|
||||
|
||||
A quick method for "disabling" buggy short roads is to use edit mode and close
|
||||
the lanes. This forces traffic to reroute around the problematic area, which
|
||||
might create other problems, but it can be useful.
|
||||
|
||||
## Fixing data used in simulation
|
||||
|
||||
Give more examples of changesets.
|
||||
|
||||
- upstreaming turn restrictions into OSM to prevent invalid U-turns and other
|
||||
crazy movements
|
||||
- ex: <https://www.openstreetmap.org/changeset/87945050>
|
||||
- upstreaming lane count fixes into OSM to improve geometry
|
@ -1,50 +0,0 @@
|
||||
# Live edits
|
||||
|
||||
When the player edits the map, there's an [efficient process](../map/edits.md)
|
||||
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).
|
||||
|
||||
The UI has a `dirty_from_edits` 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.
|
||||
|
||||
## What works today
|
||||
|
||||
Changes to traffic signals are simple -- `incremental_edit_traffic_signal`
|
||||
happens at the map layer, and then `handle_live_edited_traffic_signals` at the
|
||||
sim layer just resets the current stage to 0 if the previous configuration had
|
||||
more stages.
|
||||
|
||||
## TODO: Recalculating paths
|
||||
|
||||
Many of the edits will influence routes. For trips that haven't started yet,
|
||||
there's nothing to do immediately. Paths are calculated right before the trip
|
||||
starts, so slight changes to the start/end of the path due to map edits (like
|
||||
where somebody starts biking, for example) are captured naturally.
|
||||
|
||||
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 cancel all active trips
|
||||
whose path crosses an edited road or intersection. Later, we can figure out
|
||||
rerouting.
|
||||
|
||||
And actually, the only other case to handle is `ChangeRouteSchedule`, which
|
||||
should just be rescheduling the `StartBus` commands.
|
||||
|
||||
## TODO: Parking
|
||||
|
||||
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 get cancelled or fallback to walking.
|
||||
|
||||
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.
|
@ -1,14 +0,0 @@
|
||||
# Parking
|
||||
|
||||
TODO: Fill out the types of parking available, public/private, blackholes, how
|
||||
people pick spots, how seeding works, etc.
|
||||
|
||||
## Infinite parking
|
||||
|
||||
If you pass `--infinite_parking` on the command line, every building gets
|
||||
unlimited public spots. This effectively removes the effects of parking from the
|
||||
model, since driving trips can always begin or end at their precise building
|
||||
(except for blackhole cases). This is useful if a particular map has poor
|
||||
parking data and you need to get comparative results about speeding up some
|
||||
trips. Often the A/B testing is extremely sensitive, because a parking space
|
||||
close to someone's destination is filled up quickly, slowing down the trip.
|
@ -1,150 +0,0 @@
|
||||
# Travel demand
|
||||
|
||||
A/B Street simulates people following a schedule of trips over a day. A single
|
||||
_trip_ 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.
|
||||
|
||||
## Scenarios
|
||||
|
||||
A _scenario_ encodes the people and trips taken over a day. See the
|
||||
[code](https://github.com/dabreegster/abstreet/blob/master/sim/src/make/scenario.rs).
|
||||
|
||||
TODO:
|
||||
|
||||
- talk about vehicle assignment / parked car seeding
|
||||
|
||||
## Data sources
|
||||
|
||||
### Seattle: Soundcast
|
||||
|
||||
Seattle luckily has the Puget Sound Regional Council, which has produced the
|
||||
[Soundcast model](https://www.psrc.org/activity-based-travel-model-soundcast).
|
||||
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
|
||||
[code](https://github.com/dabreegster/abstreet/tree/master/importer/src/soundcast)
|
||||
for importing their data.
|
||||
|
||||
TODO:
|
||||
|
||||
- talk about how trips beginning/ending off-map are handled
|
||||
|
||||
### Berlin
|
||||
|
||||
This work is [ongoing](https://github.com/dabreegster/abstreet/issues/119). See
|
||||
the
|
||||
[code](https://github.com/dabreegster/abstreet/blob/master/importer/src/berlin.rs).
|
||||
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.
|
||||
|
||||
### Proletariat robot
|
||||
|
||||
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 `proletariat_robot`
|
||||
[code](https://github.com/dabreegster/abstreet/blob/master/sim/src/make/activity_model.rs)
|
||||
for an implementation of this.
|
||||
|
||||
This is [ongoing](https://github.com/dabreegster/abstreet/issues/154) 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.
|
||||
|
||||
### Census Based
|
||||
|
||||
Trips are distributed based on where we believe people live. For the US, this
|
||||
information comes from the US Census. To take advantage of this model for areas
|
||||
outside the US, you'll need to add your data to the global `population_areas`
|
||||
file. This is one huge file that is shared across regions. This is more work up
|
||||
front, but makes adding individual cities relatively straight forward.
|
||||
|
||||
#### Preparing the `population_areas` file
|
||||
|
||||
See `popdat/scripts/build_population_areas.sh` for updating or adding to the
|
||||
existing population areas. Once rebuilt, you'll need to upload the file so that
|
||||
popdat can find it.
|
||||
|
||||
### Custom import
|
||||
|
||||
If you have your own data, you can import it. The input format is JSON -- an
|
||||
example:
|
||||
|
||||
```
|
||||
{
|
||||
"scenario_name": "monday",
|
||||
"people": [
|
||||
{
|
||||
"origin": {
|
||||
"Position": {
|
||||
"longitude": -122.303723,
|
||||
"latitude": 47.6372834
|
||||
}
|
||||
},
|
||||
"trips": [
|
||||
{
|
||||
"departure": 10800.0,
|
||||
"destination": {
|
||||
"Position": {
|
||||
"longitude": -122.3075948,
|
||||
"latitude": 47.6394773
|
||||
}
|
||||
},
|
||||
"mode": "Drive"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Run the tool:
|
||||
|
||||
```
|
||||
cargo run --bin import_traffic -- --map=data/system/seattle/maps/montlake.bin --input=/path/to/input.json
|
||||
```
|
||||
|
||||
The tool matches input positions to the nearest building, within 100 meters. If
|
||||
the point lies outside the map boundary, it's snapped to the nearest map border.
|
||||
The `departure` 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.
|
||||
|
||||
## Modifying demand
|
||||
|
||||
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?
|
||||
|
||||
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).
|
||||
|
||||
## Research
|
||||
|
||||
- <https://github.com/replicahq/doppelganger>
|
||||
- <https://github.com/stasmix/popsynth>
|
||||
- <https://zephyrtransport.github.io/zephyr-directory/projects/>
|
||||
- <https://activitysim.github.io>
|
||||
- <https://github.com/BayAreaMetro/travel-model-one>
|
||||
- <https://github.com/RSGInc/DaySim>
|
||||
- <https://github.com/arup-group/pam>
|
||||
- <https://spatial-microsim-book.robinlovelace.net/smsimr.html>
|
||||
- <https://github.com/DLR-VF/TAPAS>
|
||||
- <https://sumo.dlr.de/docs/Demand/Activity-based_Demand_Generation.html>
|
@ -1,146 +0,0 @@
|
||||
# Multi-modal trips
|
||||
|
||||
A single trip consists of a sequence of `TripLegs` -- 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.
|
||||
|
||||
## Walking-only trips
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
|
||||
[*] --> FromBuilding
|
||||
[*] --> FromBorder
|
||||
FromBuilding --> Walk
|
||||
FromBorder --> Walk
|
||||
Walk --> ToBuilding
|
||||
Walk --> ToBorder
|
||||
ToBuilding --> [*]
|
||||
ToBorder --> [*]
|
||||
|
||||
@enduml
|
||||
```
|
||||
|
||||
## Trips starting from a border
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
|
||||
[*] --> FromBorder
|
||||
Walk --> ToBuilding
|
||||
ToBuilding --> [*]
|
||||
ToBorder --> [*]
|
||||
|
||||
FromBorder --> Drive
|
||||
Drive --> ToBorder
|
||||
Drive --> ParkSomewhere
|
||||
ParkSomewhere --> Walk
|
||||
|
||||
FromBorder --> Bike
|
||||
Bike --> ToBorder
|
||||
Bike --> ParkSomewhere
|
||||
|
||||
FromBorder --> RideBus
|
||||
RideBus --> ToBorder
|
||||
RideBus --> AlightAtStop
|
||||
AlightAtStop --> Walk
|
||||
|
||||
@enduml
|
||||
```
|
||||
|
||||
## Trips starting from a building
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
|
||||
[*] --> FromBuilding
|
||||
FromBuilding --> Walk1
|
||||
|
||||
Walk1 --> ToParkedCar
|
||||
ToParkedCar --> Drive
|
||||
Drive --> ToBorder
|
||||
Drive --> ParkSomewhere
|
||||
ParkSomewhere --> Walk2
|
||||
Walk2 --> ToBuilding
|
||||
|
||||
Walk1 --> ToBike
|
||||
ToBike --> Bike
|
||||
Bike --> ToBorder
|
||||
Bike --> ParkSomewhere
|
||||
|
||||
Walk1 --> ToBusStop1
|
||||
ToBusStop1 --> WaitForBus
|
||||
WaitForBus --> RideBus
|
||||
RideBus --> ToBorder
|
||||
RideBus --> ToBusStop2
|
||||
ToBusStop2 --> Walk2
|
||||
|
||||
ToBuilding --> [*]
|
||||
ToBorder --> [*]
|
||||
|
||||
@enduml
|
||||
```
|
||||
|
||||
## Spawning code overview
|
||||
|
||||
As of January 2021, starting a traffic simulation works like this:
|
||||
|
||||
1. Something creates a `Scenario`, which defines a bunch of people. Each person
|
||||
has a schedule of trips, carrying them between `TripEndpoints` via some
|
||||
`TripMode`, leaving at some `Time`.
|
||||
2. When a scenario is instantiated, not much happens besides scheduling the trip
|
||||
to start at the appropriate time and filling out `TripInfo` in `TripManager`.
|
||||
Some state in `StartTripArgs` has to be plumbed forward in the
|
||||
`Command::StartTrip`.
|
||||
3. When the command gets run later, `TripManager::start_trip` happens. The
|
||||
origin, destination, and mode flow through `TripSpec::maybe_new`.
|
||||
4. `TripSpec::to_plan` further validates these and attempts to repair impossible
|
||||
plans. Each `TripSpec` is turned into a list of `TripLegs`.
|
||||
5. Each `TripSpec` has its own initialization logic to kick off the first leg of
|
||||
the trip.
|
||||
6. Most trips have multiple legs. When the first car, bike, or pedestrian
|
||||
reaches their goal, `TripManager` gets called with some sort of transition
|
||||
function to initiate the next leg of the trip, or declare the trip finished.
|
||||
These transition functions also record stats from that leg of the trip, like
|
||||
total blocked time.
|
||||
|
||||
What're the different `TripSpec` cases, and what `TripLegs` do they get turned
|
||||
into?
|
||||
|
||||
- `VehicleAppearing`: Starts at a border. Drive, then maybe walk to the
|
||||
destination building.
|
||||
- `SpawningFailure`: No trip legs; just create and immediately cancel the trip.
|
||||
- `UsingParkedCar`: Starts at a building. Walk (to the parked car), drive, then
|
||||
maybe walk to the destination building (after parking again).
|
||||
- `JustWalking`: Just walk between two buildings/borders.
|
||||
- `UsingBike`: Starts at a building. Walk to the nearest bikeable lane, drive,
|
||||
then maybe walk to the destination building. (Note that starting a bike from a
|
||||
border uses `VehicleAppearing`.)
|
||||
- `UsingTransit`: Walk, ride the bus, maybe walk again. No transfers yet; only
|
||||
rides one bus between two stops.
|
||||
|
||||
`TripManager` has a whole bunch of transition functions:
|
||||
|
||||
- `car_reached_parking_spot`: drive -> walk, unless the destination building is
|
||||
where we parked
|
||||
- `ped_reached_parking_spot`: walk -> drive
|
||||
- `ped_ready_to_bike`: walk -> bike
|
||||
- `bike_reached_end`: bike -> walk
|
||||
- `ped_reached_building`: walk -> done
|
||||
- `ped_reached_bus_stop`: walk -> wait or ride bus
|
||||
- `ped_boarded_bus`: waiting -> ride bus
|
||||
- `person_left_bus`: riding bus -> walk
|
||||
- `ped_reached_border`: walk -> done
|
||||
- `transit_rider_reached_border`: ride bus -> done
|
||||
- `car_or_bike_reached_border`: drive -> done
|
||||
|
||||
There are at least a few use cases motivating the cleanup of all of this
|
||||
structure:
|
||||
|
||||
- Capping trips through congested areas. Sometimes this just changes the driving
|
||||
route, but sometimes it needs to cancel trips, convert driving trips to
|
||||
walking/transit, or delay the trip's start.
|
||||
- Multiple public transit rides in a single trip, aka transferring
|
||||
- Handling live map edits in the middle of a trip
|
@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
~/npm/node_modules/prettier/bin-prettier.js --write --prose-wrap=always $1
|
||||
|
||||
# Format everything:
|
||||
# for x in `find book/src/ | grep '\.md'`; do ./format_md.sh $x; done; git checkout book/src/project/CHANGELOG.md
|
@ -30,7 +30,8 @@ esac
|
||||
|
||||
mkdir $output
|
||||
|
||||
cp book/src/howto/README.md $output/INSTRUCTIONS.txt
|
||||
# TODO Probably need to have a simpler copy of the README here.
|
||||
#cp book/src/howto/README.md $output/INSTRUCTIONS.txt
|
||||
cp release/$runner $output
|
||||
|
||||
# Put most binaries in the root directory, but hide game to encourage people to
|
||||
|
@ -12,11 +12,13 @@ if [ "$OLD_PATCH" == "" ] || [ "$NEW_PATCH" == "" ]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
perl -pi -e "s/${MAJOR}_${MINOR}_${OLD_PATCH}/${MAJOR}_${MINOR}_${NEW_PATCH}/g" README.md book/src/howto/README.md book/src/side_projects/santa.md
|
||||
perl -pi -e "s/${MAJOR}\.${MINOR}\.${OLD_PATCH}/${MAJOR}\.${MINOR}\.${NEW_PATCH}/g" README.md book/src/howto/README.md book/src/side_projects/santa.md
|
||||
# This assumes https://github.com/a-b-street/docs is checked out at ~/docs
|
||||
perl -pi -e "s/${MAJOR}_${MINOR}_${OLD_PATCH}/${MAJOR}_${MINOR}_${NEW_PATCH}/g" README.md ~/docs/book/src/howto/README.md ~/docs/book/src/side_projects/santa.md
|
||||
perl -pi -e "s/${MAJOR}\.${MINOR}\.${OLD_PATCH}/${MAJOR}\.${MINOR}\.${NEW_PATCH}/g" README.md ~/docs/book/src/howto/README.md ~/docs/book/src/side_projects/santa.md
|
||||
|
||||
echo "Don't forget to:"
|
||||
echo "1) aws s3 cp --recursive s3://abstreet/dev/data/system s3://abstreet/${MAJOR}.${MINOR}.${NEW_PATCH}/data/system"
|
||||
echo "2) ./release/deploy_web.sh"
|
||||
echo "3) Post to r/abstreet"
|
||||
echo "4) Update map_gui/src/tools/updater.rs"
|
||||
echo "5) Push the docs repo too"
|
||||
|
Before Width: | Height: | Size: 2.4 MiB After Width: | Height: | Size: 2.4 MiB |
Before Width: | Height: | Size: 2.5 MiB After Width: | Height: | Size: 2.5 MiB |
Before Width: | Height: | Size: 13 MiB After Width: | Height: | Size: 13 MiB |