Пример #1
0
def get_list_from_last_ring(options, variables, architecture, kite):

    wake_nodes = options['induction']['vortex_wake_nodes']
    rings = wake_nodes - 1

    if rings < 1:
        message = 'insufficient wake nodes for creating a filament list: wake_nodes = ' + str(
            wake_nodes)
        awelogger.logger.error(message)
        return []

    last_tracked_wake_node = wake_nodes - 1
    ring = rings

    far_convection_time = options['induction']['vortex_far_convection_time']
    u_ref = options['induction']['vortex_u_ref']

    LENE = tools.get_wake_node_position_si(options, variables, kite, 'int',
                                           last_tracked_wake_node)
    LEPE = tools.get_wake_node_position_si(options, variables, kite, 'ext',
                                           last_tracked_wake_node)

    TENE = LENE + far_convection_time * u_ref * vect_op.xhat()
    TEPE = LEPE + far_convection_time * u_ref * vect_op.xhat()

    strength_prev = tools.get_ring_strength_si(options, variables, kite,
                                               ring - 1)
    strength = strength_prev

    filament_list = make_horseshoe_list(LENE, LEPE, TEPE, TENE, strength,
                                        strength_prev)
    return filament_list
Пример #2
0
def get_induction_factor_at_observer(options,
                                     filament_list,
                                     x_obs,
                                     u_zero,
                                     n_hat=vect_op.xhat()):
    u_ind = get_induced_velocity_at_observer(options,
                                             filament_list,
                                             x_obs,
                                             n_hat=n_hat)
    a_calc = -1. * u_ind / u_zero
    return a_calc
Пример #3
0
def get_body_axes(q_upper, q_lower):

    tether = q_upper - q_lower

    xhat = vect_op.xhat()
    yhat = vect_op.yhat()

    ehat_z = vect_op.normalize(tether)
    ehat_x = vect_op.normed_cross(yhat, tether)
    ehat_y = vect_op.normed_cross(ehat_z, ehat_x)

    return ehat_x, ehat_y, ehat_z
Пример #4
0
def get_MM_matrix():
    MM11 = 1.69765
    MM22 = 0.113177
    MM33 = 0.113177

    MM_col1 = MM11 * vect_op.xhat()
    MM_col2 = MM22 * vect_op.yhat()
    MM_col3 = MM33 * vect_op.zhat()

    MM = cas.horzcat(MM_col1, MM_col2, MM_col3)

    return MM
Пример #5
0
def test(test_list):

    options = {}
    options['induction'] = {}
    options['induction']['vortex_epsilon'] = 0.

    x_obs = 0.5 * vect_op.xhat_np()

    u_ind = get_induced_velocity_at_observer(options, test_list, x_obs)

    xhat_component = cas.mtimes(u_ind.T, vect_op.xhat())
    if not (xhat_component == 0):
        message = 'induced velocity at observer does not work as expected. ' \
                  'test u_ind component in plane of QSVR (along xhat) is ' + str(xhat_component)
        awelogger.logger.error(message)
        raise Exception(message)

    yhat_component = cas.mtimes(u_ind.T, vect_op.yhat())
    if not (yhat_component == 0):
        message = 'induced velocity at observer does not work as expected. ' \
                  'test u_ind component in plane of QSVR (along yhat) is ' + str(yhat_component)
        awelogger.logger.error(message)
        raise Exception(message)

    zhat_component = cas.mtimes(u_ind.T, vect_op.zhat())
    sign_along_zhat = vect_op.sign(zhat_component)
    sign_comparison = (sign_along_zhat - (-1))**2.
    if not (sign_comparison < 1.e-8):
        message = 'induced velocity at observer does not work as expected. ' \
                  'sign of test u_ind component out-of-plane of QSVR (projected on zhat) is ' + str(sign_along_zhat)
        awelogger.logger.error(message)
        raise Exception(message)

    calculated_norm = vect_op.norm(u_ind)
    expected_norm = 0.752133
    norm_comparison = (calculated_norm - expected_norm)**2.
    if not (norm_comparison < 1.e-8):
        message = 'induced velocity at observer does not work as expected. ' \
                  'squared difference of norm of test u_ind vector is ' + str(norm_comparison)
        awelogger.logger.error(message)
        raise Exception(message)

    return None
