Esempio n. 1
0
def compute_mass_matrix(dae, conf, f1, f2, f3, t1, t2, t3):
    '''
    take the dae that has x/z/u/p added to it already and return
    the states added to it and return mass matrix and rhs of the dae residual
    '''

    R_b2n = dae['R_n2b'].T
    r_n2b_n = C.veccat([dae['r_n2b_n_x'], dae['r_n2b_n_y'], dae['r_n2b_n_z']])
    r_b2bridle_b = C.veccat([0,0,conf['zt']])
    v_bn_n = C.veccat([dae['v_bn_n_x'],dae['v_bn_n_y'],dae['v_bn_n_z']])

    r_n2bridle_n = r_n2b_n + C.mul(R_b2n, r_b2bridle_b)

    mm00 = C.diag([1,1,1]) * (conf['mass'] + conf['tether_mass']/3.0)
    mm01 = C.SXMatrix(3,3)
    mm10 = mm01.T
    mm02 = r_n2bridle_n
    mm20 = mm02.T
    J = C.blockcat([[ conf['j1'],          0, conf['j31']],
                    [          0, conf['j2'],           0],
                    [conf['j31'],          0,  conf['j3']]])
    mm11 = J
    mm12 = C.cross(r_b2bridle_b, C.mul(dae['R_n2b'], r_n2b_n))
    mm21 = mm12.T
    mm22 = C.SXMatrix(1,1)

    mm = C.blockcat([[mm00,mm01,mm02],
                     [mm10,mm11,mm12],
                     [mm20,mm21,mm22]])

    # right hand side
    rhs0 = C.veccat([f1,f2,f3 + conf['g']*(conf['mass'] + conf['tether_mass']*0.5)])
    rhs1 = C.veccat([t1,t2,t3]) - C.cross(dae['w_bn_b'], C.mul(J, dae['w_bn_b']))

    # last element of RHS
    R_n2b = dae['R_n2b']
    w_bn_b = dae['w_bn_b']
    grad_r_cdot = v_bn_n + C.mul(R_b2n, C.cross(dae['w_bn_b'], r_b2bridle_b))
    tPR = - C.cross(C.mul(R_n2b, r_n2b_n), C.cross(w_bn_b, r_b2bridle_b)) - \
          C.cross(C.mul(R_n2b, v_bn_n), r_b2bridle_b)
    rhs2 = -C.mul(grad_r_cdot.T, v_bn_n) - C.mul(tPR.T, w_bn_b) + dae['dr']**2 + dae['r']*dae['ddr']

    rhs = C.veccat([rhs0,rhs1,rhs2])

    c = 0.5*(C.mul(r_n2bridle_n.T, r_n2bridle_n) - dae['r']**2)
    v_bridlen_n = v_bn_n + C.mul(R_b2n, C.cross(w_bn_b, r_b2bridle_b))
    cdot = C.mul(r_n2bridle_n.T, v_bridlen_n) - dae['r']*dae['dr']

    a_bn_n = C.veccat([dae.ddt(name) for name in ['v_bn_n_x','v_bn_n_y','v_bn_n_z']])
    dw_bn_b = C.veccat([dae.ddt(name) for name in ['w_bn_b_x','w_bn_b_y','w_bn_b_z']])
    a_bridlen_n = a_bn_n + C.mul(R_b2n, C.cross(dw_bn_b, r_b2bridle_b) + C.cross(w_bn_b, C.cross(w_bn_b, r_b2bridle_b)))
    cddot = C.mul(v_bridlen_n.T, v_bridlen_n) + C.mul(r_n2bridle_n.T, a_bridlen_n) - \
            dae['dr']**2 - dae['r']*dae['ddr']

    dae['c'] = c
    dae['cdot'] = cdot
    dae['cddot'] = cddot

    return (mm, rhs)
Esempio n. 2
0
def compute_mass_matrix(dae, conf, f1, f2, f3, t1, t2, t3):
    '''
    take the dae that has x/z/u/p added to it already and return
    the states added to it and return mass matrix and rhs of the dae residual
    '''

    R_b2n = dae['R_n2b'].T
    r_n2b_n = C.veccat([dae['r_n2b_n_x'], dae['r_n2b_n_y'], dae['r_n2b_n_z']])
    r_b2bridle_b = C.veccat([0,0,conf['zt']])
    v_bn_n = C.veccat([dae['v_bn_n_x'],dae['v_bn_n_y'],dae['v_bn_n_z']])

    r_n2bridle_n = r_n2b_n + C.mul(R_b2n, r_b2bridle_b)

    mm00 = C.diag([1,1,1]) * (conf['mass'] + conf['tether_mass']/3.0)
    mm01 = C.SXMatrix(3,3)
    mm10 = mm01.T
    mm02 = r_n2bridle_n
    mm20 = mm02.T
    J = C.vertcat([C.horzcat([ conf['j1'],          0, conf['j31']]),
                   C.horzcat([          0, conf['j2'],           0]),
                   C.horzcat([conf['j31'],          0,  conf['j3']])])
    mm11 = J
    mm12 = C.cross(r_b2bridle_b, C.mul(dae['R_n2b'], r_n2b_n))
    mm21 = mm12.T
    mm22 = C.SXMatrix(1,1)

    mm = C.vertcat([C.horzcat([mm00,mm01,mm02]),
                    C.horzcat([mm10,mm11,mm12]),
                    C.horzcat([mm20,mm21,mm22])])

    # right hand side
    rhs0 = C.veccat([f1,f2,f3 + conf['g']*(conf['mass'] + conf['tether_mass']*0.5)])
    rhs1 = C.veccat([t1,t2,t3]) - C.cross(dae['w_bn_b'], C.mul(J, dae['w_bn_b']))

    # last element of RHS
    R_n2b = dae['R_n2b']
    w_bn_b = dae['w_bn_b']
    grad_r_cdot = v_bn_n + C.mul(R_b2n, C.cross(dae['w_bn_b'], r_b2bridle_b))
    tPR = - C.cross(C.mul(R_n2b, r_n2b_n), C.cross(w_bn_b, r_b2bridle_b)) - \
          C.cross(C.mul(R_n2b, v_bn_n), r_b2bridle_b)
    rhs2 = -C.mul(grad_r_cdot.T, v_bn_n) - C.mul(tPR.T, w_bn_b) + dae['dr']**2 + dae['r']*dae['ddr']

    rhs = C.veccat([rhs0,rhs1,rhs2])

    c = 0.5*(C.mul(r_n2bridle_n.T, r_n2bridle_n) - dae['r']**2)
    v_bridlen_n = v_bn_n + C.mul(R_b2n, C.cross(w_bn_b, r_b2bridle_b))
    cdot = C.mul(r_n2bridle_n.T, v_bridlen_n) - dae['r']*dae['dr']

    a_bn_n = C.veccat([dae.ddt(name) for name in ['v_bn_n_x','v_bn_n_y','v_bn_n_z']])
    dw_bn_b = C.veccat([dae.ddt(name) for name in ['w_bn_b_x','w_bn_b_y','w_bn_b_z']])
    a_bridlen_n = a_bn_n + C.mul(R_b2n, C.cross(dw_bn_b, r_b2bridle_b) + C.cross(w_bn_b, C.cross(w_bn_b, r_b2bridle_b)))
    cddot = C.mul(v_bridlen_n.T, v_bridlen_n) + C.mul(r_n2bridle_n.T, a_bridlen_n) - \
            dae['dr']**2 - dae['r']*dae['ddr']

    dae['c'] = c
    dae['cdot'] = cdot
    dae['cddot'] = cddot

    return (mm, rhs)
Esempio n. 3
0
def add_target_orbit_constraint(mocp, p, phase_insertion):
    start = lambda a: mocp.start(a)
    end = lambda a: mocp.end(a)

    # Target orbit - soft constraints
    # 3 parameter orbit: SMA,ECC,INC
    #
    # h_target_magnitude - h_final_magnitude == 0
    # h_target_z - h_final_z == 0
    # c_target - c_final == 0

    r_final_ECEF = casadi.vertcat(end(phase_insertion.rx),
                                  end(phase_insertion.ry),
                                  end(phase_insertion.rz))
    v_final_ECEF = casadi.vertcat(end(phase_insertion.vx),
                                  end(phase_insertion.vy),
                                  end(phase_insertion.vz))

    # Convert to ECI (z rotation is omitted, because LAN is free)
    r_f = r_final_ECEF
    v_f = (
        v_final_ECEF +
        casadi.cross(casadi.SX([0, 0, p.body_rotation_speed]), r_final_ECEF))

    h_final = casadi.cross(r_f, v_f)
    h_final_mag = casadi.norm_2(h_final)
    h_final_z = h_final[2]
    c_final = casadi.sumsqr(v_f) / 2 - 1.0 / casadi.norm_2(r_f)

    defect_h_magnitude = h_final_mag - p.target_orbit_h_magnitude
    defect_h_z = h_final_z - p.target_orbit_h_z
    defect_c = c_final - p.target_orbit_c

    slack_h_magnitude = mocp.add_variable('slack_h_magnitude', init=3.0)
    slack_h_z = mocp.add_variable('slack_h_z', init=3.0)
    slack_c = mocp.add_variable('slack_c', init=3.0)

    mocp.add_constraint(slack_h_magnitude > 0)
    mocp.add_constraint(slack_h_z > 0)
    mocp.add_constraint(slack_c > 0)

    mocp.add_constraint(defect_h_magnitude < slack_h_magnitude)
    mocp.add_constraint(defect_h_magnitude > -slack_h_magnitude)
    mocp.add_constraint(defect_h_z < slack_h_z)
    mocp.add_constraint(defect_h_z > -slack_h_z)
    mocp.add_constraint(defect_c < slack_c)
    mocp.add_constraint(defect_c > -slack_c)

    mocp.add_objective(100.0 * slack_h_magnitude)
    mocp.add_objective(100.0 * slack_h_z)
    mocp.add_objective(100.0 * slack_c)
Esempio n. 4
0
    def initial_guess(self, t, tf_init, params):
        x_guess = self.xd()
        inclination = 30.0 * ca.pi / 180.0  # the other angle than the one you're thinking of
        dcmInclination = np.array(
            [[ca.cos(inclination), 0.0, -ca.sin(inclination)], [0.0, 1.0, 0.0],
             [ca.sin(inclination), 0.0,
              ca.cos(inclination)]])
        dtheta = 2.0 * ca.pi / tf_init
        theta = t * dtheta
        r = 0.25 * params['l']

        angle = ca.SX.sym('angle')
        x_cir = ca.sqrt(params['l']**2 - r**2)
        y_cir = r * ca.cos(angle)
        z_cir = r * ca.sin(angle)
        init_pos_fun = ca.Function(
            'init_pos', [angle],
            [ca.mtimes(dcmInclination, ca.veccat(x_cir, y_cir, z_cir))])
        init_vel_fun = init_pos_fun.jacobian()

        ret = {}
        ret['q'] = init_pos_fun(theta)
        ret['dq'] = init_vel_fun(theta, 0) * dtheta
        ret['w'] = ca.veccat(0.0, 0.0, dtheta)

        norm_vel = ca.norm_2(ret['dq'])
        norm_pos = ca.norm_2(ret['q'])

        R0 = ret['dq'] / norm_vel
        R2 = ret['q'] / norm_pos
        R1 = ca.cross(ret['q'] / norm_pos, ret['dq'] / norm_vel)
        ret['R'] = ca.vertcat(R0.T, R1.T, R2.T).T
        return ret
Esempio n. 5
0
def makeOrthonormal(ocp_, R):
    ocp_.constrain(C.mul(R[0, :], R[0, :].T),
                   '==',
                   1,
                   tag=('R1[0]: e1^T * e1 == 1', None))
    ocp_.constrain(C.mul(R[1, :], R[0, :].T),
                   '==',
                   0,
                   tag=('R1[0]: e2^T * e1 == 0', None))
    ocp_.constrain(C.mul(R[1, :], R[1, :].T),
                   '==',
                   1,
                   tag=('R1[0]: e2^T * e2 == 1', None))
    rhon = C.cross(R[0, :], R[1, :]) - R[2, :]
    ocp_.constrain(rhon[0],
                   '==',
                   0,
                   tag=('R1[0]: ( e1^T X e2 - e3 )[0] == 0', None))
    ocp_.constrain(rhon[2],
                   '==',
                   0,
                   tag=('R1[0]: ( e1^T X e2 - e3 )[1] == 0', None))
    ocp_.constrain(rhon[1],
                   '==',
                   0,
                   tag=('R1[0]: ( e1^T X e2 - e3 )[2] == 0', None))
Esempio n. 6
0
def compute_eSd(Gamma, sd, b, sym_flag = 0):
    if sym_flag:
        eSd = b*cs.cross(Gamma, sd)
    else:
        eSd = b*np.cross(Gamma, sd)

    return eSd
Esempio n. 7
0
def makeOrthonormal(g,R):
         g.add(C.mul(R[0,:],R[0,:].T),'==',1,  tag=('R1[0]: e1^T * e1 == 1',None))
         g.add(C.mul(R[1,:],R[0,:].T),'==',0,  tag=('R1[0]: e2^T * e1 == 0',None))
         g.add(C.mul(R[1,:],R[1,:].T),'==',1,  tag=('R1[0]: e2^T * e2 == 1',None))
         rhon = C.cross(R[0,:],R[1,:]) - R[2,:]
         g.add(rhon[0],'==',0,  tag=('R1[0]: ( e1^T X e2 - e3 )[0] == 0',None))
         g.add(rhon[2],'==',0,  tag=('R1[0]: ( e1^T X e2 - e3 )[1] == 0',None))
         g.add(rhon[1],'==',0,  tag=('R1[0]: ( e1^T X e2 - e3 )[2] == 0',None))
