t = np.array(df_X[COL_T], dtype=np.float32)
    x = np.array(df_X[COL_X], dtype=np.float32)
    y = np.array(df_X[COL_Y], dtype=np.float32)
    y = np.copy(x[:, [0, 2]])
    u = np.array(df_X[COL_U], dtype=np.float32)
    Ts = t[1] - t[0]
    n_x = x.shape[-1]

    x0_torch = torch.from_numpy(x[0, :])
    #    x_noise = np.copy(x) + np.random.randn(*x.shape)*std_noise
    #    x_noise = x_noise.astype(np.float32)
    y_noise = np.copy(y) + np.random.randn(*y.shape) * std_noise
    y_noise = y_noise.astype(np.float32)

    # In[Load model]
    ss_model = CartPoleStateSpaceModel(Ts)
    nn_solution = NeuralStateSpaceSimulator(ss_model)
    #model_name = "model_OE_minibatch_100.pkl"
    model_name = "model_ARX_FE_nonoise.pkl"
    nn_solution.ss_model.load_state_dict(
        torch.load(os.path.join("models", model_name)))

    # In[Simulation plot]

    x_torch = torch.tensor(x)
    x0_torch = torch.tensor(x[0, :])
    u_torch = torch.tensor(u)
    t_torch = torch.tensor(t)
    with torch.no_grad():
        x_sim_torch = nn_solution.f_sim(x0_torch, u_torch)
        loss = torch.mean(torch.abs(x_sim_torch - x_torch))
