Esempio n. 1
0
    def regress_model_no_surface(self):
        '''
        regress the H matrix for DFL model
        '''
        omega = np.concatenate(
            (self.X_minus.reshape(-1, self.X_minus.shape[-1]),
             self.Eta_minus.reshape(-1, self.Eta_minus.shape[-1]),
             self.U_minus.reshape(-1, self.U_minus.shape[-1])),
            axis=1).T

        Y = self.Eta_plus.reshape(-1, self.Eta_plus.shape[-1]).T

        H_disc = lstsq(omega.T, Y.T, rcond=None)[0].T

        self.H_disc_x = H_disc[:, :self.plant.n_x]
        self.H_disc_eta = H_disc[:, self.plant.n_x:self.plant.n_x +
                                 self.plant.n_eta]
        self.H_disc_u = H_disc[:, self.plant.n_x +
                               self.plant.n_eta:self.plant.n_x +
                               self.plant.n_eta + self.plant.n_u]

        (self.A_disc_x, self.B_disc_x, _, _, _) = cont2discrete(
            (self.plant.A_cont_x, self.plant.B_cont_x, np.zeros(
                self.plant.n_x), np.zeros(self.plant.n_u)), self.dt_data)

        (_, self.A_disc_eta, _, _, _) = cont2discrete(
            (self.plant.A_cont_x, self.plant.A_cont_eta,
             np.zeros(self.plant.n_x), np.zeros(self.plant.n_u)), self.dt_data)
    def __init__(self, VehicleParameters, EnvironmentParameters,TuningParameters,SimulationParameters):
        #   x-axis
        A_x = np.zeros((2,2)); A_x[0,1] = 1;
        B_x = np.zeros((2,1)); B_x[1] = -EnvironmentParameters.g; 
        C_x = np.zeros((2,2)); C_x[0,0] = 1; C_x[1,1] = 1;
        D_x = np.zeros((2,1));
        sys_x_d = signal.cont2discrete((A_x,B_x,C_x,D_x),TuningParameters.Ts,"zoh");

        #   y-axis
        A_y = np.zeros((2,2)); A_y[0,1] = 1;
        B_y = np.zeros((2,1)); B_y[1] = EnvironmentParameters.g; 
        C_y = np.zeros((2,2)); C_y[0,0] = 1; C_y[1,1] = 1;
        D_y = np.zeros((2,1));
        sys_y_d = signal.cont2discrete((A_y,B_y,C_y,D_y),TuningParameters.Ts,"zoh");

        #   z-axis
        A_z = np.zeros((2,2)); A_z[0,1] = 1;
        B_z = np.zeros((2,1)); B_z[1] = 1; 
        C_z = np.zeros((2,2)); C_z[0,0] = 1; C_z[1,1] = 1;
        D_z = np.zeros((2,1));
        sys_z_d = signal.cont2discrete((A_z,B_z,C_z,D_z),TuningParameters.Ts,"zoh");

        self.VehicleParameters = VehicleParameters;
        self.EnvironmentParameters = EnvironmentParameters;
        self.TuningParameters = TuningParameters;
        self.SimulationParameters = SimulationParameters;
        self.SysX_d = sys_x_d;
        self.SysY_d = sys_y_d;
        self.SysZ_d = sys_z_d;
Esempio n. 3
0
def get_filter(spec, filter_type='but', method='zoh'):

    wp = 2*np.pi*spec['fp']
    ws = 2*np.pi*spec['fs']

    if method == 'bilinear':
        wp = 2/spec['dt'] * np.arctan(wp * spec['dt']/2)
        ws = 2/spec['dt'] * np.arctan(ws * spec['dt']/2)
    
    if filter_type.lower() in ('butterworth'):
        N, Wn = signal.buttord(wp, ws, spec['Amax'], spec['Amin'], analog=True)
        z, p, k = signal.butter(N, Wn, output='zpk', btype='low', analog=True)
    elif filter_type.lower() in ('cauer' + 'elliptic'):
        N, Wn = signal.ellipord(wp, ws, spec['Amax'], spec['Amin'], analog=True)
        z, p, k = signal.ellip(N, spec['Amax'], spec['Amin'], Wn, output='zpk', btype='low', analog=True)

    if method == 'matched':
        zd, pd, kd, dt = matched_method(z, p, k, spec['dt'])
        kd *= 1 - (1 - 10 ** (-spec['Amax']/20))/2
    else:
        zd, pd, kd, dt = signal.cont2discrete((z,p,k), spec['dt'], method=method)

    analog_system = (z,p,k)
    discrete_system = (zd,pd,kd)

    return analog_system, discrete_system
Esempio n. 4
0
    def getDiscrete(self, A, B):
        """
		get ZOH approximation of A and B matrices
		"""
        (A_d, B_d, _, _, _) = cont2discrete((A, B, self.C, self.D), self.dt)

        return A_d, B_d
Esempio n. 5
0
    def set_tf(self, input_: Signal, output: Signal, tf):
        """
        Method to assign an output signal as a function of the input signal by applying a given transfer function.
        The transfer function is discretized using a timestep of "dt" by applying the zero-order hold method.

        :param input_:      Input signal.
        :param output:      Output signal (should be an AnalogState that is not yet assigned)
        :param tf:          Tuple consisting of a list of numerator coefficients and a list of denominator coefficients.  See
                            https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.signal.cont2discrete.html for more details.
        :return:
        """

        # discretize transfer function
        res = cont2discrete(tf, self.dt)

        # get numerator and denominator coefficients
        b = [+float(val) for val in res[0].flatten()]
        a = [-float(val) for val in res[1].flatten()]

        # create input and output histories
        i_hist = self.make_history(input_, len(b))
        o_hist = self.make_history(output, len(a))

        # implement the filter
        expr = sum_op([
            coeff * var
            for coeff, var in chain(zip(b, i_hist), zip(a[1:], o_hist))
        ])

        # make the assignment
        self.set_next_cycle(signal=output, expr=expr)
Esempio n. 6
0
def get_filter(spec, filter_type='but', method='zoh'):
    
    if filter_type.lower() in ('butterworth'):
        N, Wn = signal.buttord(2*np.pi*spec['fp'], 2*np.pi*spec['fs'], spec['Amax'], spec['Amin'], analog=True)
        z, p, k = signal.butter(N, Wn, output='zpk', btype='low', analog=True)
    elif filter_type.lower() in ('cauer' + 'elliptic'):
        N, Wn = signal.ellipord(2*np.pi*fp, 2*np.pi*spec['fs'], spec['Amax'], spec['Amin'], analog=True)
        z, p, k = signal.ellip(N, spec['Amax'], spec['Amin'], Wn, output='zpk', btype='low', analog=True)

    def matched_method(z, p, k, dt):
        zd = np.exp(z*dt)
        pd = np.exp(p*dt)
        kd = k * np.abs(np.prod(1-pd)/np.prod(1-zd) * np.prod(z)/np.prod(p))
        return zd, pd, kd, dt

    if method == 'matched':
        zd, pd, kd, dt = matched_method(z, p, k, spec['dt'])
        kd *= 1 - (1 - 10 ** (-spec['Amax']/20))/2
    else:
        zd, pd, kd, dt = signal.cont2discrete((z,p,k), spec['dt'], method=method)

    analog_system = (z,p,k)
    discrete_system = (zd,pd,kd)

    return analog_system, discrete_system
Esempio n. 7
0
    def __init__(self):
        """ Linear aircraft model wrapped by OpenAI Gym template."""
        # load saved model (csv format)
        model_name = 'f18a_model'
        model = np.genfromtxt(model_name, delimiter=',', skip_header=1)
        self.labels = np.genfromtxt(model_name,
                                    dtype=str,
                                    delimiter=',',
                                    max_rows=1)
        self.labels = list(self.labels)

        # organize matrices
        self.n_states = model.shape[0]
        self.n_controls = model.shape[
            1] - self.n_states - 1  # last col is trimmed
        self.A = model[:, :self.n_states]
        self.B = model[:, self.n_states:-1]
        self.label_states = self.labels[:self.n_states]
        self.label_controls = self.labels[self.n_states:]

        # trimmed states (x0)
        self.x0 = model[:, -1].reshape(1, self.n_states)

        # adding altitude (h)
        self.n_states += 1
        self.U1 = 1004.793
        h_dot_a = np.array([[0, -self.U1, 0, self.U1, 0, 0, 0, 0, 0, 0]])
        h_dot_b = np.array([[0, 0, 0]])
        # augment old a and b
        self.A = np.hstack((self.A, np.zeros((9, 1))))
        self.A = np.vstack((self.A, h_dot_a))
        self.B = np.vstack((self.B, h_dot_b))

        # augment x0 and labels
        self.label_states.append('$h$ (ft)')
        h0 = 5000  # ft
        self.x0 = np.column_stack((self.x0, h0))

        # initialize C assuming full-state feedback and empty D
        self.C = np.eye(self.n_states)
        self.D = np.zeros_like(self.B)

        # create system as discretize
        self.dt = 1 / 50
        self.dsys = signal.cont2discrete((self.A, self.B, self.C, self.D),
                                         self.dt)
        self.dA = self.dsys[0]
        self.dB = self.dsys[1]

        # ACTIONS
        self.action_space = spaces.Box(low=-np.pi,
                                       high=np.pi,
                                       shape=(self.n_controls, ),
                                       dtype=np.float32)

        # STATES
        self.observation_space = spaces.Box(low=-np.inf,
                                            high=np.inf,
                                            shape=(self.n_states, ),
                                            dtype=np.float32)
Esempio n. 8
0
    def get_SS(
        self, state
    ):  #This appears to match what Mat has. Need to run his matlab code to be sure
        v = state[3:6]
        phi = state[6]
        theta = state[7]
        psi = state[8]
        w = state[9:]

        ct = np.cos(theta)
        st = np.sin(theta)
        cp = np.cos(phi)
        sp = np.sin(phi)

        A = np.zeros((12, 12))

        dpd_dv = Rotation.from_euler('ZYX', [psi, theta, phi]).as_dcm()
        A[:3, 3:6] = dpd_dv

        dvd_dv = -skew(w)
        dvd_dw = skew(v)
        dvd_dang = np.array([[0, -self.g * ct, 0],
                             [self.g * ct * cp, -self.g * st * sp, 0],
                             [-self.g * ct * sp, -self.g * st * cp, 0]])
        # A[3:6, 3:6] = dvd_dv  #Mat isn't using this. Will try adding it later
        A[3:6, 6:9] = dvd_dang
        # A[3:6, 9:] = dvd_dw #Mat isn't using this. Will try adding it later

        dangd_dw = np.array([[1.0, sp * st / ct, cp * st / ct], [0.0, cp, -sp],
                             [0.0, sp / ct, cp / ct]])
        # A[6:9, 9:] = dangd_dw
        A[6:9, 9:] = np.eye(
            3
        )  #Mat is doing this not the line above. Will try switching it later

        dwd_dw = np.linalg.inv(
            self.J) @ (-skew(self.J @ w) @ (-np.eye(3)) + skew(-w) @ self.J)
        # A[9:, 9:] = dwd_dw #Mat isn't using this. Will try adding it later

        B = np.zeros((12, 4))

        dvd_du = np.zeros((3, 4))
        dvd_du[2, 0] = -1 / self.m
        B[3:6] = dvd_du

        dwd_du = np.zeros((3, 4))
        dwd_du[:, 1:] = np.diag(
            [1 / self.J[0, 0], 1 / self.J[1, 1], 1 / self.J[2, 2]])
        B[9:] = dwd_du

        C = np.eye(12)  #Full state Feedback
        D = np.zeros((12, 4))

        sysd = ss.cont2discrete((A, B, C, D),
                                self.dt)  #Get the discrete time system
        Ad = sysd[0]
        Bd = sysd[1]

        # return A, B
        return Ad, Bd
def linearized_model(state):
    g = 9.8
    m = 0.044
    # linear continuous system
    Ac = np.array([
        [0, 0, 0, 1, 0, 0],
        [0, 0, 0, 0, 1, 0],
        [0, 0, 0, 0, 0, 1],
        [0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0]
    ])
    Bc = np.array([
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0],
        [g, 0, 0],
        [0, - g, 0],
        [0, 0, 1.0/m]
    ])
    Cc = np.eye(Ac.shape[0])  # Full state observed
    Dc = np.zeros((Bc.shape[0], Bc.shape[1]))
    sysd = ss.cont2discrete((Ac, Bc, Cc, Dc), dt)  # Get the discrete time system
    Ad = sysd[0]
    Bd = sysd[1]
    return Ad, Bd
