Routing with custom data worked in 2.4, not in 3.0 or newer

I’m using a local Graphhopper server, bathymetry data and a custom PostGIS reader for boat navigation. It worked with 2.4, but now in 3.2 and 4.0-pre2 it does not find the route.

I get “ConnectionNotFoundException: Connection between locations not found”. I confirmed with the debugger that the starting and ending points get snapped correctly.

I also visualized the graph and it looks fine. There are connecting edges between the starting and ending point.

I experimented with different values for prepare.min_network_size and index.high_resolution, but it did not solve the problem.

I am suspecting that there is an issue with edge flags or the profile. Edge flags are quite confusing for a newbie like me.

Initialization

    GraphHopper hopper = new GraphHopperPostGIS(dataSource);
    GraphHopperConfig graphHopperConfig = new GraphHopperConfig();
    graphHopperConfig.putObject("graph.flag_encoders", "boat");
    graphHopperConfig.putObject("prepare.min_network_size", 0);
    graphHopperConfig.putObject("index.high_resolution", 2000);
    graphHopperConfig.putObject("graph.location", workPath);
    graphHopperConfig.setProfiles(List.of(
            new Profile("my_boat")
                    .setVehicle("boat").setWeighting("fastest")));
    hopper.setFlagEncoderFactory(new BoatFlagEncoderFactory());
    hopper.init(graphHopperConfig);
    hopper.clean();
    hopper.importOrLoad();

Node and edge initialization in the data reader

    ways.forEach(w -> {
        List<Point> path = w.getPath();
        nodeAccess.setNode(w.getStartId(), path.get(0).getLat(), path.get(0).getLon());
        nodeAccess.setNode(w.getEndId(), path.get(path.size() - 1).getLat(), path.get(path.size() - 1).getLon());
        EdgeIteratorState edge1 = graph.edge(w.getStartId(), w.getEndId());
        edge1.setDistance(w.length());
        IntsRef flags = ((BoatFlagEncoder) encodingManager.getEncoder("boat"))
                .handleWayTags(edge1.getFlags(), null, null);
        edge1.setFlags(flags);
        edge1.setWayGeometry(toPointList(w.withoutEndpoints()));
    });

Some code from BoatFlagEncoder

public class BoatFlagEncoder extends AbstractFlagEncoder {
...
...
    @Override
    public void createEncodedValues(List<EncodedValue> registerNewEncodedValue, String prefix, int index) {
        super.createEncodedValues(registerNewEncodedValue, prefix, index);
        registerNewEncodedValue.add(avgSpeedEnc = new UnsignedDecimalEncodedValue(EncodingManager.getKey(prefix, "average_speed"), speedBits, speedFactor, true));
    }

    @Override
    public EncodingManager.Access getAccess(ReaderWay way) {
        return EncodingManager.Access.WAY;
    }

    @Override
    public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay way, EncodingManager.Access accept) {
        accessEnc.setBool(false, edgeFlags, true);
        accessEnc.setBool(true, edgeFlags, true);
        setSpeed(true, edgeFlags, 80.0);
        return edgeFlags;
    }

    @Override
    public String toString() {
        return "boat";
    }

    @Override
    public double getMaxSpeed() {
        return 100.0;
    }

It’s still quite hackish. I started working on BoatFlagEncoder based on CarFlagEncoder and it needs a lot of cleaning after I get a minimum working implementation.

I cannot tell whats wrong from the code you posted. Do you get ‘connection not found’ only for a few routes or for every route? I think you should start the server and inspect the graph using the MVT endpoint. To do this open the web UI zoom in a bit, and enable ‘Local MVT’ in the map’s layers menu. You also need web.mvt.enabled: true in config.yml to make this work. You can then see GraphHopper’s road network and hover roads to see some of their attributes. You can adjust what is available in MVTResource.java. You probably want to add an entry for the edge’s weight and check if the weights on your desired route have a finite value. Something like

map.put("weight", graphHopper.createWeighting(graphHopper.getProfile("my_boat"), new PMap()));
1 Like

I figured it out. The speed was zero for some edges and it resulted in infinite weights. If I understood these correctly, you need to store values for forward and reverse traversal of edges. Well, at least these changes fixed it:

        avgSpeedEnc.setDecimal(true, edgeFlags, 100.0);
        avgSpeedEnc.setDecimal(false, edgeFlags, 100.0);

Thank you for pointing out that MVT endpoint. Sounds very useful for debugging. I will experiment with it.

Powered by Discourse