Project-OSRM / osrm-backend

Open Source Routing Machine - C++ backend
http://map.project-osrm.org
BSD 2-Clause "Simplified" License
6.3k stars 3.33k forks source link

Determine speed limit for route #5286

Closed parsispresswala closed 1 month ago

parsispresswala commented 5 years ago

Hello guys,

I'm trying to find a way to obtain all the speed limits in km/h unit for a specific route using openstreetmap. Right now I am using annotation=speed but I don't understand the result. My API of routing is something like this: http://127.0.0.1:5000/route/v1/driving/72.860856,19.198877;72.860084,19.195128?steps=true&alternatives=false&geometries=geojson&annotations=speed

weight: 102, distance: 1278.3, annotation: { speed: [ 14.3, 14.4, 14.4, 14.3, 14.4, 14.1, 14.6, 14.5, 11.2, 11.1, 11, 11.2, 15.6, 11, 11.1, 11.1, 10.8, 11.3, 14.8, 15.6, 14.9, 14.1, 14.5, 14.4 ] }, summary: "Western Express Highway, Datta Mandir Road", duration: 102 }

Anyone develop something similar, or does anything like this already exist?

Thanks!

parsispresswala commented 5 years ago

I got the answer. The given speed is of m/s unit and we need to convert it in km/h. 1 m/s = 3.4 km/h.

danpat commented 5 years ago

@parsispresswala Note that the speed value returned by OSRM is the speed we decide for routing, not exactly the maxspeed= tag from OSM. The speed values are decided by the car.lua script when parsing the OSM tags - maxspeed= is considered, but we rarely use its value exactly.

In order to fetch the actual maxspeed= data, you would need to use something like annotations=nodes in combination with https://github.com/mapbox/route-annotator to fetch the OSM tag information for the route after the route is found.

parsispresswala commented 5 years ago

@danpat Thanks for tip.

parsispresswala commented 5 years ago

Hello, I find this link for speed limit. https://help.openstreetmap.org/questions/32644/determining-speed-limits-for-given-route

Can I get speed limit of route by changing some code in car.lua profile? If yes, what changes do I have to made?

datwelk commented 5 years ago

@danpat is https://github.com/mapbox/route-annotator also how Mapbox Directions annotates the response with a maxspeed array (https://github.com/mapbox/MapboxDirections.swift/pull/367)?

pavlo-tk commented 5 years ago

Hey guys,

Allow me to squeeze in here with a related question.

I'm trying to get speed limits (used by OSRM, don't need exact maxspeed) for each of the steps along the route.

Here is a very short route I'm using: http://router.project-osrm.org/route/v1/driving/-88.900584,42.225831;-88.881613,42.233121?steps=true&annotations=speed

