Giter VIP home page Giter VIP logo

gis-ops / routingpy Goto Github PK

View Code? Open in Web Editor NEW
247.0 10.0 25.0 24.14 MB

🌎 Python library to access all public routing, isochrones and matrix APIs in a consistent manner.

Home Page: https://routingpy.readthedocs.io/en/latest/?badge=latest

License: Apache License 2.0

Python 100.00%
routing isochrones distance-matrix python3 api spatial-analysis navigation graphhopper openrouteservice valhalla

routingpy's Introduction

routingpy

tests

Documentation Status

MyBinder.org

One lib to route them all - routingpy is a Python 3 client for several popular routing webservices.

Inspired by geopy and its great community of contributors, routingpy enables easy and consistent access to third-party spatial webservices to request route directions, isochrones or time-distance matrices.

routingpy currently includes support for the following services:

This list is hopefully growing with time and contributions by other developers. An up-to-date list is always available in our documentation.

routing-py is tested against CPython versions 3.8, 3.9, 3.10, 3.11. PyPy3 is currently not supported, see #60.

© routingpy contributors 2022 under the Apache 2.0 License.

routing-py-image

Why routingpy?

You want to

  • get from A to B by transit, foot, bike, car or hgv
  • compute a region of reachability
  • calculate a time distance matrix for a N x M table

and don't know which provider to use? Great. Then routingpy is exactly what you're looking for.

For the better or worse, every provider works on different spatial global datasets and uses a plethora of algorithms on top. While Google or HERE build on top of proprietary datasets, providers such as Mapbox or Graphhopper consume OpenStreetMap data for their base network. Also, all providers offer a different amount of options one can use to restrict the wayfinding. Ultimately this means that results may differ - and our experience tells us: they do, and not too little. This calls for a careful evaluation which service provider to use for which specific use case.

With routingpy we have made an attempt to simplify this process for you.

Installation

PyPI version

Recommended: Install via poetry:

Install using pip with

Or the lastest from source

API

Every provider has its own specifications and features. However the basic blueprints are the same across all. We tried hard to make the transition from one provider to the other as seamless as possible. We follow two dogmas for all implementations:

  • All basic parameters have to be the same for all routers for each endpoint
  • All routers still retain their special parameters for their endpoints, which make them unique in the end

This naturally means that usually those basic parameters are not named the same way as the endpoints they query. However, all provider specific parameters are named the exact same as their remote counterparts.

The following table gives you an overview which basic arguments are abstracted:

Endpoint Argument Function

directions

locations

-------------------+

profile

Specify the locations to be visited in order. Usually this
is done with [Lon, Lat] tuples, but some routers offer
additional options to create a location element.
--------------------------------------------------------------+
The mode of transport, i.e. car, bicycle, pedestrian. Each
router specifies their own profiles.

isochrones

locations

-------------------+

profile

-------------------+

intervals

-------------------+

intervals _type

Specify the locations to calculate isochrones for. Usually
this is done with [Lon, Lat] tuples, but some routers
offer additional options to create a location element.
--------------------------------------------------------------+
The mode of transport, i.e. car, bicycle, pedestrian. Each
router specifies their own profiles.
--------------------------------------------------------------+
The ranges to calculate isochrones for. Either in seconds
or in meters, depending on interval_type.
--------------------------------------------------------------+
The dimension of intervals, which takes router
dependent values, but generally describes time or distance

matrix

locations

-------------------+

profile

-------------------+

sources

-------------------+

destinations

Specify all locations you want to calculate a matrix
for. If sources or destinations is not set, this
will return a symmetrical matrix. Usually this is done
with [Lon, Lat] tuples, but some routers offer
additional options to create a location element.
--------------------------------------------------------------+
The mode of transport, i.e. car, bicycle, pedestrian. Each
router specifies their own profiles.
--------------------------------------------------------------+
The indices of the locations parameter iterable to
take as sources for the matrix calculation. If not
specified all locations are considered to be sources.
--------------------------------------------------------------+
The indices of the locations parameter iterable to
take as destinations for the matrix calculation. If not
specified all locations are considered to be
destinations.

Contributing

We ❤️ contributions and realistically think that's the only way to support and maintain most routing engines in the long run. To get you started, we created a Contribution guideline.