Esempio n. 8
0
 def makeOrthonormal(self, g, R):
     g.add(C.mul(R[0, :], R[0, :].T), '==', 1, tag = ('R1[0]: e1^T * e1 == 1', None))
     g.add(C.mul(R[1, :], R[0, :].T), '==', 0, tag = ('R1[0]: e2^T * e1 == 0', None))
     g.add(C.mul(R[1, :], R[1, :].T), '==', 1, tag = ('R1[0]: e2^T * e2 == 1', None))
     rhon = C.cross(R[0, :], R[1, :]) - R[2, :]
     g.add(rhon[0], '==', 0, tag = ('R1[0]: ( e1^T X e2 - e3 )[0] == 0', None))
     g.add(rhon[2], '==', 0, tag = ('R1[0]: ( e1^T X e2 - e3 )[1] == 0', None))
     g.add(rhon[1], '==', 0, tag = ('R1[0]: ( e1^T X e2 - e3 )[2] == 0', None))
def cross(a, b, axisa=-1, axisb=-1, axisc=-1, axis=None, manual=False):
    """
    Return the cross product of two (arrays of) vectors.

    See syntax here: https://numpy.org/doc/stable/reference/generated/numpy.cross.html
    """
    if manual:
        cross_x = a[1] * b[2] - a[2] * b[1]
        cross_y = a[2] * b[0] - a[0] * b[2]
        cross_z = a[0] * b[1] - a[1] * b[0]
        return cross_x, cross_y, cross_z

    if not is_casadi_type([a, b], recursive=True):
        return _onp.cross(a,
                          b,
                          axisa=axisa,
                          axisb=axisb,
                          axisc=axisc,
                          axis=axis)

    else:
        if axis is not None:
            if not (axis == -1 or axis == 0 or axis == 1):
                raise ValueError("`axis` must be -1, 0, or 1.")
            axisa = axis
            axisb = axis
            axisc = axis

        if axisa == -1 or axisa == 1:
            if not is_casadi_type(a):
                a = _cas.DM(a)
            a = a.T
        elif axisa == 0:
            pass
        else:
            raise ValueError("`axisa` must be -1, 0, or 1.")

        if axisb == -1 or axisb == 1:
            if not is_casadi_type(b):
                b = _cas.DM(b)
            b = b.T
        elif axisb == 0:
            pass
        else:
            raise ValueError("`axisb` must be -1, 0, or 1.")

        # Compute the cross product, horizontally (along axis 1 of a 2D array)
        c = _cas.cross(a, b)

        if axisc == -1 or axisc == 1:
            c = c.T
        elif axisc == 0:
            pass
        else:
            raise ValueError("`axisc` must be -1, 0, or 1.")

        return c
Esempio n. 10
0
def get_orthonormal_constraints(R):
    ret = []
    ret.append((C.mul(R[0, :], R[0, :].T) - 1, 'R1[0]: e1^T * e1 - 1 == 0'))
    ret.append((C.mul(R[1, :], R[0, :].T), 'R1[0]: e2^T * e1     == 0'))
    ret.append((C.mul(R[1, :], R[1, :].T) - 1, 'R1[0]: e2^T * e2 - 1 == 0'))
    rhon = C.cross(R[0, :], R[1, :]) - R[2, :]
    ret.append((rhon[0], 'R1[0]: ( e1^T X e2 - e3 )[0] == 0'))
    ret.append((rhon[2], 'R1[0]: ( e1^T X e2 - e3 )[1] == 0'))
    ret.append((rhon[1], 'R1[0]: ( e1^T X e2 - e3 )[2] == 0'))
    return ret
Esempio n. 11
0
 def add_cop_constraint(self, contact, p, z, scaling=0.95):
     X = scaling * contact.X
     Y = scaling * contact.Y
     CZ, ZG = z - contact.p, p - z
     CZxZG = casadi.cross(CZ, ZG)
     Dx = casadi.dot(contact.b, CZxZG) / X
     Dy = casadi.dot(contact.t, CZxZG) / Y
     ZGn = casadi.dot(contact.n, ZG)
     slackness = Dx**2 + Dy**2 - ZGn**2
     self.nlp.add_constraint(slackness, lb=[-self.nlp.infty], ub=[-0.005])
Esempio n. 12
0
 def add_linear_cop_constraints(self, contact, p, z, scaling=0.95):
     GZ = z - p
     for (i, v) in enumerate(contact.vertices):
         v_next = contact.vertices[(i + 1) % len(contact.vertices)]
         v = v + (1. - scaling) * (contact.p - v)
         v_next = v_next + (1. - scaling) * (contact.p - v_next)
         slackness = casadi.dot(v_next - v, casadi.cross(v - p, GZ))
         self.nlp.add_constraint(slackness,
                                 lb=[-self.nlp.infty],
                                 ub=[-0.005])
Esempio n. 13
0
def get_orthonormal_constraints(R):
    ret = []
    ret.append( (C.mul(R[0,:],R[0,:].T) - 1,  'R1[0]: e1^T * e1 - 1 == 0') )
    ret.append( (C.mul(R[1,:],R[0,:].T),      'R1[0]: e2^T * e1     == 0') )
    ret.append( (C.mul(R[1,:],R[1,:].T) - 1,  'R1[0]: e2^T * e2 - 1 == 0') )
    rhon = C.cross(R[0,:],R[1,:]) - R[2,:]
    ret.append( (rhon[0,0], 'R1[0]: ( e1^T X e2 - e3 )[0] == 0') )
    ret.append( (rhon[0,2], 'R1[0]: ( e1^T X e2 - e3 )[1] == 0') )
    ret.append( (rhon[0,1], 'R1[0]: ( e1^T X e2 - e3 )[2] == 0') )
    return ret
Esempio n. 14
0
def cross(u, v):
    """
    :param u: 1d matrix
    :type u: Matrix
    :param v: 1d matrix
    :type v: Matrix
    :return: 1d Matrix. If u and v have length 4, it ignores the last entry and adds a zero to the result.
    :rtype: Matrix
    """
    return ca.cross(u, v)
Esempio n. 15
0
    def dynamics(self, aero, params):
        ScalePower = params['ScalePower']
        scale = 1000.
        xd = self.xd
        u = self.u
        xa = self.xa
        p = self.p
        puni = self.puni
        l = self.l
        m = params['mK'] + 1. / 3 * params['mT']  #mass of kite and tether
        g = params['g']  # gravity
        A = params['sref']  # area of Kite
        J = params['J']  # Kite Inertia

        xddot = ca.struct_symSX(
            [ca.entry('d' + name, shape=xd[name].shape) for name in xd.keys()])
        [q, dq, R, w, coeff, E, Drag] = xd[...]

        (Fa, M, F_tether_scaled, F_drag, F_gravity,
         Tether_drag), outputs = aero(xd, xa, p, puni, l, params)

        wx = skew(w[0], w[1],
                  w[2])  # creating a skrew matrix of the angular velocities

        # Rdot = R*w (whereas w is in the skrew symmetric form)
        Rconstraint = ca.reshape(xddot['dR'] - ca.mtimes(xd['R'], wx), 9,
                                 1)  # J*wdot +w x J*w = T
        TorqueEq = ca.mtimes(
            J, xddot['dw']) + (ca.cross(w.T,
                                        ca.mtimes(J, w).T).T - scale *
                               (1 - puni['gam']) * u['T']) - puni['gam'] * M
        DragForce = -Drag * R[0:3]

        # ------------------------------------------------------------------------------------
        #  DYNAMICS of the system - Create a structure for the Differential-Algebraic Equation
        # ------------------------------------------------------------------------------------
        res = ca.vertcat(
                       xddot['dq']        - xd['dq'],\
                       xddot['dcoeff']    - u['dcoeff'],\
                       xddot['dDrag']     - u['dDrag'],\
                       m*(xddot['ddq'][0]  + F_tether_scaled[0] - A*(1-puni['gam'])*u['u',0]) -  puni['gam']*Fa[0] - F_drag[0] - Tether_drag[0], \
                       m*(xddot['ddq'][1]  + F_tether_scaled[1] - A*(1-puni['gam'])*u['u',1]) -  puni['gam']*Fa[1] - F_drag[1] - Tether_drag[1], \
                       m*(xddot['ddq'][2]  + F_tether_scaled[2] - A*(1-puni['gam'])*u['u',2]) -  puni['gam']*Fa[2] - F_drag[2] - Tether_drag[2]+ F_gravity   , \
                       xddot['dE'] - ScalePower*ca.mtimes(F_drag.T,dq)
                      )

        res = ca.veccat(res, Rconstraint, TorqueEq)
        res = ca.veccat(res,
                        ca.sum1(xd['q'] * xddot['ddq']) + ca.sum1(xd['dq']**2))

        # --- System dynamics function (implicit formulation)
        dynamics = ca.Function('dynamics', [xd, xddot, xa, u, p, puni, l],
                               [res])
        return dynamics
Esempio n. 16
0
 def product(cls, a, b):
     assert a.shape == (4, 1) or a.shape == (4, )
     assert b.shape == (4, 1) or b.shape == (4, )
     r1 = a[0]
     v1 = a[1:]
     r2 = b[0]
     v2 = b[1:]
     res = ca.SX(4, 1)
     res[0] = r1 * r2 - ca.dot(v1, v2)
     res[1:] = r1 * v2 + r2 * v1 + ca.cross(v1, v2)
     return res
Esempio n. 17
0
 def product(cls, r1, r2):
     assert r1.shape == (4, 1) or r1.shape == (4, )
     assert r2.shape == (4, 1) or r2.shape == (4, )
     a = r1[:3]
     b = r2[:3]
     na_sq = ca.dot(a, a)
     nb_sq = ca.dot(b, b)
     res = ca.SX(4, 1)
     den = (1 + na_sq * nb_sq - 2 * ca.dot(b, a))
     res[:3] = ((1 - na_sq) * b +
                (1 - nb_sq) * a - 2 * ca.cross(b, a)) / den
     res[3] = 0  # shadow state
     return res
Esempio n. 18
0
def makeModel(conf, propertiesDir = '../properties'):
    print "\n#### File '%s' is old. It does not use the NED convention you should use carouselModel in offline_mhe_stuff instead.\n" \
           % inspect.getfile(inspect.currentframe())
    #input("Press Enter if you wish to continue...")
    dae = rawe.models.carousel(conf)
    (xDotSol, zSol) = dae.solveForXDotAndZ()
    ddp = C.vertcat([xDotSol['dx'],xDotSol['dy'],xDotSol['dz']])
    ddt_w_bn_b  = C.vertcat([xDotSol['w_bn_b_x'],xDotSol['w_bn_b_y'],xDotSol['w_bn_b_z']])
    x =   dae['x']
    y =   dae['y']

    dx  =  dae['dx']
    dy  =  dae['dy']

    ddelta = dae['ddelta']
    dddelta = xDotSol['ddelta']

    R = C.veccat( [dae[n] for n in ['e11', 'e12', 'e13',
                                    'e21', 'e22', 'e23',
                                    'e31', 'e32', 'e33']]
                      ).reshape((3,3))

    rA = conf['rArm']
    g = conf['g']
    pIMU = C.DMatrix(np.loadtxt(os.path.join(propertiesDir,'IMU/pIMU.dat')))
    RIMU = C.DMatrix(np.loadtxt(os.path.join(propertiesDir,'IMU/RIMU.dat')))
    ddpIMU = C.mul(R.T,ddp) - ddelta**2*C.mul(R.T,C.vertcat([x+rA,y,0])) + 2*ddelta*C.mul(R.T,C.vertcat([-dy,dx,0])) + dddelta*C.mul(R.T,C.vertcat([-y,x+rA,0])) + C.mul(R.T,C.vertcat([0,0,g]))
    aBridle = C.cross(ddt_w_bn_b,pIMU)
    dae['IMU_acceleration'] = C.mul(RIMU,ddpIMU+aBridle)
    dae['IMU_angular_velocity'] = C.mul(RIMU,dae['w_bn_b'])

    camConf = {'PdatC1':C.DMatrix(np.loadtxt(os.path.join(propertiesDir,'cameras/PC1.dat'))),
               'PdatC2':C.DMatrix(np.loadtxt(os.path.join(propertiesDir,'cameras/PC2.dat'))),
               'RPC1':C.DMatrix(np.loadtxt(os.path.join(propertiesDir,'cameras/RPC1.dat'))),
               'RPC2':C.DMatrix(np.loadtxt(os.path.join(propertiesDir,'cameras/RPC2.dat'))),
               'pos_marker_body1':C.DMatrix(np.loadtxt(os.path.join(propertiesDir,'markers/pos_marker_body1.dat'))),
               'pos_marker_body2':C.DMatrix(np.loadtxt(os.path.join(propertiesDir,'markers/pos_marker_body2.dat'))),
               'pos_marker_body3':C.DMatrix(np.loadtxt(os.path.join(propertiesDir,'markers/pos_marker_body3.dat')))}
    dae['marker_positions'] = camModel.fullCamModel(dae,camConf)

    dae['ConstR1'] = dae['e11']*dae['e11'] + dae['e12']*dae['e12'] + dae['e13']*dae['e13'] - 1
    dae['ConstR2'] = dae['e11']*dae['e21'] + dae['e12']*dae['e22'] + dae['e13']*dae['e23']
    dae['ConstR3'] = dae['e11']*dae['e31'] + dae['e12']*dae['e32'] + dae['e13']*dae['e33']
    dae['ConstR4'] = dae['e21']*dae['e21'] + dae['e22']*dae['e22'] + dae['e23']*dae['e23'] - 1
    dae['ConstR5'] = dae['e21']*dae['e31'] + dae['e22']*dae['e32'] + dae['e23']*dae['e33']
    dae['ConstR6'] = dae['e31']*dae['e31'] + dae['e32']*dae['e32'] + dae['e33']*dae['e33'] - 1
    #dae['ConstDelta'] = dae['cos_delta']*dae['cos_delta'] + dae['sin_delta']*dae['sin_delta'] - 1
    dae['ConstDelta'] = ( dae['cos_delta']**2 + dae['sin_delta']**2 - 1 )

    return dae
