[Import proposal] SFMTA parking time limits in San Francisco

Introduction

Hello Bay Area and US OSM communities. I’m proposing a one-time automated import of signed maximum-stay parking rules from SFMTA’s Map of Parking Regulations dataset.

SF currently has very little parking tag coverage, beyond occasional yes/no tags. Meanwhile SFMTA manages a few rich curb datasets that would see more compounding usability incorporated into OSM. The goal is to add useful curb rules to existing OSM streets while preserving mapper work and rejecting anything that cannot be matched confidently. I would use the dedicated import account sfcurbmapper_Import.

Documentation

The OSM Wiki import plan documents the tagging, conflation, splitting, relation handling, QA, rollback, and opt-out process. The source is SFMTA’s Map of Parking Regulations.

The code and dated review materials contain the SFMTA and OSM data downloaded on August 5, the exact download queries, detailed matching and proposed-tag results for all 5,978 candidates, a summary validation report, and the individual pilot decisions. File fingerprints are included so reviewers can verify that the downloads have not changed.

The repository provides an OSM-format sample of the proposed 48-record pilot. Each production batch would be generated from current OSM data immediately before upload. The interactive pilot map lets reviewers inspect the source curb, receiving interval, OSM-relative side and direction, proposed tags, split points, and parent relations. My main OSM profile is sfcurbmapper.

License

The DataSF source is published under the Open Data Commons Public Domain Dedication and License 1.0. I have checked that it can be used in OpenStreetMap under the ODbL.

Abstract

The import covers only SFMTA records classified as Time limited. It adds side-specific fee=no, maximum-stay rules, and, where applicable, RPP zones with no @ permit_holder. It adds no road geometry or physical parking attributes, never overwrites conflicting OSM parking tags, and excludes target sides where OSM says parking is unavailable or separately mapped.

Source intervals are conservatively matched to existing OSM streets. Ambiguous records are rejected, and partial-way edits use relation-aware splits that preserve existing nodes. All production output would be regenerated from current OSM data before upload.

The frozen review contains 5,978 candidates and a geographically distributed 48-record pilot, all of which I reviewed locally. After at least 14 days of community review, I would refresh and recheck the data, upload and inspect the pilot, and proceed with compact batches only if no systematic problem appears.

Hey there, nice work! This seems like a very thoroughly documented and well-motivated import, and as a San Francisco native it’d be cool to have this data in OSM. The interactive pilot is especially nice! I have a couple of comments.

  • I think it’s somewhere in your github project, but it’d be nice for a list of the exact data fields you use from the import source and which OSM tags they are translated into to be on your wiki page.

  • I notice in the interactive pilot you propose quite aggressive road splitting to match the curbs: the roads are proposed to be split basically at least twice at any intersection, and more times if the edges of the parking areas are offset, like by daylighting. I suppose this is technically correct: you can’t park in the middle of an intersection. But this comes at a cost: highly split roads are harder to work with for other users. OSM is fundamentally an abstraction, and I wonder if this is taking the parking restrictions a little too literally. You also don’t seem to have plans to map the corresponding no parking regulations in the middle of intersections, which I think will make it unclear to future users why the roads were split at all. Have you looked at other places with well-mapped parking, and is this approach common? Here’s an example of what I mean:

This appears to propose splitting Golden Gate Ave essentially a few meters short of both ends of the block. If I were mapping it, I’d probably just tag the whole block with the parking restriction, but I’m not really a parking tagging wizard. Also, at this level I kind of doubt the accuracy of the imported data, it seems like it’s just present on a block-by-block basis. Have you verified that the data is of sufficient on-the-ground accuracy to justify so much splitting?

1 Like

I would agree on that. Parking restriction from/up to an intersection I would end at the intersection-node and I would only split it in case there is a significant offset. I would also continue it across blocks, if there is no difference.

1 Like

Thanks for the detailed feedback!

Tag Mapping

I’ve added the detailed tag mapping plan to the wiki here as requested.

Intersection Splits

