Skip to content

Given a GTFS Static feed, add GTFS Flex v2 to model on-demand public transport service.

License

Notifications You must be signed in to change notification settings

derhuerst/generate-gtfs-flex

Repository files navigation

generate-gtfs-flex

Given a GTFS Static feed, add GTFS Flex v2 to model on-demand public transport service.

ISC-licensed

Note: In order to get the behaviour we want (pickup only at stops but flexible drop-off within 300m), we currently don't follow the spec as intended; See #5 and #6 for details.

Installation

npm install derhuerst/generate-gtfs-flex
# or
docker pull docker.io/derhuerst/generate-gtfs-flex

Getting started

The scripts in this repo are written to be used with any GTFS feed. But there's also a file herrenberg-flex-rules.js, which specifies the on-demand lines in Herrenberg, Germany (part of VVS).

The following steps will demonstrate how to use the scripts with herrenberg-flex-rules.js, in order to patch the VVS GTFS feed with GTFS-Flex data. You must have Node.js installed (which includes the npm CLI).

# set up an empty npm project
mkdir flex
cd flex
npm init --yes

# download and unzip 2022-01-17 VVS GTFS feed
# get the latest feed at https://www.opendata-oepnv.de/ht/de/organisation/verkehrsverbuende/vvs/startseite?tx_vrrkit_view%5Bdataset_name%5D=soll-fahrplandaten-vvs&tx_vrrkit_view%5Bdataset_formats%5D%5B0%5D=ZIP&tx_vrrkit_view%5Baction%5D=details&tx_vrrkit_view%5Bcontroller%5D=View
wget 'https://www.opendata-oepnv.de/dataset/d1768457-c717-45ea-8e26-dd1e759d5ffe/resource/ebc2eaae-9a03-4ace-8df7-28df10a80993/download/google_transit.zip' -O vvs.gtfs.zip
unzip -d vvs-gtfs vvs.gtfs.zip

# install generate-gtfs-flex as a development dependency
npm install --save-dev derhuerst/generate-gtfs-flex

# patch GTFS-Flex data into the VVS GTFS feed
npm exec --offline generate-locations-geojson \
	node_modules/generate-gtfs-flex/herrenberg-flex-rules.js \
	vvs-gtfs/{routes,trips,stops,stop_times}.txt \
	>vvs-gtfs/locations.geojson
npm exec --offline generate-booking-rules-txt \
	node_modules/generate-gtfs-flex/herrenberg-flex-rules.js \
	vvs-gtfs/routes.txt \
	>vvs-gtfs/booking_rules.txt
npm exec --offline patch-trips-txt \
	node_modules/generate-gtfs-flex/herrenberg-flex-rules.js \
	vvs-gtfs/{routes,trips,stops,stop_times}.txt \
	| sponge vvs-gtfs/trips.txt
npm exec --offline patch-routes-txt \
	node_modules/generate-gtfs-flex/herrenberg-flex-rules.js \
	vvs-gtfs/routes.txt \
	| sponge vvs-gtfs/routes.txt
npm exec --offline patch-stop-times-txt \
	node_modules/generate-gtfs-flex/herrenberg-flex-rules.js \
	vvs-gtfs/{routes,trips,stops,stop_times}.txt \
	| sponge vvs-gtfs/stop_times.txt

pro tip: If you install the package globally (via npm install derhuerst/generate-gtfs-flex -g), npm will put the scripts into your $PATH, so instead of running ./node_modules/.bin/…, you'll be able to just use them as documented below.

Usage

Usage:
    generate-locations-geojson <path-to-flex-rules> <gtfs-routes> <gtfs-trips> <gtfs-stops> <gtfs-stop-times>
Examples:
    generate-locations-geojson flex-rules.js \
        gtfs/{routes,trips,stops,stop_times}.txt >gtfs/locations.geojson
Usage:
    generate-booking-rules-txt <path-to-flex-rules> <gtfs-routes>
Examples:
    generate-booking-rules-txt flex-rules.js gtfs/routes.txt >gtfs/booking_rules.txt
Usage:
    patch-routes-txt <path-to-flex-rules> <gtfs-routes>
Examples:
    patch-routes-txt flex-rules.js gtfs/routes.txt >gtfs/routes.patched.txt
Usage:
    patch-trips-txt <path-to-flex-rules> <gtfs-routes> <gtfs-trips> <gtfs-stops> <gtfs-stop-times>
