Esempio n. 1
0
def get_planar_dmc(vec_u_eff, variables, kite, architecture):

    parent = architecture.parent_map[kite]

    # get relevant variables for kite n
    q = variables['xd']['q' + str(kite) + str(parent)]

    # in kite body:
    if parent > 0:
        grandparent = architecture.parent_map[parent]
        q_parent = variables['xd']['q' + str(parent) + str(grandparent)]
    else:
        q_parent = np.array([0., 0., 0.])

    vec_t = q - q_parent # should be roughly "up-wards", ie, act like vec_w

    vec_v = vect_op.cross(vec_t, vec_u_eff)
    vec_w = vect_op.cross(vec_u_eff, vec_v)

    uhat = vect_op.smooth_normalize(vec_u_eff)
    vhat = vect_op.smooth_normalize(vec_v)
    what = vect_op.smooth_normalize(vec_w)

    planar_dcm = cas.horzcat(uhat, vhat, what)

    return planar_dcm
Esempio n. 2
0
def filament(seg_data, epsilon=1.e-2):

    try:
        point_obs = seg_data[:3]
        point_1 = seg_data[3:6]
        point_2 = seg_data[6:9]
        Gamma = seg_data[9]

        vec_1 = point_obs - point_1
        vec_2 = point_obs - point_2
        vec_0 = point_2 - point_1

        r1 = vect_op.smooth_norm(vec_1)
        r2 = vect_op.smooth_norm(vec_2)
        r0 = vect_op.smooth_norm(vec_0)

        factor = Gamma / (4. * np.pi)

        num = (r1 + r2)

        den_ori = (r1 * r2) * (r1 * r2 + cas.mtimes(vec_1.T, vec_2))
        den_reg = (epsilon * r0)**2.
        den = den_ori + den_reg

        dir = vect_op.cross(vec_1, vec_2)
        scale = factor * num / den

        sol = dir * scale
    except:
        message = 'something went wrong while computing the filament biot-savart induction. proceed with zero induced velocity from this filament.'
        awelogger.logger.error(message)
        raise Exception(message)

    return sol
Esempio n. 3
0
def get_plane_fit_n_vec(parent, variables, parameters, architecture):

    children = sorted(architecture.kites_map[parent])

    kite0 = children[0]
    kite1 = children[1]
    kite2 = children[2]

    # there is a potential failure here if the order of the kite nodes is not increaseing from kite0 -> kite1 -> kite2,
    # where the direction of the cross-product flips, based on initialization where the lower number kites have a
    # smaller azimuthal angle. presumably, this should be resulved by the sorting above, but, just in case!
    if (kite0 > kite1) or (kite1 > kite2):
        awelogger.logger.warning(
            'based on assignment order of kites, normal vector (by cross product) may point in reverse.'
        )

    qkite0 = variables['xd']['q' + str(kite0) + str(parent)]
    qkite1 = variables['xd']['q' + str(kite1) + str(parent)]
    qkite2 = variables['xd']['q' + str(kite2) + str(parent)]

    arm1 = qkite1 - qkite0
    arm2 = qkite2 - qkite0

    n_vec = vect_op.cross(arm1, arm2)

    b_ref = parameters['theta0', 'geometry', 'b_ref']
    varrho_temp = 8.

    scale = b_ref**2. * varrho_temp**2.
    n_vec = n_vec / scale

    return n_vec
Esempio n. 4
0
def get_total_drag(model_options, diam, q_upper, q_lower, dq_upper, dq_lower, atmos, wind, cd_tether_fun):

    elem = model_options['tether']['aero_elements']
    q_average = (q_upper + q_lower) / 2.

    total_force = np.zeros((3, 1))
    total_moment = np.zeros((3, 1))

    for idx in range(elem):

        loc_s_upper = float(idx + 1) / float(elem)
        loc_s_lower = float(idx) / float(elem)

        q_loc_upper = q_lower + loc_s_upper * (q_upper - q_lower)
        q_loc_lower = q_lower + loc_s_lower * (q_upper - q_lower)

        q_loc_average = (q_loc_lower + q_loc_upper)/2.
        moment_arm = q_average - q_loc_average

        dq_loc_upper = dq_lower + loc_s_upper * (dq_upper - dq_lower)
        dq_loc_lower = dq_lower + loc_s_lower * (dq_upper - dq_lower)

        loc_force = get_segment_force(diam, q_loc_upper, q_loc_lower, dq_loc_upper, dq_loc_lower, atmos, wind, cd_tether_fun)

        loc_moment = vect_op.cross(moment_arm, loc_force)

        total_force = total_force + loc_force
        total_moment = total_moment + loc_moment

    return [total_force, total_moment]
