Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Geofencing, virtual station, and dockless support #175

Closed
wants to merge 5 commits into from

Conversation

antrim
Copy link
Contributor

@antrim antrim commented Sep 26, 2019

This pull request is to discuss a proposal (Google Doc) -- v2, revised Oct 30 to add support for dockless, geofencing, and virtual stations. Please make comments in this thread or directly in the Google Doc. Once we have arrived at a proposal that is an implementation candidate (at least one producer and consumer say they plan to implement), then @MobilityData will edit the final proposal text and commit it to this pull request.

Proposal summary

This proposal extends GBFS (General Bikesharing Feed Spec) to add support for:

  • Dockless systems: free standing vehicles (e.g. bicycles, e-bikes, scooters) that can be rented on the street, outside the bounds of a physical station.
  • Virtual stations where vehicles can be deposited or retrieved from a bounded area, but no physical dock infrastructure is installed.
  • Geofenced areas with rules for allowed and disallowed travel and speeds.

The specific changes are:

  • Add geofencing_zones.json (as a GeoJSON FeatureCollection) to define geofencing zones and allowed and disallowed travel.
  • Extend station_information.json to allow description of the area of a virtual station.
  • Revise station_information.json to describe stations with unlimited capacity.

An earlier version of the proposal, v1 (Google Doc) included additional elements (discarded because there were no interested implementers):

  • Extend the proposed vehicle_types.json (PR Add vehicle type definitions #136) to declare whether a vehicle can be left in a dock or freestanding or both.
  • Extend system_hours.json to describe hours during which actions specified in geofencing_zone_information.json can occur.

This branch and associated pull request is to discuss (a proposal)[https://docs.google.com/document/d/1po4tlv5p7jXB6KQYohLAIS0qKJfxI1e-EH3JjiyUWoc/edit] to add support for dockless, geofencing, and virtual stations.
@antrim
Copy link
Contributor Author

antrim commented Oct 9, 2019

I made the following modifications to the linked Google Doc:

  • Revise station_information.json to describe stations with unlimited capacity.
  • Extend the proposed vehicle_types.json (PR Add vehicle type definitions #136) to declare whether a vehicle can be left in a dock or freestanding or both.
  • Removed the extensions to system_hours.json.

@antrim
Copy link
Contributor Author

antrim commented Oct 10, 2019

#89 Discusses cases where station docks fill and then an area around the station becomes available for returns (overflow). As of today, I believe this proposal could serve that case in this way:

When overflow is allowed, an element in station_information.json would include the following attributes:

  • station_area: Defined (GeoJSON)
  • is_virtual_station: 1
  • capacity: "" [Meaning: unlimited]

Would this serve the use case fully or do we need to modify/clarify the current proposal?

@evansiroky
Copy link
Contributor

evansiroky commented Oct 11, 2019

#89 Discusses cases where station docks fill and then an area around the station becomes available for returns (overflow). As of today, I believe this proposal could serve that case in this way:

When overflow is allowed, an element in station_information.json would include the following attributes:

  • station_area: Defined (GeoJSON)
  • is_virtual_station: 1
  • capacity: "" [Meaning: unlimited]

Would this serve the use case fully or do we need to modify/clarify the current proposal?

I think changing the capacity field in this way would result in the loss of information about the capacity of physical docking stations. Therefore, I just proposed adding virtual_capacity and virtual_vehicle_capacity to model this situation instead. See my comments in the google doc.

@siilats
Copy link

siilats commented Oct 13, 2019

Hi, Keith Siilats, CTO of Bolt here. I read through the proposal and it maps pretty well to what Bolt is doing. We base our geofence information on open source traccar: https://www.traccar.org/documentation/geofences/
The github is here https://github.com/traccar/traccar/blob/master/src/main/java/org/traccar/geofence/GeofencePolygon.java

We keep the polygon in WKT instead of GeoJSON but I think either works. Instead of boolean is_ride_through_allowed we use a string based type field, but that is fine too. The main additions I propose is

  1. Parent child relationship. You want to include a parent_id and if it's not null you take the missing parameters from the parent. Doesn't need to be recursive.
  2. Parameter array. In order to work with OpenAPI and Swagger it would be good to define an array of attributes and then have text based items in there for various features.
  3. More text. Title, spanish etc, so that Google Maps can show some info to the user about the restricted area.
  4. Geofence Type. We have 3 types:
    a. Area which is a big parent (like South Florida) that has both Miami and Ft Lauderdale in it. Reason for this is scooters can move between adjacent cities.
    b. City: this is where we set the pricing. This is a green area displayed on the map where scooters are legally allowed to go and the capacity caps get counted by the city geofence. In practice scooters go out of the city sometimes by accident but never outside the area.
    c. Restriction: this is a small geofence that sets restrictions. We currently parent everyone to the Area geofence so we have just 2 levels and do not need recursive logic. The restrictions are:
    i. no parking (drive through)
    ii. no riding (automatically locks scooter on entry)
    iii. hidden (hide scooters on map, for the warehouse location, doesn't prevent renting).
  5. Battery thresholds - at what point will the scooter become unavailable
  6. Max scooter rental count - how many scooters can a person rent
  7. Unit of measure (Imperial or metric)
  8. Requires photo at the end of the ride
  9. Default Lat and Lon - for people with location services turned off that select the geofence from the list, what is the center of the city where the scooters are.
  10. Fine amount for leaving in restricted area
  11. Speed

For example, we show our Ft Lauderdale which is in South Florida and has a restriction of no scooters on the beach (no ride through)

Area:
{
"id": 2,
"attributes": {
"initialPayAmount": "1.0",
"priceMinRate": "0.15",
"deposit": "5",
"couponAmount": "5",
"welcomeMessage": "FTL47|Thanks for riding with Bolt in Fort Lauderdale. For your safety, when you see “LOo” on the screen, please locate and squeeze the brake. Please ride on sidewalks only, obey all traffic laws, and have fun!",
"showWelcomeMessage": "true",
"isEnabled": "true",
"mode": "gray",
"criticalTreshold": "10",
"rentDisableTreshold": "25",
"type": "area",
"maxScooterRentalCount": "4",
"localRules": "Fort Lauderdale: Scooters are only permitted to ride on sidewalks and NOT on streets, highways, or bicycle lanes. Miami (District 2): Ride on sidewalks and sidewalk areas including bike lanes. Always yield to pedestrians and alert them with the bell. Park your scooter upright and do not block sidewalks, fire hydrants, or wheelchair ramps.",
"localRules_spanish": "Fort Lauderdale: los scooters solo pueden ser conducidos por las aceras y NO están permitidos en calles, autopistas o carriles para bicicletas. Miami (Distrito 2): 1. Maneja tu Bolt en los carriles para bicicletas. De no haber disponible, puedes andar por la acera. 2. Cuidado con los peatones. 3. Estacione en posición vertical y no bloquee la acera.",
"welcomeMessage_spanish": "FTL47 | ",
"unlockSpeed": "2",
"displayName": "South Florida",
"state": "FL",
"country": "USA",
"initialPayAmountChariot": "0",
"priceMinRateChariot": "0.35",
"requiresParkingVerification": "true",
"privacyURL": "https://blog.micromobility.com/?page_id=24",
"rentalURL": "https://blog.micromobility.com/?page_id=9",
"chargerURL": "https://blog.micromobility.com/?page_id=8",
"showRange": "true",
"priceMinRateOne": "0.30",
"initialPayAmountOne": "0",
"unitOfMeasure": "imperial"
}
"name": "south_florida_area",
"description": "South Florida ",
"area": "POLYGON((27.029657614371942 -79.83432001927035, 27.043836690371265 -80.31454505485743, 26.89716489091083 -80.31014516006182, 26.67081524560149 -80.31569075281162, 26.637664676996465 -80.31806506347996, 26.58043728706774 -80.3151594385362, 26.527979706609045 -80.30244110306805, 26.44147336829407 -80.29887133527998, 26.38590324824294 -80.30000037811527, 26.346644543483706 -80.32211633483013, 26.30720878888684 -80.34770243790639, 26.265481569175236 -80.37026669104114, 26.227820411431665 -80.40219535828038, 26.21078027645855 -80.44498276102375, 26.18072701193229 -80.4764985801263, 25.959895474562813 -80.49461083506333, 25.826435778029747 -80.54508569122935, 25.45238384598555 -80.63270273596227, 25.015744038260834 -80.52586913108826, 25.026622900971134 -80.2850818634033, 25.698421110480794 -80.02160830136009, 26.041688921812778 -79.95766794902609, 26.2687882567663 -79.94338989257812, 27.029657614371942 -79.83432001927035))"
}

City:
"id": 4,
"attributes": {
"type": "city",
"parent": "2",
"welcomeMessage": "MIA38|Welcome to Bolt Miami! Bolt scooters are permitted to be ridden on sidewalks and in city bike lanes within district 2. Please obey all traffic laws and always use the bell to alert pedestrians. Most importantly remember to be safe and have fun!",
"unlockSpeed": "2",
"displayName": "Miami",
"defaultLat": "25.776645",
"defaultLon": "-80.191218",
"code": "mia",
"initialPayAmount": "0.0",
"priceMinRate": "0.30",
"deposit": "5",
"couponAmount": "5",
"state": "FL",
"country": "USA",
"initialPayAmountChariot": "0",
"priceMinRateChariot": "0.35",
"priceMinRateOne": "0.30",
"initialPayAmountOne": "0",
"welcomeMessage_spanish": "MIA38 | ¡Bienvenido a Bolt Miami! Se permite que los patinetes se monten en las aceras y en los carriles para bicicletas de la ciudad dentro del distrito 2. Por favor, obedezca todas las leyes de tránsito y siempre use el timbre para alertar a los peatones. ¡Lo más importante es recordar estar seguro y divertirse!"
},
"name": "miami_city",
"description": "Miami|Bolt service area",
"area": "POLYGON((25.815117722601627 -80.18365373284387, 25.820907745355427 -80.17651649761639, 25.832903441393967 -80.1805115056113, 25.832870089888885 -80.1843221920418, 25.83211603507425 -80.18425758038677, 25.827295622510903 -80.18727895330126, 25.82390566525835 -80.18728249140989, 25.814926262726303 -80.18923245370387, 25.811665318933706 -80.18966892326408, 25.811530603780426 -80.19583831203487, 25.798508276731667 -80.19527559992876, 25.79846907936303 -80.19736605970029, 25.78355701567989 -80.19659156767922, 25.780733066966107 -80.19646603286795, 25.763515588641596 -80.19572741647131, 25.76016560332944 -80.19641684501019, 25.757331086568115 -80.19999508499092, 25.750426051890628 -80.20929342726103, 25.741634620972718 -80.23257239830856, 25.73974579995253 -80.23791350736992, 25.745250920773515 -80.23805137518137, 25.744690417307936 -80.2544450366804, 25.742708816241674 -80.25432917370914, 25.74261326806517 -80.25645551107212, 25.73514212456655 -80.25609727743358, 25.735031498478236 -80.25794041545852, 25.732029377900062 -80.25785630309731, 25.732097120937652 -80.255675493256, 25.72773890688083 -80.25575069359533, 25.72758422370687 -80.25863458282399, 25.725148551587495 -80.25846292144705, 25.725053380102935 -80.26197755326808, 25.709375417410925 -80.26147751189946, 25.710301148434937 -80.23506688630788, 25.72957315142729 -80.22435432008933, 25.74325240268513 -80.20531534546883, 25.758954092249553 -80.18345881059004, 25.771512334868362 -80.18176063073042, 25.77387515052979 -80.18267912157472, 25.781676131658998 -80.18259378552338, 25.78712935916394 -80.18417315595505, 25.815117722601627 -80.18365373284387))"
}
Restricted Hidden
{
"id": 8,
"attributes": {
"type": "hidden",
"parent": "2",
"fine": "true",
"displayName": "Fort Lauderdale"
},
"name": "ftl_warehouse",
"description": "Ft Lauderdale Warehouse",
"area": "POLYGON((26.13533149913151 -80.15426399186252, 26.132060753440868 -80.1541603077203, 26.131996037428863 -80.1578494347632, 26.135386731919965 -80.1579763367772, 26.13533149913151 -80.15426399186252))"
}
Restricted
{
"id": 9,
"attributes": {
"type": "restricted",
"fine": "true",
"parent": "2",
"autoPause": "false",
"autoSlow": "true",
"autoSlowSpeed": "5"
},
"name": "ftl_blocked",
"description": "NO PARKING|Parking here will result in a fine. Parking on Davie and West Broward Blvd is allowed.",
"area": "POLYGON((26.191715379418795 -80.09356945753096, 26.18994234473537 -80.15094749435734, 26.151831696858423 -80.16744453459978, 26.151579196473108 -80.18772806972265, 26.1495128259472 -80.18765866756439, 26.149967575062362 -80.16818080097437, 26.146529828266623 -80.16949211229725, 26.121937755060458 -80.16922552138567, 26.121085534014696 -80.20012088119984, 26.11809082030271 -80.20005483180285, 26.118881651334945 -80.16912695020437, 26.107332337587025 -80.16944848001003, 26.10533292572049 -80.19984260201454, 26.106409258447272 -80.19991267472506, 26.106214465538443 -80.20181268453598, 26.09006328863434 -80.20019665360451, 26.090408062263805 -80.19833888858557, 26.10347799731514 -80.19950062036516, 26.105372968486108 -80.16953062266111, 26.08223556602448 -80.16865746776587, 26.082001496938375 -80.10707799865843, 26.010685654821202 -80.10915309190783, 26.00719756007865 -80.34600824117693, 26.13053338469925 -80.35566666226508, 26.274135860417317 -80.29960277431148, 26.276912657749364 -80.07197075338604, 26.191715379418795 -80.09356945753096))"
}

@antrim
Copy link
Contributor Author

antrim commented Oct 16, 2019

Hi @siilats! Thanks for sharing these great ideas. Responses inline below (and in the Google Doc).

Parent child relationship. You want to include a parent_id and if it's not null you take the missing parameters from the parent. Doesn't need to be recursive.

This would make it possible to specify default rules for an area, and then override or add rules in the child areas. Do feed consumers want to implement this?

Options:

  • Add a parent_id attribute for zone areas.
  • Specify that areas are not allowed to overlap. Feed producers would describe non-overlapping areas that specify the complete set of rules.

Parameter array. In order to work with OpenAPI and Swagger it would be good to define an array of attributes and then have text based items in there for various features.

How about changing geofencing_zone_information.json to be a GeoJSON feature collection with properties (https://tools.ietf.org/html/rfc7946#section-3.3)? This would make it possible to load the the polygons into a number of ready GeoJSON libraries and visualizers.

I've set up a Google Spreadsheet that lists possible parameters, based on your list in the proposal. Let's all discuss these parameters to figure out what would be implemented in consuming applications.

More text. Title, spanish etc, so that Google Maps can show some info to the user about the restricted area.

This is served by GBFS's current localization approach: https://github.com/NABSA/gbfs/blob/master/gbfs.md#localization. To change this, open a separate issue or pull request. It would be useful to do a survey of current practice. I'm not sure how many feeds are available in multiple localizations.

Geofence Type. We have 3 types:
a. Area which is a big parent (like South Florida) that has both Miami and Ft Lauderdale in it. Reason for this is scooters can move between adjacent cities.
b. City: this is where we set the pricing. This is a green area displayed on the map where scooters are legally allowed to go and the capacity caps get counted by the city geofence. In practice scooters go out of the city sometimes by accident but never outside the area.
c. Restriction: this is a small geofence that sets restrictions. We currently parent everyone to the Area geofence so we have just 2 levels and do not need recursive logic. The restrictions are:
i. no parking (drive through)
ii. no riding (automatically locks scooter on entry)
iii. hidden (hide scooters on map, for the warehouse location, doesn't prevent renting).

In this case (iii), I think the bike/scooter would just not be shown in the public GBFS.

Battery thresholds - at what point will the scooter become unavailable
Max scooter rental count - how many scooters can a person rent
Unit of measure (Imperial or metric)
Requires photo at the end of the ride
Default Lat and Lon - for people with location services turned off that select the geofence from the list, what is the center of the city where the scooters are.
Fine amount for leaving in restricted area
Speed

@antrim
Copy link
Contributor Author

antrim commented Oct 16, 2019

The current Dockless & Geofencing Minimum Viable Proposal proposes two files

  • geofencing_zone_information.json: Contains the polygons, names, and other information that we don't anticipate changes often.
  • geofencing_zone_status.json: Contains rules that might change more often.

I speculated that it might be useful for consumers and producers for areas to be defined in a file that doesn't change much. That assumption might be false.

From the perspectives of GBFS producers and consuming applications -- would it be useful or useless for those to be distinct files?

@siilats
Copy link

siilats commented Oct 17, 2019

iii. hidden (hide scooters on map, for the warehouse location, doesn't prevent renting).

In this case (iii), I think the bike/scooter would just not be shown in the public GBFS.

For debugging though it will drive people crazy that the scooter will disappear. Things like you want to stop a ride go to store and then take the same scooter again. I think Google Maps might want to know where our hidden areas are.

@marie-x
Copy link

marie-x commented Oct 17, 2019

@antrim The MDS Policy file-based flavor uses two files based on the same broad rationale.

@kanagy
Copy link

kanagy commented Oct 20, 2019

Sorry to reply after a while. I left comments in the spredsheet on Keith's geofencing attributes. I think most of them are already covered by one of the existing or coming proposals (vehicle attributes, deep links, pricing), others can be modelled with this geofencing proposal and the rest Maps wouldn't use.

I'd prefer geofencing_zone_information and geofencing_zone_status to be one file. Keen to hear others' opinions.

On parent-child zone relationship: would prefer to keep it simple and have non-overlapping areas, each specifying their complete set of rules. It seems simpler to implement and reason about.

@antrim
Copy link
Contributor Author

antrim commented Oct 22, 2019

Thanks for the comments.

This earlier question may have gotten buried, so I'm repeating it. Reactions to the below idea?

How about changing geofencing_zone_information.json to be a GeoJSON feature collection with properties?

@cype
Copy link

cype commented Oct 29, 2019

I think that a GeoJSON is a very good idea. Main content of the file is the geofence, therefore a geoJSON seems to be appropriate.

@antrim antrim changed the title Proposal: Dockless systems, geofencing, and virtual station support. Proposal: Geofencing, and virtual station support Oct 31, 2019
@antrim
Copy link
Contributor Author

antrim commented Oct 31, 2019

Update: Here's a version 2 proposal (Google Doc). This is intended as a minimum viable proposal candidate for implementation. Please indicate your organization's readiness or lack of readiness to implement this scheme, and request changes if necessary to make it implementation-ready.

@antrim
Copy link
Contributor Author

antrim commented Nov 12, 2019

Based on stakeholder comments (in the doc and via email), I made the following changes:

free_bike_status.json

  • Added system_id to associate free bikes with a particular system in multi-region feeds.

station_information.json

  • Removed is_virtual_station field (virtual station is assumed if station_area is supplied
  • A blank capacity field indicates unlimited capacity.

geofencing_zones.json

  • Changed the geometry field from GeoJSON Polygon/Multipolygon to Multipolygon only.
  • Removed proposed id and parent_id fields

If this looks implementable, the next step is for @MobilityData to commit the specification edits in a PR and call for a vote.

@antrim antrim changed the title Proposal: Geofencing, and virtual station support Proposal: Geofencing, virtual station, and dockless support Nov 12, 2019
@sven4all
Copy link
Contributor

I don't completely agree with removing the is_virtual_station field, why could a station area not be described in case of physical docking stations?

@antrim
Copy link
Contributor Author

antrim commented Nov 15, 2019

Hi @sven4all, I see what you're saying about describing dock facility footprint. But I haven't heard of applications that want to consume a polygon of a dock facility polygon and show it in a map yet. To all: are there applications that would want to add this functionality?

We're trying to develop a minimum viable proposal and discourage speculative changes.

@antrim
Copy link
Contributor Author

antrim commented Nov 15, 2019

Can I go ahead and call a vote on this proposal?

@jensfrandsen
Copy link

jensfrandsen commented Nov 20, 2019

Hi Jens Frandsen, CTO of Donkey Republic here

We welcome this change of adding virtual stations to the spec as our system is build up of that.
I have a question: Is it correctly understood that the geoJSON and MultiPolygon format does not support a circular area?
We describe the virtual station area simply as a point and a radius.

@barbeau
Copy link
Member

barbeau commented Nov 20, 2019

@jensfrandsen I believe that is correct - in GeoJSON you can't represent a circle as a point and a radius. You instead have to create a polygon that approximates a circle.

@antrim
Copy link
Contributor Author

antrim commented Nov 21, 2019

@jensfrandsen : Would it work for you to describe virtual stations by a polygon? A concise spec is good, but if there is a technical necessity to add the capability to describe virtual stations by radius, let's explore and consider that now.

Can you share more about Donkey Republic's use cases and needs?

  • Can you share more information about the virtual stations? What is the range of virtual station radiuses?
  • If you have your own app, how are virtual stations displayed on the map?
  • Is the service in any 3rd party applications? Are there issues with how the bikeshare system features are being displayed?

Adding features for dockless, virtual stations, and geofencing is urgent. After a bit more deliberation and comment, I propose to call the vote on this at the end of Monday, November 25 -- unless anyone raises objections(?). I hope that's enough time to make any changes we deem necessary.

@sven4all
Copy link
Contributor

sven4all commented Nov 23, 2019

To help this discussion forward, I can elaborate a little bit further on Donkey's use case.

Can you share more about Donkey Republic's use cases and needs?

  • Can you share more information about the virtual stations? What is the range of virtual station radiuses?
  • If you have your own app, how are virtual stations displayed on the map?

The virtual stations are just pin/points for the users. , I assume internally a range is used but that is not visible for the users of the system.
Screenshot_20191123-101611

  • Is the service in any 3rd party applications? Are there issues with how the bikeshare system features are being displayed?
    I am currently working with Donkey to integrate their bikes in a PT app in the Netherlands. We were planning to also show the stations as points.

Thinking it through, this was exactly the reason why I wanted a "is_virtual_station" field in the standard. When this field is included you can create a virtual stations as point without having to specifying a station_area.

When for example multiple bike-sharing/scooter operators are operating in a city the preferred way to show virtual stations is pins because station_area's are overlapping between different operators and that will be chaos for the customer. Only when a station is selected for example you can show all the station_area's of that operator in your app.

@antrim
Copy link
Contributor Author

antrim commented Nov 25, 2019

Since the display is a point, it sounds like we could accommodate that by adding back in the 'is_virtual_station' field, as @sven4all suggests. I'll make that change.

antrim and others added 3 commits November 26, 2019 11:06
@evansiroky
Copy link
Contributor

After seeing the diff, I think it'd make sense to be more specific with how to define the fields station_information.json#stations#station_area and geofencing_zones.json#geofencing_zones#geometry. The current field descriptions could result in some ambiguous definitions of data where some people might include just the MultiPolygon array portion of the MultiPolygon GeoJSON and others might include the full GeoJSON definition.

Perhaps this could use some kind of guide on what to do and what not to do. For example:

GeoJSON MultiPolygon definition

Correct

{
  ...
  "station_area": {
     "type": "MultiPolygon",
     "coordinates": [[[[-66,18],[-64,33],[-81,26],[-66,18]]]]
  }
}

Incorrect

{
  ...
  "station_area": [[[[-66,18],[-64,33],[-81,26],[-66,18]]]]
}

Incorrect

{
  ...
  "station_area": {
    "type": "Feature",
    "properties": {},
    "geometry": {
      "type": "MultiPolygon",
      "coordinates": [[[[-66,18],[-64,33],[-81,26],[-66,18]]]]
    }
  }
}

It'd also really help to have example JSON included for all these changes.

Add geofencing_zones.json example: GeoJSON FeatureCollection. Example gives a v 2.X.

station_information.json: lat, lon, and station_area are "Conditionally required".
@antrim
Copy link
Contributor Author

antrim commented Dec 4, 2019

Hi @evansiroky I checked in a change that includes:
An example for geofencing_zones.json. (I'll add another example for the station_area field, as you suggest.)

This also includes one other change:
The lat, lon (previously required), and station_area (previously optional) fields in station_information.json fields are now defined as conditionally required.

I apologize that I've delayed in calling the vote on this. I think we need to have a bit more discussion on these changes so we're sure this proposal is ready.

Looking at the example, what are people's current thoughts about wrapping geofencing zones in a GeoJSON FeatureCollection? Will this be useful to support ad hoc visualization? Or does it make the spec kludgy?

\- geometry | Yes | A GeoJSON Multipolygon that describes where rides might not be able to start, end, go through, or have other limitations. A clockwise arrangement of points defines the area enclosed by the polygon, while a counterclockwise order defines the area outside the polygon [(right-hand rule)](https://tools.ietf.org/html/rfc7946#section-3.1.6). All geofencing zones contained in this list are public.
\- properties{} | Yes | As defined below, describes travel allowances and limitations.
 - name | Optional | String- Name of the geofencing zone.
 - rules[] | Optional | Array that contains one object per rule as defined below. In the event of overlapping or colliding rule, the earlier defined rule (in order of the JSON file) takes precedence.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this should be an object of the rules. I don't see a use case for a single Multipolygon having an array of rules. There can be instances where the rules from Features that have overlapping geometry would be in conflict, so it might be good to note that.

@evansiroky
Copy link
Contributor

I do think this format is slightly different from the others, but don't have strong preferences about it although the code to parse this might look different than the other files. My main concern is making sure that there is no ambiguity on how to structure the data. I think the example provided is good and that the spec references the GeoJSON spec. However, the table of the geofencing_zones.json skips over the layer of the features array and could perhaps have stronger language about how although the GeoJSON spec does allow different feature types, anything other than a MultiPolygon is invalid.

@sven4all
Copy link
Contributor

sven4all commented Dec 6, 2019

A client is already implementing the station_area field because we need it right now.

Maybe it's a good idea to explicitly state that first the x coordinate (longitude) should be specified and then the y coordinate (latitude). Because this was not completely clear for the developer that implemented this functionality.

\- geometry | Yes | A GeoJSON Multipolygon that describes where rides might not be able to start, end, go through, or have other limitations. A clockwise arrangement of points defines the area enclosed by the polygon, while a counterclockwise order defines the area outside the polygon [(right-hand rule)](https://tools.ietf.org/html/rfc7946#section-3.1.6). All geofencing zones contained in this list are public.
\- properties{} | Yes | As defined below, describes travel allowances and limitations.
 - name | Optional | String- Name of the geofencing zone.
 - rules[] | Optional | Array that contains one object per rule as defined below. In the event of overlapping or colliding rule, the earlier defined rule (in order of the JSON file) takes precedence.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One type of rule not currently represented in this PR (but mentioned in the discussion and used at Bird) is a speed-limited zone. Perhaps we should add a max_speed field, with integer value. We should decide what units we want to use (mi/hr, km/hr, something else).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wellorder I think the intention was to only cover rules related to parking in these zones and leave other types of rules/regulations as a responsibility of the MDS spec.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@contra Whoa, I don't agree with this at all. GBFS should include everything that consumer-facing application can use and max_speed is certainly part of it : it impacts trip planning and is certainly interesting for the user to know in a UI. I though the speed was discarded because there were no implementer for it, but seems @wellorder is one of them now.

I agree regulation/rules that aren't user facing at all can be left to MDS (like vehicle caps).

@antrim
Copy link
Contributor Author

antrim commented Jan 29, 2020

A few stakeholders have indicated that they are using some features in the current geofencing proposal.

Should we vote to add this to the specification?
Or should we make modifications / additions before this goes to vote?

Requests / notes:

All feedback/responses very much appreciated!

@evansiroky
Copy link
Contributor

  • Maximum speed regulations in geofenced zones have been requested. Should this be part of a minimum viable proposal? Anyone ready to implement?

We at IBI Group would definitely use this and have already implemented some logic for loading a static GeoJSON file outside of the spec for this purpose.

  • Ready extensibility to add time-based rules (right now, the rules are in the geofencing_zones.json file, so it would require a refactorization if we specified different rules at different times). Would anyone be ready to implement?

We don't have an immediate need for this.

We at IBI Group would definitely use this and have already implemented some logic for loading a static GeoJSON file outside of the spec for this purpose.

  • Is wrapping the data in the a GeoJSON FeatureCollection actually useful or is this just fussy?

We support whatever leads to producers creating consistent error-free feeds. :)

@gcamp
Copy link

gcamp commented Jan 31, 2020

Maximum speed regulations in geofenced zones have been requested. Should this be part of a minimum viable proposal? Anyone ready to implement?

At Transit we're not ready to implement but implementation should start in Q1. We will do speed regulations.

Ready extensibility to add time-based rules (right now, the rules are in the geofencing_zones.json file, so it would require a refactorization if we specified different rules at different times). Would anyone be ready to implement?

Afaik we don't need this but we would be ok to implement at the same time.

The ability to model hybrid (docked + dockless) systems, as we have discovered that some such services do indeed exist (see issue #186). This support would probably involve adding a breaking change to the proposed vehicle_types.json file (https://github.com/NABSA/gbfs/blob/9a975187a7624dbe9df5823a00d8b08e9e42d616/gbfs.md#vehicle_typesjson).

This would be useful for us but I'm missing what exactly is missing in the spec to support this use case.

Is wrapping the data in the a GeoJSON FeatureCollection actually useful or is this just fussy?

For us this is a net positive

@matt-wirtz
Copy link

Thanks for the good work on this proposal.

While reading the version 2 proposal a couple of questions came up:

MultiPolygons need to be disjunct/non overlapping
As I understand it the idea of parent child relations between MultiPolygons has been removed. So the MultiPolygons need to be disjunct. I think this makes displaying the geo-objects and finding the relevant geo-object much harder.

I made an example of a simple service area (green) in which a small no-go area (orange) exists:
geofencing_zones

The corresponding geofencing_zones.json should look like this:

{
    "last_updated": 1434054678,
    "ttl": 0,
    "version": "2.0",
    "data": {
        "geofencing_zones": {
            "features": [{
                    "type":
                    "geometry": {
                        "type": "MultiPolygon",
                        "coordinates": [
                            [
                                [
                                    [10.0, 40.0], [10.0, 41.0], [11.0, 41.0], [11.0, 40.0], [10.0, 40.0]
                                ]
                            ]
                        ],
                        [
                            [
                                [
                                    [10.4, 40.4], [10.6, 40.4], [10.6, 40.6], [10.4, 40.6], [10.4, 40.4]
                                ]
                            ]
                        ]
                    }
                    "properties": {
                        "name": "city center"
                        "rules": [{
                                "vehicle_type_id": [1, 2]
                                "ride_start_allowed": 1
                                "ride_end_allowed": 1
                                "ride_through_allowed": 1
                                "maximum_speed_kph": 30
                            }
                        ]
                    }
                }, {
                    "type":
                    "geometry": {
                        "type": "MultiPolygon",
                        "coordinates": [
                            [
                                [
                                    [10.4, 40.4], [10.4, 40.6], [10.6, 40.6], [10.6, 40.4], [10.4, 40.4]
                                ]
                            ]
                        ]
                    }
                    "properties": {
                        "name": "pedestrian area"
                        "rules": [{
                                "vehicle_type_id": [1, 2]
                                "ride_start_allowed": 0
                                "ride_end_allowed": 0
                                "ride_through_allowed": 0
                                "maximum_speed_kph":
                            }
                        ]
                    }
                }
            ]
        }
    }
}

In the geofencing_zones.json I used two polygons to describe the lager service area. One is clockwise, the other is counter-clockwise to exclude the small no-go area. The small no-go area is represented by one clockwise polygon.

If one has a geo-coordinate from inside the no-go area and one wants to know if it is ok to end the ride here, one has to figure out which defined area is relevant. Doing this would involve checking each polygon if the point is wihtin this polygon and detecting if the points are clockwise or counter-clockwise oriented.

In addition the geo-object for the small no-go area appears twice: one clockwise and one counter-clockwise. So my impression is that the parent-child method make things easier.

Differentiation between ride_start_allowed and ride_end_allowed
Is the differentiation necessary here? I'm not sure if there is a use case where one is not allowed to start a ride at a given point but one could end a ride here. Maybe the two attributes could be combined.

Missing "features" attribute in "geofencing_zones" attribute
In my understanding the "geofencing_zones" attribute is of type FeatureCollection. And the RFC7946 states: 'A FeatureCollection object has a member with the name "features"'. So I think the features attribute is missing here. I added the attirbute in the example above but this is IMHO not yet present in the version 2 spec.

Attribute "maximum_speed_kph"
Sounds usefull to me.

It might be that some of the issues have already been discussed in other threads. In this case please bear with me.

Regards.

@kanagy
Copy link

kanagy commented Feb 6, 2020

To comment on Aaron's questions:

A few stakeholders have indicated that they are using some features in the current geofencing proposal.

Should we vote to add this to the specification? Or should we make modifications / additions before this goes to vote?

+1 for voting on MVP and adding extensions in separate proposals. Lime has already implemented the current proposal and we plan to implement it in Google Maps in the coming days.

Requests / notes:

  • Maximum speed regulations in geofenced zones have been requested. Should this be part of a minimum viable proposal? Anyone ready to implement?

No plans for us.

  • Ready extensibility to add time-based rules (right now, the rules are in the geofencing_zones.json file, so it would require a refactorization if we specified different rules at different times). Would anyone be ready to implement?

We don't plan to use these. I have trouble seeing a use case for these for consumers. GBFS is real time. If the use case is to answer micromobility queries in the future, there would have to be more changes to GBFS to be able to do that.

It would be useful for us in the future. Same as gcamp@, not sure what's missing in this spec to make that happen. Perhaps it can be done in a follow-up proposal?

  • Is wrapping the data in the a GeoJSON FeatureCollection actually useful or is this just fussy?

No strong opinion either way.

All feedback/responses very much appreciated!

@antrim
Copy link
Contributor Author

antrim commented Feb 10, 2020

@MobilityData will work on making any necessary changes in response to the community's requests, and formatting this as a pull request that's ready to merge. We'll provide a timeline by Thursday.

Responses to recent comments below.

@matt-wirtz commented --

MultiPolygons need to be disjunct/non overlapping
As I understand it the idea of parent child relations between MultiPolygons has been removed. So the MultiPolygons need to be disjunct. I think this makes displaying the geo-objects and finding the relevant geo-object much harder.

I think I see what you are saying. Would this be an issue for other consumers or for data producers who would need to specify non-overlapping areas precisely?

Two possible solutions would be to specify layers for geofences, or parent/child relationships. If this isn't imperative, this functionality could be added after the minimum viable proposal is implemented.

Differentiation between ride_start_allowed and ride_end_allowed
Is the differentiation necessary here? I'm not sure if there is a use case where one is not allowed to start a ride at a given point but one could end a ride here. Maybe the two attributes could be combined.

I'm unsure. Conceptually, I was imagining that such a feature might be used for rebalancing bikes. We don't have a comprehensive survey of all bikeshare operating rules. I looked to see whether MDS provides functions that would allow vehicles to be rented in an area but not returned there, or vice versa, and it doesn't look as though it does (https://github.com/openmobilityfoundation/mobility-data-specification/tree/dev/policy#rules), which would be a point in favor of consolidating these fields.

Can operators or those closer to bikeshare/scooter sharing systems share some insights?
@wellorder @siilats @sven4all

@wellorder
Copy link

@antrim At Bird we do not differentiate between areas where rides can start and rides can end, if you can do one you can do the other. So consolidating the fields is fine from our point of view.

Copy link

@Empty2k12 Empty2k12 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more ideas about the geo-fence zones

{
"type":"Feature",
"properties":{
"name":"Downtown Waterfront",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend three optional additional keys next to name here:

  • start_date: string (ISO 8601) | Date and time of the start of the geo-fencing zone
  • end_date: string (ISO 8601) | Date and time of the end of the geo-fencing zone
  • description: string | Description about the geo-fencing zone

These could be used to display temporary no-park zones for which cities place, for example for Christmas markets or street construction sites.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Empty2k12: If start_date and end_date were included would you or another application developer commit to implementing that in software?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we would love to implement start_date for our unofficial GBFS feeds we're providing.

We'd also like to support start_date and end_date for the GBFS explorer application we're actively developing. For that we'd implement these changes into our GraphQL wrapper for GBFS (GbfsQL) and incorporate displaying that into the viewer frontend.

@antrim
Copy link
Contributor Author

antrim commented Feb 14, 2020

@matt-wirtz

Missing "features" attribute in "geofencing_zones" attribute
In my understanding the "geofencing_zones" attribute is of type FeatureCollection. And the RFC7946 states: 'A FeatureCollection object has a member with the name "features"'. So I think the features attribute is missing here. I added the attirbute in the example above but this is IMHO not yet present in the version 2 spec.

Thank you for noticing that. I've made a change in the draft proposal (Google Doc version) to include the "features" object member (an array).

@antrim
Copy link
Contributor Author

antrim commented Feb 19, 2020

Hi all - Sorry for the delay in posting a timeline. The PR will updated with a few changes by Friday (North American time).

These additional changes will be in the PR:

  • rides_allowed instead of ride_start_allowed and ride_end_allowed
    geofencing start_date and end_date (@Empty2k12 committed to implementing this)

We propose to wait and see what needs arise around multipolygon nesting and implement later, if it proves necessary.

@timMillet
Copy link
Contributor

timMillet commented Feb 22, 2020

Hi everybody, a follow-up on this PR:

A new PR #219 has been made to reflect all the modifications on the proposal that the Gdoc reflected. This new PR has also no more conflicts with the current GBFS specification. It means that the PR #219 is replacing this PR that will be closed.

Thank you all for your contributions!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.