psycopgr is a Python wrapper of pgRouting written by me.
As said in pgRouting docs:
Just considering the different ways that the cost can be calculated, makes it almost impossible to create a general wrapper, that can work on all applications.
Indeed, in many applicatons you may need to modify the database tables and fill some computed values to fit your specific purpose, which is often done in a preprocessing stage by SQL, before real routing starts working. It is not appropriate to be wrapped.
However, after preprocessing things such as database creation, map data import, tables re-calculation and update, you are ready to use psycopgr
to do another simple thing: computing optimal routes from nodes to nodes on real map, in Python.
Note that psycopgr
is never a general purpose wrapper of pgRouting. I am a novice in GIS and what I want from this tool is just routes (with lowest costs) from places to places without writing a single line of SQL.
For preprocessing stage, I have a post “pgRouting notes” for my own reference. Before enjoyable Python coding, you have to prepare a few stuffs.
Prepare a PostgreSQL database, install PostGIS and pgRouting extensions, and import map data to database. “pgRouting notes” is a practical guide.
Update database tables according to your specific requirement.
pip install psycopgr
(Yes, it is on PyPI now.)
Or,
pipenv install psycopgr
As you may guessed from the name, psycopgr
uses psycopg2
as PostgreSQL driver. The above command will install it automatically.
First,
from psycopgr import PgrNode, PGRouting
Create an PGRouting instance with database connection:
pgr = PGRouting(database='mydb', user='user')
Adjust meta datas of tables including the edge table properies if they are different from the default (only the different properties needs to be set), e.g.:
pgr.set_meta_data(cost='cost_s', reverse_cost='reverse_cost_s', directed=true)
This is the default meta datas:
{
'table': 'ways',
'id': 'gid',
'source': 'source',
'target': 'target',
'cost': 'cost_s', # driving time in second
'reverse_cost': 'reverse_cost_s', # reverse driving time in second
'x1': 'x1',
'y1': 'y1',
'x2': 'x2',
'y2': 'y2',
'geometry': 'the_geom',
'has_reverse_cost': True,
'directed': True,
'srid': 4326
}
Prepare nodes. nodes are represented by PgrNode
namedtuple with geographic coordinates rather than vertex id (vid) in the tables. PgrNodes
is defined as:
PgrNode = namedtuple('PgrNode', ['id', 'lon', 'lat'])
in which id
could be None
or self-defined value, and lon
and lat
are double precision values. Of course nodes could be input from various interfaces such as database or another program.
For example:
nodes = [PgrNode(None, 116.30150, 40.05500),
PgrNode(None, 116.36577, 40.00253),
PgrNode(None, 116.30560, 39.95458),
PgrNode(None, 116.46806, 39.99857)]
Now we can do routings:
# many-to-many
routings = pgr.get_routes(nodes, nodes, end_speed=5.0, pgx_file='r.pgx')
# one-to-one
routings = pgr.get_routes(nodes[0], nodes[1])
# one-to-many
routings = pgr.get_routes(nodes[0], nodes)
# many-to-one
routings = pgr.get_routes(nodes, node[2])
end_speed
: speed from node to nearest vertices on ways in unit km/h.gpx_file
: set it to output paths to a gpx file.The returned is a dict of dict: {(start_node, end_node): {'path': [PgrNode], 'cost': cost}
By default, cost
is traveling time along the path in unit second. It depends on the means of columns of the edge table that you set as cost
and reverse_cost
. You can assign the relations by set_meta_data
function.
We can also get only costs without detailed paths returned:
costs = pgr.get_costs(nodes, nodes)
The returned is also a dict: {(start_node, end_node): cost}
psycopgr function | pgRouting function |
---|---|
dijkstra | pgr_dijkstra |
dijkstra_cost | pgr_dijkstraCost |
astar | pgr_astar |
These are direct wrappings of pgRouting functions. For example, dijkstra
takes vertex ids as input. This list may be extended in the future.
Last modified: 2019-05-04