Quantcast
Channel: Java – Karussell
Viewing all 53 articles
Browse latest View live

Languator: Language Detection for Local Queries

$
0
0

When you have an address lookup service like photon you need language detection for the short local queries like “Berlin Alexanderplatz” to e.g. apply a specific analysis chain. Of course German language is rather simple, but detecting if it is French or Italian etc is much more complex.

I tried the language-detection from google code. And although it has high precision for normal text, it is relative slow (creating the profile and querying) and not specific to local queries although short generic queries should work (e.g. Twitter data). Another problem is the complex and inflexible Java API as it uses lots of statics etc. E.g. the size of the n-grams is not configurable.

So I hacked together a new language detection called languator in Java specific for short local queries and fed it with OpenStreetMap data. E.g. I used the germany.pbf to create the German language profile and france.pbf for the French profile and so on. If you keep in mind that you have lots of foreign names for POI and street in every country the following error values are okayish and better than what I found from other tools:

English: 22.9%, German: 7%, French: 20%, Italian: 18.8%

Another good thing is that you can feed languator with these 4 countries in 20 minutes and create millions of queries from those countries which takes ~10 minutes, which is at least 2 times faster than the google code tool.

I invite you to beat my numbers: fork and have fun!


Filed under: Algorithm, Java, photon

Digitalizing GPX Points or How to Track Vehicles With GraphHopper

$
0
0

Recently I was asked again if I know a method, or even better a tool, which makes GPX points more align to the existing streets in OpenStreetMap. E.g. currently in Mapilarry all recorded streets are not really smooth and digitalized if you look at them in detail. GraphHopper cannot do this out of the box but provides a toolchain which will make this digitalization easier.

Map Matching

The necessary process before an import would be Map Matching. Quoting (my own words ;)) from Wikipedia:

Map matching is the process of associating a sorted list of user or vehicle positions to the road network on a digital map. The main purposes are to track vehicles, analyze traffic flow and finding the start point of the driving directions.

I have implemented this for a client some months ago with the help of GraphHopper but this code is not yet open. Instead I’m explaining in this blog post the simple steps, which should guide people to create something like that. This is not an invention by me, other papers suggesting a similar technique. But maybe we will finally end up with something open, preferable under a permissive license like GraphHopper itself. Also we should use some open testing data like the recently released taxi routes additionally to the normal unit tests.

Some wordings are necessary before we go deeper:

  • A GPS point is a tuple or object which contains latitude, longitude (, elevation) at which position it was recorded.
  • A GPX point is a tuple or object which contains latitude, longitude (, elevation) and the timestamp at which it was recorded. And a GPX list ist a list of GPX points.
  • In the digital world of maps we need a data structure to handle the road network. This data structure is a graph where the junctions from real world are nodes and the streets between them are the edges.

The question is also why would we need a routing engine at all?

Because:

  • firstly you don’t need to write the import process of OpenStreetMap and the closest edge lookup and probably some other tools necessary for map matching and
  • secondly the routing process will fill gaps between larger distances of two GPX points, and will be able to guess those gaps depending on the vehicle and
  • thirdly using a routing engine will make the outcome more realistic, e.g. avoiding going left and then returning the identical street to go further in the straight direction.
  • Lastly with GraphHopper you’ll be easily able to provide such a procedure even for the world wide case as it stores everything very compact and can be used in-memory or on-disc.

We start with an example:

example1a

All maps are from Lyrk and data is from OpenStreetMap contributors

In the left map you see the street parts highlighted where only the edges closest to the GPX points are selected. Whereas in the right map the most probable way was taken via a routing engine like GraphHopper.

The simple algorithm

The results for the map on the left side are easy to get, see the gist for example 1. For the map on the right side can try the following procedure explained in pseudocode here or see example 2 as gist for a more complete one:

  1. Find 3 closest edges per GPX point
  2. Associate every edge with a weighting, which is the distance from the edge to the point. The larger the distance the smaller is the probability that the best path goes through it.
  3. Find the best path from the first GPX point to the last, but take into account the weighting and therefor the distance to the GPX points
  4. As a post-processing step you need to assign the GPX points to the resulting path, you can do so via the edge ids and to find the coordinates you can either use path.calcPoints or the lower level API ala edgeState.fetchWayGeometry.