There are 4 steps and 9 locations if you decode the geometry value (I use https://google-developers.appspot.com/maps/documentation/utilities/polyline-utility/polylineutility).

The annotation -> speed returns 43 entries with speed values, similar to the one parsispresswala showed. So, I'm struggling to correlate those 43 speed values with 4 steps along the route. Can't understand which values are related to which steps.

What I want to achieve is to relate speed values to each of the steps. Like:

Any advice on how to read and interpret that annotation -> speed array? Thank you in advance!

mohd-akram commented 4 years ago

@parsispresswala 1 m/s = 3.6 km/h

@pavlo-tk Use the geometry in the step and ignore repeated coordinates. You can get decoded values by passing geometries=geojson. There will be one less element in the annotation array, I believe this is because the first coordinate will have a speed of 0.

danpat commented 4 years ago

If you just need it for each step, note that the RouteStep object has a distance and duration property - you can just do speed = step[n].distance/step[n].duration.

amlan007 commented 3 years ago

I am using OSMBonusPack for OSM based map on Android

i am querying https://router.project-osrm.org/route/v1/driving/105.8680712896,20.9947322000;105.8922453000,21.0393411000?alternatives=true&overview=full&steps=true to get the data.

Now i want the speed limit between each node.

Can anybody guide me how to do that ?

lukasa1993 commented 3 years ago

is there any working example how to get actual route speed limit ?

boooch commented 2 years ago

is there any working example how to get actual route speed limit ?

Do you finally found the solution of this ?

lukasa1993 commented 2 years ago

is there any working example how to get actual route speed limit ?

Do you finally found the solution of this ?

no sorry

jasonwiener commented 2 years ago

I ended up building a bespoke solution using OSM data. But haven't found a way to query it in OSRM.

SamuelBrucksch commented 1 year ago

I was wondering, if there is an easy way to extend the annotations with max speed. Some of the annotations, like weight, should have the same value as calculated in lua, right? So it should also be possible to include the max speed somehow.

In assemble_geometry this is done, any hints, how we could get the max speed from any of the available facades or any other property? Storing it into the annotations list would be easy then.

Guess we have to add it in lua first, then store it somewhere in extractor_callbacks and then access it from where the annotations are built. Would that be a valid approach?

danpat commented 1 year ago

OSRM isn't a general purpose OSM query tool, so trying to get some of this data is never as easy as it feels like it should be.

A quick-n-dirty way to get speed limit information is to encode it in the .name property on edges. To do this, you need to make two changes:

  1. Find where the .name property is set in car.lua and embed the maxspeed= tag value in it, so say "Main St, 35km/h"
  2. In MakeLegs() here dig through and see if you need to disable any of the step collapsing logic. In some cases, OSRM will join two edges together in the result, even if the name changes - you'd need to disable that behaviour in order to be sure you get all the name properties along your route.
SamuelBrucksch commented 1 year ago

Thanks @danpat, this is actually something i tried already, but then i saw that there are various checks, that use the roadname for some additional logic. One case for example is this: https://github.com/Project-OSRM/osrm-backend/blob/95c45239873818ec5d982dd5f7bfb4f66930fec4/src/engine/guidance/collapse_scenario_detection.cpp#L32

In this case the check will always be false, as we attach the speed limit after the name.

Another one here which is used in various places: https://github.com/Project-OSRM/osrm-backend/blob/95c45239873818ec5d982dd5f7bfb4f66930fec4/include/engine/guidance/collapsing_utility.hpp#L123-L149

And here: https://github.com/Project-OSRM/osrm-backend/blob/95c45239873818ec5d982dd5f7bfb4f66930fec4/src/engine/guidance/post_processing.cpp#L549

So from my understanding this could cause issues in recognizing some szenarios.

Or are my concerns not justifioed in these cases?

danpat commented 1 year ago

@SamuelBrucksch Depends what you're looking to get out of the result. None of the code you linked will impact the route that is found. What will change is the detail in the steps in the response - there will be more of them. If you're just looking to use OSRM to find a path and extract metadata about that path, then this quick hack is workable.

If you need the route steps to be sensible(ish) and fit for human consumption, then this isn't the way to go.

SamuelBrucksch commented 1 year ago

Thanks for more detailed explanation. That this does not affect the route is what I expected, as this affects guidance only. However new name is converted into other instructions sometimes, so this is where i have some doubts. More new name instructions are fine, as we can filter them anyways, but if due to that instructions are not converted anymore in certain situations that would not be so nice.

SamuelBrucksch commented 1 year ago

Ok so i did some further investigation on this and it really breaks a few instructions, so this is not really the way to go.

@danpat what would be the easiest way, to get maxspeed (or other metadata) into the route similiar to the annotations for example? I saw a PR here, that adds the way_ids to the annotations: https://github.com/Project-OSRM/osrm-backend/pull/5968

My assumption would be, that if we can add the way_ids to the annotations, it should also be possible to add the speed limits instead for that way. However that PR is not merged for 2 years and the memory consumption increased, so not sure if that is a solution we should follow.

My other idea was to add metadata from lua in a certain way, then grab it in OSRM and add a new MetaData instruction, which is hidden and not touched anywhere, except in the route to json before sending it back. Is that something which could work? And if so do you have some hints for me how to start on this?

Or is there any other approach, that would work better than reusing the name? There actually are other routing APIs, for example HERE, that allow adding metadata like speed limits, elevation and so on to be returned as part of the route, so i think this is a valid usecase, especially for navigation solutions that don't have internet on the way.

Found another related issue: https://github.com/Project-OSRM/osrm-backend/issues/6281

danpat commented 1 year ago

There actually are other routing APIs, for example HERE, that allow adding metadata like speed limits

Yep, for sure - but they also don't give you the routing engine itself, so it's not clear what their runtime requirements are on the backend - probably quite big if they're returning all that extra metadata :-)

Ultimately, the conflict here is that OSRM isn't really a general-purpose road network database - its focus is on pathfinding.

Years ago, I wrote https://github.com/mapbox/route-annotator which allows you to take a sequence of OSM node IDs and retrieve all the tags between all the pairs of nodes in the route - but you'd need to run that service separately, and it is also quite memory hungry.

Other open source routing engines like Valhalla and pgRouting store some extra fields, as they allow them to be used for route selection. But there's no free lunch - if you want that extra data, you have to store it somewhere, so your memory/disk needs get bigger.

SamuelBrucksch commented 1 year ago

But max_speed is already used while finding the route, so can't we just somehow add the meta data on the fly while putting together the route? If route-annotator also is memory hungry and needs to run in parallel, it should be fine if OSRM consumes a bit more and runs as standalone application.

I don't mind if this would b a custom solution like adding it to the names, so we can also do this on our own instance and not push it to the main version.

I just would need a starting point / some help on where to inject the data or where to best grab it, so it can be added to the route in the end.

danpat commented 1 year ago

The OSM maxspeed tag is only used during preprocessing, to come up with an estimated travel time for each section of road. When maxspeed is present, it's used as a hint as to how fast you can travel on that road. If it's missing, we guess based on other tags. But ultimately, all the OSM tags are discarded and we derive a single duration for every road - that is the thing stored in the routing graph.

If it were me, the quickest hack I can think of would be to:

  1. Keep appending the metadata you want to the .name property, after some special separator, like | or something.
  2. Once the route is found, iterate over the edge sequence and extract the appended data from the .name values.
  3. Customize the post-processing logic to ignore the appended metadata (e.g. things like haveSameName)
  4. Add an annotation to the route based on what you extracted in (2)

Not very clean, but I think would be the fewest code changes. You could alternatively add a completely new edge property similar to .name and replicate all the places where we store/add that - but that would be dozens of code changes all over the place most likely.

SamuelBrucksch commented 1 year ago

Thanks for explaining. I'll check if that works for us.

SamuelBrucksch commented 1 year ago

Did anyone actually try to use overpass api to get the speed limits for a route based on node IDs that are returned with annotations=nodes? I managed to get ways for node IDs, but they were not in the order of the node IDs I passed in. But i have the feeling, that it should be possible to do somehow. Maybe we can help out each other and build a nice overpass filter, to return the max speed (or any other requested tag) in a similiar format as we have for the node ID array.

github-actions[bot] commented 2 months ago

This issue seems to be stale. It will be closed in 30 days if no further activity occurs.