Exemplo n.º 1
0
def run_demo(with_plots=True):
    """
    This example demonstrates how to solve parameter estimation problems
    using derivative-free optimization methods.

    The data used in the example was recorded by Kristian Soltesz at the 
    Department of Automatic Control. 
    """

    curr_dir = os.path.dirname(os.path.abspath(__file__))

    # Load measurement data from file
    data = loadmat(curr_dir + '/files/qt_par_est_data.mat', appendmat=False)

    # Extract data series
    t_meas = data['t'][6000::100, 0] - 60
    y1_meas = data['y1_f'][6000::100, 0] / 100
    y2_meas = data['y2_f'][6000::100, 0] / 100
    y3_meas = data['y3_d'][6000::100, 0] / 100
    y4_meas = data['y4_d'][6000::100, 0] / 100
    u1 = data['u1_d'][6000::100, 0]
    u2 = data['u2_d'][6000::100, 0]

    # Plot measurements and inputs
    if with_plots:
        plt.figure(1)
        plt.clf()
        plt.subplot(2, 2, 1)
        plt.plot(t_meas, y3_meas)
        plt.title('x3')
        plt.grid()
        plt.subplot(2, 2, 2)
        plt.plot(t_meas, y4_meas)
        plt.title('x4')
        plt.grid()
        plt.subplot(2, 2, 3)
        plt.plot(t_meas, y1_meas)
        plt.title('x1')
        plt.xlabel('t[s]')
        plt.grid()
        plt.subplot(2, 2, 4)
        plt.plot(t_meas, y2_meas)
        plt.title('x2')
        plt.xlabel('t[s]')
        plt.grid()
        plt.show()

        plt.figure(2)
        plt.clf()
        plt.subplot(2, 1, 1)
        plt.plot(t_meas, u1)
        plt.hold(True)
        plt.title('u1')
        plt.grid()
        plt.subplot(2, 1, 2)
        plt.plot(t_meas, u2)
        plt.title('u2')
        plt.xlabel('t[s]')
        plt.hold(True)
        plt.grid()
        plt.show()

    # Build input trajectory matrix for use in simulation
    u = N.transpose(N.vstack((t_meas, u1, u2)))

    # compile FMU
    fmu_name = compile_fmu('QuadTankPack.Sim_QuadTank',
                           curr_dir + '/files/QuadTankPack.mo')

    # Load model
    model = load_fmu(fmu_name)

    # Create options object and set verbosity to zero to disable printouts
    opts = model.simulate_options()
    opts['CVode_options']['verbosity'] = 0

    # Simulate model response with nominal parameters
    res = model.simulate(input=(['u1', 'u2'], u),
                         start_time=0.,
                         final_time=60,
                         options=opts)

    # Load simulation result
    x1_sim = res['qt.x1']
    x2_sim = res['qt.x2']
    x3_sim = res['qt.x3']
    x4_sim = res['qt.x4']
    t_sim = res['time']
    u1_sim = res['u1']
    u2_sim = res['u2']

    # Plot simulation result
    if with_plots:
        plt.figure(1)
        plt.subplot(2, 2, 1)
        plt.plot(t_sim, x3_sim)
        plt.subplot(2, 2, 2)
        plt.plot(t_sim, x4_sim)
        plt.subplot(2, 2, 3)
        plt.plot(t_sim, x1_sim)
        plt.subplot(2, 2, 4)
        plt.plot(t_sim, x2_sim)
        plt.show()

    # ESTIMATION OF 2 PARAMETERS

    # Define the objective function
    def f1(x):

        model = load_fmu(fmu_name)

        # We need to scale the inputs x down since they are scaled up
        # versions of a1 and a2 (x = scalefactor*[a1 a2])
        a1 = x[0] / 1e6
        a2 = x[1] / 1e6

        # Set new values for a1 and a2 into the model
        model.set('qt.a1', a1)
        model.set('qt.a2', a2)

        # Create options object and set verbosity to zero to disable printouts
        opts = model.simulate_options()
        opts['CVode_options']['verbosity'] = 0

        # Simulate model response with new parameters a1 and a2
        res = model.simulate(input=(['u1', 'u2'], u),
                             start_time=0.,
                             final_time=60,
                             options=opts)

        # Load simulation result
        x1_sim = res['qt.x1']
        x2_sim = res['qt.x2']
        t_sim = res['time']

        # Evaluate the objective function
        y_meas = N.vstack((y1_meas, y2_meas))
        y_sim = N.vstack((x1_sim, x2_sim))
        obj = dfo.quad_err(t_meas, y_meas, t_sim, y_sim)

        return obj

    # Choose starting point (initial estimation)
    x0 = 0.03e-4 * N.ones(2)

    # Choose lower and upper bounds (optional)
    lb = x0 - 1e-6
    ub = x0 + 1e-6

    # Solve the problem using the Nelder-Mead method
    # Scale x0, lb and ub to get order of magnitude 1
    x_opt, f_opt, nbr_iters, nbr_fevals, solve_time = dfo.fmin(f1,
                                                               xstart=x0 * 1e6,
                                                               lb=lb * 1e6,
                                                               ub=ub * 1e6,
                                                               alg=1)
    # alg = 1: Nelder-Mead method
    # alg = 2: Sequential barrier method using Nelder-Mead
    # alg = 3: OpenOpt solver "de" (Differential evolution method)

    # Optimal point (don't forget to scale down)
    [a1_opt, a2_opt] = x_opt / 1e6

    # Print optimal parameter values and optimal function value
    print 'Optimal parameter values:'
    print 'a1 = ' + str(a1_opt * 1e4) + ' cm^2'
    print 'a2 = ' + str(a2_opt * 1e4) + ' cm^2'
    print 'Optimal function value: ' + str(f_opt)
    print ' '

    model = load_fmu(fmu_name)

    # Set optimal values for a1 and a2 into the model
    model.set('qt.a1', a1_opt)
    model.set('qt.a2', a2_opt)

    # Create options object and set verbosity to zero to disable printouts
    opts = model.simulate_options()
    opts['CVode_options']['verbosity'] = 0

    # Simulate model response with optimal parameters a1 and a2
    res = model.simulate(input=(['u1', 'u2'], u),
                         start_time=0.,
                         final_time=60,
                         options=opts)

    # Load optimal simulation result
    x1_opt = res['qt.x1']
    x2_opt = res['qt.x2']
    x3_opt = res['qt.x3']
    x4_opt = res['qt.x4']
    u1_opt = res['qt.u1']
    u2_opt = res['qt.u2']
    t_opt = res['time']

    assert N.abs(res.final('qt.x1') - 0.07060188) < 1e-3
    assert N.abs(res.final('qt.x2') - 0.06654621) < 1e-3
    assert N.abs(res.final('qt.x3') - 0.02736549) < 1e-3
    assert N.abs(res.final('qt.x4') - 0.02789857) < 1e-3
    assert N.abs(res.final('qt.u1') - 6.0) < 1e-3
    assert N.abs(res.final('qt.u2') - 5.0) < 1e-3

    # Plot
    if with_plots:
        font = FontProperties(size='x-small')
        plt.figure(1)
        plt.subplot(2, 2, 1)
        plt.plot(t_opt, x3_opt, 'k')
        plt.subplot(2, 2, 2)
        plt.plot(t_opt, x4_opt, 'k')
        plt.subplot(2, 2, 3)
        plt.plot(t_opt, x1_opt, 'k')
        plt.subplot(2, 2, 4)
        plt.plot(t_opt, x2_opt, 'k')
        plt.show()

    # ESTIMATION OF 4 PARAMETERS

    # Define the objective function
    def f2(x):

        model = load_fmu(fmu_name)

        # We need to scale the inputs x down since they are scaled up
        # versions of a1, a2, a3 and a4 (x = scalefactor*[a1 a2 a3 a4])
        a1 = x[0] / 1e6
        a2 = x[1] / 1e6
        a3 = x[2] / 1e6
        a4 = x[3] / 1e6

        # Set new values for a1, a2, a3 and a4 into the model
        model.set('qt.a1', a1)
        model.set('qt.a2', a2)
        model.set('qt.a3', a3)
        model.set('qt.a4', a4)

        # Create options object and set verbosity to zero to disable printouts
        opts = model.simulate_options()
        opts['CVode_options']['verbosity'] = 0

        # Simulate model response with the new parameters
        res = model.simulate(input=(['u1', 'u2'], u),
                             start_time=0.,
                             final_time=60,
                             options=opts)

        # Load simulation result
        x1_sim = res['qt.x1']
        x2_sim = res['qt.x2']
        x3_sim = res['qt.x3']
        x4_sim = res['qt.x4']
        t_sim = res['time']

        # Evaluate the objective function
        y_meas = [y1_meas, y2_meas, y3_meas, y4_meas]
        y_sim = [x1_sim, x2_sim, x3_sim, x4_sim]
        obj = dfo.quad_err(t_meas, y_meas, t_sim, y_sim)

        return obj

    # Choose starting point (initial estimation)
    x0 = 0.03e-4 * N.ones(4)

    # Lower and upper bounds
    lb = x0 - 1e-6
    ub = x0 + 1e-6

    # Solve the problem
    x_opt, f_opt, nbr_iters, nbr_fevals, solve_time = dfo.fmin(f2,
                                                               xstart=x0 * 1e6,
                                                               lb=lb * 1e6,
                                                               ub=ub * 1e6,
                                                               alg=1)

    # Optimal point (don't forget to scale down)
    [a1_opt, a2_opt, a3_opt, a4_opt] = x_opt / 1e6

    # Print optimal parameters and function value
    print 'Optimal parameter values:'
    print 'a1 = ' + str(a1_opt * 1e4) + ' cm^2'
    print 'a2 = ' + str(a2_opt * 1e4) + ' cm^2'
    print 'a3 = ' + str(a3_opt * 1e4) + ' cm^2'
    print 'a4 = ' + str(a4_opt * 1e4) + ' cm^2'
    print 'Optimal function value: ' + str(f_opt)
    print ' '

    model = load_fmu(fmu_name)

    # Set optimal values for a1, a2, a3 and a4 into the model
    model.set('qt.a1', a1_opt)
    model.set('qt.a2', a2_opt)
    model.set('qt.a3', a3_opt)
    model.set('qt.a4', a4_opt)

    # Create options object and set verbosity to zero to disable printouts
    opts = model.simulate_options()
    opts['CVode_options']['verbosity'] = 0

    # Simulate model response with the optimal parameters
    res = model.simulate(input=(['u1', 'u2'], u),
                         start_time=0.,
                         final_time=60,
                         options=opts)

    # Load optimal simulation result
    x1_opt = res['qt.x1']
    x2_opt = res['qt.x2']
    x3_opt = res['qt.x3']
    x4_opt = res['qt.x4']
    u1_opt = res['qt.u1']
    u2_opt = res['qt.u2']
    t_opt = res['time']

    assert N.abs(res.final('qt.x1') - 0.07059621) < 1e-3
    assert N.abs(res.final('qt.x2') - 0.06672873) < 1e-3
    assert N.abs(res.final('qt.x3') - 0.02723064) < 1e-3
    assert N.abs(res.final('qt.x4') - 0.02912602) < 1e-3
    assert N.abs(res.final('qt.u1') - 6.0) < 1e-3
    assert N.abs(res.final('qt.u2') - 5.0) < 1e-3

    # Plot
    if with_plots:
        font = FontProperties(size='x-small')
        plt.figure(1)
        plt.subplot(2, 2, 1)
        plt.plot(t_opt, x3_opt, 'r')
        plt.subplot(2, 2, 2)
        plt.plot(t_opt, x4_opt, 'r')
        plt.subplot(2, 2, 3)
        plt.plot(t_opt, x1_opt, 'r')
        plt.subplot(2, 2, 4)
        plt.plot(t_opt, x2_opt, 'r')
        plt.legend(
            ('Measurement', 'Simulation nom. params',
             'Simulation opt. params 2 dim', 'Simulation opt. params 4 dim'),
            loc=4,
            prop=font)
        plt.show()