This simple algorithm should work in the most cases and is very fast

The enhancements

There are two limitations of this simple algorithm:

  • If there are loops in the GPX list, then the Dijkstra from step 3 will throw data away
  • and it will happen that another route than the route marked with GPX points is taken. E.g. in the case if the GPX signal is not that frequent and the edge of one point is rather short, which means it will have a small influence on the overall weighting of the taken route.

The following improvements are possible

  • You could do a simple workaround and cut the incoming GPX list when you detect a loop and feed those GPX-list-parts to the algorithm.
  • Or find the best route not from start to end but ‘step by step’. For example from pointX to pointX+4, then pointX+4 to pointX+8 and so on, where you need to merge the results. To avoid suboptimal paths at the intersection (here pointX+4) you’ll need to ‘overlap’ the routes. So you will need to calculate the routes for pointX to pointX+4, then pointX+3 to pointX+7, …. instead. Merging will be more complex probably.
  • A more complex solution could be to maintain a list of e.g. 3 alternative end-results. As you already get 3 edge candidates for every GPX point you can then try to find all routes between them. You could think that this will slow down the search a lot but with GraphHopper you can tweak e.g. the Dijkstra or DijkstraOneToMany algorithm to do this in an efficient manner. E.g. if you want to get the best result but you want to search from multiple destinations you can do:
    DijkstraBidirectionRef dijkstra = new DijkstraBidirectionRef(hopper.getGraph(), flagEncoder, weighting);
    dijkstra.initFrom(nodeFrom, distanceToPossibility1); dijkstra.initFrom(node, distanceToPossibility2); …
    dijkstra.initTo(nodeTo, distanceToEndPossibility1); dijkstra.initTo(nodeTo, distanceToEndPossibility2); …

There are lots of other problems which you’ll encounter, that is the ugly real life with GPS signal errors, tunnels and so on. One example problem is if you are tracking e.g. a truck waiting in front of traffic lights in a one way street. You’ll see several nearly identical GPX points but as they have an error associated they won’t be identical and it could happen that they go ‘backwards’ in the one-way which will result in an extra loop if use the ‘step-by-step’ variant of the shortest path calculation:

example2

Let me know if you come up with something and/or have improved my code sketches! Have fun!


Filed under: Algorithm, GraphHopper, Java

The Flexibility of GraphHopper

$
0
0

I often hear some misconceptions about the flexibility of GraphHopper. In this post I speak about GraphHopper core.

Power Mode

GraphHopper is designed to be fast and flexible. For example you can route through entire Germany in about 1 second on average without any speed-up method, I’ll call this ‘power mode’. You have to keep in mind that this involves traversing millions of nodes in the road network. In this mode you have all possibilities and advantages like on-demand profiles, small base graph, support for multiple vehicles and so on. A naive implementation for OpenStreetMap data probably won’t reach this query speed, even if coded in C++. Additionally we fight with the memory waste and garbage collection in Java.

Speed up Mode

The main disadvantage for the power mode is that long queries will need lots of RAM, which is also not very handy on mobile devices. So you’ll have to limit the length of the route, increase the heuristical nature of the algorithm OR which is our default mode: switch to the speed up mode which uses a special algorithm called contraction hierarchies. The speed up mode comes with disadvantes e.g. only one query profile is possible or a bigger base graph. But it dramatically reduces the necessary RAM per query and as a nice side effect makes the query 50-500 times faster, depending on the length of the route. These are the reasons that the default mode for GraphHopper is the speed up mode. (And our Routing API is provided only in this speed up mode.)

With GraphHopper switching between modes is just a configuration change (chShortcuts=fastest or chShortcuts=no) and our architecture was build with this in mind and is open for new and completely different speed-up algorithms. The benefit of this simplicity is that you can play around and tune the routing of one or more vehicles with various options in the power mode, and then if you need performance or want to use it on mobile devices you can switch to the speed up mode.


