def landDrones(self, ignoreInterrupt=False):
        if not (self.appController.trajectoryEnabled or self.appController.positioningEnabled):
            return

        Logger.log("Landing drones...")
        swarmController = self.appController.swarmController
        commander = swarmController.broadcaster.high_level_commander
        light_controller = swarmController.broadcaster.light_controller

        light_controller.set_color(32, 32, 32, 4.0, True)
        commander.land(SequenceController.LANDING_HEIGHT, 4.0)

        for drone in swarmController.connectedDrones:
            if (drone.state == DroneState.IN_FLIGHT):
                drone.state = DroneState.LANDING

        self.appController.sequenceUpdated.emit()
        threadUtil.interruptibleSleep(4.5, ignoreInterrupt)

        light_controller.set_color(0, 0, 0, 0.25, True)
        commander.stop()

        for drone in swarmController.connectedDrones:
            if (drone.state == DroneState.LANDING):
                drone.state = DroneState.CONNECTED

        self.appController.sequenceUpdated.emit()
        exceptionUtil.checkInterrupt(ignoreInterrupt)
Exemple #2
0
 def onDisconnect(self, uri, errorMessage):
     Logger.error(errorMessage)
     if uri in self.droneMapping:
         drone = self.droneMapping[uri]
         drone.state = DroneState.DISCONNECTED
         self.appController.droneDisconnected.emit(uri)
         self.appController.sequenceUpdated.emit()
    def __init__(self, mainWindow, appSettings):
        super().__init__()
        Logger.initialize()

        self.clearSequence = False
        self.sequencePlaying = False
        self.appSettings = appSettings
        self.mainWindow = mainWindow
        self.sequenceController = SequenceController(self, appSettings)

        self.initializePositioning()
        self.initializeSwarm()
        self.scanInProgress = False
        self.sequenceTimer = QTimer()
        self.sequenceTimer.timeout.connect(self.updateSequence)
        self.sequenceTimer.setInterval(20)  # in MS
        self.elapsedTime = 0
        self.sequenceProgress = 0
        self.startTimestamp = None

        self.killTimer = QTimer()
        self.killTimer.timeout.connect(self.hardKill)
        self.killTimer.setSingleShot(True)

        self.startTimer.connect(self.startSequenceTimer)
        self.sequenceFinished.connect(self.stopSequenceTimer)
        self.droneDisconnected.connect(self.onDroneDisconnected)
        self.sequenceOrderUpdated.connect(self.saveSequenceSettings)
        self.connectionFailed.connect(self.onConnectionFailed)
        self.scanForDrones()
Exemple #4
0
    def writeLedTimings(self, color_data):
        mems = self.crazyflie.cf.mem.get_mems(
            MemoryElement.TYPE_DRIVER_LEDTIMING)
        if self.crazyflie is None or len(color_data) == 0:
            Logger.error("Could not upload LED data", self.swarmIndex)
            raise ValueError("Cannot write led timing data")

        self.write(lambda: mems[0].write_raw(color_data, self.writeComplete))
        exceptionUtil.checkInterrupt()
