return params.C2 @ x F = [fun1, fun2] G = [gs, gs] numSwitches = 2 ydists = numpy.array([ scipy.stats.multivariate_normal(cov=params.R2), scipy.stats.multivariate_normal(cov=params.R2) ]) xdists = numpy.array([ scipy.stats.multivariate_normal(cov=params.Q), scipy.stats.multivariate_normal(cov=params.Q) ]) cstr_filter = SPF.Model(F, G, A, xdists, ydists) nP = 500 xdist = scipy.stats.multivariate_normal(mean=init_state, cov=params.init_state_covar) sdist = [0.9, 0.1] particles = SPF.init_spf(xdist, sdist, nP, 2) switchtrack = numpy.zeros([2, params.N]) maxtrack = numpy.zeros([numSwitches, params.N]) smoothedtrack = numpy.zeros([numSwitches, params.N]) state_noise_dist = scipy.stats.multivariate_normal(cov=params.Q) meas_noise_dist = scipy.stats.multivariate_normal(cov=params.R2) params.xs[:, 0] = init_state
def fun(): isDone = True init_state = numpy.array([0.55, 450]) # initial state # Setup Switching Particle Filter A = numpy.array([[0.999, 0.001], [0.001, 0.999]]) def fun1(x, u, w): return params.cstr_model.run_reactor(x, u, params.h) + w def fun2(x, u, w): return params.cstr_model_broken.run_reactor(x, u, params.h) + w def gs(x): return params.C2 @ x F = [fun1, fun2] G = [gs, gs] numSwitches = 2 ydists = numpy.array([ scipy.stats.multivariate_normal(cov=params.R2), scipy.stats.multivariate_normal(cov=params.R2) ]) xdists = numpy.array([ scipy.stats.multivariate_normal(cov=params.Q), scipy.stats.multivariate_normal(cov=params.Q) ]) cstr_filter = SPF.Model(F, G, A, xdists, ydists) nP = 500 # number of particles xdist = scipy.stats.multivariate_normal(mean=init_state, cov=params.init_state_covar) sdist = [0.9, 0.1] particles = SPF.init_spf(xdist, sdist, nP, 2) switchtrack = numpy.zeros([2, params.N]) maxtrack = numpy.zeros([numSwitches, params.N]) smoothedtrack = numpy.zeros([numSwitches, params.N]) state_noise_dist = scipy.stats.multivariate_normal(cov=params.Q) meas_noise_dist = scipy.stats.multivariate_normal(cov=params.R2) # Setup control (use linear control) linsystems = params.cstr_model.get_nominal_linear_systems(params.h) linsystems_broken = params.cstr_model_broken.get_nominal_linear_systems( params.h) opoint = 1 # the specific linear model we will use lin_models = [None] * 2 # type: typing.List[RBPF.Model] lin_models[0] = RBPF.Model(linsystems[opoint].A, linsystems[opoint].B, linsystems[opoint].b, params.C2, params.Q, params.R2) lin_models[1] = RBPF.Model(linsystems_broken[opoint].A, linsystems_broken[opoint].B, linsystems_broken[opoint].b, params.C2, params.Q, params.R2) H = numpy.matrix([1, 0]) # only attempt to control the concentration setpoint = 0.49 controllers = [None] * 2 # type: typing.List[LQR.Controller] for k in range(2): ysp = setpoint - lin_models[k].b[0] # set point is set here x_off, u_off = LQR.offset(lin_models[k].A, numpy.matrix(lin_models[k].B), params.C2, H, numpy.matrix([ysp])) K = LQR.lqr(lin_models[k].A, numpy.matrix(lin_models[k].B), params.QQ, params.RR) controllers[k] = LQR.Controller(K, x_off, u_off) # Setup simulation params.xs[:, 0] = init_state params.ys2[:, 0] = params.C2 @ params.xs[:, 0] + meas_noise_dist.rvs( ) # measured from actual plant SPF.init_filter(particles, params.ys2[:, 0], cstr_filter) for k in range(numSwitches): switchtrack[k, 0] = numpy.sum( particles.w[numpy.where(particles.s == k)[0]]) maxtrack[:, 0] = SPF.get_max_track(particles, numSwitches) smoothedtrack[:, 0] = RBPF.smoothed_track(numSwitches, switchtrack, 1, 10) params.spfmeans[:, 0], params.spfcovars[:, :, 0] = SPF.get_stats(particles) # Controller Input ind = numpy.argmax(maxtrack[:, 0]) # use this model and controller horizon = 150 params.us[0] = MPC.mpc_lqr(params.spfmeans[:, 0] - lin_models[ind].b, horizon, lin_models[ind].A, numpy.matrix(lin_models[ind].B), params.QQ, params.RR, controllers[ind].x_off, controllers[ind].u_off) # Loop through the rest of time for t in range(1, params.N): random_element = state_noise_dist.rvs() if params.ts[t] < 100: # break here params.xs[:, t] = params.cstr_model.run_reactor( params.xs[:, t - 1], params.us[t - 1], params.h) + random_element else: params.xs[:, t] = params.cstr_model_broken.run_reactor( params.xs[:, t - 1], params.us[t - 1], params.h) params.xs[:, t] += random_element params.ys2[:, t] = params.C2 @ params.xs[:, t] + meas_noise_dist.rvs( ) # measured from actual plant SPF.spf_filter(particles, params.us[t - 1], params.ys2[:, t], cstr_filter) params.spfmeans[:, t], params.spfcovars[:, :, t] = SPF.get_stats(particles) for k in range(numSwitches): switchtrack[k, 0] = numpy.sum( particles.w[numpy.where(particles.s == k)[0]]) maxtrack[:, t] = SPF.get_max_track(particles, numSwitches) smoothedtrack[:, t] = RBPF.smoothed_track(numSwitches, switchtrack, t, 40) # Controller Input if t % 1 == 0: ind = numpy.argmax(maxtrack[:, t]) # use this model and controller params.us[t] = MPC.mpc_lqr( params.spfmeans[:, t] - lin_models[ind].b, horizon, lin_models[ind].A, numpy.matrix(lin_models[ind].B), params.QQ, params.RR, controllers[ind].x_off, controllers[ind].u_off) else: params.us[t] = params.us[t - 1] if params.us[t] is None or numpy.isnan(params.us[t]): isDone = False break return isDone, setpoint