def derive(self, gnds=S('Grounded'),
               pitch=P('Pitch'), roll=P('Roll')):

        decks = []
        for gnd in gnds:
            # The fourier transform for pitching motion...
            p = pitch.array[gnd.slice]
            if np.all(p.mask):
                continue
            n = float(len(p)) # Scaling the result to be independet of data length.
            fft_p = np.abs(np.fft.rfft(p - moving_average(p))) / n

            # similarly for roll
            r = roll.array[gnd.slice]
            if np.all(r.mask):
                continue
            fft_r = np.abs(np.fft.rfft(r - moving_average(r))) / n

            # What was the maximum harmonic seen?
            fft_max = np.ma.max(fft_p + fft_r)

            # Values of less than 0.1 were on the ground, and 0.34 on deck for the one case seen to date.
            if fft_max > 0.2:
                decks.append(gnd.slice)
        if decks:
            self.create_sections(decks)
    def derive(self, gnds=S('Grounded'), pitch=P('Pitch'), roll=P('Roll')):

        decks = []
        for gnd in gnds:
            # The fourier transform for pitching motion...
            p = pitch.array[gnd.slice]
            if np.all(p.mask):
                continue
            n = float(
                len(p))  # Scaling the result to be independet of data length.
            fft_p = np.abs(np.fft.rfft(p - moving_average(p))) / n

            # similarly for roll
            r = roll.array[gnd.slice]
            if np.all(r.mask):
                continue
            fft_r = np.abs(np.fft.rfft(r - moving_average(r))) / n

            # What was the maximum harmonic seen?
            fft_max = np.ma.max(fft_p + fft_r)

            # Values of less than 0.1 were on the ground, and 0.34 on deck for the one case seen to date.
            if fft_max > 0.2:
                decks.append(gnd.slice)
        if decks:
            self.create_sections(decks)
