Example #1
0
class HelicopterPilot:

    # Rates which equate to a demand of 1
    _gyro_normalisation_values = [50, 50, 80]

    # Thresholds
    _min_throttle = 0.3
    _yaw_threshold = 0.1

    def __init__(self):
        # Get the helicopter instance
        self.heli = Helicopter()
        # Gyro - how we sense the difference between the demand and the reality
        self.gyro = Gyro(
            normalise_rates=True,
            gyro_normalisation_values=self._gyro_normalisation_values,
            acceleration_normalisation_values=[1, 1, 1])
        # Init the demands variable
        self.demands = None
        self.flying = False
        self.thread_running = True
        # Create a thread for this to run in
        self.pilot_thread = Thread(target=self.fly, daemon=True)
        self.pilot_thread.start()

    def update_demands(self, demands):
        """ Update the helicopter's input demands"""
        if demands:
            #            print(f"Latest demands: {demands}")
            if not self.flying:
                if 'start_demand' in demands and 'stop_demand' in demands:
                    if demands['start_demand'] and not demands['stop_demand']:
                        # Then we haven't fired the motor up yet, so get it spinning
                        self.heli.start_motor()
                        self.flying = True
                if 'calibration_demand' in demands and demands[
                        'calibration_demand']:
                    # Then we want to calibrate - the gyro class will prevent us from running this multiple times, so just call calibrate() while the button is down
                    self.gyro.calibrate()

            self.demands = demands

    def fly(self):
        while self.thread_running:
            if self.flying:
                try:
                    accelerations = self.gyro.get_acceleration()
                    gyro_rates = self.gyro.get_gyro()
                except IOError as e:
                    print("Error getting gyro/accelerometer details!")
                    print(e)
                    accelerations = [0, 0, 0]
                    gyro_rates = [0, 0, 0]
                for demand in self.demands:
                    demand_value = self.demands[demand]
                    #print(f"Demand: {demand}, value = {demand_value}")
                    if demand == 'stop_demand':
                        if demand_value:
                            self.heli.stop()
                            self.flying = False
                            # This call blocks, so we can't do any processing anyway
                            # Don't stop processing in this thread just yet in case we still need to do something on the other controls
                    if demand == 'start_demand':
                        # self.heli.start_motor()
                        # Motor started before we're 'flying', so do nothing now...
                        pass
                    if demand == 'throttle_demand':
                        # Need to blend the throttle and blade pitch - increment throttle to match demand if above the threshold
                        throttle_demand = max(
                            self._min_throttle, abs(demand_value)
                        )  # Make sure that the throttle is always at least _min_throttle, and set it equal to the magnitude of the demand
                        if self.flying:
                            # Update the motor speed
                            self.heli.motor.set_motor_speed(throttle_demand)
                            # Update the swash plate position
                            self.heli.swash_plate.set_height(demand_value)
                    if demand == 'yaw_demand':
                        current_yaw_rate = gyro_rates[2]
                        demand_delta = demand_value - current_yaw_rate
                        # Only take action if we're outside the threshold range
                        if demand_delta > self._yaw_threshold:
                            print("Turning more left")
                            self.heli.turn_more_left()
                        elif demand_delta < -self._yaw_threshold:
                            print("Turning more right")
                            self.heli.turn_more_right()
                    if demand == 'pitch_demand':
                        pass
                    if demand == 'roll_demand':
                        pass
                    if demand == 'request_gyro_state_demand':
                        if demand_value:
                            print(
                                f"Gyro rates: {gyro_rates}, accelerations: {accelerations}"
                            )

    def stop_flying(self):
        """ Cleanly and safely shut down the helicopter """
        self.heli.stop()
        self.thread_running = False