Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change speed unit from m/s*100 to mm/s in Edges #295

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/main/java/com/conveyal/r5/analyst/TravelTimeComputer.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public void write (OutputStream os) throws IOException {
sr.setOrigin(fromLat, fromLon);
sr.route();

int offstreetTravelSpeedMillimetersPerSecond = (int) (request.getSpeedForMode(directMode) * 1000);
int offstreetTravelSpeedMillimetersPerSecond = (int) (request.getSpeedForMode(directMode));

LinkedPointSet linkedDestinations = destinations.link(network.streetLayer, directMode);

Expand Down Expand Up @@ -99,7 +99,7 @@ public void write (OutputStream os) throws IOException {
sr.route();

// Get the travel times to all stops reached in the initial on-street search. Convert distances to speeds.
int offstreetTravelSpeedMillimetersPerSecond = (int) (request.getSpeedForMode(accessMode) * 1000);
int offstreetTravelSpeedMillimetersPerSecond = (int) (request.getSpeedForMode(accessMode));

// getReachedStops returns distances, not times, so convert to times in the loop below
TIntIntMap accessTimes = sr.getReachedStops();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -835,7 +835,7 @@ private static void run(TransportNetwork transportNetwork) {
get("debug/speeds", (request, response) -> {
response.header("Content-Type", "application/json");
Map<String, Object> content = new HashMap<>(2);
Map<Short, Integer> speedUsage = new HashMap<>();
Map<Integer, Integer> speedUsage = new HashMap<>();
MinMax minMax = new MinMax();
if (request.queryParams().size() < 4) {

Expand Down Expand Up @@ -1172,7 +1172,7 @@ private static GeoJsonFeature getEdgeFeature(boolean both, EdgeStore.Edge cursor
GeoJsonFeature feature = new GeoJsonFeature(geometry);
feature.addProperty("permission", cursor.getPermissionsAsString());
feature.addProperty("edge_id", cursor.getEdgeIndex());
feature.addProperty("speed_ms", cursor.getSpeed());
feature.addProperty("speed_mms", cursor.getSpeed());
feature.addProperty("osmid", cursor.getOSMID());
//Needed for filtering flags
for (EdgeStore.EdgeFlag flag: EdgeStore.EdgeFlag.values()) {
Expand All @@ -1184,25 +1184,25 @@ private static GeoJsonFeature getEdgeFeature(boolean both, EdgeStore.Edge cursor
return feature;
}

private static void updateSpeed(EdgeStore.Edge edge, Map<Short, Integer> speedUsage,
private static void updateSpeed(EdgeStore.Edge edge, Map<Integer, Integer> speedUsage,
MinMax minMax) {
Short currentEdgeSpeed = edge.getSpeed();
Integer currentEdgeSpeed = edge.getSpeed();
Integer currentValue = speedUsage.getOrDefault(currentEdgeSpeed, 0);
speedUsage.put(currentEdgeSpeed, currentValue+1);
minMax.updateMin(currentEdgeSpeed);
minMax.updateMax(currentEdgeSpeed);
}

private static class MinMax {
public short min = Short.MAX_VALUE;
public short max = Short.MIN_VALUE;
public int min = Integer.MAX_VALUE;
public int max = Integer.MIN_VALUE;

public void updateMin(Short currentEdgeSpeed) {
min = (short) Math.min(currentEdgeSpeed, min);
void updateMin(Integer currentEdgeSpeed) {
min = Math.min(currentEdgeSpeed, min);
}

public void updateMax(Short currentEdgeSpeed) {
max = (short) Math.max(currentEdgeSpeed, max);
void updateMax(Integer currentEdgeSpeed) {
max = Math.max(currentEdgeSpeed, max);
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/main/java/com/conveyal/r5/profile/ProfileRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -239,17 +239,17 @@ public ZonedDateTime getFromTimeDateZD() {
}

/**
* @return the speed at which the given mode will traverse street edges.
* @return the speed at which the given mode will traverse street edges in mm/s.
*/
@JsonIgnore
public float getSpeedForMode (StreetMode streetMode) {
switch (streetMode) {
case WALK:
return walkSpeed;
return walkSpeed*1000;
case BICYCLE:
return bikeSpeed;
return bikeSpeed*1000;
case CAR:
return carSpeed;
return carSpeed*1000;
default:
break;
}
Expand Down
33 changes: 21 additions & 12 deletions src/main/java/com/conveyal/r5/streets/EdgeStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public class EdgeStore implements Serializable {
* Saved speed is mostly the same as speed saved as m/s * 1000 it differs in second decimal place and is 0.024% smaller
* This way of saving speeds is 3.5% smaller then previous (saving 7 decimal places)
*/
public TShortList speeds;
public TIntList speeds;

/** The index of the origin vertex of each edge pair in the forward direction. One entry for each edge pair. */
public TIntList fromVertices;
Expand Down Expand Up @@ -175,7 +175,7 @@ public EdgeStore (VertexStore vertexStore, StreetLayer layer, int initialSize) {

// There are separate flags and speeds entries for the forward and backward edges in each pair.
flags = new TIntArrayList(initialSize);
speeds = new TShortArrayList(initialSize);
speeds = new TIntArrayList(initialSize);
// Vertex indices, geometries, and lengths are shared between pairs of forward and backward edges.
int initialEdgePairs = initialSize / 2;
fromVertices = new TIntArrayList(initialEdgePairs);
Expand Down Expand Up @@ -469,7 +469,11 @@ public void setFlags(Set<EdgeFlag> flagSet) {
}
}

public short getSpeed() {
/**
* @return the car speed on this edge in mm/s taking live traffic updates into account if requested (though that's not
* yet implemented)
*/
public int getSpeed() {
return speeds.get(edgeIndex);
}

Expand All @@ -478,14 +482,17 @@ public short getSpeed() {
* yet implemented)
*/
public float getCarSpeedMetersPerSecond() {
return (float) ((speeds.get(edgeIndex) / 100.));
return (float) ((speeds.get(edgeIndex) / 1000.));
}

public float getSpeedkmh() {
return (float) ((speeds.get(edgeIndex) / 100.) * 3.6);
return (float) ((speeds.get(edgeIndex) / 1000.) * 3.6);
}

public void setSpeed(short speed) {
/**
* @param speed Speed in mm/s
*/
public void setSpeed(int speed) {
speeds.set(edgeIndex, speed);
}

Expand Down Expand Up @@ -540,14 +547,16 @@ public boolean isForward () {
* If driving speed is based on max edge speed. (or from traffic if traffic is supported)
*
* Otherwise speed is based on wanted walking, cycling speed provided in ProfileRequest.
*
* Unit is mm/s
*/
public float calculateSpeed(ProfileRequest options, StreetMode traverseStreetMode) {
if (traverseStreetMode == null) {
// Do we really want to do this? Why not just let the NPE happen if the parameter is missing?
return Float.NaN;
} else if (traverseStreetMode == StreetMode.CAR) {
// TODO: apply speed based on traffic information if switched on in the request
return getCarSpeedMetersPerSecond();
return getSpeed();
}
return options.getSpeedForMode(traverseStreetMode);
}
Expand All @@ -564,8 +573,8 @@ public StreetRouter.State traverse (StreetRouter.State s0, StreetMode streetMode
}

StreetRouter.State s1 = new StreetRouter.State(vertex, edgeIndex, s0);
float speedms = calculateSpeed(req, streetMode);
float time = (float) (getLengthM() / speedms);
float speedmms = calculateSpeed(req, streetMode);
float time = getLengthMm() / speedmms;
float weight = 0;

if (!canTurnFrom(s0, s1, req.reverseSearch)) return null;
Expand Down Expand Up @@ -606,8 +615,8 @@ public StreetRouter.State traverse (StreetRouter.State s0, StreetMode streetMode

if (walking) {
//Recalculation of time and speed is needed if we are walking with bike
speedms = calculateSpeed(req, StreetMode.WALK)*0.9f;
time = (float) (getLengthM() / speedms);
speedmms = calculateSpeed(req, StreetMode.WALK)*0.9f;
time = getLengthMm() / speedmms;
}

//elevation costs
Expand Down Expand Up @@ -1073,7 +1082,7 @@ public EdgeStore extendOnlyCopy() {
copy.vertexStore = vertexStore.extendOnlyCopy();
copy.flags = new TIntAugmentedList(flags);
// This is a deep copy, we should do an extend-copy but need a new class for that. Can we just use ints?
copy.speeds = new TShortArrayList(speeds);
copy.speeds = new TIntArrayList(speeds);
// Vertex indices, geometries, and lengths are shared between pairs of forward and backward edges.
copy.fromVertices = new TIntAugmentedList(fromVertices);
copy.toVertices = new TIntAugmentedList(toVertices);
Expand Down
11 changes: 7 additions & 4 deletions src/main/java/com/conveyal/r5/streets/StreetLayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -971,8 +971,11 @@ private int getEdgeLengthMillimeters (List<Node> nodes) {
return (int)(lengthMeters * 1000);
}

private static short speedToShort(Float speed) {
return (short) Math.round(speed * 100);
/**
* Converts speed from m/s to mm/s and rounds it to integer
*/
private static int speedToMmPerS(Float speed) {
return (int) Math.round(speed * 1000);
}

/**
Expand Down Expand Up @@ -1009,8 +1012,8 @@ private void makeEdge(Way way, int beginIdx, int endIdx, Long osmID) {
}

// FIXME this encoded speed should probably never be exposed outside the edge object
short forwardSpeed = speedToShort(speedLabeler.getSpeedMS(way, false));
short backwardSpeed = speedToShort(speedLabeler.getSpeedMS(way, true));
int forwardSpeed = speedToMmPerS(speedLabeler.getSpeedMS(way, false));
int backwardSpeed = speedToMmPerS(speedLabeler.getSpeedMS(way, true));

RoadPermission roadPermission = permissions.getPermissions(way);

Expand Down
18 changes: 9 additions & 9 deletions src/main/java/com/conveyal/r5/streets/StreetRouter.java
Original file line number Diff line number Diff line change
Expand Up @@ -304,12 +304,12 @@ public boolean setOrigin (double lat, double lon) {
State startState1 = new State(split.vertex1, split.edge, streetMode);
EdgeStore.Edge edge = streetLayer.edgeStore.getCursor(split.edge);
// Uses weight based on distance from end vertices, and speed on edge which depends on transport mode
float speedMetersPerSecond = edge.calculateSpeed(profileRequest, streetMode);
startState1.weight = (int) ((split.distance1_mm / 1000) / speedMetersPerSecond);
float speedMiliMetersPerSecond = edge.calculateSpeed(profileRequest, streetMode);
startState1.weight = (int) (split.distance1_mm / speedMiliMetersPerSecond);
edge.advance();
// Speed can be different on opposite sides of the same street
speedMetersPerSecond = edge.calculateSpeed(profileRequest, streetMode);
startState0.weight = (int) ((split.distance0_mm / 1000) / speedMetersPerSecond);
speedMiliMetersPerSecond = edge.calculateSpeed(profileRequest, streetMode);
startState0.weight = (int) (split.distance0_mm / speedMiliMetersPerSecond);
// FIXME we're setting weight but not time and distance on these states above!

// FIXME Below is reversing the vertices, but then aren't the weights, times, distances wrong? Why are we even doing this?
Expand Down Expand Up @@ -433,10 +433,10 @@ public void route () {
double maxAbsLatRadians = Math.toRadians(VertexStore.fixedDegreesToFloating(maxAbsLatFixed));
millimetersPerUnitLonFixed = MM_PER_UNIT_LAT_FIXED * Math.cos(maxAbsLatRadians);
// FIXME account for speeds of individual street segments, not just speed in request
double maxSpeedMetersPerSecond = profileRequest.getSpeedForMode(streetMode);
double maxSpeedMilimetersPerSecond = profileRequest.getSpeedForMode(streetMode);
// Car speed is currently often unspecified in the request and defaults to zero.
if (maxSpeedMetersPerSecond == 0) maxSpeedMetersPerSecond = 36.11; // 130 km/h
maxSpeedSecondsPerMillimeter = 1 / (maxSpeedMetersPerSecond * 1000);
if (maxSpeedMilimetersPerSecond == 0) maxSpeedMilimetersPerSecond = 36.11*1000; // 130 km/h
maxSpeedSecondsPerMillimeter = 1 / maxSpeedMilimetersPerSecond;
}

if (distanceLimitMeters > 0) {
Expand Down Expand Up @@ -735,7 +735,7 @@ public State getState(Split split) {

// figure out the turn cost
int turnCost = this.turnCostCalculator.computeTurnCost(s.backEdge, split.edge, s.streetMode);
int traversalCost = (int) Math.round(split.distance0_mm / 1000d / e.calculateSpeed(profileRequest, s.streetMode));
int traversalCost = Math.round(split.distance0_mm / e.calculateSpeed(profileRequest, s.streetMode));

// TODO length of perpendicular
ret.incrementWeight(turnCost + traversalCost);
Expand Down Expand Up @@ -765,7 +765,7 @@ public State getState(Split split) {

// figure out the turn cost
int turnCost = this.turnCostCalculator.computeTurnCost(s.backEdge, split.edge + 1, s.streetMode);
int traversalCost = (int) Math.round(split.distance1_mm / 1000d / e.calculateSpeed(profileRequest, s.streetMode));
int traversalCost = Math.round(split.distance1_mm / e.calculateSpeed(profileRequest, s.streetMode));
ret.distance += split.distance1_mm;

// TODO length of perpendicular
Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/debug-plan/scripts/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ var otp_config = {
};
//Those are layers and name of properties in a layer if detail=true
var layers = {
streetEdges:["edge_id", "permission", "speed_ms", "flags", "osmid"],
streetEdges:["edge_id", "permission", "speed_mms", "flags", "osmid"],
permEdges:["name", "edge_id", "label", "osmid"],
turns:["edge_id", "permission", "speed_ms", "only", "edge", "via_edge_idx", "restrictionId", "osmid"]
turns:["edge_id", "permission", "speed_mms", "only", "edge", "via_edge_idx", "restrictionId", "osmid"]
};
var current_layer = "streetEdges";
var url = otp_config.hostname + '/' + otp_config.restService;
Expand Down
10 changes: 5 additions & 5 deletions src/main/resources/debug-plan/scripts/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ function getStyle(type) {
"line-color":speedColor(speed),
"line-width":2
},
"filter":["==", "speed_ms", parseInt(speed)]
"filter":["==", "speed_mms", parseInt(speed)]
};
style.layers.push(speed_layer);
});
Expand Down Expand Up @@ -263,12 +263,12 @@ function getStyle(type) {
current_type = type;
}

//Converts speed from m/s to kmh/mph
//Converts speed from mm/s to kmh/mph
// based on GUI settings
// And returnes it rounded to 2 decimal places
//and wanted unit
function showSpeed(speedms) {
var speed_ms = speedms/100;
function showSpeed(speedmms) {
var speed_ms = speedmms/1000;
var speed;
if (text.unit == "kmh") {
speed = speed_ms*3.6;
Expand All @@ -287,7 +287,7 @@ function fillPopup(feature, layer) {
for (var i=0; i < layer_info.length; i++) {
pop += layer_info[i].toUpperCase();
pop +=": ";
if (layer_info[i] == "speed_ms") {
if (layer_info[i] == "speed_mms") {
pop += showSpeed(prop[layer_info[i]]);
} else if (layer_info[i] == "osmid") {
pop += "<a target='_blank' href='https://osm.org/way/"+ prop[layer_info[i]]+"'>OSM W:" + prop[layer_info[i]]+"</a>";
Expand Down