Routino

Innen: GIS Wiki

A Routino egy útvonaltervező szoftver, mely OSM adatok felhasználásával képes a legrövidebb, vagy a leggyorsabb utat kiszámítani két pont között. A szoftvert C nyelven írták, emellett a webes felületét CGI scriptek segítségével teszi dinamikussá.

Az OSM adatokat fel kell dolgozni, még az első használat előtt. Támogatott formátumok: XML, PBF, O5M. Az előfeldolgozást csak egyszer kell végrehajtani az OSM adatokon. Az útvonaltervezés eredménye kimenthető HTML, illetve GPX formátumban is.

Az útvonaltervező figyelembe veszi az utakra való korlátozásokat is (például.: sebesség, súly, méretkorlátozás), illetve a KRESZ korlátozásait is (például.: egyszerűbb tiltások a kanyarodásra, egy irányú az utca).

A programot jelenleg legtöbben saját weboldalukba beépítve, útvonaltervezésre használják, általában egy régióra lekorlátozva. Emellett, amióta kiegészült egy függvénykönyvtárral, lehetővé tették az asztali alkalmazások számára is az útvonaltervezést, kibővítve a felhasználhatósági kört.

Telepítés

Linux

Előfeltételek A program előfeltételeit célszerű telepíteni először

apt-get install gcc make libc6-dev libz-dev libbz2-dev
apt-get install libwww-perl liburi-perl libjson-pp-perl #These are optional

Telepítés A telepítéshez ez után le kell töltenünk a Routino weboldaláról a forráskódot, majd azt kibontva, le kell fordítanunk, majd be kell másolni az Apache webszerver mappájába.

make
cp -a web /var/www/routino
chown -R www-data:www-data /var/www/routino

Ezek után az OSM adatokat fel kell dolgozni:

cd /var/www/routino/data
../bin/planetsplitter --errorlog [Tetszőleges OSM fájl neve].osm.bz2

Miután megvolt, válasszuk ki, hogy OpenLayers vagy Leaflet felületen szeretnénk-e használni a Routino-t, és futtassuk ezt le:

cd /var/www/routino/www/[openlayers vagy leaflet]
sh -x install.sh

Ezek után még egy lépés hátra van, az apache /etc/apache2/sites-enabled/000-default fájljába ezeket a sorokat hozzá kell adni:

<Directory /var/www/routino>
    AllowOverride Options=MultiViews,ExecCGI FileInfo Limit
</Directory>

Konfigurálás

Szerkesszük az alábbi fájlt: /var/www/routino/www/routino/mapprops.js

  • A library változó értékével tudjuk módosítani, hogy az OpenLayers vagy a Leaflet felületet próbálja-e meg betölteni.
  • A westedge eastedge southedge northedge zoomout zoomin változókkal értelemszerűen a térkép mozgásterét tudjuk korlátozni, illetve a minimum és a maximum zoom értékeket.
  • A mapdata változóban tudjuk megadni, hogy melyik Tileserver-ről szedje le a térkép Tile-okat. Az alapértelmezett Tileserver jelenleg megfelelő lesz.

Windows

Bizonyos korlátozásokkal elérhető a Routino Windowson is, és a telepítése is egy bonyolultabb folyamat, a legegyszerűbb, ha követjük a Routino által leírt lépéseket.

Algoritmusok

Előfeldolgozás

Ahhoz, hogy kellően gyors, és hatékony legyen az útvonalkeresés, az OSM adatokat feldolgozzuk, és eltároljuk egy lokális adatbázisban. A csomópontok közül a legtöbbet töröljük, és az érdekes csomópontokat hagyjuk meg. Ezután az izolált területeket töröljük.

A csomópontok megtartásának szabályai:

  • 3 vagy több útvonalszakaszt köt össze.
  • 2 útvonalszakaszt köt össze, de a két útvonalszakasznak más tulajdonságai vannak.
  • 2 útvonalszakaszt köt össze, de az útvonalszakaszok közt megváltoztak az útvonaltervezési korlátozások.

A fentebbi szabályokat felhasználva a csomópontok törlését annyiszor ismételhetjük, amíg csak a legfontosabb csomópontok maradnak már csak meg. Ezeket a csomópontokat szuper-csomópontnak nevezzük, és a szuper-csomópontokat szuper-utak kötik össze.

