def test_get_state_matrices(self):
   """Tests the get_state_matrices function."""
   
   # Define constants
   K_list = [1, 3, 10]
   tau_list = [0.1, 0.3, 1]
   delay_list = [0.01, 0.1, 0.3, 1]
   param_list = set(itertools.chain(*[zip(K_list, x, y) for x in
                                      itertools.permutations(tau_list, len(K_list))
                                      for y in
                                      itertools.permutations(delay_list, len(K_list))]))
   for K, tau, td in param_list:
     den = tau * td ** 2
     A_exp = np.array([[0, 1, 0], [0, 0, 1], [-12 / den, -(6 * td + 12 * tau) / den, -(6 * tau + td) / tau / td]])
     B_exp = np.array([[0], [0], [12 / den]])
     C_exp = np.array([[K, -K * td / 2, K * td ** 2 / 12]])
     A, B, C = sim_functions.get_state_matrices(K, tau, td)
     self.assertListEqual(A.tolist(), A_exp.tolist(),
                          "A matrix does not match expected.")
     self.assertListEqual(B.tolist(), B_exp.tolist(),
                          "B matrix does not match expected.")
     self.assertListEqual(C.tolist(), C_exp.tolist(),
                          "C matrix does not match expected")
   
   def test_get_second_ord_matrices(self):
     """Tests the sim_functions.get_second_ord_matrices method."""
     pass
Beispiel #2
0
    def setUp(self):
        """Run repeated setup code once."""

        # Define class and local parameters
        unittest.TestCase.setUp(self)
        self.K_list = [3, 10, 99.21]
        self.tau_list = [0.3, 1]
        self.delay_list = [0.03, 0.1, 0.3]
        self.t_step = 0.01
        self.stop_time = 20.0
        self.input_val = 1.0
        self.t_step_ctrl = 0.1
        self.zeta = 0.7054  # air MFC damping ratio
        self.wn = 1.3501  # air MFC natural frequency, rad/s
        self.td = 1.8  # air MFC time delay, sec
        self.y0_1 = [0]
        self.y0_2 = [0] * 3  # for first-order model
        self.y0_3 = [0] * 4  # for second-order model
        A, B, self.C = sim_functions.get_state_matrices(
            self.K_list[1], self.tau_list[-1], self.delay_list[0])
        A2, B2, self.C2 = sim_functions.get_second_ord_matrices(
            self.K_list[-1], self.zeta, self.wn, self.td)
        self.Kp_list = [4.0, 5.0]
        self.mass_flow_des = [4.0, 2.0]
        self.std = 1.0
        self.Ks = 2.0  # filter static gain (?)
        Q = 1e-5 * np.identity(A2.shape[0])  # process noise covariance
        R = self.std  # measurement noise covariance
        self.P = Q  # initial estimate of error covariance
        self.offset = 0.0
        mean = 0.0

        # Define objects
        self.test_mfc1 = lab_hardware.MFC(
            lambda t, y, u: test_ode(t, y, u, self.K_list[1], self.tau_list[-1]
                                     ), lambda x: x[0], self.y0_1)
        self.test_mfc2 = lab_hardware.MFC(
            lambda t, y, u: sim_functions.system_state_update(t, y, u, A, B),
            lambda y: sim_functions.system_output(y, self.C), self.y0_2)
        self.test_mfc3 = lab_hardware.MFC(
            lambda t, y, u: sim_functions.system_state_update(t, y, u, A2, B2),
            lambda y: sim_functions.system_output(y, self.C2), self.y0_3)
        self.mfc_list = [
            lab_hardware.MFC(lambda t, y, u: test_ode(t, y, u, K, tau),
                             lambda x: x[0], self.y0_1)
            for K, tau in zip(self.K_list, self.tau_list)
        ]
        self.test_KF = lab_hardware.KalmanFilter(A2, B2, self.Ks * self.C2, Q,
                                                 R, self.P)
        self.test_sensor = lab_hardware.StaticSensor(
            lambda y: sim_functions.static_model(y, self.Ks, self.offset, mean,
                                                 self.std), 1.0)
