I imported data from a map extracted from OpenStreetMap. With osm2pgrouting I imported it into PostgreSQL, to be worked with pgRouting and PostGIS. Command used:

osm2pgrouting -f DIRECTORY/map.osm -d DATABASE -p 5432 -U postgres -W PASSWD-c mapconfig.xml --addnodes --attributes -- clean

He created the following table structure:

enter image description here

I am using the pgr_dijkstra function to calculate a minimum cost route between two locations:

SELECT * FROM pgr_dijkstra('
SELECT gid as id, source, target, ST_Length(the_geom::GEOGRAPHY) AS cost, 
ST_LENGTH(the_geom::GEOGRAPHY) AS reverse_cost
FROM ways',
24212, 5521, directed := true
) as di
  JOIN ways
ON di.edge = ways.gid
order by seq;

It is working perfectly when I use directed: = false. But when I put directed: = true pgRouting is returning the same result. This is wrong because even with directed: = true he is considering my unidirectional streets as bidirectional. The image below represents some return lines from my query:

enter image description here

oneway = YES and one_way = 1 is a one-way street that the function should not be returning. oneway = UNKNOWN and one_way = 0 is my two-way street. The image below shows this one-way street that is being considered as a route path, which is wrong, is in the opposite direction of traffic. In the drawing it can be a bit confusing, but the street "Florestano de Macedo" is unidirectional, as shown by the return in the database. The figure is a bit confused because it is a street that passes next to a highway, and on the other side of the highway there is another street. But this problem occurs for any route with directed: = true.

enter image description here

What am I doing wrong? Do I have to prepare/change my data in any way for these cases? Is my query wrong? PgRouting workshops only say to use directed as true or false, they do not mention data preparation for this.

1 Answer 1


You are passing in the metric length ST_Length(geom::GEOGRAPHY) of each edge E as both cost & reverse_cost - rendering it equal to to the undirected counterpart.

pgRouting realizes ordered graph restrictions via the [reverse_]cost parameters; generally speaking, while an undirected graph considers only a single cost per edge E, a directed graph treats each individual edge E as a pair of directed edges (E'[E_from, E_to] & E''[E_to, E_from]), each having it's own cost (cost -> E' & reverse_cost -> E'').

To implement one_way restrictions, set the equivalent cost parameter to -1 (-> excluded from graph); it is common (but not guaranteed) in OSM data to model one_way roads as restricted in [E_to, E_from] direction, so you'd need to set the reverse_cost accordingly:

FROM   pgr_dijkstra('
         SELECT gid AS id,
                ST_Length(the_geom::GEOGRAPHY) AS cost, 
                  WHEN one_way::BOOL THEN -1
                  ELSE ST_Length(the_geom::GEOGRAPHY)
                END AS reverse_cost
         FROM   ways',
         directed := TRUE
       ) AS di
JOIN   ways
  ON   di.edge = ways.gid
  • Hello @geozelot , you helped me a lot with this, thank you very much for the explanation and example. I just didn't quite understand that part: "one_way :: BOOL". It's a typecast, correct? Boolean is only 1 or 0, but in my tests I noticed that the values of one_way as 1, 2 and 3 he is considering and putting the reverse_cost as -1. Is it okay to change reserve_cost to -1 in these cases too, I just didn't understand why I thought the boolean would be just 1 or 0. In this case of ":: BOOL" everything that is different from zero does it consider TRUE? Apr 21, 2021 at 14:26
  • Just one more question, if my database is correct, I can also use "oneway = '' YES '' THEN -1", instead of "WHEN one_way :: BOOL THEN -1", right? I found in my database about 1,500 lines where "one_way" is equal to 2 and "oneway" is equal to NO, and about 25 lines where "one_way" is equal to 3 and "oneway" is equal to REVERSIBLE. Analyzing these streets, they are really bidirectional. Thank you very much. Apr 21, 2021 at 15:14
  • 1
    @EduardoOliveira yes, it is a CAST, the BOOL type can be cast from 1 or 0. I simply assumed that would be the reason for having the second one_way column, but if there are other numbers then you can use the CASE oneway = 'YES' you described just as well. Note, though, that the numbers in one_way may actually give you hints about the direction of the one way in relation to the topology (i.e. restricted in from->to or to->from direction), or if it allows certain vehicles (e.g. one way for cars, but bikes are allowed two ways) - check the docs here.
    – geozelot
    Apr 21, 2021 at 16:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.