Filed under: GraphHopper, Java

GraphHopper now also Available for Offline Routing on iOS

$
0
0

Today we announce the first availability of GraphHopper for iOS. It is still in an experimental shape but we would like to engage people to play with it and report issues. Go directly to the git repository and continue reading.

With GraphHopper we are in the process of building a fast and open source alternative to existing routing solutions. We provide a world wide instance for car routing, biking and walking called GraphHopper Maps. Where you can see the routing engine GraphHopper in action, combined with map tiles and address search served from other software. As GraphHopper is written in Java we already made routing possible on several platforms like Linux, Windows, Mac OS X, Raspberry Pi, Android and even offline in the Browser. But still one major platform – iOS – was missing and we thought about ways to make this possible.

RoboVM?

The most simple solution to port a Java project these days is RoboVM. RoboVM makes a complete Android app running on iOS. Several users made their none-trivial games working with the help of RoboVM and so it should be also relative easy for an app which includes GraphHopper to be used on iOS too.

J2OBJC!

But we also wanted to have the possibility that a native iOS app can use GraphHopper as a library. And according to my investigations this is currently relative hard to achieve with RoboVM. So we decided to use the conversion tool j2objc which creates Objective-C code from Java code. The first running demo on an iPhone was made by Tobias which was a huge step in the right direction (pun intended) and really nice work! It showed the first time that it was possible at all and the dream of platform independence nearly came true. Still there were several glitches in the setup which I wanted to avoid in the first release. Tobias did not found enough time for this so I was seaking help in the GraphHopper community and I got in touch with Calin who recently had enough time and was polishing like crazy. Where ‘polishing’ means creating workarounds for j2objc bugs and using good old make to avoid Xcode limitations, telling me to fix things directly in GraphHopper, preparing a nice demo, finding bugs in other tools and the usual coder safari.

Success!

At the end he was able to produce the necessary scripts and adaptations to create a static library via j2objc and a simple-to-setup demo. Only very few so called compatibility classes had to be written in Java but Calin made it possible to completely avoid custom Objective-C code, even for the more advanced things like memory mapping. With that we can almost always automatically create the updated version out of ‘GraphHopper Java’. And GraphHopper on iOS is fast, for example a route through entire Germany takes only about 1sec on iPhone 6!

We again ask for you help and feedback!

And thanks again to Tobias & Calin!


Filed under: GraphHopper, iOS, Java

GraphHopper Directions API Going Private Beta

$
0
0

Today we are proud to announce that our Directions API goes into private beta. Contact us and take part to get an API key and try our latest features.

The GraphHopper Directions API includes

  • The Routing API, a fast web service to calculate world wide routes for walking, biking and car.
  • The Matrix API, based on the Routing API you can calculate so called distance matrices more efficient.
  • The Geocoding API, a world wide address search. Still under heavy development and not yet production grade although with good results in several European countries.
  • Daily OpenStreetMap updates
  • A mature service based on the open source routing engine GraphHopper. Read more about GraphHopper at opensource.com

See the Routing and Geocoding API in action at GraphHopper Maps!


Filed under: GraphHopper, Java

The Builder Pattern in Java With the Least Code Possible

$
0
0

Immutable objects are important to make your code more robust, especially in days of more parallelization. A builder pattern is used when some of the variables of an immutable class are required and some are optional. But this leads to a massive constructor explosion, at least in Java. Today I think I found an improved builder pattern which could be used with no attribute duplication in the builder class and no separate private constructor in the domain class.

Usual Constructors

Here is a normal immutable class with the various necessary constructors for only one optional field ‘age':

public class Person {
  private final String name; // required
  private final int age;     // optional

  public Person(String name, int age) {
     this.name = name;
     this.age = age;
  }
  public Person(String name) {
     this.name = name;
  }
  public Person(int age) {
     this.age = age;
  }

  public String getName() {
     return this.name;
  }
  public int getAge() {
     return age;
  }
}

Builder Pattern 1.0

The builder pattern removes the need of various constructor combinations:

public class Person {
  private final String name; // required
  private final int age;     // optional
  private Person(PersonBuilder pb) {
     this.age = pb.age;
     this.name = pb.name;
  }

  public String getName() {
     return this.name;
  }
  public int getAge() {
     return age;
  }
}

public class PersonBuilder {
  private String name;
  private int age;

  public PersonBuilder name(String name) {
     this.name = name;
     return this;
  }
  public PersonBuilder age(int age) {
     this.age = age;
     return this;
  }

  public Person create() {
     return new Person(this);
  }
}

The usage is:

Person p = new PersonBuilder().
   name("testing").
   age(20).
   create();

Builder Pattern 2.0

Now my builder pattern with less overhead. Of course in real world examples you won’t have only one optional field making the savings more obvious. The Builder Pattern 2.0 uses a static embedded subclass for the builder and still uses (package) protected fields. As you can see this solution is only ~5 lines more than the original immutable object without the constructors as it just moves the setters into a separate class:

public class Person {
  String name; // required
  int age;     // optional

  public String getName() {
     return this.name;
  }
  public int getAge() {
     return age;
  }

  public static class BEGIN extends Person {
    public BEGIN name(String name) {
      this.name = name;
      return this;
    }
    public BEGIN age(int age) {
      this.age = age;
      return this;
    }

    public Person END() {
      return this;
    }
  } // end of builder class
} // end of domain class

The usage is similar to the original builder pattern:

Person p = new Person.BEGIN().
   name("testing").
   age(20).
   END();

Keep in mind that this solution has the ‘drawback’ of no unnecessary object creation involved like builder pattern 1.0. And therefor the END method is not thread-safe unlike the create method. (You can fix that via this.clone() within END, not sure if you like that). Also I think for those cases you probably need more something like a factory. As noted in the comments the builder class START should be renamed to Builder and then even better create a public static method ala ‘Builder Start() { return new Builder(); }’ where you then can avoid the ‘new’ when using it.

Improvement: Builder Pattern 2.1

After the comments and having this implemented in production I observed drawbacks. E.g. that you don’t have to call the END method at all as the subclass is also accepted. And that you could theoretically just downcast a Person object to its builder and change the variables again. The simplest solution is to use composition instead of inheritance like we do with our AlgorithmOptions object at GraphHopper, this way we can also use private fields again.

Conclusion

This new builder pattern is suited if a method has several arguments with some of them optional. You can move these arguments into a separate class and use this pattern to avoid code duplication like I’ll probably do for some classes in GraphHopper. For everyone in love with magic (unlike me) they can also have a look into the project lombok as noted in the comments. Still the best thing would be to have something like this directly in Java and being able to write:

Person p = new Person(name="testing", age=20);

Filed under: Java

Improved Address Autocompletion on GraphHopper Maps

Releasing GraphHopper 0.4 and the GraphHopper Directions API

$
0
0

Today we are proud to release version 0.4 of our open source road routing engine GraphHopper. Try it out on GraphHopper Maps:

gh-0.4-screenshot

We’ve taken several months for that release, but not without a reason as the GraphHopper Directions API for business was in the works and is also released today! The Directions API is a hosted GraphHopper routing service for world wide usage, including up-to-date software and OpenStreetMap data. It also offers features not found in GraphHopper like address search (aka Geocoding) and the Route Matrix API. Sign up for free and give us feedback!

A big thanks for that 0.4 release goes to all of our contributors! This release also includes features sponsored by Geofabrik and Talent Systems - thanks a lot! Read here to see how to become a sponsor or how to benefit from our GraphHopper knowledge.

Now these are the highlights of GraphHopper 0.4:

Map Matching aka ‘Snap to Road’

There is now also a map matching component based on GraphHopper and released under the Apache License 2.0. This tool can be helpful if you need to track vehicles and import their GPX tracks which is helpful to “snap them to road” like e.g. allryder is using it to optimize urban transport data or attach instructions to GPX files automatically.

Read more about it here or at wikipedia.

Now have fun with GraphHopper and expect more exciting news!


Filed under: GraphHopper, Java

Integrate traffic data into your route planner

