Пример #1
0
  def GetTimeSeries(self, params, sim, control):
    time, tether_elevation, tether_elevation_valid = self._SelectTelemetry(
        sim, control, ['time', 'tether_elevation', 'tether_elevation_valid'])
    if not (scoring_util.IsSelectionValid(tether_elevation) or
            scoring_util.IsSelectionValid(time)):
      return {'tether_elevation_std': np.array([float('nan')])}
    tether_elevation_deg = np.rad2deg(
        tether_elevation[tether_elevation_valid == 1])

    # Low pass, symmetrically (2nd order) filter the tether elevation.
    tether_elevation_deg_f = scoring_util.LpFiltFiltTimeSeries(
        time, tether_elevation_deg, self._cut_off_freq)

    # Calculate a rolling StDev of the difference between the raw signal and
    # the filtered signal.
    t_samp = scoring_util.GetTimeSamp(time)
    if np.isnan(t_samp):
      return {'tether_elevation_std': np.array([float('nan')])}
    n_window = int(self._t_window / t_samp)
    elevation_deviation_df = pd.DataFrame(
        tether_elevation_deg - tether_elevation_deg_f)
    tether_elevation_std = elevation_deviation_df.rolling(
        n_window, min_periods=n_window).std().values.flatten()

    return {'tether_elevation_std': tether_elevation_std}
Пример #2
0
    def GetTimeSeries(self, params, sim, control):
        time, tether_pitch = self._SelectTelemetry(sim, control,
                                                   ['time', 'tether_pitch'])
        if (not scoring_util.IsSelectionValid(time)
                or not scoring_util.IsSelectionValid(tether_pitch)):
            return {
                'min_sustained_tether_pitch': float('nan'),
                'max_sustained_tether_pitch': float('nan')
            }

        tether_pitch_deg = np.rad2deg(tether_pitch)

        # Low pass, symmetrically (2nd order) filter the tether pitch.
        cut_off_freq = 2.0
        tether_pitch_deg_f = scoring_util.LpFiltFiltTimeSeries(
            time, tether_pitch_deg, cut_off_freq)

        min_sustained_tether_pitch, max_sustained_tether_pitch = (
            scoring_util.GetSustainedValue(tether_pitch_deg_f,
                                           self._good_lower_limit,
                                           self._good_upper_limit,
                                           self._sustained_duration,
                                           scoring_util.GetTimeSamp(time)))

        return {
            'min_sustained_tether_pitch': min_sustained_tether_pitch,
            'max_sustained_tether_pitch': max_sustained_tether_pitch
        }
Пример #3
0
  def GetTimeSeries(self, params, sim, control):
    time = self._SelectTelemetry(sim, control, 'time')

    if scoring_util.IsSelectionValid(time):
      t_samp = scoring_util.GetTimeSamp(time)
      return {'sample_time_error': np.abs(np.diff(time) - t_samp)}
    else:
      return {'sample_time_error': np.array([float('nan')])}
Пример #4
0
    def GetTimeSeries(self, params, sim, control):
        # The detwist command is in [0, TETHER_DETWIST_REVS * 2 * pi).
        time, gs_detwist_cmd = self._SelectTelemetry(
            sim, control, ['time', 'gs_detwist_cmd'])
        dt = scoring_util.GetTimeSamp(time)
        if np.isnan(dt):
            return {'gs_detwist_cmd_rate': np.array([float('nan')])}

        gs_detwist_cmd_diff = diff_wrap_angle(
            pack_avionics_messages.TETHER_DETWIST_REVS, gs_detwist_cmd)
        gs_detwist_cmd_deriv = gs_detwist_cmd_diff / dt

        return {'gs_detwist_cmd_rate': np.rad2deg(gs_detwist_cmd_deriv)}
Пример #5
0
    def GetTimeSeries(self, params, sim, control):
        hover_params = params['control_params']['hover']

        thrust_moment, thrust_moment_avail, control_time = self._SelectTelemetry(
            sim, control, ['thrust_moment', 'thrust_moment_avail', 'time'])

        if (not scoring_util.IsSelectionValid(thrust_moment)
                or not scoring_util.IsSelectionValid(control_time)):
            return {'max_saturation_duration': float('nan')}

        if self._axis == 'thrust':
            cmd = thrust_moment['thrust']
            cmd_avail = thrust_moment_avail['thrust']
            min_software_limit = float('-infinity')
            max_software_limit = hover_params['altitude']['max_thrust']
        elif self._axis == 'moment_y':
            cmd = thrust_moment['moment']['y']
            cmd_avail = thrust_moment_avail['moment']['y']
            min_software_limit = hover_params['angles']['min_moment']['y']
            max_software_limit = hover_params['angles']['max_moment']['y']
        elif self._axis == 'moment_z':
            cmd = thrust_moment['moment']['z']
            cmd_avail = thrust_moment_avail['moment']['z']
            min_software_limit = hover_params['angles']['min_moment']['z']
            max_software_limit = hover_params['angles']['max_moment']['z']
        else:
            assert False, 'The axis %s is not supported.' % self._axis

        t_samp = scoring_util.GetTimeSamp(control_time)
        if np.isnan(t_samp):
            return {'max_saturation_duration': np.array([float('nan')])}

        saturation_mask = np.argwhere(
            np.logical_or(
                np.abs(cmd - cmd_avail) > 1e-2,
                np.logical_or(
                    np.abs(cmd - min_software_limit) < 1e-2,
                    np.abs(cmd - max_software_limit) < 1e-2)))

        if saturation_mask.size > 0:
            saturated_intervals = scoring_util.GetIntervals(saturation_mask)
            max_saturation_size = np.max([
                interval[1] - interval[0] for interval in saturated_intervals
            ])
        else:
            max_saturation_size = 0.0

        return {'max_saturation_duration': max_saturation_size * t_samp}
