diff --git a/brouter-core/src/main/java/btools/router/KinematicModel.java b/brouter-core/src/main/java/btools/router/KinematicModel.java index 0968b43..cf34abd 100644 --- a/brouter-core/src/main/java/btools/router/KinematicModel.java +++ b/brouter-core/src/main/java/btools/router/KinematicModel.java @@ -36,8 +36,8 @@ class KinematicModel extends OsmPathModel public double rightWaySpeed; // derived values - public double xweight; // the weight-factor between time and energy for cost calculation - public double timecost0; // minimum possible "energy-adjusted-time" per meter + public double pw; // balance power + public double cost0; // minimum possible cost per meter private int wayIdxMaxspeed; private int wayIdxMinspeed; @@ -50,6 +50,9 @@ class KinematicModel extends OsmPathModel private boolean initDone = false; + private double lastEffectiveLimit; + private double lastBreakingSpeed; + @Override public void init( BExpressionContextWay expctxWay, BExpressionContextNode expctxNode, Map extraParams ) { @@ -77,8 +80,8 @@ class KinematicModel extends OsmPathModel leftWaySpeed = getParam( "leftWaySpeed", 12.f ) / 3.6; rightWaySpeed = getParam( "rightWaySpeed", 12.f ) / 3.6; - xweight = 1./( 2. * f_air * vmax * vmax * vmax - p_standby ); - timecost0 = 1./vmax + xweight*(f_roll + f_air*vmax*vmax + p_standby/vmax ); + pw = 2. * f_air * vmax * vmax * vmax - p_standby; + cost0 = (pw+p_standby)/vmax + f_roll + f_air*vmax*vmax; } protected float getParam( String name, float defaultValue ) @@ -111,10 +114,39 @@ class KinematicModel extends OsmPathModel return ctxNode.getBuildInVariable( nodeIdxMaxspeed ) / 3.6f; } - public double getMaxKineticEnergy() + /** + * get the effective speed limit from the way-limit and vmax/vmin + */ + public double getEffectiveSpeedLimit( ) { - // determine maximum possible speed and kinetic energy - double mspeed = Math.min( getWayMaxspeed(), Math.max( getWayMinspeed(), vmax ) ); - return 0.5*totalweight*mspeed*mspeed; + return Math.min( getWayMaxspeed(), Math.max( getWayMinspeed(), vmax ) ); } + + /** + * get the breaking speed for current balance-power (pw) and effective speed limit (vl) + */ + public double getBreakingSpeed( double vl ) + { + if ( vl == lastEffectiveLimit ) + { + return lastBreakingSpeed; + } + + double v = vl*0.8; + double pw2 = pw+p_standby; + double e = recup_efficiency; + double x0 = pw2/vl+f_air*e*vl*vl+(1.-e)*f_roll; + for(int i=0;i<5;i++) + { + double v2 = v*v; + double x = pw2/v+f_air*e*v2 - x0; + double dx = 2.*e*f_air*v - pw2/v2; + v -= x/dx; + } + lastEffectiveLimit = vl; + lastBreakingSpeed = v; + + return v; + } + } diff --git a/brouter-core/src/main/java/btools/router/KinematicPath.java b/brouter-core/src/main/java/btools/router/KinematicPath.java index c40da1f..74f4075 100644 --- a/brouter-core/src/main/java/btools/router/KinematicPath.java +++ b/brouter-core/src/main/java/btools/router/KinematicPath.java @@ -42,13 +42,14 @@ final class KinematicPath extends OsmPath KinematicModel km = (KinematicModel)rc.pm; double cost = 0.; + double extraTime = 0.; if ( isStartpoint ) { // for forward direction, we start with target speed if ( !rc.inverseDirection ) { - cost = 0.5 * (1. - cosangle ) * 40. / km.timecost0; // 40 seconds turn penalty + extraTime = 0.5 * (1. - cosangle ) * 40.; // 40 seconds turn penalty } } else @@ -107,7 +108,11 @@ final class KinematicPath extends OsmPath if ( hasLeftWay && turnspeed > km.leftWaySpeed ) turnspeed = km.leftWaySpeed; if ( hasRightWay && turnspeed > km.rightWaySpeed ) turnspeed = km.rightWaySpeed; if ( hasResidential && turnspeed > residentialSpeed ) turnspeed = residentialSpeed; - if ( (lastpriorityclassifier < 20) ^ (priorityclassifier < 20) ) turnspeed = 0; // full stop for entering or leaving road network + if ( (lastpriorityclassifier < 20) ^ (priorityclassifier < 20) ) + { + extraTime += 10.; + turnspeed = 0; // full stop for entering or leaving road network + } } cutEkin( km.totalweight, turnspeed ); // apply turnspeed @@ -128,6 +133,9 @@ final class KinematicPath extends OsmPath message.costfactor = (float)(distanceCost/dist); } + cost += extraTime * km.pw / km.cost0; + totalTime += extraTime; + return cost + distanceCost; } @@ -137,12 +145,14 @@ final class KinematicPath extends OsmPath // elevation force double fh = delta_h * km.totalweight * 9.81 / dist; - double emax = km.getMaxKineticEnergy(); + double effectiveSpeedLimit = km.getEffectiveSpeedLimit(); + double emax = 0.5*km.totalweight*effectiveSpeedLimit*effectiveSpeedLimit; if ( emax <= 0. ) { return -1.; } - double elow = 0.7*emax; // recup phase below 70% energy (=84% vmax) + double vb = km.getBreakingSpeed( effectiveSpeedLimit ); + double elow = 0.5*km.totalweight*vb*vb; double elapsedTime = 0.; double dissipatedEnergy = 0.; @@ -209,7 +219,7 @@ final class KinematicPath extends OsmPath totalTime += elapsedTime; totalEnergy += dissipatedEnergy + dist*fh; - return (elapsedTime + km.xweight * dissipatedEnergy)/km.timecost0; // =cost + return (km.pw * elapsedTime + dissipatedEnergy)/km.cost0; // =cost } @Override diff --git a/misc/profiles2/car-eco.brf b/misc/profiles2/car-eco.brf index 0cbec3e..bc7a10d 100644 --- a/misc/profiles2/car-eco.brf +++ b/misc/profiles2/car-eco.brf @@ -177,5 +177,10 @@ assign initialcost = assign maxspeed = - if or crossing=traffic_signals highway=traffic_signals then 0 + if or crossing=traffic_signals highway=traffic_signals + then + switch greater way:priorityclassifier 24 5 + switch greater way:priorityclassifier 22 3 + switch greater way:priorityclassifier 20 1 + 0 else 999 diff --git a/misc/profiles2/car-fast.brf b/misc/profiles2/car-fast.brf index 3c9959a..ab6a494 100644 --- a/misc/profiles2/car-fast.brf +++ b/misc/profiles2/car-fast.brf @@ -177,5 +177,10 @@ assign initialcost = assign maxspeed = - if or crossing=traffic_signals highway=traffic_signals then 0 + if or crossing=traffic_signals highway=traffic_signals + then + switch greater way:priorityclassifier 24 5 + switch greater way:priorityclassifier 22 3 + switch greater way:priorityclassifier 20 1 + 0 else 999