Esempio n. 19
0
def compute_x_tilde(x, x_ref, state_space):

    if state_space == 'longitudinal':
        Vr = x[0]
        alpha = x[1]
        theta = x[2]
        q = x[3]

        Vr_ref = x_ref[0]
        theta_ref = x_ref[1]

        x_tilde = cs.vertcat(Vr - Vr_ref, alpha, theta - theta_ref, q)

    elif state_space == 'full':
        Vr_err = x[0] - x_ref[0]

        q = x[3:7]
        q_ref = x_ref[1:5]

        # Compute reduced attitudes
        R_d = cg.rotation_quaternion(q_ref)
        R = cg.rotation_quaternion(q)

        b = R_d[:, 0]

        Gamma_d = R_d.T @ b
        Gamma = R.T @ b

        # Cost functions
        q_err = 1 - cs.dot(cs.vertcat(1, 0, 0), Gamma)
        # q_err = 1 - Gamma[0]
        q_err = cs.vertcat(q_err, cs.cross(Gamma_d, Gamma))

        qw = q[0]
        qx = q[1]
        qy = q[2]
        qz = q[3]

        phi = cs.arctan2(2 * (qw * qx + qy * qz), 1 - 2 * (qx**2 + qy**2))
        omega_s = x[7:10]

        beta = x[1]
        x_tilde = cs.vertcat(Vr_err, q_err, omega_s, phi, beta)
    elif state_space == 'lateral':
        print('Not implemented state_space: ' + state_space)
    else:
        print('Unknown state_space: ' + state_space)

    return x_tilde
Esempio n. 20
0
 def casadi_ode(self, t, x, u, w):
     """
     Basic dynamics of xdot for unicycle
     """
     tau = u[1:]
     thrust = self.mass * u[0]
     e3 = cs.DM([0, 0, 1])
     v = x[3:6]
     rpy = x[6:9]
     R = self.euler2mat(rpy)
     omega = x[9:12]
     J_omega_dot = cs.cross(cs.mtimes(self.J, omega), omega) + tau
     thrust_vec = cs.mtimes(R, e3)
     acceleration = (1.0 / self.mass) * (thrust_vec * thrust + self.mg)
     omega_dot = cs.mtimes(self.Jinv, J_omega_dot)
     rpy_dot = self.omegaToRpyDot(rpy, omega)
     return cs.vertcat(v, acceleration, rpy_dot, omega_dot) + w
Esempio n. 21
0
def dot_x_stability(t, quat, Vr, alpha, beta, s_omega, u, model):
    P = model.P

    R_sb = cg.rotation_sb(alpha)
    R_ws = cg.rotation_ws(beta)
    R_wb = cg.rotation_wb(alpha, beta)

    b_omega = R_sb.T @ s_omega
    p = b_omega[0]
    q = b_omega[1]
    r = b_omega[2]
    delta_a = u[0]
    delta_e = u[1]
    delta_r = u[2]
    delta_t = u[3]

    b_tau = compute_force(0, quat, Vr, alpha, beta, b_omega, u, model)
    b_F = b_tau[:3]
    b_M = b_tau[3:]

    w_F = R_wb @ b_F
    w_omega = R_wb @ b_omega
    w_v_rel = cs.SX.zeros(3, 1)
    w_v_rel[0] = Vr
    # w_v_rel = np.array((Vr,0,0)) # [Vr, 0, 0].T
    # rhs     = w_F/P['mass'] - cg.Smtrx(w_omega)@w_v_rel
    rhs = w_F / P['mass'] - cs.cross(w_omega, w_v_rel)

    Vr_dot = rhs[0]
    beta_dot = rhs[1] / Vr
    alpha_dot = rhs[2] / (Vr * cs.cos(beta))

    b_J_cg = P['I_cg']

    dot_s_omega = dot_s_angvel_bn(alpha, alpha_dot, b_M, b_omega, b_J_cg)

    dot_quat_nb = cg.quaternion_dot(quat, b_omega)
    # dot_q_nb = dot_q_nb(:);
    s_x_dot = cs.vertcat(Vr_dot, beta_dot, alpha_dot, dot_quat_nb, dot_s_omega)

    return s_x_dot
Esempio n. 22
0
    def add_linear_cop_constraints(self, p, z, foothold, scaling=0.95):
        """
        Constraint the COP, located between the COM `p` and the (floating-base)
        ZMP `z`, to lie inside the contact area.

        Parameters
        ----------
        p : casadi.MX
            Symbol of COM position variable.
        z : casadi.MX
            Symbol of ZMP position variable.
        scaling : scalar, optional
            Scaling factor between 0 and 1 applied to the contact area.
        """
        GZ = z - p
        nb_vert = len(foothold.vertices)
        for (i, v) in enumerate(foothold.vertices):
            v_next = foothold.vertices[(i + 1) % nb_vert]
            v = v + (1. - scaling) * (foothold.p - v)
            v_next = v_next + (1. - scaling) * (foothold.p - v_next)
            slackness = casadi.dot(v_next - v, casadi.cross(v - p, GZ))
            self.nlp.add_constraint(
                slackness, lb=[-self.nlp.infty], ub=[-0.0005])
Esempio n. 23
0
def solve_launch_direction_problem(p):
    # Find the approximate launch direction vector.
    # The launch direction vector is horizontal (orthogonal to the launch site position vector).
    # The launch direction vector points (approximately) in the direction of the orbit insertion velocity.
    mocp = MOCP()

    rx = mocp.add_variable('rx', init=p.launch_site_x)
    ry = mocp.add_variable('ry', init=p.launch_site_y)
    rz = mocp.add_variable('rz', init=p.launch_site_z)

    vx = mocp.add_variable('vx', init=0.01)
    vy = mocp.add_variable('vy', init=0.01)
    vz = mocp.add_variable('vz', init=0.01)

    mocp.add_objective((rx - p.launch_site_x)**2)
    mocp.add_objective((ry - p.launch_site_y)**2)
    mocp.add_objective((rz - p.launch_site_z)**2)

    r = casadi.vertcat(rx, ry, rz)
    v = casadi.vertcat(vx, vy, vz)
    h = casadi.cross(r, v)
    h_mag = casadi.norm_2(h)
    h_z = h[2]
    c = casadi.sumsqr(v) / 2 - 1.0 / casadi.norm_2(r)

    mocp.add_objective((h_mag - p.target_orbit_h_magnitude)**2)
    mocp.add_objective((h_z - p.target_orbit_h_z)**2)
    mocp.add_objective((c - p.target_orbit_c)**2)

    mocp.solve()
    v_soln = DM([mocp.get_value(vx), mocp.get_value(vy), mocp.get_value(vz)])
    launch_direction = normalize(v_soln)
    up_direction = normalize(
        DM([p.launch_site_x, p.launch_site_y, p.launch_site_z]))
    launch_direction = launch_direction - (
        launch_direction.T @ up_direction) * up_direction
    return launch_direction
Esempio n. 24
0
def makeDae( conf = None ):
    if conf is None:
        conf = arianne_conf.makeConf()

    # Make model
    dae = rawe.models.carousel(conf)

    (xDotSol, zSol) = dae.solveForXDotAndZ()

    # Get variables and outputs from the model
    ddp = C.vertcat([xDotSol['dx'],xDotSol['dy'],xDotSol['dz']])
    ddt_w_bn_b  = C.vertcat([xDotSol['w_bn_b_x'],xDotSol['w_bn_b_y'],xDotSol['w_bn_b_z']])
    x =   dae['x']
    y =   dae['y']
    z =   dae['z']

    e31 = dae['e31']
    e32 = dae['e32']
    e33 = dae['e33']

    zt = conf['zt']

    dx  =  dae['dx']
    dy  =  dae['dy']

    ddelta = dae['ddelta']
    dddelta = xDotSol['ddelta']

    R = dae['R_c2b']
    rA = conf['rArm']
    g = conf['g']

    # Rotation matrix to convert from NWU to NED frame type
    R_nwu2ned = np.eye( 3 )
    R_nwu2ned[1, 1] = R_nwu2ned[2, 2] = -1.0

    ############################################################################
    #
    # IMU model
    #
    ############################################################################

    # Load IMU position and orientation w.r.t. body frame
#    pIMU = C.mul(R_nwu2ned, C.DMatrix(np.loadtxt(os.path.join(propertiesDir,'IMU/pIMU.dat'))))
    pIMU = C.DMatrix([0,0,0])
    pIMU = C.mul(R_nwu2ned, pIMU)
#0
#0
#0

#    RIMU = C.mul(R_nwu2ned, C.DMatrix(np.loadtxt(os.path.join(propertiesDir,'IMU/RIMU.dat'))))

#9.937680e-01   6.949103e-02    8.715574e-02
#-6.975647e-02  9.975641e-01    0
#-8.694344e-02  -6.079677e-03   9.961947e-01
    RIMU = C.DMatrix([[9.937680e-01,   6.949103e-02, 8.715574e-02],
                      [-6.975647e-02,  9.975641e-01,            0],
                      [-8.694344e-02, -6.079677e-03, 9.961947e-01]])
    RIMU = C.mul(R_nwu2ned, RIMU)

        # Define IMU measurement functions
        # TODO here is omitted the term: w x w pIMU
    # The sign of gravity is negative because of the NED convention (z points down!)
    ddpIMU_c = ddp - ddelta ** 2 * C.vertcat([x + rA, y, 0]) + 2 * ddelta * C.vertcat([-dy, dx, 0]) + \
                dddelta * C.vertcat([-y, x + rA, 0]) - C.vertcat([0, 0, g])
    ddpIMU = C.mul(R, ddpIMU_c)
    aBridle = C.cross(ddt_w_bn_b, pIMU)
    ddpIMU += aBridle
    ddpIMU = C.mul(RIMU,ddpIMU)
    # You can add a parameter to conf which will give the model 3 extra states with derivative 0 (to act as parameter) for the bias in the acceleration measurements. If that is present, it should be added to the measurement of the acceleration
    if 'useIMUAccelerationBias' in conf and conf['useIMUAccelerationBias']:
        IMUAccelerationBias = C.vertcat([dae['IMUAccelerationBias1'],dae['IMUAccelerationBias2'],dae['IMUAccelerationBias3']])
        ddpIMU += IMUAccelerationBias

    # For the accelerometers
    dae['IMU_acceleration'] = ddpIMU
    dae['IMU_acceleration_x'] = dae['IMU_acceleration'][0]
    dae['IMU_acceleration_y'] = dae['IMU_acceleration'][1]
    dae['IMU_acceleration_z'] = dae['IMU_acceleration'][2]

    # ... and for the gyroscopes
    dae['IMU_angular_velocity'] = C.mul(RIMU, dae['w_bn_b'])
    dae['IMU_angular_velocity_x'] = dae['IMU_angular_velocity'][0]
    dae['IMU_angular_velocity_y'] = dae['IMU_angular_velocity'][1]
    dae['IMU_angular_velocity_z'] = dae['IMU_angular_velocity'][2]

    if 'kinematicIMUAccelerationModel' in conf and conf['kinematicIMUAccelerationModel']:
        dae['vel_error_x'] = dae['dx']-dae['dx_IMU']
        dae['vel_error_y'] = dae['dy']-dae['dy_IMU']
        dae['vel_error_z'] = dae['dz']-dae['dz_IMU']

        ############################################################################
        #
        # LAS
        #
        ############################################################################

    x_tether = (x + zt*e31)
    y_tether = (y + zt*e32)
    z_tether = (z + zt*e33)

    dae['lineAngles'] = C.vertcat([C.arctan(y_tether/x_tether),C.arctan(z_tether/x_tether)])
    dae['lineAngle_hor'] = dae['lineAngles'][0]
    dae['lineAngle_ver'] = dae['lineAngles'][1]

    return dae
Esempio n. 25
0
    dx_bc = x_bN - x_cN
    
    # Final velocity
    v_bN = V['X',N_sim,ca.veccat,['vx_b','vy_b']]
    v_cN = V['X',N_sim,ca.veccat,['vx_c','vy_c']]
    dv_bc = v_bN - v_cN
    
    # Angle between gaze and ball velocity
    theta = V['X',N_sim,'theta']
    phi = V['X',N_sim,'phi']
    d = ca.veccat([ ca.cos(theta)*ca.cos(phi), ca.cos(theta)*ca.sin(phi), ca.sin(theta) ])
    r = V['X',N_sim,ca.veccat,['vx_b','vy_b','vz_b']]
    
????? 
    
    delta = ca.arctan2(ca.norm_2(ca.cross()))
    
    r_unit = r / (ca.norm_2(r) + 1e-2)
    d_gaze = d - r_unit
    
    # Regularize controls
    J = 1e-1 * ca.sum_square(ca.veccat(V['U'])) * dt
    
    # Multiple shooting constraints and non-linear control constraints
    g, lbg, ubg = [], [], []
    for k in range(N_sim):
        # Multiple shooting
        [x_next] = F([V['X',k], V['U',k], dt])
        g.append(x_next - V['X',k+1])
        lbg.append(ca.DMatrix.zeros(nx))
        ubg.append(ca.DMatrix.zeros(nx))