Esempio n. 10
0
    def __init__(
            self,
            input_size,
            hidden_size,
            memory_size,
            memory_order,
            A,
            B,
            trainable_scale=0.,  # how much to scale LR on A and B
            dt=0.01,
            discretization='zoh',
            **kwargs):
        super().__init__(input_size, hidden_size, memory_size, memory_order,
                         **kwargs)

        C = np.ones((1, memory_order))
        D = np.zeros((1, ))
        dA, dB, _, _, _ = signal.cont2discrete((A, B, C, D),
                                               dt=dt,
                                               method=discretization)

        dA = dA - np.eye(memory_order)  # puts into form: x += Ax
        self.trainable_scale = np.sqrt(trainable_scale)
        if self.trainable_scale <= 0.:
            self.register_buffer('A', torch.Tensor(dA))
            self.register_buffer('B', torch.Tensor(dB))
        else:
            self.A = nn.Parameter(torch.Tensor(dA / self.trainable_scale),
                                  requires_grad=True)
            self.B = nn.Parameter(torch.Tensor(dB / self.trainable_scale),
                                  requires_grad=True)
Esempio n. 11
0
def generate_state_space(v, dt):
    A1, B1 = benchmark_state_space(*benchmark_matrices(), v=v, g=9.80665)
    A = np.zeros((5, 5))
    B = np.zeros((5, 2))
    A[1:, 1:] = A1
    B[1:, :] = B1
    p = benchmark_parameters()
    A[0, 2] = v*np.cos(p['lambda'])/p['w']
    A[0, 4] = p['c']*np.cos(p['lambda'])/p['w']

    C = np.eye(5)
    D = np.zeros((5, 2))
    Ad, Bd, _, _, _ = sig.cont2discrete((A, B, C, D), dt, 'bilinear')

    print('A <<')
    print_matrix(A)

    print('B <<')
    print_matrix(B)

    print('Ad <<')
    print_matrix(Ad)

    print('Bd <<')
    print_matrix(Bd)
Esempio n. 12
0
    def initiate_model(self, configfile):
        # Load parameters from configuration file
        J = 0.01
        b = 0.1
        K = 0.01
        K = 0.01
        R = 1.
        L = 0.5
        
        # Time step
        self.h = 0.1
        self.nStates = 3
        self.nMeasurements = 1
        self.nControl = 1

        # Continuous time DC model
        A = np.array([[0., 1., 0.],[0., -b/J, K/J],[0., -K/L, -R/L]])
        B = np.array([[0.],[0.],[1./L]])
        C = np.array([[0.,1.,0.]])
        D = np.array([[0.]])
        
        # Discretize system using zero order hold
        dsys = cont2discrete((A, B, C, D), self.h, method='zoh', alpha=None)
        
        self.Ad = dsys[0]
        self.Bd = dsys[1]
        self.Cd = dsys[2]
        self.Dd = dsys[3]
Esempio n. 13
0
    def make_step(self, shape_in, shape_out, dt, rng, y0=None,
                  dtype=np.float64, method='zoh'):
        """Produces the function for filtering across one time-step."""
        assert shape_in == shape_out
        output = np.zeros(shape_out)
        if y0 is not None:
            output[...] = y0
        if y0 is None or not np.allclose(y0, 0):
            warnings.warn(
                "y0 (%s!=0) does not properly initialize the system; see "
                "Nengo issue #1124." % y0, UserWarning)

        if self.analog:
            # TODO: equivalent to cont2discrete in discrete.py, but repeated
            # here to avoid circular dependency.
            A, B, C, D, _ = cont2discrete(self.ss, dt, method=method)
            sys = LinearSystem((A, B, C, D), analog=False)
        else:
            sys = self

        if not sys.has_passthrough:
            # This makes our system behave like it does in Nengo
            sys *= z  # discrete shift of the system to remove delay
        else:
            warnings.warn(
                "Synapse (%s) has extra delay due to passthrough "
                "(https://github.com/nengo/nengo/issues/938)." % sys)

        return _CanonicalStep(sys, output, y0=y0, dtype=dtype)
Esempio n. 14
0
File: EKF.py Progetto: borlum/jmMPC
    def time_update(self, k, x_hat, u_k):
        res = self.nonlin.simulate(state=x_hat,
                                   start_time=k * self.Ts,
                                   final_time=(k + 1) * self.Ts,
                                   input=u_k,
                                   append=True)

        # Linearize
        Ak, Bk, Ck, Dk = self.nonlin.sim.get_state_space_representation()
        # Discretize
        (Ak, Bk, Ck, Dk, dt) = sig.cont2discrete(
            (Ak.toarray(), Bk.toarray(), Ck.toarray(), Dk.toarray()), self.Ts)

        self.Ak = Ak

        # Remove ignored states
        self.Ak = np.delete(self.Ak, (self.ignored_states.values()), axis=0)
        self.Ak = np.delete(self.Ak, (self.ignored_states.values()), axis=1)
        # Turn into numpy matrix, for matrix multiplication with *
        self.Ak = np.asmatrix(self.Ak)

        # Obtain state values
        x_hat = []
        for state in self.states:
            x_hat.append(res[state][-1])

        # Transpose, to obtain a state column vector
        self.x_hat = np.array([x_hat]).T

        # Calculate measurement column vector
        self.y_hat = self.Ck * self.x_hat

        # Obtain new error covariance
        self.P = self.Ak * self.P * self.Ak.T + self.Q
Esempio n. 15
0
 def tf(self):
     analog = EgoStengelOriginal()
     analog.passband = self.prewarped_passband
     b, a, _ = cont2discrete(analog.tf, self.dt, method="bilinear")
     # An idiosyncracy of cont2discrete:
     b = b.flatten()
     return b, a
def simulate(r_series):
    Num = len(r_series)
    #GA用パラメータ部
    K_p = 1.0
    K_d = 0.5
    A = np.array([[0, 1], [-K_p, -0.5 - K_d]])
    B = np.array([[0], [1.0]])
    C = np.array([[-K_p, -K_d]])
    D = np.array([K_p])

    Ts = 0.05
    c2d = sg.cont2discrete((A, B, C, D), dt=Ts)
    A_d, B_d, C_d, D_d = c2d[0], c2d[1].reshape(2), c2d[2], c2d[3]
    #GA用パラメータ部終了

    #保存用ログ確保
    x_series = np.zeros((Num, 2), dtype=np.float64)
    u_series = np.zeros((Num, 1), dtype=np.float64)

    for i in range(Num - 1):
        x = A_d @ x_series[i] + B_d * r_series[i]
        u = C_d @ x_series[i] + D_d * r_series[i]

        x_series[i + 1] = x
        u_series[i + 1] = u

    return x_series, u_series
Esempio n. 17
0
    def __init__(self, param):
        self._set_param(param)

        # Create continouous time linearized model
        Ac = np.zeros([12, 12])
        Ac[0:3, 3:6] = np.diag([1., 1., 1.])
        Ac[3:6, 3:6] = -np.diag(self.A) / self.m
        Ac[6:9, 9:12] = np.diag([1., 1., 1.])

        Bc = np.zeros([12, 4])
        Bc[5, :] = self.k
        Bc[9:12, 0:4] = np.array(
            [[0., -self.k * self.l / self.Ixx, 0., self.k * self.l / self.Ixx],
             [-self.k * self.l / self.Iyy, 0., self.k * self.l / self.Ixx, 0.],
             [
                 -self.b / self.Izz, self.b / self.Izz, -self.b / self.Izz,
                 self.b / self.Izz
             ]])

        Cc = np.zeros([7, 12])
        Cc[0:7, 2:9] = np.diag(np.ones([1, 7])[0])

        Dc = np.zeros([7, 4])

        # Discretize model
        discreteSystem = cont2discrete((Ac, Bc, Cc, Dc),
                                       self.Ts,
                                       method='zoh',
                                       alpha=None)

        # Set discrete matrices
        self.Ad = discreteSystem[0]
        self.Bd = discreteSystem[1]
        self.Cd = discreteSystem[2]
Esempio n. 18
0
    def __init__(self, param):
        self._set_param(param)

        # Create continouous time linearized model
        Ac = np.zeros([12,12])
        Ac[0:3,3:6] = np.diag([1.,1.,1.])
        Ac[3:6,3:6] = -np.diag(self.A)/self.m
        Ac[6:9,9:12] = np.diag([1.,1.,1.])
        
        Bc = np.zeros([12,4])
        Bc[5,:] =self.k
        Bc[9:12,0:4] = np.array([[0., -self.k*self.l/self.Ixx, 0., self.k*self.l/self.Ixx],
                                 [-self.k*self.l/self.Iyy, 0., self.k*self.l/self.Ixx, 0.],
                                 [-self.b/self.Izz, self.b/self.Izz, -self.b/self.Izz, self.b/self.Izz]])
                                 
        Cc = np.zeros([7,12])
        Cc[0:7,2:9] = np.diag(np.ones([1,7])[0])
        
        Dc = np.zeros([7,4])
        
        # Discretize model
        discreteSystem = cont2discrete((Ac,Bc,Cc,Dc), self.Ts, method='zoh', alpha=None)

        # Set discrete matrices
        self.Ad = discreteSystem[0]
        self.Bd = discreteSystem[1]
        self.Cd = discreteSystem[2]
Esempio n. 19
0
def control_systems(request):
    ct_sys, ref = request.param
    Ac, Bc, Cc = ct_sys.data
    Dc = np.zeros((Cc.shape[0], 1))

    Q = np.eye(Ac.shape[0])
    R = np.eye(Bc.shape[1] if len(Bc.shape) > 1 else 1)

    Sc = linalg.solve_continuous_are(Ac, Bc.reshape(-1, 1), Q, R,)
    Kc = linalg.solve(R, Bc.T @ Sc).reshape(1, -1)
    ct_ctr = LTISystem(Kc)

    evals = np.sort(np.abs(
        linalg.eig(Ac, left=False, right=False, check_finite=False)
    ))
    dT = 1/(2*evals[-1])

    Tsim = (8/np.min(evals[~np.isclose(evals, 0)])
            if np.sum(np.isclose(evals[np.nonzero(evals)], 0)) > 0
            else 8
            )

    dt_data = signal.cont2discrete((Ac, Bc.reshape(-1, 1), Cc, Dc), dT)
    Ad, Bd, Cd, Dd = dt_data[:-1]
    Sd = linalg.solve_discrete_are(Ad, Bd.reshape(-1, 1), Q, R,)
    Kd = linalg.solve(Bd.T @ Sd @ Bd + R, Bd.T @ Sd @ Ad)

    dt_sys = LTISystem(Ad, Bd, dt=dT)
    dt_sys.initial_condition = ct_sys.initial_condition
    dt_ctr = LTISystem(Kd, dt=dT)

    yield ct_sys, ct_ctr, dt_sys, dt_ctr, ref, Tsim
Esempio n. 20
0
    def discretise(self, dt, method="zoh", alpha=None):
        """Transform a continuous-time system into a discrete-time one.

        Parameters
        ----------
        dt : float
            the discretisation time step

        method : str, optional
            discretisation method, refer to the documentation for
            :func:`scipy.signal.cont2discrete`

        alpha : float within [0, 1], optional
            weighting parameter, refer to the documentation for
            :func:`scipy.signal.cont2discrete`

        Returns
        -------
        controlboros.StateSpaceBuilder
            intermediate builder object

        """
        self._a, self._b, self._c, self._d, _ = signal.cont2discrete(
            (self._a, self._b, self._c, self._d),
            dt,
            method=method,
            alpha=alpha,
        )
        self._discrete = True
        return self
Esempio n. 21
0
    def simulate(self, r_series):
        #実際の状態方程式におけるシミュレーション
        #印加される目標値に対して状態と入力を出力
        Num = len(r_series)

        #パラメータ部開始
        K_p = 1.0
        K_d = 0.5
        x_series = np.zeros((Num, 2), dtype=np.float64)
        u_series = np.zeros((Num, 1), dtype=np.float64)

        A = np.array([[0, 1], [-K_p, -0.5 - K_d]])
        B = np.array([[0], [1.0]])
        C = np.array([[-K_p, -K_d]])
        D = np.array([K_p])

        Ts = 0.05
        c2d = sg.cont2discrete((A, B, C, D), dt=Ts)
        A_d, B_d, C_d, D_d = c2d[0], c2d[1].reshape(2), c2d[2], c2d[3]
        #パラメータ部終了

        #更新式
        for i in range(Num - 1):
            x = A_d @ x_series[i] + B_d * r_series[i]
            u = C_d @ x_series[i] + D_d * r_series[i]

            x_series[i + 1] = x
            u_series[i + 1] = u

        return x_series, u_series
