I am running a simulator for my DJI drone so I can learn to use the drone before flying it in person. However, whenever I initialize the code the drone fails to enter GUIDED mode. This is my code: import collections import collections.abc collections.MutableMapping = collections.abc.MutableMapping #this is a technical issue. might actually affect a future issue #there was some sort of update that switched around the files, and this switches it back from dronekit import connect, VehicleMode, LocationGlobalRelative import dronekit_sitl import time import math import threading from pymavlink import mavutil from pynput import keyboard import dronekit_sitl sitl = dronekit_sitl.start_default(lat=0, lon=0) connection_string = sitl.connection_string() class Location: def __init__(self, lat, lon, alt): self.lat = lat self.lon = lon self.alt = alt def __repr__(self): return "Location(%s, %s, %s)" % (self.lat, self.lon, self.alt) class DroneController: def __init__(self, connection_string=""): print(f"Attempting to connect to {connection_string}") self.vehicle = connect(connection_string, wait_ready=True, timeout=60) print("Successfully connected to the vehicle") def get_location(self): return Location(self.vehicle.location.global_relative_frame.lat, self.vehicle.location.global_relative_frame.lon, self.vehicle.location.global_relative_frame.alt) def arm_and_takeoff(self, target_altitude): print("Basic pre-arm checks") while not self.vehicle.is_armable: print(" Waiting for vehicle to initialise...") time.sleep(1) if not self.set_guided_mode(): print("not guieded mode") return False print("Arming motors") self.vehicle.armed = True arming_timeout = 60 start_time = time.time() while not self.vehicle.armed: if time.time() - start_time > arming_timeout: print("Failed to arm within timeout period") return False print(" Waiting for arming...") time.sleep(1) print("Taking off!") self.vehicle.simple_takeoff(target_altitude) takeoff_timeout = 30 start_time = time.time() while True: current_altitude = self.vehicle.location.global_relative_frame.alt print(f" Altitude: {current_altitude}") if current_altitude >= target_altitude * 0.95: print("Reached target altitude") return True elif time.time() - start_time > takeoff_timeout: print("Takeoff failed, timeout reached") return False time.sleep(1) def pre_arm_check(self): print("waiting for vehicle to initialise") while not self.vehicle.is_armable: print("waiting for vehicle to initialise...") time.sleep(1) print("vehicle is ready to arm") def set_guided_mode(self): print("Attempting to set GUIDED mode") # Try to set mode using standard method self.vehicle.mode = VehicleMode("GUIDED") self.vehicle.flush() start_time = time.time() timeout = 10 while self.vehicle.mode.name != 'GUIDED': if time.time() - start_time > timeout: print("Failed to set GUIDED mode within timeout period") print(f"Mode: {self.vehicle.mode.name}") return False time.sleep(1) print("GUIDED mode set successfully") return True def fly_to_point(self, location: Location): print("Flying to point") point_end = LocationGlobalRelative(location.lat, location.lon, location.alt) self.vehicle.simple_goto(point_end) # Wait until the drone reaches the correct spot while True: distance = self.distance_to(location) print(f"Distance to target: {distance:.2f} meters") if distance <= 1: print("Reached target point") break time.sleep(1) def land(self): print("Landing...") self.vehicle.mode = VehicleMode("RTL") #might be "LAND" def close(self): self.vehicle.close() def get_distance(self, location1: Location, location2: Location): #use the haversine formula to calculate the distance between two points on a 3d sphere earth_radius = 6371000 #meters lat1 = math.radians(location1.lat) lon1 = math.radians(location1.lon) lat2 = math.radians(location2.lat) lon2 = math.radians(location2.lon) dlat = lat2 - lat1 # differences in latitude and longitude dlon = lon2 - lon1 #haversine formula to calculate the distance between two points on a sphere a = (math.sin(dlat/2) * math.sin(dlat/2) + math.cos(lat1) * math.cos(lat2) * math.sin(dlon/2) * math.sin(dlon/2)) c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a)) distance = earth_radius * c alt_diff = abs(location2.alt - location1.alt) total_distance = math.sqrt(distance**2 + alt_diff**2) return total_distance def distance_to(self, location: Location): current_location = self.get_location() return self.get_distance(current_location, location) def print_position(self): location = self.vehicle.location.global_relative_frame print(f"Position: Lat: {location.lat}, Lon: {location.lon}, Alt: {location.alt}") def position_printer(self, stop): while not stop(): self.print_position() time.sleep(1) #print the position every second def keyboard_control(self): print("starting keyboard control. use arrow keys to move the drone, press 'q' to quit") with keyboard.Listener(on_press=self.on_press, on_release=self.on_release) as listener: listener.join() def set_velocity(self, x, y, z, yaw): msg = self.vehicle.message_factory.set_position_target_local_ned_encode( 0, # time_boot_ms (not used) 0, 0, # target system, target component mavutil.mavlink.MAV_FRAME_LOCAL_NED, # frame 0b0000111111000111, # type_mask (only speeds enabled) 0, 0, 0, # x, y, z positions (not used) x, y, z, # x, y, z velocity in m/s 0, 0, 0, # x, y, z acceleration (not supported yet, ignored in GCS_Mavlink) 0, math.radians(yaw)) # yaw, yaw_rate (not supported yet, ignored in GCS_Mavlink) self.vehicle.send_mavlink(msg) self.vehicle.flush() def move_forward(self): self.set_velocity(5, 0, 0, 0) print("moving forward") def move_backward(self): self.set_velocity(-5, 0, 0, 0) print("moving backward") def move_left(self): self.set_velocity(0, 5, 0, 0) print("moving left") def move_right(self): self.set_velocity(0, -5, 0, 0) print("moving right") def move_up(self): self.set_velocity(0, 0, -5, 0) print("moving up") def move_down(self): self.set_velocity(0, 0, 5, 0) print("moving down") def stop(self): self.set_velocity(0, 0, 0, 0) print("stopping") def on_press(self, key): try: if key == keyboard.Key.up: self.move_forward() elif key == keyboard.Key.down: self.move_backward() elif key == keyboard.Key.left: self.move_left() elif key == keyboard.Key.right: self.move_right() elif hasattr(key, 'char'): if key.char == 'w': self.move_up() elif key.char == 's': self.move_down() elif key.char == 'q': print("Quitting keyboard control") return False except AttributeError: print('special key {0} pressed'.format(key)) def on_release(self, key): self.set_velocity(0, 0, 0, 0) print("stopping") if key == keyboard.Key.esc: # Stop listener return False if __name__ == "__main__": print("Connecting to vehicle on: %s" % connection_string) drone = DroneController(connection_string) stop_threads = False printer_thread = threading.Thread(target=drone.position_printer, args=(lambda: stop_threads,)) try: print("Performing pre-arm check") drone.pre_arm_check() print("Pre-arm check completed. Attempting takeoff") print(f"Is Armable: {drone.vehicle.is_armable}") print(f"System Status: {drone.vehicle.system_status.state}") print(f"Mode: {drone.vehicle.mode.name}") takeoff_success = drone.arm_and_takeoff(10) if takeoff_success: print("Takeoff successful") time.sleep(2) print("Starting keyboard control") printer_thread.start() drone.keyboard_control() else: print("Takeoff failed. Checking vehicle state:") print(f"Is Armed: {drone.vehicle.armed}") print(f"System Status: {drone.vehicle.system_status.state}") print(f"Mode: {drone.vehicle.mode.name}") print("Aborting mission") except Exception as e: print(f"An error occurred: {str(e)}") finally: print("Landing and closing connection") stop_threads = True printer_thread.join() drone.land() drone.close() sitl.stop() and this is the error I keep getting: Starting copter simulator (SITL) SITL already Downloaded and Extracted. Ready to boot. Connecting to vehicle on: tcp:127.0.0.1:5760 Attempting to connect to tcp:127.0.0.1:5760 CRITICAL:autopilot:APM:Copter V3.3 (d6053245) CRITICAL:autopilot:Frame: QUAD CRITICAL:autopilot:Calibrating barometer CRITICAL:autopilot:Initialising APM... CRITICAL:autopilot:barometer calibration complete CRITICAL:autopilot:GROUND START Successfully connected to the vehicle Performing pre-arm check waiting for vehicle to initialise waiting for vehicle to initialise... waiting for vehicle to initialise... waiting for vehicle to initialise... waiting for vehicle to initialise... waiting for vehicle to initialise... vehicle is ready to arm Pre-arm check completed. Attempting takeoff Is Armable: True System Status: STANDBY Mode: STABILIZE Basic pre-arm checks Attempting to set GUIDED mode Failed to set GUIDED mode within timeout period Mode: STABILIZE not guieded mode Takeoff failed. Checking vehicle state: Is Armed: False System Status: STANDBY Mode: STABILIZE Aborting mission Landing and closing connection Traceback (most recent call last): File "/Users/koviressler/Desktop/AeroCleanTech/Drone_Control/drone_controller.py", line 274, in <module> printer_thread.join() File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/threading.py", line 1107, in join raise RuntimeError("cannot join thread before it is started") RuntimeError: cannot join thread before it is started Don't worry about the thread error. I am simply using threading to print out the drone's position every second and the error only occurs because I only start the thread if the drone takes of correctly, which it isn't. I tried debugging by adding tons of print statements, but it always led back to the GUIDED mode issue. It used to work, but one day I must have added something that broke it and it hasn't worked since. It could be a compatability issue. Continue reading...