Esempio n. 5
0
def approx_kite_tang_vector(variables, architecture, kite):

    parent = architecture.parent_map[kite]

    z_vec = tether_vector(variables, architecture, parent)
    r_vec = approx_kite_radius_vector(variables, architecture, kite)

    t_vec_dimensioned = vect_op.cross(z_vec, r_vec)

    return t_vec_dimensioned
Esempio n. 6
0
def approx_kite_normal_vector(variables, architecture, kite):

    # z cross r = t
    # r x t = n

    r_vec = approx_kite_radius_vector(variables, architecture, kite)
    t_vec = approx_kite_tang_vector(variables, architecture, kite)
    n_vec = vect_op.cross(r_vec, t_vec)

    return n_vec
Esempio n. 7
0
def generate_rotational_dynamics(variables, f_nodes, parameters, outputs,
                                 architecture):
    kite_nodes = architecture.kite_nodes
    parent_map = architecture.parent_map

    j_inertia = parameters['theta0', 'geometry', 'j']

    xd = variables['SI']['xd']
    xddot = variables['SI']['xddot']

    cstr_list = mdl_constraint.MdlConstraintList()

    for kite in kite_nodes:
        parent = parent_map[kite]
        moment = f_nodes['m' + str(kite) + str(parent)]

        rlocal = cas.reshape(xd['r' + str(kite) + str(parent)], (3, 3))
        drlocal = cas.reshape(xddot['dr' + str(kite) + str(parent)], (3, 3))

        omega = xd['omega' + str(kite) + str(parent)]
        omega_skew = vect_op.skew(omega)
        domega = xddot['domega' + str(kite) + str(parent)]

        tether_moment = outputs['tether_moments']['n{}{}'.format(kite, parent)]

        # moment = J dot(omega) + omega x (J omega) + [tether moment which is zero if holonomic constraints do not depend on omega]
        J_dot_omega = cas.mtimes(j_inertia, domega)
        omega_cross_J_omega = vect_op.cross(omega,
                                            cas.mtimes(j_inertia, omega))
        omega_derivative = moment - (J_dot_omega + omega_cross_J_omega +
                                     tether_moment)
        rotational_2nd_law = omega_derivative / vect_op.norm(
            cas.diag(j_inertia))

        rotation_dynamics_cstr = cstr_op.Constraint(expr=rotational_2nd_law,
                                                    name='rotation_dynamics' +
                                                    str(kite),
                                                    cstr_type='eq')
        cstr_list.append(rotation_dynamics_cstr)

        # Rdot = R omega_skew -> R ( kappa/2 (I - R.T R) + omega_skew )
        baumgarte = parameters['theta0', 'kappa_r']
        orthonormality = baumgarte / 2. * (cas.DM_eye(3) -
                                           cas.mtimes(rlocal.T, rlocal))
        ref_frame_deriv_matrix = drlocal - (cas.mtimes(
            rlocal, orthonormality + omega_skew))
        ref_frame_derivative = cas.reshape(ref_frame_deriv_matrix, (9, 1))

        ortho_cstr = cstr_op.Constraint(expr=ref_frame_derivative,
                                        name='ref_frame_deriv' + str(kite),
                                        cstr_type='eq')
        cstr_list.append(ortho_cstr)

    return cstr_list, outputs
Esempio n. 8
0
def get_binormal_n_vec(parent, variables, parameters, architecture):

    children = architecture.kites_map[parent]

    n_vec = np.zeros((3, 1))
    for kite in children:
        dqk = variables['xddot']['dq' + str(kite) + str(parent)]
        ddqk = variables['xddot']['ddq' + str(kite) + str(parent)]

        binormal_dim = vect_op.cross(dqk, ddqk)

        n_vec = n_vec + binormal_dim

    return n_vec