Esempio n. 22
0
    def linearize(self):
        """Return the discretized, scaled, linearized system.

        Returns
        -------
        Ad : ndarray
            The discrete-time state matrix.
        Bd : ndarray
            The discrete-time action matrix.

        """
        m = self.pendulum_mass
        M = self.cart_mass
        L = self.length
        b = self.rot_friction
        g = self.gravity

        A = np.array(
            [[0, 0, 1, 0], [0, 0, 0, 1], [0, g * m / M, 0, -b / (M * L)],
             [0, g * (m + M) / (L * M), 0, -b * (m + M) / (m * M * L**2)]],
            dtype=config.np_dtype)

        B = np.array([0, 0, 1 / M, 1 / (M * L)]).reshape((-1, self.action_dim))

        if self.normalization is not None:
            Tx, Tu = map(np.diag, self.normalization)
            Tx_inv, Tu_inv = map(np.diag, self.inv_norm)
            A = np.linalg.multi_dot((Tx_inv, A, Tx))
            B = np.linalg.multi_dot((Tx_inv, B, Tu))

        Ad, Bd, _, _, _ = signal.cont2discrete((A, B, 0, 0),
                                               self.dt,
                                               method='zoh')
        return Ad, Bd
Esempio n. 23
0
def test_ctle2(fz, fp1, npts, order, gbw, dtmax, err_lim):
    # normalize frequencies
    fz = fz*dtmax
    fp1 = fp1*dtmax
    gbw = gbw*dtmax

    # read in data
    my_data = np.genfromtxt(DATA_FILE, delimiter=',', skip_header=1)
    t_resp = my_data[:, 1] - my_data[0, 1]
    v_resp = my_data[:, 2]

    # find timestep of oversampled data
    tover = np.median(np.diff(t_resp))
    assert np.all(np.isclose(np.diff(t_resp), tover))
    print(f'tover: {tover*1e12:0.3f} ps')

    # build interpolator for data
    my_interp = interp1d(t_resp, v_resp)
    svec = np.linspace(0, 1, npts)

    # find state-space representation of the CTLE
    A, B, C, D = calc_ctle_abcd(fz=fz, fp1=fp1, gbw=gbw)

    # calculate response using spline method
    # the list of timesteps used is one that was found to be particularly bad for the emulator
    W = calc_interp_w(npts=npts, order=order)
    ctle = SplineLDS(A=A, B=B, C=C, D=D, W=W)
    x = np.zeros((A.shape[0],), dtype=float)
    t = 0
    dtlist = [0.960, 0.080, 0.960, 0.960, 0.080, 0.960, 0.960, 0.080, 0.960, 0.960,
              0.080, 0.960, 0.960, 0.080, 0.960, 0.960, 0.080, 0.960, 0.960, 0.080,
              0.960, 0.960, 0.080, 0.960, 0.960, 0.080, 0.960, 0.960, 0.080, 0.960,
              0.960, 0.080, 0.960, 0.960, 0.080, 0.960, 0.960, 0.080, 0.960, 0.960,
              0.080, 0.960, 0.960, 0.080, 0.960, 0.960, 0.080]
    tlist = []
    ylist = []
    for dt in dtlist:
        tlist.append(t)
        x, y = ctle.calc_update(xo=x, inpt=my_interp(t+svec*dtmax), dt=dt)
        ylist.append(y)
        t += dt*dtmax

    # calculate measured values
    y_meas = interp_emu_res(tlist, ylist, dtmax, t_resp, order, npts)

    # find expected response of the CTLE
    num, den = calc_ctle_num_den(fz=fz, fp1=fp1, gbw=gbw)
    b, a, _ = cont2discrete((num, den), dt=tover/dtmax)
    y_expt = lfilter(b[0], a, v_resp)

    # uncomment to plot results
    # import matplotlib.pyplot as plt
    # plt.plot(t_resp, y_expt)
    # plt.plot(t_resp, y_meas)
    # plt.show()

    # calculate error
    rms_err = np.sqrt(np.mean((y_expt-y_meas)**2))
    print('rms_err:', rms_err)
    assert rms_err < err_lim
Esempio n. 24
0
def generate_state_space(v, dt):
    A1, B1 = benchmark_state_space(*benchmark_matrices(), v=v, g=9.80665)
    A = np.zeros((5, 5))
    B = np.zeros((5, 2))
    A[1:, 1:] = A1
    B[1:, :] = B1
    p = benchmark_parameters()
    A[0, 2] = v * np.cos(p['lambda']) / p['w']
    A[0, 4] = p['c'] * np.cos(p['lambda']) / p['w']

    C = np.eye(5)
    D = np.zeros((5, 2))
    Ad, Bd, _, _, _ = sig.cont2discrete((A, B, C, D), dt, 'bilinear')

    print('A <<')
    print_matrix(A)

    print('B <<')
    print_matrix(B)

    print('Ad <<')
    print_matrix(Ad)

    print('Bd <<')
    print_matrix(Bd)
Esempio n. 25
0
    def generate_hybrid_model(self, xi_order):

        U = np.concatenate((self.X_minus.reshape(-1, self.X_minus.shape[-1]),
                            self.U_minus.reshape(-1, self.U_minus.shape[-1])),
                           axis=1).T

        Y_temp = self.Eta_minus.reshape(-1, self.Eta_minus.shape[-1]).T

        Y = self.plant.P.dot(Y_temp)

        if len(Y.shape) == 1:
            Y = Y.T
            Y = np.expand_dims(Y, axis=0)

        (A_disc_x, B_disc_x, _, _, _) = cont2discrete(
            (self.plant.A_cont_x, self.plant.B_cont_x, np.zeros(
                self.plant.n_x), np.zeros(self.plant.n_u)), self.dt_data)

        (_, A_disc_eta_hybrid, _, _, _) = cont2discrete(
            (self.plant.A_cont_x, self.plant.A_cont_eta_hybrid,
             np.zeros(self.plant.n_x), np.zeros(self.plant.n_eta)),
            self.dt_data)

        method = 'N4SID'
        sys_id = system_identification(
            Y, U, method, SS_D_required=True,
            SS_fixed_order=int(xi_order))  #, IC='AICc')#

        # SS_fixed_order = self.plant.N_eta,
        A_til, B_til, C_til, D_til = sys_id.A, sys_id.B, sys_id.C, sys_id.D

        B_til_1 = B_til[:, :self.plant.n_x]
        B_til_2 = B_til[:, self.plant.n_x:]
        D_til_1 = D_til[:, :self.plant.n_x]
        D_til_2 = D_til[:, self.plant.n_x:]

        A1 = A_disc_x + A_disc_eta_hybrid.dot(D_til_1)
        A2 = A_disc_eta_hybrid.dot(C_til)
        B1 = B_disc_x + A_disc_eta_hybrid.dot(D_til_2)

        self.A_disc_hybrid_full = np.block([[A1, A2], [B_til_1, A_til]])

        self.B_disc_hybrid_full = np.block([[B1], [B_til_2]])

        self.C_til = C_til
        self.D_til_1 = D_til_1
        self.D_til_2 = D_til_2
def c2d(A, B, C, D, dt):
    """Convert continuous state system to discrete time.

    Converts a set of continuous state space system matrices to their
    discrete counterpart.

    Parameters
    ----------
    A, B, C, D : float arrays
        State space system matrices
    dt : float
        Time step of discrete system

    Returns
    -------
    Ad, Bd, C, D : float arrays
        Discrete state space system matrices

    Examples
    --------
    >>> import numpy as np
    >>> np.set_printoptions(precision=4, suppress=True)
    >>> import vibrationtesting as vt
    >>> A1 = np.array([[ 0.,   0. ,  1.    ,  0.    ]])
    >>> A2 = np.array([[ 0.,   0. ,  0.    ,  1.    ]])
    >>> A3 = np.array([[-1.4,  1.2, -0.0058,  0.0014]])
    >>> A4 = np.array([[ 0.8, -1.4,  0.0016, -0.0038]])
    >>> A = np.array([[ 0.,   0. ,  1.    ,  0.    ],
    ...               [ 0.,   0. ,  0.    ,  1.    ],
    ...               [-1.4,  1.2, -0.0058,  0.0014],
    ...               [ 0.8, -1.4,  0.0016, -0.0038]])
    >>> B = np.array([[ 0.],
    ...               [ 0.],
    ...               [ 0.],
    ...               [ 1.]])
    >>> C = np.array([[-1.4, 1.2, -0.0058, 0.0014]])
    >>> D = np.array([[-0.2]])
    >>> Ad, Bd, *_ = vt.c2d(A, B, C, D, 0.01)
    >>> print(Ad)
    [[ 0.9999  0.0001  0.01    0.    ]
     [ 0.      0.9999  0.      0.01  ]
     [-0.014   0.012   0.9999  0.0001]
     [ 0.008  -0.014   0.0001  0.9999]]
    >>> print(Bd)
    [[ 0.  ]
     [ 0.  ]
     [ 0.  ]
     [ 0.01]]

    Notes
    -----
    .. note:: Zero-order hold solution
    .. seealso:: :func:`d2c`.

    """
    Ad, Bd, _, _, _ = sig.cont2discrete((A, B, C, D), dt)
    # Ad = la.expm(A * dt)
    # Bd = la.solve(A, (Ad - np.eye(A.shape[0]))) @ B
    return Ad, Bd, C, D
Esempio n. 27
0
def main():
    # Define state space
    m = VEHICLE_MASS
    b = LINEAR_DRAG_COEFFICIENT
    A = np.array([[0, 1], [0, -b / m]])
    B = np.array([[0], [1 / m]])
    C = np.array([[1, 0]])
    D = np.array([[0]])
    Q = np.array([[MEASUREMENT_NOISE_COVARIANCE]])
    R = np.array([[PROCESS_NOISE_COVARIANCE_POSITION, 0],
                  [0, PROCESS_NOISE_COVARIANCE_VELOCITY]])
    state_space = cont2discrete((A, B, C, D), dt=SAMPLE_PERIOD)
    A = state_space[0]
    B = state_space[1]
    C = state_space[2]
    D = state_space[3]
    Atranspose = A.transpose()
    Ctranspose = C.transpose()

    # Initial beliefs
    mean_belief = np.array([[0], [0]])
    variance_belief = np.array([[1, 0], [0, 1]])
    # Initial conditions
    xt_current = 0
    vt_current = 0

    # Initialize histories for plotting
    all_xt = [xt_current]
    all_vt = [vt_current]
    all_mean_belief = [mean_belief]
    all_variance_belief = [variance_belief]
    all_kt = []

    # Execute kalman filter for 50 seconds
    time_steps = int(50 / SAMPLE_PERIOD)
    for time_step in range(time_steps):
        # Calculate input
        ut = thrust((time_step + 1) * SAMPLE_PERIOD)
        # Update true state
        state = np.array([[xt_current], [vt_current]])
        state_plus_one = dot(A, state) + dot(B, ut) + process_noise(R)
        xt_current = state_plus_one[0][0]
        vt_current = state_plus_one[1][0]

        # Update sensor measurement of state
        zt = xt_current + measurement_noise(Q)
        # Calculate beliefs
        mean_belief, variance_belief, kt = kalman_filter(
            mean_belief, variance_belief, ut, zt, A, B, C, Atranspose,
            Ctranspose, R, Q)

        # Record outputs for plotting
        all_xt.append(xt_current)
        all_vt.append(vt_current)
        all_mean_belief.append(mean_belief)
        all_variance_belief.append(variance_belief)
        all_kt.append(kt)
    plot_everything(all_xt, all_vt, all_mean_belief, all_variance_belief,
                    all_kt)
Esempio n. 28
0
def run_simulation(t_resp, v_resp):
    # find timestep of oversampled data
    tover = np.median(np.diff(t_resp))
    assert np.all(np.isclose(np.diff(t_resp), tover))
    print(f'tover: {tover*1e12:0.3f} ps')

    # CLTE1
    nd1 = calc_ctle_num_den(fz=ctle1_fz * dtmax,
                            fp1=ctle1_fp * dtmax,
                            gbw=gbw * dtmax)
    b1, a1, _ = cont2discrete(nd1, dt=tover / dtmax)
    ctle1_out = lfilter(b1[0], a1, v_resp)

    # NL1
    nl_vsat = calc_tanh_vsat(nl_dB, 'dB', veval=nl_veval)
    nl_func = lambda v: tanhsat(v, nl_vsat)
    nl1_out = nl_func(ctle1_out)

    # CTLE2
    nd2 = calc_ctle_num_den(fz=ctle2_fz * dtmax,
                            fp1=ctle2_fp * dtmax,
                            gbw=gbw * dtmax)
    b2, a2, _ = cont2discrete(nd2, dt=tover / dtmax)
    ctle2_out = lfilter(b2[0], a2, nl1_out)

    # NL2
    nl2_out = nl_func(ctle2_out)

    # CTLE3
    nd3 = calc_ctle_num_den(fz=ctle3_fz * dtmax,
                            fp1=ctle3_fp * dtmax,
                            gbw=gbw * dtmax)
    b3, a3, _ = cont2discrete(nd3, dt=tover / dtmax)
    ctle3_out = lfilter(b3[0], a3, nl2_out)

    # NL3
    nl3_out = nl_func(ctle3_out)

    return {
        'ctle1_out': ctle1_out,
        'nl1_out': nl1_out,
        'ctle2_out': ctle2_out,
        'nl2_out': nl2_out,
        'ctle3_out': ctle3_out,
        'nl3_out': nl3_out
    }