Exemplo n.º 2
0
def run_demo(with_plots=True):
    """
    This example demonstrates how to solve parameter estimation problems
    using derivative-free optimization methods.

    The data used in the example was recorded by Kristian Soltesz at the 
    Department of Automatic Control. 
    """
    
    curr_dir = os.path.dirname(os.path.abspath(__file__));

    # Load measurement data from file
    data = loadmat(curr_dir+'/files/qt_par_est_data.mat',appendmat=False)
    
    # Extract data series
    t_meas = data['t'][6000::100,0]-60
    y1_meas = data['y1_f'][6000::100,0]/100
    y2_meas = data['y2_f'][6000::100,0]/100
    y3_meas = data['y3_d'][6000::100,0]/100
    y4_meas = data['y4_d'][6000::100,0]/100
    u1 = data['u1_d'][6000::100,0]
    u2 = data['u2_d'][6000::100,0]

    # Plot measurements and inputs
    if with_plots:
        plt.figure(1)
        plt.clf()
        plt.subplot(2,2,1)
        plt.plot(t_meas,y3_meas)
        plt.title('x3')
        plt.grid()
        plt.subplot(2,2,2)
        plt.plot(t_meas,y4_meas)
        plt.title('x4')
        plt.grid()
        plt.subplot(2,2,3)
        plt.plot(t_meas,y1_meas)
        plt.title('x1')
        plt.xlabel('t[s]')
        plt.grid()
        plt.subplot(2,2,4)
        plt.plot(t_meas,y2_meas)
        plt.title('x2')
        plt.xlabel('t[s]')
        plt.grid()
        plt.show()

        plt.figure(2)
        plt.clf()
        plt.subplot(2,1,1)
        plt.plot(t_meas,u1)
        plt.hold(True)
        plt.title('u1')
        plt.grid()
        plt.subplot(2,1,2)
        plt.plot(t_meas,u2)
        plt.title('u2')
        plt.xlabel('t[s]')
        plt.hold(True)
        plt.grid()
        plt.show()

    # Build input trajectory matrix for use in simulation
    u = N.transpose(N.vstack((t_meas,u1,u2)))

    # compile FMU
    fmu_name = compile_fmu('QuadTankPack.Sim_QuadTank', 
        curr_dir+'/files/QuadTankPack.mo')

    # Load model
    model = load_fmu(fmu_name)
    
    # Create options object and set verbosity to zero to disable printouts
    opts = model.simulate_options()
    opts['CVode_options']['verbosity'] = 0

    # Simulate model response with nominal parameters
    res = model.simulate(input=(['u1','u2'],u),start_time=0.,final_time=60,options=opts)

    # Load simulation result
    x1_sim = res['qt.x1']
    x2_sim = res['qt.x2']
    x3_sim = res['qt.x3']
    x4_sim = res['qt.x4']
    t_sim  = res['time']
    u1_sim = res['u1']
    u2_sim = res['u2']

    # Plot simulation result
    if with_plots:
        plt.figure(1)
        plt.subplot(2,2,1)
        plt.plot(t_sim,x3_sim)
        plt.subplot(2,2,2)
        plt.plot(t_sim,x4_sim)
        plt.subplot(2,2,3)
        plt.plot(t_sim,x1_sim)
        plt.subplot(2,2,4)
        plt.plot(t_sim,x2_sim)
        plt.show()
    
    # ESTIMATION OF 2 PARAMETERS
    
    # Define the objective function
    def f1(x):

        model = load_fmu(fmu_name)

        # We need to scale the inputs x down since they are scaled up 
        # versions of a1 and a2 (x = scalefactor*[a1 a2])
        a1 = x[0]/1e6
        a2 = x[1]/1e6
        
        # Set new values for a1 and a2 into the model 
        model.set('qt.a1',a1)
        model.set('qt.a2',a2)
        
        # Create options object and set verbosity to zero to disable printouts
        opts = model.simulate_options()
        opts['CVode_options']['verbosity'] = 0
        
        # Simulate model response with new parameters a1 and a2
        res = model.simulate(input=(['u1','u2'],u),start_time=0.,final_time=60,options=opts)
        
        # Load simulation result
        x1_sim = res['qt.x1']
        x2_sim = res['qt.x2']
        t_sim  = res['time']
        
        # Evaluate the objective function
        y_meas = N.vstack((y1_meas,y2_meas))
        y_sim = N.vstack((x1_sim,x2_sim))
        obj = dfo.quad_err(t_meas,y_meas,t_sim,y_sim)
        
        return obj

    # Choose starting point (initial estimation)
    x0 = 0.03e-4*N.ones(2)

    # Choose lower and upper bounds (optional)
    lb = x0 - 1e-6
    ub = x0 + 1e-6

    # Solve the problem using the Nelder-Mead method
    # Scale x0, lb and ub to get order of magnitude 1
    x_opt,f_opt,nbr_iters,nbr_fevals,solve_time = dfo.fmin(f1,xstart=x0*1e6,lb=lb*1e6,
                                                           ub=ub*1e6,alg=1)
    # alg = 1: Nelder-Mead method
    # alg = 2: Sequential barrier method using Nelder-Mead
    # alg = 3: OpenOpt solver "de" (Differential evolution method)

    # Optimal point (don't forget to scale down)
    [a1_opt,a2_opt] = x_opt/1e6

    # Print optimal parameter values and optimal function value
    print 'Optimal parameter values:'
    print 'a1 = ' + str(a1_opt*1e4) + ' cm^2'
    print 'a2 = ' + str(a2_opt*1e4) + ' cm^2'
    print 'Optimal function value: ' + str(f_opt)
    print ' '

    model = load_fmu(fmu_name)

    # Set optimal values for a1 and a2 into the model
    model.set('qt.a1',a1_opt)
    model.set('qt.a2',a2_opt)
    
    # Create options object and set verbosity to zero to disable printouts
    opts = model.simulate_options()
    opts['CVode_options']['verbosity'] = 0

    # Simulate model response with optimal parameters a1 and a2
    res = model.simulate(input=(['u1','u2'],u),start_time=0.,final_time=60,options=opts)

    # Load optimal simulation result
    x1_opt = res['qt.x1']
    x2_opt = res['qt.x2']
    x3_opt = res['qt.x3']
    x4_opt = res['qt.x4']
    u1_opt = res['qt.u1']
    u2_opt = res['qt.u2']
    t_opt  = res['time']
    
    assert N.abs(res.final('qt.x1') - 0.07060188) < 1e-3
    assert N.abs(res.final('qt.x2') - 0.06654621) < 1e-3
    assert N.abs(res.final('qt.x3') - 0.02736549) < 1e-3
    assert N.abs(res.final('qt.x4') - 0.02789857) < 1e-3
    assert N.abs(res.final('qt.u1') - 6.0)        < 1e-3
    assert N.abs(res.final('qt.u2') - 5.0)        < 1e-3


    # Plot
    if with_plots:
        font = FontProperties(size='x-small')
        plt.figure(1)
        plt.subplot(2,2,1)
        plt.plot(t_opt,x3_opt,'k')
        plt.subplot(2,2,2)
        plt.plot(t_opt,x4_opt,'k')
        plt.subplot(2,2,3)
        plt.plot(t_opt,x1_opt,'k')
        plt.subplot(2,2,4)
        plt.plot(t_opt,x2_opt,'k')
        plt.show()
    
    # ESTIMATION OF 4 PARAMETERS
    
    # Define the objective function
    def f2(x):                

        model = load_fmu(fmu_name)

        # We need to scale the inputs x down since they are scaled up 
        # versions of a1, a2, a3 and a4 (x = scalefactor*[a1 a2 a3 a4])
        a1 = x[0]/1e6
        a2 = x[1]/1e6
        a3 = x[2]/1e6
        a4 = x[3]/1e6
        
        # Set new values for a1, a2, a3 and a4 into the model 
        model.set('qt.a1',a1)
        model.set('qt.a2',a2)
        model.set('qt.a3',a3)
        model.set('qt.a4',a4)
        
        # Create options object and set verbosity to zero to disable printouts
        opts = model.simulate_options()
        opts['CVode_options']['verbosity'] = 0
        
        # Simulate model response with the new parameters
        res = model.simulate(input=(['u1','u2'],u),start_time=0.,final_time=60,options=opts)
        
        # Load simulation result
        x1_sim = res['qt.x1']
        x2_sim = res['qt.x2']
        x3_sim = res['qt.x3']
        x4_sim = res['qt.x4']
        t_sim  = res['time']
        
        # Evaluate the objective function
        y_meas = [y1_meas,y2_meas,y3_meas,y4_meas]
        y_sim = [x1_sim,x2_sim,x3_sim,x4_sim]
        obj = dfo.quad_err(t_meas,y_meas,t_sim,y_sim)
        
        return obj

    # Choose starting point (initial estimation)
    x0 = 0.03e-4*N.ones(4)

    # Lower and upper bounds
    lb = x0 - 1e-6
    ub = x0 + 1e-6

    # Solve the problem
    x_opt,f_opt,nbr_iters,nbr_fevals,solve_time = dfo.fmin(f2,xstart=x0*1e6,lb=lb*1e6,
                                                          ub=ub*1e6,alg=1)

    # Optimal point (don't forget to scale down)
    [a1_opt,a2_opt,a3_opt,a4_opt] = x_opt/1e6

    # Print optimal parameters and function value
    print 'Optimal parameter values:'
    print 'a1 = ' + str(a1_opt*1e4) + ' cm^2'
    print 'a2 = ' + str(a2_opt*1e4) + ' cm^2'
    print 'a3 = ' + str(a3_opt*1e4) + ' cm^2'
    print 'a4 = ' + str(a4_opt*1e4) + ' cm^2'
    print 'Optimal function value: ' + str(f_opt)
    print ' '

    model = load_fmu(fmu_name)
    
    # Set optimal values for a1, a2, a3 and a4 into the model
    model.set('qt.a1',a1_opt)
    model.set('qt.a2',a2_opt)
    model.set('qt.a3',a3_opt)
    model.set('qt.a4',a4_opt)
    
    # Create options object and set verbosity to zero to disable printouts
    opts = model.simulate_options()
    opts['CVode_options']['verbosity'] = 0

    # Simulate model response with the optimal parameters
    res = model.simulate(input=(['u1','u2'],u),start_time=0.,final_time=60,options=opts)

    # Load optimal simulation result
    x1_opt = res['qt.x1']
    x2_opt = res['qt.x2']
    x3_opt = res['qt.x3']
    x4_opt = res['qt.x4']
    u1_opt = res['qt.u1']
    u2_opt = res['qt.u2']
    t_opt  = res['time']
    
    assert N.abs(res.final('qt.x1') - 0.07059621) < 1e-3
    assert N.abs(res.final('qt.x2') - 0.06672873) < 1e-3
    assert N.abs(res.final('qt.x3') - 0.02723064) < 1e-3
    assert N.abs(res.final('qt.x4') - 0.02912602) < 1e-3
    assert N.abs(res.final('qt.u1') - 6.0)        < 1e-3
    assert N.abs(res.final('qt.u2') - 5.0)        < 1e-3
    

    # Plot
    if with_plots:
        font = FontProperties(size='x-small')
        plt.figure(1)
        plt.subplot(2,2,1)
        plt.plot(t_opt,x3_opt,'r')
        plt.subplot(2,2,2)
        plt.plot(t_opt,x4_opt,'r')
        plt.subplot(2,2,3)
        plt.plot(t_opt,x1_opt,'r')
        plt.subplot(2,2,4)
        plt.plot(t_opt,x2_opt,'r')
        plt.legend(('Measurement','Simulation nom. params','Simulation opt. params 2 dim','Simulation opt. params 4 dim'),loc=4,prop=font)
        plt.show()
