def GetTimeSeries(self, params, sim, control): # Tether sphere radius at mean tether tension. # - The 0.75 factor applied to the tether tensile stiffness is used to # account for catenary effects. # - The extra 0.16 meter offset is used to account for the distance from # the bridle pivot to the origin of the body frame. tether_params = params['system_params']['tether'] wing_params = params['system_params']['wing'] mean_tether_sphere_radius = ( tether_params['length'] + self._mean_tether_tension / (0.75 * tether_params['tensile_stiffness'] / tether_params['length']) + wing_params['bridle_rad'] + 0.16) wing_xg, tether_xg_start = self._SelectTelemetry( sim, control, ['wing_xg', 'tether_xg_start']) if (scoring_util.IsSelectionValid(wing_xg) and scoring_util.IsSelectionValid(tether_xg_start)): tether_norm = np.linalg.norm( numpy_utils.Vec3ToArray(wing_xg) - numpy_utils.Vec3ToArray(tether_xg_start), axis=1) deviation = tether_norm - mean_tether_sphere_radius else: deviation = np.array([], dtype=float) return {'tether_sphere_deviation': deviation}
def GetTimeSeries(self, params, sim, control): buoy_accel_g = self._SelectTelemetry(sim, control, 'buoy_accel_g') try: buoy_accel_g_norm = np.sum(np.abs( numpy_utils.Vec3ToArray(buoy_accel_g))**2, axis=-1)**(1. / 2) except (TypeError, ValueError): buoy_accel_g_norm = np.array([float('nan')]) return {'buoy_accel_norm_gs': buoy_accel_g_norm / 9.81}
def GetTimeSeries(self, params, sim, control): wing_g, wind_g = self._SelectTelemetry( sim, control, ['wing_xg', 'wind_g_vector_f_slow']) # Only want xy ground components of wind and position. wing_xy = numpy_utils.Vec3ToArray(wing_g)[:, :2] wind_xy = numpy_utils.Vec3ToArray(wind_g)[:, :2] wind_mag = np.linalg.norm(wind_xy, axis=1) # Protect against divide by zero. # Overfly distance will be nan if wind_mag is zero. wind_mag[wind_mag == 0.0] = [float('nan')] # New axis for numpy to broadcast correctly for division. wind_unit_vec = wind_xy / wind_mag[:, np.newaxis] # Vectorized dot product of wing_xy and wind_unit_vec. overfly_dist = -np.sum(wing_xy * wind_unit_vec, axis=1) if np.all(np.isnan(overfly_dist)): return {'overfly_dist': float('nan')} else: return {'overfly_dist': overfly_dist}
def GetTimeSeries(self, params, sim, control): airspeeds, angular_rates, app_wind_b = self._SelectTelemetry( sim, control, ['airspeed', 'body_rates', 'apparent_wind_vector']) # Converts the indices into an (n,) sized array for 2D array masking. data_indices = np.reshape( np.argwhere(airspeeds > self._airspeed_threshold), -1) if data_indices.size == 0: wing_alphas_max = np.array([float('nan')]) wing_alphas_min = np.array([float('nan')]) else: # Mask the body rates for telemetry that crosses the threshold. omega_b = numpy_utils.Vec3ToArray(angular_rates)[data_indices] # Mask the cartesian wind for telemetry that crosses the threshold. wind_b = numpy_utils.Vec3ToArray(app_wind_b)[data_indices] # Compute the kinematic-based local values of alpha. # TODO: Wing_model should be mapped to enumerate wing models. wing_model = _WING_MODEL_HELPER.ShortName( int(params['system_params']['wing_model'][0])) wing_serial = _WING_SERIAL_HELPER.Name( int(params['system_params']['wing_serial'][0])) ssam = aero_ssam.SSAMModel(wing_model, wing_serial) wing_alphas_deg = ssam.GetMainWingAlphas(omega_b, wind_b) # Provide telemetry of maximum alphas anywhere along the main wing. # As per GetMainWingAlphas the expected size of wing_alphas_deg is (n, m) # where m is the number of wing panels and n is the number of elements in # the time series. wing_alphas_max = np.amax(wing_alphas_deg, axis=1) wing_alphas_min = np.amin(wing_alphas_deg, axis=1) return {'alphas_max': wing_alphas_max, 'alphas_min': wing_alphas_min}
def testH5MathHelpers(self): num_samples = 10 # A fake log file is used strictly to get appropriate dtypes for the Vec3 # and Mat3 timeseries. with tempfile.NamedTemporaryFile(suffix='.h5', delete=False) as tmp: file_name = tmp.name log_file = test_util.CreateSampleHDF5File(file_name, 1) state_est = (log_file['messages']['kAioNodeControllerA'] ['kMessageTypeControlTelemetry']['message']['state_est']) vec3 = numpy.zeros(num_samples, dtype=state_est['Xg'].dtype) mat3 = numpy.zeros(num_samples, dtype=state_est['dcm_g2b'].dtype) log_file.close() os.remove(file_name) # Populate vec3 and mat3 with random data. for axis in ('x', 'y', 'z'): vec3[axis] = numpy.random.rand(num_samples) mat3['d'] = numpy.random.rand(num_samples, 3, 3) # Test Vec3ToArray. Values of `vec3` and `array` should be bitwise # identical, so equality is appropriate. array = numpy_utils.Vec3ToArray(vec3) for i, axis in enumerate(('x', 'y', 'z')): self.assertTrue((array[:, i] == vec3[axis]).all()) # Test Vec3Norm. norm1 = (vec3['x']**2.0 + vec3['y']**2.0 + vec3['z']**2.0)**0.5 norm2 = numpy_utils.Vec3Norm(vec3) self.assertTrue((numpy.abs(norm1 - norm2) < 1e-15).all()) # Test Mat3Vec3Mult. mult = numpy_utils.Mat3Vec3Mult(mat3, vec3) for i in range(num_samples): b_expected = numpy.dot( mat3['d'][i], numpy.array([vec3['x'][i], vec3['y'][i], vec3['z'][i]])) self.assertTrue((numpy.abs(mult[i, :] - b_expected) < 1e-15).all()) # Test Mat3TransVec3Mult. trans_mult = numpy_utils.Mat3TransVec3Mult(mat3, vec3) for i in range(num_samples): b_expected = numpy.dot( mat3['d'][i].T, numpy.array([vec3['x'][i], vec3['y'][i], vec3['z'][i]])) self.assertTrue((numpy.abs(trans_mult[i, :] - b_expected) < 1e-15).all())