init
This commit is contained in:
parent
da66b6a3fb
commit
0084ecff0c
81
README.md
81
README.md
@ -1,3 +1,80 @@
|
|||||||
# osrm
|
# OSRM (Open Source Routing Machine) API Lua SDK
|
||||||
|
|
||||||
SDK для Open Source Routing Machine (OSRM)
|
API: https://project-osrm.org/docs/v5.24.0/api/
|
||||||
|
|
||||||
|
## Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
local api = require('osrm.api')
|
||||||
|
local json = require('cjson')
|
||||||
|
|
||||||
|
res,err = api.route({{13.428555,52.523219},{13.428545,52.523249}})
|
||||||
|
|
||||||
|
res,err = api.route({{13.428555,52.523219},{13.428545,52.523249}},'walking')
|
||||||
|
|
||||||
|
if not err then print(json.encode(res)) else print(json.encode(res)..err) end
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Profiles
|
||||||
|
|
||||||
|
- driving
|
||||||
|
- walking
|
||||||
|
- cycling
|
||||||
|
|
||||||
|
|
||||||
|
## Services
|
||||||
|
|
||||||
|
### Nearest service
|
||||||
|
|
||||||
|
Snaps a coordinate to the street network and returns the nearest n matches.
|
||||||
|
|
||||||
|
```
|
||||||
|
nearest(coords,profile,options)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Route service
|
||||||
|
|
||||||
|
Finds the fastest route between coordinates in the supplied order.
|
||||||
|
|
||||||
|
```
|
||||||
|
route(coords,profile,options)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Table service
|
||||||
|
|
||||||
|
Computes the duration of the fastest route between all pairs of supplied coordinates. Returns the durations or distances or both between the coordinate pairs. Note that the distances are not the shortest distance between two coordinates, but rather the distances of the fastest routes. Duration is in seconds and distances is in meters.
|
||||||
|
|
||||||
|
```
|
||||||
|
table(coords,profile,options)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Match service
|
||||||
|
|
||||||
|
Map matching matches/snaps given GPS points to the road network in the most plausible way. Please note the request might result multiple sub-traces. Large jumps in the timestamps (> 60s) or improbable transitions lead to trace splits if a complete matching could not be found. The algorithm might not be able to match all points. Outliers are removed if they can not be matched successfully.
|
||||||
|
|
||||||
|
```
|
||||||
|
match(coords,profile,options)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Trip service
|
||||||
|
|
||||||
|
The trip plugin solves the Traveling Salesman Problem using a greedy heuristic (farthest-insertion algorithm) for 10 or more waypoints and uses brute force for less than 10 waypoints. The returned path does not have to be the fastest path. As TSP is NP-hard it only returns an approximation. Note that all input coordinates have to be connected for the trip service to work.
|
||||||
|
|
||||||
|
```
|
||||||
|
trip(coords,profile,options)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tile service
|
||||||
|
|
||||||
|
This service generates Mapbox Vector Tiles that can be viewed with a vector-tile capable slippy-map viewer.
|
||||||
|
|
||||||
|
```
|
||||||
|
tile(x,y,zoom,profile)
|
||||||
|
|
||||||
|
```
|
||||||
|
|||||||
52
config/config.lua
Executable file
52
config/config.lua
Executable file
@ -0,0 +1,52 @@
|
|||||||
|
local json = require('cjson.safe')
|
||||||
|
local _M = {}
|
||||||
|
_M.data = {}
|
||||||
|
_M.comments = {}
|
||||||
|
_M.file = '' -- файл конфигурации
|
||||||
|
local key
|
||||||
|
|
||||||
|
function _M.read()
|
||||||
|
for line in io.lines(_M.file) do
|
||||||
|
key = string.match(line, '([%w_]+)::')
|
||||||
|
if (key) then
|
||||||
|
_M.data[key] = string.match(line, '::(.*) #')
|
||||||
|
_M.comments[key] = string.match(line, '#(.*)')
|
||||||
|
if string.find(_M.data[key],'%{%"') or string.find(_M.data[key],'%[%"') then
|
||||||
|
_M.data[key] = json.decode(_M.data[key])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function reprint(k,v)
|
||||||
|
if type(v) == 'table' then
|
||||||
|
for i,j in pairs(v) do
|
||||||
|
reprint(i,j)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
print(k..': '..v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function _M.data:write()
|
||||||
|
local config_file = io.open(_M.file, 'w')
|
||||||
|
for k,v in pairs(self) do
|
||||||
|
if type(v) ~= 'function' then
|
||||||
|
if type(v) == 'table' then v = json.encode(v) end
|
||||||
|
config_file:write(k..'::'..v..' #'.._M.comments[key]..'\n')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
config_file:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function _M.data:print()
|
||||||
|
for k,v in pairs(self) do
|
||||||
|
if type(v) ~= 'function' then
|
||||||
|
if _M.comments[k] then print('\n'.._M.comments[k]:gsub("^%s*(.-)%s*$", "%1")..': \n') end
|
||||||
|
reprint(k,v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return _M
|
||||||
|
|
||||||
5
config/osrm.lua
Executable file
5
config/osrm.lua
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
local config = require('config.config')
|
||||||
|
local _M = config
|
||||||
|
_M.file = 'osrm.conf' -- файл конфигурации
|
||||||
|
_M.read()
|
||||||
|
return _M.data
|
||||||
3
osrm.conf
Normal file
3
osrm.conf
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
url::http://router.project-osrm.org/ #API URL
|
||||||
|
version::v1 #API VERSION
|
||||||
|
format::json #Output format (or flatbuffers)
|
||||||
151
osrm/api.lua
Normal file
151
osrm/api.lua
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
local json = require('cjson')
|
||||||
|
local cURL = require("cURL")
|
||||||
|
local date = require("date")
|
||||||
|
local log = require('utils.log')
|
||||||
|
local config = require('config.osrm')
|
||||||
|
|
||||||
|
local _M = {}
|
||||||
|
_M.result = nil
|
||||||
|
_M.base = config.url
|
||||||
|
_M.format = config.format
|
||||||
|
log.outfile = 'logs/osrm_'..os.date('%Y-%m-%d')..'.log'
|
||||||
|
log.level = 'trace'
|
||||||
|
_M.profile = 'driving' -- location /route/v1/driving location /route/v1/walking location /route/v1/cycling
|
||||||
|
|
||||||
|
function defaults()
|
||||||
|
return {
|
||||||
|
['generate_hints'] = true,
|
||||||
|
['snapping'] = 'default',
|
||||||
|
['skip_waypoints'] = false
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function coordinates(coords)
|
||||||
|
if coords[1] then
|
||||||
|
if type(coords[1]) == 'number' then return table.concat(coords,',') end
|
||||||
|
local out = {}
|
||||||
|
for i,c in pairs(coords) do table.insert(out,table.concat(c,',')) end
|
||||||
|
return table.concat(out,';')
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function query(data)
|
||||||
|
if not data then return '' end
|
||||||
|
local str = '?'
|
||||||
|
for k,v in pairs(data) do
|
||||||
|
if str == '?' then str = str..k..'='..tostring(v)
|
||||||
|
else str = str..'&'..k..'='..tostring(v) end
|
||||||
|
end
|
||||||
|
return str
|
||||||
|
end
|
||||||
|
|
||||||
|
function get_result(str,url)
|
||||||
|
local result, err = pcall(json.decode,str)
|
||||||
|
if result then
|
||||||
|
_M.result = json.decode(str)
|
||||||
|
else
|
||||||
|
log.error(url..':'..err)
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
return _M.result
|
||||||
|
end
|
||||||
|
|
||||||
|
function get(service,coords,profile,options)
|
||||||
|
local str = ''
|
||||||
|
local url = ''
|
||||||
|
local res
|
||||||
|
profile = profile or _M.profile
|
||||||
|
if service == 'tile' then
|
||||||
|
url = _M.base..service..'/'..config.version..'/'..profile..'/tile('..table.concat(coords,',')..').mvt'
|
||||||
|
else
|
||||||
|
url = _M.base..service..'/'..config.version..'/'..profile..'/'..coordinates(coords)..query(options)
|
||||||
|
end
|
||||||
|
|
||||||
|
local headers = {
|
||||||
|
'Content-type: application/json',
|
||||||
|
'Accept: application/json'
|
||||||
|
}
|
||||||
|
local c = cURL.easy{
|
||||||
|
url = url,
|
||||||
|
httpheader = headers,
|
||||||
|
writefunction = function(st)
|
||||||
|
str = str..st
|
||||||
|
end
|
||||||
|
}
|
||||||
|
local ok, err = c:perform()
|
||||||
|
local code = c:getinfo_response_code()
|
||||||
|
c:close()
|
||||||
|
if not ok then return nil, err end
|
||||||
|
if code ~= 200 then return {['code']=code,['url']=url},str end
|
||||||
|
if _M.format == 'json' then
|
||||||
|
res,err = get_result(str,url)
|
||||||
|
else
|
||||||
|
res = str
|
||||||
|
end
|
||||||
|
if not res then return nil,err end
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
function _M.route(coords,profile,options)
|
||||||
|
if not options then
|
||||||
|
options = defaults()
|
||||||
|
options['alternatives'] = false
|
||||||
|
options['steps'] = false
|
||||||
|
options['annotations'] = false
|
||||||
|
options['geometries'] = 'polyline'
|
||||||
|
options['overview'] = 'simplified'
|
||||||
|
options['continue_straight'] = 'default'
|
||||||
|
end
|
||||||
|
return get('route',coords,profile,options)
|
||||||
|
end
|
||||||
|
|
||||||
|
function _M.nearest(coords,profile,options)
|
||||||
|
if not options then
|
||||||
|
options = defaults()
|
||||||
|
oprions['number'] = 1
|
||||||
|
end
|
||||||
|
return get('nearest',coords,profile,options)
|
||||||
|
end
|
||||||
|
|
||||||
|
function _M.table(coords,profile,options)
|
||||||
|
if not options then
|
||||||
|
options = defaults()
|
||||||
|
options['annotations'] = 'duration'
|
||||||
|
options['fallback_coordinate'] = 'input'
|
||||||
|
end
|
||||||
|
return get('table',coords,profile,options)
|
||||||
|
end
|
||||||
|
|
||||||
|
function _M.match(coords,profile,options)
|
||||||
|
if not options then
|
||||||
|
options = defaults()
|
||||||
|
options['steps'] = false
|
||||||
|
options['geometries'] = 'polyline'
|
||||||
|
options['annotations'] = false
|
||||||
|
options['overview'] = 'simplified'
|
||||||
|
options['gaps'] = 'split'
|
||||||
|
options['tidy'] = false
|
||||||
|
end
|
||||||
|
return get('match',coords,profile,options)
|
||||||
|
end
|
||||||
|
|
||||||
|
function _M.trip(coords,profile,options)
|
||||||
|
if not options then
|
||||||
|
options = defaults()
|
||||||
|
options['roundtrip'] = true
|
||||||
|
options['source'] = 'any'
|
||||||
|
options['destination'] = 'any'
|
||||||
|
options['steps'] = false
|
||||||
|
options['annotations'] = false
|
||||||
|
options['geometries'] = 'polyline'
|
||||||
|
options['overview'] = 'simplified'
|
||||||
|
end
|
||||||
|
return get('trip',coords,profile,options)
|
||||||
|
end
|
||||||
|
|
||||||
|
function _M.tile(x,y,zoom,profile)
|
||||||
|
return get('tile',profile,{x,y,zoom})
|
||||||
|
end
|
||||||
|
|
||||||
|
return _M
|
||||||
16
test.lua
Normal file
16
test.lua
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
local json = require('cjson')
|
||||||
|
local api = require('osrm.api')
|
||||||
|
local date = require("date")
|
||||||
|
|
||||||
|
res,err = api.route({{48.395994,54.324645},{48.398233,54.343602}})
|
||||||
|
if not err then print(res.routes[1].distance) else print(json.encode(res)..err) end
|
||||||
|
|
||||||
|
res,err = api.route({{13.428555,52.523219},{13.428545,52.523249}},'walking')
|
||||||
|
if not err then print(json.encode(res)) else print(json.encode(res)..err) end
|
||||||
|
|
||||||
|
res,err = api.table({{50.1169,53.1912},{50.1661,53.2172},{50.0839,53.1881},{50.128,53.1985},{50.1057,53.1846}})
|
||||||
|
if not err then print(json.encode(res)) else print(json.encode(res)..err) end
|
||||||
|
|
||||||
|
res,err = api.table({{50.1169,53.1912},{50.1661,53.2172},{50.0839,53.1881},{50.128,53.1985},{50.1057,53.1846}},'driving',{['sources']=0,['destinations']=4})
|
||||||
|
if not err then print(json.encode(res)) else print(json.encode(res)..err) end
|
||||||
|
|
||||||
90
utils/log.lua
Normal file
90
utils/log.lua
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
--
|
||||||
|
-- log.lua
|
||||||
|
--
|
||||||
|
-- Copyright (c) 2016 rxi
|
||||||
|
--
|
||||||
|
-- This library is free software; you can redistribute it and/or modify it
|
||||||
|
-- under the terms of the MIT license. See LICENSE for details.
|
||||||
|
--
|
||||||
|
|
||||||
|
local log = { _version = "0.1.0" }
|
||||||
|
|
||||||
|
log.usecolor = true
|
||||||
|
log.outfile = nil
|
||||||
|
log.level = "trace"
|
||||||
|
|
||||||
|
|
||||||
|
local modes = {
|
||||||
|
{ name = "trace", color = "\27[34m", },
|
||||||
|
{ name = "debug", color = "\27[36m", },
|
||||||
|
{ name = "info", color = "\27[32m", },
|
||||||
|
{ name = "warn", color = "\27[33m", },
|
||||||
|
{ name = "error", color = "\27[31m", },
|
||||||
|
{ name = "fatal", color = "\27[35m", },
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
local levels = {}
|
||||||
|
for i, v in ipairs(modes) do
|
||||||
|
levels[v.name] = i
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local round = function(x, increment)
|
||||||
|
increment = increment or 1
|
||||||
|
x = x / increment
|
||||||
|
return (x > 0 and math.floor(x + .5) or math.ceil(x - .5)) * increment
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local _tostring = tostring
|
||||||
|
|
||||||
|
local tostring = function(...)
|
||||||
|
local t = {}
|
||||||
|
for i = 1, select('#', ...) do
|
||||||
|
local x = select(i, ...)
|
||||||
|
if type(x) == "number" then
|
||||||
|
x = round(x, .01)
|
||||||
|
end
|
||||||
|
t[#t + 1] = _tostring(x)
|
||||||
|
end
|
||||||
|
return table.concat(t, " ")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
for i, x in ipairs(modes) do
|
||||||
|
local nameupper = x.name:upper()
|
||||||
|
log[x.name] = function(...)
|
||||||
|
|
||||||
|
-- Return early if we're below the log level
|
||||||
|
if i < levels[log.level] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local msg = tostring(...)
|
||||||
|
local info = debug.getinfo(2, "Sl")
|
||||||
|
local lineinfo = info.short_src .. ":" .. info.currentline
|
||||||
|
|
||||||
|
-- Output to console
|
||||||
|
print(string.format("%s[%-6s%s]%s %s: %s",
|
||||||
|
log.usecolor and x.color or "",
|
||||||
|
nameupper,
|
||||||
|
os.date("%H:%M:%S"),
|
||||||
|
log.usecolor and "\27[0m" or "",
|
||||||
|
lineinfo,
|
||||||
|
msg))
|
||||||
|
|
||||||
|
-- Output to log file
|
||||||
|
if log.outfile then
|
||||||
|
local fp = io.open(log.outfile, "a")
|
||||||
|
local str = string.format("[%-6s%s] %s: %s\n",
|
||||||
|
nameupper, os.date(), lineinfo, msg)
|
||||||
|
fp:write(str)
|
||||||
|
fp:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return log
|
||||||
Loading…
x
Reference in New Issue
Block a user