diff --git a/.gitignore b/.gitignore
index ac56614b7b9d2173ed98b14bada25995242f6595..8d8ad390db46113f027d2d7a64a3ced8a6f0c45e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,3 +23,6 @@ msvcp90.dll
 # PyCharm
 .idea/*
 .DS_Store
+
+# vscode
+.vscode/
\ No newline at end of file
diff --git a/setup.py b/setup.py
index ef1a971b8b56dd1c5b5fd7a4e5519ab5254f20f3..04ff299aea9c86d586018fc6340db77bc71d7ef2 100644
--- a/setup.py
+++ b/setup.py
@@ -17,7 +17,10 @@ if sys.argv[1] == 'build':
             'build_exe': {'includes': ['numpy.core._methods',
                                        'numpy.lib.format',
                                        'pyqtgraph.debug',
-                                       'pyqtgraph.ThreadsafeTimer']}
+                                       'pyqtgraph.ThreadsafeTimer',
+                                       ],
+                          'packages': ['asyncio'],
+                          'excludes': ['tkinter']}
         },
         'executables': [Executable("bin/cfclient", icon='bitcraze.ico')],
     }
@@ -128,7 +131,9 @@ setup(
                                           'appdirs>=1.4.0',
                                           'pyzmq',
                                           'pyqtgraph>=0.10',
-                                          'PyYAML'],
+                                          'PyYAML',
+                                          'quamash==0.6.1',
+                                          'qtm>=2.0.2'],
 
     # List of dev and qt dependencies
     # You can install them by running
diff --git a/src/cfclient/gui.py b/src/cfclient/gui.py
index 7c0526e31bdfd74f20f48ac963e6498f5c5ab753..25598f3983e3961f89ae291dc7e1ba8a2133573e 100644
--- a/src/cfclient/gui.py
+++ b/src/cfclient/gui.py
@@ -28,11 +28,13 @@
 
 import sys
 import os
+import asyncio
 import argparse
 import datetime
 
 import logging
 
+from quamash import QSelectorEventLoop
 import cfclient
 
 __author__ = 'Bitcraze AB'
@@ -138,6 +140,10 @@ def main():
 
     app = QApplication(sys.argv)
 
+    # Create and set an event loop that combines qt and asyncio
+    loop = QSelectorEventLoop(app)
+    asyncio.set_event_loop(loop)
+
     app.setWindowIcon(QIcon(cfclient.module_path + "/icon-256.png"))
     # Make sure the right icon is set in Windows 7+ taskbar
     if os.name == 'nt':
diff --git a/src/cfclient/ui/tabs/QualisysTab.py b/src/cfclient/ui/tabs/QualisysTab.py
new file mode 100644
index 0000000000000000000000000000000000000000..d5418a35b0e53ea0528adfb1b546b08d92232cf4
--- /dev/null
+++ b/src/cfclient/ui/tabs/QualisysTab.py
@@ -0,0 +1,1451 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+#     ||          ____  _ __
+#  +------+      / __ )(_) /_______________ _____  ___
+#  | 0xBC |     / __  / / __/ ___/ ___/ __ `/_  / / _ \
+#  +------+    / /_/ / / /_/ /__/ /  / /_/ / / /_/  __/
+#   ||  ||    /_____/_/\__/\___/_/   \__,_/ /___/\___/
+#
+#  Copyright (C) 2011-2013 Bitcraze AB
+#
+#  Crazyflie Nano Quadcopter Client
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+#  02110-1301, USA.
+"""
+Tab for controlling the Crazyflie using Qualisys Motion Capturing system
+"""
+
+import logging
+import time
+import datetime
+import math
+from enum import Enum
+
+from PyQt5 import uic
+from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, pyqtProperty
+from PyQt5.QtCore import QStateMachine, QState, QEvent, QTimer
+from PyQt5.QtCore import QAbstractTransition
+from PyQt5.QtWidgets import QMessageBox
+from PyQt5.QtGui import QStandardItemModel, QStandardItem
+
+import cfclient
+from cfclient.ui.tab import Tab
+from cfclient.utils.config import Config
+from cflib.crazyflie.log import LogConfig
+from cflib.crazyflie.syncCrazyflie import SyncCrazyflie
+from cflib.crazyflie.syncLogger import SyncLogger
+
+import xml.etree.cElementTree as ET
+import threading
+
+import qtm
+import asyncio
+
+__author__ = 'Bitcraze AB'
+__all__ = ['QualisysTab']
+
+logger = logging.getLogger(__name__)
+
+qualisys_tab_class, _ = uic.loadUiType(cfclient.module_path +
+                                       "/ui/tabs/qualisysTab.ui")
+
+
+class FlightModeEvent(QEvent):
+
+    def __init__(self, mode, parent=None):
+        super(FlightModeEvent, self).__init__(QEvent.Type(QEvent.User + 1))
+        self.mode = mode
+
+
+class FlightModeTransition(QAbstractTransition):
+
+    def __init__(self, value, parent=None):
+        super(FlightModeTransition, self).__init__(parent)
+        self.value = value
+
+    def eventTest(self, event):
+        if event.type() != QEvent.Type(QEvent.User + 1):
+            return False
+
+        return event.mode == self.value
+
+    def onTransition(self, event):
+        pass
+
+
+class FlightModeStates(Enum):
+    LAND = 0
+    LIFT = 1
+    FOLLOW = 2
+    PATH = 3
+    HOVERING = 4
+    GROUNDED = 5
+    DISCONNECTED = 6
+    CIRCLE = 7
+    RECORD = 8
+
+
+COLOR_BLUE = '#3399ff'
+COLOR_GREEN = '#00ff60'
+COLOR_RED = '#cc0404'
+
+
+def progressbar_stylesheet(color):
+    return """
+        QProgressBar {
+            border: 1px solid #AAA;
+            background-color: transparent;
+        }
+
+        QProgressBar::chunk {
+            background-color: """ + color + """;
+        }
+    """
+
+
+def start_async_task(task):
+    return asyncio.ensure_future(task)
+
+
+class QDiscovery(QObject):
+    discoveringChanged = pyqtSignal(bool)
+    discoveredQTM = pyqtSignal(str, str)
+
+    def __init__(self, *args):
+        super().__init__(*args)
+        self._discovering = False
+        self._found_qtms = {}
+
+    @pyqtProperty(bool, notify=discoveringChanged)
+    def discovering(self):
+        return self._discovering
+
+    @discovering.setter
+    def discovering(self, value):
+        if value != self._discovering:
+            self._discovering = value
+            self.discoveringChanged.emit(value)
+
+    def discover(self, *, interface='0.0.0.0'):
+        self.discovering = True
+        start_async_task(self._discover_qtm(interface))
+
+    async def _discover_qtm(self, interface):
+        try:
+            async for qtm_instance in qtm.Discover(interface):
+                info = qtm_instance.info.decode("utf-8").split(",")[0]
+                self.discoveredQTM.emit(info, qtm_instance.host)
+
+        except Exception as e:
+            logger.info("Exception during qtm discovery: %s", e)
+
+        self.discovering = False
+
+
+class QualisysTab(Tab, qualisys_tab_class):
+    """
+        Tab for controlling the crazyflie using
+        Qualisys Motion Capturing system
+    """
+
+    _connected_signal = pyqtSignal(str)
+    _disconnected_signal = pyqtSignal(str)
+    _log_data_signal = pyqtSignal(int, object, object)
+    _log_error_signal = pyqtSignal(object, str)
+    _param_updated_signal = pyqtSignal(str, str)
+    _imu_data_signal = pyqtSignal(int, object, object)
+
+    _flight_path_select_row = pyqtSignal(int)
+    _flight_path_set_model = pyqtSignal(object)
+    _path_selector_add_item = pyqtSignal(str)
+    _path_selector_set_index = pyqtSignal(int)
+
+    statusChanged = pyqtSignal(str)
+    cfStatusChanged = pyqtSignal(str)
+    qtmStatusChanged = pyqtSignal(str)
+
+    def __init__(self, tabWidget, helper, *args):
+        super(QualisysTab, self).__init__(*args)
+        self.setupUi(self)
+
+        self._machine = QStateMachine()
+        self._setup_states()
+        self._event = threading.Event()
+
+        self.tabName = "Qualisys"
+        self.menuName = "Qualisys Tab"
+        self.tabWidget = tabWidget
+        self.qtm_6DoF_labels = None
+        self._helper = helper
+        self._qtm_connection = None
+        self.scf = None
+        self.uri = "80/2M"
+        self.model = QStandardItemModel(10, 4)
+
+        self._cf_status = self.cfStatusLabel.text()
+        self._status = self.statusLabel.text()
+        self._qtm_status = self.qtmStatusLabel.text()
+
+        self.flying_enabled = False
+        self.switch_flight_mode(FlightModeStates.DISCONNECTED)
+        self.cf_ready_to_fly = False
+        self.path_pos_threshold = 0.2
+        self.circle_pos_threshold = 0.1
+        self.circle_radius = 1.5
+        self.circle_resolution = 15.0
+        self.position_hold_timelimit = 0.1
+        self.length_from_wand = 2.0
+        self.circle_height = 1.2
+        self.new_path = []
+        self.recording = False
+        self.land_for_recording = False
+        self.default_flight_paths = [[
+            "Path 1: Sandbox", [0.0, -1.0, 1.0, 0.0], [0.0, 1.0, 1.0, 0.0]
+        ],
+                                     [
+                                         "Path 2: Height Test",
+                                         [0.0, 0.0, 0.5, 0.0],
+                                         [0.0, 0.0, 1.0, 0.0],
+                                         [0.0, 0.0, 1.5, 0.0],
+                                         [0.0, 0.0, 2.0, 0.0],
+                                         [0.0, 0.0, 2.3, 0.0],
+                                         [0.0, 0.0, 1.8, 0.0],
+                                         [0.0, 0.0, 0.5, 0.0],
+                                         [0.0, 0.0, 0.3, 0.0],
+                                         [0.0, 0.0, 0.15, 0.0]
+                                     ],
+                                     [
+                                         "Path 3: 'Spiral'",
+                                         [0.0, 0.0, 1.0, 0.0],
+                                         [0.5, 0.5, 1.0, 0.0],
+                                         [0.0, 1.0, 1.0, 0.0],
+                                         [-0.5, 0.5, 1.0, 0.0],
+                                         [0.0, 0.0, 1.0, 0.0],
+                                         [0.5, 0.5, 1.2, 0.0],
+                                         [0.0, 1.0, 1.4, 0.0],
+                                         [-0.5, 0.5, 1.6, 0.0],
+                                         [0.0, 0.0, 1.8, 0.0],
+                                         [0.5, 0.5, 1.5, 0.0],
+                                         [0.0, 1.0, 1.0, 0.0],
+                                         [-0.5, 0.5, 0.5, 0.0],
+                                         [0.0, 0.0, 0.25, 0.0]
+                                     ]]
+
+        # The position and rotation of the cf and wand obtained by the
+        # camera tracking, if it cant be tracked the position becomes Nan
+        self.cf_pos = Position(0, 0, 0)
+        self.wand_pos = Position(0, 0, 0)
+
+        # The regular cf_pos can a times due to lost tracing become Nan,
+        # this the latest known valid cf position
+        self.valid_cf_pos = Position(0, 0, 0)
+
+        try:
+            self.flight_paths = Config().get("flight_paths")
+        except Exception as err:
+            logger.debug("No flight config")
+            self.flight_paths = self.default_flight_paths
+
+        if self.flight_paths == []:
+            self.flight_paths = self.default_flight_paths
+
+        # Always wrap callbacks from Crazyflie API though QT Signal/Slots
+        # to avoid manipulating the UI when rendering it
+        self._connected_signal.connect(self._connected)
+        self._disconnected_signal.connect(self._disconnected)
+        self._log_data_signal.connect(self._log_data_received)
+        self._param_updated_signal.connect(self._param_updated)
+
+        self._flight_path_select_row.connect(self._select_flight_path_row)
+        self._flight_path_set_model.connect(self._set_flight_path_model)
+        self._path_selector_add_item.connect(self._add_path_selector_item)
+        self._path_selector_set_index.connect(self._set_path_selector_index)
+
+        self.statusChanged.connect(self._update_status)
+        self.cfStatusChanged.connect(self._update_cf_status)
+        self.qtmStatusChanged.connect(self._update_qtm_status)
+
+        # Connect the Crazyflie API callbacks to the signals
+        self._helper.cf.connected.add_callback(self._connected_signal.emit)
+
+        self._helper.cf.disconnected.add_callback(
+            self._disconnected_signal.emit)
+
+        # Connect the UI elements
+        self.connectQtmButton.clicked.connect(self.establish_qtm_connection)
+        self.landButton.clicked.connect(self.set_land_mode)
+        self.liftButton.clicked.connect(self.set_lift_mode)
+        self.followButton.clicked.connect(self.set_follow_mode)
+        self.emergencyButton.clicked.connect(self.set_kill_engine)
+        self.pathButton.clicked.connect(self.set_path_mode)
+        self.circleButton.clicked.connect(self.set_circle_mode)
+        self.recordButton.clicked.connect(self.set_record_mode)
+        self.removePathButton.clicked.connect(self.remove_current_path)
+
+        for i in range(len(self.flight_paths)):
+            self.pathSelector.addItem(self.flight_paths[i][0])
+
+        self.pathSelector.currentIndexChanged.connect(self.path_changed)
+
+        self.quadBox.currentIndexChanged[str].connect(self.quad_changed)
+        self.stickBox.currentIndexChanged[str].connect(self.stick_changed)
+        self.stickName = 'qstick'
+        self.quadName = 'crazyflie'
+
+        # Populate UI elements
+        self.posHoldPathBox.setText(str(self.position_hold_timelimit))
+        self.radiusBox.setText(str(self.circle_radius))
+        self.posHoldCircleBox.setText(str(self.position_hold_timelimit))
+        self.resolutionBox.setText(str(self.circle_resolution))
+        self.path_changed()
+
+        self._discovery = QDiscovery()
+        self._discovery.discoveringChanged.connect(self._is_discovering)
+        self._discovery.discoveredQTM.connect(self._qtm_discovered)
+
+        self.discoverQTM.clicked.connect(self._discovery.discover)
+        self._discovery.discover()
+
+        self._ui_update_timer = QTimer(self)
+        self._ui_update_timer.timeout.connect(self._update_ui)
+
+    def _setup_states(self):
+        parent_state = QState()
+
+        # DISCONNECTED
+        disconnected = QState(parent_state)
+        disconnected.assignProperty(self, "status", "Disabled")
+        disconnected.assignProperty(self.pathButton, "text", "Path Mode")
+        disconnected.assignProperty(self.followButton, "text", "Follow Mode")
+        disconnected.assignProperty(self.circleButton, "text", "Circle Mode")
+        disconnected.assignProperty(self.recordButton, "text", "Record Mode")
+        disconnected.assignProperty(self.pathButton, "enabled", False)
+        disconnected.assignProperty(self.emergencyButton, "enabled", False)
+        disconnected.assignProperty(self.landButton, "enabled", False)
+        disconnected.assignProperty(self.followButton, "enabled", False)
+        disconnected.assignProperty(self.liftButton, "enabled", False)
+        disconnected.assignProperty(self.circleButton, "enabled", False)
+        disconnected.assignProperty(self.recordButton, "enabled", False)
+        disconnected.entered.connect(self._flight_mode_disconnected_entered)
+
+        # HOVERING
+        hovering = QState(parent_state)
+        hovering.assignProperty(self, "status", "Hovering...")
+        hovering.assignProperty(self.pathButton, "text", "Path Mode")
+        hovering.assignProperty(self.followButton, "text", "Follow Mode")
+        hovering.assignProperty(self.circleButton, "text", "Circle Mode")
+        hovering.assignProperty(self.recordButton, "text", "Record Mode")
+        hovering.assignProperty(self.pathButton, "enabled", True)
+        hovering.assignProperty(self.emergencyButton, "enabled", True)
+        hovering.assignProperty(self.landButton, "enabled", True)
+        hovering.assignProperty(self.followButton, "enabled", True)
+        hovering.assignProperty(self.liftButton, "enabled", False)
+        hovering.assignProperty(self.circleButton, "enabled", True)
+        hovering.assignProperty(self.recordButton, "enabled", True)
+        hovering.entered.connect(self._flight_mode_hovering_entered)
+
+        # GROUNDED
+        grounded = QState(parent_state)
+        grounded.assignProperty(self, "status", "Landed")
+        grounded.assignProperty(self.pathButton, "text", "Path Mode")
+        grounded.assignProperty(self.followButton, "text", "Follow Mode")
+        grounded.assignProperty(self.circleButton, "text", "Circle Mode")
+        grounded.assignProperty(self.recordButton, "text", "Record Mode")
+        grounded.assignProperty(self.pathButton, "enabled", True)
+        grounded.assignProperty(self.emergencyButton, "enabled", True)
+        grounded.assignProperty(self.landButton, "enabled", False)
+        grounded.assignProperty(self.followButton, "enabled", False)
+        grounded.assignProperty(self.liftButton, "enabled", True)
+        grounded.assignProperty(self.circleButton, "enabled", True)
+        grounded.assignProperty(self.recordButton, "enabled", True)
+        grounded.entered.connect(self._flight_mode_grounded_entered)
+
+        # PATH
+        path = QState(parent_state)
+        path.assignProperty(self, "status", "Path Mode")
+        path.assignProperty(self.pathButton, "text", "Stop")
+        path.assignProperty(self.followButton, "text", "Follow Mode")
+        path.assignProperty(self.circleButton, "text", "Circle Mode")
+        path.assignProperty(self.recordButton, "text", "Record Mode")
+        path.assignProperty(self.pathButton, "enabled", True)
+        path.assignProperty(self.emergencyButton, "enabled", True)
+        path.assignProperty(self.landButton, "enabled", True)
+        path.assignProperty(self.followButton, "enabled", False)
+        path.assignProperty(self.liftButton, "enabled", False)
+        path.assignProperty(self.circleButton, "enabled", False)
+        path.assignProperty(self.recordButton, "enabled", False)
+        path.entered.connect(self._flight_mode_path_entered)
+
+        # FOLLOW
+        follow = QState(parent_state)
+        follow.assignProperty(self, "status", "Follow Mode")
+        follow.assignProperty(self.pathButton, "text", "Path Mode")
+        follow.assignProperty(self.followButton, "text", "Stop")
+        follow.assignProperty(self.circleButton, "text", "Circle Mode")
+        follow.assignProperty(self.recordButton, "text", "Record Mode")
+        follow.assignProperty(self.pathButton, "enabled", False)
+        follow.assignProperty(self.emergencyButton, "enabled", True)
+        follow.assignProperty(self.landButton, "enabled", True)
+        follow.assignProperty(self.followButton, "enabled", False)
+        follow.assignProperty(self.liftButton, "enabled", False)
+        follow.assignProperty(self.circleButton, "enabled", False)
+        follow.assignProperty(self.recordButton, "enabled", False)
+        follow.entered.connect(self._flight_mode_follow_entered)
+
+        # LIFT
+        lift = QState(parent_state)
+        lift.assignProperty(self, "status", "Lifting...")
+        lift.assignProperty(self.pathButton, "enabled", False)
+        lift.assignProperty(self.emergencyButton, "enabled", True)
+        lift.assignProperty(self.landButton, "enabled", True)
+        lift.assignProperty(self.followButton, "enabled", False)
+        lift.assignProperty(self.liftButton, "enabled", False)
+        lift.assignProperty(self.circleButton, "enabled", False)
+        lift.assignProperty(self.recordButton, "enabled", False)
+        lift.entered.connect(self._flight_mode_lift_entered)
+
+        # LAND
+        land = QState(parent_state)
+        land.assignProperty(self, "status", "Landing...")
+        land.assignProperty(self.pathButton, "enabled", False)
+        land.assignProperty(self.emergencyButton, "enabled", True)
+        land.assignProperty(self.landButton, "enabled", False)
+        land.assignProperty(self.followButton, "enabled", False)
+        land.assignProperty(self.liftButton, "enabled", False)
+        land.assignProperty(self.circleButton, "enabled", False)
+        land.assignProperty(self.recordButton, "enabled", False)
+        land.entered.connect(self._flight_mode_land_entered)
+
+        # CIRCLE
+        circle = QState(parent_state)
+        circle.assignProperty(self, "status", "Circle Mode")
+        circle.assignProperty(self.pathButton, "text", "Path Mode")
+        circle.assignProperty(self.followButton, "text", "Follow Mode")
+        circle.assignProperty(self.circleButton, "text", "Stop")
+        circle.assignProperty(self.recordButton, "text", "Record Mode")
+        circle.assignProperty(self.pathButton, "enabled", False)
+        circle.assignProperty(self.emergencyButton, "enabled", True)
+        circle.assignProperty(self.landButton, "enabled", True)
+        circle.assignProperty(self.followButton, "enabled", False)
+        circle.assignProperty(self.liftButton, "enabled", False)
+        circle.assignProperty(self.circleButton, "enabled", True)
+        circle.assignProperty(self.recordButton, "enabled", False)
+        circle.entered.connect(self._flight_mode_circle_entered)
+
+        # RECORD
+        record = QState(parent_state)
+        record.assignProperty(self, "status", "Record Mode")
+        record.assignProperty(self.pathButton, "text", "Path Mode")
+        record.assignProperty(self.followButton, "text", "Follow Mode")
+        record.assignProperty(self.circleButton, "text", "Circle Mode")
+        record.assignProperty(self.recordButton, "text", "Stop")
+        record.assignProperty(self.pathButton, "enabled", False)
+        record.assignProperty(self.emergencyButton, "enabled", True)
+        record.assignProperty(self.landButton, "enabled", False)
+        record.assignProperty(self.followButton, "enabled", False)
+        record.assignProperty(self.liftButton, "enabled", False)
+        record.assignProperty(self.circleButton, "enabled", False)
+        record.assignProperty(self.recordButton, "enabled", True)
+        record.entered.connect(self._flight_mode_record_entered)
+
+        def add_transition(mode, child_state, parent):
+            transition = FlightModeTransition(mode)
+            transition.setTargetState(child_state)
+            parent.addTransition(transition)
+
+        add_transition(FlightModeStates.LAND, land, parent_state)
+        add_transition(FlightModeStates.LIFT, lift, parent_state)
+        add_transition(FlightModeStates.FOLLOW, follow, parent_state)
+        add_transition(FlightModeStates.PATH, path, parent_state)
+        add_transition(FlightModeStates.HOVERING, hovering, parent_state)
+        add_transition(FlightModeStates.GROUNDED, grounded, parent_state)
+        add_transition(FlightModeStates.DISCONNECTED, disconnected,
+                       parent_state)
+        add_transition(FlightModeStates.CIRCLE, circle, parent_state)
+        add_transition(FlightModeStates.RECORD, record, parent_state)
+
+        parent_state.setInitialState(disconnected)
+        self._machine.addState(parent_state)
+        self._machine.setInitialState(parent_state)
+        self._machine.start()
+
+    def _is_discovering(self, discovering):
+        if discovering:
+            self.qtmIpBox.clear()
+        self.discoverQTM.setEnabled(not discovering)
+
+    def _qtm_discovered(self, info, ip):
+        self.qtmIpBox.addItem("{} {}".format(ip, info))
+
+    @pyqtSlot(str)
+    def _update_status(self, status):
+        self.statusLabel.setText("Status: {}".format(status))
+
+    @pyqtSlot(str)
+    def _update_cf_status(self, status):
+        self.cfStatusLabel.setText(status)
+
+    @pyqtSlot(str)
+    def _update_qtm_status(self, status):
+        self.qtmStatusLabel.setText(status)
+
+    @pyqtSlot(str)
+    def quad_changed(self, quad):
+        self.quadName = quad
+
+    @pyqtSlot(str)
+    def stick_changed(self, stick):
+        self.stickName = stick
+
+    # Properties
+
+    @pyqtProperty(str, notify=statusChanged)
+    def status(self):
+        return self._status
+
+    @status.setter
+    def status(self, value):
+        if value != self._status:
+            self._status = value
+            self.statusChanged.emit(value)
+
+    @pyqtProperty(str, notify=qtmStatusChanged)
+    def qtmStatus(self):
+        return self._qtm_status
+
+    @qtmStatus.setter
+    def qtmStatus(self, value):
+        if value != self._qtm_status:
+            self._qtm_status = value
+            self.qtmStatusChanged.emit(value)
+
+    @pyqtProperty(str, notify=cfStatusChanged)
+    def cfStatus(self):
+        return self._qtm_status
+
+    @cfStatus.setter
+    def cfStatus(self, value):
+        if value != self._cf_status:
+            self._cf_status = value
+            self.cfStatusChanged.emit(value)
+
+    def _select_flight_path_row(self, row):
+        self.flightPathDataTable.selectRow(row)
+
+    def _set_flight_path_model(self, model):
+        self.flightPathDataTable.setModel(model)
+
+    def _add_path_selector_item(self, item):
+        self.pathSelector.addItem(item)
+
+    def _set_path_selector_index(self, index):
+        self.pathSelector.setCurrentIndex(index)
+
+    def path_changed(self):
+
+        if self.flight_mode == FlightModeStates.PATH:
+            self.switch_flight_mode(FlightModeStates.HOVERING)
+            time.sleep(0.1)
+
+        # Flight path ui table setup
+        self.model = QStandardItemModel(10, 4)
+        self.model.setHorizontalHeaderItem(0, QStandardItem('X (m)'))
+        self.model.setHorizontalHeaderItem(1, QStandardItem('Y (m)'))
+        self.model.setHorizontalHeaderItem(2, QStandardItem('Z (m)'))
+        self.model.setHorizontalHeaderItem(3, QStandardItem('Yaw (deg)'))
+
+        # Populate the table with data
+        if (len(self.flight_paths) == 0):
+            return
+        current = self.flight_paths[self.pathSelector.currentIndex()]
+        for i in range(1, len(current)):
+            for j in range(0, 4):
+                self.model.setItem(i - 1, j,
+                                   QStandardItem(str(current[i][j])))
+        self._flight_path_set_model.emit(self.model)
+        Config().set("flight_paths", self.flight_paths)
+
+    def remove_current_path(self):
+
+        if self.flight_mode == FlightModeStates.PATH:
+            self.switch_flight_mode(FlightModeStates.HOVERING)
+            time.sleep(0.1)
+        if len(self.flight_paths) == 0:
+            return
+
+        current_index = self.pathSelector.currentIndex()
+        answer = QMessageBox.question(
+            self, "CFClient: Qualisystab", "Delete the flightpath: {}?".format(
+                self.flight_paths[current_index][0]),
+            QMessageBox.Yes | QMessageBox.No)
+
+        if answer == QMessageBox.Yes:
+            self.flight_paths.pop(current_index)
+            self.pathSelector.clear()
+
+            for j in range(len(self.flight_paths)):
+                self.pathSelector.addItem(self.flight_paths[j][0])
+
+            if current_index == 0:
+                self.pathSelector.setCurrentIndex(0)
+            else:
+                self.pathSelector.setCurrentIndex(current_index - 1)
+
+            self.path_changed()
+
+    def set_lift_mode(self):
+        self.switch_flight_mode(FlightModeStates.LIFT)
+
+    def set_land_mode(self):
+        self.switch_flight_mode(FlightModeStates.LAND)
+
+    def set_circle_mode(self):
+
+        # Toggle circle mode on and off
+
+        if self.flight_mode == FlightModeStates.CIRCLE:
+            self.switch_flight_mode(FlightModeStates.HOVERING)
+
+        else:
+            try:
+                self.position_hold_timelimit = float(
+                    self.posHoldCircleBox.text())
+                self.circle_radius = float(self.radiusBox.text())
+                self.circle_resolution = float(self.resolutionBox.text())
+                self.circle_pos_threshold = (2 * self.circle_radius * round(
+                    math.sin(math.radians(
+                        (self.circle_resolution / 2))), 4)) * 2
+                logger.info(self.circle_pos_threshold)
+            except ValueError as err:
+                self.status = ("illegal character used in circle"
+                               " settings: {}").format(str(err))
+                logger.info(self.status)
+                return
+
+            self.switch_flight_mode(FlightModeStates.CIRCLE)
+
+    def set_record_mode(self):
+        # Toggle record mode on and off
+
+        if self.flight_mode == FlightModeStates.RECORD:
+            # Cancel the recording
+            self.recording = False
+            self.switch_flight_mode(FlightModeStates.GROUNDED)
+            self.land_for_recording = False
+        elif self.flight_mode != FlightModeStates.GROUNDED:
+            # If the cf is flying, start by landing
+            self.land_for_recording = True
+            self.switch_flight_mode(FlightModeStates.LAND)
+        else:
+            self.switch_flight_mode(FlightModeStates.RECORD)
+
+    def set_follow_mode(self):
+        # Toggle follow mode on and off
+
+        if self.flight_mode == FlightModeStates.FOLLOW:
+            self.switch_flight_mode(FlightModeStates.HOVERING)
+        else:
+            self.switch_flight_mode(FlightModeStates.FOLLOW)
+
+    def set_path_mode(self):
+        logger.info(self.model.item(0, 0))
+        # Toggle path mode on and off
+
+        # Path mode on, return to hovering
+        if self.flight_mode == FlightModeStates.PATH:
+            self.switch_flight_mode(FlightModeStates.HOVERING)
+
+        elif self.model.item(0, 0) is None:
+            self.status = "missing Flight Plan"
+            return
+        # Path mode off, read data from UI table and start path mode
+        else:
+
+            try:
+                self.position_hold_timelimit = float(
+                    self.posHoldPathBox.text())
+            except ValueError as err:
+                self.status = ("illegal character used in path"
+                               " settings: {}").format(str(err))
+                logger.info(self.status)
+                return
+
+            # Get the flightpath from the GUI table
+            x, y = 0, 0
+            temp = self.model.item(x, y)
+            reading_data = True
+            list = ''
+            while reading_data:
+                try:
+                    element = str(temp.text())
+
+                    if element != "":
+                        list += temp.text()
+                        # a "," gets added after the last element,
+                        # remove that later for neatness
+                        list += ','
+                        try:
+                            float(element)
+                        except ValueError:
+                            self._flight_path_select_row.emit(y)
+                            self.status = ("Value at cell x:{} y:{} "
+                                           "must be a number").format(x, y)
+                            logger.info(self.status)
+                            break
+
+                    x += 1
+                    if x % 4 == 0:
+                        x = 0
+                        y += 1
+                        # list += temp_position
+                        # temp_position = []
+                    temp = self.model.item(y, x)
+
+                except Exception as err:
+                    reading_data = False
+                    # remove the last "," element
+                    list = list[:(len(list) - 1)]
+                    list = list.split(',')
+                    list = [float(i) for i in list]
+                    if (len(list) % 4) != 0:
+                        self.status = ("Missing value to create a valid"
+                                       " flight path")
+                        logger.info(self.status)
+                        break
+                    list = [list[i:i + 4] for i in range(0, len(list), 4)]
+                    list.insert(
+                        0,
+                        self.flight_paths[self.pathSelector.currentIndex()][0])
+                    self.flight_paths[self.pathSelector.currentIndex()] = list
+                    Config().set("flight_paths", self.flight_paths)
+                    self.switch_flight_mode(FlightModeStates.PATH)
+
+    def set_kill_engine(self):
+        self.send_setpoint(self.scf, Position(0, 0, 0))
+        self.switch_flight_mode(FlightModeStates.GROUNDED)
+        logger.info('Stop button pressed, kill engines')
+
+    def establish_qtm_connection(self):
+        if self.qtmIpBox.count() == 0 and self.qtmIpBox.currentText() == "":
+            return
+
+        if self._qtm_connection is None:
+            try:
+                ip = self.qtmIpBox.currentText().split(" ")[0]
+            except Exception as e:
+                logger.error("Incorrect entry: %s", e)
+                return
+
+            self.connectQtmButton.setEnabled(False)
+            start_async_task(self.qtm_connect(ip))
+
+        else:
+            self._qtm_connection.disconnect()
+            self._qtm_connection = None
+
+    async def qtm_connect(self, ip):
+
+        connection = await qtm.connect(
+            ip,
+            on_event=self.on_qtm_event,
+            on_disconnect=lambda reason: start_async_task(
+                self.on_qtm_disconnect(reason)))
+
+        if connection is None:
+            start_async_task(self.on_qtm_disconnect("Failed to connect"))
+            return
+
+        self._qtm_connection = connection
+        await self.setup_qtm_connection()
+
+    def setup_6dof_comboboxes(self):
+        quadName = self.quadName
+        stickName = self.stickName
+
+        self.quadBox.clear()
+        self.stickBox.clear()
+        for label in self.qtm_6DoF_labels:
+            self.quadBox.addItem(label)
+            self.stickBox.addItem(label)
+
+        if quadName in self.qtm_6DoF_labels:
+            self.quadBox.setCurrentIndex(
+                self.qtm_6DoF_labels.index(quadName))
+
+        if stickName in self.qtm_6DoF_labels:
+            self.stickBox.setCurrentIndex(
+                self.qtm_6DoF_labels.index(stickName))
+
+    async def setup_qtm_connection(self):
+        self.connectQtmButton.setEnabled(True)
+        self.connectQtmButton.setText('Disconnect QTM')
+        self.qtmStatus = ': connected : Waiting QTM to start sending data'
+
+        try:
+            result = await self._qtm_connection.get_parameters(
+                parameters=['6d'])
+
+            # Parse the returned xml
+            xml = ET.fromstring(result)
+            self.qtm_6DoF_labels = [label.text for label in xml.iter('Name')]
+
+            # Make all names lowercase
+            self.qtm_6DoF_labels = [x.lower() for x in self.qtm_6DoF_labels]
+            logger.info('6Dof bodies active in qtm: {}'.format(
+                self.qtm_6DoF_labels))
+
+            self.setup_6dof_comboboxes()
+
+            # Gui
+            self.qtmStatus = ': connected'
+            self.qtmCfPositionBox.setEnabled(True)
+            self.qtmWandPositionBox.setEnabled(True)
+            self.discoverQTM.setEnabled(False)
+            self.qtmIpBox.setEnabled(False)
+
+            if self.cf_ready_to_fly:
+                self.switch_flight_mode(FlightModeStates.GROUNDED)
+
+            self._ui_update_timer.start(200)
+
+            # Make sure this is the last thing done with the qtm_connection
+            # (due to qtmRTProtocol structure)
+            await self._qtm_connection.stream_frames(
+                components=['6deuler', '3d'], on_packet=self.on_packet)
+
+        except Exception as err:
+            logger.info(err)
+
+    async def on_qtm_disconnect(self, reason):
+        """Callback when QTM has been disconnected"""
+
+        self._ui_update_timer.stop()
+
+        self._qtm_connection = None
+        logger.info(reason)
+
+        # Gui
+        self.qtmCfPositionBox.setEnabled(False)
+        self.qtmWandPositionBox.setEnabled(False)
+        self.discoverQTM.setEnabled(True)
+        self.qtmIpBox.setEnabled(True)
+        self.connectQtmButton.setEnabled(True)
+        self.connectQtmButton.setText('Connect QTM')
+        self.qtmStatus = ': not connected : {}'.format(
+            reason if reason is not None else ''
+            )
+
+        self.switch_flight_mode(FlightModeStates.DISCONNECTED)
+
+    def on_qtm_event(self, event):
+        logger.info(event)
+        if event == qtm.QRTEvent.EventRTfromFileStarted:
+            self.qtmStatus = ': connected'
+            self.qtmCfPositionBox.setEnabled(True)
+            self.qtmWandPositionBox.setEnabled(True)
+
+        elif event == qtm.QRTEvent.EventRTfromFileStopped:
+            self.qtmStatus = ': connected : Waiting QTM to start sending data'
+            self.qtmCfPositionBox.setEnabled(False)
+            self.qtmWandPositionBox.setEnabled(False)
+
+    def on_packet(self, packet):
+        # Callback when QTM sends a 'packet' of the requested data,
+        # one every tracked frame.
+        # The speed depends on QTM settings
+        header, bodies = packet.get_6d_euler()
+
+        # Cf not created yet or no packet received due to various reasons...
+        # Wait for the two asynchronous calls in 'setup connection'
+        # to return with data
+        if bodies is None or self.qtm_6DoF_labels is None:
+            return
+
+        try:
+            temp_cf_pos = bodies[self.qtm_6DoF_labels.index(self.quadName)]
+            # QTM returns in mm in the order x, y, z, the Crazyflie api need
+            # data in meters, divide by thousand
+            # QTM returns euler rotations in deg in the order
+            # yaw, pitch, roll, not Qualisys Standard!
+            self.cf_pos = Position(
+                temp_cf_pos[0][0] / 1000,
+                temp_cf_pos[0][1] / 1000,
+                temp_cf_pos[0][2] / 1000,
+                roll=temp_cf_pos[1][2],
+                pitch=temp_cf_pos[1][1],
+                yaw=temp_cf_pos[1][0])
+
+        except ValueError as err:
+            self.qtmStatus = ' : connected : No 6DoF body found'
+
+        try:
+            temp_wand_pos = bodies[self.qtm_6DoF_labels.index(self.stickName)]
+            self.wand_pos = Position(
+                temp_wand_pos[0][0] / 1000,
+                temp_wand_pos[0][1] / 1000,
+                temp_wand_pos[0][2] / 1000,
+                roll=temp_wand_pos[1][2],
+                pitch=temp_wand_pos[1][1],
+                yaw=temp_wand_pos[1][0])
+
+        except ValueError as err:
+            self.qtmStatus = ' : connected : No 6DoF body found'
+
+        if self.scf is not None and self.cf_pos.is_valid():
+            # If a scf (syncronous Crazyflie) exists and the position is valid
+            # Feed the current position of the cf back to the cf to
+            # allow for self correction
+            self.scf.cf.extpos.send_extpos(self.cf_pos.x, self.cf_pos.y,
+                                           self.cf_pos.z)
+
+    def _update_ui(self):
+        # Update the data in the GUI
+        self.qualisysX.setText(("%0.4f" % self.cf_pos.x))
+        self.qualisysY.setText(("%0.4f" % self.cf_pos.y))
+        self.qualisysZ.setText(("%0.4f" % self.cf_pos.z))
+
+        self.qualisysRoll.setText(("%0.2f" % self.cf_pos.roll))
+        self.qualisysPitch.setText(("%0.2f" % self.cf_pos.pitch))
+        self.qualisysYaw.setText(("%0.2f" % self.cf_pos.yaw))
+
+        self.qualisysWandX.setText(("%0.4f" % self.wand_pos.x))
+        self.qualisysWandY.setText(("%0.4f" % self.wand_pos.y))
+        self.qualisysWandZ.setText(("%0.4f" % self.wand_pos.z))
+
+        self.qualisysWandRoll.setText(("%0.2f" % self.wand_pos.roll))
+        self.qualisysWandPitch.setText(("%0.2f" % self.wand_pos.pitch))
+        self.qualisysWandYaw.setText(("%0.2f" % self.wand_pos.yaw))
+
+    def _flight_mode_land_entered(self):
+        self.current_goal_pos = self.valid_cf_pos
+        logger.info('Trying to land at: x: {} y: {}'.format(
+            self.current_goal_pos.x, self.current_goal_pos.y))
+        self.land_rate = 1
+        self._event.set()
+
+    def _flight_mode_path_entered(self):
+        self.path_index = 1
+
+        current = self.flight_paths[self.pathSelector.
+                                    currentIndex()]
+        self.current_goal_pos = Position(
+            current[self.path_index][0],
+            current[self.path_index][1],
+            current[self.path_index][2],
+            yaw=current[self.path_index][3])
+        logger.info('Setting position {}'.format(
+            self.current_goal_pos))
+        self._flight_path_select_row.emit(self.path_index - 1)
+        self._event.set()
+
+    def _flight_mode_circle_entered(self):
+        self.current_goal_pos = Position(
+            round(math.cos(math.radians(self.circle_angle)),
+                  8) * self.circle_radius,
+            round(math.sin(math.radians(self.circle_angle)), 8)
+            * self.circle_radius,
+            self.circle_height,
+            yaw=self.circle_angle)
+
+        logger.info('Setting position {}'.format(
+            self.current_goal_pos))
+        self._event.set()
+
+    def _flight_mode_follow_entered(self):
+        self.last_valid_wand_pos = Position(0, 0, 1)
+        self._event.set()
+
+    def _flight_mode_record_entered(self):
+        self.new_path = []
+        self._event.set()
+
+    def _flight_mode_lift_entered(self):
+        self.current_goal_pos = self.valid_cf_pos
+        logger.info('Trying to lift at: {}'.format(
+            self.current_goal_pos))
+        self._event.set()
+
+    def _flight_mode_hovering_entered(self):
+        self.current_goal_pos = self.valid_cf_pos
+        logger.info('Hovering at: {}'.format(
+            self.current_goal_pos))
+        self._event.set()
+
+    def _flight_mode_grounded_entered(self):
+        self._event.set()
+
+    def _flight_mode_disconnected_entered(self):
+        self._event.set()
+
+    def flight_controller(self):
+        try:
+            _scf = SyncCrazyflie("radio://0/{}".format(self.uri),
+                                 self._helper.cf)
+
+            # init scf
+            self.scf = _scf
+            cf = self.scf.cf
+            cf.param.set_value('stabilizer.estimator', '2')
+            self.reset_estimator(self.scf)
+
+            cf.param.set_value('flightmode.posSet', '1')
+
+            time.sleep(0.1)
+
+            # The threshold for how many frames without tracking
+            # is allowed before the cf's motors are stopped
+            lost_tracking_threshold = 100
+            frames_without_tracking = 0
+            position_hold_timer = 0
+            self.circle_angle = 0.0
+
+            # The main flight control loop, the behaviour
+            # is controlled by the state of "FlightMode"
+            while self.flying_enabled:
+
+                # Check that the position is valid and store it
+                if self.cf_pos.is_valid():
+                    self.valid_cf_pos = self.cf_pos
+                    frames_without_tracking = 0
+                else:
+                    # if it isn't, count number of frames
+                    frames_without_tracking += 1
+
+                    if frames_without_tracking > lost_tracking_threshold:
+                        self.switch_flight_mode(FlightModeStates.GROUNDED)
+                        self.status = "Tracking lost, turning off motors"
+                        logger.info(self.status)
+
+                # If the cf is upside down, kill the motors
+                if self.flight_mode != FlightModeStates.GROUNDED and (
+                        self.valid_cf_pos.roll > 120
+                        or self.valid_cf_pos.roll < -120):
+                    self.switch_flight_mode(FlightModeStates.GROUNDED)
+                    self.status = "Status: Upside down, turning off motors"
+                    logger.info(self.status)
+
+                # Switch on the FlightModeState and take actions accordingly
+                # Wait so that any on state change actions are completed
+                self._event.wait()
+
+                if self.flight_mode == FlightModeStates.LAND:
+
+                    self.send_setpoint(
+                        self.scf,
+                        Position(
+                            self.current_goal_pos.x,
+                            self.current_goal_pos.y,
+                            (self.current_goal_pos.z / self.land_rate),
+                            yaw=0))
+                    # Check if the cf has reached the  position,
+                    # if it has set a new position
+
+                    if self.valid_cf_pos.distance_to(
+                            Position(self.current_goal_pos.x,
+                                     self.current_goal_pos.y,
+                                     (self.current_goal_pos.z / self.land_rate
+                                      ))) < self.path_pos_threshold:
+                        self.land_rate *= 1.1
+
+                    if self.land_rate > 1000:
+                        self.send_setpoint(self.scf, Position(0, 0, 0))
+                        if self.land_for_recording:
+                            # Return the control to the recording mode
+                            # after landing
+                            mode = FlightModeStates.RECORD
+                            self.land_for_recording = False
+                        else:
+                            # Regular landing
+                            mode = FlightModeStates.GROUNDED
+                        self.switch_flight_mode(mode)
+
+                elif self.flight_mode == FlightModeStates.PATH:
+
+                    self.send_setpoint(self.scf, self.current_goal_pos)
+                    # Check if the cf has reached the goal position,
+                    # if it has set a new goal position
+                    if self.valid_cf_pos.distance_to(
+                            self.current_goal_pos) < self.path_pos_threshold:
+
+                        if position_hold_timer > self.position_hold_timelimit:
+
+                            current = self.flight_paths[self.pathSelector.
+                                                        currentIndex()]
+
+                            self.path_index += 1
+                            if self.path_index == len(current):
+                                self.path_index = 1
+                            position_hold_timer = 0
+
+                            self.current_goal_pos = Position(
+                                current[self.path_index][0],
+                                current[self.path_index][1],
+                                current[self.path_index][2],
+                                yaw=current[self.path_index][3])
+
+                            logger.info('Setting position {}'.format(
+                                self.current_goal_pos))
+                            self._flight_path_select_row.emit(
+                                self.path_index - 1)
+                        elif position_hold_timer == 0:
+
+                            time_of_pos_reach = time.time()
+                            # Add som time just to get going,
+                            # it will be overwritten in the next step.
+                            # Setting it higher than the limit
+                            # will break the code.
+                            position_hold_timer = 0.0001
+                        else:
+                            position_hold_timer = time.time(
+                            ) - time_of_pos_reach
+
+                elif self.flight_mode == FlightModeStates.CIRCLE:
+                    self.send_setpoint(self.scf, self.current_goal_pos)
+
+                    # Check if the cf has reached the goal position,
+                    # if it has set a new goal position
+                    if self.valid_cf_pos.distance_to(
+                            self.current_goal_pos) < self.circle_pos_threshold:
+
+                        if position_hold_timer >= self.position_hold_timelimit:
+
+                            position_hold_timer = 0
+
+                            # increment the angle
+                            self.circle_angle = ((self.circle_angle +
+                                                  self.circle_resolution)
+                                                 % 360)
+
+                            # Calculate the next position in
+                            # the circle to fly to
+                            self.current_goal_pos = Position(
+                                round(
+                                    math.cos(math.radians(self.circle_angle)),
+                                    4) * self.circle_radius,
+                                round(
+                                    math.sin(math.radians(self.circle_angle)),
+                                    4) * self.circle_radius,
+                                self.circle_height,
+                                yaw=self.circle_angle)
+
+                            logger.info('Setting position {}'.format(
+                                self.current_goal_pos))
+
+                        elif position_hold_timer == 0:
+
+                            time_of_pos_reach = time.time()
+                            # Add som time just to get going, it will be
+                            # overwritten in the next step.
+                            # Setting it higher than the imit will
+                            # break the code.
+                            position_hold_timer = 0.0001
+                        else:
+                            position_hold_timer = time.time(
+                            ) - time_of_pos_reach
+
+                elif self.flight_mode == FlightModeStates.FOLLOW:
+
+                    if self.wand_pos.is_valid():
+                        self.last_valid_wand_pos = self.wand_pos
+
+                        # Fit the angle of the wand in the interval 0-4
+                        self.length_from_wand = (2 * (
+                            (self.wand_pos.roll + 90) / 180) - 1) + 2
+                        self.send_setpoint(
+                            self.scf,
+                            Position(
+                                self.wand_pos.x + round(
+                                    math.cos(math.radians(self.wand_pos.yaw)),
+                                    4) * self.length_from_wand,
+                                self.wand_pos.y + round(
+                                    math.sin(math.radians(self.wand_pos.yaw)),
+                                    4) * self.length_from_wand,
+                                ((self.wand_pos.z + round(
+                                    math.sin(
+                                        math.radians(self.wand_pos.pitch)), 4)
+                                  * self.length_from_wand) if
+                                 ((self.wand_pos.z + round(
+                                     math.sin(
+                                         math.radians(self.wand_pos.pitch)), 4)
+                                   * self.length_from_wand) > 0) else 0)))
+                    else:
+                        self.length_from_wand = (2 * (
+                            (self.last_valid_wand_pos.roll + 90) / 180) -
+                                                 1) + 2
+                        self.send_setpoint(
+                            self.scf,
+                            Position(
+                                self.last_valid_wand_pos.x + round(
+                                    math.cos(
+                                        math.radians(
+                                            self.last_valid_wand_pos.yaw)),
+                                    4) * self.length_from_wand,
+                                self.last_valid_wand_pos.y + round(
+                                    math.sin(
+                                        math.radians(
+                                            self.last_valid_wand_pos.yaw)),
+                                    4) * self.length_from_wand,
+                                int(self.last_valid_wand_pos.z + round(
+                                    math.sin(
+                                        math.radians(self.last_valid_wand_pos.
+                                                     pitch)), 4) *
+                                    self.length_from_wand)))
+
+                elif self.flight_mode == FlightModeStates.LIFT:
+
+                    self.send_setpoint(
+                        self.scf,
+                        Position(self.current_goal_pos.x,
+                                 self.current_goal_pos.y, 1))
+
+                    if self.valid_cf_pos.distance_to(
+                            Position(self.current_goal_pos.x,
+                                     self.current_goal_pos.y, 1)) < 0.05:
+                        # Wait for hte crazyflie to reach the goal
+                        self.switch_flight_mode(FlightModeStates.HOVERING)
+
+                elif self.flight_mode == FlightModeStates.HOVERING:
+                    self.send_setpoint(self.scf, self.current_goal_pos)
+
+                elif self.flight_mode == FlightModeStates.RECORD:
+
+                    if self.valid_cf_pos.z > 1.0 and not self.recording:
+                        # Start recording when the cf is lifted
+                        self.recording = True
+                        # Start the timer thread
+                        self.save_current_position()
+                        # Gui
+                        self.status = "Recording Flightpath"
+                        logger.info(self.status)
+
+                    elif self.valid_cf_pos.z < 0.03 and self.recording:
+                        # Stop the recording when the cf is put on
+                        # the ground again
+                        logger.info("Recording stopped")
+                        self.recording = False
+
+                        # Remove the last bit (1s) of the recording,
+                        # containing setting the cf down
+                        for self.path_index in range(20):
+                            self.new_path.pop()
+
+                        # Add the new path to list and Gui
+                        now = datetime.datetime.fromtimestamp(time.time())
+
+                        new_name = ("Recording {}/{}/{} {}:{}".format(
+                            now.year - 2000, now.month
+                            if now.month > 9 else "0{}".format(now.month),
+                            now.day if now.day > 9 else "0{}".format(now.day),
+                            now.hour if now.hour > 9 else "0{}".format(
+                                now.hour), now.minute
+                            if now.minute > 9 else "0{}".format(now.minute)))
+
+                        self.new_path.insert(0, new_name)
+                        self.flight_paths.append(self.new_path)
+                        self._path_selector_add_item.emit(new_name)
+
+                        # Select the new path
+                        self._path_selector_set_index.emit(
+                            len(self.flight_paths) - 1)
+                        self.path_changed()
+                        Config().set("flight_paths", self.flight_paths)
+
+                        # Wait while the operator moves away
+                        self.status = "Replay in 3s"
+                        time.sleep(1)
+                        self.status = "Replay in 2s"
+                        time.sleep(1)
+                        self.status = "Replay in 1s"
+                        time.sleep(1)
+                        # Switch to path mode and replay the recording
+                        self.switch_flight_mode(FlightModeStates.PATH)
+
+                elif self.flight_mode == FlightModeStates.GROUNDED:
+                    pass  # If gounded, the control is switched back to gamepad
+
+                time.sleep(0.001)
+
+        except Exception as err:
+            logger.error(err)
+            self.cfStatus = str(err)
+
+    def save_current_position(self):
+        if self.recording:
+            # Restart the timer
+            threading.Timer(0.05, self.save_current_position).start()
+            # Save the current position
+            self.new_path.append([
+                self.valid_cf_pos.x, self.valid_cf_pos.y,
+                self.valid_cf_pos.z, self.valid_cf_pos.yaw
+            ])
+
+    def _connected(self, link_uri):
+        """Callback when the Crazyflie has been connected"""
+
+        if not self.flying_enabled:
+            self.flying_enabled = True
+            self.cfStatus = ": connecting..."
+            t = threading.Thread(target=self.flight_controller)
+            t.start()
+
+        self.uri = link_uri
+        logger.debug("Crazyflie connected to {}".format(self.uri))
+
+        # Gui
+        self.cfStatus = ': connected'
+
+    def _disconnected(self, link_uri):
+        """Callback for when the Crazyflie has been disconnected"""
+
+        logger.info("Crazyflie disconnected from {}".format(link_uri))
+        self.cfStatus = ': not connected'
+        self.flying_enabled = False
+        self.cf_ready_to_fly = False
+
+    def _param_updated(self, name, value):
+        """Callback when the registered parameter get's updated"""
+
+        logger.debug("Updated {0} to {1}".format(name, value))
+
+    def _log_data_received(self, timestamp, data, log_conf):
+        """Callback when the log layer receives new data"""
+
+        logger.debug("{0}:{1}:{2}".format(timestamp, log_conf.name, data))
+
+    def _logging_error(self, log_conf, msg):
+        """Callback from the log layer when an error occurs"""
+
+        QMessageBox.about(
+            self, "Example error", "Error when using log config"
+            " [{0}]: {1}".format(log_conf.name, msg))
+
+    def wait_for_position_estimator(self, scf):
+        logger.info('Waiting for estimator to find stable position...')
+
+        self.cfStatus = (
+            'Waiting for estimator to find stable position... '
+            '(QTM needs to be connected and providing data)'
+        )
+
+        log_config = LogConfig(name='Kalman Variance', period_in_ms=500)
+        log_config.add_variable('kalman.varPX', 'float')
+        log_config.add_variable('kalman.varPY', 'float')
+        log_config.add_variable('kalman.varPZ', 'float')
+
+        var_y_history = [1000] * 10
+        var_x_history = [1000] * 10
+        var_z_history = [1000] * 10
+
+        threshold = 0.001
+
+        with SyncLogger(scf, log_config) as log:
+            for log_entry in log:
+                data = log_entry[1]
+
+                var_x_history.append(data['kalman.varPX'])
+                var_x_history.pop(0)
+                var_y_history.append(data['kalman.varPY'])
+                var_y_history.pop(0)
+                var_z_history.append(data['kalman.varPZ'])
+                var_z_history.pop(0)
+
+                min_x = min(var_x_history)
+                max_x = max(var_x_history)
+                min_y = min(var_y_history)
+                max_y = max(var_y_history)
+                min_z = min(var_z_history)
+                max_z = max(var_z_history)
+
+                # print("{} {} {}".
+                # format(max_x - min_x, max_y - min_y, max_z - min_z))
+
+                if (max_x - min_x) < threshold and (
+                        max_y - min_y) < threshold and (
+                            max_z - min_z) < threshold:
+                    logger.info(
+                        "Position found with error in, x: {}, y: {}, z: {}".
+                        format(max_x - min_x, max_y - min_y, max_z - min_z))
+
+                    self.cfStatus = ": connected"
+
+                    self.switch_flight_mode(FlightModeStates.GROUNDED)
+                    self.cf_ready_to_fly = True
+
+                    break
+
+    def reset_estimator(self, scf):
+        # Reset the kalman filter
+
+        cf = scf.cf
+        cf.param.set_value('kalman.resetEstimation', '1')
+        time.sleep(0.1)
+        cf.param.set_value('kalman.resetEstimation', '0')
+
+        self.wait_for_position_estimator(cf)
+
+    def switch_flight_mode(self, mode):
+        # Handles the behaviour of switching between flight modes
+
+        self.flight_mode = mode
+
+        # Handle client input control.
+        # Disable gamepad input if we are not grounded
+        if self.flight_mode in [
+                FlightModeStates.GROUNDED, FlightModeStates.DISCONNECTED,
+                FlightModeStates.RECORD
+        ]:
+            self._helper.mainUI.disable_input(False)
+        else:
+            self._helper.mainUI.disable_input(True)
+
+        self._event.clear()
+        # Threadsafe call
+        self._machine.postEvent(FlightModeEvent(mode))
+
+        logger.info('Switching Flight Mode to: %s', mode)
+
+    def send_setpoint(self, scf_, pos):
+        # Wraps the send command to the crazyflie
+
+        # The 'send_setpoint' function strangely takes the
+        # arguments in the order (Y, X, Yaw, Z)
+        scf_.cf.commander.send_setpoint(pos.y, pos.x, 0, int(pos.z * 1000))
+        pass
+
+
+class Position:
+    def __init__(self, x, y, z, roll=0.0, pitch=0.0, yaw=0.0):
+        self.x = x
+        self.y = y
+        self.z = z
+        self.roll = roll
+        self.pitch = pitch
+        self.yaw = yaw
+
+    def distance_to(self, other_point):
+        return math.sqrt(
+            math.pow(self.x - other_point.x, 2) +
+            math.pow(self.y - other_point.y, 2) +
+            math.pow(self.z - other_point.z, 2))
+
+    def is_valid(self):
+        # Checking if the respective values are nan
+        return self.x == self.x and self.y == self.y and self.z == self.z
+
+    def __str__(self):
+        return "x: {} y: {} z: {} Roll: {} Pitch: {} Yaw: {}".format(
+            self.x, self.y, self.z, self.roll, self.pitch, self.yaw)
diff --git a/src/cfclient/ui/tabs/__init__.py b/src/cfclient/ui/tabs/__init__.py
index d07aa5725db94d1db1a9437056892d4cbc8da1c7..a2903e30f843e90173dc8820a8dd1d0acca8634d 100644
--- a/src/cfclient/ui/tabs/__init__.py
+++ b/src/cfclient/ui/tabs/__init__.py
@@ -39,6 +39,7 @@ from .LogTab import LogTab
 from .ParamTab import ParamTab
 from .PlotTab import PlotTab
 from .locopositioning_tab import LocoPositioningTab
+from .QualisysTab import QualisysTab
 
 __author__ = 'Bitcraze AB'
 __all__ = []
@@ -54,4 +55,5 @@ available = [
     ParamTab,
     PlotTab,
     LocoPositioningTab,
+    QualisysTab,
 ]
diff --git a/src/cfclient/ui/tabs/qualisysTab.ui b/src/cfclient/ui/tabs/qualisysTab.ui
new file mode 100644
index 0000000000000000000000000000000000000000..3568726e5fd8e3860e61b0ca07680fbd00226e6e
--- /dev/null
+++ b/src/cfclient/ui/tabs/qualisysTab.ui
@@ -0,0 +1,1012 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Layout</class>
+ <widget class="QWidget" name="Layout">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>745</width>
+    <height>512</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Plot</string>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout">
+   <item>
+    <layout class="QVBoxLayout" name="verticalLayout_3">
+     <property name="topMargin">
+      <number>0</number>
+     </property>
+     <property name="rightMargin">
+      <number>0</number>
+     </property>
+     <item>
+      <layout class="QHBoxLayout" name="horizontalLayout_4">
+       <property name="topMargin">
+        <number>0</number>
+       </property>
+       <item>
+        <widget class="QLabel" name="label_2">
+         <property name="text">
+          <string>QTM</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QComboBox" name="qtmIpBox">
+         <property name="minimumSize">
+          <size>
+           <width>173</width>
+           <height>0</height>
+          </size>
+         </property>
+         <property name="editable">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QPushButton" name="connectQtmButton">
+         <property name="text">
+          <string>Connect to QTM</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QPushButton" name="discoverQTM">
+         <property name="text">
+          <string>Scan</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="qtmStatusLabel">
+         <property name="text">
+          <string>: not connected</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer name="horizontalSpacer_3">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <layout class="QHBoxLayout" name="horizontalLayout_3">
+       <property name="topMargin">
+        <number>0</number>
+       </property>
+       <property name="bottomMargin">
+        <number>10</number>
+       </property>
+       <item>
+        <widget class="QLabel" name="label">
+         <property name="text">
+          <string>Crazyflie status</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="cfStatusLabel">
+         <property name="text">
+          <string>: not connected</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer name="horizontalSpacer_2">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <widget class="QLabel" name="statusLabel">
+       <property name="styleSheet">
+        <string notr="true">font: 11pt &quot;MS Shell Dlg 2&quot;;
+</string>
+       </property>
+       <property name="text">
+        <string>Status: disabled</string>
+       </property>
+       <property name="scaledContents">
+        <bool>true</bool>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+       </property>
+       <property name="margin">
+        <number>0</number>
+       </property>
+       <property name="openExternalLinks">
+        <bool>false</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="Line" name="line">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <layout class="QHBoxLayout" name="horizontalLayout_2">
+       <property name="topMargin">
+        <number>0</number>
+       </property>
+       <property name="rightMargin">
+        <number>0</number>
+       </property>
+       <item>
+        <layout class="QVBoxLayout" name="verticalLayout_7">
+         <property name="sizeConstraint">
+          <enum>QLayout::SetDefaultConstraint</enum>
+         </property>
+         <property name="leftMargin">
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="QGroupBox" name="groupBox">
+           <property name="enabled">
+            <bool>true</bool>
+           </property>
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>120</width>
+             <height>0</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>16777215</width>
+             <height>220</height>
+            </size>
+           </property>
+           <property name="title">
+            <string>Crazyflie controls</string>
+           </property>
+           <property name="alignment">
+            <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_4">
+            <property name="leftMargin">
+             <number>9</number>
+            </property>
+            <property name="rightMargin">
+             <number>9</number>
+            </property>
+            <item>
+             <widget class="QPushButton" name="liftButton">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="text">
+               <string>Lift</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="pathButton">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="text">
+               <string>Fly along path</string>
+              </property>
+              <property name="checkable">
+               <bool>false</bool>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="circleButton">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="text">
+               <string>Fly in cicrcle</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="followButton">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="minimumSize">
+               <size>
+                <width>0</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>16777215</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="layoutDirection">
+               <enum>Qt::LeftToRight</enum>
+              </property>
+              <property name="text">
+               <string>Follow Mode</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="recordButton">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="text">
+               <string>Record Mode</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="landButton">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="minimumSize">
+               <size>
+                <width>40</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>16777215</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="text">
+               <string>Land</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="emergencyButton">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="minimumSize">
+               <size>
+                <width>0</width>
+                <height>20</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>16777215</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="text">
+               <string>Kill engines</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <spacer name="verticalSpacer_4">
+           <property name="orientation">
+            <enum>Qt::Vertical</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>20</width>
+             <height>40</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <layout class="QVBoxLayout" name="verticalLayout">
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="QGroupBox" name="PathSettings">
+           <property name="minimumSize">
+            <size>
+             <width>305</width>
+             <height>194</height>
+            </size>
+           </property>
+           <property name="layoutDirection">
+            <enum>Qt::LeftToRight</enum>
+           </property>
+           <property name="title">
+            <string>Path Settings</string>
+           </property>
+           <layout class="QVBoxLayout" name="verticalLayout_5">
+            <property name="topMargin">
+             <number>0</number>
+            </property>
+            <property name="rightMargin">
+             <number>9</number>
+            </property>
+            <item>
+             <widget class="QTableView" name="flightPathDataTable">
+              <property name="minimumSize">
+               <size>
+                <width>285</width>
+                <height>140</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>16777215</width>
+                <height>120</height>
+               </size>
+              </property>
+              <attribute name="horizontalHeaderDefaultSectionSize">
+               <number>60</number>
+              </attribute>
+              <attribute name="verticalHeaderDefaultSectionSize">
+               <number>20</number>
+              </attribute>
+             </widget>
+            </item>
+            <item>
+             <layout class="QHBoxLayout" name="horizontalLayout_5">
+              <property name="spacing">
+               <number>6</number>
+              </property>
+              <property name="topMargin">
+               <number>9</number>
+              </property>
+              <property name="rightMargin">
+               <number>0</number>
+              </property>
+              <property name="bottomMargin">
+               <number>9</number>
+              </property>
+              <item>
+               <widget class="QLineEdit" name="posHoldPathBox">
+                <property name="maximumSize">
+                 <size>
+                  <width>30</width>
+                  <height>16777215</height>
+                 </size>
+                </property>
+                <property name="text">
+                 <string>0.5</string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QLabel" name="flightPathStatusLabel">
+                <property name="minimumSize">
+                 <size>
+                  <width>0</width>
+                  <height>15</height>
+                 </size>
+                </property>
+                <property name="text">
+                 <string>Position hold (s)</string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <spacer name="horizontalSpacer_4">
+                <property name="orientation">
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeHint" stdset="0">
+                 <size>
+                  <width>40</width>
+                  <height>15</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+              <item>
+               <widget class="QComboBox" name="pathSelector">
+                <property name="minimumSize">
+                 <size>
+                  <width>145</width>
+                  <height>0</height>
+                 </size>
+                </property>
+                <property name="maximumSize">
+                 <size>
+                  <width>145</width>
+                  <height>16777215</height>
+                 </size>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QPushButton" name="removePathButton">
+                <property name="maximumSize">
+                 <size>
+                  <width>20</width>
+                  <height>22</height>
+                 </size>
+                </property>
+                <property name="text">
+                 <string>X</string>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="CircleSettings">
+           <property name="minimumSize">
+            <size>
+             <width>0</width>
+             <height>105</height>
+            </size>
+           </property>
+           <property name="title">
+            <string>Circle Settings</string>
+           </property>
+           <layout class="QGridLayout" name="gridLayout_3">
+            <property name="bottomMargin">
+             <number>9</number>
+            </property>
+            <item row="0" column="0">
+             <widget class="QLineEdit" name="radiusBox">
+              <property name="maximumSize">
+               <size>
+                <width>30</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="text">
+               <string>1</string>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="1">
+             <widget class="QLabel" name="label_4">
+              <property name="text">
+               <string>Radius (m)</string>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="0">
+             <widget class="QLineEdit" name="posHoldCircleBox">
+              <property name="maximumSize">
+               <size>
+                <width>30</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="text">
+               <string>0.5</string>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="1">
+             <widget class="QLabel" name="label_5">
+              <property name="text">
+               <string>Position hold (s)</string>
+              </property>
+             </widget>
+            </item>
+            <item row="2" column="0">
+             <widget class="QLineEdit" name="resolutionBox">
+              <property name="maximumSize">
+               <size>
+                <width>30</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="text">
+               <string>10</string>
+              </property>
+             </widget>
+            </item>
+            <item row="2" column="1">
+             <widget class="QLabel" name="label_3">
+              <property name="text">
+               <string>Resolution (deg)</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <spacer name="verticalSpacer_2">
+           <property name="orientation">
+            <enum>Qt::Vertical</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>20</width>
+             <height>40</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <spacer name="horizontalSpacer">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <layout class="QVBoxLayout" name="verticalLayout_2">
+         <property name="spacing">
+          <number>6</number>
+         </property>
+         <property name="rightMargin">
+          <number>0</number>
+         </property>
+         <property name="bottomMargin">
+          <number>0</number>
+         </property>
+         <item>
+          <widget class="QGroupBox" name="qtmCfPositionBox">
+           <property name="enabled">
+            <bool>false</bool>
+           </property>
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>170</width>
+             <height>135</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>170</width>
+             <height>135</height>
+            </size>
+           </property>
+           <property name="title">
+            <string>Crazyflie</string>
+           </property>
+           <layout class="QGridLayout" name="gridLayout">
+            <item row="2" column="0">
+             <widget class="QLabel" name="y">
+              <property name="text">
+               <string>y:</string>
+              </property>
+             </widget>
+            </item>
+            <item row="2" column="3">
+             <widget class="QLineEdit" name="qualisysPitch">
+              <property name="maximumSize">
+               <size>
+                <width>50</width>
+                <height>16777215</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <item row="3" column="3">
+             <widget class="QLineEdit" name="qualisysYaw">
+              <property name="maximumSize">
+               <size>
+                <width>50</width>
+                <height>16777215</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <item row="2" column="1">
+             <widget class="QLineEdit" name="qualisysY">
+              <property name="maximumSize">
+               <size>
+                <width>50</width>
+                <height>16777215</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="2">
+             <widget class="QLabel" name="roll">
+              <property name="maximumSize">
+               <size>
+                <width>20</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="text">
+               <string>Roll:</string>
+              </property>
+             </widget>
+            </item>
+            <item row="2" column="2">
+             <widget class="QLabel" name="pitch">
+              <property name="text">
+               <string>Pitch:</string>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="1">
+             <widget class="QLineEdit" name="qualisysX">
+              <property name="maximumSize">
+               <size>
+                <width>50</width>
+                <height>16777215</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <item row="3" column="0">
+             <widget class="QLabel" name="z">
+              <property name="text">
+               <string>z:</string>
+              </property>
+             </widget>
+            </item>
+            <item row="3" column="1">
+             <widget class="QLineEdit" name="qualisysZ">
+              <property name="maximumSize">
+               <size>
+                <width>50</width>
+                <height>16777215</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="0">
+             <widget class="QLabel" name="x">
+              <property name="maximumSize">
+               <size>
+                <width>10</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="text">
+               <string>x:</string>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="3">
+             <widget class="QLineEdit" name="qualisysRoll">
+              <property name="maximumSize">
+               <size>
+                <width>50</width>
+                <height>16777215</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <item row="3" column="2">
+             <widget class="QLabel" name="yaw">
+              <property name="text">
+               <string>Yaw:</string>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="0" colspan="4">
+             <layout class="QHBoxLayout" name="horizontalLayout_6">
+              <item>
+               <widget class="QLabel" name="label_6">
+                <property name="text">
+                 <string>6DOF</string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QComboBox" name="quadBox">
+                <property name="sizePolicy">
+                 <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                  <horstretch>0</horstretch>
+                  <verstretch>0</verstretch>
+                 </sizepolicy>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="qtmWandPositionBox">
+           <property name="enabled">
+            <bool>false</bool>
+           </property>
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="minimumSize">
+            <size>
+             <width>170</width>
+             <height>135</height>
+            </size>
+           </property>
+           <property name="maximumSize">
+            <size>
+             <width>170</width>
+             <height>135</height>
+            </size>
+           </property>
+           <property name="title">
+            <string>QStick</string>
+           </property>
+           <layout class="QGridLayout" name="gridLayout_2">
+            <item row="1" column="0">
+             <widget class="QLabel" name="x_2">
+              <property name="maximumSize">
+               <size>
+                <width>10</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="text">
+               <string>x:</string>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="1">
+             <widget class="QLineEdit" name="qualisysWandX">
+              <property name="maximumSize">
+               <size>
+                <width>50</width>
+                <height>16777215</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="2">
+             <widget class="QLabel" name="roll_2">
+              <property name="maximumSize">
+               <size>
+                <width>20</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="text">
+               <string>Roll:</string>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="3">
+             <widget class="QLineEdit" name="qualisysWandRoll">
+              <property name="maximumSize">
+               <size>
+                <width>50</width>
+                <height>16777215</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <item row="2" column="0">
+             <widget class="QLabel" name="y_2">
+              <property name="text">
+               <string>y:</string>
+              </property>
+             </widget>
+            </item>
+            <item row="2" column="1">
+             <widget class="QLineEdit" name="qualisysWandY">
+              <property name="maximumSize">
+               <size>
+                <width>50</width>
+                <height>16777215</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <item row="2" column="2">
+             <widget class="QLabel" name="pitch_2">
+              <property name="text">
+               <string>Pitch:</string>
+              </property>
+             </widget>
+            </item>
+            <item row="2" column="3">
+             <widget class="QLineEdit" name="qualisysWandPitch">
+              <property name="maximumSize">
+               <size>
+                <width>50</width>
+                <height>16777215</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <item row="3" column="0">
+             <widget class="QLabel" name="z_2">
+              <property name="text">
+               <string>z:</string>
+              </property>
+             </widget>
+            </item>
+            <item row="3" column="1">
+             <widget class="QLineEdit" name="qualisysWandZ">
+              <property name="maximumSize">
+               <size>
+                <width>50</width>
+                <height>16777215</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <item row="3" column="2">
+             <widget class="QLabel" name="yaw_2">
+              <property name="text">
+               <string>Yaw:</string>
+              </property>
+             </widget>
+            </item>
+            <item row="3" column="3">
+             <widget class="QLineEdit" name="qualisysWandYaw">
+              <property name="maximumSize">
+               <size>
+                <width>50</width>
+                <height>16777215</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="0" colspan="4">
+             <layout class="QHBoxLayout" name="horizontalLayout_8">
+              <item>
+               <widget class="QLabel" name="label_8">
+                <property name="text">
+                 <string>6DOF</string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QComboBox" name="stickBox">
+                <property name="sizePolicy">
+                 <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                  <horstretch>0</horstretch>
+                  <verstretch>0</verstretch>
+                 </sizepolicy>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <spacer name="verticalSpacer">
+           <property name="orientation">
+            <enum>Qt::Vertical</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>20</width>
+             <height>40</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>qtmIpBox</tabstop>
+  <tabstop>connectQtmButton</tabstop>
+  <tabstop>liftButton</tabstop>
+  <tabstop>pathButton</tabstop>
+  <tabstop>circleButton</tabstop>
+  <tabstop>followButton</tabstop>
+  <tabstop>recordButton</tabstop>
+  <tabstop>landButton</tabstop>
+  <tabstop>emergencyButton</tabstop>
+  <tabstop>flightPathDataTable</tabstop>
+  <tabstop>posHoldPathBox</tabstop>
+  <tabstop>pathSelector</tabstop>
+  <tabstop>removePathButton</tabstop>
+  <tabstop>radiusBox</tabstop>
+  <tabstop>posHoldCircleBox</tabstop>
+  <tabstop>resolutionBox</tabstop>
+  <tabstop>qualisysX</tabstop>
+  <tabstop>qualisysY</tabstop>
+  <tabstop>qualisysZ</tabstop>
+  <tabstop>qualisysRoll</tabstop>
+  <tabstop>qualisysPitch</tabstop>
+  <tabstop>qualisysYaw</tabstop>
+  <tabstop>qualisysWandX</tabstop>
+  <tabstop>qualisysWandY</tabstop>
+  <tabstop>qualisysWandZ</tabstop>
+  <tabstop>qualisysWandRoll</tabstop>
+  <tabstop>qualisysWandPitch</tabstop>
+  <tabstop>qualisysWandYaw</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>