Set edge speed per time range

Hi,
I am working on a project whith GraphHopper and Hadoop. The idea is that I have in Hadoop a big volume of spatiotemporal data from millions of trips. I mainly have acces to the coordinates, the hour and the speed for each point. I would like to use this data to update the edge speed flag of every edge in GraphHopper to get more accurate travel time predictions. I am already able to update the speed of each edge using this code snipet:

EdgeIteratorState edge; CarFlagEncoder encoder; double value; edge.setFlags(encoder.setSpeed(edge.getFlags(), value));

However, what I ultimately would like to do is to set the speed for different time ranges. For example, set one speed value for 9:00 to 10:00, a different speed value for 10:00 to 11:00, etc. This for every edge in the graph, so that when I build a route, the graph will predict a travel time based on the time when the travel takes place.

So, is there a way to store in a single edge several speed values linked to a specific time range? How could I do this?

Thanks a lot in advance.
José

This is currently not possible. You’ll have to store this in a separate array or DataAccess (as an edgeId can be easily used as array index) and then use this in the Weighting. But this has relative high priority being implemented or better integrated soonish.

Thanks for your answer.
Could you please redirect me to any source of information on how to use the com.graphhopper.storage.DataAccess object and how to use it in the Weighting? I am a little bit lost right now…

Thanks again,
José

See e.g. the tests RAMIntDataAccessTest and DataAccessTest or just use an array.

Just to see if I get what you mean: I should create an array containing the different speed values per hour range for each edgeId, right? Also, how should I link each array to the edgeId?

For simplicity you can create one array per hour:

// create it via
speedsFor9am = new double[graphHopperStorage.getAllEdges().getMaxId()];

// access it via
speedsFor9am[edgeIterator.getEdge()] = 123;

Hi,

Thanks a lot for your answer. I see how to store the speed values in different arrays per hour. What I strugle to see is how the routing engine will pick the correct speed value for each edge depending on the hour. I guess I have to implement a class extending the Weighting class and store the hour arrays in it, but I don’t understand how this class works, and I don’t understand how to tell my graph to calculate the route using this new class.

I’m sorry this questions may be very basic, but I’m quite new using GraphHopper.
Thanks again,
Jose

For the moment, I have created a class implementing the Weighting interface:

import java.util.HashMap;

import org.joda.time.DateTime;

import com.graphhopper.GraphHopper;
import com.graphhopper.routing.util.FlagEncoder;
import com.graphhopper.routing.util.HintsMap;
import com.graphhopper.routing.util.Weighting;
import com.graphhopper.util.EdgeIteratorState;

public class HourlyWeighting implements Weighting{
	
	private HashMap<Integer, double[]> hourlySpeeds = new HashMap<Integer, double[]>();
	private GraphHopper hopper;
	private String name = "HourlyWeighting";
	private double maxVelocity = 130.0;

	public HourlyWeighting(GraphHopper hopper) {
		this.hopper = hopper;
		for (int i=0; i <= 23; i++) {
			hourlySpeeds.put(i, new double[hopper.getGraphHopperStorage().getAllEdges().getMaxId()]);
		}
		//A method to populate the arrays from a csv data goes here
	}
	
	public double getMinWeight(double distance) {
		return distance/maxVelocity;
	}

	public double calcWeight(EdgeIteratorState edgeState, boolean reverse, int prevOrNextEdgeId) {
		DateTime dt = new DateTime();
		return hourlySpeeds.get(dt.getHourOfDay())[edgeState.getEdge()];
	}

	public FlagEncoder getFlagEncoder() {
		return hopper.getEncodingManager().fetchEdgeEncoders().get(0);
	}

	public String getName() {
		return name;
	}

	public boolean matches(HintsMap map) {
		String weighting = map.getWeighting();
		String vehicle = map.getVehicle();
		return (name.equals(weighting) && ????.equals(vehicle));
	}

}

Now, what I don’t see is how to set this new HourlyWeighting weighting to my graph. Any help on this please?

Thanks,
José

Overload the createWeighting method in the GraphHopper class and e.g. use vehicle=car&weighting=custom_[hour] or something?

Hi,

Thanks for the answer. I have finally used Infinispan to store my hourly speed values in the form of a hour/edge_id matrix.
I have created a HourlyGraphHopper and a HourlyWeighting objects and the results are quite good.

Thanks for the help.
José

1 Like

Hi,

I am facing an issue while accessing edges from my hashmap. I have stored the speed of edges on the Hashmap for each hour like this:

for(int j = allEdgesIterator.getBaseNode(); j < hopper.getGraphHopperStorage().getEdges(); j++){
//Find and store edgeId’s speed as index of array.
}

Everytime while storing edgeIds in the array this loop runs from 0 to i.e. 20000 and speeds are stored.

calcWeight(EdgeIteratorState edgeState, boolean reverse, int prevOrNextEdgeId) {
//Find weight from here using edgeState.getEdge() of array index.
}

Problem: Now when I request for any route and then access the speed of edgeIds from array index for any hour from hashmap, this index is always greater than 20000(Last array index.)
Please Help.

Thanks.

The problem here might be the so called virtual edge. E.g. when a query comes in and is not directly on a junction (i.e. most of the routes) then a new virtual and temporary node is created plus its virtual edges connecting to the neighbor nodes. The node IDs of it are >= graphHopperStorage.getNodes and the IDs of the virtual edges are >= allEdgeIterator.length

You could try to get the “original” edge ID via:

if (edge instanceof VirtualEdgeIteratorState)
 return GHUtility.getEdgeFromEdgeKey(((VirtualEdgeIteratorState) edge).getOriginalEdgeKey());
else
 return edge.getEdge();