Examples

Follow our examples to understand how simple routingpy is to use.

On top of the examples listed below, find interactive notebook(s) on mybinder.org.

Basic Usage

Get all attributes

routingpy is designed to take the burden off your shoulder to parse the JSON response of each provider, exposing the most important information of the response as attributes of the response object. The actual JSON is always accessible via the raw attribute:

Multi Provider

Easily calculate routes, isochrones and matrices for multiple providers:

Dry run - Debug

Often it is crucial to examine the request before it is sent. Mostly useful for debugging:

Advanced Usage

Local instance of FOSS router

All FOSS routing engines can be run locally, such as openrouteservice, Valhalla, OSRM and GraphHopper. To be able to use routingpy with a local installation, just change the base_url of the client. This assumes that you did not change the URL(s) of the exposed endpoint(s):

Proxies, Rate limiters and API errors

Proxies are easily set up using following requests scheme for proxying. Also, when batch requesting, routingpy can be set up to resume its requests when the remote API rate limits (i.e. responds with HTTP 429). Also, it can be set up to ignore API errors and instead print them as warnings to stdout. Be careful, when ignoring RouterApiErrors, those often count towards your rate limit.

All these parameters, and more, can optionally be globally set for all router modules or individually per instance:

routingpy's People

Contributors

1maxnet1 avatar alichass avatar ananya2001-an avatar chrstnbwnkl avatar dependabot[bot] avatar jan-bausch avatar khamaileon avatar mthh avatar nilsnolde avatar nmalasevic avatar nurikk avatar remanitinpo avatar sadikkuzu avatar serphentas avatar timmccauley avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

routingpy's Issues

activate coveralls again

when we did the repo name change, it messed up coveralls. had to throw it out for the time being in 26354b3. look into how to support test coverage again for the badge (and only the badge really..)

3.11 is out

Another year passed, python 3.11 is out, so we should build for that as well.

MapboxOSRM: CloudFront error when 2 requests follow each other

Here's what I did

from routingpy.routers import MapboxOSRM
from pprint import pprint

# Some locations in Berlin
coords = [[13.413706, 52.490202], [13.421838, 52.514105],
          [13.453649, 52.507987], [13.401947, 52.543373]]

client = MapboxOSRM(api_key='token')

route = client.directions(locations=coords, profile='walking')
isochrones = client.isochrones(locations=coords[0], profile='walking', intervals=[600, 1200])

pprint((route.geometry, route.duration, route.distance, route.raw))
pprint((isochrones.raw, isochrones[0].geometry, isochrones[0].center, isochrones[0].interval))

Here's what I got

---------------------------------------------------------------------------
JSONDecodeError                           Traceback (most recent call last)
File ~/.virtualenvs/middler-api/lib/python3.8/site-packages/requests/models.py:971, in Response.json(self, **kwargs)
    970 try:
--> 971     return complexjson.loads(self.text, **kwargs)
    972 except JSONDecodeError as e:
    973     # Catch JSON-related errors and raise as requests.JSONDecodeError
    974     # This aliases json.JSONDecodeError and simplejson.JSONDecodeError

File /usr/lib/python3.8/json/__init__.py:357, in loads(s, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)
    354 if (cls is None and object_hook is None and
    355         parse_int is None and parse_float is None and
    356         parse_constant is None and object_pairs_hook is None and not kw):
--> 357     return _default_decoder.decode(s)
    358 if cls is None:

File /usr/lib/python3.8/json/decoder.py:337, in JSONDecoder.decode(self, s, _w)
    333 """Return the Python representation of ``s`` (a ``str`` instance
    334 containing a JSON document).
    335 
    336 """
--> 337 obj, end = self.raw_decode(s, idx=_w(s, 0).end())
    338 end = _w(s, end).end()

File /usr/lib/python3.8/json/decoder.py:355, in JSONDecoder.raw_decode(self, s, idx)
    354 except StopIteration as err:
--> 355     raise JSONDecodeError("Expecting value", s, err.value) from None
    356 return obj, end

JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

JSONDecodeError                           Traceback (most recent call last)
File ~/.virtualenvs/middler-api/src/routingpy/routingpy/client_default.py:235, in Client._get_body(response)
    234 try:
--> 235     body = response.json()
    236 except json.decoder.JSONDecodeError:

File ~/.virtualenvs/middler-api/lib/python3.8/site-packages/requests/models.py:975, in Response.json(self, **kwargs)
    972 except JSONDecodeError as e:
    973     # Catch JSON-related errors and raise as requests.JSONDecodeError
    974     # This aliases json.JSONDecodeError and simplejson.JSONDecodeError
--> 975     raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)

JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

JSONParseError                            Traceback (most recent call last)
Cell In[47], line 2
      1 route = client.directions(locations=coords, profile='walking')
----> 2 isochrones = client.isochrones(locations=coords[0], profile='walking', intervals=[600, 1200])
      3 #matrix = client.matrix(locations=coords, profile='walking')

File ~/.virtualenvs/middler-api/src/routingpy/routingpy/routers/mapbox_osrm.py:413, in MapboxOSRM.isochrones(self, locations, profile, intervals, contours_colors, polygons, denoise, generalize, dry_run)
    408     params["generalize"] = generalize
    410 profile = profile.replace("mapbox/", "")
    412 return self.parse_isochrone_json(
--> 413     self.client._request(
    414         "/isochrone/v1/mapbox/" + profile + "/" + locations_string,
    415         get_params=params,
    416         dry_run=dry_run,
    417     ),
    418     intervals,
    419     locations,
    420 )

File ~/.virtualenvs/middler-api/src/routingpy/routingpy/client_default.py:200, in Client._request(self, url, get_params, post_params, first_request_time, retry_counter, dry_run)
    197     return self._request(url, get_params, post_params, first_request_time, retry_counter + 1)
    199 try:
--> 200     result = self._get_body(response)
    202     return result
    204 except exceptions.RouterApiError:

File ~/.virtualenvs/middler-api/src/routingpy/routingpy/client_default.py:237, in Client._get_body(response)
    235     body = response.json()
    236 except json.decoder.JSONDecodeError:
--> 237     raise exceptions.JSONParseError("Can't decode JSON response:{}".format(response.text))
    239 if status_code == 429:
    240     raise exceptions.OverQueryLimit(status_code, body)

JSONParseError: Can't decode JSON response:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERROR: The request could not be satisfied</TITLE>
</HEAD><BODY>
<H1>403 ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px">
Bad request.
We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
<BR clear="all">
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.
<BR clear="all">
<HR noshade size="1px">
<PRE>
Generated by cloudfront (CloudFront)
Request ID: iEXFhiP_CsxoQhlfeCQf6c12ZikAJBNqsftyZtYi_7fbDnoYBr9u0Q==
</PRE>
<ADDRESS>
</ADDRESS>
</BODY></HTML>

Here's what I was expecting

Result of the 2 requests


Here's what I think could be improved

At first I thought the calls must be too close together. So I added a time.sleep between them, but without success.

client class should be replaceable

The main advantage of this package IMO is the parsing of the response. We could re-use this in our valhalla QGIS plugin, but for that to work we need to be able to replace the client with a custom one (not using the requests package, but QgsNetworkAccessManager). That's a little bit of a bigger job of refactoring to make it possible:

  • change the pattern to not have a base Router class but rather a client class which can get passed to the individual router classes
  • the new (default) client class should be an abstract base class (similar to Router right now) which one can inherit from to build a new client class

should be doable in a backwards-compatible way.

Rename `isochrones` to `reachability`

The isochrones method seems to be a bit of a misnomer, because in most cases, the isochrone endpoints can be used for isochrones and isodistances. Something like reachability could be a better suited name, what do you think? We just released 1.0.0 a couple months ago, so maybe something for down the road.

Local OSRM distances Matrix not working

Here's what I did

from routingpy.routers import OSRM

router = OSRM(requests_kwargs={'proxies': {'https': '129.125.12.0'}})
client = OSRM(base_url='http://localhost:5000')
Matrix=OSRM.matrix(client, locations=addresses, profile='car', dry_run=True)