def simulate_pendulum_MPC(sim_options):

    use_NN_model = get_parameter(sim_options, 'use_NN_model')

    if use_NN_model:
        Ts_fit = 10e-3  # model was fitted with this sampling time
        ss_model = CartPoleStateSpaceModel(Ts=Ts_fit)
        nn_solution = NeuralStateSpaceSimulator(ss_model, Ts=Ts_fit)
        model_name = "model_SS_1step_nonoise.pkl"
        nn_solution.ss_model.load_state_dict(
            torch.load(os.path.join("models", model_name)))
        f_ODE = nn_solution.f_ODE
    else:
        f_ODE = f_ODE_wrapped

    seed_val = get_parameter(sim_options, 'seed_val')
    if seed_val is not None:
        np.random.seed(seed_val)

    Ac = get_parameter(sim_options, 'Ac')
    Bc = get_parameter(sim_options, 'Bc')

    Cc = np.array([[1., 0., 0., 0.], [0., 0., 1., 0.]])

    Dc = np.zeros((2, 1))

    [nx, nu] = Bc.shape  # number of states and number or inputs
    ny = np.shape(Cc)[0]

    Ts_MPC = get_parameter(sim_options, 'Ts_MPC')
    ratio_Ts = int(Ts_MPC // Ts_fast)
    Ts_MPC = (
        (Ts_MPC //
         Ts_fast)) * Ts_fast  # make Ts_MPC an integer multiple of Ts_fast

    # Brutal forward euler discretization
    Ad = np.eye(nx) + Ac * Ts_MPC
    Bd = Bc * Ts_MPC
    Cd = Cc
    Dd = Dc

    # Standard deviation of the measurement noise on position and angle

    std_npos = get_parameter(sim_options, 'std_npos')
    std_nphi = get_parameter(sim_options, 'std_nphi')

    # Force disturbance
    std_dF = get_parameter(sim_options, 'std_dF')

    # disturbance power spectrum
    w_F = get_parameter(sim_options,
                        'w_F')  # bandwidth of the force disturbance
    tau_F = 1 / w_F
    Hu = control.TransferFunction([1], [1 / w_F, 1])
    Hu = Hu * Hu
    Hud = control.matlab.c2d(Hu, Ts_MPC)
    N_sim_imp = tau_F / Ts_MPC * 20
    t_imp = np.arange(N_sim_imp) * Ts_MPC
    t, y = control.impulse_response(Hud, t_imp)
    y = y[0]
    std_tmp = np.sqrt(np.sum(y**2))  # np.sqrt(trapz(y**2,t))
    Hu = Hu / (std_tmp) * std_dF

    N_skip = 1  #int(20 * tau_F // Ts_MPC) # skip initial samples to get a regime sample of d
    t_sim_d = get_parameter(sim_options, 'len_sim')  # simulation length (s)
    N_sim_d = int(t_sim_d // Ts_MPC)
    N_sim_d = N_sim_d + N_skip + 1
    e = np.random.randn(N_sim_d)
    te = np.arange(N_sim_d) * Ts_MPC
    _, d, _ = control.forced_response(Hu, te, e)
    d = d.ravel()
    p_ref = d[N_skip:]
    #td = np.arange(len(d)) * Ts_fast

    Np = get_parameter(sim_options, 'Np')
    Nc = get_parameter(sim_options, 'Nc')

    Qx = get_parameter(sim_options, 'Qx')
    QxN = get_parameter(sim_options, 'QxN')
    Qu = get_parameter(sim_options, 'Qu')
    QDu = get_parameter(sim_options, 'QDu')

    # Reference input and states
    xref_fun = get_parameter(sim_options, 'xref_fun')  # reference state
    xref_fun_v = np.vectorize(xref_fun, signature='()->(n)')

    t0 = 0
    xref_MPC = xref_fun(t0)
    uref = get_parameter(sim_options, 'uref')
    uminus1 = np.array(
        [0.0]
    )  # input at time step negative one - used to penalize the first delta u at time instant 0. Could be the same as uref.

    # Constraints
    xmin = np.array([-1000, -1000, -1000, -1000])
    xmax = np.array([1000, 1000.0, 1000, 1000])

    umin = np.array([-10])
    umax = np.array([10])

    Dumin = np.array([-100 * Ts_MPC])
    Dumax = np.array([100 * Ts_MPC])

    # Initialize simulation system
    phi0 = 0.0  #10*2*np.pi/360
    x0 = np.array([0, 0, phi0, 0])  # initial state
    #    system_dyn = ode(f_ODE_wrapped).set_integrator('vode', method='bdf') #    dopri5
    system_dyn = ode(f_ODE).set_integrator('dopri5')
    system_dyn.set_initial_value(x0, t0)
    system_dyn.set_f_params(0.0)

    QP_eps_rel = get_parameter(sim_options, 'QP_eps_rel')
    QP_eps_abs = get_parameter(sim_options, 'QP_eps_abs')

    # Emergency exit conditions

    EMERGENCY_STOP = False
    EMERGENCY_POS = 30.0
    EMERGENCY_ANGLE = 90 * DEG_TO_RAD

    K = MPCController(Ad,
                      Bd,
                      Np=Np,
                      Nc=Nc,
                      x0=x0,
                      xref=xref_MPC,
                      uminus1=uminus1,
                      Qx=Qx,
                      QxN=QxN,
                      Qu=Qu,
                      QDu=QDu,
                      xmin=xmin,
                      xmax=xmax,
                      umin=umin,
                      umax=umax,
                      Dumin=Dumin,
                      Dumax=Dumax,
                      eps_feas=1e3,
                      eps_rel=QP_eps_rel,
                      eps_abs=QP_eps_abs)

    try:
        K.setup(solve=True)  # setup initial problem and also solve it
    except:
        EMERGENCY_STOP = True

    if not EMERGENCY_STOP:
        if K.res.info.status != 'solved':
            EMERGENCY_STOP = True

    # Basic Kalman filter design
    Q_kal = get_parameter(sim_options, 'Q_kal')
    R_kal = get_parameter(sim_options, 'R_kal')
    L, P, W = kalman_design_simple(Ad,
                                   Bd,
                                   Cd,
                                   Dd,
                                   Q_kal,
                                   R_kal,
                                   type='predictor')
    x0_est = x0
    KF = LinearStateEstimator(x0_est, Ad, Bd, Cd, Dd, L)

    # Simulate in closed loop
    len_sim = get_parameter(sim_options, 'len_sim')  # simulation length (s)
    nsim = int(
        np.ceil(len_sim / Ts_MPC)
    )  # simulation length(timesteps) # watch out! +1 added, is it correct?
    t_vec = np.zeros((nsim, 1))
    t_calc_vec = np.zeros(
        (nsim, 1))  # computational time to get MPC solution (+ estimator)
    status_vec = np.zeros((nsim, 1))
    x_vec = np.zeros((nsim, nx))
    x_ref_vec = np.zeros((nsim, nx))
    y_vec = np.zeros((nsim, ny))
    y_meas_vec = np.zeros((nsim, ny))
    y_est_vec = np.zeros((nsim, ny))
    x_est_vec = np.zeros((nsim, nx))
    u_vec = np.zeros((nsim, nu))
    x_MPC_pred = np.zeros(
        (nsim, Np + 1, nx))  # on-line predictions from the Kalman Filter

    nsim_fast = int(len_sim // Ts_fast)
    t_vec_fast = np.zeros((nsim_fast, 1))
    x_vec_fast = np.zeros(
        (nsim_fast, nx))  # finer integration grid for performance evaluation
    x_ref_vec_fast = np.zeros(
        (nsim_fast, nx))  # finer integration grid for performance evaluatio
    u_vec_fast = np.zeros(
        (nsim_fast, nu))  # finer integration grid for performance evaluatio
    Fd_vec_fast = np.zeros((nsim_fast, nu))  #
    t_int_vec_fast = np.zeros((nsim_fast, 1))
    emergency_vec_fast = np.zeros((nsim_fast, 1))  #

    t_pred_all = t0 + np.arange(nsim + Np + 1) * Ts_MPC
    Xref_MPC_all = xref_fun_v(t_pred_all)

    t_step = t0
    x_step = x0
    u_MPC = None
    for idx_fast in range(nsim_fast):

        ## Determine step type: fast simulation only or MPC step
        idx_MPC = idx_fast // ratio_Ts
        run_MPC = (idx_fast % ratio_Ts) == 0

        # Output for step i
        # Ts_MPC outputs
        if run_MPC:  # it is also a step of the simulation at rate Ts_MPC
            t_vec[idx_MPC, :] = t_step
            x_vec[idx_MPC, :] = x_step  #system_dyn.y
            xref_MPC = np.array([p_ref[idx_MPC], 0.0, 0.0, 0.0])
            #xref_MPC = xref_fun(t_step)  # reference state
            t_pred = t_step + np.arange(Np + 1) * Ts_MPC
            x_ref_vec[idx_MPC, :] = xref_MPC

            if not EMERGENCY_STOP:
                #                u_MPC, info_MPC = K.output(return_x_seq=True, return_status=True)  # u[i] = k(\hat x[i]) possibly computed at time instant -1
                u_MPC, info_MPC = K.output(
                    return_status=True, return_x_seq=True
                )  # u[i] = k(\hat x[i]) possibly computed at time instant -1
            else:
                u_MPC = np.zeros(nu)

            if not EMERGENCY_STOP:
                if info_MPC['status'] != 'solved':
                    EMERGENCY_STOP = True

            if not EMERGENCY_STOP:
                #pass
                x_MPC_pred[idx_MPC, :, :] = info_MPC[
                    'x_seq']  # x_MPC_pred[i,i+1,...| possibly computed at time instant -1]
            u_vec[idx_MPC, :] = u_MPC

            y_step = Cd.dot(x_step)  # y[i] from the system
            ymeas_step = np.copy(y_step)
            ymeas_step[0] += std_npos * np.random.randn()
            ymeas_step[1] += std_nphi * np.random.randn()
            y_vec[idx_MPC, :] = y_step
            y_meas_vec[idx_MPC, :] = ymeas_step
            if not EMERGENCY_STOP:
                status_vec[idx_MPC, :] = (info_MPC['status'] != 'solved')

            if np.abs(ymeas_step[0]) > EMERGENCY_POS or np.abs(
                    ymeas_step[1]) > EMERGENCY_ANGLE:
                EMERGENCY_STOP = True

        # Ts_fast outputs
        t_vec_fast[idx_fast, :] = t_step
        x_vec_fast[idx_fast, :] = x_step  #system_dyn.y
        x_ref_vec_fast[idx_fast, :] = xref_MPC
        u_fast = u_MPC
        u_vec_fast[idx_fast, :] = u_fast
        Fd_vec_fast[idx_fast, :] = 0.0
        emergency_vec_fast[idx_fast, :] = EMERGENCY_STOP

        ## Update to step i+1

        # Controller simulation step at rate Ts_MPC
        if run_MPC:
            time_calc_start = time.perf_counter()
            # Kalman filter: update and predict
            #KF.update(ymeas_step) # \hat x[i|i]
            #KF.predict(u_MPC)    # \hat x[i+1|i]
            KF.predict_update(u_MPC, ymeas_step)
            # MPC update
            if not EMERGENCY_STOP:
                #Xref_MPC = Xref_MPC_all[idx_MPC:idx_MPC + Np + 1]
                K.update(
                    KF.x, u_MPC,
                    xref=xref_MPC)  # update with measurement and reference
                #K.update(KF.x, u_MPC, xref=xref_MPC)  # update with measurement and reference
            t_calc_vec[idx_MPC, :] = time.perf_counter() - time_calc_start
            if t_calc_vec[idx_MPC, :] > 2 * Ts_MPC:
                EMERGENCY_STOP = True

        # System simulation step at rate Ts_fast
        time_integrate_start = time.perf_counter()
        system_dyn.set_f_params(u_fast)
        system_dyn.integrate(t_step + Ts_fast)
        x_step = system_dyn.y
        #x_step = x_step + f_ODE(t_step, x_step, u_fast)*Ts_fast
        t_int_vec_fast[
            idx_fast, :] = time.perf_counter() - time_integrate_start

        # Time update
        t_step += Ts_fast

    simout = {
        't': t_vec,
        'x': x_vec,
        'u': u_vec,
        'y': y_vec,
        'y_meas': y_meas_vec,
        'x_ref': x_ref_vec,
        'x_MPC_pred': x_MPC_pred,
        'status': status_vec,
        'Fd_fast': Fd_vec_fast,
        't_fast': t_vec_fast,
        'x_fast': x_vec_fast,
        'x_ref_fast': x_ref_vec_fast,
        'u_fast': u_vec_fast,
        'emergency_fast': emergency_vec_fast,
        'KF': KF,
        'K': K,
        'nsim': nsim,
        'Ts_MPC': Ts_MPC,
        't_calc': t_calc_vec,
        't_int_fast': t_int_vec_fast,
        'use_NN_model': use_NN_model
    }

    return simout
    x_est[:, 2] = y_meas[:, 1]
    x_est[:, 1] = np.convolve(x_est[:, 0], taps, 'same')
    x_est[:, 3] = np.convolve(x_est[:, 2], taps, 'same')

    # Get fit data
    n_fit = int(len_fit // Ts)
    time_fit = t[0:n_fit]
    u_fit = u[0:n_fit]
    x_est_fit = x_est[0:n_fit]
    y_meas_fit = y[0:n_fit]
    batch_size = n_fit // seq_len
    x_hidden_fit = torch.tensor(
        x_est_fit, requires_grad=True)  # this is an optimization variable!

    # Setup neural model structure
    ss_model = CartPoleStateSpaceModel(Ts, init_small=True)
    nn_solution = NeuralStateSpaceSimulator(ss_model)

    # Setup optimizer
    params = list(nn_solution.ss_model.parameters()) + [x_hidden_fit]
    optimizer = optim.Adam(params, lr=lr)

    # Batch extraction funtion
    def get_sequential_batch(seq_len):

        # Select batch indexes
        num_train_samples = x_est_fit.shape[0]
        batch_size = num_train_samples // seq_len - 1
        batch_start = np.arange(0, batch_size, dtype=np.int64) * seq_len
        batch_idx = batch_start[:, np.newaxis] + np.arange(
            seq_len)  # batch all indices
    COL_Y = ['p_meas', 'theta_meas']
    COL_X = ['p', 'v', 'theta', 'omega']
    COL_U = ['u']
    COL_R = ['r']
    df_X = pd.read_csv(os.path.join("data", "pendulum_data_MPC_ref.csv"))

    t = np.array(df_X[COL_T], dtype=np.float32)
    y = np.array(df_X[COL_Y], dtype=np.float32)
    x = np.array(df_X[COL_X], dtype=np.float32)
    #u = np.array(df_X[COL_U],dtype=np.float32)
    u = np.array(df_X[COL_U], dtype=np.float32)
    Ts = t[1] - t[0]
    x_noise = x

    # In[Model]
    ss_model = CartPoleStateSpaceModel(Ts)
    model_name = "model_ARX_FE_nonoise.pkl"
    ss_model.load_state_dict(torch.load(os.path.join("models", model_name)))

    ss_model_residual = NeuralStateSpaceModel(n_x=4, n_u=1, n_feat=64)
    nn_solution = NeuralSumODE([ss_model, ss_model_residual])

    # In[Setup optimization problem]

    len_fit = 40
    n_fit = int(len_fit // Ts)
    u_fit = u[0:n_fit]
    x_fit = x_noise[0:n_fit]
    t_fit = t[0:n_fit]
    u_fit_torch = torch.from_numpy(u_fit)
    x_meas_fit_torch = torch.from_numpy(x_fit)
Beispiel #5
0
    COL_Y = ['p_meas', 'theta_meas']
    COL_X = ['p', 'v', 'theta', 'omega']
    COL_U = ['u']
    COL_R = ['r']
    df_X = pd.read_csv(os.path.join("data", "pendulum_data_MPC_ref.csv"))

    t = np.array(df_X[COL_T], dtype=np.float32)
    y = np.array(df_X[COL_Y],dtype=np.float32)
    x = np.array(df_X[COL_X],dtype=np.float32)
    #u = np.array(df_X[COL_U],dtype=np.float32)
    u = np.array(df_X[COL_R],dtype=np.float32)
    Ts = t[1] - t[0]
    x_noise = x
 
# In[Model]
    ss_model = CartPoleStateSpaceModel(Ts)#n_x=4, n_u=1, n_feat=64)
    nn_solution = NeuralStateSpaceSimulator(ss_model)
   
# In[Setup optimization problem]

    len_fit = 40
    n_fit = int(len_fit//Ts)
    u_fit = u[0:n_fit]
    x_fit = x_noise[0:n_fit]
    t_fit = t[0:n_fit]
    u_fit_torch = torch.from_numpy(u_fit)
    x_meas_fit_torch = torch.from_numpy(x_fit)
    t_fit_torch = torch.from_numpy(t_fit)
    
    num_iter = 10000
    test_freq = 1
Beispiel #6
0
    'xref_fun': xref_fun_def,
    'uref': np.array([0.0]),  # N
    'std_npos': 0 * 0.001,  # m
    'std_nphi': 0 * 0.00005,  # rad
    'std_dF': 0.1,  # N
    'w_F': 5,  # rad
    'len_sim': 40,  #s
    'Ac': Ac_def,
    'Bc': Bc_def,
    'Ts_slower_loop': Ts_slower,
    'Q_kal': np.diag([0.1, 10, 0.1, 10]),
    'R_kal': 1 * np.eye(2),
    'seed_val': 42
}

ss_model = CartPoleStateSpaceModel(Ts=Ts_slower)
nn_solution = NeuralStateSpaceSimulator(ss_model, Ts=Ts_PID)
model_name = "model_SS_1step_nonoise.pkl"
nn_solution.ss_model.load_state_dict(
    torch.load(os.path.join("models", model_name)))
f_ODE_wrapped = nn_solution.f_ODE


def get_parameter(sim_options, par_name):
    return sim_options.get(par_name, DEFAULTS_PENDULUM_MPC[par_name])


def get_default_parameters(sim_options):
    """ Which parameters are left to default ??"""
    default_keys = [
        key for key in DEFAULTS_PENDULUM_MPC if key not in sim_options