Exemplo n.º 3
0
def run_demo(with_plots=True):
    """
    This example demonstrates how to solve a parameter estimation problem 
    using a derivative-free optimization method. The model to be calibrated
    is a model of a Furuta pendulum. The optimization algorithm used is
    an implementation of the Nelder-Mead simplex algorithm which uses 
    multiprocessing for the function evaluations.
    
    The file furuta_dfo_cost.py is also a part of this example. It contains
    the definition of the objective function.
    
    Note that when this example is run, sub-directories to the current one
    are created, where the function evaluations are performed. These 
    should be manually removed after a run.
    
    The data used in the example was recorded by Kristian Soltesz at the 
    Department of Automatic Control.
    """

    curr_dir = os.path.dirname(os.path.abspath(__file__))

    # Load measurement data from file
    data = loadmat(os.path.join(curr_dir, 'files', 'FurutaData.mat'),
                   appendmat=False)

    # Extract data series
    t_meas = data['time'][:, 0]
    phi_meas = data['phi'][:, 0]
    theta_meas = data['theta'][:, 0]

    # Plot measurements
    if with_plots:
        font = FontProperties(size='small')
        plt.figure(1)
        plt.clf()
        plt.subplot(2, 1, 1)
        plt.plot(t_meas, theta_meas, label='Measurements')
        plt.title('theta [rad]')
        plt.legend(prop=font, loc=1)
        plt.grid()
        plt.subplot(2, 1, 2)
        plt.plot(t_meas, phi_meas, label='Measurements')
        plt.title('phi [rad]')
        plt.legend(prop=font, loc=1)
        plt.grid()
        plt.show()

    # Load model
    model = load_fmu(os.path.join(curr_dir, 'files', 'FMUs', 'Furuta.fmu'))

    # Simulate model response with nominal parameters
    res = model.simulate(start_time=0., final_time=40)

    # Load simulation result
    phi_sim = res['armJoint.phi']
    theta_sim = res['pendulumJoint.phi']
    t_sim = res['time']

    # Plot simulation result
    if with_plots:
        plt.figure(1)
        plt.subplot(2, 1, 1)
        plt.plot(t_sim,
                 theta_sim,
                 '--',
                 linewidth=2,
                 label='Simulation nominal parameters')
        plt.legend(prop=font, loc=1)
        plt.subplot(2, 1, 2)
        plt.plot(t_sim,
                 phi_sim,
                 '--',
                 linewidth=2,
                 label='Simulation nominal parameters')
        plt.xlabel('t [s]')
        plt.legend(prop=font, loc=1)
        plt.show()

    # Choose starting point (initial estimation)
    x0 = N.array([0.012, 0.002])

    # Choose lower and upper bounds (optional)
    lb = N.zeros(2)
    ub = x0 + 1e-2

    # Solve the problem using the Nelder-Mead method
    # Scale x0, lb and ub to get order of magnitude 1
    # alg = 1: Nelder-Mead method
    # alg = 2: Sequential barrier method using Nelder-Mead
    # alg = 3: OpenOpt solver "de" (Differential evolution method)
    x_opt, f_opt, nbr_iters, nbr_fevals, solve_time = dfo.fmin(os.path.join(
        curr_dir, 'furuta_dfo_cost.py'),
                                                               xstart=x0 * 1e3,
                                                               lb=lb * 1e3,
                                                               ub=ub * 1e3,
                                                               alg=1,
                                                               nbr_cores=1,
                                                               x_tol=1e-3,
                                                               f_tol=1e-2)

    # Optimal point (don't forget to scale down)
    [armFrictionCoefficient_opt, pendulumFrictionCoefficient_opt] = x_opt / 1e3

    # Print optimal parameter values and optimal function value
    print('Optimal parameter values:')
    print('arm friction coefficient = ' + str(armFrictionCoefficient_opt))
    print('pendulum friction coefficient = ' +
          str(pendulumFrictionCoefficient_opt))
    print('Optimal function value: ' + str(f_opt))
    print(' ')

    # Load model
    model = load_fmu(os.path.join(curr_dir, 'files', 'FMUs', 'Furuta.fmu'))

    # Set optimal parameter values into the model
    model.set('armFriction', armFrictionCoefficient_opt)
    model.set('pendulumFriction', pendulumFrictionCoefficient_opt)

    # Simulate model response with optimal parameter values
    res = model.simulate(start_time=0., final_time=40)

    # Load optimal simulation result
    phi_opt = res['armJoint.phi']
    theta_opt = res['pendulumJoint.phi']
    t_opt = res['time']

    assert N.abs(res.final('armJoint.phi') + 0.314) < 2e-2
    assert N.abs(res.final('pendulumJoint.phi') - 3.137) < 2e-2
    assert N.abs(res.final('time') - 40.0) < 1e-3

    # Plot
    if with_plots:
        plt.figure(1)
        plt.subplot(2, 1, 1)
        plt.plot(t_opt,
                 theta_opt,
                 '-.',
                 linewidth=3,
                 label='Simulation optimal parameters')
        plt.legend(prop=font, loc=1)
        plt.subplot(2, 1, 2)
        plt.plot(t_opt,
                 phi_opt,
                 '-.',
                 linewidth=3,
                 label='Simulation optimal parameters')
        plt.legend(prop=font, loc=1)
        plt.show()