Esempio n. 29
0
	def f(x,u,eta=None):
		# Continuous-Time state-space matrices
		A_x   = np.array([[0,1],[0,0]])
		A_eta = np.array([[0,0],[-1/m,-1/m]])
		B_x   = np.array([[0],[1/m]])

		# Convert state-space matrices to discrete-time
		_  , A_eta, _, _, _ = cont2discrete((A_x, A_eta, np.zeros(l_x), np.zeros(l_eta)), dt)
		A_x, B_x  , _, _, _ = cont2discrete((A_x, B_x  , np.zeros(l_x), np.zeros(l_u  )), dt)

		# Nonlinear elements
		if eta is None:
			eta = g(x)

		return np.matmul(A_x  ,   x) + \
			   np.matmul(A_eta, eta) + \
			   np.matmul(B_x  ,   u)
Esempio n. 30
0
    def discrete_dynamics(self):
        """
            Discrete state-space model
        """

        self.discrete = signal.cont2discrete(self.continuous,
                                             self.params['dt'],
                                             method='zoh')
Esempio n. 31
0
    def cont2shift(self, dt):

        if not self.is_continuous():
            msg = 'System must be continuous to call this function.'
            raise ValueError(msg)

        tup = signal.cont2discrete(self.cofs, dt, method='bilinear')
        return StateSpace(tup[0:4], dt=dt)
Esempio n. 32
0
    def loop(self):
        # predict
        self.getFB()
        (self.Fd, self.Bd, self.H, self.D, self.dT) = cont2discrete(
            (self.F, self.B, self.H, self.D), self.dT)
        self.x_pre = self.fx(self.x_est, self.u)
        self.P_pre = multi_dot([self.Fd, self.P_est, self.Fd.T]) + self.Q

        # calculate Kalman Gain, estimate
        if self.ir_velocity_tf is True:
            print 'IR on'
            self.K = multi_dot([
                self.P_pre, self.H[0:9, :].T,
                inv(
                    multi_dot([self.H[0:9, :], self.P_pre, self.H[0:9, :].T]) +
                    self.R[0:9, 0:9])
            ])
            self.hx = self.gethx(self.x_pre)
            self.x_est = self.x_pre + np.dot(self.K,
                                             self.z[0:9, :] - self.hx[0:9, :])
            #self.P_est = np.dot(np.eye(9)-np.dot(self.K, self.H[0:9, :]), self.P_pre)
            self.P_est = multi_dot([
                np.eye(9) - np.dot(self.K, self.H[0:9, :]), self.P_pre,
                (np.eye(9) - np.dot(self.K, self.H[0:9, :])).T
            ]) + multi_dot([self.K, self.R[0:9, 0:9], self.K.T])
        elif self.ir_pose_tf is True:
            print 'IR pose on'
            self.K = multi_dot([
                self.P_pre, self.H[3:9, :].T,
                inv(
                    multi_dot([self.H[3:9, :], self.P_pre, self.H[3:9, :].T]) +
                    self.R[3:9, 3:9])
            ])
            self.hx = self.gethx(self.x_pre)
            self.x_est = self.x_pre + np.dot(self.K,
                                             self.z[3:9, :] - self.hx[3:9, :])
            #self.P_est = np.dot(np.eye(9)-np.dot(self.K, self.H[3:9, :]), self.P_pre)
            self.P_est = multi_dot([
                np.eye(9) - np.dot(self.K, self.H[3:9, :]), self.P_pre,
                (np.eye(9) - np.dot(self.K, self.H[3:9, :])).T
            ]) + multi_dot([self.K, self.R[3:9, 3:9], self.K.T])
        else:
            print 'IMU'
            self.x_est = self.x_pre
            self.P_est = self.P_pre

        self.limitAngle()
        self.setState()
        self.pub_state.publish(self.state)
        self.pub_position.publish(self.position)
        self.pub_attitude.publish(self.attitude)
        self.pub_linear_velocity.publish(self.linear_velocity)
        self.pub_inertial_acceleration.publish(self.inertial_acceleration)

        self.ir_pose_tf = False
        self.ir_velocity_tf = False

        self.r.sleep()
Esempio n. 33
0
def c2d(A, B, C, D, dt):
    """returns Ad, Bd, C, D
    Converts a set of digital state space system matrices to their continuous counterpart.
    Simply calls scipy.signal.cont2discrete
    """

    Ad, Bd, _, _, _ = sig.cont2discrete((A, B, C, D), dt)
    Ad = la.expm(A * dt)
    Bd = la.solve(A, (Ad - sp.eye(A.shape[0]))) @ B
    return Ad, Bd, C, D
Esempio n. 34
0
def sample_system(sysc, Ts, method='matched'):
    # TODO: add docstring

    # Make sure we have a continuous time system
    if not isctime(sysc):
        raise ValueError("First argument must be continuous time system")

    # TODO: impelement MIMO version
    if (sysc.inputs != 1 or sysc.outputs != 1):
        raise NotImplementedError("MIMO implementation not available")

    # If we are passed a state space system, convert to transfer function first
    if isinstance(sysc, StateSpace):
        warn("sample_system: converting to transfer function")
        sysc = _convertToTransferFunction(sysc)

    # Decide what to do based on the methods available
    if method == 'matched':
        sysd = _c2dmatched(sysc, Ts)

    elif method == 'tustin':
        sys = [sysc.num[0][0], sysc.den[0][0]]
        scipySysD = cont2discrete(sys, Ts, method='bilinear')
        sysd = TransferFunction(scipySysD[0][0], scipySysD[1], dt)

    elif method == 'zoh':
        sys = [sysc.num[0][0], sysc.den[0][0]]
        scipySysD = cont2discrete(sys, Ts, method='zoh')
        sysd = TransferFunction(scipySysD[0][0],scipySysD[1], dt)

    elif method == 'foh' or method == 'impulse':
        raise ValueError("Method not developed yet")

    else:
        raise ValueError("Invalid discretization method: %s" % method)

    # TODO: Convert back into the input form
    # Set sampling time
    return sysd
Esempio n. 35
0
 def __init__(self, model, eta_c=0.9, eta_d=0.9, Tleak=96, ts=15):
     """
         Create an instance of a generic buffered production model. Here
         eta_c and eta_d are the charging and discharging efficiencies of
         the battery, respectively, Tleak is time constant (in hours) of
         the charge leakage, and ts is the sampling time (in minutes).
     """
     Act = np.array([[-1.0/(Tleak*3600), 0], [0, 0]])
     Bct = np.array([[eta_c, -1.0/eta_d], [0, 1]])
     Cct = np.array([[0, 0]])
     Dct = np.array([[0, 0]])
     (A, B, C, D, dt) = cont2discrete(
         (Act, Bct, Cct, Dct), ts*60, method='zoh')
     super(GenericBufferedProduction, self).__init__(model, A, B)
    def sample(self, Ts, method='zoh', alpha=None):
        """Convert a continuous-time system to discrete time

        Creates a discrete-time system from a continuous-time system by
        sampling.  Multiple methods of conversion are supported.

        Parameters
        ----------
        Ts : float
            Sampling period
        method :  {"gbt", "bilinear", "euler", "backward_diff", "zoh", "matched"}
            Which method to use:

               * gbt: generalized bilinear transformation
               * bilinear: Tustin's approximation ("gbt" with alpha=0.5)
               * euler: Euler (or forward differencing) method ("gbt" with alpha=0)
               * backward_diff: Backwards differencing ("gbt" with alpha=1.0)
               * zoh: zero-order hold (default)

        alpha : float within [0, 1]
            The generalized bilinear transformation weighting parameter, which
            should only be specified with method="gbt", and is ignored otherwise

        Returns
        -------
        sysd : StateSpace system
            Discrete time system, with sampling rate Ts

        Notes
        -----
        1. Available only for SISO systems

        2. Uses the command `cont2discrete` from `scipy.signal`

        Examples
        --------
        >>> sys = TransferFunction(1, [1,1])
        >>> sysd = sys.sample(0.5, method='bilinear')

        """
        if not self.isctime():
            raise ValueError("System must be continuous time system")
        if not self.issiso():
            raise NotImplementedError("MIMO implementation not available")
        if method == "matched":
            return _c2dmatched(self, Ts)
        sys = (self.num[0][0], self.den[0][0])
        numd, dend, dt = cont2discrete(sys, Ts, method, alpha)
        return TransferFunction(numd[0,:], dend, dt)
Esempio n. 37
0
 def __init__(self, model, eta_c=0.95, eta_d=0.95, Tleak=96, ts=15):
     """
         Create an instance of a QuadraticUtilityWithBattery model. Here
         eta_c and eta_d are the battery's charging and discharging
         efficiencies, respectively, Tleak is time constant (in hours) of
         the charge leakage, and ts is the sampling time (in minutes).
     """
     Act = np.array([[-1.0/(Tleak*3600)]])
     # Act = np.expand_dims(Act, axis=0)
     Bct = np.array([[eta_c, -1.0/eta_d, 0]])
     Cct = np.array([[0]])
     Dct = np.array([[0, 0, 0]])
     (A, B, C, D, dt) = cont2discrete(
         (Act, Bct, Cct, Dct), ts*60, method='zoh')
     B = np.array([[eta_c, -1.0/eta_d, 0]])
     super(QuadraticUtilityWithBattery, self).__init__(model, A, B)
Esempio n. 38
0
    def sample(self, Ts, method='zoh', alpha=None):
        """Convert a continuous time system to discrete time

        Creates a discrete-time system from a continuous-time system by
        sampling.  Multiple methods of conversion are supported.

        Parameters
        ----------
        Ts : float
            Sampling period
        method :  {"gbt", "bilinear", "euler", "backward_diff", "zoh"}
            Which method to use:

            * gbt: generalized bilinear transformation
            * bilinear: Tustin's approximation ("gbt" with alpha=0.5)
            * euler: Euler (or forward differencing) method ("gbt" with 
              alpha=0)
            * backward_diff: Backwards differencing ("gbt" with alpha=1.0)
            * zoh: zero-order hold (default)

        alpha : float within [0, 1]
            The generalized bilinear transformation weighting parameter, which
            should only be specified with method="gbt", and is ignored
            otherwise

        Returns
        -------
        sysd : StateSpace
            Discrete time system, with sampling rate Ts

        Notes
        -----
        Uses the command 'cont2discrete' from scipy.signal

        Examples
        --------
        >>> sys = StateSpace(0, 1, 1, 0)
        >>> sysd = sys.sample(0.5, method='bilinear')

        """
        if not self.isctime():
            raise ValueError("System must be continuous time system")

        sys = (self.A, self.B, self.C, self.D)
        Ad, Bd, C, D, dt = cont2discrete(sys, Ts, method, alpha)
        return StateSpace(Ad, Bd, C, D, dt)
Esempio n. 39
0
    def _first_order_markov(self, tau, sigma, dt):
        """
        Forms a first order Markov process model of the form:
        dx(t)/dt = (-1/tau) x(t) + w(t)
        
        where w(t) ~ N(0,Qw) is the driving white noise and
        Q = sigma * sigma is the steady state variance of x(t)
        
        Parameters
        ----------
          tau: time constant [sec]
        sigma: steady state (continuous time) standard deviation of x(t)
           dt: discrete system time step
        
        Returns
        -------
            Qw_d: the discrete-time equivalent covariance for the white-noise
                  driving process w(t)
        A_d, B_d: the discrete time system specification for simulating the
                  Markove process: 
                  x(k+1) = A_d * x(k) + B_d * w(k)
                  where w(k) ~ N(0,Qw_d) and A_d, B_d are scalars
        all returned values are scalars      
        """
        
        a = np.matrix(-1.0/tau)
        b, c, d = np.matrix(1.0), np.matrix(1.0), np.matrix(0.0)
        
        # Driving Noise White Power Spectral Density
        # This defines the relationship between the steady state variance
        # and the variance of the driving white noise.
        Qw = np.matrix(2.0 * sigma * sigma / tau)
        
        # Determine the discrete-time equivalent process noise
        # for the driving white process
        Qw_d = disrw(a, b, dt, Qw, order=5)
        
        # Convert continuous time to discrete time system for Markov process
        SS_dis = signal.cont2discrete((a, b, c, d), dt)

        A_d, B_d, C_d, D_d, Ts = SS_dis
        
        return Qw_d.item(), A_d.item(), B_d.item()
Esempio n. 40
0
    def make_step(self, shape_in, shape_out, dt, rng, y0=None,
                  dtype=np.float64, method='zoh'):
        assert shape_in == shape_out
        output = np.zeros(shape_out)

        if self.analog:
            # Note: equivalent to cont2discrete in discrete.py, but repeated
            # here to avoid circular dependency.
            A, B, C, D, _ = cont2discrete(self.ss, dt, method=method)
            sys = LinearSystem((A, B, C, D), analog=False)
        else:
            sys = self

        if not sys.has_passthrough:
            # This makes our system behave like it does in Nengo
            sys *= z  # discrete shift of the system to remove delay
        else:
            warnings.warn("Synapse (%s) has extra delay due to passthrough "
                          "(https://github.com/nengo/nengo/issues/938)" % sys)

        return _DigitalStep(sys, output, y0=y0, dtype=dtype)
