# Difference between revisions of "Marble/Runners/MarblePythonVehicleTracking"

Vehicle Tracking
 Tutorial Series Marble Python Tutorial Previous Tutorial 6 - Displaying Places the proper way (via GeoDataDocuments) What's Next Tutorial 13 - GeoPainter: Painting onto the map Further Reading n/a

We want to present you another Python example of Marble Runnable usage, here on KDE TechBase. It's about the cars. Imagine that there are two flying cars in the air. They are driving around ukranian city Kiev (EURO-2012). They are driving circles around it with set radius and speed. At the end of tutorial you will have an application looking something like:

Let's think about implementation a bit:

1. Init MarbleWidget
2. Implement placemarks for cars "Bus" and "Car"
3. Change their coordinates using trigonometry functions
4. Apply new coordinates

We need to change coordinates with really small interval (~10 ms). In this way, to not block GUI thread we need to use multi-threading. For that we suggest that model:

2. Create CarWorker #1 (= worker for cars' coordinates)
3. Move CarWorker #1 into thread #1
4. The same for Car #2 (1-3)

Then we will have three threads - GUI, Calculations #1, Calculations #2. To connect calc. threads with GUI we should use Qt S/S (Signal/Slot) connection.

Important
Use here connection type Qt::BlockingQueuedConnection, another way GUI thread will be blocked

Now we have a nice implementation plan. Let's start coding.

1. main() creates an object of the Window (our main QWidget-based window)
2. Window creates the MarbleWidget and sets two GeoDataPlacemarks there
3. main() calls Window::startCars()
5. Window creates two CarWorkers
6. Window moves car workers into their threads

Then each CarWorker creates a QTimer with interval x. On timeout() it calls the CarWorker::iterate() - function to calculate new position of placemark and notify Window (another thread) about it.

Everything is going on until the application finishes.

```#!/usr/bin/env python
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyKDE4.marble import *
import sys
from math import *

class CarWorker(QObject):
QObject.__init__(self)
# initialize the worker's data
self.city = city
self.speed = speed
self.timer = QTimer(self)
self.alpha = 0.0

def startWork(self):
self.timer.setInterval(0)
self.connect(self.timer, SIGNAL('timeout()'), self.iterate)
self.timer.start()

def iterate(self):
# update the loaction of the current worker

coord = Marble.GeoDataCoordinates(lon, lat, 0.0, Marble.GeoDataCoordinates.Degree);
self.emit(SIGNAL("coordinatesChanged(PyQt_PyObject)"), coord)

self.alpha += self.speed;

def finishWork(self):
self.timer.stop()

class Window(QWidget):
def __init__(self):
QWidget.__init__(self)

# create the marble widget
self.marble = Marble.MarbleWidget()

# resize the widget and add a window title
self.resize(1000, 800)
self.setWindowTitle("vehicletracking")

layout = QVBoxLayout(self)
self.setLayout(layout)

self.marble.setMapThemeId("earth/openstreetmap/openstreetmap.dgml")
self.marble.setProjection(Marble.Mercator)
# center the map on Kiev
Kiev = Marble.GeoDataCoordinates(30.523333, 50.45, 0.0, Marble.GeoDataCoordinates.Degree)
self.marble.centerOn(Kiev);
# set the zoom
self.marble.setZoom(2300)

# create the placemarks and their containing document
self.carFirst = Marble.GeoDataPlacemark("Bus")
self.carSecond = Marble.GeoDataPlacemark("Car")

self.document.append(self.carFirst)
self.document.append(self.carSecond)

# add the placemark document to the map

# add the widget to the KMainWindow
self.show()

def startCars(self):
Kiev = Marble.GeoDataCoordinates(30.523333, 50.45, 0.0, Marble.GeoDataCoordinates.Degree)

# create the thread for the first car
self.firstWorker = CarWorker(Kiev, 0.1, 0.7)

self.connect(self.firstWorker, SIGNAL("coordinatesChanged(PyQt_PyObject)"),
self.setCarCoordinates, Qt.BlockingQueuedConnection)

# create the thread for the second car
self.secondWorker = CarWorker(Kiev, 0.2, -0.5)

self.connect(self.secondWorker, SIGNAL("coordinatesChanged(PyQt_PyObject)"),
self.setCarCoordinates, Qt.BlockingQueuedConnection)

# when both the threads start, begin running the workers

def setCarCoordinates(self, coord):
worker = self.sender()
# set the coordinates based on which worker emitted the signal
if (worker == self.firstWorker):
self.carFirst.setCoordinate(coord)
self.marble.model().treeModel().updateFeature(self.carFirst)
elif (worker == self.secondWorker):
self.carSecond.setCoordinate(coord)
self.marble.model().treeModel().updateFeature(self.carSecond)

def main():
app = QApplication(sys.argv)

window = Window()
window.startCars()

app.exec_()

main()
```

Save this file as "vehicletracking.py" then execute python vehicletracking.py. If everything goes fine, marble widget will appear as shown in the screenshot at the start of the tutorial.

Content is available under Creative Commons License SA 4.0 unless otherwise noted.