Regarding the concern about the near-intersection splits, it seems like there are two subpoints:

  • The precision of the source SFMTA dataset, ie. whether it has enough precision at the intersection to justify splitting the corresponding OSM ways to match.
  • To what granularity curbs or parking restrictions ought to be mapped in the first place, especially as it pertains to intersections.

Source Geometry Precision

For the source geometry precision, I investigated more closely, including measuring all eight incoming curb endpoints at several ordinary four-way intersections.

It turns out endpoints are not arbitrary fixed offsets from the intersection. SFMTA maintains a separate Blockfaces dataset, described as curb-line geography created using manual drawing, street-centerline offsets, and a blockface-generation tool. Its underlying SFMTA curb layer distinguishes straight blockface segments from separately modeled intersection curb returns.

The time-limit geometries here closely follow those straight blockfaces. At Green Street and Baker Street, for example, all eight time-limit endpoints were within approximately 0.2–0.8 m of the corresponding current SFMTA blockface endpoints. I found the same pattern at 22nd Street/Chattanooga Street, 19th Street/Mississippi Street, and Howth Street/Niagara Avenue, generally within about 1 m.

Across 400 ordinary four-way intersections where all eight source endpoints could be identified:

  • The median endpoint distance from the OSM intersection center was 11.15 m.
  • The median full gap between opposing blockfaces was 22.04 m.
  • The endpoints moved outward as the crossing street became wider.
  • The two curb endpoints on the same approach were usually closely aligned.

The gaps therefore appear to represent the physical intersection and corner/curb-return geometry excluded from SFMTA’s straight blockface model. They are not just a constant buffer added to every intersection.

Based on that, I am leaning toward retaining the source-supported blockface boundaries rather than snapping every endpoint to the OSM junction node. Snapping would extend a positive SFMTA time-limit rule into an area that the source deliberately excludes from the blockface. For granular curb applications, such as estimating parking lost to a bike lane or identifying a valid robotaxi pickup location, I would prefer not to make the imported rule look spatially broader than the source supports.

You make a good point about marking parking=no on intersections to coherently explain the inclusion of these splits. I think that makes a lot of sense in most cases, but I’d like to handle that as a separate task ideally. Although the gap generally contains intersection, crosswalk, and curved-corner space where parking is unavailable, this dataset does not distinguish the exact reason or legal boundary. Some restrictions arise from the intersection itself; others may involve crosswalks, daylighting, red curbs, curb extensions, driveways, hydrants, or other features.

I would instead treat explicit intersection and other short no-parking intervals as a follow-up curb-mapping project. SFMTA has described a broader Digital Curb Program, which may eventually provide a better basis for importing more complete curb-use information. I was informed that this is launching publicly in the next few months, and would provide a rich source of granular data for import. So followup imports could address intersection restrictions together with daylighting, driveways, hydrants, color curbs, loading zones, and other granular curb uses.

Weighing Pros/Cons, Precedent for Granular Way Splitting

There is precedent in OSM for this level of parking detail, though there doesn’t appear to be a clear consensus. For most cities, there is very little curb rule coverage, yet alone granular coverage (There’s some feedback loop between little OSM curb consumption by applications and little motivation for curb mapping. Culturally it seems like curb mapping is less emphasized relative to other features, and the tooling/syntax is not the best for it at this time. But this can be discussed separately.) The street-parking documentation allows roadways to be split where parking properties change, while noting that short implicit restrictions may alternatively be derived by data consumers. So we have two potential approaches. For one example of granular mapping of even implicit restrictions, see Berlin, one of the cities with the most OSM curb rule coverage. Berlin has extensive granular parking mapping and an open methodology for deriving usable parking segments after subtracting junction clearances, bus stops, driveways, street furniture, and similar obstacles:

Berlin also contains explicitly mapped short junction restrictions, for example:

Personally, I’ve also done some manual mapping of Santa Rosa, CA on the ground with this level of granularity:

This does impose a maintenance cost through additional way segments. I think that tradeoff is justified where the boundaries come from meaningful curb geometry and the splitting is done safely. Ultimately better tooling does become necessary as splits increase in the long term. But shying away from this leads to other proprietary platforms capturing most of the granular rules/inferences necessary to reason about the curb. The current import is careful to preserve all existing relations when performing the split (eg. bus routes, turn restrictions).