Beispiel #3
0
def run_simulation():
  """Run a simulation of the controller."""
  
  # Define system parameters
  p_atm = 14.0  # psi
  t_step = 0.01  # simulation time step, seconds
  t_step_ctrl = 0.1  # controller update rate, seconds
  K = 0.1  # static pressure sensor gain, V/psi (?)
  offset = 1.0  # static pressure sensor offset, V (?)
  K_mfcs = [99.21, 7.968, 8.007]  # MFC gains: [air, pilot, outer], SLPM/V
  zeta_mfcs = [0.7054, 0.6, 0.6]  # MFC damping ratios: [air, pilot, outer]
  wn_mfcs = [1.3501, 1, 1]  # MFC natural frequencies: [air, pilot, outer], rad/sec
  td_mfcs = [1.8, 0.139, 0.306]  # MFC time delays: [air, pilot, outer], sec
  K_mid = 7.964  # middle fuel MFC static gain, SLPM/V
  tau_mid = 0.516  # middle fuel MFC time constant, sec (first-order)
  td_mid = 0.194  # middle fuel MFC time delay, sec
  y0 = [0.0, 0.0, 0.0, 0.0]  # initial value, 2nd order sys with 3,2 order Pade approximation of time delay
  mfc_list = []
  control_law_list = []
  Q = np.ndarray([[100, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0] [0, 0, 0, 1]])
  R = np.ndarray([[1]])
  sensor_locations = [43.81, 76.2, 236.728, 609.6]  # dynamic P sensor locations from base, mm
    
  # Initialize sensor list
  sensor_list = [lab_hardware.StaticSensor(model=lambda y: sim_functions.static_model(y, K, offset),
                              location=0.0)]
  for loc in sensor_locations:
    sensor_list.append(lab_hardware.DynamicSensor(model=tf1, location=loc))
  # TODO figure out sensor transfer functions or models!
  
  # Initialize mass flow controller (MFC) list and control law list
  for K, zeta, wn, td in zip(K_mfcs, zeta_mfcs, wn_mfcs, td_mfcs):
    A, B, C = sim_functions.get_second_ord_matrices(K, zeta, wn, td)
    K_lqr = sim_functions.make_lqr_law(A, B, Q, R)
    mfc_list.append(lab_hardware.MFC(lambda t, y, u: sim_functions.system_state_update(t, y, u, A, B),
                                     lambda y: sim_functions.system_output(y, C),
                                     y0))
    control_law_list.append(lambda e:-K_lqr.dot(e))
    
  # Insert our first-order-modeled middle fuel MFC
  A, B, C = sim_functions.get_state_matrices(K_mid, tau_mid, td_mid)
  K_lqr = sim_functions.make_lqr_law(A, B, Q[:2, :2], R)  # smaller Q matrix, only 3 states
  mfc_list.insert(2, lab_hardware.MFC(lambda t, y, u: sim_functions.system_state_update(t, y, u, A, B),
                                     lambda y: sim_functions.system_output(y, C),
                                     y0[:2]))  # shorter y0, only 3 states
  control_law_list.insert(2, lambda e:-K_lqr.dot(e))
  
  # mfc and control law list should be in order: [air, pilot, middle, outer]
  # Initialize the combustor object
  combustor = lab_hardware.Combustor(p_atm, t_step, t_step_ctrl, sensor_list,
                                     mfc_list, control_law_list)
 def setUp(self):
   """Run repeated setup code once."""
   
   # Define class and local parameters
   unittest.TestCase.setUp(self)
   self.K_list = [3, 10, 99.21]
   self.tau_list = [0.3, 1]
   self.delay_list = [0.03, 0.1, 0.3]
   self.t_step = 0.01
   self.stop_time = 20.0
   self.input_val = 1.0
   self.t_step_ctrl = 0.1
   self.zeta = 0.7054  # air MFC damping ratio
   self.wn = 1.3501  # air MFC natural frequency, rad/s
   self.td = 1.8  # air MFC time delay, sec
   self.y0_1 = [0]
   self.y0_2 = [0] * 3  # for first-order model
   self.y0_3 = [0] * 4  # for second-order model
   A, B, self.C = sim_functions.get_state_matrices(self.K_list[1],
                                              self.tau_list[-1],
                                              self.delay_list[0])
   A2, B2, self.C2 = sim_functions.get_second_ord_matrices(self.K_list[-1],
                                                           self.zeta, self.wn,
                                                           self.td)
   self.Kp_list = [4.0, 5.0]
   self.mass_flow_des = [4.0, 2.0]
   self.std = 1.0
   self.Ks = 2.0  # filter static gain (?)
   Q = 1e-5 * np.identity(A2.shape[0])  # process noise covariance
   R = self.std  # measurement noise covariance
   self.P = Q  # initial estimate of error covariance
   self.offset = 0.0
   mean = 0.0
   
   # Define objects
   self.test_mfc1 = lab_hardware.MFC(lambda t, y, u: test_ode(t, y, u, self.K_list[1], self.tau_list[-1]),
                                     lambda x: x[0], self.y0_1)
   self.test_mfc2 = lab_hardware.MFC(lambda t, y, u: sim_functions.system_state_update(t, y, u, A, B),
                                     lambda y: sim_functions.system_output(y, self.C),
                                     self.y0_2)
   self.test_mfc3 = lab_hardware.MFC(lambda t, y, u: sim_functions.system_state_update(t, y, u, A2, B2),
                                     lambda y: sim_functions.system_output(y, self.C2),
                                     self.y0_3)
   self.mfc_list = [lab_hardware.MFC(lambda t, y, u: test_ode(t, y, u, K, tau),
                                     lambda x: x[0], self.y0_1)
                    for K, tau in zip(self.K_list, self.tau_list)]
   self.test_KF = lab_hardware.KalmanFilter(A2, B2, self.Ks * self.C2, Q, R, self.P)
   self.test_sensor = lab_hardware.StaticSensor(lambda y: sim_functions.static_model(y, self.Ks, self.offset, mean, self.std),
                                                1.0)