Esempio n. 9
0
def get_actuator_moment(model_options, variables, outputs, parent,
                        architecture):

    children = architecture.kites_map[parent]

    total_moment_aero = np.zeros((3, 1))
    for kite in children:
        aero_force = outputs['aerodynamics']['f_aero_earth' + str(kite)]
        kite_radius = actuator_geom.get_kite_radius_vector(
            model_options, kite, variables, architecture)
        aero_moment = vect_op.cross(kite_radius, aero_force)

        total_moment_aero = total_moment_aero + aero_moment

    return total_moment_aero
Esempio n. 10
0
def get_binormal_nhat(parent, variables, parameters, architecture):

    children = architecture.kites_map[parent]

    nvec = np.zeros((3, 1))
    for kite in children:
        dqk = variables['xddot']['dq' + str(kite) + str(parent)]
        ddqk = variables['xddot']['ddq' + str(kite) + str(parent)]

        binormal_dim = vect_op.cross(dqk, ddqk)

        nvec = nvec + binormal_dim

    scale = 1.e-3
    factor = scale * get_factor_var(parent, variables, parameters)
    nhat = nvec * factor

    return nhat
Esempio n. 11
0
def get_element_drag_and_moment_fun(wind, atmos, cd_tether_fun):

    info_sym = cas.SX.sym('info_sym', (16, 1))

    q_upper = info_sym[:3]
    q_lower = info_sym[3:6]
    dq_upper = info_sym[6:9]
    dq_lower = info_sym[9:12]
    diam = info_sym[12]
    q_seg_avg = info_sym[13:16]

    q_average = (q_upper + q_lower) / 2.
    zz = q_average[2]

    ua = get_uapp(q_upper, q_lower, dq_upper, dq_lower, wind)

    epsilon = 1.e-6

    ua_norm = vect_op.smooth_norm(ua, epsilon)
    ehat_ua = vect_op.smooth_normalize(ua, epsilon)

    tether = q_upper - q_lower

    length_sq = cas.mtimes(tether.T, tether)
    length_parallel_to_wind = cas.mtimes(tether.T, ehat_ua)
    length_perp_to_wind = vect_op.smooth_sqrt(
        length_sq - length_parallel_to_wind**2., epsilon)

    re_number = reynolds.get_reynolds_number(atmos, ua, diam, q_upper, q_lower)
    cd = cd_tether_fun(re_number)

    density = atmos.get_density(zz)
    drag = cd * 0.5 * density * ua_norm * diam * length_perp_to_wind * ua

    moment_arm = q_average - q_seg_avg
    moment = vect_op.cross(moment_arm, drag)

    element_drag_fun = cas.Function('element_drag_fun', [info_sym], [drag])
    element_moment_fun = cas.Function('element_moment_fun', [info_sym],
                                      [moment])

    return element_drag_fun, element_moment_fun