Esempio n. 41
0
File: EKF.py Progetto: borlum/jmMPC
    def time_update(self, k, x_hat, u_k):
        res = self.nonlin.simulate(
            state=x_hat,
            start_time=k*self.Ts,
            final_time=(k+1)*self.Ts,
            input=u_k,
            append=True
        )

        # Linearize
        Ak, Bk, Ck, Dk = self.nonlin.sim.get_state_space_representation()
        # Discretize
        (Ak, Bk, Ck, Dk, dt) = sig.cont2discrete((
            Ak.toarray(), Bk.toarray(), Ck.toarray(), Dk.toarray()
        ), self.Ts)

        self.Ak = Ak

        # Remove ignored states
        self.Ak = np.delete(self.Ak, (self.ignored_states.values()), axis=0)
        self.Ak = np.delete(self.Ak, (self.ignored_states.values()), axis=1)
        # Turn into numpy matrix, for matrix multiplication with *
        self.Ak = np.asmatrix(self.Ak)

        # Obtain state values
        x_hat = []
        for state in self.states:
            x_hat.append(res[state][-1])

        # Transpose, to obtain a state column vector
        self.x_hat = np.array([x_hat]).T

        # Calculate measurement column vector
        self.y_hat = self.Ck * self.x_hat

        # Obtain new error covariance
        self.P = self.Ak * self.P * self.Ak.T + self.Q
    def handle_reference_data(self, msg):
        # TODO include discretised quadcopter dynamics and publish measurements
        omega = np.array(msg.data)
        x = self.x
        Ts = self.timestep
        g = self.g
        k = self.k
        A = self.A
        I = self.I
        l = self.l
        b = self.b
        m = self.m

        # Equations from Teppo Luukkonen, Modelling and control of quadcopter
        # Extracs the euler angle states and positional derivatives
        phi, theta, psi, phidot, thetadot, psidot = np.reshape(x[6:12,0:1],[1,6])[0]
        
        # eq. (7)
        T = k * sum(omega ** 2)

        # Define the C-matrix, see eq. (19)
        Ixx, Iyy, Izz = I
        
        Sphi = sin(phi)
        Stheta = sin(theta)
        Spsi = sin(psi);
        Cphi = cos(phi)
        Ctheta = cos(theta)
        Cpsi = cos(psi)
        
        C11 = 0.
        C12 = ((Iyy - Izz) * (thetadot * Cphi * Sphi +
               psidot * Sphi ** 2 *Ctheta) +
               (Izz - Iyy) * psidot * Cphi ** 2 *Ctheta -
               Ixx * psidot * Ctheta)
        C13 = (Izz - Iyy) * psidot * Cphi * Sphi * Ctheta ** 2
        C21 = ((Izz - Iyy) * (thetadot * Cphi * Sphi +
               psidot * Sphi * Ctheta) +
               (Iyy - Izz) * psidot * Cphi ** 2 * Ctheta -
               Ixx * psidot * Ctheta)
        C22 = (Izz - Iyy) * phidot * Cphi * Sphi
        C23 = (-Ixx * psidot * Stheta * Ctheta +
               Iyy * psidot * Sphi ** 2 * Stheta * Ctheta +
               Izz * psidot * Cphi ** 2 * Stheta * Ctheta)
        C31 = ((Iyy - Izz) * psidot * Ctheta ** 2 * Sphi * Cphi -
               Ixx * thetadot * Ctheta)
        C32 = ((Izz - Iyy) * (thetadot * Cphi * Sphi * Stheta +
               phidot * Sphi ** 2 * Ctheta) +
               (Iyy - Izz) * phidot * Cphi ** 2 * Ctheta +
               Ixx * psidot * Stheta * Ctheta -
               Iyy * psidot * Sphi ** 2 * Stheta * Ctheta -
               Izz * psi * Cphi ** 2 * Stheta * Ctheta)
        C33 = ((Iyy - Izz) * phidot * Cphi * Sphi * Ctheta ** 2 -
               Iyy * thetadot * Sphi ** 2 * Ctheta * Stheta -
               Izz * thetadot * Cphi ** 2 * Ctheta * Stheta +
               Ixx * thetadot * Ctheta * Stheta)
        
        C = np.array([[C11,C12,C13],
                      [C21,C22,C23],
                      [C31,C32,C33]]);   
        
        # eq. (8) Modified from the work of lukkonen, here rotor 2 and 4 spin in
        # the opposite directions
        tau_phi =  l * k * (-omega[1] ** 2 + omega[3] ** 2)
        tau_theta =  l * k * (-omega[0] ** 2 + omega[2] ** 2)
        tau_psi =  b * (omega[0] ** 2 - omega[1] ** 2 +
                        omega[2] ** 2 - omega[3] ** 2)
        
        tau_b = np.array([[tau_phi],[tau_theta],[tau_psi]])
        
        # eq. (16)
        J11 = Ixx
        J12 = 0.
        J13 = -Ixx*Stheta
        J21 = 0.
        J22 = Iyy * Cphi ** 2 + Izz * Sphi ** 2
        J23 = (Iyy - Izz) * Cphi * Sphi * Ctheta
        J31 = -Ixx * Stheta
        J32 = (Iyy - Izz) * Cphi * Sphi * Ctheta
        J33 = (Ixx * Stheta ** 2 + Iyy * Sphi ** 2 * Ctheta ** 2 +
               Izz * Cphi ** 2 * Ctheta ** 2)
        J = np.array([[J11,J12,J13],
                      [J21,J22,J23],
                      [J31,J32,J33]])
        
        invJ = spl.inv(J)

        # Sets up continuous system
        I3 = np.diag(np.ones([1,3])[0])
        
        Ac = np.zeros([12,12])
        Ac[0:3,3:6] = I3
        Ac[3:6,3:6] = -(1/m)*np.diag(A)
        Ac[6:9,9:12] = I3
        Ac[9:12,9:12] = -np.dot(invJ,C)
        
        Rz = (1/m) * np.array([[cos(psi) * sin(theta) * cos(phi) + sin(psi) * sin(phi)],
                               [sin(psi) * sin(theta) * cos(phi) - cos(psi) * sin(phi)],
                               [cos(theta) * cos(phi)]])
        
        Bc = np.zeros([12,4])
        Bc[3:6,0:1] = Rz
        Bc[9:12,1:4] = invJ
        
        Cc = np.zeros([6,12])
        Cc[0,0] = 1. # x
        Cc[1,1] = 1. # y
        Cc[2,2] = 1. # z
        Cc[3,6] = 1. # phi
        Cc[4,7] = 1. # theta
        Cc[5,8] = 1. # psi
        
        Dc = np.array([])
        
        discreteSystem = cont2discrete((Ac,Bc,Cc,Dc), Ts, method='zoh', alpha=None)
        
        Ad = discreteSystem[0]
        Bd = discreteSystem[1]
        Cd = discreteSystem[2]
        Dd = discreteSystem[3]
        G = np.zeros([12,1])
        G[5,0]=-g
        
        # Sets up control signal
        u = np.concatenate([[[T]],tau_b])
        
        xout = np.dot(Ad,x) + np.dot(Bd,u) + G*Ts
        yout = np.dot(Cd,x)
        
        self.x = xout
        self.measured_states_pub.publish(xout)
Esempio n. 43
0
def sample_system(sysc, Ts, method='matched'):
    """Convert a continuous time system to discrete time

    Creates a discrete time system from a continuous time system by
    sampling.  Multiple methods of conversion are supported.

    Parameters
    ----------
    sysc : linsys
        Continuous time system to be converted
    Ts : real
        Sampling period
    method : string
        Method to use for conversion: 'matched' (default), 'tustin', 'zoh'

    Returns
    -------
    sysd : linsys
        Discrete time system, with sampling rate Ts

    Notes
    -----
    1. The conversion methods 'tustin' and 'zoh' require the
       cont2discrete() function, including in SciPy 0.10.0 and above.

    2. Additional methods 'foh' and 'impulse' are planned for future
       implementation.

    Examples
    --------
    >>> sysc = TransferFunction([1], [1, 2, 1])
    >>> sysd = sample_system(sysc, 1, method='matched')
    """

    # Make sure we have a continuous time system
    if not isctime(sysc):
        raise ValueError("First argument must be continuous time system")

    # TODO: impelement MIMO version
    if (sysc.inputs != 1 or sysc.outputs != 1):
        raise NotImplementedError("MIMO implementation not available")

    # If we are passed a state space system, convert to transfer function first
    if isinstance(sysc, StateSpace):
        warn("sample_system: converting to transfer function")
        sysc = _convertToTransferFunction(sysc)

    # Decide what to do based on the methods available
    if method == 'matched':
        sysd = _c2dmatched(sysc, Ts)

    elif method == 'tustin':
        try:
            from scipy.signal import cont2discrete
            sys = [sysc.num[0][0], sysc.den[0][0]]
            scipySysD = cont2discrete(sys, Ts, method='bilinear')
            sysd = TransferFunction(scipySysD[0][0], scipySysD[1], Ts)
        except ImportError:
            raise TypeError("cont2discrete not found in scipy.signal; upgrade to v0.10.0+")

    elif method == 'zoh':
        try:
            from scipy.signal import cont2discrete
            sys = [sysc.num[0][0], sysc.den[0][0]]
            scipySysD = cont2discrete(sys, Ts, method='zoh')
            sysd = TransferFunction(scipySysD[0][0],scipySysD[1], Ts)
        except ImportError:
            raise TypeError("cont2discrete not found in scipy.signal; upgrade to v0.10.0+")

    elif method == 'foh' or method == 'impulse':
        raise ValueError("Method not developed yet")

    else:
        raise ValueError("Invalid discretization method: %s" % method)

    # TODO: Convert back into the input form
    # Set sampling time
    return sysd
