Use graphhoper to indoor navigation

I am working with GraphHopper 10.0 and trying to implement indoor navigation. To represent different floors, I added the level tag in JOSM, but I need to handle route calculations across different floors myself. I came across the GHPoint3D class in the project, which allows navigation at different altitudes by passing an elevation parameter. I believe this can be used to implement navigation between floors.

But I don’t know how to use it, hahah

Thank you for your help and responses!

Yes, there is a GHPoint3D which (besides lat/lon) has an elevation value. However, in GraphHopper this is only used to represent (absolute) altitude, but not for handling indoor routing across different floors. To actually use GraphHopper for this a lot more needs to be done. There is an issue on github that discusses indoor routing that might be useful for you: Indoor Routing · Issue #646 · graphhopper/graphhopper · GitHub

Thanks for your reply

I have an idea to simply implement this function, add level tags in osm, if there is no cross-layer, then use the existing route navigation, if it is cross-layer, it needs to be divided into two parts, the first part is from the starting point to the elevator or stairs closest to the starting point, the second part is from the elevator of the target floor to the end point, and finally merge the two routes
I encountered several problems

  1. How do I save the level tag to the graph node when reading osm
  2. In the api response, how to add floor information to points, such as
    {
    “hints”: {

    },
    “info”: {

    },
    “paths”: [
    {

    “points”: {
    “type”: “LineString”,
    “coordinates”: [
    [
    103.989152,
    1.360096,
    1
    ],
    [
    103.989195,
    1.360066,
    1
    ],
    [
    103.989195,
    1.360066, 2 ], [ 103.989266, 1.359997, 2 ], [ 103.989301, 1.359944, 2 ] ] }, “instructions”: [ … ] } } ] }

thanks
regards qingshan

GraphHopper’s graph memory layout does not provide easy support for storing extra data for nodes (in contrast to graph edges where this is easily possible with encoded values). However, you could certainly ‘abuse’ the elevation field to represent the level if you do not need it for elevation. You could then acquire the level of a node by simply calling something like graph.getNodeAccess().getEle(nodeId). This data would then even be part of the api response automatically, just like elevation normally.
Of course there are many other ways to store the level of each node: You could store a simple mapping between graph node IDs and the level for example, or even extend the graph memory layout for nodes (just add another field ‘level’ similarly to the already existing ‘elevation’ field).

Yes, I added a new level attribute, provided setter/getter in EdgeIteratorState, and set the level attribute when parsing osm. When looking for the nearest edge, I changed the filter to find the edge of the current floor, but found that the level in EdgeIteratorState is empty. Isn’t EdgeIteratorState global?

If you make sure your setter writes to the underlying memory it should be persistent. If you load the graph from disk your data needs to be flushed to disk before you close it, of course. But honestly I can only speculate what you are doing unless you are more specific.