Útkeresés

  1. A kezdőponttól útvonalat keresünk a legközelebbi szuper-csomóponthoz.
  2. A végponttól útvonalat keresünk a legközelebbi szuper-csomóponthoz.
  3. Az 1. és a 2. szuper-csomópont közt megkeressük a szuper-útvonalat.
  4. A 3. pontban talált szuper-útvonalak mindegyikére megkeresi a legrövidebb utat a szuper-útvonal kezdő és végpontja között.

Az útvonal keresési algoritmust az A* algoritmussal (vagy legalábbis egy ehhez nagyon hasonlító algoritmussal) oldották meg. Ez az algoritmus a kezdő csomóponttól a legkisebb érték (legrövidebb, vagy leggyorsabb út) kiszámítására törekszik minden csomóponthoz.

A 4. pontban lévő útvonalakat viszont a Dijkstra algoritmussal keresi meg.

Webes felület

Útvonaltervező

Az útvonaltervező felület alapvetően 3 fülre van bontva, melyeken csoportosítva érhetőek el a funkciók.

Beállítások

Itt lehet kiválasztani az utazás kezdő és végpontjait, illetve a közbeeső állomások pontjait is itt lehet megadni, emellett van lehetőségünk az utazás fajtáját kiválasztani, illetve a preferenciákat módosítani, a sebességkorlátokat módosítani, illetve meg lehet adni súly, vagy méretbeli korlátozásokat.

Routino options.png

Eredmény

Az útvonaltervezés instrukciói, a távolsága, és az időtartama itt jelenik meg, ezenkívül van lehetőségünk ezt az útvonalat megjeleníteni egy új lapon HTML, szöveges, vagy akár GPX formátumban is.

Routino results.png

Adatok

Innen érhető el az adatvizualizációs felület, illetve megjeleníthetőek benne az adatokkal kapcsolatos statisztikák.

Adat vizualizáció

Vizualizáló

Itt lehet megjeleníttetni a Routino által eltárolt információkat a térképen, mint például a szuper-utakat, korlátozásokat, csomópontokat.

Routino visualiser.png

Útvonaltervező

Innen vissza lehet menni az útvonaltervező interfészre.

Adatok

Az útvonaltervezőnél lévő adatok fülre hasonlít, ugyanazokat az adatokat/statisztikákat lehet itt is megjeleníteni.

Fejlesztés

Webes felületre

A webes felület elérhető Leaflet, illetve OpenLayers térképmegjelenítőkben is, ezért érdemes a gyárilag kapott webes interfészt használni, azt személyre szabni (CSS), átvariálni a kezelőfelületét, és beleépíteni a honlapunkba, ahol szeretnénk használni az útvonaltervezés funkciót. Amennyiben egyáltalán nem használnánk a gyárilag kapott webes felületet, írhatunk saját megjelenítőt, a lentebbi két opció által.

A programot használva

A fordítás után létrejött egy router nevű futtatható állomány, mellyel parancssori argumentumok segítségével tervezhetünk útvonalat, és azt HTML, szöveges, vagy GPX formátumban fájlba menthetjük, vagy akár kiírhatjuk a képernyőre. Használat:

Usage: router [--version]
              [--help | --help-profile | --help-profile-xml |
                        --help-profile-json | --help-profile-perl ]
              [--dir=<dirname>] [--prefix=<name>]
              [--profiles=<filename>] [--translations=<filename>]
              [--exact-nodes-only]
              [--quiet | [--loggable] [--logtime] [--logmemory]]
              [--output-html]
              [--output-gpx-track] [--output-gpx-route]
              [--output-text] [--output-text-all]
              [--output-none] [--output-stdout]
              [--profile=<name>]
              [--transport=<transport>]
              [--shortest | --quickest]
              --lon1=<longitude> --lat1=<latitude>
              --lon2=<longitude> --lon2=<latitude>
              [ ... --lon99=<longitude> --lon99=<latitude>]
              [--reverse] [--loop]
              [--heading=<bearing>]
              [--highway-<highway>=<preference> ...]
              [--speed-<highway>=<speed> ...]
              [--property-<property>=<preference> ...]
              [--oneway=(0|1)] [--turns=(0|1)]
              [--weight=<weight>]
              [--height=<height>] [--width=<width>] [--length=<length>]

Példa a használatra:

