a-b-street / abstreet

Transportation planning and traffic simulation software for creating cities friendlier to walking, biking, and public transit
https://a-b-street.github.io/docs/
Apache License 2.0
7.66k stars 340 forks source link

Mode shift #448

Open dabreegster opened 3 years ago

dabreegster commented 3 years ago

Quoting some docs: 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?

Here's a strawman proposal for how this could work: after the player edits the map, re-evaluate every trip in the scenario. Calculate a cost for driving/walking/transit/biking for each one. Change the mode specified by the input to the best choice.

Thinking a little about UX of switching modes.

dabreegster commented 3 years ago

https://github.com/byu-transpolab/modechoice https://www.ce.utexas.edu/prof/bhat/COURSES/LM_Draft_060131Final-060630.pdf

dabreegster commented 3 years ago

screencast Here's a new toy. Access it by launching a scenario, opening the dashboard, then selecting "mode shift" from the top-left dropdown.

This looks for all driving trips in the map and shows the expected time to drive vs bike. Also shows the distance and elevation gain/loss of the trip. You can filter by different things and count the number of matching trips. So it's a super rudimentary interactive PCT-ish query. These're good candidate trips that could be swayed to cycle. Maybe a next step would be to figure out what kind of infrastructure changes (better signal timing, more protected cycle lanes along the route) would convince the person to switch.

@Robinlovelace Any feedback on this approach? Anything you'd like to see in this kind of dashboard? Handing you a blank cheque here. ;)

Robinlovelace commented 3 years ago

This looks great, a solid basis for implementing mode shift models in A/B Street by the looks of it! Wish list for things I'd like to see:

There may well be some lower hanging fruit. Good news is: there's lots of literature on mode shift and much of it revolves around logit models. Not so great news: not much of the research is reproducible or based on open code.

Here are some figures showing the concepts of distance decay and hilliness decay in action.

image

image

dabreegster commented 3 years ago

Ideas from a call with Michael & Robin:

dabreegster commented 3 years ago

Alright, starting to put a few things together... Screenshot from 2021-07-26 10-50-34 Screenshot from 2021-07-26 10-48-41 They're not easy to see in this initial view, but the maps have a heatmap of roads. Based on the current filters that find short driving trips, we calculate what route that trip might take if it biked instead. Then we look at all road segments those routes cross, filter for high-stress roads (the definition of this is extremely preliminary), and count the most popular segments. So this is kind of PCTish. We look for trips that're good candidate to shift onto cycling, then look for reasons why the direct cycling route might be scary, and find the most common problem areas. It's a really quick+interactive way to focus attention on certain roads.

Robinlovelace commented 3 years ago

Very good being able to link trips filtered by length and mode to the map.

michaelkirk commented 3 years ago

filter for high-stress roads (the definition of this is extremely preliminary)

If you wanted to leverage the work of others in this department, there exists: https://bna.peopleforbikes.org/#/places/0ea909ec-0b15-4bae-b593-a40da8a72312/

e.g. here's seattle low vs high stress streets:

Screen Shot 2021-07-26 at 5 07 27 PM

They have many cities and towns in the US (including Seattle), and a handful of international cities. It looks like their scoring logic is also based on OSM tagging and census data.

Also, I came across their nice bike-centric OSM tagging guide: https://docs.google.com/document/d/1HuAXQUnCEcv9aLZyIDHkLTJ5ZSKfB-U4MlJSmN-1BLk/edit

The BNA score seems to come from this repository: https://github.com/azavea/pfb-network-connectivity

After a cursory review, I think the analysis is primarily driven from here(?): https://github.com/azavea/pfb-network-connectivity/blob/develop/src/analysis/scripts/run_analysis.sh

and largely driven by a string of SQL mutations: https://github.com/azavea/pfb-network-connectivity/tree/develop/src/analysis/stress

If not literally using their results, it might be worth checking some of their methods, e.g. in https://github.com/azavea/pfb-network-connectivity/blob/develop/src/analysis/stress/stress_tertiary_ints.sql#L14

dabreegster commented 3 years ago

I absolutely want to avoid reinventing the wheel on defining high-stress. Thank you for the detailed links! I'll figure out tradeoffs between importing their data separately vs trying to replicate their classifier. (An argument for the latter being: the user will probably be changing roads to make things less stressful)

dabreegster commented 3 years ago

