Ejemplo n.º 1
0
def get_general_regularization_function(variables):

    weight_sym = cas.SX.sym('weight_sym', variables.cat.shape)
    var_sym = cas.SX.sym('var_sym', variables.cat.shape)
    ref_sym = cas.SX.sym('ref_sym', variables.cat.shape)

    diff = (var_sym - ref_sym)

    weight = cas.diag(weight_sym)

    diff_sq = cas.mtimes(cas.diag(diff), diff)
    reg = cas.mtimes(weight, diff_sq)

    reg_fun = cas.Function('reg_fun', [var_sym, ref_sym, weight_sym], [reg])

    return reg_fun
Ejemplo n.º 2
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
Ejemplo n.º 3
0
def var_scaled_to_si(var_type, var_name, var_scaled, scaling):

    scaling_defined_for_variable = (var_type in scaling.keys()) and (
        var_name in scaling[var_type].keys())
    if scaling_defined_for_variable:

        scale = scaling[var_type][var_name]

        if scale.shape == (1, 1):

            use_unit_scaling = (scale == cas.DM(1.)) or (scale == 1.)
            if use_unit_scaling:
                return var_scaled
            else:
                return var_scaled * scale
        else:
            matrix_factor = cas.diag(scale)
            return cas.mtimes(matrix_factor, var_scaled)

    else:
        return var_scaled
Ejemplo n.º 4
0
def get_force_and_moment(options, parameters, vec_u_earth, kite_dcm, omega,
                         delta, rho):

    # we use the vec_u_earth and the kite_dcm to give the relative orientation.
    # this means, that they must be in the same frame. otherwise, the frame of
    # the wind vector is not used in this function.

    alpha = indicators.get_alpha(vec_u_earth, kite_dcm)
    beta = indicators.get_beta(vec_u_earth, kite_dcm)

    airspeed = vect_op.norm(vec_u_earth)
    force_coeff_info, moment_coeff_info = stability_derivatives.stability_derivatives(
        options, alpha, beta, airspeed, omega, delta, parameters)

    force_info = {}
    moment_info = {}

    force_info['frame'] = force_coeff_info['frame']
    moment_info['frame'] = moment_coeff_info['frame']

    CF = force_coeff_info['coeffs']
    CM = moment_coeff_info['coeffs']

    # notice that magnitudes don't change under rotation
    dynamic_pressure = 1. / 2. * rho * cas.mtimes(vec_u_earth.T, vec_u_earth)
    planform_area = parameters['theta0', 'geometry', 's_ref']

    force = CF * dynamic_pressure * planform_area
    force_info['vector'] = force

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

    moment = dynamic_pressure * planform_area * cas.mtimes(
        reference_lengths, CM)
    moment_info['vector'] = moment

    return force_info, moment_info
Ejemplo n.º 5
0
def get_outputs(options, atmos, wind, variables, outputs, parameters,
                architecture):
    parent_map = architecture.parent_map
    kite_nodes = architecture.kite_nodes

    xd = variables['xd']
    u = variables['u']

    elevation_angle = indicators.get_elevation_angle(xd)

    for n in kite_nodes:

        parent = parent_map[n]

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

        r = cas.reshape(xd['r' + str(n) + str(parent)], (3, 3))
        ehat_span = r[:, 1]
        ehat_chord = r[:, 0]

        # wind parameters
        rho_infty = atmos.get_density(q[2])
        uw_infty = wind.get_velocity(q[2])

        # apparent air velocity
        if options['induction_model'] == 'actuator':
            ua = actuator_disk_flow.get_kite_effective_velocity(
                options, variables, wind, n, parent, architecture)
        else:
            ua = uw_infty - dq

        # relative air speed
        norm_ua_squared = cas.mtimes(ua.T, ua)
        ua_norm = norm_ua_squared**0.5

        # angle of attack and sideslip angle
        alpha = indicators.get_alpha(ua, r)
        beta = indicators.get_beta(ua, r)

        if int(options['surface_control']) == 0:
            delta = u['delta' + str(n) + str(parent)]
            omega = xd['omega' + str(n) + str(parent)]
            [CF, CM] = stability_derivatives.stability_derivatives(
                options, alpha, beta, ua, omega, delta, parameters)
        elif int(options['surface_control']) == 1:
            delta = xd['delta' + str(n) + str(parent)]
            omega = xd['omega' + str(n) + str(parent)]
            [CF, CM] = stability_derivatives.stability_derivatives(
                options, alpha, beta, ua, omega, delta, parameters)
        else:
            raise ValueError('unsupported surface_control chosen: %i',
                             options['surface_control'])

        # body-_frameforcecomponents
        # notice that these are unusual because an apparent wind reference coordinate system is in use.
        # see below (get_coeffs_from_control_surfaces) for information
        CA = CF[0]
        CY = CF[1]
        CN = CF[2]

        Cl = CM[0]
        Cm = CM[1]
        Cn = CM[2]

        dynamic_pressure = 1. / 2. * rho_infty * norm_ua_squared
        planform_area = parameters['theta0', 'geometry', 's_ref']
        ftilde_aero = cas.mtimes(r, CF)
        f_aero = dynamic_pressure * planform_area * ftilde_aero

        ehat_drag = vect_op.normalize(ua)
        f_drag = cas.mtimes(cas.mtimes(f_aero.T, ehat_drag), ehat_drag)

        ehat_lift = vect_op.normed_cross(ua, ehat_span)
        f_lift = cas.mtimes(cas.mtimes(f_aero.T, ehat_lift), ehat_lift)

        f_side = f_aero - f_drag - f_lift

        drag_cross_lift = indicators.convert_from_body_to_wind_axes(
            alpha, beta, CF)
        CD = drag_cross_lift[0]
        CS = drag_cross_lift[1]
        CL = drag_cross_lift[2]

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

        reference_lengths = cas.diag(cas.vertcat(b_ref, c_ref, b_ref))
        m_aero = dynamic_pressure * planform_area * cas.mtimes(
            reference_lengths, CM)

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

        outputs = indicators.collect_kite_aerodynamics_outputs(
            options, atmos, ua, ua_norm, aero_coefficients, f_aero, f_lift,
            f_drag, f_side, m_aero, ehat_chord, ehat_span, r, q, n, outputs,
            parameters)
        outputs = indicators.collect_environmental_outputs(
            atmos, wind, q, n, outputs)
        outputs = indicators.collect_aero_validity_outputs(
            options, xd, ua, n, parent, outputs, parameters)
        outputs = indicators.collect_local_performance_outputs(
            options, atmos, wind, variables, CL, CD, elevation_angle, ua, n,
            parent, outputs, parameters)
        outputs = indicators.collect_power_balance_outputs(
            variables, n, outputs, architecture)

    return outputs
Ejemplo n.º 6
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
Ejemplo n.º 7
0
def from_control_to_body(vector):
    rot = cas.diag(cas.DM([-1., 1., -1.]))
    transformed = cas.mtimes(rot, vector)
    return transformed