Esempio n. 3
0
    def derive(self, alt_rad=P('Altitude Radio'),
               alt_aal=P('Altitude AAL'),
               alt_baro=P('Altitude STD Smoothed'),
               gog=M('Gear On Ground')):

        # If we have no Altitude Radio we will have to fall back to Altitude AAL
        if not alt_rad:
            self.array = alt_aal.array
            return

        # When was the helicopter on the ground?
        gear_on_grounds = np.ma.clump_masked(np.ma.masked_equal(gog.array, 1))
        # Find and eliminate short spikes (15 seconds) as these are most likely errors.
        short_spikes = slices_find_small_slices(gear_on_grounds, time_limit=20, hz=gog.hz)
        for _slice in short_spikes:
            gog.array[_slice.start:_slice.stop] = 0

        # Remove slices shorter than 15 seconds as these are most likely created in error.
        gear_on_grounds = slices_remove_small_slices(gear_on_grounds, time_limit=20, hz=gog.hz)
        # Compute the half period which we will need.
        hp = int(alt_rad.frequency*ALTITUDE_AGL_SMOOTHING) // 2

        # We force altitude AGL to be zero when the gear shows 'Ground' state
        alt_agl = moving_average(np.maximum(alt_rad.array, 0.0) * (1 - gog.array.data), window=hp*2+1, weightings=None)

        # Refine the baro estimates
        length = len(alt_agl)-1
        baro_sections = np.ma.clump_masked(np.ma.masked_greater(alt_agl, ALTITUDE_AGL_TRANS_ALT))
        for baro_section in baro_sections:
            begin = max(baro_section.start - 1, 0)
            end = min(baro_section.stop + 1, length)
            start_diff = alt_baro.array[begin] - alt_agl[begin]
            stop_diff = alt_baro.array[end] - alt_agl[end]
            if start_diff is not np.ma.masked and stop_diff is not np.ma.masked:
                diff = np.linspace(start_diff, stop_diff, end-begin-2)
                alt_agl[begin+1:end-1] = alt_baro.array[begin+1:end-1]-diff
            elif start_diff is not np.ma.masked:
                alt_agl[begin+1:end-1] = alt_baro.array[begin+1:end-1] - start_diff
            elif stop_diff is not np.ma.masked:
                alt_agl[begin+1:end-1] = alt_baro.array[begin+1:end-1] - stop_diff
            else:
                pass
        low_sections = np.ma.clump_unmasked(np.ma.masked_greater(alt_agl, 5))
        for both in slices_and(low_sections, gear_on_grounds):
            alt_agl[both] = 0.0

        '''
        # Quick visual check of the altitude agl.
        import matplotlib.pyplot as plt
        plt.plot(alt_baro.array, 'y-')
        plt.plot(alt_rad.array, 'r-')
        plt.plot(alt_agl, 'b-')
        plt.show()
        '''

        self.array = alt_agl
    def derive(self, alt_rad=P('Altitude Radio'),
               alt_aal=P('Altitude AAL'),
               alt_baro=P('Altitude STD Smoothed'),
               gog=M('Gear On Ground')):

        # If we have no Altitude Radio we will have to fall back to Altitude AAL
        if not alt_rad:
            self.array = alt_aal.array
            return

        # When was the helicopter on the ground?
        gear_on_grounds = np.ma.clump_masked(np.ma.masked_equal(gog.array, 1))
        # Find and eliminate short spikes (15 seconds) as these are most likely errors.
        short_spikes = slices_find_small_slices(gear_on_grounds, time_limit=15, hz=gog.hz)
        for slice in short_spikes:
            gog.array[slice.start:slice.stop] = 0

        # Remove slices shorter than 15 seconds as these are most likely created in error.
        gear_on_grounds = slices_remove_small_slices(gear_on_grounds, time_limit=15, hz=gog.hz)
        # Compute the half period which we will need.
        hp = int(alt_rad.frequency*ALTITUDE_AGL_SMOOTHING)//2
        # We force altitude AGL to be zero when the gear shows 'Ground' state
        alt_agl = moving_average(np.maximum(alt_rad.array, 0.0) * (1 - gog.array.data), window=hp*2+1, weightings=None)

        # Refine the baro estimates
        length = len(alt_agl)-1
        baro_sections = np.ma.clump_masked(np.ma.masked_greater(alt_agl, ALTITUDE_AGL_TRANS_ALT))
        for baro_section in baro_sections:
            begin = max(baro_section.start - 1, 0)
            end = min(baro_section.stop + 1, length)
            start_diff = alt_baro.array[begin] - alt_agl[begin]
            stop_diff = alt_baro.array[end] - alt_agl[end]
            if start_diff is not np.ma.masked and stop_diff is not np.ma.masked:
                diff = np.linspace(start_diff, stop_diff, end-begin-2)
                alt_agl[begin+1:end-1] = alt_baro.array[begin+1:end-1]-diff
            elif start_diff is not np.ma.masked:
                alt_agl[begin+1:end-1] = alt_baro.array[begin+1:end-1] - start_diff
            elif stop_diff is not np.ma.masked:
                alt_agl[begin+1:end-1] = alt_baro.array[begin+1:end-1] - stop_diff
            else:
                pass
        low_sections = np.ma.clump_unmasked(np.ma.masked_greater(alt_agl, 5))
        for both in slices_and(low_sections, gear_on_grounds):
            alt_agl[both] = 0.0

        '''
        # Quick visual check of the altitude agl.
        import matplotlib.pyplot as plt
        plt.plot(alt_baro.array, 'y-')
        plt.plot(alt_rad.array, 'r-')
        plt.plot(alt_agl, 'b-')
        plt.show()
        '''

        self.array = alt_agl