Esempio n. 44
0
    def evaluate_system(self, x, u):
        phi, theta, psi, phidot, thetadot, psidot = np.reshape(x[6:12,0:1],[1,6])[0]

        Ts = self.Ts
        
        # Local parameters
        g = self.g
        m = self.m
        k = self.k
        A = self.A
        I = self.I
        l = self.l
        b = self.b
        
        u = u[:,0]
        T = k * sum(u ** 2)
    
        # Define the C-matrix, see eq. (19)
        Ixx, Iyy, Izz = I
        
        Sphi = sin(phi)
        Stheta = sin(theta)
        Spsi = sin(psi);
        Cphi = cos(phi)
        Ctheta = cos(theta)
        Cpsi = cos(psi)
        
        C11 = 0.
        C12 = ((Iyy - Izz) * (thetadot * Cphi * Sphi +
               psidot * Sphi ** 2 *Ctheta) +
               (Izz - Iyy) * psidot * Cphi ** 2 *Ctheta -
               Ixx * psidot * Ctheta)
        C13 = (Izz - Iyy) * psidot * Cphi * Sphi * Ctheta ** 2
        C21 = ((Izz - Iyy) * (thetadot * Cphi * Sphi +
               psidot * Sphi * Ctheta) +
               (Iyy - Izz) * psidot * Cphi ** 2 * Ctheta -
               Ixx * psidot * Ctheta)
        C22 = (Izz - Iyy) * phidot * Cphi * Sphi
        C23 = (-Ixx * psidot * Stheta * Ctheta +
               Iyy * psidot * Sphi ** 2 * Stheta * Ctheta +
               Izz * psidot * Cphi ** 2 * Stheta * Ctheta)
        C31 = ((Iyy - Izz) * psidot * Ctheta ** 2 * Sphi * Cphi -
               Ixx * thetadot * Ctheta)
        C32 = ((Izz - Iyy) * (thetadot * Cphi * Sphi * Stheta +
               phidot * Sphi ** 2 * Ctheta) +
               (Iyy - Izz) * phidot * Cphi ** 2 * Ctheta +
               Ixx * psidot * Stheta * Ctheta -
               Iyy * psidot * Sphi ** 2 * Stheta * Ctheta -
               Izz * psi * Cphi ** 2 * Stheta * Ctheta)
        C33 = ((Iyy - Izz) * phidot * Cphi * Sphi * Ctheta ** 2 -
               Iyy * thetadot * Sphi ** 2 * Ctheta * Stheta -
               Izz * thetadot * Cphi ** 2 * Ctheta * Stheta +
               Ixx * thetadot * Ctheta * Stheta)
        
        C = np.array([[C11,C12,C13],
                      [C21,C22,C23],
                      [C31,C32,C33]]);   
        
        # eq. (8) Modified from the work of lukkonen, here rotor 2 and 4 spin in
        # the opposite directions
        tau_phi =  l * k * (-u[1] ** 2 + u[3] ** 2)
        tau_theta =  l * k * (-u[0] ** 2 + u[2] ** 2)
        tau_psi =  b * (u[0] ** 2 - u[1] ** 2 +
                        u[2] ** 2 - u[3] ** 2)
        
        tau_b = np.array([[tau_phi],[tau_theta],[tau_psi]])
        
        # eq. (16)
        J11 = Ixx
        J12 = 0.
        J13 = -Ixx*Stheta
        J21 = 0.
        J22 = Iyy * Cphi ** 2 + Izz * Sphi ** 2
        J23 = (Iyy - Izz) * Cphi * Sphi * Ctheta
        J31 = -Ixx * Stheta
        J32 = (Iyy - Izz) * Cphi * Sphi * Ctheta
        J33 = (Ixx * Stheta ** 2 + Iyy * Sphi ** 2 * Ctheta ** 2 +
               Izz * Cphi ** 2 * Ctheta ** 2)
        J = np.array([[J11,J12,J13],
                      [J21,J22,J23],
                      [J31,J32,J33]])
        
        invJ = sp.linalg.inv(J)
    
        # Sets up continuous system
        I3 = np.diag(np.ones([1,3])[0])
        
        Ac = np.zeros([12,12])
        Ac[0:3,3:6] = I3
        Ac[3:6,3:6] = -(1/m)*np.diag(A)
        Ac[6:9,9:12] = I3
        Ac[9:12,9:12] = -np.dot(invJ,C)
        
        Rz = (1/m) * np.array([[cos(psi) * sin(theta) * cos(phi) + sin(psi) * sin(phi)],
                               [sin(psi) * sin(theta) * cos(phi) - cos(psi) * sin(phi)],
                               [cos(theta) * cos(phi)]])
        
        Bc = np.zeros([12,4])
        Bc[3:6,0:1] = Rz
        Bc[9:12,1:4] = invJ
        
        Cc = np.zeros([7,12])
        Cc[0:7,2:9] = np.diag(np.ones([1,7])[0]) # z,rdot,eta
        
        Dc = np.array([])
        
        discreteSystem = cont2discrete((Ac,Bc,Cc,Dc), Ts, method='zoh', alpha=None)
        
        Ad = discreteSystem[0]
        Bd = discreteSystem[1]
        Cd = discreteSystem[2]

        G = np.zeros([12,1])
        G[5,0]=-g
        
        # Sets up control signal
        u = np.concatenate([[[T]],tau_b])
        
        xout = np.dot(Ad,x) + np.dot(Bd,u) + G*Ts
        yout = np.dot(Cd,x)

        return xout, yout
 def RunFilter(self,x_vec,t_vec):
     den = signal.convolve(np.array([self.Ts1,1]),np.array([self.Ts2,1]));
     num = self.dc_gain;
     filter_obj = signal.cont2discrete((num,den),self.Ts,method='zoh');
     tout, x_filt= signal.dlsim(filter_obj,x_vec,t=t_vec);
     return x_filt;
Esempio n. 46
0
def test_detector():
  fitSamples = 100

#  Prepare detector
  zero_1 = -5.56351644e+07
  pole_1 = -1.38796386e+04
  pole_real = -2.02559385e+07
  pole_imag = 9885315.37450211
  
  gain = 2./1e-8
  
  zeros = [zero_1,0. ]
  poles = [ pole_real+pole_imag*1j, pole_real-pole_imag*1j, pole_1]
  system = signal.lti(zeros, poles, gain )
  
  system.to_tf()
  num = system.num
  den = system.den
  
  print "original num: " + str(num)
  print "original den" + str(den)
  
  system.to_zpk()
  print "back to the zpk"
  print system.zeros
  print system.poles
  print system.gain

#  num = np.array((3478247474.8078203, 1.9351287044375424e+17, 6066014749714584.0)) 
#  den = [1, 40525756.715025946, 508584795912802.44, 7.0511687850000589e+18]
#  system = signal.lti(num, den)
#
#  zeros = system.zeros
#  poles = system.poles
#  gain = system.gain

  new_num, new_den, dt = signal.cont2discrete((num, den), 1E-8, method="bilinear")
#  new_num /= 1.05836038e-08
  print "new discrete tf representation"
  print new_num
  print new_den
  print dt

  new_z, new_p, new_k, dt = signal.cont2discrete((zeros, poles, gain), 1E-8, method="bilinear" )
  print "new discrete zpk representation"
  print new_z
  print new_p
  print new_k
  print dt
  
  print "...and back to tf"
  dis_num, dis_den = signal.zpk2tf(new_z, new_p, new_k)
  print dis_num
  print dis_den

  tempGuess = 77.89
  gradGuess = 0.0483
  pcRadGuess = 2.591182
  pcLenGuess = 1.613357

  #Create a detector model
  detName = "conf/P42574A_grad%0.2f_pcrad%0.2f_pclen%0.2f.conf" % (0.05,2.5, 1.65)
  det =  Detector(detName, temperature=tempGuess, timeStep=10., numSteps=fitSamples, )
  det.LoadFields("P42574A_fields_v3.npz")
  det.SetFields(pcRadGuess, pcLenGuess, gradGuess)

  print "time steps out number is %d" % det.siggenInst.GetSafeConfiguration()['ntsteps_out']
  print "time steps calc number is %d" % det.siggenInst.GetSafeConfiguration()['time_steps_calc']
  print "step size out is %f" % det.siggenInst.GetSafeConfiguration()['step_time_out']
  print "step size calc is %f" % det.siggenInst.GetSafeConfiguration()['step_time_calc']


  sig_array = det.GetRawSiggenWaveform( 0.174070, 0.528466, 10.755795)
  
  t, sig_array2, x = signal.lsim(system, sig_array, det.time_steps, interp=False)
  
  
  sig_array1 = signal.lfilter(new_num[0], new_den, sig_array)
  sig_array4 = signal.lfilter(dis_num, dis_den, sig_array)
  
#  dissystem = system.to_discrete(1E-8)
#  
##  new_k = dissystem.zeros
##  new_p = dissystem.poles
##  new_k = dissystem.gain
##  dis_num, dis_den = signal.zpk2tf(new_z, new_p, new_k)
##  sig_array5 = signal.lfilter(dis_num, dis_den, sig_array)


#
#
  plt.figure()
  plt.plot(sig_array1, "b:")
  plt.plot(sig_array2, color="black")
  plt.plot(sig_array4, "r:")
#  plt.plot(sig_array5, "g:")

  plt.figure()
  plt.plot(sig_array2-sig_array1, color="b")
  plt.plot(sig_array2-sig_array4, color="r")
#  plt.plot(sig_array2-sig_array5, color="g")

  #plt.ylim(-0.05, 1.05)
  plt.xlabel("Time [ns]")
  plt.ylabel("Charge [arb.]")
  plt.show()
Esempio n. 47
0
def test_lti():
    import scipy.signal as sps

    dt = 1e-3
    tend = 10.
    t = dt * np.arange(tend / dt)
    nt = len(t)

    tau = 1e-2
    tf = sps.cont2discrete(([1], [tau, 1]), dt, method='euler')[:2]
    # tf = sps.cont2discrete(([1], [tau**2, 2*tau, 1]), dt, method='zoh')[:2]
    # tf = sps.butter(6, dt / (np.pi * tau))
    # tf = sps.cheby1(5, 40, dt / (np.pi * tau))
    print tf

    # tf2 = sps.cont2discrete(([1], [tau, 1]), dt, method='zoh')[:2]
    tf2 = sps.cont2discrete(([1], [tau, 1]), dt, method='gbt', alpha=0.5)[:2]

    ### plot filtered signal and spectrum
    x = np.random.normal(size=(nt,1000))
    y = neurotools.filters.lti(x, tf)
    y2 = neurotools.filters.lti(x, tf2)

    plt.figure(1)
    plt.clf()

    plt.subplot(211)
    plt.plot(t, y[:,0])
    plt.plot(t, y2[:,0])

    f, mag, ang = get_spectrum(t, x, y)
    f2, mag2, ang2 = get_spectrum(t, x, y2)
    plt.subplot(223)
    plt.loglog(f, mag)
    plt.loglog(f2, mag2)

    plt.subplot(224)
    delay = ang / (2 * np.pi * f)
    delay2 = ang2 / (2 * np.pi * f2)
    plt.semilogx(f[1:], delay[1:])
    plt.semilogx(f2[1:], delay2[1:])

    ### plot impulse response
    tend = 10 * tau
    t = dt * np.arange(tend / dt)
    nt = len(t)

    x = np.zeros(nt)
    x[0] = 1. / dt
    y = neurotools.filters.lti(x, tf)

    plt.figure(2)
    plt.clf()
    plt.plot(t, y)
    print("Impulse response sum:", y.sum() * dt)

    ### plot sine input
    x = np.sin(3 * (2 * np.pi) * t)
    y = neurotools.filters.lti(x, tf)
    plt.figure(3)
    plt.clf()
    plt.plot(t, x)
    plt.plot(t, y)

    plt.show()
Esempio n. 48
0
 def discretize(self, samplerate):
     systf = (self.num, self.den)
     (dnum, dden, _) = signal.cont2discrete(systf, 1 / samplerate)
     return (np.squeeze(dnum), np.squeeze(dden))
Esempio n. 49
0
def quadcopter_dynamics(x, u, param):
    # The model of the quadcopter which is used in non-linear state estimation
    # on the host and for simulation purposes. The state is updated internally
    # and updated on every time step with reference to the input control signal
    # omega. The parameters defining the process and states are loaded from 
    # a parameter dictionary on the same for as that used in the configuration
    # file (see /config/*).
    #
    # ARGS:
    #     u - np.array of shape (4,1) - control signals (omega)
    # RETURN:
    #     xout - np.array of shape (12,1) - state vector with on the form
    #         [r,dr,eta,deta]^T.
    #     yout - np.array of shape (12,1) - Measuereent vector returning 
    #         certain states as specified in C.

    # Extract angles and parameters
    phi, theta, psi, phidot, thetadot, psidot = np.reshape(x[6:12,0:1],[1,6])[0]
    Ts = param['global']['inner_loop_h']
    g = param['quadcopter_model']['g']
    m = param['quadcopter_model']['m']
    k = param['quadcopter_model']['k']
    A = param['quadcopter_model']['A']
    I = param['quadcopter_model']['I']
    l = param['quadcopter_model']['l']
    b = param['quadcopter_model']['b']
    
    u = u[:,0]
    T = k * sum(u ** 2)

    # Define the C-matrix, see eq. (19)
    Ixx, Iyy, Izz = I
    
    Sphi = sin(phi)
    Stheta = sin(theta)
    Spsi = sin(psi);
    Cphi = cos(phi)
    Ctheta = cos(theta)
    Cpsi = cos(psi)
    
    C11 = 0.
    C12 = ((Iyy - Izz) * (thetadot * Cphi * Sphi +
           psidot * Sphi ** 2 *Ctheta) +
           (Izz - Iyy) * psidot * Cphi ** 2 *Ctheta -
           Ixx * psidot * Ctheta)
    C13 = (Izz - Iyy) * psidot * Cphi * Sphi * Ctheta ** 2
    C21 = ((Izz - Iyy) * (thetadot * Cphi * Sphi +
           psidot * Sphi * Ctheta) +
           (Iyy - Izz) * psidot * Cphi ** 2 * Ctheta -
           Ixx * psidot * Ctheta)
    C22 = (Izz - Iyy) * phidot * Cphi * Sphi
    C23 = (-Ixx * psidot * Stheta * Ctheta +
           Iyy * psidot * Sphi ** 2 * Stheta * Ctheta +
           Izz * psidot * Cphi ** 2 * Stheta * Ctheta)
    C31 = ((Iyy - Izz) * psidot * Ctheta ** 2 * Sphi * Cphi -
           Ixx * thetadot * Ctheta)
    C32 = ((Izz - Iyy) * (thetadot * Cphi * Sphi * Stheta +
           phidot * Sphi ** 2 * Ctheta) +
           (Iyy - Izz) * phidot * Cphi ** 2 * Ctheta +
           Ixx * psidot * Stheta * Ctheta -
           Iyy * psidot * Sphi ** 2 * Stheta * Ctheta -
           Izz * psi * Cphi ** 2 * Stheta * Ctheta)
    C33 = ((Iyy - Izz) * phidot * Cphi * Sphi * Ctheta ** 2 -
           Iyy * thetadot * Sphi ** 2 * Ctheta * Stheta -
           Izz * thetadot * Cphi ** 2 * Ctheta * Stheta +
           Ixx * thetadot * Ctheta * Stheta)
    
    C = np.array([[C11,C12,C13],
                  [C21,C22,C23],
                  [C31,C32,C33]]);   
    
    # eq. (8) Modified from the work of lukkonen, here rotor 2 and 4 spin in
    # the opposite directions
    tau_phi =  l * k * (-u[1] ** 2 + u[3] ** 2)
    tau_theta =  l * k * (-u[0] ** 2 + u[2] ** 2)
    tau_psi =  b * (u[0] ** 2 - u[1] ** 2 +
                    u[2] ** 2 - u[3] ** 2)
    
    tau_b = np.array([[tau_phi],[tau_theta],[tau_psi]])
    
    # eq. (16)
    J11 = Ixx
    J12 = 0.
    J13 = -Ixx*Stheta
    J21 = 0.
    J22 = Iyy * Cphi ** 2 + Izz * Sphi ** 2
    J23 = (Iyy - Izz) * Cphi * Sphi * Ctheta
    J31 = -Ixx * Stheta
    J32 = (Iyy - Izz) * Cphi * Sphi * Ctheta
    J33 = (Ixx * Stheta ** 2 + Iyy * Sphi ** 2 * Ctheta ** 2 +
           Izz * Cphi ** 2 * Ctheta ** 2)
    J = np.array([[J11,J12,J13],
                  [J21,J22,J23],
                  [J31,J32,J33]])
    
    invJ = inv(J)

    # Sets up continuous system
    I3 = np.diag(np.ones([1,3])[0])
    
    Ac = np.zeros([12,12])
    Ac[0:3,3:6] = I3
    Ac[3:6,3:6] = -(1/m)*np.diag(A)
    Ac[6:9,9:12] = I3
    Ac[9:12,9:12] = -np.dot(invJ,C)
    
    Rz = (1/m) * np.array([[cos(psi) * sin(theta) * cos(phi) + sin(psi) * sin(phi)],
                           [sin(psi) * sin(theta) * cos(phi) - cos(psi) * sin(phi)],
                           [cos(theta) * cos(phi)]])
    
    Bc = np.zeros([12,4])
    Bc[3:6,0:1] = Rz
    Bc[9:12,1:4] = invJ
    
    Cc = np.zeros([7,12])
    Cc[0:7,2:9] = np.diag(np.ones([1,7])[0]) # z,rdot,eta
    
    Dc = np.array([])
    
    discreteSystem = cont2discrete((Ac,Bc,Cc,Dc), Ts, method='zoh', alpha=None)
    
    Ad = discreteSystem[0]
    Bd = discreteSystem[1]
    Cd = discreteSystem[2]

    G = np.zeros([12,1])
    G[5,0]=-g
    
    # Sets up control signal
    u = np.concatenate([[[T]],tau_b])
    
    xout = np.dot(Ad,x) + np.dot(Bd,u) + G*Ts
    yout = np.dot(Cd,x)

    return xout, yout