https://osmus.slack.com/archives/C2VJAJCS0/p1630599064085200 Discussion of tagging levels of traffic stress in OSM directly

Robinlovelace commented 3 years ago

That sounds good to me. Couldn't see the Slack (do I need to join the group?) but interested in the idea. After chatting with Martin about tagging 'LTN' I tentatively agree with the 'keep it objective' approach, unless there is a very clear definition of traffic stress, including things like surface quality that may not be captured in OSM. Stress is key to prioritising effort where it's most needed though and likely levels of use so great to see more potential data sources on it.

dabreegster commented 3 years ago

Try https://osmus-slack.herokuapp.com/ to join the Slack. Luckily it's public and has permanent archiving (afaict), but you do need to sign up. :(

Note that tagging level of cycling stress is different than tagging an LTN, but they're definitely related.

dabreegster commented 3 years ago

I'm going to take some more steps on this, but in the context of the bike network tool for #743. The end goal is to predict which trips from an input scenario will switch from driving to biking due to the user's proposed map edits.

The "differential" approach needs to avoid the "spurious" changes mentioned in the original message of this issue. So on an unedited map, given the chosen parameters for distance/time/elevation thresholds, calculate which trips would switch "baseline." Then after edits, repeat, and see how many more trips match.

But... I'm not sure this makes sense. If all those trips would have switched without the user's edits, why hasn't that happened yet? One of the main barriers from the real human perspective is safety. So I think we can "score" the user's network by running mode shift and seeing how many trips will make use of new infrastructure. In other words, take the existing "find the most important gaps" layer, and just overlay that with the proposed network.

So some concrete steps to get there, as a gift to my less clear-headed future self in the morning: 1) Add a 4th tab to the ungap tool. Put the 4 thresholds as the "input" parameters there. On the map, show the most important gaps by default. Figure out what to cache and where. Evaluate the gaps against the unedited map, always! 2) Hover on a road segment to see the number of potential trips that would switch -- and maybe not just number, but total distance of those trips? 2) Add a button to open up the table of individual trips. Clicking will switch to the individual route tool. 3) Add some kind of "score", the number of trips that would switch, further filtered by those whose route leads through improved infrastructure.

Then more speculative steps:

dabreegster commented 3 years ago

Alright, some progress: Screenshot from 2021-09-20 17-47-46

This new page works as follows: 0) Start with an existing travel demand model, which predicts the trips people take daily, and the mode they use. 1) Search for all driving trips which might consider biking instead. There are filters to select maximum time, distance, and elevation gain for the potential biking trip. As a possible next step, this could use a decay function instead of being a hard cut-off. 2) For all of those trips, calculate the path they would take if biking, assuming no major preferences to avoid hills or stressful roads. (I'm considering changing this to avoid hills, or making it configurable.) 3) Count the number of these potential biking trips that pass through every segment of a high-stress road. That's the red heatmap; tooltips show exact counts. 4) Then, based on the current proposed bike network extensions, decide if each potential trip would be positively impacted by the new bike lanes. For now that's just a simple test -- does the path make use of at least 1 new bike lane on a previously stressful road? 5) That's our guess for which driving trips will convert to biking, if this new infrastructure is built. From that, we can sum up the total mileage of the driving trip that we're converting, and calculate the annual CO2 savings, assuming a simple 404 grams per mile and assuming these trips happen 5 times a week, 52 weeks a year.

I took a video showing the end-to-end workflow of the tool so far, but the GIF is too big for github; I'll record a youtube video talking through it later. But the gist is this: 1) Use the explore mode to just understand the city's current bike network. There are layers to explore elevation. Ideally I'll have time to add a layer showing historic collision data. 2) Use the route tool to draw a particular route from A to B -- like my commute to work, for example. See what the biking route probably looks like, and score how much it's forced to use high-stress roads. Adjust preferences to avoid those stressful roads or to avoid hills, and see the trade-offs between the two. 3) Armed with that knowledge, use the quick-sketch tool to expand the bike network. 4) Return to the "individual test cases" in the routing tool. The user can add protected infrastructure along the ideal, flat route that they want to use. 5) But now, the user can also evaluate their changes against a large set of "test cases" and see how many people might be convinced to stop driving, and the subsequent CO2 savings. There are many assumptions that go into that calculation, but the UI lets the user tune those parameters.