Esempio n. 26
0
    def __init__(self, inertial_frame_id='world'):
        Vehicle.__init__(self, inertial_frame_id)
    
        # Declaring state variables
        ## Generalized position vector
        self.eta = casadi.SX.sym('eta', 6)
        ## Generalized velocity vector
        self.nu = casadi.SX.sym('nu', 6)

        # Build the Coriolis matrix
        self.CMatrix = casadi.SX.zeros(6, 6)

        S_12 = - cross_product_operator(
            casadi.mtimes(self._Mtotal[0:3, 0:3], self.nu[0:3]) +
            casadi.mtimes(self._Mtotal[0:3, 3:6], self.nu[3:6]))
        S_22 = - cross_product_operator(
            casadi.mtimes(self._Mtotal[3:6, 0:3], self.nu[0:3]) +
            casadi.mtimes(self._Mtotal[3:6, 3:6], self.nu[3:6]))

        self.CMatrix[0:3, 3:6] = S_12
        self.CMatrix[3:6, 0:3] = S_12
        self.CMatrix[3:6, 3:6] = S_22

        # Build the damping matrix (linear and nonlinear elements)
        self.DMatrix = - casadi.diag(self._linear_damping)        
        self.DMatrix -= casadi.diag(self._linear_damping_forward_speed)
        self.DMatrix -= casadi.diag(self._quad_damping * self.nu)      

        # Build the restoring forces vectors wrt the BODY frame
        Rx = np.array([[1, 0, 0],
                       [0, casadi.cos(self.eta[3]), -1 * casadi.sin(self.eta[3])],
                       [0, casadi.sin(self.eta[3]), casadi.cos(self.eta[3])]])
        Ry = np.array([[casadi.cos(self.eta[4]), 0, casadi.sin(self.eta[4])],
                       [0, 1, 0],
                       [-1 * casadi.sin(self.eta[4]), 0, casadi.cos(self.eta[4])]])
        Rz = np.array([[casadi.cos(self.eta[5]), -1 * casadi.sin(self.eta[5]), 0],
                       [casadi.sin(self.eta[5]), casadi.cos(self.eta[5]), 0],
                       [0, 0, 1]])

        R_n_to_b = casadi.transpose(casadi.mtimes(Rz, casadi.mtimes(Ry, Rx)))

        if inertial_frame_id == 'world_ned':
            Fg = casadi.SX([0, 0, -self.mass * self.gravity])
            Fb = casadi.SX([0, 0, self.volume * self.gravity * self.density])
        else:
            Fg = casadi.SX([0, 0, self.mass * self.gravity])
            Fb = casadi.SX([0, 0, -self.volume * self.gravity * self.density])

        self.gVec = casadi.SX.zeros(6)

        self.gVec[0:3] = -1 * casadi.mtimes(R_n_to_b, Fg + Fb)  
        self.gVec[3:6] = -1 * casadi.mtimes(
            R_n_to_b, casadi.cross(self._cog, Fg) + casadi.cross(self._cob, Fb))
        
        # Build Jacobian
        T = 1 / casadi.cos(self.eta[4]) * np.array(
            [[0, casadi.sin(self.eta[3]) * casadi.sin(self.eta[4]), casadi.cos(self.eta[3]) * casadi.sin(self.eta[4])],
             [0, casadi.cos(self.eta[3]) * casadi.cos(self.eta[4]), -casadi.cos(self.eta[4]) * casadi.sin(self.eta[3])],
             [0, casadi.sin(self.eta[3]), casadi.cos(self.eta[3])]])

        self.eta_dot = casadi.vertcat(
            casadi.mtimes(casadi.transpose(R_n_to_b), self.nu[0:3]),
            casadi.mtimes(T, self.nu[3::]))

        self.u = casadi.SX.sym('u', 6)
        
        self.nu_dot = casadi.solve(
            self._Mtotal, 
            self.u - casadi.mtimes(self.CMatrix, self.nu) - casadi.mtimes(self.DMatrix, self.nu) - self.gVec)

        
Esempio n. 27
0
    sref = conf['sref']
    bref = conf['bref']
    cref = conf['cref']

    # airfoil speed in wind frame
    v_bw_n_x = v_bw_n[0]
    v_bw_n_y = v_bw_n[1]
    v_bw_n_z = v_bw_n[2]

    vKite2 = C.mul(v_bw_n.trans(), v_bw_n) #Airfoil speed^2
    vKite = C.sqrt(vKite2) #Airfoil speed
    dae['airspeed'] = vKite

    # Lift axis, normed to airspeed
    eLe_v = C.cross(C.veccat([eTe1, eTe2, eTe3]), v_bw_n)

    # sideforce axis, normalized to airspeed^2
    eYe_v2 = C.cross(eLe_v, -v_bw_n)

    # Relative wind speed in Airfoil's referential 'E'
    v_bw_b_x = v_bw_b[0]
    v_bw_b_y = v_bw_b[1]
    v_bw_b_z = v_bw_b[2]

    if conf['alpha_beta_computation'] == 'first_order':
        alpha = alpha0 + v_bw_b_z / v_bw_b_x
        beta = v_bw_b_y / v_bw_b_x
#        beta = v_bw_b_y / C.sqrt(v_bw_b_x*v_bw_b_x + v_bw_b_z*v_bw_b_z)
    elif conf['alpha_beta_computation'] == 'closed_form':
        (alpha, beta) = getWindAnglesFrom_v_bw_b(vKite, v_bw_b)
Esempio n. 28
0
    def __init__(self, inertial_frame_id='world'):
        Vehicle.__init__(self, inertial_frame_id)

        # Declaring state variables
        ## Generalized position vector
        self.eta = casadi.SX.sym('eta', 6)
        ## Generalized velocity vector
        self.nu = casadi.SX.sym('nu', 6)

        # Build the Coriolis matrix
        self.CMatrix = casadi.SX.zeros(6, 6)

        S_12 = -cross_product_operator(
            casadi.mtimes(self._Mtotal[0:3, 0:3], self.nu[0:3]) +
            casadi.mtimes(self._Mtotal[0:3, 3:6], self.nu[3:6]))
        S_22 = -cross_product_operator(
            casadi.mtimes(self._Mtotal[3:6, 0:3], self.nu[0:3]) +
            casadi.mtimes(self._Mtotal[3:6, 3:6], self.nu[3:6]))

        self.CMatrix[0:3, 3:6] = S_12
        self.CMatrix[3:6, 0:3] = S_12
        self.CMatrix[3:6, 3:6] = S_22

        # Build the damping matrix (linear and nonlinear elements)
        self.DMatrix = -casadi.diag(self._linear_damping)
        self.DMatrix -= casadi.diag(self._linear_damping_forward_speed)
        self.DMatrix -= casadi.diag(self._quad_damping * self.nu)

        # Build the restoring forces vectors wrt the BODY frame
        Rx = np.array(
            [[1, 0, 0],
             [0, casadi.cos(self.eta[3]), -1 * casadi.sin(self.eta[3])],
             [0, casadi.sin(self.eta[3]),
              casadi.cos(self.eta[3])]])
        Ry = np.array(
            [[casadi.cos(self.eta[4]), 0,
              casadi.sin(self.eta[4])], [0, 1, 0],
             [-1 * casadi.sin(self.eta[4]), 0,
              casadi.cos(self.eta[4])]])
        Rz = np.array(
            [[casadi.cos(self.eta[5]), -1 * casadi.sin(self.eta[5]), 0],
             [casadi.sin(self.eta[5]),
              casadi.cos(self.eta[5]), 0], [0, 0, 1]])

        R_n_to_b = casadi.transpose(casadi.mtimes(Rz, casadi.mtimes(Ry, Rx)))

        if inertial_frame_id == 'world_ned':
            Fg = casadi.SX([0, 0, -self.mass * self.gravity])
            Fb = casadi.SX([0, 0, self.volume * self.gravity * self.density])
        else:
            Fg = casadi.SX([0, 0, self.mass * self.gravity])
            Fb = casadi.SX([0, 0, -self.volume * self.gravity * self.density])

        self.gVec = casadi.SX.zeros(6)

        self.gVec[0:3] = -1 * casadi.mtimes(R_n_to_b, Fg + Fb)
        self.gVec[3:6] = -1 * casadi.mtimes(
            R_n_to_b,
            casadi.cross(self._cog, Fg) + casadi.cross(self._cob, Fb))

        # Build Jacobian
        T = 1 / casadi.cos(self.eta[4]) * np.array(
            [[
                0,
                casadi.sin(self.eta[3]) * casadi.sin(self.eta[4]),
                casadi.cos(self.eta[3]) * casadi.sin(self.eta[4])
            ],
             [
                 0,
                 casadi.cos(self.eta[3]) * casadi.cos(self.eta[4]),
                 -casadi.cos(self.eta[4]) * casadi.sin(self.eta[3])
             ], [0, casadi.sin(self.eta[3]),
                 casadi.cos(self.eta[3])]])

        self.eta_dot = casadi.vertcat(
            casadi.mtimes(casadi.transpose(R_n_to_b), self.nu[0:3]),
            casadi.mtimes(T, self.nu[3::]))

        self.u = casadi.SX.sym('u', 6)

        self.nu_dot = casadi.solve(
            self._Mtotal, self.u - casadi.mtimes(self.CMatrix, self.nu) -
            casadi.mtimes(self.DMatrix, self.nu) - self.gVec)
Esempio n. 29
0
def rocket_equations(jit=True):
    x = ca.SX.sym('x', 14)
    u = ca.SX.sym('u', 4)
    p = ca.SX.sym('p', 16)
    t = ca.SX.sym('t')
    dt = ca.SX.sym('dt')

    # State: x
    # body frame: Forward, Right, Down
    omega_b = x[0:3]  # inertial angular velocity expressed in body frame
    r_nb = x[3:7]  # modified rodrigues parameters
    v_b = x[7:10]  # inertial velocity expressed in body components
    p_n = x[10:13]  # positon in nav frame
    m_fuel = x[13]  # mass

    # Input: u
    m_dot = ca.if_else(m_fuel > 0, u[0], 0)
    fin = u_to_fin(u)

    # Parameters: p
    g = p[0]  # gravity
    Jx = p[1]  # moment of inertia
    Jy = p[2]
    Jz = p[3]
    Jxz = p[4]
    ve = p[5]
    l_fin = p[6]
    w_fin = p[7]
    CL_alpha = p[8]
    CL0 = p[9]
    CD0 = p[10]
    K = p[11]
    s_fin = p[12]
    rho = p[13]
    m_empty = p[14]
    l_motor = p[15]

    # Calculations
    m = m_empty + m_fuel
    J_b = ca.SX.zeros(3, 3)
    J_b[0, 0] = Jx + m_fuel * l_motor**2
    J_b[1, 1] = Jy + m_fuel * l_motor**2
    J_b[2, 2] = Jz
    J_b[0, 2] = J_b[2, 0] = Jxz

    C_nb = so3.Dcm.from_mrp(r_nb)
    g_n = ca.vertcat(0, 0, g)
    v_n = ca.mtimes(C_nb, v_b)

    # aerodynamics
    VT = ca.norm_2(v_b)
    q = 0.5 * rho * ca.dot(v_b, v_b)
    fins = {
        'top': {
            'fwd': [1, 0, 0],
            'up': [0, 1, 0],
            'angle': fin[0]
        },
        'left': {
            'fwd': [1, 0, 0],
            'up': [0, 0, -1],
            'angle': fin[1]
        },
        'down': {
            'fwd': [1, 0, 0],
            'up': [0, -1, 0],
            'angle': fin[2]
        },
        'right': {
            'fwd': [1, 0, 0],
            'up': [0, 0, 1],
            'angle': fin[3]
        },
    }
    rel_wind_dir = v_b / VT

    # build fin lift/drag forces
    vel_tol = 1e-3
    FA_b = ca.vertcat(0, 0, 0)
    MA_b = ca.vertcat(0, 0, 0)
    for key, data in fins.items():
        fwd = data['fwd']
        up = data['up']
        angle = data['angle']
        U = ca.dot(fwd, v_b)
        W = ca.dot(up, v_b)
        side = ca.cross(fwd, up)
        alpha = ca.if_else(ca.fabs(U) > vel_tol, -ca.atan(W / U), 0)
        perp_wind_dir = ca.cross(side, rel_wind_dir)
        norm_perp = ca.norm_2(perp_wind_dir)
        perp_wind_dir = ca.if_else(
            ca.fabs(norm_perp) > vel_tol, perp_wind_dir / norm_perp, up)
        CL = CL0 + CL_alpha * (alpha + angle)
        CD = CD0 + K * (CL - CL0)**2
        # model stall as no lift if above 23 deg.
        L = ca.if_else(ca.fabs(alpha) < 0.4, CL * q * s_fin, 0)
        D = CD * q * s_fin
        FAi_b = L * perp_wind_dir - D * rel_wind_dir
        FA_b += FAi_b
        MA_b += ca.cross(-l_fin * fwd - w_fin * side, FAi_b)

    FA_b = ca.if_else(ca.fabs(VT) > vel_tol, FA_b, ca.SX.zeros(3))
    MA_b = ca.if_else(ca.fabs(VT) > vel_tol, MA_b, ca.SX.zeros(3))

    # propulsion
    FP_b = ca.vertcat(m_dot * ve, 0, 0)

    # force and momental total
    F_b = FA_b + FP_b + ca.mtimes(C_nb.T, m * g_n)
    M_b = MA_b

    force_moment = ca.Function('force_moment', [x, u, p], [F_b, M_b],
                               ['x', 'u', 'p'], ['F_b', 'M_b'])

    # right hand side
    rhs = ca.Function('rhs', [x, u, p], [
        ca.vertcat(
            ca.mtimes(ca.inv(J_b),
                      M_b - ca.cross(omega_b, ca.mtimes(J_b, omega_b))),
            so3.Mrp.kinematics(r_nb, omega_b),
            F_b / m - ca.cross(omega_b, v_b), ca.mtimes(C_nb, v_b), -m_dot)
    ], ['x', 'u', 'p'], ['rhs'], {'jit': jit})

    # prediction
    t0 = ca.SX.sym('t0')
    h = ca.SX.sym('h')
    x0 = ca.SX.sym('x', 14)
    x1 = rk4(lambda t, x: rhs(x, u, p), t0, x0, h)
    x1[3:7] = so3.Mrp.shadow_if_necessary(x1[3:7])
    predict = ca.Function('predict', [x0, u, p, t0, h], [x1], {'jit': jit})

    def schedule(t, start, ty_pairs):
        val = start
        for ti, yi in ty_pairs:
            val = ca.if_else(t > ti, yi, val)
        return val

    # reference trajectory
    pitch_d = 1.0

    euler = so3.Euler.from_mrp(r_nb)  # roll, pitch, yaw
    pitch = euler[1]

    # control
    u_control = ca.SX.zeros(4)
    # these controls are just test controls to make sure the fins are working

    u_control[0] = 0.1  # mass flow rate

    import control
    s = control.tf([1, 0], [0, 1])
    H = 140 * (s + 50) * (s + 50) / (s * (2138 * s + 208.8))
    Hd = control.tf2ss(control.c2d(H, 0.01))

    theta_c = (100 - p_n[2]) * (0.01) / (v_b[2] * ca.cos(p_n[2]))

    x_elev = ca.SX.sym('x_elev', 2)
    u_elev = ca.SX.sym('u_elev', 1)
    x_1 = ca.mtimes(Hd.A, x_elev) + ca.mtimes(Hd.B, u_elev)
    y_elev = ca.mtimes(Hd.C, x_elev) + ca.mtimes(Hd.D, u_elev)

    elev_c = (theta_c - p_n[2]) * y_elev / (0.5 * rho * v_b[2]**2)

    u_control[0] = 0.1  # mass flow rate
    u_control[1] = 0
    u_control[2] = elev_c
    u_control[3] = 0

    control = ca.Function('control', [x, p, t, dt], [u_control],
                          ['x', 'p', 't', 'dt'], ['u'])

    # initialize
    pitch_deg = ca.SX.sym('pitch_deg')
    omega0_b = ca.vertcat(0, 0, 0)
    r0_nb = so3.Mrp.from_euler(ca.vertcat(0, pitch_deg * ca.pi / 180, 0))
    v0_b = ca.vertcat(0, 0, 0)
    p0_n = ca.vertcat(0, 0, 0)
    m0_fuel = 0.8
    # x: omega_b, r_nb, v_b, p_n, m_fuel
    x0 = ca.vertcat(omega0_b, r0_nb, v0_b, p0_n, m0_fuel)
    #     g, Jx, Jy, Jz, Jxz, ve, l_fin, w_fin, CL_alpha, CL0, CD0, K, s, rho, m_emptpy, l_motor
    p0 = [
        9.8, 0.05, 1.0, 1.0, 0.0, 350, 1.0, 0.05, 2 * np.pi, 0, 0.01, 0.01,
        0.05, 1.225, 0.2, 1.0
    ]
    initialize = ca.Function('initialize', [pitch_deg], [x0, p0])

    return {
        'rhs': rhs,
        'predict': predict,
        'control': control,
        'initialize': initialize,
        'force_moment': force_moment,
        'x': x,
        'u': u,
        'p': p
    }
    return rhs, x, u, p
