Skip to content

[Archived] Speed Visualizations (SpeedViz) Design Proposal

Eddy Ionescu edited this page Jul 8, 2018 · 1 revision

Requirements

Visualize speed of buses on a map with red/yellow/green highlights (with each one having a speed).

Client Requirements

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:

  1. they correspond to the submitted time interval
  2. they're not overlapping for the same route
  3. together, they form a continuous route
  4. there's not a ridiculous number of SpeedEdges (less than 1000 per route)

API Requirements

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:

  1. Get all vehicleLocations within the time interval for those routes
  2. 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]
}
  1. 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.

  2. 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.

  1. 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.

  1. Generate relative scores and return the speed edges.
speedEdges: [SpeedEdge]

Stack: NodeJS, GraphQL, Cassandra

Orion and DB Requirements

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)

Reviewers

(add your name with relevant comments and whether it should move forward)