From e37010da599502c7a47066cb1ea33cbc7c1dfb85 Mon Sep 17 00:00:00 2001 From: Kevin Date: Thu, 27 Nov 2025 01:33:44 -0600 Subject: [PATCH] First Drone+BCI Deployment - Added logic that prevents the drone from going to sleep by using a pseudo watchdog (timer instance running in the background) to keep the drone active (in other words, preventing it from landing after 15 seconds). Timer is set on a 200ms interval to run GUI5.hover_loop. Also updated the QML to run a takeoff function to perform the takeoff logic --- GUI5.py | 33 +++++++++++++++++++++++++++------ ManualDroneControl.qml | 2 +- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/GUI5.py b/GUI5.py index 123a03b3..e2d6ee87 100644 --- a/GUI5.py +++ b/GUI5.py @@ -4,7 +4,7 @@ from pathlib import Path from PySide6.QtWidgets import QApplication,QFileDialog, QMessageBox from PySide6.QtQml import QQmlApplicationEngine -from PySide6.QtCore import QObject, Signal, Slot, Property, QProcess, QUrl +from PySide6.QtCore import QObject, Signal, Slot, Property, QProcess, QUrl, QTimer from pdf2image import convert_from_path from djitellopy import Tello import random @@ -220,6 +220,13 @@ def __init__(self): self.drone_lock = threading.Lock() self.config = configparser.ConfigParser() self.config.optionxform = str + + # Timer to send periodic hover signals () + self.hover_timer = QTimer() + self.hover_timer.timeout.connect(self.hover_loop) + + self.is_flying = False + try: self.tello = Tello() except Exception as e: @@ -242,6 +249,23 @@ def __init__(self): else: self.bcicon = None + @Slot() + def takeoff(self): + self.tello.takeoff() + self.connected = True + self.is_flying = True + self.hover_timer.start(200) + self.logMessage.emit("Hovering") + + @Slot() + def hover(self): + self.tello.send_rc_control(0, 0, 0, 0) + self.logMessage.emit("Hovering") + + def hover_loop(self): + if self.is_flying: + self.tello.send_rc_control(0, 0, 0, 0) + @Slot(str) def selectModel(self, model_name): """ Select the machine learning model """ @@ -274,6 +298,7 @@ def readMyMind(self): else: # Deep Learning if self.current_framework == "PyTorch": prediction = self.run_deep_learning_pytorch() + self.logMessage.emit("Getting prediction from pytorch using the deep learning model.") else: prediction = self.run_deep_learning_tensorflow() self.logMessage.emit(f"Prediction received: {prediction}") @@ -467,7 +492,7 @@ def getDroneAction(self, action): self.flight_log.insert(0, f"Drone connected (Battery: {battery}%)") self.flightLogUpdated.emit(self.flight_log) return - elif self.connected: + elif not self.connected: self.logMessage.emit("Drone not connected. Please connect first.") self.flight_log.insert(0, "Command failed: Drone not connected") self.flightLogUpdated.emit(self.flight_log) @@ -536,10 +561,6 @@ def record_action(name, value=None): record_action('flip_right') self.logMessage.emit("Flipping right") self.flight_log.insert(0, "Flipping right") - elif action == 'takeoff': - self.tello.takeoff() - self.logMessage.emit("Taking off") - self.flight_log.insert(0, "Taking off") elif action == 'land': self.tello.land() self.logMessage.emit("Landing") diff --git a/ManualDroneControl.qml b/ManualDroneControl.qml index 73f3326b..59ab83c6 100644 --- a/ManualDroneControl.qml +++ b/ManualDroneControl.qml @@ -650,7 +650,7 @@ Rectangle { anchors.fill: parent onEntered: parent.color = "white" onExited: parent.color = "#242c4d" - onClicked: backend.doDroneTAction("takeoff") + onClicked: backend.takeoff() } }