Esempio n. 30
0
    def __init__(self,
                 nb_steps,
                 state_estimator,
                 com_target,
                 contact_sequence,
                 omega2,
                 swing_duration=None):
        super(WrenchPredictiveController, self).__init__()
        t_build_start = time()
        end_com = list(com_target.p)
        end_comd = list(com_target.pd)
        nb_contacts = len(contact_sequence)
        start_com = list(state_estimator.com)
        start_comd = list(state_estimator.comd)

        p_0 = self.nlp.new_constant('p_0', 3, start_com)
        v_0 = self.nlp.new_constant('v_0', 3, start_comd)
        p_k = p_0
        v_k = v_0
        T_swing = 0
        T_total = 0

        for k in range(nb_steps):
            contact = contact_sequence[nb_contacts * k / nb_steps]
            u_k = self.nlp.new_variable('u_%d' % k,
                                        3,
                                        init=[0., 0., 0.],
                                        lb=self.u_min,
                                        ub=self.u_max)
            dT_k = self.nlp.new_variable('dT_%d' % k,
                                         1,
                                         init=[self.dT_init],
                                         lb=[self.dT_min],
                                         ub=[self.dT_max])
            l_k = self.nlp.new_variable('l_%d' % k,
                                        16,
                                        init=[0.] * 16,
                                        lb=[0.] * 16,
                                        ub=self.l_max)

            c = contact.p
            w_k = casadi.mtimes(contact.wrench_span, l_k)
            f_k, tau_k = w_k[:3, :], w_k[3:, :]
            Ld_k = casadi.cross(c - p_k, f_k) + tau_k
            m = state_estimator.pendulum.com_state.mass
            self.nlp.add_equality_constraint(u_k, f_k / m + gravity)
            # hard angular-momentum constraint just don't work
            # nlp.add_constraint(Ld_k, lb=[0., 0., 0.], ub=[0., 0., 0.])

            self.nlp.extend_cost(self.weights['Ld'] * casadi.dot(Ld_k, Ld_k) *
                                 dT_k)
            self.nlp.extend_cost(self.weights['l'] * casadi.dot(l_k, l_k) *
                                 dT_k)
            self.nlp.extend_cost(self.weights['u'] * casadi.dot(u_k, u_k) *
                                 dT_k)

            p_next = p_k + v_k * dT_k + u_k * dT_k**2 / 2
            v_next = v_k + u_k * dT_k
            T_total = T_total + dT_k
            if 2 * k < nb_steps:
                T_swing = T_swing + dT_k

            p_k = self.nlp.new_variable('p_%d' % (k + 1),
                                        3,
                                        init=start_com,
                                        lb=self.p_min,
                                        ub=self.p_max)
            v_k = self.nlp.new_variable('v_%d' % (k + 1),
                                        3,
                                        init=start_comd,
                                        lb=self.v_min,
                                        ub=self.v_max)
            self.nlp.add_equality_constraint(p_next, p_k)
            self.nlp.add_equality_constraint(v_next, v_k)

        self.nlp.add_constraint(T_swing,
                                lb=[swing_duration],
                                ub=[100],
                                name='T_swing')

        p_last, v_last = p_k, v_k
        p_diff = p_last - end_com
        v_diff = v_last - end_comd
        self.nlp.extend_cost(self.weights['p'] * casadi.dot(p_diff, p_diff))
        self.nlp.extend_cost(self.weights['v'] * casadi.dot(v_diff, v_diff))
        self.nlp.extend_cost(self.weights['t'] * T_total)
        self.nlp.create_solver()
        #
        self.build_time = time() - t_build_start
        self.com_target = com_target
        self.contact_sequence = contact_sequence
        self.end_com = array(end_com)
        self.end_comd = array(end_comd)
        self.nb_contacts = nb_contacts
        self.nb_steps = nb_steps
        self.omega2 = omega2
        self.preview = ZMPPreviewBuffer(contact_sequence)
        self.start_com = array(start_com)
        self.start_comd = array(start_comd)
        self.state_estimator = state_estimator
        self.swing_dT_min = self.dT_min