Examples:
    patch-trips-txt flex-rules.js \
        gtfs/{routes,trips,stops,stop_times}.txt >gtfs/trips.patched.txt
Usage:
    patch-stop-times-txt <path-to-flex-rules> <gtfs-routes> <gtfs-trips> <gtfs-stops> <gtfs-stop-times>
Examples:
    patch-stop-times-txt flex-rules.js \
        gtfs/{routes,trips,stops,stop_times}.txt >gtfs/stop_times.patched.txt

Note: Currently, generate-gtfs-flex inserts all trips & stop_times rows affected by any of the rules twice: One on-demand trip stopping directly at the stops, one trip stopping at Flex areas.

with Docker

You can use the docker.io/derhuerst/generate-gtfs-flex Docker image. It will call the tools documented above on a GTFS feed that you mount into the container:

docker run -v /path/to/gtfs:/gtfs --rm -it docker.io/derhuerst/generate-gtfs-flex

⚠️ This will overwrite the original routes.txt, trips.txt & stop_times.txt files.

with your own GTFS feed & GTFS-Flex rules

You can use the scripts in this repo with any GTFS feed. As an example, we're going to patch sample-gtfs-feed's A ("Ada Lovelace Bus Line") route to have flexible on-demand drop-offs.

# as above, initialise an empty npm project & install generate-gtfs-flex
mkdir sample-gtfs-feed-with-flex
cd sample-gtfs-feed-with-flex
npm init --yes
npm install --save-dev sample-gtfs-feed derhuerst/generate-gtfs-flex

We're going to write a file flex-rules.js that exports a list of GTFS-Flex rules. Each of these rules is a function that must, when given a routes.txt entry/row, return either null to leave it unchanged or return a GTFS-Flex spec (check out the schema) to patch it:

const pickupTypes = require('gtfs-utils/pickup-types')
const dropOffTypes = require('gtfs-utils/drop-off-types')
const bookingTypes = require('gtfs-utils/booking-types')

const adaLovelaceFlexibleDropOff = (route) => {
	if (route.route_id !== 'A') return null // leave route unchanged
	return {
		id: 'A-flexible-drop-off', // ID of the GTFS-Flex spec
		radius: .200, // flexible drop-off within 200m of a stop
		pickup_type: pickupTypes.MUST_PHONE_AGENCY,
		drop_off_type: dropOffTypes.MUST_COORDINATE_WITH_DRIVER,
		bookingRule: {
			// ID of the GTFS-BookingRules booking_rules.txt entry/row to be generated
			booking_rule_id: 'flexible-drop-off',
			booking_type: bookingTypes.SAME_DAY,
			prior_notice_duration_min: 30,
			message: 'Get dropped off right at home! Please call 30min before.',
			booking_url: 'https://example.org/flex'
		},
	}
}

module.exports = [
	adaLovelaceFlexibleDropOff,
]

We can now patch the GTFS-Flex rules into sample-gtfs-feed's GTFS feed:

# copy the GTFS feed first, so that we don't mutate node_modules
# Note: You can benefit from copy-on-write using `-c` (BSD/macOS) or `--reflink=auto` (GNU/Linux).
cp -r node_modules/sample-gtfs-feed/gtfs gtfs

npm exec --offline generate-locations-geojson \
	flex-rules.js gtfs/{routes,trips,stops,stop_times}.txt \
	>gtfs/locations.geojson
npm exec --offline generate-booking-rules-txt \
	flex-rules.js gtfs/routes.txt \
	>gtfs/booking_rules.txt
npm exec --offline patch-routes-txt \
	flex-rules.js gtfs/routes.txt \
	| sponge gtfs/routes.txt
npm exec --offline patch-trips-txt \
	flex-rules.js gtfs/{routes,trips,stops,stop_times}.txt \
	| sponge gtfs/trips.txt
npm exec --offline patch-stop-times-txt \
	flex-rules.js gtfs/{routes,trips,stops,stop_times}.txt \
	| sponge gtfs/stop_times.txt

Contributing

If you have a question or need support using generate-gtfs-flex, please double-check your code and setup first. If you think you have found a bug or want to propose a feature, use the issues page.

About

Given a GTFS Static feed, add GTFS Flex v2 to model on-demand public transport service.

Topics

Resources

License

Stars

Watchers

Forks

Contributors 4

  •  
  •  
  •  
  •