Exemple #5
0
    def waitForEstimator(self):
        startTime = time.time()
        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')
        log_config.add_variable('kalman.stateX', 'float')
        log_config.add_variable('kalman.stateY', 'float')
        log_config.add_variable('kalman.stateZ', 'float')

        var_y_history = [1000] * 10
        var_x_history = [1000] * 10
        var_z_history = [1000] * 10
        threshold = 0.001

        with SyncLogger(self.crazyflie, log_config) as logger:
            for log_entry in logger:

                exceptionUtil.checkInterrupt()
                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)

                x = data['kalman.stateX']
                y = data['kalman.stateY']
                z = data['kalman.stateZ']

                has_converged = (max_x - min_x) < threshold and (
                    max_y - min_y) < threshold and (max_z - min_z) < threshold
                timed_out = (time.time() -
                             startTime) > Drone.ESTIMATOR_TIMEOUT_SEC

                if has_converged:
                    print("Initial position for drone", self.swarmIndex,
                          "has converged, to position: ",
                          ("({:.2f}, {:.2f}, {:.2f})".format(x, y, z)))
                    self.startPosition = (float(x), float(y), float(z))
                    break
                elif timed_out:
                    Logger.error("Drone position sensor failed to update!",
                                 self.swarmIndex)
                    self.setError()
                    raise DroneException(
                        "Drone did not achieve the target position")
    def setInitialPosition(self, drone):
        exceptionUtil.checkInterrupt()

        sequence = SequenceController.CURRENT
        track = sequence.getTrack(drone.swarmIndex)
        commander = drone.commander
        self.appController.updateSequence()
        exceptionUtil.checkInterrupt()

        if track is not None:

            r, g, b = sequence.getStartingColor(drone.swarmIndex)
            x, y, z = sequence.getStartingPosition(drone.swarmIndex)
            drone.light_controller.set_color(r, g, b, 0.25, True)

            if self.appController.trajectoryEnabled or self.appController.positioningEnabled:
                Logger.log("Getting into position", drone.swarmIndex)

                # Step 0 - Make sure the drone has reached its takeoff position
                initialX, initialY, initialZ = drone.startPosition

                print("Waiting for drone", drone.swarmIndex, "to converge to position", ("({:.2f}, {:.2f}, {:.2f})".format(initialX, initialY, SequenceController.MIN_HEIGHT)))
                drone.waitForTargetPosition(initialX, initialY, SequenceController.MIN_HEIGHT)

                # Step 1 - Move to some height determined by index
                targetHeight = min(SequenceController.MIN_HEIGHT + (drone.swarmIndex * 0.1), SequenceController.MAX_HEIGHT)
                numDrones = len(self.appController.swarmController.connectedDrones)
                moveTime = 5.0 + (numDrones * 0.3)

                print("Moving drone", drone.swarmIndex, "to position", ("({:.2f}, {:.2f}, {:.2f})".format(initialX, initialY, targetHeight)), "over time:", moveTime)
                commander.go_to(initialX, initialY, targetHeight, 0, moveTime)
                threadUtil.interruptibleSleep(moveTime + 0.25)
                print("Waiting for drone", drone.swarmIndex, "to converge to position", ("({:.2f}, {:.2f}, {:.2f})".format(initialX, initialY, targetHeight)))
                drone.waitForTargetPosition(initialX, initialY, targetHeight)

                # Step 2 - Move to position, maintaining target height
                print("Moving drone", drone.swarmIndex, "to position", ("({:.2f}, {:.2f}, {:.2f})".format(x, y, targetHeight)), "over time:", 8.0)
                commander.go_to(x, y, targetHeight, 0, 8.0)
                threadUtil.interruptibleSleep(8.25)
                print("Waiting for drone", drone.swarmIndex, "to converge to position", ("({:.2f}, {:.2f}, {:.2f})".format(x, y, targetHeight)))
                drone.waitForTargetPosition(x, y, targetHeight)

                # Step 3 - Move to actual starting position
                print("Moving drone", drone.swarmIndex, "to position", ("({:.2f}, {:.2f}, {:.2f})".format(x, y, z)), "over time:", 8.0)
                commander.go_to(x, y, z, 0.0, 8.0)
                threadUtil.interruptibleSleep(8.25)
                print("Waiting for drone", drone.swarmIndex, "to converge to position", ("({:.2f}, {:.2f}, {:.2f})".format(x, y, z)))
                drone.waitForTargetPosition(x, y, z)

            Logger.log("Ready!", drone.swarmIndex)
            self.appController.updateSequence()
            exceptionUtil.checkInterrupt()