Пример #6
0
def get_induction_factor_at_kite(options,
                                 filament_list,
                                 wind,
                                 variables,
                                 parameters,
                                 architecture,
                                 kite_obs,
                                 n_hat=vect_op.xhat()):

    x_obs = variables['xd']['q' + str(kite_obs) +
                            str(architecture.parent_map[kite_obs])]

    parent = architecture.parent_map[kite_obs]
    u_zero_vec = actuator_flow.get_uzero_vec(options, wind, parent, variables,
                                             parameters, architecture)
    u_zero = vect_op.smooth_norm(u_zero_vec)

    a_calc = get_induction_factor_at_observer(options,
                                              filament_list,
                                              x_obs,
                                              u_zero,
                                              n_hat=n_hat)

    return a_calc
Пример #7
0
def test():

    point_obs = vect_op.yhat()
    point_1 = 1000. * vect_op.zhat()
    point_2 = -1. * point_1
    Gamma = 1.
    epsilon = 1.e-2
    seg_data = cas.vertcat(point_obs, point_1, point_2, Gamma, epsilon)

    vec_found = filament(seg_data)
    val_normalize = 1. / (2. * np.pi)
    vec_norm = vec_found / val_normalize

    difference = vec_norm - vect_op.xhat()
    resi = cas.mtimes(difference.T, difference)

    thresh = 1.e-6
    if resi > thresh:
        message = 'biot-savart filament induction test gives error of size: ' + str(
            resi)
        awelogger.logger.error(message)
        raise Exception(message)

    return None
Пример #8
0
def get_aerodynamic_outputs(options, atmos, wind, variables, outputs,
                            parameters, architecture):

    xd = variables['xd']

    b_ref = parameters['theta0', 'geometry', 'b_ref']
    c_ref = parameters['theta0', 'geometry', 'c_ref']
    s_ref = parameters['theta0', 'geometry', 's_ref']
    reference_lengths = cas.diag(cas.vertcat(b_ref, c_ref, b_ref))

    kite_nodes = architecture.kite_nodes
    for kite in kite_nodes:
        parent = architecture.parent_map[kite]

        q = xd['q' + str(kite) + str(parent)]
        dq = xd['dq' + str(kite) + str(parent)]

        vec_u_eff = tools.get_u_eff_in_earth_frame(options, variables, wind,
                                                   kite, architecture)
        u_eff = vect_op.smooth_norm(vec_u_eff)
        rho = atmos.get_density(q[2])
        q_eff = 0.5 * rho * cas.mtimes(vec_u_eff.T, vec_u_eff)

        if int(options['kite_dof']) == 3:
            kite_dcm = three_dof_kite.get_kite_dcm(options, variables, wind,
                                                   kite, architecture)
        elif int(options['kite_dof']) == 6:
            kite_dcm = six_dof_kite.get_kite_dcm(kite, variables, architecture)
        else:
            message = 'unsupported kite_dof chosen in options: ' + str(
                options['kite_dof'])
            awelogger.logger.error(message)

        if int(options['kite_dof']) == 3:
            framed_forces = tools.get_framed_forces(vec_u_eff, kite_dcm,
                                                    variables, kite,
                                                    architecture)
            m_aero_body = cas.DM.zeros((3, 1))
        elif int(options['kite_dof']) == 6:
            framed_forces = tools.get_framed_forces(vec_u_eff, kite_dcm,
                                                    variables, kite,
                                                    architecture)
            framed_moments = tools.get_framed_moments(vec_u_eff, kite_dcm,
                                                      variables, kite,
                                                      architecture)
            m_aero_body = framed_moments['body']
        else:
            message = 'unsupported kite_dof chosen in options: ' + str(
                options['kite_dof'])
            awelogger.logger.error(message)

        f_aero_body = framed_forces['body']
        f_aero_wind = framed_forces['wind']
        f_aero_control = framed_forces['control']
        f_aero_earth = framed_forces['earth']

        coeff_body = f_aero_body / q_eff / s_ref
        CA = coeff_body[0]
        CY = coeff_body[1]
        CN = coeff_body[2]

        f_drag_wind = f_aero_wind[0] * vect_op.xhat()
        f_side_wind = f_aero_wind[1] * vect_op.yhat()
        f_lift_wind = f_aero_wind[2] * vect_op.zhat()

        f_drag_earth = frames.from_wind_to_earth(vec_u_eff, kite_dcm,
                                                 f_drag_wind)
        f_side_earth = frames.from_wind_to_earth(vec_u_eff, kite_dcm,
                                                 f_side_wind)
        f_lift_earth = frames.from_wind_to_earth(vec_u_eff, kite_dcm,
                                                 f_lift_wind)

        coeff_wind = f_aero_wind / q_eff / s_ref
        CD = coeff_wind[0]
        CS = coeff_wind[1]
        CL = coeff_wind[2]

        CM = cas.mtimes(cas.inv(reference_lengths),
                        m_aero_body) / q_eff / s_ref
        Cl = CM[0]
        Cm = CM[1]
        Cn = CM[2]

        aero_coefficients = {}
        aero_coefficients['CD'] = CD
        aero_coefficients['CS'] = CS
        aero_coefficients['CL'] = CL
        aero_coefficients['CA'] = CA
        aero_coefficients['CY'] = CY
        aero_coefficients['CN'] = CN
        aero_coefficients['Cl'] = Cl
        aero_coefficients['Cm'] = Cm
        aero_coefficients['Cn'] = Cn
        aero_coefficients['LoverD'] = CL / CD

        base_aerodynamic_quantities = {}
        base_aerodynamic_quantities['kite'] = kite
        base_aerodynamic_quantities['air_velocity'] = vec_u_eff
        base_aerodynamic_quantities['airspeed'] = u_eff
        base_aerodynamic_quantities['aero_coefficients'] = aero_coefficients
        base_aerodynamic_quantities['f_aero_earth'] = f_aero_earth
        base_aerodynamic_quantities['f_aero_body'] = f_aero_body
        base_aerodynamic_quantities['f_aero_control'] = f_aero_control
        base_aerodynamic_quantities['f_aero_wind'] = f_aero_wind
        base_aerodynamic_quantities['f_lift_earth'] = f_lift_earth
        base_aerodynamic_quantities['f_drag_earth'] = f_drag_earth
        base_aerodynamic_quantities['f_side_earth'] = f_side_earth
        base_aerodynamic_quantities['m_aero_body'] = m_aero_body
        base_aerodynamic_quantities['kite_dcm'] = kite_dcm
        base_aerodynamic_quantities['q'] = q
        base_aerodynamic_quantities['dq'] = dq

        outputs = indicators.collect_kite_aerodynamics_outputs(
            options, architecture, atmos, wind, variables, parameters,
            base_aerodynamic_quantities, outputs)
        outputs = indicators.collect_environmental_outputs(
            atmos, wind, base_aerodynamic_quantities, outputs)
        outputs = indicators.collect_aero_validity_outputs(
            options, base_aerodynamic_quantities, outputs)
        outputs = indicators.collect_local_performance_outputs(
            architecture, atmos, wind, variables, parameters,
            base_aerodynamic_quantities, outputs)
        outputs = indicators.collect_power_balance_outputs(
            options, architecture, variables, base_aerodynamic_quantities,
            outputs)

    return outputs