./router --shortest --lon1=19.45000 --lat1=47.17563 --lon2=19.09424 --lat2=47.33138 --dir=../data --output-stdout --output-text

A függvénykönyvtárat használva

A Routino 3.0 megjelenése óta külön függvénykönyvtárként is elérhető az útvonaltervező szolgáltatás. Kétféle library is készült hozzá, a libroutino és a libroutino-slim. Az interfészük teljesen megegyezik, viszont a slim változat kevesebb memóriát fogyaszt, cserébe lassabb is. A teljes leírása az API-nak elérhető itt. A használatát egy egyszerű példaprogrammal bemutatom itt, megtalálhatóak benne a legfontosabb függvények, hogy hogyan kell használni, és hogy az eredményen hogyan lehet végigiterálni:

#include <iostream>
#include <cstdlib>
#include <routino.h>

int main (int argc, char *argv[])
{
	Routino_Database    *t_routinoDB   = Routino_LoadDatabase("/var/www/routino/data", NULL);   //Betöltjük az adatbázist
	if(!t_routinoDB) { std::cout << "Could not find database" << std::endl; return 1; }
	Routino_ParseXMLProfiles("/var/www/routino/data/profiles.xml");                             //Felolvassuk a Profiles XML-t
	Routino_ParseXMLTranslations("/var/www/routino/data/translations.xml");                     //Felolvassuk a fordításokat
		
	Routino_Profile     *t_profile     = Routino_GetProfile("motorcar");                        //Kiválasztjuk az utazási módot: autó
	if(!t_profile) { std::cout << "Could not find profile" << std::endl; return 1; }
	Routino_Translation *t_translation = Routino_GetTranslation("hu");                          //Kiválasztjuk a nyelvet: magyar
	if(Routino_ValidateProfile(t_routinoDB, t_profile) != 0) { std::cout << "Not valid profile" << std::endl; return 1; }	//Ellenőrizzük, hogy érvényes-e a profil
	
	Routino_Waypoint   **t_waypoints = (Routino_Waypoint**)calloc(sizeof(Routino_Waypoint*), 2); //Lefoglaljuk a helyet a kezdő és a végpontnak
	
	t_waypoints[0] = Routino_FindWaypoint(t_routinoDB, t_profile, 47.17563, 19.45000);           //Beállítjuk a kezdőpontot
	t_waypoints[1] = Routino_FindWaypoint(t_routinoDB, t_profile, 47.33138, 19.09424);           //Beállítjuk a végpontot
	
	if(!t_waypoints[0]) { std::cout << "Could not find starting point" << std::endl; return 1; }
	if(!t_waypoints[1]) { std::cout << "Could not find ending point" << std::endl; return 1; }
	
	int t_routingOptions = 0;
	t_routingOptions |= ROUTINO_ROUTE_QUICKEST;             //A legrövidebb úton menjünk
	t_routingOptions |= ROUTINO_ROUTE_LIST_TEXT_ALL;        //Szövegesen írja ki az utcaneveket
	
	Routino_Output *t_output = Routino_CalculateRoute(t_routinoDB, t_profile, t_translation, t_waypoints, 2, t_routingOptions, NULL); //Kiszámítjuk az útvonalat
	
	Routino_Output *t_iter = t_output;
	while(t_iter) //Amíg végig nem érünk az útvonal pontjain, kiírjuk a koordinátáit, és az utca nevét
	{
		std::cout << ( t_iter->lon * 180 ) / 3.14 << " " << ( t_iter->lat * 180 ) / 3.14;
		if(t_iter->name)
			std::cout << " " << t_iter->name;
		std::cout << std::endl;
		t_iter = t_iter->next;
	}
	
	Routino_DeleteRoute(t_output);                  //Felszabadítjuk a memóriából az útvonalat
	Routino_UnloadDatabase(t_routinoDB);            //Felszabadítjuk a memóriából az adatbázist
	Routino_FreeXMLProfiles();                      //Felszabadítjuk a memóriából a betöltött profilokat
	Routino_FreeXMLTranslations();                  //Felszabadítjuk a memóriából a betöltött nyelveket
	for(int waypoint=0;waypoint<2;waypoint++)
		free(t_waypoints[waypoint]);
	free(t_waypoints);                              //Töröljük az általunk foglalt területeket
}

Hivatkozások