RiverScout - Routeplanner voor schepen
Introductie
Aan het begin van de stage werden er twee opdrachten aangeboden, de ene was het maken van een master database voor schepen en een routeplanner. Joost Zonneveld en ik hadden beide gekozen voor het werken aan de routeplanner.
Voor deze opdracht gaan we een routeplanner ontwikkelen voor schepen. Op dit moment wordt de routebepaling verwerkt door een derde partij en wordt dus niet door het bedrijf zelf berekend. De bedoeling van deze opdracht is dus om een routeplanner te maken die de huidige derde partij kan vervangen. Om deze routeplanner ook van verbeteringen te voorzien kan ook gekeken worden naar bijvoorbeeld openingstijden van bruggen, werking van verschillende sluizen en de stroming van het water en de werking daarvan op het schip.
De reden om deze routeplanner te maken was voornamelijk om de huidige routeplanner te kunnen verbeteren en invloed te kunnen hebben op de inhoud van de grafieken binnen de routeplanner. Daarnaast waren er ook een aantal features die de huidige routeplanner niet had, maar die wel graag geïmplementeerd zouden moeten worden.
Brainstorms
Uitleg over het samenvoegen van verschillende grafieken
Voor het opstellen van grafieken heb ik aan Joost uitgelegd hoe het geïmplementeerd was. Hiervoor heb ik de verschillende delen op een bord geschreven en ben ik samen met hem door deze delen gelopen, zodat hij ook begreep hoe het in z'n werk ging.
Bij de werking hiervan, weergegeven in onderstaande afbeelding, komen verschillende onderderdelen aan bod, zoals:
- Asynchroon inladen van verschillende grafieken (bijvoorbeeld FIS, Fairway Information Service van Rijkswaterstaat)
- Samenvoegen van meerdere grafieken
- Samenvoegen van objecten in verschillende grafieken
- Initialisatie en verwerking van het
Graph
object
De stappen benoemd die gebruikt worden voor het aanmaken en samenvoegen van verschillende grafieken
Samenvoegen van routes uit verschillende bronnen
Een probleem dat voorkwam bij het maken van de grafiek was dat de FIS, Fairway Information Service, niet consistent is. Deze inconsistentie kwam zowel voor binnen één bron als tussen verschillende bronnen, wat het heel moeilijk maakt om deze bronnen te koppelen aan elkaar.
Om dit op te lossen moest een algoritme ontwikkeld worden die verschillende bronnen samen kon voegen tot één grafiek die alle gegevens bevat. Het uitdenken van dit algoritme kostte erg veel tijd en is voor het verduidelijken van het probleem ook uitgetekend in de onderstaande afbeelding.
Dit algoritme heeft een hele hoge prioriteit in de werking van de volledige applicatie, het is namelijk verantwoordelijk voor het goed verwerken van verschillende bronnen tot één grafiek wat de routeplanner laat werken. Door deze reden is het van belang dat het heel goed getest is, een gedeelte van de tests voor dit algoritme zijn te vinden bij Realiseren 2 - Graph Route Merging Tests.
Samenvoegen van verschillende segmenten uit verschillende bronnen
Samenvoegen van verschillende grafieken van verschillende versies en bronnen
En een ander probleem is het kunnen samenvoegen van verschillende bronnen, maar deze ook kunnen beheren. Daar komt een beheersysteem bij kijken waar door middel van een aantal instellingen grafieken beheerd kunnen worden.
Om dit beheersysteem te kunnen ontwikkelen heb ik uitgetekend hoe vanaf verschillende bronnen deze worden samengevoegd tot één grafiek die modulair ingesteld kan worden en aangepast kan worden door handmatige input. In de afbeelding hieronder staat weergegeven dat de verschillende bronnen van de FIS worden samengevoegd tot één FIS-grafiek, deze grafiek behoort tot de 'prepared graphs'. Naast 'prepared graphs' zijn er ook 'custom graphs' en dat zijn zelfgemaakte grafieken die opgestuurd naar en samengevoegd in RiverScout kunnen worden. De 'prepared' en 'custom' grafieken vormen samen een 'saved graph' en bij het genereren van een 'final graph' wordt de handmatige input hierbij samengevoegd.
Ten slotte staat in de afbeelding daaronder een visualisatie van hoe deze bronnen opgeslagen en samengevoegd worden.
Notitie van de werking van het beheersysteem
Visualisatie van hoe verschillende bronnen samengevoegd worden tot de uiteindelijke volledige grafiek
Samenwerking
Bij het RiverScout project hebben Joost en ik ook samengewerkt met de data scientist van Teqplay, genaamd Stephan. Hij was bezig met de aanvaarroutes van verschillende landen in kaart te brengen door de AIS-berichten van schepen.
Omdat hij hiermee ook zijn eigen grafieken genereerd moeten deze ook opgenomen kunnen worden in RiverScout, zodat gegevens over zeeschepen ook meegenomen kunnen worden. Zo zouden zeeroutes informatie kunnen bevatten over snelheden van bepaalde soorten schepen en welke routes genomen worden over zee.
Om Stephan de grafieken naar RiverScout te kunnen laten sturen moesten we samen bespreken hoe hij deze graag wilde sturen en hoe wij dit in RiverScout zouden implementeren. In de afbeelding hieronder heeft Stephan samen met Joost en ik opgeschreven hoe de samenwerking met RiverScout in zijn werk zou kunnen gaan. Hiervoor zijn er drie onderdelen die de grafiek identificeren: de informatie van de grafiek (wie stuurt deze grafiek, van welk gebied, etc.), de knooppunten (nodes) uit de grafiek en de lijnen (edges) die tussen die knooppunten lopen. Onder de afbeelding staat een JSON-schema dat ik gemaakt heb om vast te stellen hoe grafieken verstuurd kunnen worden en wat de implementatie in RiverScout verwacht.
Notitie waar Stephan heeft opgeschreven hoe de grafiek opgestuurd wordt naar RiverScout
// Graph Schema
object { // graph
object { // graphInfo
string ownerId
string generationId
string area
string description
},
array { // nodes
string id
object { // location
string type /^(Point)$/
array [ number; ] {2,2} coordinates; // Longitude and latitude in this order
}
},
array { // edges
string id
string from (Node id)
string to (Node id)
object { // between
string type /^(LineString)$/;
array [array [number;] {2,2} ] coordinates // Longitude and latitude in this order
}
map[string,string] info (Key value pairs for extra information)
}
}
// Example
{
"graphInfo": {
"ownerId": "owner",
"generationId": "generation",
"area": "NORTH SEA",
"description": "description"
},
"nodes": [
{
"id": "UUID1",
"location": {
"type": "Point",
"coordinates": [
4.0,
52.0
]
}
},
{
"id": "UUID2",
"location": {
"type": "Point",
"coordinates": [
4.0,
53.0
]
}
}
],
"edges": [
{
"id": "UUID",
"from": "UUID1",
"to": "UUID2",
"between": {
"coordinates": [
[
4.0,
52.25
],
[
4.0,
52.75
]
],
"type": "LineString"
},
"info": {
"key1": "value1",
"key2": "value2"
}
}
]
}
Het JSON-schema dat de verwachting om een grafiek te ontvangen in RiverScout beschrijft
Resultaat
Het resultaat is een routeplanner die verschillende bronnen kan gebruiken om grafieken te maken, deze grafieken opensteld, snel routes kan berekenen met details van een schip en de werking en kwaliteit ervan beter is dan de huidige routeplanner. Daarnaast heeft RiverScout de huidige routeplanner op de ontwikkelingsomgeving van Teqplay al vervangen en zal deze later ook op de live-omgeving aangesloten worden.
Naast dat RiverScout aan de requirements voldoet, geeft het Teqplay ook de mogelijkheid om de grafieken van de routeplanner aan te passen en aan te vullen met verbeterde en nieuwe informatie over routes. Hierdoor is RiverScout een hele waardevolle aanwinst om te gebruiken als routeplanner voor Teqplay.
Hieronder staan twee afbeeldingen die de grafiek van RiverScout visualiseren. Als eerste de 'Graph-Visualizer' die aan het begin van het ontwikkelproces van RiverScout ontwikkeld is om de grafiek in te kunnen zien en erg geholpen heeft bij de ontwikkeling van RiverScout zelf. Daaronder staat de frontend van RiverScout die Joost Zonneveld ontwikkeld heeft en aangesloten staat op de API van de backend van RiverScout.
De 'Graph-Visualizer' van RiverScout
De frontend van RiverScout