So the proposed treatment is intentionally asymmetric: preserve the positively supported time-limit interval now, do not extend it across the intersection, and do not yet infer the complementary parking=no geometry. Explicit, granular no-parking mapping would follow when suitable curb and restriction sources can support it.

If this is not amenable to the community, I can try and infer an extension of parking rules across intersections to avoid the split. However, this introduces the risk of making wrong inferences and accidentally extending across intentional gaps in the dataset. There are some unmapped zones near intersections such as this one on Hayes St where parking is explicitly disallowed (confirmed by checking on the ground), and we’d want to be careful not to extend the blockface incorrectly there.

If these inferences were made, it would also require potential cleanup in the future if we do want to go ahead and include granular intersection zones.

I would be in favor of conservatively sticking to snapping the existing SFMTA dataset near intersections as is, and later mapping explicit no parking zones at intersections and other areas based on other granular data. This introduces the least accuracy risk right now and leaves the door open to further granular mapping, albeit at the cost of more splits.

I appreciate any further feedback! It’s worthwhile to get curb conventions right.

It’s not only the maintenance cost of additional segments. It’s also keeping track of where the parking actually starts. If you add that level of detail, there should also be the intention to maintain the accuracy over the time. Otherwise the result is higher overall maintenance and “wrong” data. Kind of a worse-worse-situation.

In your Hayes St example, I would only split the way at the left red dot, but not at the right one.

1 Like

I asked whether these datapoints are sufficiently on-the-ground accurate to be worth splitting in OSM, not how they compare to other SF Gov datasets, which I assume have the same source anyway. Based on the screenshot you provide, it seems to me like they aren’t sufficiently accurate: it looks like you propose splitting Hayes St in the middle of the crosswalk, but the curb is red for maybe a few feet onwards past it per Bing Streetside imagery:

But maybe the imagery in your screenshot is just poorly aligned, I don’t know where it’s from.

I am also very dubious of the idea that (a) importing very detailed splitting of ways due to parking restrictions but not filling in the actual parking restrictions makes much sense and (b) this is the “conservative approach”. The conservative approach is to regularize the data to defer to OSM geometries. As the comment above also mentions, OSM unfortunately has a long history of incomplete imports that lead to a huge burden on mappers over time to clean them up, and we want to make sure this isn’t one of those cases. I would prefer an approach where these data are imported on a coarser basis, maybe on a block level but excluding long exclusion zones like the bus stops you mention, with further meter-level curb refinements when that full dataset is available and verified to be sufficiently accurate for an OSM import.

I also note that the (very interesting) Berlin analysis you provide doesn’t really support your approach IMO:

Signposted parking and stopping restrictions were taken into account, as were other parking conditions of “significant” length, even if they only affect a 15-metre road segment, for example. Some mappers might shudder at the prospect of this level of micro-mapping – but such precise data can be extremely valuable, and not just for a project like this.

However, in most cases it is not even necessary to break up roads into many small segments, as the relevant information can be derived from other objects in the space if they are well mapped: For example, it is clear that parking is not allowed on a zebra crossing, in front of a bus stop or near a pedestrian traffic light.

Maybe 15m is a good rule of thumb for a minimum length of restriction you should intend to capture with this import, as I think it fits the accuracy of the original data best.

The idea mentioned above, actually mapping the intersection space as no parking rather than leaving it inexplicably blank, seems coherent, so I would like to revise the proposal around that approach.

The SFMTA time-limit geometries follow its straight blockfaces, while the gaps correspond to the separately modeled intersection and curb-return space. I would retain those blockface boundaries, apply the time-limit rules to the mapped blockfaces, and explicitly tag the intervening intersection segments as unavailable for parking.

The tagging would likely be along these lines, adjusted for each side:

parking:<side>=no
parking:<side>:restriction=no_stopping
parking:<side>:restriction:reason=junction

California law prohibits stopping, standing, or parking within intersections and on crosswalks. Daylighting would be mapped separately later with an appropriate daylighting or crossing reason, rather than being folded into the junction reason.