$
0
0

There are several companies having its own traffic data e.g. those companies having an own fleet or fetching it from an external source. Often on the GraphHopper mailing list people ask how they can integrate this into GraphHopper and until now there was only descriptive information but no code example. This post will change this, where I’ve created a little demo project at github for this task.

The demo is easy to use and provides a simple web service where you can POST your own JSON data influencing the routing. If you look at the Readme there are only three steps involved:

  • Start the route planner server with the area of your choice:
    ./td.sh datasource=your-osm-file.pbf
  • Visit http://localhost:8989 to try the routing
  • Now feed some data and try routing again:
    curl -H "Content-Type: application/json" --data @traffic.json http://localhost:8989/datafeed
    

The simulated traffic jam is marked red. The routing therefore tries to avoid it.

The necessary code is very minimal: just take the double value from JSON and use it as speed for the identified street:

edge.setFlags(carEncoder.setSpeed(edge.getFlags(), value));

A street is a so called ‘edge’ in GraphHopper, read more about internals e.g. in this presentation or in the official documentation. But how to find this GraphHopper edge from the coordinates (list of latitude,longitude)? Currently we just take the very first coordinate of the provided points list in the JSON:

Point point = entry.getPoints().get(0);
QueryResult qr = locationIndex.findClosest(point.lat, point.lon, EdgeFilter.ALL_EDGES);
EdgeIteratorState edge = graph.getEdgeProps(qr.getClosestEdge().getEdge(), Integer.MIN_VALUE);

But in reality this can get more complex and could be improved by using our map matching component. So we just hope here no other edge can be mixed up with a close but completely different edge. Such problems are possible if you get the data from external none-OpenStreetMap data sources or from vehicles on the road without a high precision coordinate information. Other important points on the TODO-list for this demo are that the routing should be locked while updating the graph and that stopping the server should flush the graph to make the newly received data persistent.

Nevertheless this shows nicely how easy it is to feed GraphHopper with your own data where the possibilities are endlessly to e.g. block complete roads or prefer roads for routing and more. Let us know about your use case!


Filed under: Algorithm, GraphHopper, Java

Visualize and Handle Traffic Information with GraphHopper in Real-time for Cologne (Germany, Köln)

$
0
0

As our Directions API currently does not include traffic data we still show you that it is possible to integrate traffic data into GraphHopper if you have the data. A few days ago I’ve blogged about a simple way to feed GraphHopper with generic traffic data from elsewhere. Today we look into one specific example: Cologne.

ghmaps-with-traffic

This German city has a nice open data community and an open data portal. There I found the traffic data and it is noted that the update is done every 5-10 minutes so we have rough real time traffic information. For other open data or other cities have a look into codefor.de

The source repository for the necessary changes is also at github. The most important change was to visualize the traffic information directly in the browser, this helps a lot when debugging things – still lots of room for you to improve it. Using leaflet.canvas is a bit complex as we would need to separate the traffic information into the tiles structure. Instead I’m using the big canvas solution from CartoDB making everything really simple.

Three further simple steps are necessary when extending the old example:

  • Fetch data periodically
  • Parse and interpret the data correctly
  • Locking when writing the data and locking when routing

Fetching the data and parsing it is a simple procedure done within DataUpdater.fetch. Also surrounding the data feeding method with a write-lock is easy:

public void feed(RoadData data) {
    writeLock.lock();
    try {
        lockedFeed(data);
    } finally {
        writeLock.unlock();
    }
}

And finally we need to surround every route request with a read-lock:

GraphHopper tmp = new GraphHopper() {
    @Override public GHResponse route(GHRequest request) {
        lock.readLock().lock();
        try {
            return super.route(request);
        } finally {
            lock.readLock().unlock();
        }
    }
}.forServer().init(args);

Now we just need to fetch the road network for this area and start the server:

  1. wget http://download.geofabrik.de/europe/germany/nordrhein-westfalen/koeln-regbez-latest.osm.pbf
  2. ./td.sh datasource=koeln-regbez-latest.osm.pbf
  3. Visit http://localhost:8989 to try the routing and see the traffic infos