Exemplo n.º 4
0
def run_demo(with_plots=True):
    """
    This example demonstrates how to solve a parameter estimation problem 
    using a derivative-free optimization method. The model to be calibrated
    is a model of a Furuta pendulum. The optimization algorithm used is
    an implementation of the Nelder-Mead simplex algorithm which uses 
    multiprocessing for the function evaluations.
    
    The file furuta_dfo_cost.py is also a part of this example. It contains
    the definition of the objective function.
    
    Note that when this example is run, sub-directories to the current one
    are created, where the function evaluations are performed. These 
    should be manually removed after a run.
    
    The data used in the example was recorded by Kristian Soltesz at the 
    Department of Automatic Control.
    """
    
    curr_dir = os.path.dirname(os.path.abspath(__file__));
    
    # Load measurement data from file
    data = loadmat(os.path.join(curr_dir, 'files', 'FurutaData.mat'), appendmat=False)
    
    # Extract data series
    t_meas = data['time'][:,0]
    phi_meas = data['phi'][:,0]
    theta_meas = data['theta'][:,0]
    
    # Plot measurements
    if with_plots:
        font = FontProperties(size='small')
        plt.figure(1)
        plt.clf()
        plt.subplot(2,1,1)
        plt.plot(t_meas, theta_meas, label='Measurements')
        plt.title('theta [rad]')
        plt.legend(prop=font, loc=1)
        plt.grid()
        plt.subplot(2,1,2)
        plt.plot(t_meas, phi_meas, label='Measurements')
        plt.title('phi [rad]')
        plt.legend(prop=font, loc=1)
        plt.grid()
        plt.show()
    
    # Load model
    model = load_fmu(os.path.join(curr_dir, 'files', 'FMUs', 'Furuta.fmu'))
    
    # Create options object and set verbosity to zero to disable printouts
    opts = model.simulate_options()
    opts['CVode_options']['verbosity'] = 0
    
    # Simulate model response with nominal parameters
    res = model.simulate(start_time=0., final_time=40, options=opts)
    
    # Load simulation result
    phi_sim = res['armJoint.phi']
    theta_sim = res['pendulumJoint.phi']
    t_sim  = res['time']
    
    # Plot simulation result
    if with_plots:
        plt.figure(1)
        plt.subplot(2,1,1)
        plt.plot(t_sim, theta_sim, '--', linewidth=2, label='Simulation nominal parameters')
        plt.legend(prop=font,loc=1)
        plt.subplot(2,1,2)
        plt.plot(t_sim,phi_sim, '--', linewidth=2, label='Simulation nominal parameters')
        plt.xlabel('t [s]')
        plt.legend(prop=font,loc=1)
        plt.show()
    
    # Choose starting point (initial estimation)
    x0 = N.array([0.012,0.002])
    
    # Choose lower and upper bounds (optional)
    lb = N.zeros(2)
    ub = x0 + 1e-2
    
    # Solve the problem using the Nelder-Mead method
    # Scale x0, lb and ub to get order of magnitude 1
    # alg = 1: Nelder-Mead method
    # alg = 2: Sequential barrier method using Nelder-Mead
    # alg = 3: OpenOpt solver "de" (Differential evolution method)
    x_opt,f_opt,nbr_iters,nbr_fevals,solve_time = dfo.fmin(os.path.join(curr_dir, 'furuta_dfo_cost.py'), 
                                                           xstart=x0*1e3, 
                                                           lb=lb*1e3, 
                                                           ub=ub*1e3, 
                                                           alg=1, 
                                                           nbr_cores=1, 
                                                           x_tol=1e-3, 
                                                           f_tol=1e-2)
    
    # Optimal point (don't forget to scale down)
    [armFrictionCoefficient_opt, pendulumFrictionCoefficient_opt] = x_opt/1e3
    
    # Print optimal parameter values and optimal function value
    print 'Optimal parameter values:'
    print 'arm friction coefficient = ' + str(armFrictionCoefficient_opt)
    print 'pendulum friction coefficient = ' + str(pendulumFrictionCoefficient_opt)
    print 'Optimal function value: ' + str(f_opt)
    print ' '
    
    # Load model
    model = load_fmu(os.path.join(curr_dir,'files','FMUs','Furuta.fmu'))
    
    # Set optimal parameter values into the model
    model.set('armFriction', armFrictionCoefficient_opt)
    model.set('pendulumFriction', pendulumFrictionCoefficient_opt)
    
    # Create options object and set verbosity to zero to disable printouts
    opts = model.simulate_options()
    opts['CVode_options']['verbosity'] = 0
    
    # Simulate model response with optimal parameter values
    res = model.simulate(start_time=0., final_time=40, options=opts)
    
    # Load optimal simulation result
    phi_opt = res['armJoint.phi']
    theta_opt = res['pendulumJoint.phi']
    t_opt  = res['time']

    assert N.abs(res.final('armJoint.phi') + 0.3123)      < 1e-3
    assert N.abs(res.final('pendulumJoint.phi') - 3.1318) < 1e-3
    assert N.abs(res.final('time') - 40.0)                < 1e-3

    # Plot
    if with_plots:
        plt.figure(1)
        plt.subplot(2,1,1)
        plt.plot(t_opt, theta_opt, '-.', linewidth=3, label='Simulation optimal parameters')
        plt.legend(prop=font, loc=1)
        plt.subplot(2,1,2)
        plt.plot(t_opt, phi_opt, '-.', linewidth=3, label='Simulation optimal parameters')
        plt.legend(prop=font, loc=1)
        plt.show()