Esempio n. 31
0
    """
    eTe_f = C.veccat([eTe_f_1, eTe_f_2, eTe_f_3])
    rho = conf['rho']
    alpha0 = conf['alpha0deg'] * C.pi / 180

    sref = conf['sref']
    bref = conf['bref']
    cref = conf['cref']

    vKite2 = C.mul(v_bw_f.T, v_bw_f)  #Airfoil speed^2
    vKite = C.sqrt(vKite2)  #Airfoil speed
    dae['airspeed'] = vKite

    # Lift axis, normed to airspeed
    eLe_v_f = C.cross(eTe_f, v_bw_f)

    # sideforce axis, normalized to airspeed^2
    eYe_v2_f = C.cross(eLe_v_f, -v_bw_f)

    if conf['alpha_beta_computation'] == 'first_order':
        alpha = alpha0 + v_bw_b[2] / v_bw_b[0]
        beta = v_bw_b[1] / v_bw_b[0]
#        beta = v_bw_b_y / C.sqrt(v_bw_b[0]*v_bw_b[0] + v_bw_b[2]*v_bw_b[2])
    elif conf['alpha_beta_computation'] == 'closed_form':
        (alpha, beta) = getWindAnglesFrom_v_bw_b(vKite, v_bw_b)
        alpha += alpha0
    else:
        raise ValueError('config "alpha_beta_compuation" value ' +
                         str(conf['alpha_beta_computation']) +
                         ' not recognized, use "first_order" or "closed_form"')
Esempio n. 32
0
def makeModel(conf,propertiesDir='../properties'):
    print "Using the update carousel model"
    
    # Make model
    dae = rawe.models.carousel(conf)
    (xDotSol, zSol) = dae.solveForXDotAndZ()
    
    # Get variables and outputs from the model
    ddp = C.vertcat([xDotSol['dx'],xDotSol['dy'],xDotSol['dz']])
    ddt_w_bn_b  = C.vertcat([xDotSol['w_bn_b_x'],xDotSol['w_bn_b_y'],xDotSol['w_bn_b_z']])
    x =   dae['x']
    y =   dae['y']
    z =   dae['z']

    e31 = dae['e31']
    e32 = dae['e32']
    e33 = dae['e33']

    zt = conf['zt']

    dx  =  dae['dx']
    dy  =  dae['dy']

    ddelta = dae['ddelta']
    dddelta = xDotSol['ddelta']
    
    R = dae['R_c2b']
    rA = conf['rArm']
    g = conf['g']
    
    # Rotation matrix to convert from NWU to NED frame type
    R_nwu2ned = np.eye( 3 )
    R_nwu2ned[1, 1] = R_nwu2ned[2, 2] = -1.0
    
    ############################################################################
    #
    # IMU model
    #
    ############################################################################
    
    # Load IMU position and orientation w.r.t. body frame
    pIMU = C.mul(R_nwu2ned, C.DMatrix(np.loadtxt(os.path.join(propertiesDir,'IMU/pIMU.dat'))))
    RIMU = C.mul(R_nwu2ned, C.DMatrix(np.loadtxt(os.path.join(propertiesDir,'IMU/RIMU.dat'))))

	# Define IMU measurement functions
	# TODO here is omitted the term: w x w pIMU 
    # The sign of gravity is negative because of the NED convention (z points down!)
    ddpIMU_c = ddp - ddelta ** 2 * C.vertcat([x + rA, y, 0]) + 2 * ddelta * C.vertcat([-dy, dx, 0]) + \
                dddelta * C.vertcat([-y, x + rA, 0]) - C.vertcat([0, 0, g])
    ddpIMU = C.mul(R, ddpIMU_c)
    aBridle = C.cross(ddt_w_bn_b, pIMU)
    ddpIMU += aBridle
    ddpIMU = C.mul(RIMU,ddpIMU)
    # You can add a parameter to conf which will give the model 3 extra states with derivative 0 (to act as parameter) for the bias in the acceleration measurements. If that is present, it should be added to the measurement of the acceleration
    if 'useIMUAccelerationBias' in conf and conf['useIMUAccelerationBias']:
        IMUAccelerationBias = C.vertcat([dae['IMUAccelerationBias1'],dae['IMUAccelerationBias2'],dae['IMUAccelerationBias3']])
        ddpIMU += IMUAccelerationBias

    # For the accelerometers
    dae['IMU_acceleration'] = ddpIMU
    # ... and for the gyroscopes
    dae['IMU_angular_velocity'] = C.mul(RIMU, dae['w_bn_b'])

    if 'kinematicIMUAccelerationModel' in conf and conf['kinematicIMUAccelerationModel']:
        dae['vel_error_x'] = dae['dx']-dae['dx_IMU']
        dae['vel_error_y'] = dae['dy']-dae['dy_IMU']
        dae['vel_error_z'] = dae['dz']-dae['dz_IMU']

	############################################################################
	#
	# Stereo vision subsystem modeling
	#
	############################################################################

	# Load calibration data from configuration files
    camConf = {'PdatC1':C.DMatrix(np.loadtxt(os.path.join(propertiesDir, 'cameras/PC1.dat'))),
               'PdatC2':C.DMatrix(np.loadtxt(os.path.join(propertiesDir, 'cameras/PC2.dat'))),
               'RPC1':C.DMatrix(np.loadtxt(os.path.join(propertiesDir, 'cameras/RPC1.dat'))),
               'RPC2':C.DMatrix(np.loadtxt(os.path.join(propertiesDir, 'cameras/RPC2.dat'))),
               'pos_marker_body1':C.DMatrix(np.loadtxt(os.path.join(propertiesDir, 'markers/pos_marker_body1.dat'))),
               'pos_marker_body2':C.DMatrix(np.loadtxt(os.path.join(propertiesDir, 'markers/pos_marker_body2.dat'))),
               'pos_marker_body3':C.DMatrix(np.loadtxt(os.path.join(propertiesDir, 'markers/pos_marker_body3.dat')))}

	# Construction of the measurement functions
    dae['marker_positions'] = camModel.fullCamModel(dae, camConf)
    x_tether = (x + zt*e31)
    y_tether = (y + zt*e32)
    z_tether = (z + zt*e33)

    dae['lineAngles'] = C.vertcat([C.arctan(y_tether/x_tether),C.arctan(z_tether/x_tether)])

	############################################################################
	#
	# Constraints in the MHE
	#
	############################################################################
	
    dae['ConstR1'] = dae['e11']*dae['e11'] + dae['e12']*dae['e12'] + dae['e13']*dae['e13'] - 1
    dae['ConstR2'] = dae['e11']*dae['e21'] + dae['e12']*dae['e22'] + dae['e13']*dae['e23']
    dae['ConstR3'] = dae['e11']*dae['e31'] + dae['e12']*dae['e32'] + dae['e13']*dae['e33']
    dae['ConstR4'] = dae['e21']*dae['e21'] + dae['e22']*dae['e22'] + dae['e23']*dae['e23'] - 1
    dae['ConstR5'] = dae['e21']*dae['e31'] + dae['e22']*dae['e32'] + dae['e23']*dae['e33']
    dae['ConstR6'] = dae['e31']*dae['e31'] + dae['e32']*dae['e32'] + dae['e33']*dae['e33'] - 1
    dae['ConstDelta'] = (dae['cos_delta'] ** 2 + dae['sin_delta'] ** 2 - 1)

    return dae
Esempio n. 33
0
  def __init__(self,NR=4,debug=False,quatnorm=False):
    """
    Keyword arguments:
      NR    -- the number of rotors
      debug -- wether to print out debug info
      quatnorm -- add the quaternion norm to the DAE rhs
    """

    # ----------- system states and their derivatives ----
    pos = struct_symSX(["x","y","z"])     # rigid body centre of mass position [m]   {0}   
    v   = struct_symSX(["vx","vy","vz"])  # rigid body centre of mass position velocity [m/s] {0}

    NR = 4                               # Number of rotors
    
    states = struct_symSX([
      entry("p",struct=pos),
      entry("v",struct=v),
      entry("q",shape=4),                # quaternions  {0} -> {1}
      entry("w",shape=3),                # rigid body angular velocity w_101 [rad/s] {1}
      entry("r",shape=NR)                # spin speed of rotor, wrt to platform. [rad/s] Should be positive!
                                         # The signs are such that positive means lift generating, regardless of spin direction.
      
    ])
    
    pos, v, q, w, r = states[...]

    # ------------------------------------------------

    dist = struct_symSX([
      entry("Faer",shape=NR),             # Disturbance on aerodynamic forcing [N]
      entry("Caer",shape=NR)             # Disturbance on aerodynamic torques [Nm]
    ])


    # ----------------- Controls ---------------------
    controls = struct_symSX([
      entry("CR",shape=NR)              # [Nm]
          # Torques of the motors that drive the rotors, acting from platform on propeller
          # The torque signs are always positive when putting energy in the propellor,
          # regardless of spin direction.
          # 
    ])
    
    CR = controls["CR"]
    
    # ------------------------------------------------


    # ----------------  Temporary symbols --------------
    F = ssym("F",3)          # Forces acting on the platform in {1} [N]
    C = ssym("C",3)          # Torques acting on the platform in {1} [Nm]

    rotors_Faer = [ssym("Faer_%d" %i,3,1) for i in range(NR)] # Placeholder for aerodynamic force acting on propeller {1} [N]
    rotors_Caer = [ssym("Caer_%d" %i,3,1) for i in range(NR)] # Placeholder for aerodynamic torques acting on propeller {1} [Nm]

    # ---------------------------------------------------


    # ----------------- Parameters ---------------------
    
    rotor_model = struct_symSX([
         "c",        # c          Cord length [m]
         "R",        # R          Radius of propeller [m]
         "CL_alpha", # CL_alpha   Lift coefficient [-]
         "alpha_0",  # alpha_0
         "CD_alpha", # CD_alpha   Drag coefficient [-]
         "CD_i",     # CD_i       Induced drag coefficient [-]  
    ])
    
    p = struct_symSX([
      entry("rotors_model",repeat=NR,struct=rotor_model),    # Parameters that describe the rotor model
      entry("rotors_I",repeat=NR,shape=sp_diag(3)),  # Inertias of rotors [kg.m^2]
      entry("rotors_spin",repeat=NR),    # Direction of spin from each rotor. 1 means rotation around positive z.
      entry("rotors_p",repeat=NR,shape=3),  # position of rotors in {1} [m],
      entry("I",sym=casadi.diag(ssym("[Ix,Iy,Iz]"))), # Inertia of rigid body [kg.m^2]
      "m",       # Mass of the whole system [kg]
      "g",       # gravity [m/s^2]
      "rho",     # Air density [kg/m^3]
    ])
    
    I,m,g,rho = p[["I","m","g","rho"]]
 
    # --------------------------------------------------

   
    # ----------------- Parameters fillin's ---------------------

    p_ = p()
    p_["rotors_spin"] = [1,-1,1,-1]

    p_["rotors_model",:,{}] =  { "c": 0.01, "R" : 0.127, "CL_alpha": 6.0, "alpha_0": 0.15, "CD_alpha": 0.02, "CD_i": 0.05} # c          Cord length [m]

    p_["m"] = 0.5      # [kg]
    p_["g"] = 9.81     # [N/kg]
    p_["rho"] = 1.225  # [kg/m^3]

    L = 0.25
    
    I_max = p_["m"] * L**2 # Inertia of a point mass at a distance L
    I_ref = I_max/5   
    
    p_["I"] = casadi.diag([I_ref/2,I_ref/2,I_ref]) # [N.m^2]
    

    p_["rotors_p",0] = DM([L,0,0])
    p_["rotors_p",1] = DM([0,L,0])
    p_["rotors_p",2] = DM([-L,0,0])
    p_["rotors_p",3] = DM([0,-L,0])

    for i in range(NR):
        R_ = p_["rotors_model",i,"R"] #  Radius of propeller [m]
        m_ = 0.01 # Mass of a propeller [kg]
        I_max = m_ * R_**2 # Inertia of a point mass
        I_ref = I_max/5 
        p_["rotors_I",i] = casadi.diag([I_ref/2,I_ref/2,I_ref])

    if debug:
        print p.vecNZcat()
        
    dist_ = dist(0)
        
    # ----------------- Scaling ---------------------
    
    scaling_states   = states(1)
    scaling_controls = controls(1)
    
    scaling_states["r"] = 500
    scaling_controls["CR"] = 0.005
    
    scaling_dist = dist()
    
    scaling_dist["Faer"] = float(p_["m"]*p_["g"]/NR)
    scaling_dist["Caer"] = 0.0026

    # ----------- Frames ------------------
    T_10 = mul(tr(*pos),Tquat(*q))
    T_01 = kin_inv(T_10)
    R_10 = T2R(T_10)
    R_01 = R_10.T
    # -------------------------------------

    dstates = struct_symSX(states)
    
    dp,dv,dq,dw,dr = dstates[...]
    
    res = struct_SX(states) # DAE residual hand side
    # ----------- Dynamics of the body ----
    res["p"] = v - dp
    # Newton, but transform the force F from {1} to {0}
    res["v"] = mul(R_10,F) - m*dv
    # Kinematics of the quaterion.
    res["q"] = mul(quatDynamics(*q),w)-dq
    # This is a trick by Sebastien Gros to stabilize the quaternion evolution equation
    res["q"] += -q*(sumAll(q**2)-1)
    # Agular impulse H_1011
    H = mul(p["I"],w)    # Due to platform
    for i in range(NR):
      H+= mul(p["rotors_I",i], w + vertcat([0,0,p["rotors_spin",i]*r[i]])) # Due to rotor i

    dH = mul(jacobian(H,w),dw) + mul(jacobian(H,q),dq) + mul(jacobian(H,r),dr) + casadi.cross(w,H)

    res["w"] = C - dH

    for i in range(NR):
      res["r",i] = CR[i] + p["rotors_spin",i]*rotors_Caer[i][2] - p["rotors_I",i][2]*(dr[i]+dw[2]) # Dynamics of rotor i
    
    # ---------------------------------

    # Make a vector of f ?
    #if quatnorm:
    #    f = vertcat(f+[sumAll(q**2)-1])
    #else:
    #    f = vertcat(f)  

    # ------------ Force model ------------

    Fg = mul(R_01,vertcat([0,0,-g*m]))

    F_total = Fg + sum(rotors_Faer)    # Total force acting on the platform
    C_total = SX([0,0,0])                    # Total torque acting on the platform

    for i in range(NR):
       C_total[:2] += rotors_Caer[i][:2] # The x and y components propagate
       C_total[2] -= p["rotors_spin",i]*CR[i]         # the z compent moves through a serparate system
       C_total += casadi.cross(p["rotors_p",i],rotors_Faer[i]) # Torques due to thrust

    
    res = substitute(res,F,F_total)
    res = substitute(res,C,C_total)
    
    subs_before = []
    subs_after  = []
    
    v_global = mul(R_01,v)
    u_z = SX([0,0,1])
    
    # Now fill in the aerodynamic forces
    for i in range(NR):
        c,R,CL_alpha,alpha_0, CD_alpha, CD_i = p["rotors_model",i,...]
        #Bristeau P-jean, Martin P, Salaun E, Petit N. The role of propeller aerodynamics in the model of a quadrotor UAV. In: Proceedings of the European Control Conference 2009.; 2009:683-688.
        v_local = v_global + (casadi.cross(w,p["rotors_p",i])) # Velocity at rotor i
        rotors_Faer_physics =  (rho*c*R**3*r[i]**2*CL_alpha*(alpha_0/3.0-v_local[2]/(2.0*R*r[i]))) * u_z
        subs_before.append(rotors_Faer[i])
        subs_after.append(rotors_Faer_physics  + dist["Faer",i])
        rotors_Caer_physics = -p["rotors_spin",i]*rho*c*R**4*r[i]**2*(CD_alpha/4.0+CD_i*alpha_0**2*(alpha_0/4.0-2.0*v_local[2]/(3.0*r[i]*R))-CL_alpha*v_local[2]/(r[i]*R)*(alpha_0/3.0-v_local[2]/(2.0*r[i]*R))) * u_z
        subs_before.append(rotors_Caer[i])
        subs_after.append(rotors_Caer_physics  + dist["Caer",i])
    

    
    res = substitute(res,veccat(subs_before),veccat(subs_after))
    
    # Make an explicit ode
    rhs = - casadi.solve(jacobian(res,dstates),substitute(res,dstates,0))
    
    # --------------------------------------

    self.res_w = res
    self.res = substitute(res,dist,dist_)
    self.res_ = substitute(self.res,p,p_)
    
    resf = SXFunction([dstates, states, controls ],[self.res_])
    resf.init()
    self.resf = resf
    
    self.rhs_w = rhs
    
    self.rhs = substitute(rhs,dist,dist_)

    self.rhs_ = substitute(self.rhs,p,p_)

    t = SX("t")
    # We end up with a DAE that captures the system dynamics
    dae = SXFunction(daeIn(t=t,x=states,p=controls),daeOut(ode=self.rhs_))
    dae.init()
    
    self.dae = dae
    
    cdae = SXFunction(controldaeIn(t=t, x=states, u= controls,p=p),daeOut(ode=self.rhs))
    cdae.init()
    self.cdae = cdae

    self.states  = states
    self.dstates = dstates
    self.p = p
    self.p_ = p_
    self.controls = controls
    self.NR = NR
    self.w = dist
    self.w_ = dist_
    self.t = t
    
    self.states_  = states()
    self.dstates_ = states()
    self.controls_ = controls()
    
    self.scaling_states = scaling_states
    self.scaling_controls = scaling_controls
    self.scaling_dist = scaling_dist
Esempio n. 34
0
def create_rocket_stage_phase(mocp, phase_name, p, **kwargs):
    is_powered = kwargs['is_powered']
    has_heating = kwargs['has_heating']
    drag_area = kwargs['drag_area']
    maxQ = kwargs['maxQ']
    init_mass = kwargs['init_mass']
    init_position = kwargs['init_position']
    init_velocity = kwargs['init_velocity']

    if is_powered:
        init_steering = kwargs['init_steering']

        engine_type = kwargs['engine_type']
        engine_count = kwargs['engine_count']
        mdot_max = kwargs['mdot_max']
        mdot_min = kwargs['mdot_min']

        if engine_type == 'vacuum':
            effective_exhaust_velocity = kwargs['effective_exhaust_velocity']
        else:
            exhaust_velocity = kwargs['exhaust_velocity']
            exit_area = kwargs['exit_area']
            exit_pressure = kwargs['exit_pressure']

    duration = mocp.create_phase(phase_name, init=0.001, n_intervals=2)

    # Total vessel mass
    mass = mocp.add_trajectory(phase_name, 'mass', init=init_mass)

    # ECEF position vector
    rx = mocp.add_trajectory(phase_name, 'rx', init=init_position[0])
    ry = mocp.add_trajectory(phase_name, 'ry', init=init_position[1])
    rz = mocp.add_trajectory(phase_name, 'rz', init=init_position[2])
    r_vec = casadi.vertcat(rx, ry, rz)

    # ECEF velocity vector
    vx = mocp.add_trajectory(phase_name, 'vx', init=init_velocity[0])
    vy = mocp.add_trajectory(phase_name, 'vy', init=init_velocity[1])
    vz = mocp.add_trajectory(phase_name, 'vz', init=init_velocity[2])
    v_vec = casadi.vertcat(vx, vy, vz)

    if is_powered:

        # ECEF steering unit vector
        ux = mocp.add_trajectory(phase_name, 'ux', init=init_steering[0])
        uy = mocp.add_trajectory(phase_name, 'uy', init=init_steering[1])
        uz = mocp.add_trajectory(phase_name, 'uz', init=init_steering[2])

        u_vec = casadi.vertcat(ux, uy, uz)

        # Engine mass flow for a SINGLE engine
        mdot = mocp.add_trajectory(phase_name, 'mdot', init=mdot_max)
        mdot_rate = mocp.add_trajectory(phase_name, 'mdot_rate', init=0.0)

    if has_heating:
        heat = mocp.add_trajectory(phase_name, 'heat', init=0.0)

    ## Dynamics

    r_squared = rx**2 + ry**2 + rz**2 + 1e-8
    v_squared = vx**2 + vy**2 + vz**2 + 1e-8
    airspeed = v_squared**0.5
    r = r_squared**0.5
    altitude = r - 1
    r3_inv = r_squared**(-1.5)

    mocp.add_path_output(
        'downrange_distance',
        casadi.asin(
            casadi.norm_2(
                casadi.cross(
                    r_vec / r,
                    casadi.SX(
                        [p.launch_site_x, p.launch_site_y,
                         p.launch_site_z])))))
    mocp.add_path_output('altitude', altitude)
    mocp.add_path_output('airspeed', airspeed)
    mocp.add_path_output('vertical_speed', (r_vec.T / r) @ v_vec)
    mocp.add_path_output(
        'horizontal_speed_ECEF',
        casadi.norm_2(v_vec - ((r_vec.T / r) @ v_vec) * (r_vec / r)))

    # Gravitational acceleration (mu=1 is omitted)
    gx = -r3_inv * rx
    gy = -r3_inv * ry
    gz = -r3_inv * rz

    # Atmosphere
    atmosphere_fraction = casadi.exp(-altitude / p.scale_height)
    air_pressure = p.air_pressure_MSL * atmosphere_fraction
    air_density = p.air_density_MSL * atmosphere_fraction
    dynamic_pressure = 0.5 * air_density * v_squared
    mocp.add_path_output('dynamic_pressure', dynamic_pressure)

    if is_powered:
        lateral_airspeed = casadi.sqrt(
            casadi.sumsqr(v_vec - ((v_vec.T @ u_vec) * u_vec)) + 1e-8)
        lateral_dynamic_pressure = 0.5 * air_density * lateral_airspeed * airspeed  # Same as Q * sin(alpha), but without trigonometry
        mocp.add_path_output('lateral_dynamic_pressure',
                             lateral_dynamic_pressure)

        mocp.add_path_output(
            'alpha',
            casadi.acos((v_vec.T @ u_vec) / airspeed) * 180.0 / pi)
        mocp.add_path_output(
            'pitch', 90.0 - casadi.acos((r_vec.T / r) @ u_vec) * 180.0 / pi)

    # Thrust force
    if is_powered:
        if engine_type == 'vacuum':
            engine_thrust = effective_exhaust_velocity * mdot
        else:
            engine_thrust = exhaust_velocity * mdot + exit_area * (
                exit_pressure - air_pressure)

        total_thrust = engine_thrust * engine_count
        mocp.add_path_output('total_thrust', total_thrust)

        Tx = total_thrust * ux
        Ty = total_thrust * uy
        Tz = total_thrust * uz
    else:
        Tx = 0.0
        Ty = 0.0
        Tz = 0.0

    # Drag force
    drag_factor = (-0.5 * drag_area) * air_density * airspeed
    Dx = drag_factor * vx
    Dy = drag_factor * vy
    Dz = drag_factor * vz

    # Coriolis Acceleration
    ax_Coriolis = 2 * vy * p.body_rotation_speed
    ay_Coriolis = -2 * vx * p.body_rotation_speed
    az_Coriolis = 0.0

    # Centrifugal Acceleration
    ax_Centrifugal = rx * p.body_rotation_speed**2
    ay_Centrifugal = ry * p.body_rotation_speed**2
    az_Centrifugal = 0.0

    # Acceleration
    ax = gx + ax_Coriolis + ax_Centrifugal + (Dx + Tx) / mass
    ay = gy + ay_Coriolis + ay_Centrifugal + (Dy + Ty) / mass
    az = gz + az_Coriolis + az_Centrifugal + (Dz + Tz) / mass

    if is_powered:
        mocp.set_derivative(mass, -engine_count * mdot)
        mocp.set_derivative(mdot, mdot_rate)
    else:
        mocp.set_derivative(mass, 0.0)

    mocp.set_derivative(rx, vx)
    mocp.set_derivative(ry, vy)
    mocp.set_derivative(rz, vz)
    mocp.set_derivative(vx, ax)
    mocp.set_derivative(vy, ay)
    mocp.set_derivative(vz, az)

    # Heat flow
    heat_flow = 1e-4 * (air_density**0.5) * (airspeed**3.15)
    mocp.add_path_output('heat_flow', heat_flow)
    if has_heating:
        mocp.set_derivative(heat, heat_flow)

    ## Constraints

    # Duration is positive and bounded
    mocp.add_constraint(duration > 0.006)
    mocp.add_constraint(duration < 10.0)

    # Mass is positive
    mocp.add_path_constraint(mass > 1e-6)

    # maxQ soft constraint
    weight_dynamic_pressure_penalty = mocp.get_parameter(
        'weight_dynamic_pressure_penalty')
    slack_maxQ = mocp.add_trajectory(phase_name, 'slack_maxQ', init=10.0)
    mocp.add_path_constraint(slack_maxQ > 0.0)
    mocp.add_mean_objective(weight_dynamic_pressure_penalty * slack_maxQ)
    mocp.add_path_constraint(dynamic_pressure / maxQ < 1.0 + slack_maxQ)

    if is_powered:
        # u is a unit vector
        mocp.add_path_constraint(ux**2 + uy**2 + uz**2 == 1.0)

        # Do not point down
        mocp.add_path_constraint((r_vec / r).T @ u_vec > -0.2)

        # Engine flow limits
        mocp.add_path_constraint(mdot_min < mdot)
        mocp.add_path_constraint(mdot < mdot_max)

        # Throttle rate reduction
        mocp.add_mean_objective(1e-6 * mdot_rate**2)

        # Lateral dynamic pressure penalty
        weight_lateral_dynamic_pressure_penalty = mocp.get_parameter(
            'weight_lateral_dynamic_pressure_penalty')
        mocp.add_mean_objective(
            weight_lateral_dynamic_pressure_penalty *
            (lateral_dynamic_pressure / p.maxQ_sin_alpha)**8)

    variables = locals().copy()
    RocketStagePhase = collections.namedtuple('RocketStagePhase',
                                              sorted(list(variables.keys())))
    return RocketStagePhase(**variables)
Esempio n. 35
0
def aero(xd, xa, p, puni, l, params):
    [q, dq, R, w, coeff, E, Drag] = xd[...]
    # --- Build current wind shear profile
    #
    Lagrange_polynomial_x = fcts.Lagrange_poly(puni['altitude'], puni['tau_x'])
    Lagrange_polynomial_y = fcts.Lagrange_poly(puni['altitude'], puni['tau_y'])
    # --- wind vector & apparent velocity
    xwind = Lagrange_polynomial_x(q[-1])
    ywind = Lagrange_polynomial_y(q[-1])
    v_app = dq - np.array([xwind, ywind, 0])

    # xwind = puni['wind']*(q[-1]/params['windShearRefAltitude'])**0.15   #NOTE:AUTOMATE THAT!!!!!!
    # v_app = dq - np.array([xwind,0,0])

    # --- calculate angle of attack and side slip (convert apparent velocity to body frame)
    AoA = -ca.mtimes(R[6:9].T, (v_app)) / ca.mtimes(R[0:3].T, (v_app))
    sslip = ca.mtimes(R[3:6].T, (v_app)) / ca.mtimes(R[0:3].T, (v_app))

    params['rho'] = fcts.rho(q[-1])
    CF, CM, Cl, Cm, Cn = aero_coeffs(AoA, sslip, v_app, w, coeff, params)

    F_aero = 0.5 * params['rho'] * params['sref'] * ca.norm_2(v_app) * (
        ca.cross(CF[2] * v_app, R[3:6]) + CF[0] * (v_app))
    reference_lengths = ca.vertcat(
        [params['bref'], params['cref'], params['bref']])
    M_aero = 0.5 * params['rho'] * params['sref'] * ca.norm_2(
        v_app)**2 * CM * reference_lengths

    F_drag = -Drag * R[0:3] * params[
        'eff']  # Drag in opposite x-direction of kite (Props)
    F_tether = q * xa  # Force of the tether at the kite
    # m           = params['mK'] + 1./3*params['mT']
    m = params[
        'mK'] + 1. / 3 * params['tether_density'] * l  #mass of kite and tether

    F_gravity = m * params['g']

    # --- Tether Drag, defined in + x direction , therefore minus sign
    C_tet = 0.4
    Tether_drag = -1. / 8 * params['rho'] * params[
        'tether_diameter'] * C_tet * l * ca.norm_2(v_app)**2 * R[0:3]
    # Tether_drag  =  -  1./6 * params['rho'] * params['tether_diameter'] * C_tet * l * ca.norm_2(v_app)**2 * R[0:3]

    outputs = {}
    outputs['v_app'] = v_app
    # outputs['rho']              = params['rho']
    outputs['speed'] = ca.norm_2(v_app)
    outputs['windspeed_shear'] = xwind
    # outputs['windspeedy_shear'] = ywind
    outputs['momentconst'] = ([Cl, Cm, Cn])
    outputs['AoA'] = AoA
    outputs['sslip'] = sslip
    outputs['AoA_deg'] = AoA * 180 / pi
    outputs['sslip_deg'] = sslip * 180 / pi
    outputs['CL'] = CF[2]
    outputs['CD'] = -CF[0]
    outputs['F_aero'] = F_aero
    outputs['F_drag'] = F_drag
    outputs['F_tether_scaled'] = F_tether  # This is scaled so Force/kg
    outputs['F_tether'] = F_tether * m
    outputs['tethercstr'] = (xa * l * m) - pi / 3. * (
        params['tether_diameter'] * 1000 /
        2.)**2 * 3600  # tdiameter in m, l*xa = F_tether instead of norm (q*xa)
    # Tensile strength of aramid: 3600N/mm^2, while dyneema has only 1700?
    outputs['M_aero'] = M_aero
    outputs['power'] = ca.mtimes(F_drag.T, dq)
    outputs['Tether_drag'] = Tether_drag
    return (F_aero, M_aero, F_tether, F_drag, F_gravity, Tether_drag), outputs
Esempio n. 36
0
       
    """
    eTe_f = C.veccat([eTe_f_1, eTe_f_2, eTe_f_3])
    rho = conf["rho"]
    alpha0 = conf["alpha0deg"] * C.pi / 180

    sref = conf["sref"]
    bref = conf["bref"]
    cref = conf["cref"]

    vKite2 = C.mul(v_bw_f.T, v_bw_f)  # Airfoil speed^2
    vKite = C.sqrt(vKite2)  # Airfoil speed
    dae["airspeed"] = vKite

    # Lift axis, normed to airspeed
    eLe_v_f = C.cross(eTe_f, v_bw_f)

    # sideforce axis, normalized to airspeed^2
    eYe_v2_f = C.cross(eLe_v_f, -v_bw_f)

    if conf["alpha_beta_computation"] == "first_order":
        alpha = alpha0 + v_bw_b[2] / v_bw_b[0]
        beta = v_bw_b[1] / v_bw_b[0]
    #        beta = v_bw_b_y / C.sqrt(v_bw_b[0]*v_bw_b[0] + v_bw_b[2]*v_bw_b[2])
    elif conf["alpha_beta_computation"] == "closed_form":
        (alpha, beta) = getWindAnglesFrom_v_bw_b(vKite, v_bw_b)
        alpha += alpha0
    else:
        raise ValueError(
            'config "alpha_beta_compuation" value '
            + str(conf["alpha_beta_computation"])
Esempio n. 37
0
def design_reference(phi_0,
                     A_phi,
                     f_phi,
                     theta_0,
                     A_theta,
                     f_theta,
                     time,
                     run_test=False):
    """TODO: Docstring for design_reference.

    :phi_0: TODO
    :A_phi: TODO
    :f_phi: TODO
    :theta_0: TODO
    :A_theta: TODO
    :f_theta: TODO
    :returns: TODO

    """
    def evaluate_scalar_casadi_function(fun, var):
        """TODO: Docstring for evaluate_scalar_casadi_function.

        :fun: TODO
        :var: TODO
        :returns: TODO

        """
        return np.squeeze(np.double(fun(var)))

    def f_eval_cs_vec(fun, var):
        """TODO: Docstring for f_eval_cs_vec.

        :fun: TODO
        :var: TODO
        :returns: TODO

        """
        return np.double(fun(var).reshape((3, 1))).reshape(3)

    # phi_0 = 0
    # A_phi = np.pi/6
    # f_phi = 0.5

    # theta_0 = 0
    # A_theta = np.pi/8
    # f_theta = 0.5

    # Symbolics
    t = cs.SX.sym('t', 1, 1)

    phi = phi_0 + A_phi * cs.sin(2 * cs.pi * f_phi * t)
    dphi = cs.jacobian(phi, t)
    ddphi = cs.jacobian(dphi, t)

    theta = theta_0 + A_theta * cs.cos(2 * cs.pi * f_theta * t)
    dtheta = cs.jacobian(theta, t)
    ddtheta = cs.jacobian(dtheta, t)

    Gamma = Geometric_controller.compute_sym_Gamma_rp(phi, theta)
    # Gamma_dot = cg.orthogonal_projector(Gamma)@cs.jacobian(Gamma, t)
    Gamma_dot = cs.jacobian(Gamma, t)
    omega = cs.cross(Gamma_dot, Gamma)
    omega_dot = cs.jacobian(omega, t)

    f_phi = cs.Function('phi', [t], [phi])
    f_theta = cs.Function('theta', [t], [theta])
    f_Gamma = cs.Function('Gamma', [t], [Gamma])
    f_Gamma_dot = cs.Function('Gamma_dot', [t], [Gamma_dot])
    f_omega = cs.Function('omega', [t], [omega])
    f_omega_dot = cs.Function('omega_dot', [t], [omega_dot])

    # Gamma_dot = cg.compute_perpendicular_projector(Gamma)@

    # Generate numeric values
    t = time
    t0 = t[0]
    dt = t[1] - t[0]
    fs = 1 / dt
    T = t[-1] + dt
    N = len(t)

    phi = np.zeros(N)
    theta = np.zeros(N)
    Gamma = np.zeros((3, N))
    Gamma_dot = np.zeros((3, N))
    omega = np.zeros((3, N))
    omega_dot = np.zeros((3, N))

    phi = np.squeeze(np.double(f_phi(t)))
    theta = np.squeeze(np.double(f_theta(t)))

    is_orthogonal_Gamma_omega = np.zeros(N)

    test_orthogonal_Gamma_omega = 0
    test_orthogonal_Gamma_Gamma_dot = 0
    for k in range(0, N):
        Gamma[:, k] = f_eval_cs_vec(f_Gamma, t[k])
        Gamma_dot[:, k] = f_eval_cs_vec(f_Gamma_dot, t[k])
        omega[:, k] = f_eval_cs_vec(f_omega, t[k])
        omega_dot[:, k] = f_eval_cs_vec(f_omega_dot, t[k])

        test_orthogonal_Gamma_omega += np.dot(Gamma[:, k], omega[:, k])**2
        test_orthogonal_Gamma_Gamma_dot += np.dot(Gamma[:, k], Gamma_dot[:,
                                                                         k])**2

    if run_test:
        print('Design reference')
        print('# Tests failed:' + str(
            test_eval(test_orthogonal_Gamma_omega) +
            test_eval(test_orthogonal_Gamma_Gamma_dot)))

        # Integration Test
        Gamma_integrated = np.zeros((3, N))
        omega_integrated = np.zeros((3, N))
        x_Gamma = Gamma[:,
                        0]  #Geometric_controller.compute_Gamma_rp(phi[0], theta[0])
        x_omega = omega[:, 0]

        for k in range(0, N):
            Gamma_dot = np.cross(Gamma[:, k], omega[:, k])
            x_Gamma += dt * Gamma_dot
            x_Gamma = x_Gamma / np.linalg.norm(x_Gamma)
            Gamma_integrated[:, k] = x_Gamma

            x_omega += dt * omega_dot[:, k]
            # x_omega += Geometric_controller.compute_perpendicular_projector(Gamma[:, k])@x_omega
            omega_integrated[:, k] = x_omega

        fig, ax = plt.subplots(2, 1)
        color = ['r', 'g', 'b']
        for i in range(0, 3):
            ax[0].plot(t, Gamma[i, :].T, color=color[i])
            ax[0].plot(t,
                       Gamma_integrated[i, :].T,
                       color=color[i],
                       linestyle='--')
            ax[1].plot(t, omega[i, :].T, color=color[i])
            ax[1].plot(t,
                       omega_integrated[i, :].T,
                       color=color[i],
                       linestyle='--')
            plt.show(block=False)

    return [Gamma, omega, omega_dot]
Esempio n. 38
0
def aero_drag_ampyx(xd, xa, p, puni, l, params):
    [q, dq, R, w, coeff, E, Drag] = xd[...]
    # --- Build current wind shear profile
    Lagrange_polynomial_x = fcts.Lagrange_poly(puni['altitude'], puni['tau_x'])
    Lagrange_polynomial_y = fcts.Lagrange_poly(puni['altitude'], puni['tau_y'])
    # --- wind vector & apparent velocity
    xwind = Lagrange_polynomial_x(q[-1])
    ywind = Lagrange_polynomial_y(q[-1])
    v_app = dq - np.array([xwind, ywind, 0])

    # xwind = puni['wind']*(q[-1]/params['windShearRefAltitude'])**0.15   #NOTE:AUTOMATE THAT!!!!!!
    # v_app = dq - np.array([xwind,0,0])

    v_app_body = ca.mtimes(R.T, v_app)

    # calculate angle of attack and side slip (convert apparent velocity to body frame)
    AoA = -ca.mtimes(R[6:9].T, (v_app)) / ca.mtimes(R[0:3].T, (v_app))
    sslip = ca.mtimes(R[3:6].T, (v_app)) / ca.mtimes(R[0:3].T, (v_app))

    CF, CM, CD, CL = aero_coeffs_ampyx(AoA, sslip, v_app, w, coeff, params)

    W0 = v_app / ca.norm_2(v_app)
    W2 = ca.cross(v_app, R[3:6]) / ca.norm_2(v_app)
    W1 = ca.cross(W2, W0)
    W = ca.vertcat(W0.T, W1.T, W2.T).T

    #NED to zUp
    #NED2zup =  [ [1, 0, 0], [0, -1, 0], [0, 0, -1]]
    #NED2zup = np.reshape(NED2zup, (3,3))
    #CF      = ca.mtimes(NED2zup,CF)
    F_aero = ca.mtimes(W, CF)
    M_aero = CM
    # F_aero = 0.5 * params['rho'] * params['sref'] * ca.norm_2(v_app) * (ca.cross(-CF[2]*v_app,R[3:6]) + CF[0]*(v_app) )
    # reference_lengths = ca.vertcat([params['bref'], params['cref'], params['bref']])
    # M_aero = 0.5 * params['rho'] * params['sref'] *  ca.norm_2(v_app)**2 * CM # * reference_lengths

    F_drag = -Drag * R[0:3] * params[
        'eff']  # Drag in opposite x-direction of kite (Props)
    F_tether = q * xa  # Force of the tether at the kite
    m = params['mK'] + 1. / 3 * params['tether_density'] * l
    # m   = params['mK'] + 1./3*params['tether_density']*ltet    #mass of kite and tether

    F_gravity = m * params['g']

    # Tether Drag
    # defined in + x direction , therefore minus sign
    C_tet = 1.2
    # Tether_drag  =  - 1./8 * params['rho'] * params['tether_diameter'] * C_tet * ltet * ca.norm_2(v_app)**2 * ca.veccat(ca.cos(AoA), 0, ca.sin(AoA))
    Tether_drag = -1. / 8 * params['rho'] * params[
        'tether_diameter'] * C_tet * l * ca.norm_2(v_app) * v_app

    Tether_drag_body = Tether_drag  #!!!!----NOTE: It should be nav frame from the beginning, since we use v_app_nav, right?

    outputs = {}
    outputs['v_app'] = v_app
    outputs['speed'] = ca.norm_2(v_app)
    outputs['windspeed_shear'] = xwind
    outputs['AoA'] = AoA
    outputs['sslip'] = sslip
    outputs['AoA_deg'] = AoA * 180 / pi
    outputs['sslip_deg'] = sslip * 180 / pi
    outputs['CL'] = CL[0][0]
    outputs['CD'] = -CD[0][0]
    outputs['F_aero'] = F_aero
    outputs['F_aero_b'] = ca.mtimes(R.T, F_aero)
    outputs['F_drag'] = F_drag
    outputs['F_tether_scaled'] = F_tether  # This is scaled so Force/kg
    outputs['F_tether'] = F_tether * m
    outputs['tethercstr'] = (xa * l * m) - pi / 3. * (
        params['tether_diameter'] * 1000 /
        2.)**2 * 3600  # tdiameter in m, l*xa = F_tether instead of norm (q*xa)
    outputs['M_aero'] = M_aero
    outputs['power'] = ca.mtimes(F_drag.T, dq)
    outputs['Tether_drag'] = Tether_drag
    return (F_aero, M_aero, F_tether, F_drag, F_gravity, Tether_drag), outputs
def generate_figures():
    import matplotlib
    import matplotlib.pyplot as plt
    import numpy as np
    import json

    with open('trajectory.json', 'r') as f:
        data = json.load(f)

    phases = data['phases']
    scale = data['scale']

    # Profile plot
    e1 = normalize(
        DM([
            phases['ascent']['trajectories']['rx'][0],
            phases['ascent']['trajectories']['ry'][0],
            phases['ascent']['trajectories']['rz'][0]
        ]))
    e2 = -normalize(
        DM([
            phases['target']['trajectories']['rx'][0],
            phases['target']['trajectories']['ry'][0],
            phases['target']['trajectories']['rz'][0]
        ]))
    e3 = normalize(cross(e1, e2))
    e2 = normalize(cross(e3, e1))
    R = casadi.horzcat(e1, e2, e3).T

    fig, ax = plt.subplots()
    fig.set_size_inches(fig.get_size_inches() * 0.6)
    to_km = scale['length'] / 1000
    a = np.linspace(0, 2 * pi, 200)
    ax.plot(np.cos(a) * to_km, np.sin(a) * to_km, 'k')
    for phase_name in phases:
        position_trajectory = R @ DM([
            phases[phase_name]['trajectories']['rx'],
            phases[phase_name]['trajectories']['ry'],
            phases[phase_name]['trajectories']['rz']
        ])
        position_trajectory = np.array(position_trajectory)
        ax.plot(position_trajectory[1] * to_km, position_trajectory[0] * to_km)

    ax.set(xlabel='y (km)', ylabel='x (km)', title='Path Profile')
    ax.axis('equal')
    ax.grid()
    fig.tight_layout()
    fig.savefig('fig/trajectory_profile.png', dpi=288)
    ax.set_xlim(-300, 300)
    ax.set_ylim(-300 + 600, 300 + 600)
    fig.tight_layout()
    fig.savefig('fig/trajectory_profile_zoomed.png', dpi=288)
    plt.close('all')

    fig, ax = plt.subplots()
    fig.set_size_inches(fig.get_size_inches() * 0.6)
    to_km = scale['length'] / 1000
    a = np.linspace(0, 2 * pi, 200)
    ax.plot(np.cos(a) * to_km, np.sin(a) * to_km, 'k')
    for phase_name in phases:
        position_trajectory = R @ DM([
            phases[phase_name]['trajectories']['rx'],
            phases[phase_name]['trajectories']['ry'],
            phases[phase_name]['trajectories']['rz']
        ])
        position_trajectory = np.array(position_trajectory)
        ax.plot(position_trajectory[2] * to_km, position_trajectory[0] * to_km)

    ax.set(xlabel='z (km)', ylabel='x (km)', title='Path Parallel')
    ax.axis('equal')
    ax.grid()
    fig.tight_layout()
    fig.savefig('fig/trajectory_parallel.png', dpi=288)
    ax.set_xlim(-300, 300)
    ax.set_ylim(-300 + 600, 300 + 600)
    fig.tight_layout()
    fig.savefig('fig/trajectory_parallel_zoomed.png', dpi=288)
    plt.close('all')

    # Timeseries plots
    paths = \
        sorted(list(set([('trajectories',k) for e in phases.values() for k in e['trajectories'].keys()])))+\
        sorted(list(set([('outputs',k) for e in phases.values() for k in e['outputs'].keys()])))

    for path in paths:
        fig, ax = plt.subplots()
        fig.set_size_inches(fig.get_size_inches() * 0.6)
        for phase_name in phases:
            path_scale = get_scale_factor(path[1], scale)
            ax.set(xlabel='Time (s)', ylabel=path[1], title=path[1])

            if path[1] in phases[phase_name][path[0]]:
                if path[1] in ['mass', 'rx', 'ry', 'rz', 'altitude']:
                    path_scale /= 1000.0
                elif 'pressure' in path[1]:
                    path_scale /= 1000.0
                t_grid = phases[phase_name]['start_time'] + phases[phase_name][
                    'duration'] * np.linspace(
                        0.0, 1.0, len(phases[phase_name][path[0]][path[1]]))
                ax.plot(
                    scale['time'] * t_grid,
                    np.array(phases[phase_name][path[0]][path[1]]) *
                    path_scale)

        ax.grid()
        fig.tight_layout()
        fig.savefig('fig/trajectory_' + path[1] + '.png', dpi=288)
        plt.close('all')
Esempio n. 40
0
    sref = conf['sref']
    bref = conf['bref']
    cref = conf['cref']

    # airfoil speed in wind frame
    v_bw_n_x = v_bw_n[0]
    v_bw_n_y = v_bw_n[1]
    v_bw_n_z = v_bw_n[2]

    vKite2 = C.mul(v_bw_n.trans(), v_bw_n)  #Airfoil speed^2
    vKite = C.sqrt(vKite2)  #Airfoil speed
    dae['airspeed'] = vKite

    # Lift axis, normed to airspeed
    eLe_v = C.cross(C.veccat([eTe1, eTe2, eTe3]), v_bw_n)

    # sideforce axis, normalized to airspeed^2
    eYe_v2 = C.cross(eLe_v, -v_bw_n)

    # Relative wind speed in Airfoil's referential 'E'
    v_bw_b_x = v_bw_b[0]
    v_bw_b_y = v_bw_b[1]
    v_bw_b_z = v_bw_b[2]

    if conf['alpha_beta_computation'] == 'first_order':
        alpha = alpha0 + v_bw_b_z / v_bw_b_x
        beta = v_bw_b_y / v_bw_b_x
#        beta = v_bw_b_y / C.sqrt(v_bw_b_x*v_bw_b_x + v_bw_b_z*v_bw_b_z)
    elif conf['alpha_beta_computation'] == 'closed_form':
        (alpha, beta) = getWindAnglesFrom_v_bw_b(vKite, v_bw_b)
 def angular_acceleration(self, inputs, omega):
     tau = self.torques(inputs)
     omegadot = mtimes(self.I_inv,
                       tau - cross(omega, mtimes(self.I, omega)))
     return omegadot