And you’ll see regularly updates of the speed where routing should be influenced, at least the duration for the route:

Speed change at 50.94432295851602, 7.057916495227443. Old: 30.0, new:5.0
Speed change at 50.944496505815735, 7.057842025768907. Old: 60.0, new:45.0
Speed change at 50.94422920435813, 6.982818132995898. Old: 65.0, new:45.0
Speed change at 50.96702284992454, 7.03188984955171. Old: 45.0, new:20.0
Speed change at 50.90650702086146, 7.0605028341376235. Old: 70.0, new:45.0
Updated 86 street elements. Errors:0

To start from scratch you can remove the graph-cache folder and the old speed values will be used. Still this is only a rough prototype. For example:

  • Map matching not yet integrated
  • Fallback to old values -> either store within RoadData or separate GH instance
  • UI: artifact when zooming. No concrete info is shown on mouse over
  • Use two directions for speed if no one-way street
  • Of course it is best to try the system in German-early times and hope that many traffic jams events are there ;)

This is only one city, but we collect more here! Now have fun to test and tweak the system!


Filed under: GraphHopper, Java

Elevation data and OpenStreetMap

$
0
0

Handling elevation data and combine it with OpenStreetMap can be a pain. And indeed it was when we implemented this for GraphHopper roughly one year ago. But we really wanted to make it easy for our users. And it is very easy – you just need to set:

graph.elevation.provider=srtm

in the config.properties and GraphHopper will include elevation automatically! For the full elevation documentation please read this.

In GraphHopper Maps you can try it and see the elevation widget for every route for bike&foot:

elevation-widget

So GraphHopper will include elevation then automatically in

  • the import process and therefor also calculate more precise distances
  • the API where it adds three dimensional points (GHPoint3D) instead of just GHPoint
  • the web API where it uses a third dimension. As we also use a compact form called encoded polyline for this, you need the adapted decoding procedure when consuming the route and not using GeoJSON.

But to make a vehicle (e.g. bike) actually using the height information you need to tell it that uphill its slower than downhill via bike2. So you need a flag encoder with two weights per edge. But it is easy to enable:

graph.flagEncoders=bike2

With this logic in place it should be easy to improve our mountain bike profile to prefer up and down hill. It is important to note that for ‘preferring’ a specific feature it is not necessary to increase the speed. You can just tune this behavior via the priority implemented for bike and foot. Read more about how to write your own flag encoder here.

Other providers and more configurations

The nice thing about our modular approach is also that you can use a complete different provider like we do with CGIAR (improved SRTM data) or even inject your elevation data into the OSM. You just need to change this in the config

graph.elevation.provider=cgiar

Also you can have an in-memory or on-disc storage for this elevation data. E.g. to reduce RAM usage you use the default setting, but to speed up the import and not having SSD discs you set

graph.elevation.dataaccess=RAM_STORE

The nice thing is that you also can use our ElevationProvider implementations for you own Java application. Is it currently not separated from GraphHopper but it is relative separated and GraphHopper core is not big :)


Filed under: GraphHopper, Java

Pick the Best Electric Vehicle Charging Station Along a Route with GraphHopper

$
0
0

mapNearly all electric vehicles to date that rely 100% on electric energy have a severe range problem, especially cars and especially in cold seasons. If you still want to plan a long-distance tour you’ll have to include one (or more) charging station as stopover.

But how to find the best one with the least detour e.g. in this example from Hamburg to Munich?

You calculate all routes to all charging stations and pick the best. That sounds crazy but is completely reasonable in real time with GraphHopper even for hundreds of stations. In this blog post we’ll use the GraphHopper Matrix API and have created the JavaScript charging station example.

Calculate detours with the GraphHopper Matrix API

The GraphHopper Matrix API is a specially crafted piece of software to make many-to-many requests very fast. For example in logistics you need this to determine the optimal order for e.g. delivering parcels.

Now to calculate the best detour we need a similar logic: we need
A) one request, the one-to-many and
B) another request, the many-to-one.

