Custom vehicle doesn't work after update to 8.0

After update to 8.0 from 5.3 I tried to rewrite one of our custom encoder to TagParsers. There had to be an internal change in graphhopper or I made some weird mistake.

Old encoder:

class PisteEncoder : AbstractFlagEncoder(4, 1.0, 0) {

    init {
        avgSpeedEnc = DecimalEncodedValueImpl(EncodingManager.getKey(name, "average_speed"), speedBits, speedFactor, false)
        restrictedValues.clear()
        blockFords(false)
    }

    override fun createEncodedValues(registerNewEncodedValue: MutableList<EncodedValue?>) {
        super.createEncodedValues(registerNewEncodedValue)
        registerNewEncodedValue.add(avgSpeedEnc)
    }

    override fun getTransportationMode(): TransportationMode = TransportationMode.FOOT

    override fun getAccess(way: ReaderWay): EncodingManager.Access {
        return EncodingManager.Access.WAY
    }

    override fun applyWayTags(way: ReaderWay?, edge: EdgeIteratorState?) {
    }

    override fun handleWayTags(edgeFlags: IntsRef, way: ReaderWay): IntsRef {
        if (way.isPisteNordic()) {
            avgSpeedEnc.setDecimal(false, edgeFlags, 5.0)
            accessEnc.setBool(false, edgeFlags, way.isPisteNordic())
            accessEnc.setBool(true, edgeFlags, way.isPisteNordic())
        }

        return edgeFlags
    }

    private fun ReaderWay.isPisteNordic(): Boolean {
        return getTag("piste:type") == "nordic"
    }

}

New approach:

Access:

class PisteAccessParser(lookup: EncodedValueLookup, properties: PMap) : TagParser {

    private val accessEnc = lookup.getBooleanEncodedValue(VehicleAccess.key(properties.getString("name", "piste")))

    private fun ReaderWay.isPisteNordic(): Boolean {
        return getTag("piste:type") == "nordic"
    }

    override fun handleWayTags(edgeId: Int, edgeIntAccess: EdgeIntAccess?, way: ReaderWay, relationFlags: IntsRef?) {
        if (way.isPisteNordic()) {
            accessEnc.setBool(false, edgeId, edgeIntAccess, true)
            accessEnc.setBool(true, edgeId, edgeIntAccess, true)
        }
    }
}

Priority:

class PistePriorityParser(lookup: EncodedValueLookup, properties: PMap) : TagParser {

    private fun ReaderWay.isPisteNordic(): Boolean {
        return getTag("piste:type") == "nordic"
    }

    private val priorityWayEncoder = lookup.getDecimalEncodedValue(VehiclePriority.key(properties.getString("name", "piste")))

    override fun handleWayTags(edgeId: Int, edgeIntAccess: EdgeIntAccess, way: ReaderWay, relationFlags: IntsRef) {
        if (way.isPisteNordic()) {
            priorityWayEncoder.setDecimal(false, edgeId, edgeIntAccess, PriorityCode.getValue(PriorityCode.BEST.value))
        } else
            priorityWayEncoder.setDecimal(false, edgeId, edgeIntAccess, PriorityCode.getValue(PriorityCode.EXCLUDE.value))
    }
}

Average speed:

class PisteAverageSpeedParser(lookup: EncodedValueLookup, properties: PMap) : AbstractAverageSpeedParser(
    lookup.getDecimalEncodedValue(VehicleSpeed.key(properties.getString("name", "piste"))),
    lookup.getDecimalEncodedValue(FerrySpeed.KEY),
) {
    override fun handleWayTags(edgeId: Int, edgeIntAccess: EdgeIntAccess, way: ReaderWay) {
        if (way.isPisteNordic()) {
            setSpeed(false, edgeId, edgeIntAccess, 5.0)
        }
    }

    private fun ReaderWay.isPisteNordic(): Boolean {
        return getTag("piste:type") == "nordic"
    }
}

EncodedValues are created as foot with name change:

  configuration.putObject("name", "piste")
  VehicleEncodedValues.foot(configuration)

VehicleTagParsers:

 configuration.putObject("name", "piste")
        VehicleTagParsers(
            PisteAccessParser(lookup, configuration),
            PistePriorityParser(lookup, configuration),
            PisteAverageSpeedParser(lookup, configuration),
        )

I always receive PointNotFoundException.

Continuing the discussion from here.

I am sure that TagParsers are called correctly, if I remove all “way.isPiste()” calls and just set speed and access then it works.

What do you mean here? The default value for the speed encoded value is 0 and for the access encoded value it is false. So it sounds a bit strange that it works if you remove the code that makes the values valid.

I have no idea what “import.osm.ignored_highways” are

It is a new property introduced in 7.x I think. See this commit. But shouldn’t matter in your case if none are specified.

Piste tag is set on ways which are not highways, that is the point of this custom vehicle, so maybe some code inside graphhopper is strictly allowing only highway tags?

It should be more flexible now, but might require code changes. See this comment.

See this code where some filtering is happening.

Thanks for your help, I found the issue. In never version of Graphhopper there is filter, that blocks almost all not “highway” ways. It seems it should be modified to be more flexible, because now I cannot see a way to interact with it.

Parser is created inside OSMReader so it is hard to modify it:

  WaySegmentParser waySegmentParser = new WaySegmentParser.Builder(baseGraph.getNodeAccess(), baseGraph.getDirectory())
                .setElevationProvider(eleProvider)
                .setWayFilter(this::acceptWay)
                .setSplitNodeFilter(this::isBarrierNode)
                .setWayPreprocessor(this::preprocessWay)
                .setRelationPreprocessor(this::preprocessRelations)
                .setRelationProcessor(this::processRelation)
                .setEdgeHandler(this::addEdge)
                .setWorkerThreads(config.getWorkerThreads())
                .build();

“.setWayFilter(this::acceptWay)” is setting this global filter.

I created pre processor that is adding highway:piste tag to every way with piste:type tag and everything works