diff --git a/brouter-core/src/main/java/btools/router/KinematicModel.java b/brouter-core/src/main/java/btools/router/KinematicModel.java index db35a30..5631eaa 100644 --- a/brouter-core/src/main/java/btools/router/KinematicModel.java +++ b/brouter-core/src/main/java/btools/router/KinematicModel.java @@ -5,7 +5,8 @@ */ package btools.router; -import btools.expressions.BExpressionContext; +import java.util.Map; + import btools.expressions.BExpressionContextNode; import btools.expressions.BExpressionContextWay; @@ -27,6 +28,7 @@ class KinematicModel extends OsmPathModel public double f_air; public double f_recup; public double p_standby; + public double outside_temp; public double recup_efficiency; public double totalweight; public double vmax; @@ -44,34 +46,51 @@ class KinematicModel extends OsmPathModel protected BExpressionContextWay ctxWay; protected BExpressionContextNode ctxNode; + protected Map params; + private boolean initDone = false; @Override - public void init( BExpressionContextWay expctxWay, BExpressionContextNode expctxNode ) + public void init( BExpressionContextWay expctxWay, BExpressionContextNode expctxNode, Map extraParams ) { - ctxWay = expctxWay; - ctxNode = expctxNode; - - BExpressionContext expctxGlobal = expctxWay; // just one of them... + if ( !initDone ) + { + ctxWay = expctxWay; + ctxNode = expctxNode; + wayIdxMaxspeed = ctxWay.getOutputVariableIndex( "maxspeed", false ); + wayIdxMinspeed = ctxWay.getOutputVariableIndex( "minspeed", false ); + nodeIdxMaxspeed = ctxNode.getOutputVariableIndex( "maxspeed", false ); + initDone = true; + } - turnAngleDecayLength = expctxGlobal.getVariableValue( "turnAngleDecayLength", 50.f ); - f_roll = expctxGlobal.getVariableValue( "f_roll", 232.f ); - f_air = expctxGlobal.getVariableValue( "f_air", 0.4f ); - f_recup = expctxGlobal.getVariableValue( "f_recup", 400.f ); - p_standby = expctxGlobal.getVariableValue( "p_standby", 250.f ); - recup_efficiency = expctxGlobal.getVariableValue( "recup_efficiency", 0.7f ); - totalweight = expctxGlobal.getVariableValue( "totalweight", 1640.f ); - vmax = expctxGlobal.getVariableValue( "vmax", 80.f ) / 3.6; - leftWaySpeed = expctxGlobal.getVariableValue( "leftWaySpeed", 12.f ) / 3.6; - rightWaySpeed = expctxGlobal.getVariableValue( "rightWaySpeed", 12.f ) / 3.6; + params = extraParams; + + turnAngleDecayLength = getParam( "turnAngleDecayLength", 50.f ); + f_roll = getParam( "f_roll", 232.f ); + f_air = getParam( "f_air", 0.4f ); + f_recup = getParam( "f_recup", 400.f ); + p_standby = getParam( "p_standby", 250.f ); + outside_temp = getParam( "outside_temp", 20.f ); + recup_efficiency = getParam( "recup_efficiency", 0.7f ); + totalweight = getParam( "totalweight", 1640.f ); + vmax = getParam( "vmax", 80.f ) / 3.6; + 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 ); - - wayIdxMaxspeed = ctxWay.getOutputVariableIndex( "maxspeed", false ); - wayIdxMinspeed = ctxWay.getOutputVariableIndex( "minspeed", false ); + } - nodeIdxMaxspeed = ctxNode.getOutputVariableIndex( "maxspeed", false ); + protected float getParam( String name, float defaultValue ) + { + String sval = params == null ? null : params.get( name ); + if ( sval != null ) + { + return Float.parseFloat( sval ); + } + float v = ctxWay.getVariableValue( name, defaultValue ); + params.put( name, "" + v ); + return v; } public float getWayMaxspeed() diff --git a/brouter-core/src/main/java/btools/router/KinematicModelDummy.java b/brouter-core/src/main/java/btools/router/KinematicModelDummy.java index b215f6c..af4c2b4 100644 --- a/brouter-core/src/main/java/btools/router/KinematicModelDummy.java +++ b/brouter-core/src/main/java/btools/router/KinematicModelDummy.java @@ -5,6 +5,8 @@ */ package btools.router; +import java.util.Map; + import btools.expressions.BExpressionContextNode; import btools.expressions.BExpressionContextWay; @@ -41,7 +43,7 @@ final class KinematicModelDummy extends KinematicModel public double timecost0 = 1./vmax + xweight*(f_roll + f_air*vmax*vmax + p_standby/vmax ); @Override - public void init( BExpressionContextWay expctxWay, BExpressionContextNode expctxNode ) + public void init( BExpressionContextWay expctxWay, BExpressionContextNode expctxNode, Map extraParams ) { } diff --git a/brouter-core/src/main/java/btools/router/KinematicPath.java b/brouter-core/src/main/java/btools/router/KinematicPath.java index 24884cd..c40da1f 100644 --- a/brouter-core/src/main/java/btools/router/KinematicPath.java +++ b/brouter-core/src/main/java/btools/router/KinematicPath.java @@ -37,7 +37,7 @@ final class KinematicPath extends OsmPath } @Override - protected double processWaySection( RoutingContext rc, double dist, double delta_h, double angle, double cosangle, boolean isStartpoint, int nsection, int lastpriorityclassifier ) + protected double processWaySection( RoutingContext rc, double dist, double delta_h, double elevation, double angle, double cosangle, boolean isStartpoint, int nsection, int lastpriorityclassifier ) { KinematicModel km = (KinematicModel)rc.pm; @@ -113,7 +113,15 @@ final class KinematicPath extends OsmPath cutEkin( km.totalweight, turnspeed ); // apply turnspeed } - double distanceCost = evolveDistance( km, dist, delta_h ); + // linear temperature correction + double tcorr = (20.-km.outside_temp)*0.0035; + + // air_pressure down 1mb/8m + double ecorr = 0.0001375 * (elevation - 100.); + + double f_air = km.f_air * ( 1. + tcorr - ecorr ); + + double distanceCost = evolveDistance( km, dist, delta_h, f_air ); if ( message != null ) { @@ -124,7 +132,7 @@ final class KinematicPath extends OsmPath } - protected double evolveDistance( KinematicModel km, double dist, double delta_h ) + protected double evolveDistance( KinematicModel km, double dist, double delta_h, double f_air ) { // elevation force double fh = delta_h * km.totalweight * 9.81 / dist; @@ -134,7 +142,7 @@ final class KinematicPath extends OsmPath { return -1.; } - double elow = 0.5*emax; // recup phase below half energy (=70% vmax) + double elow = 0.7*emax; // recup phase below 70% energy (=84% vmax) double elapsedTime = 0.; double dissipatedEnergy = 0.; @@ -146,23 +154,24 @@ final class KinematicPath extends OsmPath boolean slow = ekin < elow; boolean fast = ekin >= emax; double etarget = slow ? elow : emax; - double f = km.f_roll + km.f_air*v*v + fh; + double f = km.f_roll + f_air*v*v + fh; double f_recup = Math.max( 0., fast ? -f : (slow ? km.f_recup :0 ) -fh ); // additional recup for slow part f += f_recup; double delta_ekin; + double timeStep; double x; if ( fast ) { x = d; delta_ekin = x*f; - elapsedTime += x/v; + timeStep = x/v; ekin = etarget; } else { delta_ekin = etarget-ekin; - double b = 2.*km.f_air / km.totalweight; + double b = 2.*f_air / km.totalweight; double x0 = delta_ekin/f; double x0b = x0*b; x = x0*(1. - x0b*(0.5 + x0b*(0.333333333-x0b*0.25 ) ) ); // = ln( delta_ekin*b/f + 1.) / b; @@ -180,13 +189,19 @@ final class KinematicPath extends OsmPath } double v2 = Math.sqrt( 2. * ekin / km.totalweight ); double a = f / km.totalweight; // TODO: average force? - elapsedTime += (v2-v)/a; + timeStep = (v2-v)/a; v = v2; } d -= x; + elapsedTime += timeStep; // dissipated energy does not contain elevation and efficient recup dissipatedEnergy += delta_ekin - x*(fh + f_recup*km.recup_efficiency); + + // correction: inefficient recup going into heating is half efficient + double ieRecup = x*f_recup*(1.-km.recup_efficiency); + double eaux = timeStep*km.p_standby; + dissipatedEnergy -= Math.max( ieRecup, eaux ) * 0.5; } dissipatedEnergy += elapsedTime * km.p_standby; diff --git a/brouter-core/src/main/java/btools/router/OsmPath.java b/brouter-core/src/main/java/btools/router/OsmPath.java index 1454662..2df58a1 100644 --- a/brouter-core/src/main/java/btools/router/OsmPath.java +++ b/brouter-core/src/main/java/btools/router/OsmPath.java @@ -305,8 +305,9 @@ abstract class OsmPath implements OsmLinkHolder } } + double elevation = ele2 == Short.MIN_VALUE ? 100. : ele2/4.; - double sectionCost = processWaySection( rc, dist, delta_h, angle, cosangle, isStartpoint, nsection, lastpriorityclassifier ); + double sectionCost = processWaySection( rc, dist, delta_h, elevation, angle, cosangle, isStartpoint, nsection, lastpriorityclassifier ); if ( ( sectionCost < 0. || costfactor > 9998. && !detailMode ) || sectionCost + cost >= 2000000000. ) { cost = -1; @@ -413,7 +414,7 @@ abstract class OsmPath implements OsmLinkHolder return (short)( e1*(1.-fraction) + e2*fraction ); } - protected abstract double processWaySection( RoutingContext rc, double dist, double delta_h, double angle, double cosangle, boolean isStartpoint, int nsection, int lastpriorityclassifier ); + protected abstract double processWaySection( RoutingContext rc, double dist, double delta_h, double elevation, double angle, double cosangle, boolean isStartpoint, int nsection, int lastpriorityclassifier ); protected abstract double processTargetNode( RoutingContext rc ); diff --git a/brouter-core/src/main/java/btools/router/OsmPathModel.java b/brouter-core/src/main/java/btools/router/OsmPathModel.java index 17a7bda..63b21b3 100644 --- a/brouter-core/src/main/java/btools/router/OsmPathModel.java +++ b/brouter-core/src/main/java/btools/router/OsmPathModel.java @@ -5,7 +5,8 @@ */ package btools.router; -import btools.expressions.BExpressionContext; +import java.util.Map; + import btools.expressions.BExpressionContextNode; import btools.expressions.BExpressionContextWay; @@ -16,5 +17,5 @@ abstract class OsmPathModel public abstract OsmPath createPath(); - public abstract void init( BExpressionContextWay expctxWay, BExpressionContextNode expctxNode ); + public abstract void init( BExpressionContextWay expctxWay, BExpressionContextNode expctxNode, Map keyValues ); } diff --git a/brouter-core/src/main/java/btools/router/ProfileCache.java b/brouter-core/src/main/java/btools/router/ProfileCache.java index b6b4c8f..d823c96 100644 --- a/brouter-core/src/main/java/btools/router/ProfileCache.java +++ b/brouter-core/src/main/java/btools/router/ProfileCache.java @@ -39,7 +39,8 @@ public final class ProfileCache profileDir = new File( profileBaseDir ); profileFile = new File( profileDir, rc.localFunction + ".brf" ) ; } - rc.profileTimestamp = profileFile.lastModified(); + + rc.profileTimestamp = profileFile.lastModified() + rc.getKeyValueChecksum()<<24; File lookupFile = new File( profileDir, "lookups.dat" ); // check for re-use diff --git a/brouter-core/src/main/java/btools/router/RoutingContext.java b/brouter-core/src/main/java/btools/router/RoutingContext.java index 5c28da5..01ee5e2 100644 --- a/brouter-core/src/main/java/btools/router/RoutingContext.java +++ b/brouter-core/src/main/java/btools/router/RoutingContext.java @@ -9,6 +9,7 @@ import java.io.DataOutput; import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Map; import btools.expressions.BExpressionContext; import btools.expressions.BExpressionContextNode; @@ -30,6 +31,8 @@ public final class RoutingContext public String localFunction; public long profileTimestamp; + public Map keyValues; + public String rawTrackPath; public String getProfileName() @@ -91,9 +94,27 @@ public final class RoutingContext throw new RuntimeException( "Cannot create path-model: " + e ); } } - pm.init( expctxWay, expctxNode ); + initModel(); } + public void initModel() + { + pm.init( expctxWay, expctxNode, keyValues ); + } + + public long getKeyValueChecksum() + { + long s = 0L; + if ( keyValues != null ) + { + for( Map.Entry e : keyValues.entrySet() ) + { + s += e.getKey().hashCode() + e.getValue().hashCode(); + } + } + return s; + } + public void readGlobalConfig() { BExpressionContext expctxGlobal = expctxWay; // just one of them... diff --git a/brouter-core/src/main/java/btools/router/StdModel.java b/brouter-core/src/main/java/btools/router/StdModel.java index 11f4701..84d360e 100644 --- a/brouter-core/src/main/java/btools/router/StdModel.java +++ b/brouter-core/src/main/java/btools/router/StdModel.java @@ -5,6 +5,8 @@ */ package btools.router; +import java.util.Map; + import btools.expressions.BExpressionContext; import btools.expressions.BExpressionContextNode; import btools.expressions.BExpressionContextWay; @@ -27,7 +29,7 @@ final class StdModel extends OsmPathModel @Override - public void init( BExpressionContextWay expctxWay, BExpressionContextNode expctxNode ) + public void init( BExpressionContextWay expctxWay, BExpressionContextNode expctxNode, Map keyValues ) { ctxWay = expctxWay; ctxNode = expctxNode; diff --git a/brouter-core/src/main/java/btools/router/StdPath.java b/brouter-core/src/main/java/btools/router/StdPath.java index 6f73f92..c1a8524 100644 --- a/brouter-core/src/main/java/btools/router/StdPath.java +++ b/brouter-core/src/main/java/btools/router/StdPath.java @@ -34,7 +34,7 @@ final class StdPath extends OsmPath } @Override - protected double processWaySection( RoutingContext rc, double distance, double delta_h, double angle, double cosangle, boolean isStartpoint, int nsection, int lastpriorityclassifier ) + protected double processWaySection( RoutingContext rc, double distance, double delta_h, double elevation, double angle, double cosangle, boolean isStartpoint, int nsection, int lastpriorityclassifier ) { // calculate the costfactor inputs float turncostbase = rc.expctxWay.getTurncost();