Finally we’ll pick the fastest tour (smallest A+B). The same approach we would take to calculate an optimal ridesharing where you ‘pick up’ and ‘deliver’ people.

We also need all charging stations and grab them from OpenStreetMap via the Overpass API and use the wizard to specify amenity=charging_station and car=yes. We ignore for a moment the socket type of the station and a possible required authentication or fee.

For the German tour from Hamburg to Munich we fetch all stations from middle Germany (roughly 80) and select all which are in the center of our route e.g. within a 400km radius (reducing this is necessary for the free package).

There are several optimizations possible like the route calculating itself to consider elevation to avoid hills or a completely other vehicle like an electric bicycle. Or in real world you have to consider the opening hours of the stations or seek for multiple stops for shorter ranges, then the Tour Optimization API or special routing expertise could be necessary.

In our Hamburg-Munich case the result is the following tour of ~750km and roughly 8.5 hours plus the time required for charging or replacing the battery at this charging station in Erfurt. Compare this to the normal route which takes only 8 hours and is 775km long.

best-station-tour


Filed under: GraphHopper, Java

Map Matching use cases, or why an Open Source and Open Data alternative is superior to the Google Maps Roads API

$
0
0

A map matching software component makes your recorded GPS points align to some digital roads like the one from GraphHopper. The following picture illustrates this map matching process from recorded data (blue) to matching data (green):

The screenshot shows the real world data in blue and the calculated matched roads in green.

This screenshot shows the real world data in blue and the calculated matching roads in green.

But why is this ‘snap to road’ useful? For that we will look today into three possible usage scenarios. Before we start we need to clarify the wording a bit. A GPS point is a location on earth with latitude and longitude data, and a GPX point is a GPS point with an associated timestamp. So when you record your walking or biking trail you often have a GPX file which is a list of GPX points.

1. Attach data available in the digital map

The Google Maps Roads API allows you to make GPX tracks align to their proprietary road network, which is useful. They also allow you to attach the maximum allowed speed but no further information and only for business customers. A solution like a map matching component from GraphHopper which is based on OpenStreetMap has some advantages over that:

  • You can attach not only maximum speed values to your data after the matching, but also turn instructions, street names, surface values, access restrictions, road types and well, nearly any way tag which is stored in OpenStreetMap. And as GraphHopper supports elevation, enhancing the input data with elevation afterwards is possible and easy too.
  • If you find a mistake in the matching which is caused due to a problem in the data or because of missing data in developing countries, then you can easily change this in OpenStreetMap and rerun again. For example allryder uses this process to track urban transport data in emerging regions. Also you can find illegal turns of bicyclists and more which e.g. urban planners can use to improve bikeability of their city. You can read through a German description from ratrun of more of these data wrangling problems.
route_with_maxspeed

Attach any OpenStreetMap way tag to the GPX track like maxspeed=50 in this example.

2. Make recorded routes and speeds more precise

If you track vehicles the data will suffer from GPS device precision errors, which also means that the speed and location is not that exact. Having more precise road network data and use this to enhance your recorded data will help you to calculate more precise distance and speed values for your tracked vehicles.

3. Identical road segments

Once you have recorded the GPX tracks and transformed them into digital paths you know the road IDs. With that information you can easily detect if two vehicles are passing the same road although the GPS coordinates are completely different and just ‘similar’ in location. This makes it easier to assign values like the measured speed to a road. Also this data can be used for traffic influenced routing.

And more

Furthermore an open source solution makes it easy to

  1. Attach your own data like any user rating to the recorded data
  2. Customize the software to your needs e.g. for electric vehicles or improve the matching algorithm itself
  3. Combine the results with a powerful routing algorithm as done in the use case ‘Identical road segments’

Have fun when playing around and let us know about your use case!


Filed under: GraphHopper, Java

Simple Route Optimization integrated in the GraphHopper Routing API

$
0
0

Since several months we’ve been working on our new Route Optimization API, which is a powerful API for your problems in logistics and similar areas. It includes time windows, capacity restrictions and much more features. It’ll be announced soon on its own!

