Merge pull request #125 from Phyks/travelTime

Travel time computation for bikes and foot
This commit is contained in:
abrensch 2018-11-23 00:04:25 +01:00 committed by GitHub
commit c57eaf9eff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 196 additions and 84 deletions

View file

@ -9,11 +9,15 @@ package btools.router;
final class KinematicPath extends OsmPath final class KinematicPath extends OsmPath
{ {
private double ekin; // kinetic energy (Joule) private double ekin; // kinetic energy (Joule)
private double totalTime; // travel time (seconds)
private double totalEnergy; // total route energy (Joule) private double totalEnergy; // total route energy (Joule)
private float floatingAngleLeft; // sliding average left bend (degree) private float floatingAngleLeft; // sliding average left bend (degree)
private float floatingAngleRight; // sliding average right bend (degree) private float floatingAngleRight; // sliding average right bend (degree)
KinematicPath() {
super();
computeTime = false; // Time is already computed by the kinematic model.
}
@Override @Override
protected void init( OsmPath orig ) protected void init( OsmPath orig )
{ {
@ -35,12 +39,12 @@ final class KinematicPath extends OsmPath
floatingAngleLeft = 0.f; floatingAngleLeft = 0.f;
floatingAngleRight = 0.f; floatingAngleRight = 0.f;
} }
@Override @Override
protected double processWaySection( RoutingContext rc, double dist, double delta_h, double elevation, 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; KinematicModel km = (KinematicModel)rc.pm;
double cost = 0.; double cost = 0.;
double extraTime = 0.; double extraTime = 0.;
@ -64,7 +68,7 @@ final class KinematicPath extends OsmPath
if ( angle < 0 ) floatingAngleLeft -= (float)angle; if ( angle < 0 ) floatingAngleLeft -= (float)angle;
else floatingAngleRight += (float)angle; else floatingAngleRight += (float)angle;
float aa = Math.max( floatingAngleLeft, floatingAngleRight ); float aa = Math.max( floatingAngleLeft, floatingAngleRight );
if ( aa > 130. ) turnspeed = 0.; if ( aa > 130. ) turnspeed = 0.;
else if ( aa > 100. ) turnspeed = 1.; else if ( aa > 100. ) turnspeed = 1.;
else if ( aa > 70. ) turnspeed = 2.; else if ( aa > 70. ) turnspeed = 2.;
@ -73,9 +77,9 @@ final class KinematicPath extends OsmPath
else if ( aa > 20. ) turnspeed = 14.; else if ( aa > 20. ) turnspeed = 14.;
else if ( aa > 10. ) turnspeed = 20.; else if ( aa > 10. ) turnspeed = 20.;
} }
if ( nsection == 0 ) // process slowdown by crossing geometry if ( nsection == 0 ) // process slowdown by crossing geometry
{ {
int classifiermask = (int)rc.expctxWay.getClassifierMask(); int classifiermask = (int)rc.expctxWay.getClassifierMask();
// penalty for equal priority crossing // penalty for equal priority crossing
@ -85,12 +89,12 @@ final class KinematicPath extends OsmPath
for( OsmPrePath prePath = rc.firstPrePath; prePath != null; prePath = prePath.next ) for( OsmPrePath prePath = rc.firstPrePath; prePath != null; prePath = prePath.next )
{ {
KinematicPrePath pp = (KinematicPrePath)prePath; KinematicPrePath pp = (KinematicPrePath)prePath;
if ( ( (pp.classifiermask ^ classifiermask) & 8 ) != 0 ) // exactly one is linktype if ( ( (pp.classifiermask ^ classifiermask) & 8 ) != 0 ) // exactly one is linktype
{ {
continue; continue;
} }
if ( ( pp.classifiermask & 32 ) != 0 ) // touching a residential? if ( ( pp.classifiermask & 32 ) != 0 ) // touching a residential?
{ {
hasResidential = true; hasResidential = true;
@ -104,7 +108,7 @@ final class KinematicPath extends OsmPath
} }
} }
double residentialSpeed = 13.; double residentialSpeed = 13.;
if ( hasLeftWay && turnspeed > km.leftWaySpeed ) turnspeed = km.leftWaySpeed; if ( hasLeftWay && turnspeed > km.leftWaySpeed ) turnspeed = km.leftWaySpeed;
if ( hasRightWay && turnspeed > km.rightWaySpeed ) turnspeed = km.rightWaySpeed; if ( hasRightWay && turnspeed > km.rightWaySpeed ) turnspeed = km.rightWaySpeed;
if ( hasResidential && turnspeed > residentialSpeed ) turnspeed = residentialSpeed; if ( hasResidential && turnspeed > residentialSpeed ) turnspeed = residentialSpeed;
@ -141,7 +145,7 @@ final class KinematicPath extends OsmPath
protected double evolveDistance( KinematicModel km, double dist, double delta_h, double f_air ) protected double evolveDistance( KinematicModel km, double dist, double delta_h, double f_air )
{ {
// elevation force // elevation force
double fh = delta_h * km.totalweight * 9.81 / dist; double fh = delta_h * km.totalweight * 9.81 / dist;
@ -154,7 +158,7 @@ final class KinematicPath extends OsmPath
double vb = km.getBreakingSpeed( effectiveSpeedLimit ); double vb = km.getBreakingSpeed( effectiveSpeedLimit );
double elow = 0.5*km.totalweight*vb*vb; double elow = 0.5*km.totalweight*vb*vb;
double elapsedTime = 0.; double elapsedTime = 0.;
double dissipatedEnergy = 0.; double dissipatedEnergy = 0.;
double v = Math.sqrt( 2. * ekin / km.totalweight ); double v = Math.sqrt( 2. * ekin / km.totalweight );
@ -167,7 +171,7 @@ final class KinematicPath extends OsmPath
double f = km.f_roll + 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 double f_recup = Math.max( 0., fast ? -f : (slow ? km.f_recup :0 ) -fh ); // additional recup for slow part
f += f_recup; f += f_recup;
double delta_ekin; double delta_ekin;
double timeStep; double timeStep;
double x; double x;
@ -215,7 +219,7 @@ final class KinematicPath extends OsmPath
} }
dissipatedEnergy += elapsedTime * km.p_standby; dissipatedEnergy += elapsedTime * km.p_standby;
totalTime += elapsedTime; totalTime += elapsedTime;
totalEnergy += dissipatedEnergy + dist*fh; totalEnergy += dissipatedEnergy + dist*fh;
@ -235,7 +239,7 @@ final class KinematicPath extends OsmPath
if ( initialcost >= 1000000. ) if ( initialcost >= 1000000. )
{ {
return -1.; return -1.;
} }
cutEkin( km.totalweight, km.getNodeMaxspeed() ); // apply node maxspeed cutEkin( km.totalweight, km.getNodeMaxspeed() ); // apply node maxspeed
if ( message != null ) if ( message != null )
@ -247,7 +251,7 @@ final class KinematicPath extends OsmPath
} }
return 0.; return 0.;
} }
private void cutEkin( double weight, double speed ) private void cutEkin( double weight, double speed )
{ {
double e = 0.5*weight*speed*speed; double e = 0.5*weight*speed*speed;
@ -264,7 +268,7 @@ final class KinematicPath extends OsmPath
f *= 0.367879; f *= 0.367879;
} }
return f*( 1. + x*( 1. + x * ( 0.5 + x * ( 0.166667 + 0.0416667 * x) ) ) ); return f*( 1. + x*( 1. + x * ( 0.5 + x * ( 0.166667 + 0.0416667 * x) ) ) );
} }
@Override @Override
@ -281,14 +285,14 @@ final class KinematicPath extends OsmPath
int c = p.cost; int c = p.cost;
return cost > c + 100; return cost > c + 100;
} }
public double getTotalTime() public double getTotalTime()
{ {
return totalTime; return totalTime;
} }
public double getTotalEnergy() public double getTotalEnergy()
{ {
return totalEnergy; return totalEnergy;

View file

@ -25,7 +25,7 @@ abstract class OsmPath implements OsmLinkHolder
public short selev; public short selev;
public int airdistance = 0; // distance to endpos public int airdistance = 0; // distance to endpos
protected OsmNode sourceNode; protected OsmNode sourceNode;
protected OsmNode targetNode; protected OsmNode targetNode;
@ -50,6 +50,12 @@ abstract class OsmPath implements OsmLinkHolder
protected int priorityclassifier; protected int priorityclassifier;
protected boolean computeTime = false;
protected double totalTime; // travel time (seconds)
// Gravitational constant, g
private double GRAVITY = 9.81; // in meters per second^(-2)
private static final int PATH_START_BIT = 1; private static final int PATH_START_BIT = 1;
private static final int CAN_LEAVE_DESTINATION_BIT = 2; private static final int CAN_LEAVE_DESTINATION_BIT = 2;
private static final int IS_ON_DESTINATION_BIT = 4; private static final int IS_ON_DESTINATION_BIT = 4;
@ -129,7 +135,7 @@ abstract class OsmPath implements OsmLinkHolder
init( origin ); init( origin );
addAddionalPenalty(refTrack, detailMode, origin, link, rc ); addAddionalPenalty(refTrack, detailMode, origin, link, rc );
} }
protected abstract void init( OsmPath orig ); protected abstract void init( OsmPath orig );
protected abstract void resetState(); protected abstract void resetState();
@ -191,7 +197,7 @@ abstract class OsmPath implements OsmLinkHolder
lastClassifier = newClassifier; lastClassifier = newClassifier;
lastInitialCost = newInitialCost; lastInitialCost = newInitialCost;
// *** destination logic: no destination access in between // *** destination logic: no destination access in between
int classifiermask = (int)rc.expctxWay.getClassifierMask(); int classifiermask = (int)rc.expctxWay.getClassifierMask();
boolean newDestination = (classifiermask & 64) != 0; boolean newDestination = (classifiermask & 64) != 0;
boolean oldDestination = getBit( IS_ON_DESTINATION_BIT ); boolean oldDestination = getBit( IS_ON_DESTINATION_BIT );
@ -217,14 +223,14 @@ abstract class OsmPath implements OsmLinkHolder
} }
} }
setBit( IS_ON_DESTINATION_BIT, newDestination ); setBit( IS_ON_DESTINATION_BIT, newDestination );
OsmTransferNode transferNode = link.geometry == null ? null OsmTransferNode transferNode = link.geometry == null ? null
: rc.geometryDecoder.decodeGeometry( link.geometry, sourceNode, targetNode, isReverse ); : rc.geometryDecoder.decodeGeometry( link.geometry, sourceNode, targetNode, isReverse );
for(int nsection=0; ;nsection++) for(int nsection=0; ;nsection++)
{ {
originLon = lon1; originLon = lon1;
originLat = lat1; originLat = lat1;
@ -300,7 +306,7 @@ abstract class OsmPath implements OsmLinkHolder
} }
int dist = rc.calcDistance( lon1, lat1, lon2, lat2 ); int dist = rc.calcDistance( lon1, lat1, lon2, lat2 );
boolean stopAtEndpoint = false; boolean stopAtEndpoint = false;
if ( rc.shortestmatch ) if ( rc.shortestmatch )
{ {
@ -393,63 +399,130 @@ abstract class OsmPath implements OsmLinkHolder
traffic += dist*rc.expctxWay.getTrafficSourceDensity()*Math.pow(cost2/10000.f,rc.trafficSourceExponent); traffic += dist*rc.expctxWay.getTrafficSourceDensity()*Math.pow(cost2/10000.f,rc.trafficSourceExponent);
} }
if ( message != null ) String wayKeyValues = "";
{ if ( message != null ) {
message.turnangle = (float)angle; wayKeyValues = rc.expctxWay.getKeyValueDescription( isReverse, description );
message.time = (float)getTotalTime();
message.energy = (float)getTotalEnergy();
message.priorityclassifier = priorityclassifier;
message.classifiermask = classifiermask;
message.lon = lon2;
message.lat = lat2;
message.ele = ele2;
message.wayKeyValues = rc.expctxWay.getKeyValueDescription( isReverse, description );
} }
if ( stopAtEndpoint ) // Only do speed computation for detailMode (final) and bike or foot modes.
if (detailMode && computeTime)
{ {
if ( recordTransferNodes ) // Travel speed
double speed = Double.NaN;
if (rc.footMode || (rc.bikeMode && wayKeyValues.contains("bicycle=dismount")))
{ {
originElement = OsmPathElement.create( rc.ilonshortest, rc.ilatshortest, ele2, originElement, rc.countTraffic ); // Use Tobler's hiking function for walking sections
originElement.cost = cost; speed = 6 * Math.exp(-3.5 * Math.abs(elevation / dist + 0.05)) / 3.6;
if ( message != null ) }
else if (rc.bikeMode)
{
// Uphill angle
double alpha = Math.atan2(delta_h, dist);
// Compute the speed assuming a basic kinematic model with constant
// power.
// Solves a * v^3 + b * v^2 + c * v + d = 0 with a Newton method to get
// the speed v for the section.
double a = rc.S_C_x;
double b = 0.0;
double c = (rc.bikeMass * GRAVITY * (rc.defaultC_r + Math.sin(alpha)));
double d = -1. * rc.bikerPower;
double tolerance = 1e-3;
int max_count = 10;
// Initial guess, this works rather well considering the allowed speeds.
speed = rc.maxSpeed;
double y = (a * speed * speed * speed) + (b * speed * speed) + (c * speed) + d;
double y_prime = (3 * a * speed * speed) + (2 * b * speed) + c;
int i = 0;
for (i = 0; (Math.abs(y) > tolerance) && (i < max_count); i++) {
speed = speed - y / y_prime;
if (speed > rc.maxSpeed || speed <= 0) {
// No need to compute further, the speed is likely to be
// invalid or force set to maxspeed.
speed = rc.maxSpeed;
break;
}
y = (a * speed * speed * speed) + (b * speed * speed) + (c * speed) + d;
y_prime = (3 * a * speed * speed) + (2 * b * speed) + c;
}
if (i == max_count)
{ {
originElement.message = message; // Newton method did not converge, speed is invalid.
speed = Double.NaN;
}
else
{
// Speed cannot exceed max speed
speed = Math.min(speed, rc.maxSpeed);
} }
} }
if ( rc.nogomatch ) if (!Double.isNaN(speed) && speed > 0)
{ {
cost = -1; totalTime += dist / speed;
} }
return;
} }
if ( transferNode == null ) if ( message != null )
{
// *** penalty for being part of the reference track
if ( refTrack != null && refTrack.containsNode( targetNode ) && refTrack.containsNode( sourceNode ) )
{ {
int reftrackcost = linkdisttotal; message.turnangle = (float)angle;
cost += reftrackcost; message.time = (float)getTotalTime();
message.energy = (float)getTotalEnergy();
message.priorityclassifier = priorityclassifier;
message.classifiermask = classifiermask;
message.lon = lon2;
message.lat = lat2;
message.ele = ele2;
message.wayKeyValues = wayKeyValues;
} }
selev = ele2;
break;
}
transferNode = transferNode.next;
if ( recordTransferNodes ) if ( stopAtEndpoint )
{ {
originElement = OsmPathElement.create( lon2, lat2, ele2, originElement, rc.countTraffic ); if ( recordTransferNodes )
originElement.cost = cost; {
originElement.addTraffic( traffic ); originElement = OsmPathElement.create( rc.ilonshortest, rc.ilatshortest, ele2, originElement, rc.countTraffic );
traffic = 0; originElement.cost = cost;
if ( message != null )
{
originElement.message = message;
}
}
if ( rc.nogomatch )
{
cost = -1;
}
return;
}
if ( transferNode == null )
{
// *** penalty for being part of the reference track
if ( refTrack != null && refTrack.containsNode( targetNode ) && refTrack.containsNode( sourceNode ) )
{
int reftrackcost = linkdisttotal;
cost += reftrackcost;
}
selev = ele2;
break;
}
transferNode = transferNode.next;
if ( recordTransferNodes )
{
originElement = OsmPathElement.create( lon2, lat2, ele2, originElement, rc.countTraffic );
originElement.cost = cost;
originElement.addTraffic( traffic );
traffic = 0;
}
lon0 = lon1;
lat0 = lat1;
lon1 = lon2;
lat1 = lat2;
ele1 = ele2;
} }
lon0 = lon1;
lat0 = lat1;
lon1 = lon2;
lat1 = lat2;
ele1 = ele2;
}
// check for nogo-matches (after the *actual* start of segment) // check for nogo-matches (after the *actual* start of segment)
if ( rc.nogomatch ) if ( rc.nogomatch )
@ -514,9 +587,9 @@ abstract class OsmPath implements OsmLinkHolder
public double getTotalTime() public double getTotalTime()
{ {
return 0.; return totalTime;
} }
public double getTotalEnergy() public double getTotalEnergy()
{ {
return 0.; return 0.;

View file

@ -34,7 +34,7 @@ public final class RoutingContext
public Map<String,String> keyValues; public Map<String,String> keyValues;
public String rawTrackPath; public String rawTrackPath;
public String getProfileName() public String getProfileName()
{ {
String name = localFunction == null ? "unknown" : localFunction; String name = localFunction == null ? "unknown" : localFunction;
@ -46,17 +46,18 @@ public final class RoutingContext
public BExpressionContextWay expctxWay; public BExpressionContextWay expctxWay;
public BExpressionContextNode expctxNode; public BExpressionContextNode expctxNode;
public GeometryDecoder geometryDecoder = new GeometryDecoder(); public GeometryDecoder geometryDecoder = new GeometryDecoder();
public int memoryclass = 64; public int memoryclass = 64;
public int downhillcostdiv; public int downhillcostdiv;
public int downhillcutoff; public int downhillcutoff;
public int uphillcostdiv; public int uphillcostdiv;
public int uphillcutoff; public int uphillcutoff;
public boolean carMode; public boolean carMode;
public boolean bikeMode; public boolean bikeMode;
public boolean footMode;
public boolean considerTurnRestrictions; public boolean considerTurnRestrictions;
public boolean processUnusedTags; public boolean processUnusedTags;
public boolean forceSecondaryData; public boolean forceSecondaryData;
@ -74,8 +75,8 @@ public final class RoutingContext
public double inittimeadjustment; public double inittimeadjustment;
public double starttimeoffset; public double starttimeoffset;
public boolean transitonly; public boolean transitonly;
private void setModel( String className ) private void setModel( String className )
{ {
if ( className == null ) if ( className == null )
@ -96,7 +97,7 @@ public final class RoutingContext
} }
initModel(); initModel();
} }
public void initModel() public void initModel()
{ {
pm.init( expctxWay, expctxNode, keyValues ); pm.init( expctxWay, expctxNode, keyValues );
@ -120,7 +121,7 @@ public final class RoutingContext
BExpressionContext expctxGlobal = expctxWay; // just one of them... BExpressionContext expctxGlobal = expctxWay; // just one of them...
setModel( expctxGlobal._modelClass ); setModel( expctxGlobal._modelClass );
downhillcostdiv = (int)expctxGlobal.getVariableValue( "downhillcost", 0.f ); downhillcostdiv = (int)expctxGlobal.getVariableValue( "downhillcost", 0.f );
downhillcutoff = (int)(expctxGlobal.getVariableValue( "downhillcutoff", 0.f )*10000); downhillcutoff = (int)(expctxGlobal.getVariableValue( "downhillcutoff", 0.f )*10000);
uphillcostdiv = (int)expctxGlobal.getVariableValue( "uphillcost", 0.f ); uphillcostdiv = (int)expctxGlobal.getVariableValue( "uphillcost", 0.f );
@ -129,6 +130,7 @@ public final class RoutingContext
if ( uphillcostdiv != 0 ) uphillcostdiv = 1000000/uphillcostdiv; if ( uphillcostdiv != 0 ) uphillcostdiv = 1000000/uphillcostdiv;
carMode = 0.f != expctxGlobal.getVariableValue( "validForCars", 0.f ); carMode = 0.f != expctxGlobal.getVariableValue( "validForCars", 0.f );
bikeMode = 0.f != expctxGlobal.getVariableValue( "validForBikes", 0.f ); bikeMode = 0.f != expctxGlobal.getVariableValue( "validForBikes", 0.f );
footMode = 0.f != expctxGlobal.getVariableValue( "validForFoot", 0.f );
// turn-restrictions used per default for car profiles // turn-restrictions used per default for car profiles
considerTurnRestrictions = 0.f != expctxGlobal.getVariableValue( "considerTurnRestrictions", carMode ? 1.f : 0.f ); considerTurnRestrictions = 0.f != expctxGlobal.getVariableValue( "considerTurnRestrictions", carMode ? 1.f : 0.f );
@ -170,6 +172,20 @@ public final class RoutingContext
} }
turnInstructionCatchingRange = expctxGlobal.getVariableValue( "turnInstructionCatchingRange", 40.f ); turnInstructionCatchingRange = expctxGlobal.getVariableValue( "turnInstructionCatchingRange", 40.f );
turnInstructionRoundabouts = expctxGlobal.getVariableValue( "turnInstructionRoundabouts", 1.f ) != 0.f; turnInstructionRoundabouts = expctxGlobal.getVariableValue( "turnInstructionRoundabouts", 1.f ) != 0.f;
// Speed computation model (for bikes)
if (bikeMode) {
// Mass of the biker + bike + luggages, in kg
bikeMass = expctxGlobal.getVariableValue( "bikeMass", 90.f );
// Max speed (before braking), in km/h in profile and m/s in code
maxSpeed = expctxGlobal.getVariableValue( "maxSpeed", 45.f ) / 3.6;
// Equivalent surface for wind, S * C_x, F = -1/2 * S * C_x * v^2 = - S_C_x * v^2
S_C_x = expctxGlobal.getVariableValue( "S_C_x", 0.5f * 0.45f );
// Default resistance of the road, F = - m * g * C_r (for good quality road)
defaultC_r = expctxGlobal.getVariableValue( "C_r", 0.01f );
// Constant power of the biker (in W)
bikerPower = expctxGlobal.getVariableValue( "bikerPower", 100.f );
}
} }
public List<OsmNodeNamed> nogopoints = null; public List<OsmNodeNamed> nogopoints = null;
@ -202,13 +218,20 @@ public final class RoutingContext
public boolean showspeed; public boolean showspeed;
public boolean inverseRouting; public boolean inverseRouting;
public OsmPrePath firstPrePath; public OsmPrePath firstPrePath;
public int turnInstructionMode; // 0=none, 1=auto, 2=locus, 3=osmand, 4=comment-style, 5=gpsies-style public int turnInstructionMode; // 0=none, 1=auto, 2=locus, 3=osmand, 4=comment-style, 5=gpsies-style
public double turnInstructionCatchingRange; public double turnInstructionCatchingRange;
public boolean turnInstructionRoundabouts; public boolean turnInstructionRoundabouts;
// Speed computation model (for bikes)
public double bikeMass;
public double maxSpeed;
public double S_C_x;
public double defaultC_r;
public double bikerPower;
public static void prepareNogoPoints( List<OsmNodeNamed> nogos ) public static void prepareNogoPoints( List<OsmNodeNamed> nogos )
{ {
for( OsmNodeNamed nogo : nogos ) for( OsmNodeNamed nogo : nogos )
@ -242,7 +265,7 @@ public final class RoutingContext
{ {
if ( wp.calcDistance( nogo ) < radiusInMeter if ( wp.calcDistance( nogo ) < radiusInMeter
&& (!(nogo instanceof OsmNogoPolygon) && (!(nogo instanceof OsmNogoPolygon)
|| (((OsmNogoPolygon)nogo).isClosed || (((OsmNogoPolygon)nogo).isClosed
? ((OsmNogoPolygon)nogo).isWithin(wp.ilon, wp.ilat) ? ((OsmNogoPolygon)nogo).isWithin(wp.ilon, wp.ilat)
: ((OsmNogoPolygon)nogo).isOnPolyline(wp.ilon, wp.ilat)))) : ((OsmNogoPolygon)nogo).isOnPolyline(wp.ilon, wp.ilat))))
{ {
@ -268,7 +291,7 @@ public final class RoutingContext
} }
return cs; return cs;
} }
public void setWaypoint( OsmNodeNamed wp, boolean endpoint ) public void setWaypoint( OsmNodeNamed wp, boolean endpoint )
{ {
keepnogopoints = nogopoints; keepnogopoints = nogopoints;
@ -438,9 +461,9 @@ public final class RoutingContext
double x4 = x2*x2; double x4 = x2*x2;
return x * ( 57.4539 + 9.57565 * x2 + 4.30904 * x4 + 2.56491 * x2*x4 ); return x * ( 57.4539 + 9.57565 * x2 + 4.30904 * x4 + 2.56491 * x2*x4 );
} }
public OsmPathModel pm; public OsmPathModel pm;
public OsmPrePath createPrePath( OsmPath origin, OsmLink link ) public OsmPrePath createPrePath( OsmPath origin, OsmLink link )
{ {
OsmPrePath p = pm.createPrePath(); OsmPrePath p = pm.createPrePath();
@ -464,5 +487,5 @@ public final class RoutingContext
p.init( origin, link, refTrack, detailMode, this ); p.init( origin, link, refTrack, detailMode, this );
return p; return p;
} }
} }