To clarify my earlier comparison between the SFMTA datasets: my intention was to verify that these gaps were intentional features of the same curb/blockface model rather than arbitrary offsets introduced during this import. The comparison supports that conclusion. The blockface endpoints are not intended to correspond specifically to the end of a painted red curb or the edge of a crosswalk; they mark the transition between SFMTA’s straight blockface and its separately modeled curb-return/intersection space.

The Hayes example illustrates the remaining limitation. This import would map the blockface-level time-limit rule and the intervening intersection space. It would not yet capture every smaller variation along that blockface, such as the precise limits of red curbs, crosswalks, daylighted approaches, driveways, hydrants, or curb cuts. Those refinements are intended as follow-up curb mapping. But because the intersection space is already implicitly identifiable from the gaps in this source geometry, it seems useful and coherent to begin by mapping that space as no parking now.

The Berlin parking analysis appears to show mixed implementation rather than one universal convention. It explains that many short restrictions can be derived from other mapped objects as you note, but in practice Berlin also explicitly maps some intersection segments, for example Rochstraße and Max-Beer-Straße, both using parking:both=no with parking:both:reason=junction. That suggests both approaches coexist, depending on how explicitly the local parking environment is being mapped.

I agree with the maintenance concern as well. The intention is to maintain and refine this information over time, including incorporating mapper corrections and, when suitable source data becomes available, adding the more granular curb restrictions described above. Complicated intersections such as roundabouts and unusual merges would be excluded from the automated treatment or reviewed separately.

This changes the proposed output materially, so I would update the implementation and review map and bring the revised result back here before uploading anything.

How does that approach sound?

We very often elide minor changes approaching an intersection. For example, when a divided road’s median ends in favor of a left turn lane approaching an intersection, we relax the physical separation rule and map the intersection as a # shape, continuing the parallel ways all the way through.

I guess the question is whether we really need the parking tags on the roadways to be so precise if we’re going to import the blockface geometries anyways. Does the city publish geometries of on-street parking stalls or enough information to reconstruct those geometries? If so, what if we tag the streets with parking:both=separate in favor of mapping amenity=parking areas and barrier=kerb ways, reducing the need for splitting?

1 Like

This is an interesting counterpoint. I suppose you have to look at the value of the granularity as opposed to aesthetics, convenience, maintenance, etc. For parking in dense cities specifically, in the long-run, if intersections and daylighting zones were elided, you often end up with a very different number of available parking spots estimated.

Unfortunately this granularity of data does not seem to be available from my research. Even the city’s future efforts seek to map curb intervals linearly. I don’t see any dataset that presents the parking area polygons as such, and don’t see that forthcoming.

If there had been a convention of mapping parking linearly but separate from the roadway centerline, that could have been an interesting approach to support granular mapping without interfering with other usecases. However, amenity=parking is only attached to areas and not lines/ways, and barrier=kerb does not take on parking restrictions itself.

I’ve been lurking and may have missed something. In cases where sidewalks are mapped as separate ways (or after adding such separate ways), would it make sense to consider adding on-street parking as separate ways between the street and the sidewalk? This would avoid complicating the existing ways and would not interfere with intersections, driveways, dropped curbs, etc.; and the maintenance issue for detailed parking restrictions would be left up to the people who are interested in it.

But the intersection space is not implicit. That Hayes St example itself illustrates that other no parking zones (like bus stops) are folded in to this dataset as well, and that the actual boundaries of the parking zones are not sufficiently precise. Based on what you’ve provided, I remain opposed to introducing artificially precise way splitting for parking zones in this import when it is not merited by the source data accuracy.

1 Like

Are the spaces generally marked individually? I usually see cities in the Bay Area take that option instead of relying on drivers to assemble in a dense pattern organically. If so, you could have a separate phase of the import that manually tags the parking areas with their capacities based on the markings.

That would be reminiscent of a 2019 proposal by SharedStreets to map curb restrictions as nodes at the locations of the traffic signs, so that data consumers would perform linear referencing to infer the affected street segments. Instead, we ended up formalizing the practice of micromapping the stalls as areas.

1 Like