dry_run results:
url:
http://localhost:5000/table/v1/car/-75.567589,6.191159;-75.558888,6.2834;-75.554428,6.303507;-75.508671,6.342607;-75.571788,6.174933;-75.566615,6.184022?
Parameters:
{
"headers": {
"User-Agent": "routingpy/v0.2.7",
"Content-Type": "application/json"
},
"timeout": 60
}

Here's what I got

Matrix.durations worked correctly, but Matrix.distances is completely empty.


Here's what I was expecting

I was expecting Matrix.durations and Matrix.distances to be acquired, but only received Matrix.durations.

Here's what I think could be improved

If annotations='distance,duration' could be used as default, instead of only 'duration', I think we should be able to get both the durations and distances matrices.

Faulty geometries returned by HereMaps.isochrones()

Here's what I did

Wanted to calculate isochrones with HereMaps:

api = get_router_by_name("heremaps")(api_key="tm04dMxnZ5rRKQVxfvGTtgkpV3FEerIDoExbDG0kEPs")

location = [13.410701945045075, 52.56057471477219]

isochrones = api.isochrones(locations=location, profile="car", intervals=[300,600])

Here's what I got

  • An Isochrones object with geometries consisting of list of list_reverseiterators

Here's what I was expecting

  • An Isochrones object with geometries consisting of lists of coordinates

Here's what I think could be improved

  • when parsing the result returned by the API, make sure to convert the reversed coordinates to a list on line 1094

Support Graphhopper's POST Route Endpoint

Graphhopper supports both a GET and a POST directions endpoint. However, the GET endpoint has some limitations:

For the GET request you specify the parameters in the URL and can try it directly in every browser. However, it has some disadvantages when using many points (URL length limit) and the custom_model Feature cannot be used. Therefore, our recommended endpoint is the POST route endpoint.

(Quote from the Graphhopper docs)

Currently, routingpy only supports the GET endpoint. It would be cool to use POST, to be able to set custom models!

Issue google search

Hey, may you help me with my own issue?
I'm trying to scrape large amount of results in Google, but I reach a limit of XXX with the message :

"In order to show you the most relevant results, we have omitted some entries very similar to the XXX already displayed.
If you like, you can repeat the search with the omitted results included."

I'm trying to get through 1000 results.
Any advises? clues?
Thanks ahead.

OSRM

Hello I just started to use routingpy. I see that there is many providers. I would like to use OSRM. However, the examples that I have seen are using mapbox_osrm which use a mapbox token and the free version has a very limited numbers of requests.

How can I use directly OSRM? In the webpage of OSRM I dont find the steps to create a token.

Best regards,
Orlando

Add support for map-matching

OSRM, Valhalla and Mapbox support map-matching. The feature consists of snapping input points, such as GPS points, to the OSM network.

GraphHopper parsing fails with not encoded points

Here's what I did

I set points_encoded=False to verify that during parsing of points in GraphHopper response are always decoded as polyline even if points_encoded=False

url:
http://localhost:8989/route?vehicle=car&point=50.046531%2C14.514527&point=50.068452%2C14.508087&points_encoded=false&debug=true
Parameters:
{
  "headers": {
    "User-Agent": "routingpy/v0.3.3",
    "Content-Type": "application/json"
  },
  "timeout": 60
}

Here's what I got

Key error from _trans / _decode


Here's what I was expecting

Geometry should be parsed from the JSON LineString


Here's what I think could be improved

Decoding from polyline should not happen if the response contains points_encoded=False

Deprecate HERE provider

I have no intention of ever working on the HERE provider and it's lacking behind since a while. I'd actually like to slash all commercial providers, but Google is too prevalent (and has fairly sane parameterization).

If anyone would like to keep it, speak up. Then it'll be your turn to maintain it properly:)

release v1.0

It's about time anyways to publish 1.0.. Now we have a (somewhat) major change, so let's do this.

  • fix #15
  • merge #23
  • fix #32
  • test example jupyter notebooks with api keys
  • check documentation one last time
  • update the version in code
  • release PyPI
  • update examples is README

Upper limits in input destination in Computing the Distance Matrix

Does any one know how many destinations at most should be set in Computing the Distance Matrix? I set 300 candidate destinations and 33 origins. Then the error shows like this:

JSONDecodeError: Expecting value: line 1 column 1 (char 0)