Esempio n. 50
0
def mapCtoD(sys_c, t=(0, 1), f0=0.0):
    """Map a MIMO continuous-time to an equiv. SIMO discrete-time system.

    The criterion for equivalence is that the sampled pulse response
    of the CT system must be identical to the impulse response of the DT system.
    i.e. If ``yc`` is the output of the CT system with an input ``vc`` taken
    from a set of DACs fed with a single DT input ``v``, then ``y``, the output
    of the equivalent DT system with input ``v`` satisfies:
    ``y(n) = yc(n-)`` for integer ``n``. The DACs are characterized by
    rectangular impulse responses with edge times specified in the t list.

    **Input:**

    sys_c : object
           the LTI description of the CT system, which can be:

     * the ABCD matrix,
     * a list-like containing the A, B, C, D matrices,
     * a list of zpk tuples (internally converted to SS representation),
     * a list of LTI objects.

    t : array_like
        The edge times of the DAC pulse used to make CT waveforms
        from DT inputs. Each row corresponds to one of the system
        inputs; [-1 -1] denotes a CT input. The default is [0 1],
        for all inputs except the first.

    f0 : float
         The (normalized) frequency at which the Gp filters' gains are
         to be set to unity. Default 0 (DC).

    **Output:**

    sys : tuple
         the LTI description for the DT equivalent, in A, B, C, D
         representation.

    Gp : list of lists
         the mixed CT/DT prefilters which form the samples
         fed to each state for the CT inputs.

    **Example:**

    Map the standard second order CT modulator shown below to its CT
    equivalent and verify that its NTF is :math:`(1-z^{-1})^2`.

    .. image:: ../doc/_static/mapCtoD.png
        :align: center
        :alt: mapCtoD block diagram

    It can be done as follows::

        from __future__ import print_function
        import numpy as np
        from scipy.signal import lti
        from deltasigma import *
        LFc = lti([[0, 0], [1, 0]], [[1, -1], [0, -1.5]], [[0, 1]], [[0, 0]])
        tdac = [0, 1]
        LF, Gp = mapCtoD(LFc, tdac)
        LF = lti(*LF)
        ABCD = np.vstack((
                np.hstack((LF.A, LF.B)),
                np.hstack((LF.C, LF.D))
               ))
        NTF, STF = calculateTF(ABCD)
        print("NTF:") # after rounding to a 1e-6 resolution
        print("Zeros:", np.real_if_close(np.round(NTF.zeros, 6)))
        print("Poles:", np.real_if_close(np.round(NTF.poles, 6)))

    Prints::

        Zeros: [ 1.  1.]
        Poles: [ 0.  0.]

    Equivalent to::

               (z -1)^2
        NTF = ----------
                 z^2

    .. seealso:: R. Schreier and B. Zhang, "Delta-sigma modulators employing \
    continuous-time circuitry," IEEE Transactions on Circuits and Systems I, \
    vol. 43, no. 4, pp. 324-332, April 1996.
    """
    # You need to have A, B, C, D specification of the system
    Ac, Bc, Cc, Dc = _getABCD(sys_c)
    ni = Bc.shape[1]
    # Sanitize t
    if hasattr(t, "tolist"):
        t = t.tolist()
    if (type(t) == tuple or type(t) == list) and np.isscalar(t[0]):
        t = [t]  # we got a simple list, like the default value
    if not (type(t) == tuple or type(t) == list) and not (type(t[0]) == tuple or type(t[0]) == list):
        raise ValueError("The t argument has an unrecognized shape")
    # back to business
    t = np.array(t)
    if t.shape == (1, 2) and ni > 1:
        t = np.vstack((np.array([[-1, -1]]), np.dot(np.ones((ni - 1, 1)), t)))
    if t.shape != (ni, 2):
        raise ValueError("The t argument has the wrong dimensions.")
    di = np.ones(ni).astype(bool)
    for i in range(ni):
        if t[i, 0] == -1 and t[i, 1] == -1:
            di[i] = False

    # c2d assumes t1=0, t2=1.
    # Also c2d often complains about poor scaling and can even produce
    # incorrect results.
    A, B, C, D, _ = cont2discrete((Ac, Bc, Cc, Dc), 1, method="zoh")
    Bc1 = Bc[:, ~di]

    # Examine the discrete-time inputs to see how big the
    # augmented matrices need to be.
    B1 = B[:, ~di]
    D1 = D[:, ~di]
    n = A.shape[0]
    t2 = np.ceil(t[di, 1]).astype(np.int_)
    esn = (t2 == t[di, 1]) and (D[0, di] != 0).T  # extra states needed?
    npp = n + np.max(t2 - 1 + 1 * esn)

    # Augment A to npp x npp, B to np x 1, C to 1 x np.
    Ap = padb(padr(A, npp), npp)
    for i in range(n + 1, npp):
        Ap[i, i - 1] = 1
    Bp = np.zeros((npp, 1))
    if npp > n:
        Bp[n, 0] = 1
    Cp = padr(C, npp)
    Dp = np.zeros((1, 1))

    # Add in the contributions from each DAC
    for i in np.flatnonzero(di):
        t1 = t[i, 0]
        t2 = t[i, 1]
        B2 = B[:, i]
        D2 = D[:, i]
        if t1 == 0 and t2 == 1 and D2 == 0:  # No fancy stuff necessary
            Bp = Bp + padb(B2, npp)
        else:
            n1 = np.floor(t1)
            n2 = np.ceil(t2) - n1 - 1
            t1 = t1 - n1
            t2 = t2 - n2 - n1
            if t2 == 1 and D2 != 0:
                n2 = n2 + 1
                extraStateNeeded = 1
            else:
                extraStateNeeded = 0
            nt = n + n1 + n2
            if n2 > 0:
                if t2 == 1:
                    Ap[:n, nt - n2 : nt] = Ap[:n, nt - n2 : nt] + np.tile(B2, (1, n2))
                else:
                    Ap[:n, nt - n2 : nt - 1] = Ap[:n, nt - n2 : nt - 1] + np.tile(B2, (1, n2 - 1))
                    Ap[:n, (nt - 1)] = Ap[:n, (nt - 1)] + _B2formula(Ac, 0, t2, B2)
            if n2 > 0:  # pulse extends to the next period
                Btmp = _B2formula(Ac, t1, 1, B2)
            else:  # pulse ends in this period
                Btmp = _B2formula(Ac, t1, t2, B2)
            if n1 > 0:
                Ap[:n, n + n1 - 1] = Ap[:n, n + n1 - 1] + Btmp
            else:
                Bp = Bp + padb(Btmp, npp)
            if n2 > 0:
                Cp = Cp + padr(np.hstack((np.zeros((D2.shape[0], n + n1)), D2 * np.ones((1, n2)))), npp)
    sys = (Ap, Bp, Cp, Dp)
    if np.any(~di):
        # Compute the prefilters and add in the CT feed-ins.
        # Gp = inv(sI - Ac)*(zI - A)/z*Bc1
        n, m = Bc1.shape
        Gp = np.empty_like(np.zeros((n, m)), dtype=object)
        # !!Make this like stf: an array of zpk objects
        ztf = np.empty_like(Bc1, dtype=object)
        # Compute the z-domain portions of the filters
        ABc1 = np.dot(A, Bc1)
        for h in range(m):
            for i in range(n):
                if Bc1[i, h] == 0:
                    ztf[i, h] = (np.array([]), np.array([0.0]), -ABc1[i, h])  # dt=1
                else:
                    ztf[i, h] = (np.atleast_1d(ABc1[i, h] / Bc1[i, h]), np.array([0.0]), Bc1[i, h])  # dt = 1
        # Compute the s-domain portions of each of the filters
        stf = np.empty_like(np.zeros((n, n)), dtype=object)  # stf[out, in] = zpk
        for oi in range(n):
            for ii in range(n):
                # Doesn't do pole-zero cancellation
                stf[oi, ii] = ss2zpk(Ac, np.eye(n), np.eye(n)[oi, :], np.zeros((1, n)), input=ii)
                # scipy as of v 0.13 has no support for LTI MIMO systems
                # only 'MISO', therefore you can't write:
                # stf = ss2zpk(Ac, eye(n), eye(n), np.zeros(n, n)))
        for h in range(m):
            for i in range(n):
                # k = 1 unneded, see below
                for j in range(n):
                    # check the k values for a non-zero term
                    if stf[i, j][2] != 0 and ztf[j, h][2] != 0:
                        if Gp[i, h] is None:
                            Gp[i, h] = {}
                            Gp[i, h].update({"Hs": [list(stf[i, j])]})
                            Gp[i, h].update({"Hz": [list(ztf[j, h])]})
                        else:
                            Gp[i, h].update({"Hs": Gp[i, h]["Hs"] + [list(stf[i, j])]})
                            Gp[i, h].update({"Hz": Gp[i, h]["Hz"] + [list(ztf[j, h])]})
                        # the MATLAB-like cell code for the above statements would have
                        # been:
                        # Gp[i, h](k).Hs = stf[i, j]
                        # Gp[i, h](k).Hz = ztf[j, h]
                        # k = k + 1
        if f0 != 0:  # Need to correct the gain terms calculated by c2d
            # B1 = gains of Gp @f0;
            for h in range(m):
                for i in range(n):
                    B1ih = np.real_if_close(evalMixedTF(Gp[i, h], f0))
                    # abs() used because ss() whines if B has complex entries...
                    # This is clearly incorrect.
                    # I've fudged the complex stuff by including a sign....
                    B1[i, h] = np.abs(B1ih) * np.sign(np.real(B1ih))
                    if np.abs(B1[i, h]) < 1e-09:
                        B1[i, h] = 1e-09  # This prevents NaN in "line 174" below
        # Adjust the gains of the pre-filters
        for h in range(m):
            for i in range(n):
                for j in range(max(len(Gp[i, h]["Hs"]), len(Gp[i, h]["Hz"]))):
                    # The next is "line 174"
                    Gp[i, h]["Hs"][j][2] = Gp[i, h]["Hs"][j][2] / B1[i, h]
        sys = (
            sys[0],  # Ap
            np.hstack((padb(B1, npp), sys[1])),  # new B
            sys[2],  # Cp
            np.hstack((D1, sys[3])),
        )  # new D
    return sys, Gp