View file

@ -18,12 +18,18 @@ final class StdPath extends OsmPath
private int ehbd; // in micrometer private int ehbd; // in micrometer
private int ehbu; // in micrometer private int ehbu; // in micrometer
StdPath() {
super();
computeTime = true;
}
@Override @Override
public void init( OsmPath orig ) public void init( OsmPath orig )
{ {
StdPath origin = (StdPath)orig; StdPath origin = (StdPath)orig;
this.ehbd = origin.ehbd; this.ehbd = origin.ehbd;
this.ehbu = origin.ehbu; this.ehbu = origin.ehbu;
this.totalTime = origin.totalTime;
} }
@Override @Override
@ -31,6 +37,7 @@ final class StdPath extends OsmPath
{ {
ehbd = 0; ehbd = 0;
ehbu = 0; ehbu = 0;
totalTime = 0.;
} }
@Override @Override
@ -139,7 +146,7 @@ final class StdPath extends OsmPath
} }
sectionCost += dist * costfactor + 0.5f; sectionCost += dist * costfactor + 0.5f;
return sectionCost; return sectionCost;
} }
@ -589,8 +596,13 @@ final class StdPath extends OsmPath
int delta = p.ehbu - ehbu; int delta = p.ehbu - ehbu;
if ( delta > 0 ) c += delta/rc.uphillcostdiv; if ( delta > 0 ) c += delta/rc.uphillcostdiv;
} }
return cost > c; return cost > c;
} }
@Override
public double getTotalTime()
{
return totalTime;
}
} }