My code:
all_locations = demand + cand
source_indices = [i for i in range(n_demand)]
target_indices = [i for i in range(n_demand, len(all_locations))]

client = OSRM(base_url="https://router.project-osrm.org")
osrm_routing_matrix = client.matrix(
dry_run=False,
locations=all_locations,
sources=source_indices,
destinations=target_indices,
profile="car",
)
cost_matrix = np.array(osrm_routing_matrix.durations)

If I set at about 200, everything goes fine. So I guess this has reached the maximum of API port. Does anyone know how to change the upper limits? Looking forward to the reply! Thx!

Google Router distance and duration wrong for single route response

Here's what I did

Google Directions API with single route and multiple legs.


Here's what I got

I got values for distance and duration only from last leg instead of sum of all legs.


Here's what I was expecting

I was expecting the distance and duration values to be the sum of all legs.


Here is the fix:

#108

pypy3 is broken in ci

I fiddled a bit yesterday:

  • changed the build system to setuptools_scm for automatic versioning based on git tags
  • added a workflow for automatic publishing on pypi

somehow that broke all kinds of tests in CI, none of the failures I could reproduce locally despite the same python version and workflow. the tests looked broken though, so I fixed them up.

now pypy3 is broken: https://github.com/gis-ops/routing-py/runs/5544884127?check_suite_focus=true

it seems to me that it tried to install a py27 version of typed-ast for pypy3.6:

ast27/Parser/tokenizer.c:17:10: fatal error: codecs.h: No such file or directory
       17 | #include "codecs.h"
          |          ^~~~~~~~~~
    compilation terminated.
    error: command 'gcc' failed with exit status 1

`preference` parameter isn't read when asking for isochrones with Valhalla engine

Here's what I did and what I got

Asking for isochrones with default values

isochrones = api.isochrones(
    locations=(5.86659,45.26936),
    profile='bicycle',
    interval_type='time',
    intervals=[i * 60 for i in (20,50,80,110)],
)

and asking for isochrones using the preference attribute (but no options attribute)

isochrones_shortest = api.isochrones(
    locations=(5.86659,45.26936),
    profile='bicycle',
    interval_type='time',
    intervals=[i * 60 for i in (20,50,80,110)],
    preference="shortest",
)

both return the same result.
By adding dry_run=True we can see that the preference is not used :

url:
http://localhost:8002/isochrone
Parameters:
{
  "headers": {
    "User-Agent": "routingpy/v1.3.0",
    "Content-Type": "application/json"
  },
  "timeout": 60,
  "json": {
    "locations": [
      {
        "lon": 5.86659,
        "lat": 45.26936
      }
    ],
    "costing": "bicycle",
    "contours": [
      {
        "time": 20.0
      },
      {
        "time": 50.0
      },
      {
        "time": 80.0
      },
      {
        "time": 110.0
      }
    ]
  }
}

However, if you add any values in options, the preference is taken into account :

isochrones_shortest = api.isochrones(
    locations=(5.86659,45.26936),
    profile='bicycle',
    interval_type='time',
    intervals=[i * 60 for i in (20,50,80,110)],
    preference="shortest",
    options={"foo": 12},
    dry_run=True,
)

Output :

url:
http://localhost:8002/isochrone
Parameters:
{
  "headers": {
    "User-Agent": "routingpy/v1.3.0",
    "Content-Type": "application/json"
  },
  "timeout": 60,
  "json": {
    "locations": [
      {
        "lon": 5.86659,
        "lat": 45.26936
      }
    ],
    "costing": "bicycle",
    "contours": [
      {
        "time": 20.0
      },
      {
        "time": 50.0
      },
      {
        "time": 80.0
      },
      {
        "time": 110.0
      }
    ],
    "costing_options": {
      "bicycle": {
        "foo": 12,
        "shortest": true
      }
    }
  }
}

Here's what I was expecting

I was expecting the preference parameter to be taken into account, as per the documentation, even if options is None.


Here's what I think could be improved

After looking at the code and according to my understanding, in isochrones with Valhalla engine, the preference parameter is only read if the options parameter is not None. See

A possible fix could be to do as with directions, and replace if options by if options or preference on line 441 ; cf.