Esempio n. 51
0
def cont2discrete(sys, dt, method='bilinear'):
    discrete_sys = signal.cont2discrete(sys, dt, method=method)[:-1]
    if len(discrete_sys) == 2:
        discrete_sys = tuple(np.squeeze(b_or_a) for b_or_a in discrete_sys)
    return discrete_sys
def compute_gains(Q, R, W, V, dt):
    """Given LQR Q and R matrices, and Kalman W and V matrices, and sample
    time, compute optimal feedback gain and optimal filter gains."""

    data = np.empty((N,), dtype=controller_t)

    # Loop over all speeds for which we have system dynamics
    for i in range(N):
        data['theta_R_dot'][i] = theta_R_dot[i]
        data['dt'][i] = dt
        # Convert the bike dynamics to discrete time using a zero order hold
        data['A'][i], data['B'][i], _, _, _ = cont2discrete(
                        (A_w[i], B_w[i, :], eye(4), zeros((4, 1))), dt)
        data['plant_evals_d'][i] = la.eigvals(data['A'][i])
        data['plant_evals_c'][i] = np.log(data['plant_evals_d'][i]) / dt
        
        # Bicycle measurement matrices
        # - steer angle
        # - roll rate
        data['C_m'][i] = C_w[i, :2, :]
        # - yaw rate
        data['C_z'][i] = C_w[i, 2, :]

        A = data['A'][i]
        B = data['B'][i, :, 2].reshape((4, 1))
        C_m = data['C_m'][i]
        C_z = data['C_z'][i]

        # Controllability from steer torque
        data['ctrb_plant'][i] = ctrb(A, B)
        u, s, v = la.svd(data['ctrb_plant'][i])
        assert(np.all(s > 1e-13))

        # Solve discrete algebraic Ricatti equation associated with LQI problem
        P_c = dare(A, B, R, Q)
        
        # Optimal feedback gain using solution of Ricatti equation
        K_c = -la.solve(R + dot(B.T, dot(P_c, B)),
                                dot(B.T, dot(P_c, A)))
        data['K_c'][i] = K_c
        data['A_c'][i] = A + dot(B, K_c)
        data['B_c'][i] = B
        data['controller_evals'][i] = la.eigvals(data['A_c'][i])
        data['controller_evals_c'][i] = np.log(data['controller_evals'][i]) / dt
        assert(np.all(abs(data['controller_evals'][i]) < 1.0))

        # Observability from steer angle and roll rate measurement
        # Note that (A, C_m * A) must be observable in the "current estimator"
        # formulation
        data['obsv_plant'][i] = obsv(A, dot(C_m, A))
        u, s, v = la.svd(data['obsv_plant'][i])
        assert(np.all(s > 1e-13))

        # Solve Riccati equation
        P_e = dare(A.T, C_m.T, V, W)
        # Compute Kalman gain
        K_e = dot(P_e, dot(C_m.T, la.inv(dot(C_m, dot(P_e, C_m.T)) + V)))
        data['K_e'][i] = K_e
        data['A_e'][i] = dot(eye(4) - dot(K_e, C_m), A)
        data['B_e'][i] = np.hstack((dot(eye(4) - dot(K_e, C_m), B), K_e))
        data['estimator_evals'][i] = la.eigvals(data['A_e'][i])
        data['estimator_evals_c'][i] = np.log(data['estimator_evals'][i]) / dt
        # Verify that Kalman estimator eigenvalues are stable
        assert(np.all(abs(data['estimator_evals'][i]) < 1.0))

        # Closed loop state space equations
        A_cl = np.zeros((8, 8))
        A_cl[:4, :4] = A
        A_cl[:4, 4:] = dot(B, K_c)
        A_cl[4:, :4] = dot(K_e, dot(C_m, A))
        A_cl[4:, 4:] = A - A_cl[4:, :4] + A_cl[:4, 4:]
        data['A_cl'][i] = A_cl
        data['closed_loop_evals'][i] = la.eigvals(A_cl)
        assert(np.all(abs(data['closed_loop_evals'][i]) < 1.0))

        B_cl = np.zeros((8, 1))
        B_cl[:4, 0] = B.reshape((4,))
        B_cl[4:, 0] = dot(eye(4) - dot(K_e, C_m), B).reshape((4,))
        data['B_cl'][i] = B_cl

        C_cl = np.hstack((C_z, np.zeros((1, 4))))
        data['C_cl'][i] = C_cl

        # Transfer functions from r to yaw rate
        num, den = ss2tf(A_cl, B_cl, C_cl, 0)
        data['w_r_to_psi_dot'][i], y = freqz(num[0], den)
        data['w_r_to_psi_dot'][i] /= (dt * 2.0 * np.pi)
        data['mag_r_to_psi_dot'][i] = 20.0 * np.log10(abs(y))
        data['phase_r_to_psi_dot'][i] = np.unwrap(np.angle(y)) * 180.0 / np.pi

        # Open loop transfer function from e to yaw rate (PI loop not closed,
        # but LQR/LQG loop closed.
        inner_cl = ss(A_cl, B_cl, C_cl, 0)
        pi_block = ss([[1]], [[1]], [[data['Ki_fit'][i]*dt]], [[data['Kp_fit'][i]]])
        e_to_psi_dot = series(pi_block, inner_cl)
        num, den = ss2tf(e_to_psi_dot.A, e_to_psi_dot.B, e_to_psi_dot.C, e_to_psi_dot.D)
        data['w_e_to_psi_dot'][i], y = freqz(num[0], den)
        data['w_e_to_psi_dot'][i] /= (dt * 2.0 * np.pi)
        data['mag_e_to_psi_dot'][i] = 20.0 * np.log10(abs(y))
        data['phase_e_to_psi_dot'][i] = np.unwrap(np.angle(y)) * 180.0 / np.pi




    return data
Esempio n. 53
0
print A.T.dot(P) + P.dot(A)

R = np.eye(2)
S = 1.0

K = E.T.dot(P).dot(R).dot(P.T).dot(E)
vk,V = np.linalg.eig(K)
print vk

b = 2*np.sqrt(S*np.max(vk)/np.min(vp))

v,V = np.linalg.eig(A)
print v

Ad,Bd,Cd,Dd,dt = cont2discrete((A,B,np.eye(2),np.eye(2)), dt, method='zoh')
x0 = np.array([[1.5,0]]).T

x = x0
t = 0

X = [x0]
T = [t]
U = [np.array([[0,0]]).T]
_B = np.linalg.inv(Bd)

while t<10.0:
	if (t<3):
		_u = -x.copy()
	if t%2.<2.0*dt and ( t>5):
		_u = x.copy()
Esempio n. 54
0
def quadcopter_dynamics(x, u, param):
    """The Tait-Bryan model of the quadcopter which is used in non-linear
    state estimation on the host and for simulation purposes. The state is
    updated internally and updated on every time step with reference to the
    input control signal omega. The parameters defining the process and states
    are loaded from a parameter dictionary on the same for as that used in the
    configuration file (see /config/).
    
    :param x: State vector x = [p, dp, eta, deta]^T at a time k. 
    :param u: Control signals on the form [T, tau_x, tau_y, tau_z]^T at a time k.
    :param param: Parameter dictionary with quadcopter coefficients.
    :type x: np.array of shape (12,1)
    :type u: np.array of shape (4,1)
    :type param: Dictionary

    :returns: xout, yout
    :rtype: np.array (12,1), np.array (M,1) as specified in C
    """

    # Extract angles and parameters
    phi, theta, psi, phidot, thetadot, psidot = np.reshape(x[6:12,0:1],[1,6])[0]
    Ts = param['global']['inner_loop_h']
    g = param['quadcopter_model']['g']
    m = param['quadcopter_model']['m']
    k = param['quadcopter_model']['k']
    A = param['quadcopter_model']['A']
    I = param['quadcopter_model']['I']
    l = param['quadcopter_model']['l']
    b = param['quadcopter_model']['b']
    
    u = u[:,0]
    T = k * sum(u ** 2)

    Ixx, Iyy, Izz = I
    
    Sphi = sin(phi)
    Stheta = sin(theta)
    Spsi = sin(psi);
    Cphi = cos(phi)
    Ctheta = cos(theta)
    Cpsi = cos(psi)
    
    C11 = 0.
    C12 = ((Iyy - Izz) * (thetadot * Cphi * Sphi +
           psidot * Sphi ** 2 *Ctheta) +
           (Izz - Iyy) * psidot * Cphi ** 2 *Ctheta -
           Ixx * psidot * Ctheta)
    C13 = (Izz - Iyy) * psidot * Cphi * Sphi * Ctheta ** 2
    C21 = ((Izz - Iyy) * (thetadot * Cphi * Sphi +
           psidot * Sphi * Ctheta) +
           (Iyy - Izz) * psidot * Cphi ** 2 * Ctheta -
           Ixx * psidot * Ctheta)
    C22 = (Izz - Iyy) * phidot * Cphi * Sphi
    C23 = (-Ixx * psidot * Stheta * Ctheta +
           Iyy * psidot * Sphi ** 2 * Stheta * Ctheta +
           Izz * psidot * Cphi ** 2 * Stheta * Ctheta)
    C31 = ((Iyy - Izz) * psidot * Ctheta ** 2 * Sphi * Cphi -
           Ixx * thetadot * Ctheta)
    C32 = ((Izz - Iyy) * (thetadot * Cphi * Sphi * Stheta +
           phidot * Sphi ** 2 * Ctheta) +
           (Iyy - Izz) * phidot * Cphi ** 2 * Ctheta +
           Ixx * psidot * Stheta * Ctheta -
           Iyy * psidot * Sphi ** 2 * Stheta * Ctheta -
           Izz * psi * Cphi ** 2 * Stheta * Ctheta)
    C33 = ((Iyy - Izz) * phidot * Cphi * Sphi * Ctheta ** 2 -
           Iyy * thetadot * Sphi ** 2 * Ctheta * Stheta -
           Izz * thetadot * Cphi ** 2 * Ctheta * Stheta +
           Ixx * thetadot * Ctheta * Stheta)
    
    C = np.array([[C11,C12,C13],
                  [C21,C22,C23],
                  [C31,C32,C33]]);   
    
    tau_phi =  l * k * (-u[1] ** 2 + u[3] ** 2)
    tau_theta =  l * k * (-u[0] ** 2 + u[2] ** 2)
    tau_psi =  b * (u[0] ** 2 - u[1] ** 2 +
                    u[2] ** 2 - u[3] ** 2)
    
    tau_b = np.array([[tau_phi],[tau_theta],[tau_psi]])
    
    J11 = Ixx
    J12 = 0.
    J13 = -Ixx*Stheta
    J21 = 0.
    J22 = Iyy * Cphi ** 2 + Izz * Sphi ** 2
    J23 = (Iyy - Izz) * Cphi * Sphi * Ctheta
    J31 = -Ixx * Stheta
    J32 = (Iyy - Izz) * Cphi * Sphi * Ctheta
    J33 = (Ixx * Stheta ** 2 + Iyy * Sphi ** 2 * Ctheta ** 2 +
           Izz * Cphi ** 2 * Ctheta ** 2)
    J = np.array([[J11,J12,J13],
                  [J21,J22,J23],
                  [J31,J32,J33]])
    
    invJ = inv(J)

    I3 = np.diag(np.ones([1,3])[0])
    
    Ac = np.zeros([12,12])
    Ac[0:3,3:6] = I3
    Ac[3:6,3:6] = -(1/m)*np.diag(A)
    Ac[6:9,9:12] = I3
    Ac[9:12,9:12] = -np.dot(invJ,C)
    
    Rz = (1/m) * np.array([[cos(psi) * sin(theta) * cos(phi) + sin(psi) * sin(phi)],
                           [sin(psi) * sin(theta) * cos(phi) - cos(psi) * sin(phi)],
                           [cos(theta) * cos(phi)]])
    
    Bc = np.zeros([12,4])
    Bc[3:6,0:1] = Rz
    Bc[9:12,1:4] = invJ
    
    Cc = np.zeros([7,12])
    Cc[0:7,2:9] = np.diag(np.ones([1,7])[0])
    
    Dc = np.array([])
    
    discreteSystem = cont2discrete((Ac,Bc,Cc,Dc), Ts, method='zoh', alpha=None)
    
    Ad = discreteSystem[0]
    Bd = discreteSystem[1]
    Cd = discreteSystem[2]

    G = np.zeros([12,1])
    G[5,0]=-g
    
    # Sets up control signal
    u = np.concatenate([[[T]],tau_b])
    
    xout = np.dot(Ad,x) + np.dot(Bd,u) + G*Ts
    yout = np.dot(Cd,x)
    return xout, yout
Esempio n. 55
0
 def c2d(self, dt):
     out = signal.cont2discrete((squeeze(self.num), squeeze(self.den)),dt,self.c2dmethod)
     self.numz = squeeze(out[0])
     self.denz = squeeze(out[1])
     self.Nden = len(self.denz)