added speed profile to json result
This commit is contained in:
parent
7547d5d820
commit
137d87c085
8 changed files with 137 additions and 21 deletions
|
@ -40,6 +40,7 @@ final class KinematicModel extends OsmPathModel
|
||||||
public double cost0; // minimum possible cost per meter
|
public double cost0; // minimum possible cost per meter
|
||||||
|
|
||||||
private int wayIdxMaxspeed;
|
private int wayIdxMaxspeed;
|
||||||
|
private int wayIdxMaxspeedExplicit;
|
||||||
private int wayIdxMinspeed;
|
private int wayIdxMinspeed;
|
||||||
|
|
||||||
private int nodeIdxMaxspeed;
|
private int nodeIdxMaxspeed;
|
||||||
|
@ -61,6 +62,7 @@ final class KinematicModel extends OsmPathModel
|
||||||
ctxWay = expctxWay;
|
ctxWay = expctxWay;
|
||||||
ctxNode = expctxNode;
|
ctxNode = expctxNode;
|
||||||
wayIdxMaxspeed = ctxWay.getOutputVariableIndex( "maxspeed", false );
|
wayIdxMaxspeed = ctxWay.getOutputVariableIndex( "maxspeed", false );
|
||||||
|
wayIdxMaxspeedExplicit = ctxWay.getOutputVariableIndex( "maxspeed_explicit", false );
|
||||||
wayIdxMinspeed = ctxWay.getOutputVariableIndex( "minspeed", false );
|
wayIdxMinspeed = ctxWay.getOutputVariableIndex( "minspeed", false );
|
||||||
nodeIdxMaxspeed = ctxNode.getOutputVariableIndex( "maxspeed", false );
|
nodeIdxMaxspeed = ctxNode.getOutputVariableIndex( "maxspeed", false );
|
||||||
initDone = true;
|
initDone = true;
|
||||||
|
@ -104,6 +106,11 @@ final class KinematicModel extends OsmPathModel
|
||||||
return ctxWay.getBuildInVariable( wayIdxMaxspeed ) / 3.6f;
|
return ctxWay.getBuildInVariable( wayIdxMaxspeed ) / 3.6f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float getWayMaxspeedExplicit()
|
||||||
|
{
|
||||||
|
return ctxWay.getBuildInVariable( wayIdxMaxspeedExplicit ) / 3.6f;
|
||||||
|
}
|
||||||
|
|
||||||
public float getWayMinspeed()
|
public float getWayMinspeed()
|
||||||
{
|
{
|
||||||
return ctxWay.getBuildInVariable( wayIdxMinspeed ) / 3.6f;
|
return ctxWay.getBuildInVariable( wayIdxMinspeed ) / 3.6f;
|
||||||
|
|
|
@ -76,6 +76,8 @@ final class KinematicPath extends OsmPath
|
||||||
|
|
||||||
if ( nsection == 0 ) // process slowdown by crossing geometry
|
if ( nsection == 0 ) // process slowdown by crossing geometry
|
||||||
{
|
{
|
||||||
|
double junctionspeed = 999.; // just high
|
||||||
|
|
||||||
int classifiermask = (int)rc.expctxWay.getClassifierMask();
|
int classifiermask = (int)rc.expctxWay.getClassifierMask();
|
||||||
|
|
||||||
// penalty for equal priority crossing
|
// penalty for equal priority crossing
|
||||||
|
@ -105,16 +107,27 @@ final class KinematicPath extends OsmPath
|
||||||
}
|
}
|
||||||
double residentialSpeed = 13.;
|
double residentialSpeed = 13.;
|
||||||
|
|
||||||
if ( hasLeftWay && turnspeed > km.leftWaySpeed ) turnspeed = km.leftWaySpeed;
|
if ( hasLeftWay && junctionspeed > km.leftWaySpeed ) junctionspeed = km.leftWaySpeed;
|
||||||
if ( hasRightWay && turnspeed > km.rightWaySpeed ) turnspeed = km.rightWaySpeed;
|
if ( hasRightWay && junctionspeed > km.rightWaySpeed ) junctionspeed = km.rightWaySpeed;
|
||||||
if ( hasResidential && turnspeed > residentialSpeed ) turnspeed = residentialSpeed;
|
if ( hasResidential && junctionspeed > residentialSpeed ) junctionspeed = residentialSpeed;
|
||||||
|
|
||||||
if ( (lastpriorityclassifier < 20) ^ (priorityclassifier < 20) )
|
if ( (lastpriorityclassifier < 20) ^ (priorityclassifier < 20) )
|
||||||
{
|
{
|
||||||
extraTime += 10.;
|
extraTime += 10.;
|
||||||
turnspeed = 0; // full stop for entering or leaving road network
|
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 = turnspeed > junctionspeed ? junctionspeed : turnspeed;
|
||||||
|
|
||||||
|
if ( message != null )
|
||||||
|
{
|
||||||
|
message.vnode0 = (int) ( junctionspeed * 3.6 + 0.5 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cutEkin( km.totalweight, turnspeed ); // apply turnspeed
|
cutEkin( km.totalweight, turnspeed ); // apply turnspeed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,6 +144,10 @@ final class KinematicPath extends OsmPath
|
||||||
if ( message != null )
|
if ( message != null )
|
||||||
{
|
{
|
||||||
message.costfactor = (float)(distanceCost/dist);
|
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;
|
cost += extraTime * km.pw / km.cost0;
|
||||||
|
@ -242,6 +259,8 @@ final class KinematicPath extends OsmPath
|
||||||
{
|
{
|
||||||
message.linknodecost += (int)initialcost;
|
message.linknodecost += (int)initialcost;
|
||||||
message.nodeKeyValues = rc.expctxNode.getKeyValueDescription( false, targetNode.nodeDescription );
|
message.nodeKeyValues = rc.expctxNode.getKeyValueDescription( false, targetNode.nodeDescription );
|
||||||
|
|
||||||
|
message.vnode1 = (int) ( km.getNodeMaxspeed() * 3.6 + 0.5 );
|
||||||
}
|
}
|
||||||
return initialcost;
|
return initialcost;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,14 @@ final class MessageData implements Cloneable
|
||||||
float time;
|
float time;
|
||||||
float energy;
|
float energy;
|
||||||
|
|
||||||
|
// speed profile
|
||||||
|
int vmaxExplicit = -1;
|
||||||
|
int vmax = -1;
|
||||||
|
int vmin = -1;
|
||||||
|
int vnode0 = 999;
|
||||||
|
int vnode1 = 999;
|
||||||
|
int extraTime = 0;
|
||||||
|
|
||||||
String toMessage()
|
String toMessage()
|
||||||
{
|
{
|
||||||
if ( wayKeyValues == null )
|
if ( wayKeyValues == null )
|
||||||
|
|
|
@ -345,7 +345,7 @@ abstract class OsmPath implements OsmLinkHolder
|
||||||
{
|
{
|
||||||
if ( rc.startDirectionValid )
|
if ( rc.startDirectionValid )
|
||||||
{
|
{
|
||||||
double dir = rc.startDirection.intValue() / CheapRulerSingleton.DEG_TO_RAD;
|
double dir = rc.startDirection.intValue() * CheapRulerSingleton.DEG_TO_RAD;
|
||||||
double[] lonlat2m = CheapRulerSingleton.getLonLatToMeterScales( (lon0 + lat1) >> 1 );
|
double[] lonlat2m = CheapRulerSingleton.getLonLatToMeterScales( (lon0 + lat1) >> 1 );
|
||||||
lon0 = lon1 - (int) ( 1000. * Math.sin( dir ) / lonlat2m[0] );
|
lon0 = lon1 - (int) ( 1000. * Math.sin( dir ) / lonlat2m[0] );
|
||||||
lat0 = lat1 - (int) ( 1000. * Math.cos( dir ) / lonlat2m[1] );
|
lat0 = lat1 - (int) ( 1000. * Math.cos( dir ) / lonlat2m[1] );
|
||||||
|
|
|
@ -53,6 +53,8 @@ public final class OsmTrack
|
||||||
|
|
||||||
private VoiceHintList voiceHints;
|
private VoiceHintList voiceHints;
|
||||||
|
|
||||||
|
private boolean sendSpeedProfile;
|
||||||
|
|
||||||
public String message = null;
|
public String message = null;
|
||||||
public ArrayList<String> messageList = null;
|
public ArrayList<String> messageList = null;
|
||||||
|
|
||||||
|
@ -146,6 +148,31 @@ public final class OsmTrack
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ArrayList<String> aggregateSpeedProfile()
|
||||||
|
{
|
||||||
|
ArrayList<String> res = new ArrayList<String>();
|
||||||
|
int vmax = -1;
|
||||||
|
int vmaxe = -1;
|
||||||
|
int vmin = -1;
|
||||||
|
int extraTime = 0;
|
||||||
|
for( int i = nodes.size()-1; i > 0; i-- )
|
||||||
|
{
|
||||||
|
OsmPathElement n = nodes.get(i);
|
||||||
|
MessageData m = n.message;
|
||||||
|
int vnode = getVNode( i );
|
||||||
|
if ( m != null && ( vmax != m.vmax || vmin != m.vmin || vmaxe != m.vmaxExplicit || vnode < m.vmax || extraTime != m.extraTime ) )
|
||||||
|
{
|
||||||
|
vmax = m.vmax;
|
||||||
|
vmin = m.vmin;
|
||||||
|
vmaxe = m.vmaxExplicit;
|
||||||
|
extraTime = m.extraTime;
|
||||||
|
res.add( i + "," + vmaxe + "," + vmax + "," + vmin + "," + vnode + "," + extraTime );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* writes the track in binary-format to a file
|
* writes the track in binary-format to a file
|
||||||
*
|
*
|
||||||
|
@ -324,6 +351,7 @@ public final class OsmTrack
|
||||||
energy += t.energy;
|
energy += t.energy;
|
||||||
|
|
||||||
showspeed |= t.showspeed;
|
showspeed |= t.showspeed;
|
||||||
|
sendSpeedProfile |= t.sendSpeedProfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int distance;
|
public int distance;
|
||||||
|
@ -563,24 +591,41 @@ public final class OsmTrack
|
||||||
sb.append( " \"total-time\": \"" ).append( getTotalSeconds() ).append( "\",\n" );
|
sb.append( " \"total-time\": \"" ).append( getTotalSeconds() ).append( "\",\n" );
|
||||||
sb.append( " \"total-energy\": \"" ).append( energy ).append( "\",\n" );
|
sb.append( " \"total-energy\": \"" ).append( energy ).append( "\",\n" );
|
||||||
sb.append( " \"cost\": \"" ).append( cost ).append( "\",\n" );
|
sb.append( " \"cost\": \"" ).append( cost ).append( "\",\n" );
|
||||||
sb.append( " \"voicehints\": [\n" );
|
if ( voiceHints != null && !voiceHints.list.isEmpty() )
|
||||||
for( VoiceHint hint: voiceHints.list )
|
|
||||||
{
|
{
|
||||||
sb.append( " [" ).append( hint.indexInTrack ).append( ',' ).append( hint.getCommand() ).append( ',' ).append( hint.getExitNumber() ).append( "],\n" );
|
sb.append( " \"voicehints\": [\n" );
|
||||||
|
for( VoiceHint hint: voiceHints.list )
|
||||||
|
{
|
||||||
|
sb.append( " [" ).append( hint.indexInTrack ).append( ',' ).append( hint.getCommand() ).append( ',' ).append( hint.getExitNumber() ).append( "],\n" );
|
||||||
|
}
|
||||||
|
sb.deleteCharAt( sb.lastIndexOf( "," ) );
|
||||||
|
sb.append( " ],\n" );
|
||||||
}
|
}
|
||||||
sb.deleteCharAt( sb.lastIndexOf( "," ) );
|
if ( sendSpeedProfile ) // true if vmax was send
|
||||||
sb.append( " ],\n" );
|
|
||||||
sb.append( " \"messages\": [\n" );
|
|
||||||
sb.append( " [\"" ).append( MESSAGES_HEADER.replaceAll( "\t", "\", \"" ) ).append( "\"],\n" );
|
|
||||||
for ( String m : aggregateMessages() )
|
|
||||||
{
|
{
|
||||||
sb.append( " [\"" ).append( m.replaceAll( "\t", "\", \"" ) ).append( "\"],\n" );
|
ArrayList<String> sp = aggregateSpeedProfile();
|
||||||
|
if ( sp.size() > 0 )
|
||||||
|
{
|
||||||
|
sb.append( " \"speedprofile\": [\n" );
|
||||||
|
for( int i=sp.size()-1; i>=0; i-- )
|
||||||
|
{
|
||||||
|
sb.append( " [" ).append( sp.get(i) ).append( i> 0 ? "],\n" : "]\n" );
|
||||||
|
}
|
||||||
|
sb.append( " ]\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // ... otherwise traditional message list
|
||||||
|
{
|
||||||
|
sb.append( " \"messages\": [\n" );
|
||||||
|
sb.append( " [\"" ).append( MESSAGES_HEADER.replaceAll( "\t", "\", \"" ) ).append( "\"],\n" );
|
||||||
|
for ( String m : aggregateMessages() )
|
||||||
|
{
|
||||||
|
sb.append( " [\"" ).append( m.replaceAll( "\t", "\", \"" ) ).append( "\"],\n" );
|
||||||
|
}
|
||||||
|
sb.deleteCharAt( sb.lastIndexOf( "," ) );
|
||||||
|
sb.append( " ]\n" );
|
||||||
}
|
}
|
||||||
sb.deleteCharAt( sb.lastIndexOf( "," ) );
|
|
||||||
sb.append( " ]\n" );
|
|
||||||
|
|
||||||
sb.append( " },\n" );
|
sb.append( " },\n" );
|
||||||
|
|
||||||
if ( iternity != null )
|
if ( iternity != null )
|
||||||
{
|
{
|
||||||
sb.append( " \"iternity\": [\n" );
|
sb.append( " \"iternity\": [\n" );
|
||||||
|
@ -628,6 +673,15 @@ public final class OsmTrack
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getVNode( int i )
|
||||||
|
{
|
||||||
|
MessageData m1 = i+1 < nodes.size() ? nodes.get(i+1).message : null;
|
||||||
|
MessageData m0 = i < nodes.size() ? nodes.get(i ).message : null;
|
||||||
|
int vnode0 = m1 == null ? 999 : m1.vnode0;
|
||||||
|
int vnode1 = m0 == null ? 999 : m0.vnode1;
|
||||||
|
return vnode0 < vnode1 ? vnode0 : vnode1;
|
||||||
|
}
|
||||||
|
|
||||||
private int getTotalSeconds()
|
private int getTotalSeconds()
|
||||||
{
|
{
|
||||||
float s = nodes.size() < 2 ? 0 : nodes.get( nodes.size()-1 ).getTime() - nodes.get( 0 ).getTime();
|
float s = nodes.size() < 2 ? 0 : nodes.get( nodes.size()-1 ).getTime() - nodes.get( 0 ).getTime();
|
||||||
|
@ -755,6 +809,11 @@ public final class OsmTrack
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void prepareSpeedProfile( RoutingContext rc )
|
||||||
|
{
|
||||||
|
sendSpeedProfile = rc.keyValues != null && rc.keyValues.containsKey( "vmax" );
|
||||||
|
}
|
||||||
|
|
||||||
public void processVoiceHints( RoutingContext rc )
|
public void processVoiceHints( RoutingContext rc )
|
||||||
{
|
{
|
||||||
voiceHints = new VoiceHintList();
|
voiceHints = new VoiceHintList();
|
||||||
|
|
|
@ -192,6 +192,7 @@ public final class RoutingContext
|
||||||
|
|
||||||
public Integer startDirection;
|
public Integer startDirection;
|
||||||
public boolean startDirectionValid;
|
public boolean startDirectionValid;
|
||||||
|
public boolean forceUseStartDirection;
|
||||||
|
|
||||||
private double cosangle;
|
private double cosangle;
|
||||||
public double nogoCost = 0.;
|
public double nogoCost = 0.;
|
||||||
|
|
|
@ -808,7 +808,9 @@ public class RoutingEngine extends Thread
|
||||||
|
|
||||||
if ( start1 == null || start2 == null ) return null;
|
if ( start1 == null || start2 == null ) return null;
|
||||||
|
|
||||||
if ( routingContext.startDirectionValid = ( fastPartialRecalc && routingContext.startDirection != null && !routingContext.inverseDirection ) )
|
routingContext.startDirectionValid = routingContext.forceUseStartDirection || fastPartialRecalc;
|
||||||
|
routingContext.startDirectionValid &= routingContext.startDirection != null && !routingContext.inverseDirection;
|
||||||
|
if ( routingContext.startDirectionValid )
|
||||||
{
|
{
|
||||||
logInfo( "using start direction " + routingContext.startDirection );
|
logInfo( "using start direction " + routingContext.startDirection );
|
||||||
}
|
}
|
||||||
|
@ -1221,6 +1223,7 @@ public class RoutingEngine extends Thread
|
||||||
{
|
{
|
||||||
track.copyDetours( guideTrack );
|
track.copyDetours( guideTrack );
|
||||||
track.processVoiceHints( routingContext );
|
track.processVoiceHints( routingContext );
|
||||||
|
track.prepareSpeedProfile( routingContext );
|
||||||
}
|
}
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,7 +188,26 @@ public class RouteServer extends Thread
|
||||||
{
|
{
|
||||||
NearRecentWps.add( wplist );
|
NearRecentWps.add( wplist );
|
||||||
}
|
}
|
||||||
|
for( Map.Entry<String,String> e : params.entrySet() )
|
||||||
|
{
|
||||||
|
if ( "timode".equals( e.getKey() ) )
|
||||||
|
{
|
||||||
|
rc.turnInstructionMode = Integer.parseInt( e.getValue() );
|
||||||
|
}
|
||||||
|
else if ( "heading".equals( e.getKey() ) )
|
||||||
|
{
|
||||||
|
rc.startDirection = Integer.valueOf( Integer.parseInt( e.getValue() ) );
|
||||||
|
rc.forceUseStartDirection = true;
|
||||||
|
}
|
||||||
|
else if ( e.getKey().startsWith( "profile:" ) )
|
||||||
|
{
|
||||||
|
if ( rc.keyValues == null )
|
||||||
|
{
|
||||||
|
rc.keyValues = new HashMap<String,String>();
|
||||||
|
}
|
||||||
|
rc.keyValues.put( e.getKey().substring( 8 ), e.getValue() );
|
||||||
|
}
|
||||||
|
}
|
||||||
cr = new RoutingEngine( null, null, serviceContext.segmentDir, wplist, rc );
|
cr = new RoutingEngine( null, null, serviceContext.segmentDir, wplist, rc );
|
||||||
cr.quite = true;
|
cr.quite = true;
|
||||||
cr.doRun( maxRunningTime );
|
cr.doRun( maxRunningTime );
|
||||||
|
|
Loading…
Reference in a new issue