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

Add vehicle type definitions #136

Merged
merged 37 commits into from
May 22, 2020
Merged
Changes from 5 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
83def47
first attempt at refactoring gbfs to allow vehicle type definitions
evansiroky Feb 19, 2019
053e604
in free_vehicle_status.json, rename vehicle_type to vehicle_type_id
evansiroky Feb 19, 2019
8715a98
remove no longer necessary reference to multiple vehicle types
evansiroky Feb 19, 2019
65fdf55
Refactor PR to a minimum viable product
evansiroky Sep 19, 2019
6a73469
Merge branch 'nabsa-master'
evansiroky Sep 19, 2019
81aa440
Include changes recommended by @kanagy
evansiroky Sep 24, 2019
9477593
Add additional form factor options for vehicle type
evansiroky Sep 25, 2019
37cb9a5
Refactor a few things to address discussion at GBFS developer workshop
evansiroky Oct 8, 2019
2d68f57
Add some more clarification and requirements for the range fields
evansiroky Oct 8, 2019
98f61a2
Improve a few small items in field documentation
evansiroky Oct 10, 2019
dde2a8f
Refactor station_status to allow reporting of individual vehicle details
evansiroky Oct 28, 2019
005333f
Try to clarify better when certain station_status fields are required.
evansiroky Nov 14, 2019
2df27ce
Modify propulsion_type field and add is_carryable field.
evansiroky Nov 23, 2019
33a0ae7
Merge branch 'nabsa-master'
evansiroky Nov 27, 2019
8f3906b
Include required version info in example json
evansiroky Nov 27, 2019
2698f13
Add gbfs_versions.json file to TOC
evansiroky Nov 27, 2019
3c89327
Merge commit '3fd004c7ea9a52896c1f204e79d489bccfcd48d7'
evansiroky Dec 6, 2019
167d6b7
Refactor fields about vehicle capacity/availability at stations
evansiroky Dec 6, 2019
071e0c6
Make num_bikes_available be required again
evansiroky Dec 6, 2019
becb09c
Merge branch 'nabsa-master'
evansiroky Jan 28, 2020
9a97518
Update field tables to latest format and add type information
evansiroky Jan 28, 2020
f0e9cf6
Merge branch 'nabsa-master'
evansiroky Feb 4, 2020
b8e46a9
Add fields describing energy potentials of vehicles
evansiroky Feb 21, 2020
314a332
Merge branch 'nabsa-master'
evansiroky Mar 4, 2020
e62ae18
Remove is_carryable field from vehicle_types.json file.
evansiroky Mar 4, 2020
fd404bb
Merge branch 'nabsa-master'
evansiroky Mar 6, 2020
b1be46c
Rename `bike` to `vehicle` in documentation wherever possible
evansiroky Mar 6, 2020
ba7c5cd
Revert back to vehicle range values
evansiroky Mar 11, 2020
fae9460
Rename field in station_status
evansiroky Mar 11, 2020
174ca6d
Merge branch 'nabsa-master'
evansiroky Mar 20, 2020
b318908
Update example JSON to have a future version number
evansiroky Mar 20, 2020
50b611d
Small formatting fix for consistency
evansiroky Mar 20, 2020
a03a7c6
Update boolean values and fix some merge problems.
evansiroky Mar 20, 2020
2010a60
A few more minor merge conflict fixes.
evansiroky Mar 20, 2020
a8e518a
Merge branch 'nabsa-master'
evansiroky Apr 6, 2020
d1b6626
Update gbfs.md
heidiguenin May 11, 2020
403e906
Add version labels, update MDS attribution & link
barbeau May 22, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 142 additions & 6 deletions gbfs.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This document explains the types of files and data that comprise the General Bik
* [Field Definitions](#field-definitions)
* [gbfs.json](#gbfsjson)
* [system_information.json](#system_informationjson)
* [vehicle_types.json](#vehicle_typesjson)
* [station_information.json](#station_informationjson)
* [station_status.json](#station_statusjson)
* [free_bike_status.json](#free_bike_statusjson)
Expand Down Expand Up @@ -41,6 +42,7 @@ File Name | Required | Defines
--------------------------- | ----------------------- | ----------
gbfs.json | Optional | Auto-discovery file that links to all of the other files published by the system. This file is optional, but highly recommended.
system_information.json | Yes | Describes the system including System operator, System location, year implemented, URLs, contact info, time zone
vehicle_types.json | Conditionally required | Describes the types of vehicles that System operator has available for rent. Required of systems that include information about vehicle types in the station_status and/or free_bike_status files. If this file is not included, then all vehicles in the feed are assumed to be non-motorized bicycles
station_information.json | Conditionally required | Mostly static list of all stations, their capacities and locations. Required of systems utilizing docks.
station_status.json | Conditionally required | Number of available bikes and docks at each station and station availability. Required of systems utilizing docks.
free_bike_status.json | Conditionally required | Describes bikes that are available for rent. Required of systems that don't utilize docks or offer bikes for rent outside of stations.
Expand Down Expand Up @@ -173,6 +175,43 @@ email | Optional | A single contact email address for customers to
timezone | Yes | The time zone where the system is located. Time zone names never contain the space character but may contain an underscore. Please refer to the "TZ" value in https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for a list of valid values
license_url | Optional | A fully qualified URL of a page that defines the license terms for the GBFS data for this system, as well as any other license terms the system would like to define (including the use of corporate trademarks, etc)

### vehicle_types.json
The following fields are all attributes within the main "data" object for this feed.

ield Name | Required | Defines
Copy link

Choose a reason for hiding this comment

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

Nit: missing 'F'

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops.

------------------| --------- | ----------
vehicle_types | Yes | Array that contains one object per vehicle type in the system as defined below
\- vehicle_type_id | Yes | Unique identifier of a vehicle type. See [Field Definitions](#field-definitions) above for ID field requirements
\- form_factor | Yes | An enumerable describing the vehicle's general form factor. <br /><br />Current valid values are:<br /><ul><li>`bicycle`</li><li>`scooter`</li><li>`car`</li></ul>
Copy link
Contributor

Choose a reason for hiding this comment

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

I think there may be a missing moped value here for providers like Revel/Scoot.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I went ahead and added moped. I also added the value other in order to allow the definition of any vehicle form factor that is not able to be categorized by any of the pre-defined form factors.

\- propulsion_types | Yes | An array consisting of enumerables that describe the propulsion type of the vehicle. <br /><br />A device may have one or more values from the propulsion_type, depending on the number of modes of operation. For example, a scooter that can be powered by foot or by electric motor would have the propulsion_type represented by the array ['human', 'electric']. A bicycle with pedal-assist would have the propulsion_type represented by the array ['human', 'electric_assist'] if it can also be operated as a traditional bicycle. A car with an internal combustion engine would be represented by the array ['combustion']<br /><br />Current valid values are:<br /><ul><li>`human` _(Pedal or foot propulsion)_</li><li>`electric assist` _(Provides power only alongside human propulsion)_</li><li>`electric` _(Contains throttle mode with a battery-powered motor)_</li><li>`combustion` _(Contains throttle mode with a gas engine-powered motor)_</li></ul> This field was copied from [City of Los Angeles Mobility Data Specification](https://github.com/CityOfLosAngeles/mobility-data-specification/blob/73995a151f0a1d67aab3d617a4693f8f81967936/provider/README.md#propulsion-types)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the "electric assist" value supposed to be electric_assist or electric assist? I see that it's inconsistent between the field definition and the example. I would suggest going with the underscore just to avoid ambiguity (i.e. with a space there's more of a possibility of it being confused for 2 different values).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, it should be electric_assist. Fix incoming.

\- description | Optional | A free text description of the vehicle
Copy link

Choose a reason for hiding this comment

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

Can you add what is description meant to be used for?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea. I added more detail.

\- max_range | Optional | If the vehicle has a motor, this represents the furthest distance in meters that the vehicle can travel without recharging or refueling when it has the maximum amount of energy potential (for example a full battery or full tank of gas)

Example:

```json
{
"last_updated": 1434054678,
"ttl": 0,
"data": {
"vehicle_types": [
{
"vehicle_type_id": "abc123",
"form_factor": "bicycle",
"propulsion_types": ["human"],
"description": "a bicycle without a motor"
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it would be really nice if it's possible to add a link to a photo/graphic of the vehicle type. Is that something we can specify as optional field as well well?

If we add it, I think it's a good idea to specify the resolution and format of the image.

},
{
"vehicle_type_id": "def456",
"form_factor": "scooter",
"propulsion_types": ["human", "electric"],
"description": "an electric scooter",
"max_range": 12345
}
]
}
}
```

### station_information.json
All stations contained in this list are considered public (ie, can be shown on a map for public use). If there are private stations (such as Capital Bikeshare’s White House station) these should not be exposed here and their status should not be included in station_status.json.
Expand All @@ -190,22 +229,90 @@ stations | Yes | Array that contains one object per station in th
\- region_id | Optional | ID of the region where station is located (see [system_regions.json](#system_regionsjson))
\- post_code | Optional | Postal code where station is located
\- rental_methods | Optional | Array of enumerables containing the payment methods accepted at this station. <br />Current valid values (in CAPS) are:<br /><ul><li>KEY _(i.e. operator issued bike key / fob / card)_</li> <li>CREDITCARD</li> <li>PAYPASS</li> <li>APPLEPAY</li> <li>ANDROIDPAY</li> <li>TRANSITCARD</li> <li>ACCOUNTNUMBER</li> <li>PHONE</li> </ul> This list is intended to be as comprehensive at the time of publication as possible but is subject to change, as defined in [File Requirements](#file-requirements) above
\- capacity | Optional | Number of total docking points installed at this station, both available and unavailable
\- capacity | Optional | Number of total docking points installed at this station, both available and unavailable, regardless of what vehicle types are allowed at each dock. This field should only be used if every dock at the station is able to accept every vehicle type used in the system.
\- vehicle_type_capacity | Optional | An object where each key is a vehicle_type_id as described in [vehicle_types.json](#vehicle_typesjson) and the value is a number representing the total docking points installed at this station, both available and unavailable for the specified vehicle type.
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to enable a hierarchy or groups of vehicle types? e.g. are there cases where there are various defined electric bikes with different amenities, and we just need to specify capacity for electric bikes in general?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think this is necessary as it is possible to determine the form factor and additional information about a vehicle type by looking up the data associated with a particular vehicle type ID.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Recently and number of cities ( DC, Bay Area, Portland etc.) have taken steps to introduce various types of adaptive cycles to their bike share fleets. Additionally there are a number of examples of shared cargo bikes now in Europe. How would these types of vehicles be differentiated within the form factor and vehicle type? Existing examples are:

  • Upright handcycle
  • Recumbent handcycle
  • Recumbent leg trike
  • Recumbent trike tandem
  • Side-by-side tandem bicycle
  • Cargo bicycle
  • Cargo tricycle

Copy link
Contributor Author

@evansiroky evansiroky Sep 26, 2019

Choose a reason for hiding this comment

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

I think the intent of the form_factor field is to have a very general classification and avoid making up a potentially endless hyper-specific list of enumerations of what a vehicle's "type" is. Therefore, all of those vehicles @mplsmitch listed would each have a form_factor value of bicycle. For now, the place to further explain details about the vehicle would be in the description field of a vehicle type object in the vehicle_types.json file. In my initial PR, I didn't include this field, but instead proposed to add many more fields with additional places to differentiate vehicles (such as adding pictures which @sven4all brought up again). However, after a discussion with @antrim and @kanagy, I removed those other fields and added the form_factor field in order to try to make a minimum viable pull request to merge in.


Example:

```json
{
"last_updated": 1434054678,
"ttl": 0,
"data": {
"stations": [
{
"station_id": "pga",
"name": "Parking garage A",
"lat": 12.34,
"lon": 45.67,
"vehicle_type_capacity": {
"abc123": 7,
"def456": 9
}
}
]
}
}
```

### station_status.json

Field Name | Required | Defines
--------------------- | ----------| ----------
stations | Yes | Array that contains one object per station in the system as defined below
\- station_id | Yes | Unique identifier of a station (see station_information.json)
\- num_bikes_available | Yes | Number of bikes available for rental
\- num_bikes_available | Conditionally required | Number of vehicles of all types available for rental. This field is not required if the `vehicles_available` field has been defined.
Copy link
Contributor

@yocontra yocontra Sep 24, 2019

Choose a reason for hiding this comment

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

Thoughts on deprecating this + num_docks_available since it is bike specific? Not sure if making breaking changes are out of scope here, since versioning is still up for discussion. Seems like a lot to have two ways of specifying the same thing, but one is clearly better than the other.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I do like the idea of versioning and would change this and rename everything that says "bike" to "vehicle", but will await guidance from the community.

\- num_bikes_disabled | Optional | Number of disabled bikes at the station. Vendors who do not want to publicize the number of disabled bikes or docks in their system can opt to omit station capacity (in station_information), num_bikes_disabled and num_docks_disabled. If station capacity is published then broken docks/bikes can be inferred (though not specifically whether the decreased capacity is a broken bike or dock)
Copy link

Choose a reason for hiding this comment

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

Do you need to update this description to make it clear that this is the number of disabled vehicles of any type? I.e. what you did for num_docks_available.

That said, I'm not sure why num_bikes_disabled and num_docks_disabled (and now vehicle_docks_disabled and vehicles_disabled) are part of the consumer GBFS spec. Users wouldn't care how many bikes/docks are disabled, only how many are functional. Any idea why this is in the spec (and does it make sense to make it clear in description)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I should do that. Change incoming.

\- num_docks_available | Yes | Number of docks accepting bike returns
\- num_docks_available | Conditionally Required | Number of docks accepting returns of any vehicle type. This field is not required if the `vehicle_docks_available` field has been defined. This field should only be used if every dock at the station is able to accept every vehicle type in the system
\- num_docks_disabled | Optional | Number of empty but disabled dock points at the station. This value remains as part of the spec as it is possibly useful during development
\- is_installed | Yes | 1/0 boolean - is the station currently on the street
\- is_renting | Yes | 1/0 boolean - is the station currently renting bikes (even if the station is empty, if it is set to allow rentals this value should be 1)
\- is_returning | Yes | 1/0 boolean - is the station accepting bike returns (if a station is full but would allow a return if it was not full then this value should be 1)
\- last_reported | Yes | Integer POSIX timestamp indicating the last time this station reported its status to the backend
\- vehicle_docks_available | Conditionally Required | This field is required if the [vehicle_types.json](#vehicle_typesjson) file has been defined and the `num_docks_available` field is not defined. This field's value is an object consisting of keys that are vehicle_type_ids as described in [vehicle_types.json](#vehicle_typesjson) and values that represent the number of docks accepting vehicle returns of vehicles of the respective vehicle type. If a single dock can accept multiple types, these should be added to the count of available docks for each applicable vehicle type.
Copy link

Choose a reason for hiding this comment

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

We wouldn't use it ourselves in Transit but I know compagnies that use GBFS for statical analysis and prediction of dock availability. If a single dock is included in the count of multiple types that will be hard/impossible to analyze in the same way. Not a deal breaker for us but could be for other companies. I know that Quicit did something similar.

Copy link

Choose a reason for hiding this comment

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

It seems like this change makes it difficult for clients to understand how many total docks are available. For example, let's say the station accepts bikes, e-bikes, and scooters. There are 5 bike docks, 5 e-bike docks, and 5 scooter docks available. So are there 5 available docks if you have a bike or e-bike, or 10? How would you know that the docks are specific in what they can accept or not?

Additionally, this requires knowledge from another feed, which makes it especially difficult to understand the dock situation.

Copy link
Contributor

Choose a reason for hiding this comment

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

If the optional station_information.capacity field was provided, then consumers could know the total capacity. I think appropriate spec here depends on the needs of consumers. If consumers need more precision, then the proposed vehicle_docks_available object could instead include an array of vehicle_type_id.

What do you think?
@kanagy @gcamp

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've also been wondering this and do believe it would be challenging to make a UI that shows dock availability according to vehicle type. Overall it does seem like it would be useful to provide an overall metric of the total number of docks available, but I still think it's critical to include vehicle-specific dock availability info as well.

Looking at how I worded the spec, I think it would make sense to make a change to always require the station_information.json#capacity and station_status.json#num_docks_available fields and indicate that it always represents the total amount of docks regardless of whether certain docks only accept certain vehicle types. In a system that omits the vehicle_types.json file, this would indicate the number of docks at the station (according to station_information.json#capacity) and those that are currently available (according to station_status.json#num_docks_available). And in systems that include the vehicle_types.json this could represent the total number of docks/current availability of docks regardless of the compatibility of each dock with each vehicle type.

Copy link

Choose a reason for hiding this comment

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

I agree with making station_status.num_docks_available always required. In addition, you may want to change vehicle_docks_available so you can represent exclusivity better. For example: vehicle_docks_available: [{'vehicle_type': ['ebike', 'bike'], 'count': 5}].

\- vehicle_docks_disabled | Optional | An object consisting of keys that are vehicle_type_ids as described in [vehicle_types.json](#vehicle_typesjson) and values that represent the number of empty but disabled dock points for vehicles of the respective vehicle type at the station.
\- vehicles_available | Conditionally Required | This field is required if the [vehicle_types.json](#vehicle_typesjson) file has been defined. This field's value is an object consisting of keys that are vehicle_type_ids as described in [vehicle_types.json](#vehicle_typesjson) and values that represent the number of vehicles of the respective vehicle type available for rental
Copy link

Choose a reason for hiding this comment

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

There's no way to know the current_range_meters for vehicles in a station. We can potentially use the max_range_meters from the vehicle but that might be inaccurate.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right. This seems like a critical design flaw. I'll work on revising my PR in light of this.

\- vehicles_disabled | Optional | An object consisting of keys that are vehicle_type_ids as described in [vehicle_types.json](#vehicle_typesjson) and values that represent the number of disabled vehicles of the respective vehicle type at the station. Vendors who do not want to publicize the number of disabled vehicles or docks in their system can opt to omit station capacity (in station_information), num_vehicles_disabled and num_docks_disabled.

Example:

```json
{
"last_updated": 1434054678,
"ttl": 0,
"data": {
"stations": [
{
"station_id": "station 1",
"is_installed": 1,
"is_renting": 1,
"is_returning": 1,
"last_reported": 1434054678,
"vehicles_available": {
"abc123": 3,
"def456": 4
},
"vehicle_docks_available": {
"abc123": 2,
"def456": 1
}
}, {
"station_id": "station 2",
"is_installed": 1,
"is_renting": 1,
"is_returning": 1,
"last_reported": 1434054678,
"num_docks_available": 8,
"vehicles_available": {
"abc123": 2,
"def456": 3
}
}
]
}
}
```


### free_bike_status.json
Describes bikes that are not at a station and are not currently in the middle of an active ride.
Expand All @@ -218,6 +325,38 @@ bikes | Yes | Array that contains one object per bike that is
\- lon | Yes | Longitude of the bike. The field value must be a valid WGS 84 latitude in decimal degrees format. See: http://en.wikipedia.org/wiki/World_Geodetic_System, https://en.wikipedia.org/wiki/Decimal_degrees
\- is_reserved | Yes | 1/0 value - is the bike currently reserved for someone else
\- is_disabled | Yes | 1/0 value - is the bike currently disabled (broken)
\- vehicle_type_id | Conditionally Required | The vehicle_type_id of this vehicle as described in [vehicle_types.json](#vehicle_typesjson). This field is required if the [vehicle_types.json](#vehicle_typesjson) is defined.
\- range | Optional | If the vehicle has a motor, this value represents the furthest distance in meters that the vehicle can travel without recharging or refueling with the vehicle's current charge or fuel.
Copy link

Choose a reason for hiding this comment

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

current_range_meters would be a more explicit name. "current" makes it clear what range is being referred to and its nice to make the units explicit. Similarly, I'd prefer if max_range was renamed to max_range_meters.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good, I implemented this as you recommended.


Copy link

Choose a reason for hiding this comment

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

Can we add a last_reported field here, which would optionally specify the timestamp when the bike was last reported (defaulting to feed last_updated)? It would be consistent with station_status.json, which already has last_reported.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added this field and marked it as required. I believe this might introduce a breaking change, so if I need to mark it as optional in order to be backwards-compatible, I will do so.

Example:

```json
{
"last_updated": 1434054678,
"ttl": 0,
"data": {
"bikes": [
{
"bike_id": "ghi789",
"lat": 12.34,
"lon": 56.78,
"is_reserved": 0,
"is_disabled": 0,
"vehicle_type_id": "abc123"
}, {
"bike_id": "jkl012",
"lat": 12.34,
"lon": 56.78,
"is_reserved": 0,
"is_disabled": 0,
"vehicle_type_id": "def456",
"range": 450
}
]
}
}
```


### system_hours.json
Describes the system hours of operation. A JSON array of hours defined as follows:
Expand Down Expand Up @@ -325,9 +464,6 @@ There are some items that were proposed in an earlier version of this document b
* _equipment_ - Removed due to a lack of specificity behind the intent of this field and a question about the actual relevance to the public
* _jurisdictions_ - It is believed that the need for this field is negated by the presence of the system_regions.json feed

* station_status.json
* need a way to distinguish between multiple bike types at a station if/when hybrid systems using e-bikes become available

## Disclaimers

_Apple Pay, PayPass and other third-party product and service names are trademarks or registered trademarks of their respective owners._
Expand Down