Esempio n. 12
0
def collect_kite_aerodynamics_outputs(options, architecture, atmos, wind,
                                      variables, parameters,
                                      base_aerodynamic_quantities, outputs):

    if 'aerodynamics' not in list(outputs.keys()):
        outputs['aerodynamics'] = {}

    # unpack
    kite = base_aerodynamic_quantities['kite']
    air_velocity = base_aerodynamic_quantities['air_velocity']
    aero_coefficients = base_aerodynamic_quantities['aero_coefficients']
    f_aero_earth = base_aerodynamic_quantities['f_aero_earth']
    f_aero_body = base_aerodynamic_quantities['f_aero_body']

    f_aero_control = base_aerodynamic_quantities['f_aero_control']
    f_aero_wind = base_aerodynamic_quantities['f_aero_wind']
    f_lift_earth = base_aerodynamic_quantities['f_lift_earth']
    f_drag_earth = base_aerodynamic_quantities['f_drag_earth']
    f_side_earth = base_aerodynamic_quantities['f_side_earth']
    m_aero_body = base_aerodynamic_quantities['m_aero_body']
    kite_dcm = base_aerodynamic_quantities['kite_dcm']
    q = base_aerodynamic_quantities['q']

    f_lift_earth_overwrite = options['aero']['overwrite']['f_lift_earth']
    if f_lift_earth_overwrite is not None:
        f_lift_earth = f_lift_earth_overwrite

    for name in set(base_aerodynamic_quantities['aero_coefficients'].keys()):
        outputs['aerodynamics'][
            name +
            str(kite)] = base_aerodynamic_quantities['aero_coefficients'][name]

    outputs['aerodynamics']['air_velocity' + str(kite)] = air_velocity
    airspeed = vect_op.norm(air_velocity)
    outputs['aerodynamics']['airspeed' + str(kite)] = airspeed
    outputs['aerodynamics']['u_infty' + str(kite)] = wind.get_velocity(q[2])

    rho = atmos.get_density(q[2])
    outputs['aerodynamics']['air_density' + str(kite)] = rho
    outputs['aerodynamics']['dyn_pressure' +
                            str(kite)] = 0.5 * rho * cas.mtimes(
                                air_velocity.T, air_velocity)

    ehat_chord = kite_dcm[:, 0]
    ehat_span = kite_dcm[:, 1]
    ehat_up = kite_dcm[:, 2]

    outputs['aerodynamics']['ehat_chord' + str(kite)] = ehat_chord
    outputs['aerodynamics']['ehat_span' + str(kite)] = ehat_span
    outputs['aerodynamics']['ehat_up' + str(kite)] = ehat_up

    outputs['aerodynamics']['f_aero_body' + str(kite)] = f_aero_body
    outputs['aerodynamics']['f_aero_control' + str(kite)] = f_aero_control
    outputs['aerodynamics']['f_aero_earth' + str(kite)] = f_aero_earth
    outputs['aerodynamics']['f_aero_wind' + str(kite)] = f_aero_wind

    ortho = cas.reshape(cas.mtimes(kite_dcm.T, kite_dcm) - np.eye(3), (9, 1))
    ortho_resi = cas.mtimes(ortho.T, ortho)
    outputs['aerodynamics']['ortho_resi' + str(kite)] = ortho_resi

    conversion_resis = []
    conversion_targets = {
        'control': f_aero_control,
        'earth': f_aero_earth,
        'wind': f_aero_wind
    }
    for f_aero_target in conversion_targets.values():
        resi = 1. - vect_op.norm(f_aero_target) / vect_op.norm(f_aero_body)
        conversion_resis = cas.vertcat(conversion_resis, resi)

    resi = vect_op.norm(f_aero_earth - f_lift_earth - f_drag_earth -
                        f_side_earth) / vect_op.norm(f_aero_body)
    conversion_resis = cas.vertcat(conversion_resis, resi)

    outputs['aerodynamics']['check_conversion' + str(kite)] = conversion_resis

    outputs['aerodynamics']['f_lift_earth' + str(kite)] = f_lift_earth
    outputs['aerodynamics']['f_drag_earth' + str(kite)] = f_drag_earth
    outputs['aerodynamics']['f_side_earth' + str(kite)] = f_side_earth

    b_ref = parameters['theta0', 'geometry', 'b_ref']
    c_ref = parameters['theta0', 'geometry', 'c_ref']

    circulation_cross = vect_op.smooth_norm(
        f_lift_earth) / b_ref / rho / vect_op.smooth_norm(
            vect_op.cross(air_velocity, ehat_span))
    circulation_cl = 0.5 * airspeed**2. * aero_coefficients[
        'CL'] * c_ref / vect_op.smooth_norm(
            vect_op.cross(air_velocity, ehat_span))

    outputs['aerodynamics']['circulation_cross' +
                            str(kite)] = circulation_cross
    outputs['aerodynamics']['circulation_cl' + str(kite)] = circulation_cl
    outputs['aerodynamics']['circulation' + str(kite)] = circulation_cross

    outputs['aerodynamics']['wingtip_ext' +
                            str(kite)] = q + ehat_span * b_ref / 2.
    outputs['aerodynamics']['wingtip_int' +
                            str(kite)] = q - ehat_span * b_ref / 2.

    outputs['aerodynamics']['fstar_aero' + str(kite)] = cas.mtimes(
        air_velocity.T, ehat_chord) / c_ref

    outputs['aerodynamics']['r' + str(kite)] = kite_dcm.reshape((9, 1))

    if int(options['kite_dof']) == 6:
        outputs['aerodynamics']['m_aero_body' + str(kite)] = m_aero_body

    outputs['aerodynamics']['mach' + str(kite)] = get_mach(
        options, atmos, air_velocity, q)
    outputs['aerodynamics']['reynolds' + str(kite)] = get_reynolds(
        options, atmos, air_velocity, q, parameters)

    return outputs