Robinlovelace commented 3 years ago

This looks like a really useful development. The approach sounds sensible. Looking forward to giving it a spin!

dabreegster commented 2 years ago

Screenshot from 2021-10-06 12-15-38 This is where we're at. The 3 colored bars work as a kind of "funnel". 1) The first shows all the driving trips in the area 2) After you specify the max time and hills somebody's willing to bike, we filter down and show how many of those trips would switch if stuff was safer 3) After you make map edits, the third further filters that down to the trips who cross at least one improved section

I'm about to add another filter, either "what percentage of someone's trip has to be on low-stress roads for them to switch?" or "what's the total distance someone's willing to spend on their trip on high-stress roads?" (where they might choose to gingerly walk their bike on a sidewalk or something else). That'll further restrict the 3rd colored bar.

My question is, should we express that new safety requirements filter as a new thing in the third box? Or should it be part of the other 2 filters? If the latter, do we even need this 3-step funnel view? We could just have one bar, showing the total driving trips in the area, then the final results based on all the filters. Originally splitting it up was meant to show gradual barriers to mode shift (first just intrinsic to the geography, then based on stuff that could be fixed with new infra). But if all the filters are slideable, then the user can explore this themselves.

Robinlovelace commented 2 years ago

I think would great for the user to be able to explore different scenarios of behaviour (e.g. max % people willing to cycle, which could be cultural and slow to change) and willingness to cycle on busy infrastructure. 2D plots showing 'distance decay', 'hilliness decay', 'business decay' and other variables could help people understand what moving these slides does, perhaps by moving things inside a 2D plotting window. Sketchy idea below, thinking you could represent each of those variables (max elevation gain, max distance) inside the graph and have linear or curved 'ramp up' and 'ramp down' lines showing that it's not about hard limits but %s dropping...

image

Robinlovelace commented 2 years ago

The thing is that the links between the different factors are not yet know. I'm confident that for distance the 5 slides enable the user to capture most possible variability, e.g. by shifting max distance (and right plateau) vertical dotted lines right to represent E-Bike adoption. Interactive sketch: https://excalidraw.com/#room=11d6a02f5445a16de228,DadvVTIbaYcHi4tsQG86KQ

Robinlovelace commented 2 years ago

(In the above plots Distance could be switched for Time and the curves would be similar, I think time is more realistic but distance is easier to model due to high variability of cycling speeds.)

dabreegster commented 2 years ago

moving things inside a 2D plotting window

I need to think about this a little more to guess how hard it'd be to implement. I think it's possibly not so bad. Plenty of ideas about requirements in this thread...

The thing is that the links between the different factors are not yet know.

My probability knowledge is super fuzzy right now. Would it be reasonable to start by assuming these 3 factors are independent, so we could multiply the probabilities? The logic would be something like:

for each candidate trip:
  calculate hilliness, distance, and stress
  p1 = plug hilliness into the appropriate plot
  p2 = ... distance
  p3 = ... stress
  final_probability = p1 * p2 * p3
  if random coinflip, weighted by final_probability is true:
    this trip will mode-shift
Robinlovelace commented 2 years ago

Yes, that's reasonable. An actual working function, published in the R package pct, that calculates probability of cycling if citizens switch to Dutch likelihood of cycling is as follows:

uptake_pct_godutch = function(distance,
                              gradient,
                              alpha = -3.959 + 2.523,
                              d1 = -0.5963 - 0.07626,
                              d2 = 1.866,
                              d3 = 0.008050,
                              h1 = -0.2710,
                              i1 = 0.009394,
                              i2 = -0.05135,
                              verbose = FALSE) {
  distance_gradient = check_distance_gradient(distance, gradient, verbose)
  distance = distance_gradient$distance
  gradient = distance_gradient$gradient
  logit_pcycle = alpha + (d1 * distance) +
    (d2 * sqrt(distance)) + (d3 * distance ^ 2) +
    (h1 * gradient) +
    (i1 * distance * gradient) +
    (i2 * sqrt(distance) * gradient)
  boot::inv.logit(logit_pcycle)
}

I don't actually like that function - too complex - functional forms based on the Beta distribution are neater and require fewer parameters, but the point is many different functions can be used. I think keeping it simple as you suggest is the way forward.

Robinlovelace commented 2 years ago

Discussing this with Fred, Lucas and others today.