-
Notifications
You must be signed in to change notification settings - Fork 6
[Archived] Speed Visualizations (SpeedViz) Design Proposal
Visualize speed of buses on a map with red/yellow/green highlights (with each one having a speed).
Client fulfills requirements by requiring a list of speed-edges, having the following schema:
Route, Coordinate (see Vehicle Locations - https://github.com/trynmaps/orion/wiki/Vehicle-Locations)
Score {
score: Number (1 to 10)
}
SpeedEdge {
route: Route
start: Coordinate
end: Coordinate
speed: Number
relativeScore: Score
}
Assumptions:
- they correspond to the submitted time interval
- they're not overlapping for the same route
- together, they form a continuous route
- there's not a ridiculous number of SpeedEdges (less than 1000 per route)
API fulfills the client's requests by making use of {agency}_realtime_vehicles
tables from the database.
The vehicle locations schema can be found in Vehicle Locations - https://github.com/trynmaps/orion/wiki/Vehicle-Locations.
Client Request:
- routes
- startTime
- endTime
Workflow:
- Get all vehicleLocations within the time interval for those routes
- For each vehicle, generate a LinkedVehicle
A LinkedVehicle is a vehicle that contains an ordered list of (time, coordinates) pairs, sorted in ascending order by time. The pairs are all consecutive states.
This is generated by iterating through all the vehicleLocations obtained for each state (timestamp).
Position: {
position: (time: String, coordinate: Coordinate)
}
LinkedVehicle: {
...Vehicle
positions: [Position]
}
-
Since the GPS coordinates are bound to have some error, we "snap" them onto the route, as defined by the route in the geoJSON. This'll be done by
routeify
(https://github.com/trynmaps/orion/wiki/Routeify-Design-Proposal), which takes in the LinkedVehicles and returns them with modified/snapped positions. -
For each LinkedVehicle, generate a LinkedVehicleSpeeds, which contains the speedEdges the client needs. Since the straight-line distance won't be accurate, we have to measure the distance between the coordinates based on the distance from the route.
routeify
will do this too (fortunately they've already been snapped to the route).
LinkedVehicleSpeeds: {
linkedVehicle: LinkedVehicle
speedEdges: [(startPosition: Position, endPosition: Position, speed: Number)]
}
At this point, we could just return this object, but it would violate assumptions 2-4. Here's a diagram to clarify things: https://docs.google.com/drawings/d/1NA_uo9TKhdykwRYVBVygyhStvKmdPbmQH29cQAUfg8k/edit?usp=sharing
Sidenote: this could potentially be stored in a graph database as to get really fast reads.
- Now we turn all these overlapping edges into a list of continuous edges (one for each route).
5.1. We'll first do this by sorting them based on how close (along the route the startPosition is to the route's starting point. routeify
will do this for us.
5.2. We'll then combine overlapping edges, where for any overlap between any two edges, a new edge with the average value of the two is created. routeify
will also do this for us.
5.3. We could also have a gap between edges, so we "extend them" by adding in a new edge containing their average speed. This is expected to happen when the time interval is too short to see a vehicle complete its route.
- Generate relative scores and return the speed edges.
speedEdges: [SpeedEdge]
Stack: NodeJS, GraphQL, Cassandra
Assumptions:
- is a bus is active on a route during a certain time interval, it appears in all the states.
- the DB can deliver the data in a timely manner
Flawed Assumptions:
- a bus's location will update every state. (in reality, Nextbus is expected to update every 60 seconds (which it usually does), as will the winner of Muni's RFP - RIP any dreams of Muni streaming data)
(add your name with relevant comments and whether it should move forward)