if options or preference:

HereMaps Isochrones returning faulty geometry

Here's what I did

from shapely.geometry import Polygon
from routingpy import get_router_by_name

api = get_router_by_name("heremaps")(api_key)

location = [13.479801753996686, 52.55725875370285]

isochrones = api.isochrones(location, profile="car", intervals=[300,600])

geometries = []
for isochrone in isochrones:
    geometries.append(Polygon(isochrone.geometry))

Here's what I got

  • Shapely's Polygon instantiation causes an `AttributeError´: 'list' object has no attribute 'array_interface'

Here's what I was expecting

A list of Polygons


Here's what I think could be improved

Since HereMaps is the only router having that problem, the bug is likely to be caused by the response parsing. It seems like the geometry is wrapped one too many times into a list, because

geometries.append(Polygon(isochrone.geometry[0])) 

produces the desired result.

Rename `test_helper` file

We can rename the test_helper.py file in tests dir to something like test_mock.py since it's basically a mock and the helper name is kind of misleading...we already have a test_utils.py file as well. We can also maybe move it to a data folder inside tests like: tests/data/mock.py wdyt?

Use type hinting in router methods

We're still not using Python's type annotations in most router methods (except e.g. Valhalla's expansion). Maybe we could start by annotating Valhalla's methods and start removing type hints from the doc strings there?

Calculate walking distance between two points

Hi I would like to calculate walking distance between two points.

I copied and pasted the following code:

Here's what I did

`from routingpy import Graphhopper
from shapely.geometry import Polygon

//Define the clients and their profile parameter
apis = (
(Graphhopper(api_key='81d8fd41-33fb-4c98-b3a7-83b2e498cd14 '), 'bike'),
)
//Define me locations in Berlin
coords = [[13.413706, 52.490202], [13.421838, 52.514105],
[13.453649, 52.507987], [13.401947, 52.543373]]

for api in apis:
client, profile = api
route = client.directions(locations=coords, profile=profile)
print("Direction - {}:\n\tDuration: {}\n\tDistance: {}".format(client.class.name,
route.duration,
route.distance))
isochrones = client.isochrones(locations=coords[0], profile=profile, intervals=[600, 1200])
for iso in isochrones:
print("Isochrone {} secs - {}:\n\tArea: {} sqm".format(client.class.name,
iso.interval,
Polygon(iso.geometry).area))
matrix = client.matrix(locations=coords, profile=profile)
print("Matrix - {}:\n\tDurations: {}\n\tDistances: {}".format(client.class.name,
matrix.durations,
matrix.distances))`


Here's what I got

from routingpy import Graphhopper ImportError: cannot import name 'Graphhopper' from 'routingpy' (C:\Users\a463154\Desktop\Programmi Python\routing py\routingpy.py)

What is the problem in your opinion?

supply **kwargs to all methods of all routers

in #41 (comment) we realized that the **kwargs are not even used when they're passed to a method. instead of removing that parameter, we should make use of it and simply append the whole thing to the request parameters. reason is that we likely won't keep up here with all the changes of the individual router arguments to APIs which will be added in the future and this provides a means of passing those anyways, sort of a safety net for our (and the community's!!!) laziness;)

OSRM profiles removed

Hi guys!

Thanks for the amazing library. I was wondering for the reasons of OSRM profiles being removed from the library by #64.
According to OSRM api docs there is a concept of "profile" and in fact our team was using routing-py with multi profile OSRM. This is usually achieved by using a proxy, which maps different OSRM instances by url. Using profiles in routing-py router was extremely convenient for us.

Is it possible to revert #64 and restore previous API, while setting default version of profile to driving?

MapboxOSRM isochrone costing parameters

Hi and thanks for you nice package,

Here's what I did

Query for an isochrone polygon using the class MapboxOSRM as client.

image


Here's what I got

RouterApiError: 422 ({'message': 'Invalid query param', 'code': 'InvalidInput'})

Here's what I was expecting

An object of type routingpy.isochrone.Isochrones


Here's what I think could be improved

  1. I think the issue came from the 'costing' parameters. https://github.com/gis-ops/routing-py/blob/801bb5b3f80bc4852d7a30e0741d5ff5970a52bd/routingpy/routers/mapbox_osrm.py#L401
    When I dry run, then I copy and paste the url, remove the costing parameters and curl the url it works well.

  2. I think there is a typo in the readme, on the multiprovider example. The profile is 'cycling' and it supposes to be mapbox/cycling for the isochrone query.
    https://github.com/gis-ops/routing-py/blob/801bb5b3f80bc4852d7a30e0741d5ff5970a52bd/routingpy/routers/mapbox_osrm.py#L369

OSRM client.direction return lat, lon list instead of lon lat like ORS service

Hi Chris,
Thanks for this nice library. I can use it on a number of offline routing engines.
I think there is a discrepancy in the returning geometry.

The OSRM return lat, lon pair inside the route.geometry instead of lon, lat. Not the same to OSR...

route = client.directions(
locations = lnglats,
profile='car'
)

By the way, is it possible to get the speed and altitude at each coordinate in the geometry?

Best regards

Add convenience method for converting between intervals and buckets

Since graphhopper's isochrone endpoint expects a limit and a number of buckets instead of intervals, what if we provide a convenience method that takes a time limit and a number of buckets and converts it to intervals like this:

time_limit = 850
buckets = 5
intervals = [int(time_limit-n*time_limit/buckets) for n in range(buckets)]

Pretty high level, but possibly a nice gem and a contribution to consistent access across routers ;)