Пример #6
0
  def GetTimeSeries(self, params, sim, control):
    # TODO: Use the Gs02TransformStageFilter.
    if self._transform_stages:
      gs02_mode, gs02_transform_stage, tether_elevation = (
          self._SelectTelemetry(
              sim, control, ['gs02_mode', 'gs02_transform_stage',
                             'tether_elevation']))

      if (not scoring_util.IsSelectionValid(gs02_mode) or
          not scoring_util.IsSelectionValid(gs02_transform_stage) or
          not scoring_util.IsSelectionValid(tether_elevation)):
        return {
            'gs02_mode': None,
            'gs02_transform_stage': None,
            'tether_elevation': None
        }
      else:
        tether_elevation_deg = np.rad2deg(tether_elevation)
        return {
            'gs02_mode': gs02_mode,
            'gs02_transform_stage': gs02_transform_stage,
            'tether_elevation': tether_elevation_deg
        }
    else:
      time, tether_elevation = self._SelectTelemetry(
          sim, control, ['time', 'tether_elevation'])
      if not (scoring_util.IsSelectionValid(tether_elevation) or
              scoring_util.IsSelectionValid(time)):
        return {
            'tether_elevation': None
        }
      tether_elevation_deg = np.rad2deg(tether_elevation)

      # Low pass, symmetrically (2nd order) filter the tether elevation.
      cut_off_freq = 0.4
      tether_elevation_deg_f = scoring_util.LpFiltFiltTimeSeries(
          time, tether_elevation_deg, cut_off_freq)
      self._t_samp = scoring_util.GetTimeSamp(time)

      # Return filtered data.
      return {
          'tether_elevation': tether_elevation_deg_f
      }
Пример #7
0
    def GetTimeSeries(self, params, sim, control):
        time, gs_detwist_pos, loop_angle = self._SelectTelemetry(
            sim, control, ['time', 'gs_detwist_pos', 'loop_angle'])
        accum_loops = np.cumsum(np.diff(loop_angle) > np.deg2rad(350.))
        dt = scoring_util.GetTimeSamp(time)
        if np.isnan(dt):
            return {'gs_detwist_ratios_per_loop': []}

        # Obtain the derivative of the detwist angle to remove the steadily
        # decreasing ramp and the jump at every revolution. The frequency content
        # is preserved.
        # Wrapping first the detwist position to [0, 2*pi).
        gs_detwist_pos_diff = diff_wrap_angle(
            pack_avionics_messages.TETHER_DETWIST_REVS, gs_detwist_pos)
        gs_detwist_pos_deriv = gs_detwist_pos_diff / dt

        # Obtain the number of points in the FFT based on the desired frequency
        # resolution and the sampling time: frequency_resolution ~= fs/nfft Hz.
        frequency_resolution = 0.1  # [Hz]
        nfft = 2.0**np.ceil(np.log2(1.0 / dt / frequency_resolution))

        # Iterate through all loops.
        num_loops = np.floor(accum_loops[-1])
        if np.isnan(num_loops):
            num_loops = 0
        gs_detwist_ratios_per_loop = []
        for loop in range(1, int(num_loops) + 1):
            detwist_deriv_this_loop = gs_detwist_pos_deriv[np.where(
                np.floor(accum_loops).astype(int) == loop)]

            f_this_loop, pxx_this_loop = periodogram(detwist_deriv_this_loop,
                                                     fs=1.0 / dt,
                                                     nfft=int(nfft),
                                                     scaling='spectrum',
                                                     detrend=False)

            # Find the peaks in the spectrum.
            # Peaks are where the derivative changes sign and the second derivative
            # is negative.
            pxx_diff_this_loop = np.diff(10.0 * np.log10(pxx_this_loop))
            pxx_diff_sign_change_this_loop = (pxx_diff_this_loop[1:] *
                                              pxx_diff_this_loop[0:-1])
            pxx_diff_diff_this_loop = np.diff(pxx_diff_this_loop)
            min_freq = 0.25  # [Hz]
            pxx_peaks_idx_this_loop = np.where(
                (pxx_diff_sign_change_this_loop < 0.)
                & (pxx_diff_diff_this_loop < 0.)
                & (f_this_loop[0:-2] > min_freq))[0] + 1

            if pxx_peaks_idx_this_loop.size == 0:
                # No peaks were found.
                continue

            # Get the highest secondary lobe.
            max_peak_this_loop_db = 10.0 * np.log10(
                np.max(pxx_this_loop[pxx_peaks_idx_this_loop]))
            max_ratio_this_loop_db = (max_peak_this_loop_db -
                                      10.0 * np.log10(pxx_this_loop[0]))
            f_secondary_this_loop = f_this_loop[pxx_peaks_idx_this_loop[
                np.argmax(pxx_this_loop[pxx_peaks_idx_this_loop])]]

            # Store tuple (loop number, lobe frequency [Hz], lobe power ratio [dB]).
            gs_detwist_ratios_per_loop.append(
                (loop + 1, f_secondary_this_loop, max_ratio_this_loop_db))

        return {'gs_detwist_ratios_per_loop': gs_detwist_ratios_per_loop}