Пример #9
0
def compute_vortex_verification_points(plot_dict, cosmetics, idx_at_eval, kdx):

    kite_plane_induction_params = get_kite_plane_induction_params(
        plot_dict, idx_at_eval)

    architecture = plot_dict['architecture']
    filament_list = reconstruct_filament_list(plot_dict, idx_at_eval)
    number_of_kites = architecture.number_of_kites

    radius = kite_plane_induction_params['average_radius']
    center = kite_plane_induction_params['center']
    u_infty = kite_plane_induction_params['u_infty']

    u_zero = u_infty

    verification_points = plot_dict['options']['model']['aero']['vortex'][
        'verification_points']
    half_points = int(verification_points / 2.) + 1

    psi0_base = plot_dict['options']['solver']['initialization']['psi0_rad']

    mu_grid_min = kite_plane_induction_params['mu_start_by_path']
    mu_grid_max = kite_plane_induction_params['mu_end_by_path']
    psi_grid_min = psi0_base - np.pi / float(number_of_kites) + float(
        kdx) * 2. * np.pi / float(number_of_kites)
    psi_grid_max = psi0_base + np.pi / float(number_of_kites) + float(
        kdx) * 2. * np.pi / float(number_of_kites)

    # define mu with respect to kite mid-span radius
    mu_grid_points = np.linspace(mu_grid_min,
                                 mu_grid_max,
                                 verification_points,
                                 endpoint=True)
    length_mu = mu_grid_points.shape[0]

    beta = np.linspace(0., np.pi / 2, half_points)
    cos_front = 0.5 * (1. - np.cos(beta))
    cos_back = -1. * cos_front[::-1]
    psi_grid_unscaled = cas.vertcat(cos_back, cos_front) + 0.5
    psi_grid_points_cas = psi_grid_unscaled * (psi_grid_max -
                                               psi_grid_min) + psi_grid_min

    psi_grid_points_np = np.array(psi_grid_points_cas)
    psi_grid_points_recenter = np.deg2rad(np.rad2deg(psi_grid_points_np))
    psi_grid_points = np.unique(psi_grid_points_recenter)

    length_psi = psi_grid_points.shape[0]

    # reserve mesh space
    y_matr = np.ones((length_psi, length_mu))
    z_matr = np.ones((length_psi, length_mu))
    a_matr = np.ones((length_psi, length_mu))

    for mdx in range(length_mu):
        mu_val = mu_grid_points[mdx]

        for pdx in range(length_psi):
            psi_val = psi_grid_points[pdx]

            r_val = mu_val * radius

            ehat_radial = vect_op.zhat_np() * cas.cos(
                psi_val) - vect_op.yhat_np() * cas.sin(psi_val)
            added = r_val * ehat_radial
            x_obs = center + added

            unscaled = mu_val * ehat_radial

            a_ind = float(
                vortex_flow.get_induction_factor_at_observer(
                    plot_dict['options']['model'],
                    filament_list,
                    x_obs,
                    u_zero,
                    n_hat=vect_op.xhat()))

            unscaled_y_val = float(cas.mtimes(unscaled.T, vect_op.yhat_np()))
            unscaled_z_val = float(cas.mtimes(unscaled.T, vect_op.zhat_np()))

            y_matr[pdx, mdx] = unscaled_y_val
            z_matr[pdx, mdx] = unscaled_z_val
            a_matr[pdx, mdx] = a_ind

    y_list = np.array(cas.reshape(y_matr, (length_psi * length_mu, 1)))
    z_list = np.array(cas.reshape(z_matr, (length_psi * length_mu, 1)))

    return y_matr, z_matr, a_matr, y_list, z_list