Exemple #7
0
    def __init__(self, appController, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.appController = appController
        self.appController.sequenceSelected.connect(self.clearLog)
        self.appController.sequenceStarted.connect(self.clearLog)
        # self.appController.sequenceFinished.connect(self.clearLog)
        self.appController.sequenceUpdated.connect(self.scrollBottom)
        Logger.bind_handler(self.log)

        self.layout = layoutUtil.createLayout(LayoutType.VERTICAL, self)
        self.createTitle()
        self.createLogPanel()
        self.clearLog()
Exemple #8
0
    def writeTrajectory(self, data):
        if self.crazyflie is None or len(data) == 0:
            Logger.error("Could not upload trajectory data!", self.swarmIndex)
            raise ValueError("Cannot write trajectory data")

        trajectoryMemory = self.crazyflie.cf.mem.get_mems(
            MemoryElement.TYPE_TRAJ)[0]
        self.write(lambda: trajectoryMemory.write_raw(data, self.writeComplete,
                                                      self.writeFailed))

        exceptionUtil.checkInterrupt()
        self.crazyflie.cf.high_level_commander.define_trajectory_compressed(
            Drone.TRAJECTORY_ID, 0)
    def run(self):

        # Update the order of the recent sequences
        if self.sequenceIndex:
            self.sequences.insert(0, self.sequences.pop(self.sequenceIndex))
            self.appController.sequenceOrderUpdated.emit()

        try:
            Logger.log("SEQUENCE STARTING")
            swarmController = self.appController.swarmController

            # connect to required drones
            numDrones = min(SequenceController.CURRENT.drones, self.appController.availableDrones)
            self.appController.swarmController.connectSwarm(numDrones)
            self.appController.sequenceUpdated.emit()
            threadUtil.interruptibleSleep(0.25)

            # ensure all drones have updated light house info & know their positions
            uploadLighthouseData = self.appController.trajectoryEnabled or self.appController.positioningEnabled
            swarmController.initializeSensors(uploadLighthouseData)
            self.appController.sequenceUpdated.emit()
            threadUtil.interruptibleSleep(0.25)

            # get all drones in position
            swarmController.parallel(self.uploadFlightData)
            self.synchronizedTakeoff()
            swarmController.parallel(self.setInitialPosition)
            threadUtil.interruptibleSleep(0.25)

            # kick off the actual sequence action4
            self.runSequence()

            # land all drones
            self.landDrones()

            # Wrap up
            self.completeSequence()

        except SequenceInterrupt:
            Logger.log("ABORTING SEQUENCE")
            self.abort()
            return

        except ConnectionAbortedError:
            print("-- Drone connection failed, cancelling sequence --")
            self.appController.connectionFailed.emit()
            return

        # Re-throw all other exceptions
        except Exception:
            raise
Exemple #10
0
    def initialize(self, address, disconnectCallback):
        Logger.log("Connecting to address " + address, self.swarmIndex)
        crazyflie = Crazyflie(ro_cache='./cache', rw_cache='./cache')
        syncCrazyflie = SyncCrazyflie(address, cf=crazyflie)
        crazyflie.connection_lost.add_callback(disconnectCallback)
        syncCrazyflie.open_link()

        self.crazyflie = syncCrazyflie
        self.commander = syncCrazyflie.cf.high_level_commander
        self.light_controller = syncCrazyflie.cf.light_controller
        self.light_controller.set_color(0, 0, 0, 0.0, True)
        threadUtil.interruptibleSleep(0.5)

        self.state = DroneState.INITIALIZING
        self.light_controller.set_color(255, 200, 0, 0.0, True)
Exemple #11
0
    def connectSwarm(self, numDrones=None):
        toConnect = []
        if numDrones and (isinstance(numDrones, int)
                          or numDrones.is_integer()):
            totalCount = len(self.availableDrones)
            desiredCount = totalCount if numDrones < 0 else numDrones
            end = max(0, min(desiredCount, totalCount))
            toConnect = self.availableDrones[:end]

        Logger.log("Attempting to open " + str(len(toConnect)) +
                   " drone connections")
        self.broadcaster = Broadcaster(self.channel)
        self.broadcaster.open_link()
        self.connectedDrones = self.parallel(self.connectToDrone, toConnect)
        Logger.log("Successfully opened " + str(len(self.connectedDrones)) +
                   " drone connections")
    def runSequence(self):
        Logger.log("Starting flight paths!")
        swarmController = self.appController.swarmController
        commander = swarmController.broadcaster.high_level_commander
        light_controller = swarmController.broadcaster.light_controller
        duration = SequenceController.CURRENT.duration

        # Start the automated trajectory
        if self.appController.trajectoryEnabled:
            commander.start_trajectory(Drone.TRAJECTORY_ID)

        # Start the automated LED sequence
        if self.appController.colorSequenceEnabled:
            light_controller.set_effect(RingEffect.TIMING_EFFECT)

        self.appController.startTimer.emit()
        threadUtil.interruptibleSleep(duration + 0.25)
    def uploadFlightData(self, drone):
        sequence = SequenceController.CURRENT
        track = sequence.getTrack(drone.swarmIndex)
        exceptionUtil.checkInterrupt()

        if track is not None:
            Logger.log("Uploading trajectory & LED data", drone.swarmIndex)

            if self.appController.trajectoryEnabled:
                trajectoryData = bytearray(track['CompressedTrajectory'])
                drone.writeTrajectory(trajectoryData)
                exceptionUtil.checkInterrupt()

            if self.appController.colorSequenceEnabled:
                lightData = bytearray(track['LedTimings'])
                drone.writeLedTimings(lightData)
                exceptionUtil.checkInterrupt()
Exemple #14
0
    def updateSensors(self, uploadGeometry, geometryOne, geometryTwo):
        Logger.log("Updating sensor & positioning data", self.swarmIndex)
        self.crazyflie.cf.param.set_value('lighthouse.method', '0')
        self.crazyflie.cf.param.set_value('lighthouse.systemType', '1')

        # PID controller
        self.crazyflie.cf.param.set_value('stabilizer.controller', '0')
        self.crazyflie.cf.param.set_value('commander.enHighLevel', '1')
        exceptionUtil.checkInterrupt()

        if uploadGeometry:
            self.writeBaseStationData(geometryOne, geometryTwo)
            self.resetEstimator()

        self.state = DroneState.CONNECTED
        self.light_controller.set_color(0, 255, 0, 0.0, True)
        exceptionUtil.checkInterrupt()
    def synchronizedTakeoff(self):
        if not (self.appController.trajectoryEnabled or self.appController.positioningEnabled):
            return

        Logger.log("Taking off")
        swarmController = self.appController.swarmController
        commander = swarmController.broadcaster.high_level_commander
        light_controller = swarmController.broadcaster.light_controller

        light_controller.set_color(0, 127, 255, 0.1, True)
        commander.takeoff(SequenceController.MIN_HEIGHT, 4.0)
        print("Taking off to height:", SequenceController.MIN_HEIGHT, ", over time:", 4.0)

        for drone in swarmController.connectedDrones:
            drone.state = DroneState.IN_FLIGHT

        self.appController.sequenceUpdated.emit()
        threadUtil.interruptibleSleep(4.0)
Exemple #16
0
    def waitForTargetPosition(self,
                              targetX,
                              targetY,
                              targetZ,
                              timeoutSeconds=None):
        startTime = time.time()
        log_config = LogConfig(name='Kalman Position', period_in_ms=50)
        log_config.add_variable('kalman.stateX', 'float')
        log_config.add_variable('kalman.stateY', 'float')
        log_config.add_variable('kalman.stateZ', 'float')
        threshold = 0.05

        with SyncLogger(self.crazyflie, log_config) as logger:
            for log_entry in logger:

                exceptionUtil.checkInterrupt()
                data = log_entry[1]

                x = float(data['kalman.stateX'])
                y = float(data['kalman.stateY'])
                z = float(data['kalman.stateZ'])

                has_converged = abs(targetX - x) < threshold and abs(
                    targetY - y) and abs(targetZ - z)
                timed_out = (time.time() - startTime
                             ) > timeoutSeconds if timeoutSeconds else False

                if has_converged:
                    print("Target position for drone", self.swarmIndex,
                          "has converged. Target was:",
                          ("({:.2f}, {:.2f}, {:.2f})".format(
                              targetX, targetY, targetZ)),
                          ", converged to position: ",
                          ("({:.2f}, {:.2f}, {:.2f})".format(x, y, z)))
                    break
                elif timed_out:
                    Logger.error("Drone failed to reach target position!",
                                 self.swarmIndex)
                    self.setError()
                    raise ConnectionAbortedError(
                        "Drone position was not able to converge!")
 def completeSequence(self):
     Logger.log("SEQUENCE COMPLETE")
     self.appController.swarmController.disconnectSwarm()
     self.appController.onSequenceCompleted()
     self.appController.sequenceUpdated.emit()