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()
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()
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()
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()