@Override
    protected double processWaySection(final RoutingContext rc, final double dist, final double deltaH, final double elevation, final double angle, final double cosangle, final boolean isStartpoint, final int nsection, final int lastpriorityclassifier) {
        final KinematicModel km = (KinematicModel) rc.pm;

        double cost = 0.;
        double extraTime = 0.;

        if (isStartpoint) {
            // for forward direction, we start with target speed
            if (!rc.inverseDirection) {
                extraTime = 0.5 * (1. - cosangle) * 40.; // 40 seconds turn penalty
            }
        } else {
            double turnspeed = 999.; // just high

            if (km.turnAngleDecayTime != 0.) { // process turn-angle slowdown
                if (angle < 0) {
                    floatingAngleLeft -= (float) angle;
                } else {
                    floatingAngleRight += (float) angle;
                }
                final float aa = Math.max(floatingAngleLeft, floatingAngleRight);

                final double curveSpeed = aa > 10. ? 200. / aa : 20.;
                final double distanceTime = dist / curveSpeed;
                final double decayFactor = Math.exp(-distanceTime / km.turnAngleDecayTime);
                floatingAngleLeft = (float) (floatingAngleLeft * decayFactor);
                floatingAngleRight = (float) (floatingAngleRight * decayFactor);

                if (curveSpeed < 20.) {
                    turnspeed = curveSpeed;
                }
            }

            if (nsection == 0) { // process slowdown by crossing geometry
                double junctionspeed = 999.; // just high

                final int classifiermask = (int) rc.expctxWay.getClassifierMask();

                // penalty for equal priority crossing
                boolean hasLeftWay = false;
                boolean hasRightWay = false;
                boolean hasResidential = false;
                for (OsmPrePath prePath = rc.firstPrePath; prePath != null; prePath = prePath.next) {
                    final KinematicPrePath pp = (KinematicPrePath) prePath;

                    if (((pp.classifiermask ^ classifiermask) & 8) != 0) { // exactly one is linktype
                        continue;
                    }

                    if ((pp.classifiermask & 32) != 0) { // touching a residential?
                        hasResidential = true;
                    }

                    if (pp.priorityclassifier > priorityclassifier || pp.priorityclassifier == priorityclassifier && priorityclassifier < 20) {
                        final double diff = pp.angle - angle;
                        if (diff < -40. && diff > -140.) {
                            hasLeftWay = true;
                        }
                        if (diff > 40. && diff < 140.) {
                            hasRightWay = true;
                        }
                    }
                }
                final double residentialSpeed = 13.;

                if (hasLeftWay && junctionspeed > km.leftWaySpeed) {
                    junctionspeed = km.leftWaySpeed;
                }
                if (hasRightWay && junctionspeed > km.rightWaySpeed) {
                    junctionspeed = km.rightWaySpeed;
                }
                if (hasResidential && junctionspeed > residentialSpeed) {
                    junctionspeed = residentialSpeed;
                }

                if ((lastpriorityclassifier < 20) ^ (priorityclassifier < 20)) {
                    extraTime += 10.;
                    junctionspeed = 0; // full stop for entering or leaving road network
                }

                if (lastpriorityclassifier != priorityclassifier && (classifiermask & 8) != 0) {
                    extraTime += 2.; // two seconds for entering a link-type
                }
                turnspeed = Math.min(turnspeed, junctionspeed);

                if (message != null) {
                    message.vnode0 = (int) (junctionspeed * 3.6 + 0.5);
                }
            }
            cutEkin(km.totalweight, turnspeed); // apply turnspeed
        }

        // linear temperature correction
        final double tcorr = (20. - km.outsideTemp) * 0.0035;

        // air_pressure down 1mb/8m
        final double ecorr = 0.0001375 * (elevation - 100.);

        final double fAir = km.fAir * (1. + tcorr - ecorr);

        final double distanceCost = evolveDistance(km, dist, deltaH, fAir);

        if (message != null) {
            message.costfactor = (float) (distanceCost / dist);
            message.vmax = (int) (km.getWayMaxspeed() * 3.6 + 0.5);
            message.vmaxExplicit = (int) (km.getWayMaxspeedExplicit() * 3.6 + 0.5);
            message.vmin = (int) (km.getWayMinspeed() * 3.6 + 0.5);
            message.extraTime = (int) (extraTime * 1000);
        }

        cost += extraTime * km.pw / km.cost0;
        totalTime += extraTime;

        return cost + distanceCost;
    }
The path-instance of the kinematic model

@author ab
main/src/main/java/cgeo/geocaching/brouter/core/KinematicPath.java