Пример #10
0
def get_ehat_tether(options):
    inclination = options['incid_deg'] * np.pi / 180.
    ehat_tether = np.cos(inclination) * vect_op.xhat() + np.sin(
        inclination) * vect_op.zhat()

    return ehat_tether
Пример #11
0
def __process_interpolation_Variables(interpolation_variables, configurations,
                                      model):
    """Create casadi functions mapping interpolation variables to states

    :type interpolation_variables: dict
    :param interpolation_variables: variables defining the interpolation

    :type configurations: dict
    :param configurations: parameters defining a given configuration

    :type model: awebox.model_dir.model
    :param model: system model

    :rtype: dict, casadi.struct_symSX
    """

    # initialize dict
    rotation_matrix = {}
    rotation_matrix['q00'] = np.eye(3)
    rotation_matrix['dq00'] = np.zeros([3, 3])

    kite_nodes = model.architecture.kite_nodes
    parent_nodes = model.architecture.parent_map
    parent_nodes[0] = 0
    number_of_nodes = model.architecture.number_of_nodes
    kite_dof = model.kite_dof
    trajectory_type = model.options['trajectory']['type']

    conf_0 = configurations['conf_0']
    conf_f = configurations['conf_f']
    l_s = configurations['l_s']
    l_i = configurations['l_i']

    ## generate casadi expressions

    # generate symbolic variables
    sinterp = __get_sstruct(interpolation_variables)
    sstates = {}
    sstates['var'] = {}
    sstates['var']['q00'] = 0.
    sstates['dvar'] = {}
    sstates['dvar']['q00'] = 0.
    sstates['ddvar'] = {}
    sstates['ddvar']['q00'] = 0.

    # generate dict to store functions in
    sstates_functions = {}

    # generate casadi functions: inteprolation variables -> states
    l_t = sinterp['var', 'l_t']
    for node in range(1, number_of_nodes):
        parent_node = parent_nodes[node]
        node_str = str(node) + str(parent_node)
        grandparent_node = parent_nodes[parent_node]
        parent_str = str(parent_node) + str(grandparent_node)
        grandgrandparent_node = parent_nodes[grandparent_node]
        grandparent_str = str(grandparent_node) + str(grandgrandparent_node)

        if (node == 1) and (
                node not in kite_nodes
        ):  # first node parameterized with main tether length
            a = cas.mtimes((conf_f['q' + node_str] - conf_0['q' + node_str]).T,
                           (conf_f['q' + node_str] - conf_0['q' + node_str]))
            if a == 0:
                e_t = vect_op.normalize(conf_0['q' + node_str])
            else:
                b = 2 * cas.mtimes(
                    conf_0['q' + node_str].T,
                    (conf_f['q' + node_str] - conf_0['q' + node_str]))
                c = cas.mtimes(conf_0['q' + node_str].T,
                               conf_0['q' + node_str]) - l_t**2
                D = b**2 - 4 * a * c
                x1 = (-b + np.sqrt(D)) / (2 * a)
                x2 = (-b - np.sqrt(D)) / (2 * a)
                #if x2 >= 0:
                #    s = x2
                #else:
                #    s = x1
                s = x1
                e_t = 1. / l_t * (
                    conf_0['q' + node_str] + s *
                    (conf_f['q' + node_str] - conf_0['q' + node_str]))
            sstates['var']['q' + node_str] = l_t * e_t
            rotation_matrix = compute_rotation_matrices(
                sinterp.prefix['var'], node_str, parent_str, rotation_matrix)

        else:
            if (node in kite_nodes):

                if node == 1:
                    tether_length = l_t
                else:
                    tether_length = l_s

                Phi = sinterp['var', 'Phi' + node_str]
                Omega = sinterp['var', 'Omega' + node_str]
                parent = sstates['var']['q' + parent_str]
                grandparent = sstates['var']['q' + grandparent_str]

                radius = tether_length * np.sin(Phi)
                l_x = tether_length * np.cos(Phi)

                # define axis of rotation
                if node != 1:
                    axis_of_rot = parent - grandparent
                    axis_of_rot = vect_op.normalize(axis_of_rot)
                else:
                    inclination = sinterp['var', 'inclination' + node_str]
                    axis_of_rot = np.zeros([3, 1])
                    axis_of_rot[0] = np.cos(inclination)
                    axis_of_rot[2] = np.sin(inclination)
                e_hat_x = axis_of_rot
                e_hat_y = vect_op.normed_cross(e_hat_x, vect_op.zhat())
                e_hat_z = vect_op.normed_cross(e_hat_y, e_hat_x)
                e_hat_r = e_hat_z * np.sin(Omega) + e_hat_y * np.cos(Omega)

                sstates['var']['q' + node_str] = sstates['var'][
                    'q' + parent_str] + e_hat_r * radius + e_hat_x * l_x

            else:
                tether_length = l_i
                rotation_matrix = compute_rotation_matrices(
                    sinterp.prefix['var'], node_str, parent_str,
                    rotation_matrix)
                tether_vector = vect_op.xhat()
                tether_vector = cas.mtimes(rotation_matrix['q' + node_str],
                                           tether_vector)
                sstates['var']['q' + node_str] = sstates['var'][
                    'q' + parent_str] + tether_vector * tether_length

        sstates['dvar']['q' + node_str] = cas.mtimes(
            cas.jacobian(sstates['var']['q' + node_str], sinterp['var']),
            sinterp['dvar'])

        # create rotational kinematics
        if int(kite_dof) == 6:

            # iterate over all kite ndoes
            if node in kite_nodes:

                # get node strings
                parent = parent_nodes[node]
                node_str = str(node) + str(parent)
                grandparent = parent_nodes[parent]
                parent_str = str(parent) + str(grandparent)
                grandgrandparent = parent_nodes[grandparent]
                grandparent_str = str(grandparent) + str(grandgrandparent)

                # compute dcm matrix for node
                e_hat_1, e_hat_2, e_hat_3 = __get_kite_axis(
                    sstates, node_str, parent_str, grandparent_str,
                    trajectory_type)
                dcm = ct.horzcat(e_hat_1, e_hat_2, e_hat_3)
                dcm_column = ct.reshape(dcm, (9, 1))

                # compute rotation around axis
                omega_norm = vect_op.norm(
                    sstates['dvar']['q' + node_str]) / radius
                if trajectory_type == 'lift_mode':
                    omega_vector = vect_op.normalize(axis_of_rot) * omega_norm
                elif trajectory_type == 'nominal_landing':
                    omega_vector = cas.DM([0, 0, 0])

                # put in state dict
                sstates['omega' + node_str] = omega_vector
                sstates['r' + node_str] = dcm_column

        # generate functions
        sstates_functions['q' + node_str] = cas.Function(
            'q' + node_str, [sinterp], [sstates['var']['q' + node_str]])
        sstates_functions['dq' + node_str] = cas.Function(
            'dq' + node_str, [sinterp], [sstates['dvar']['q' + node_str]])
        if int(kite_dof) == 6 and node in kite_nodes:
            sstates_functions['r' + node_str] = cas.Function(
                'r' + node_str, [sinterp], [sstates['r' + node_str]])
            sstates_functions['omega' + node_str] = cas.Function(
                'omega' + node_str, [sinterp], [sstates['omega' + node_str]])

    return sstates_functions, sinterp