Last week we had an idea: we wanted to make the integration of this new API as easy and straightforward as it can be. And the existing clients of the Routing API now just need to add ‘optimize=true’ to the request URL and the returned route is already optimized regarding overall time. So these clients can now easily solve traveling salesman problems too, and for all problems with more than one vehicle or more advanced restrictions you can still use our Route Optimization API. Of course, all times are based on real road networks instead of imprecise beeline approximations.

Several things need to be calculated under the hood to make this optimization happening:

  1. Decide to do route optimization instead of ‘just’ A-to-B routing.
  2. Now calculate all travel times between all locations (A to B, A to C, B to A, B to C, …), which gives us the travel time matrix (also known as distance matrix). For example, if you specify 5 points then 5*5-5 travel time values are calculated – this is done using our fast Matrix API which is way faster than the sum of individual point-to-point calculations.
  3. Now use the previously calculated travel time matrix to solve the underlying traveling salesman problem, i.e. to optimize the location order.
  4. Finally fetch the complete route with the correct location order including e.g. elevation data for foot and bike routing via the Routing API.

You can already use this feature with our Java and JavaScript clients. And so I did. I locally added this optimize parameter to the GraphHopper Maps UI and what I got was a bit magical! Look into this video to see what I mean:


Filed under: GraphHopper, Java

Releasing GraphHopper 0.5


See how Falk, Ride with GPS and Volo benefit from using GraphHopper

GraphHopper’s new Route Optimization Editor

Analysis of unexpected GraphHopper Directions API downtime

Blog Moved

Releasing GraphHopper 0.3 – Plan Your Outdoor Trips Beyond Two Dimensions

$
0
0

Today we are happy to finally release version 0.3 of GraphHopper – the Open Source road routing engine. Here is a screenshot showing our slightly polished UI

gh-screenshot-0.3

It shows a route result where elevation was enabled. Try it yourself at GraphHopper Maps or see the variety of already implemented use cases!

Highlights:

  • You can easily enable elevation and Graphhopper will not only automatically import and display this, but you can actually use it for routing! E.g. for bike routing hills will be avoided. But also even for horse-routing.
  • GraphHopper runs on Raspberry Pi and even in the Browser!
  • GraphHopper is now available in 19 languages! See here for the details.
  • A more powerful and compact API, including GPX support with turn instructions and elevation information.
  • The address suggestions is done via photon and is available as part of our Web Routing API which is currently in closed alpha.

Thanks a lot to all contributors: NopMap, ratrun, konsoletyper, dardin88, lmar and b3nn0. And all the translators!

Details:

  • You can store two weights per edge (dependent on the direction) – this allows using GraphHopper for interesting new use cases:
    • Biking and hiking tours can now avoid hills as up- and down-hill speed can be different.
    • With traffic data you can make routing more precise as speed values has to be different for the two directions.
  • To make use of this new feature we implemented to read elevation data. For now only hgt files are supported but more will follow. This makes GraphHopper different to many routing engine, especially because we can scale with elevation to world wide coverage (although elevation data is only available for +-60°).
  • The elevation Leaflet widget from MrMufflon is very useful and has a nice dragging feature
  • Support to read OSM relations like for biking routes and overall improved bike routes as it is easier to tweak them
  • Support for more than 2 points – still we need an improved UI to use this feature
  • A new web API format which improves compactness and introduces the new but optional 3rd dimension. Additionally it makes it possible to retrieve the sub-path geometry for every turn instruction. See the documentation.
  • Upgraded the Android demo to the latest mapsforge 0.4.3, and a further fix of an ugly bug
  • Support to make it possible to click on instructions and see them on the map. Additionally navigation software can now easier find the next instruction
  • Lots of the documentation is now in the source, which is better for the user to have up-to-date information. Or where it is possible to look at old docs too.
  • and a lot more bug fixes

Last but not least some months ago there was an article about GraphHopper in the Java Magazine and a session at FOSDEM. Did I mention that you should check out our enterprise offers ;) ? Feel free to join our mailing list or follow us!

Have fun!


Filed under: Java
Viewing all 53 articles
Browse latest View live