pypi release

Hello, would it be possible to release recent changes to pypi? Especially this one since it changed url (removed profile and added driving) it fails tests

List index out of range error for google directions

Here's what I did (dry run output):

url:
https://maps.googleapis.com/maps/api/directions/json?departure_time=1602059400&destination=37.42306%2C-122.08413&key=####################&mode=transit&origin=37.26044%2C-122.11921&units=metric
Parameters:
{
"headers": {
"User-Agent": "routingpy/v0.3.2",
"Content-Type": "application/json"
},
"timeout": 60
}


Here's what I got

image

Seems to be cause by this repsonse:
{'available_travel_modes': ['DRIVING', 'WALKING', 'BICYCLING'], 'geocoded_waypoints': [{}, {}], 'routes': [], 'status': 'ZERO_RESULTS'}


Here's what I was expecting

Empty direction object if response is:
{'available_travel_modes': ['DRIVING', 'WALKING', 'BICYCLING'], 'geocoded_waypoints': [{}, {}], 'routes': [], 'status': 'ZERO_RESULTS'}

routingpy ipykernel update

Is it possible to update routingpy per this documentation? opengeos/geospatial#16

@ArterialMapping It appears that routingpy requires ipykernel >=5.3.4,<6, which was released over a year ago. Many packages in the geospatial stack require a much newer version of ipykernel. routingpy needs to bring ipykernel up to date before it can be added to geospatial.

https://github.com/conda-forge/routingpy-feedstock/blob/c32ee1d1500c3f6bbda723b342886b9b45488513/recipe/meta.yaml#L30 image

[image

GraphHopper "profile" is set under "vehicle"

Here's what I did

A simple query, such as:

client.directions(locations=[...],[...]],instructions=False,elevation=True,profile="car",**{"avoid":"motorway;ferry"})

Here's what I got

No "profile" set, but a "vehicle" that GraphHopper doesn't accept:

    raise exceptions.RouterApiError(status_code, body)
routingpy.exceptions.RouterApiError: 400 ({'message': 'profile parameter required', 'hints': [{'message': 'profile parameter required', 'details': 'java.lang.IllegalArgumentException'}]})

Here's what I was expecting

The "profile" key to be set accordingly


Here's what I think could be improved

This line should be changed from

params = {"vehicle": profile}

to

params = {"profile": profile}

since no "vehicle" key exists in the GraphHopper API documentation.

Here isochrone router returns coords in lat,lon rather than lon,lat

Here's what I did

Used HEREclient.isochrones


Here's what I got

Isochrone([[[37.5624275, -122.3239231], [37.5629425, -122.3238373], [37.5650024, -122.3238373], ...


Here's what I was expecting (based on docs)

Isochrone([[[-122.3239231, 37.5624275, ], [-122.3238373, 37.5629425 ], ...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.