Esempio n. 5
0
 def derive(self,
            torq_max=P('Eng (*) Torque Max'),
            torq_min=P('Eng (*) Torque Min')):
     diff = (torq_max.array - torq_min.array)
     window = 5  # 5 second window
     self.array = moving_average(diff, window=window)
 def derive(self, torq_max=P('Eng (*) Torque Max'), torq_min=P('Eng (*) Torque Min')):
     diff = (torq_max.array - torq_min.array)
     window = 5 # 5 second window
     self.array = moving_average(diff, window=window)
    def derive(self,
               gl=M('Gear (L) On Ground'),
               gr=M('Gear (R) On Ground'),
               vert_spd=P('Vertical Speed'),
               torque=P('Eng (*) Torque Avg'),
               ac_series=A('Series'),
               collective=P('Collective')):

        if gl and gr:
            delta = abs((gl.offset - gr.offset) * gl.frequency)
            if 0.75 < delta or delta < 0.25:
                # If the samples of the left and right gear are close together,
                # the best representation is to map them onto a single
                # parameter in which we accept that either wheel on the ground
                # equates to gear on ground.
                self.array = np.ma.logical_or(gl.array, gr.array)
                self.frequency = gl.frequency
                self.offset = gl.offset
                return
            else:
                # If the paramters are not co-located, then
                # merge_two_parameters creates the best combination possible.
                self.array, self.frequency, self.offset = merge_two_parameters(
                    gl, gr)
                return
        elif gl or gr:
            gear = gl or gr
            self.array = gear.array
            self.frequency = gear.frequency
            self.offset = gear.offset
        elif vert_spd and torque:
            vert_spd_limit = 100.0
            torque_limit = 30.0
            if ac_series and ac_series.value == 'Columbia 234':
                vert_spd_limit = 125.0
                torque_limit = 22.0
                collective_limit = 15.0

                vert_spd_array = align(
                    vert_spd,
                    torque) if vert_spd.hz != torque.hz else vert_spd.array
                collective_array = align(
                    collective,
                    torque) if collective.hz != torque.hz else collective.array

                vert_spd_array = moving_average(vert_spd_array)
                torque_array = moving_average(torque.array)
                collective_array = moving_average(collective_array)

                roo_vs_array = runs_of_ones(
                    abs(vert_spd_array) < vert_spd_limit, min_samples=1)
                roo_torque_array = runs_of_ones(torque_array < torque_limit,
                                                min_samples=1)
                roo_collective_array = runs_of_ones(
                    collective_array < collective_limit, min_samples=1)

                vs_and_torque = slices_and(roo_vs_array, roo_torque_array)
                grounded = slices_and(vs_and_torque, roo_collective_array)

                array = np_ma_zeros_like(vert_spd_array)
                for _slice in slices_remove_small_slices(grounded, count=2):
                    array[_slice] = 1
                array.mask = vert_spd_array.mask | torque_array.mask
                array.mask = array.mask | collective_array.mask
                self.array = nearest_neighbour_mask_repair(array)
                self.frequency = torque.frequency
                self.offset = torque.offset

            else:
                vert_spd_array = align(
                    vert_spd,
                    torque) if vert_spd.hz != torque.hz else vert_spd.array
                # Introducted for S76 and Bell 212 which do not have Gear On Ground available

                vert_spd_array = moving_average(vert_spd_array)
                torque_array = moving_average(torque.array)

                grounded = slices_and(
                    runs_of_ones(abs(vert_spd_array) < vert_spd_limit,
                                 min_samples=1),
                    runs_of_ones(torque_array < torque_limit, min_samples=1))

                array = np_ma_zeros_like(vert_spd_array)
                for _slice in slices_remove_small_slices(grounded, count=2):
                    array[_slice] = 1
                array.mask = vert_spd_array.mask | torque_array.mask
                self.array = nearest_neighbour_mask_repair(array)
                self.frequency = torque.frequency
                self.offset = torque.offset

        else:
            # should not get here if can_operate is correct
            raise NotImplementedError()
    def derive(self,
               gl=M('Gear (L) On Ground'),
               gr=M('Gear (R) On Ground'),
               vert_spd=P('Vertical Speed'),
               torque=P('Eng (*) Torque Avg'),
               ac_series=A('Series'),
               collective=P('Collective')):

        if gl and gr:
            delta = abs((gl.offset - gr.offset) * gl.frequency)
            if 0.75 < delta or delta < 0.25:
                # If the samples of the left and right gear are close together,
                # the best representation is to map them onto a single
                # parameter in which we accept that either wheel on the ground
                # equates to gear on ground.
                self.array = np.ma.logical_or(gl.array, gr.array)
                self.frequency = gl.frequency
                self.offset = gl.offset
                return
            else:
                # If the paramters are not co-located, then
                # merge_two_parameters creates the best combination possible.
                self.array, self.frequency, self.offset = merge_two_parameters(gl, gr)
                return
        elif gl or gr:
            gear = gl or gr
            self.array = gear.array
            self.frequency = gear.frequency
            self.offset = gear.offset
        elif vert_spd and torque:
            vert_spd_limit = 100.0
            torque_limit = 30.0
            if ac_series and ac_series.value == 'Columbia 234':
                vert_spd_limit = 125.0
                torque_limit = 22.0
                collective_limit = 15.0

                vert_spd_array = align(vert_spd, torque) if vert_spd.hz != torque.hz else vert_spd.array
                collective_array = align(collective, torque) if collective.hz != torque.hz else collective.array

                vert_spd_array = moving_average(vert_spd_array)
                torque_array = moving_average(torque.array)
                collective_array = moving_average(collective_array)

                roo_vs_array = runs_of_ones(abs(vert_spd_array) < vert_spd_limit, min_samples=1)
                roo_torque_array = runs_of_ones(torque_array < torque_limit, min_samples=1)
                roo_collective_array = runs_of_ones(collective_array < collective_limit, min_samples=1)

                vs_and_torque = slices_and(roo_vs_array, roo_torque_array)
                grounded = slices_and(vs_and_torque, roo_collective_array)

                array = np_ma_zeros_like(vert_spd_array)
                for _slice in slices_remove_small_slices(grounded, count=2):
                    array[_slice] = 1
                array.mask = vert_spd_array.mask | torque_array.mask
                array.mask = array.mask | collective_array.mask
                self.array = nearest_neighbour_mask_repair(array)
                self.frequency = torque.frequency
                self.offset = torque.offset

            else:
                vert_spd_array = align(vert_spd, torque) if vert_spd.hz != torque.hz else vert_spd.array
                # Introducted for S76 and Bell 212 which do not have Gear On Ground available

                vert_spd_array = moving_average(vert_spd_array)
                torque_array = moving_average(torque.array)

                grounded = slices_and(runs_of_ones(abs(vert_spd_array) < vert_spd_limit, min_samples=1),
                                      runs_of_ones(torque_array < torque_limit, min_samples=1))

                array = np_ma_zeros_like(vert_spd_array)
                for _slice in slices_remove_small_slices(grounded, count=2):
                    array[_slice] = 1
                array.mask = vert_spd_array.mask | torque_array.mask
                self.array = nearest_neighbour_mask_repair(array)
                self.frequency = torque.frequency
                self.offset = torque.offset

        else:
            # should not get here if can_operate is correct
            raise NotImplementedError()
    def derive(self,
               vert_spd=P('Vertical Speed'),
               torque=P('Eng (*) Torque Avg'),
               ac_series=A('Series'),
               collective=P('Collective')):

        vert_spd_limit = 100.0
        torque_limit = 30.0
        if ac_series and ac_series.value == 'Columbia 234':
            vert_spd_limit = 125.0
            torque_limit = 22.0
            collective_limit = 15.0

            vert_spd_array = align(
                vert_spd,
                torque) if vert_spd.hz != torque.hz else vert_spd.array
            collective_array = align(
                collective,
                torque) if collective.hz != torque.hz else collective.array

            vert_spd_array = moving_average(vert_spd_array)
            torque_array = moving_average(torque.array)
            collective_array = moving_average(collective_array)

            roo_vs_array = runs_of_ones(abs(vert_spd_array) < vert_spd_limit,
                                        min_samples=1)
            roo_torque_array = runs_of_ones(torque_array < torque_limit,
                                            min_samples=1)
            roo_collective_array = runs_of_ones(
                collective_array < collective_limit, min_samples=1)

            vs_and_torque = slices_and(roo_vs_array, roo_torque_array)
            grounded = slices_and(vs_and_torque, roo_collective_array)

            array = np_ma_zeros_like(vert_spd_array)
            for _slice in slices_remove_small_slices(grounded, count=2):
                array[_slice] = 1
            array.mask = vert_spd_array.mask | torque_array.mask
            array.mask = array.mask | collective_array.mask
            self.array = nearest_neighbour_mask_repair(array)
            self.frequency = torque.frequency
            self.offset = torque.offset

        else:
            vert_spd_array = align(
                vert_spd,
                torque) if vert_spd.hz != torque.hz else vert_spd.array
            # Introducted for S76 and Bell 212 which do not have Gear On Ground available

            vert_spd_array = moving_average(vert_spd_array)
            torque_array = moving_average(torque.array)

            grounded = slices_and(
                runs_of_ones(abs(vert_spd_array) < vert_spd_limit,
                             min_samples=1),
                runs_of_ones(torque_array < torque_limit, min_samples=1))

            array = np_ma_zeros_like(vert_spd_array)
            for _slice in slices_remove_small_slices(grounded, count=2):
                array[_slice] = 1
            array.mask = vert_spd_array.mask | torque_array.mask
            self.array = nearest_neighbour_mask_repair(array)
            self.frequency = torque.frequency
            self.offset = torque.offset