Skip to content
This repository has been archived by the owner on Jul 11, 2019. It is now read-only.

Commit

Permalink
allow OTP to be configured as an alternate source for transit data
Browse files Browse the repository at this point in the history
  • Loading branch information
atogle committed Apr 16, 2012
1 parent bfc4a7e commit 210025d
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 2 deletions.
25 changes: 23 additions & 2 deletions choices.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require 'cgi'
require './fare.rb'
require './constants.rb'
require './otp.rb'

require 'pp'
def get_info_from_bing(params)
Expand All @@ -15,7 +16,7 @@ def get_info_from_bing(params)
}.map {|k,v| "#{k}=#{CGI.escape(v)}"}*"&"
modes=%w{driving walking transit}

results =modes.map do |mode|
results = modes.map do |mode|
Thread.new do
begin
usable_url=URI.parse(base_url+mode+query_params)
Expand Down Expand Up @@ -124,6 +125,10 @@ def calculate_transit_by_bing_resource(resource)
return [200,{},JSON.pretty_generate(results)]
end

# Save the geocoded address points in an array [lat,lon] for OTP to use
origin = results["driving"]["routeLegs"][0]["actualStart"]["coordinates"]
destination = results["driving"]["routeLegs"][0]["actualEnd"]["coordinates"]

if (resource=results["driving"])
results["driving"]=generic_by_bing_resource(resource)
results["driving"][:emissions] = results["driving"][:distance] * SOV_LBS_CO2_PASSENGER_KM
Expand All @@ -150,7 +155,23 @@ def calculate_transit_by_bing_resource(resource)
results["biking"][:emissions] = 0
results["biking"][:cost]= (results["biking"][:distance] * BIKING_COST_PER_KM).round(2)
end
if (resource=results["transit"])

# If we have an OTP config for both the origin and destination, then use OTP over Bing
if (has_otp_config(origin[0], origin[1]) && has_otp_config(destination[0], destination[1]))
params = {
:origin => origin,
:destination => destination,
:date => Date.today.strftime("%m/%d/%Y"),
:time => Time.now.strftime("%I:%M %p")
}

resource = get_info_from_otp(params)
results["transit"][:duration] = resource[:duration]
results["transit"][:calories] = resource[:walk_duration] * CALORIES_PER_SECOND_WALKING + resource[:transit_duration] * CALORIES_PER_SECOND_SITTING
results["transit"][:emissions] = results["driving"][:distance] * BUS_LBS_CO2_PASSENGER_KM
results["transit"][:cost] = resource[:cost]
# If we got results from Bing and there's not OTP, use Bing
elsif (resource=results["transit"])
resource[:distance] = results["driving"][:distance]
results["transit"] = calculate_transit_by_bing_resource(resource)
end
Expand Down
9 changes: 9 additions & 0 deletions constants.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@
SOV_LBS_CO2_PASSENGER_KM = 0.597 #Average SOV car pounds of CO2 emitted per km (0.96 * 0.6214)
BUS_LBS_CO2_PASSENGER_KM = 0.404 #Average bus pounds of CO2 emitted per km (0.65 * 0.6214)

# Map a bbox (left, bottom, right, top) to an OTP service url
# You can get the bbox from the /meta route on your OTP service
OTP_MAPPING = [
{
"bbox" => {"min_lon"=>-75.56027, "min_lat"=>38.92998, "max_lon"=>-71.91406, "max_lat"=>41.85966},
"url" =>"http://nyc.deployer.opentripplanner.org/opentripplanner-api-webapp/ws/"
}
]

GTFS_MAPPING = {
"San Francisco Municipal Transportation Agency"=>["MUNI_google_transit","SFMTA"],
"Bay Area Rapid Transit"=>["BART_google_transit","BART"],
Expand Down
57 changes: 57 additions & 0 deletions otp.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
require 'cgi'
require 'net/http'
require 'json'
require 'pp'
require './constants'

# Is this point within the configured bbox of an OTP instance?
def has_otp_config(lat, lon)
match = OTP_MAPPING.select {|m| lon >= m["bbox"]["min_lon"] && lon <= m["bbox"]["max_lon"] &&
lat >= m["bbox"]["min_lat"] && lat <= m["bbox"]["max_lat"] }
!match.empty?
end

# Get the base url for the OTP instance for this point
def get_otp_url(lat, lon)
match = OTP_MAPPING.select {|m| lon >= m["bbox"]["min_lon"] && lon <= m["bbox"]["max_lon"] &&
lat >= m["bbox"]["min_lat"] && lat <= m["bbox"]["max_lat"] }
match.first["url"] if !match.empty?
end

# Get the important data from OTP
def get_info_from_otp(params)
base_url=get_otp_url(params[:origin][0], params[:origin][1])

# Do we have a url?
if (!base_url.nil?)

# Params to pas to OTP
query_params = "plan?" + {
"arriveBy" => "false",
"date" => params[:date] || Date.today.strftime("%m/%d/%Y"),
"time" => params[:time] || Time.now.strftime("%I:%M %p"),
"mode" => "TRANSIT,WALK",
"optimize" => "QUICK",
"maxWalkDistance" => "1260",
"toPlace" => params[:origin].join(","),
"fromPlace" => params[:destination].join(",")
}.map {|k,v| "#{k}=#{CGI.escape(v)}"}*"&"

uri = URI.parse(base_url+query_params)
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
# Be sure to ask for JSON
request.initialize_http_header({"Accept" => "application/json"})

# puts "calling url #{uri}"
res = JSON.parse(http.request(request).body)

{
:walk_duration => res["plan"]["itineraries"].first["walkTime"],
:transit_duration => res["plan"]["itineraries"].first["transitTime"],
:wait_duration => res["plan"]["itineraries"].first["waitingTime"],
:duration => res["plan"]["itineraries"].first["duration"].fdiv(1000),
:cost => res["plan"]["itineraries"].first["fare"]["fare"]["regular"]["cents"].fdiv(100) || nil
}
end
end

0 comments on commit 210025d

Please sign in to comment.