def __init__(self, name, num_rtol, num_atol, START_STEP_SIZE, FMU_START_RATE): self._num_rtol = num_rtol self._num_atol = num_atol self._max_iterations = 100 self._power = PowerFMU("power", num_rtol, num_atol, START_STEP_SIZE / FMU_START_RATE, J=0.085, b=5, K=7.45, R=0.15, L=0.036, V_a=12) self.omega = self._power.omega self.theta = self._power.theta self._window = WindowFMU("window", num_rtol, num_atol, START_STEP_SIZE / FMU_START_RATE, r=0.11, b=10) self._obstacle = ObstacleFMU("obstacle", num_rtol, num_atol, START_STEP_SIZE / FMU_START_RATE, c=1e5, fixed_x=0.45) self.up = self._power.up self.down = self._power.down input_vars = [self.down, self.up] self.i = self._power.i self.omega = self._power.omega self.theta = self._power.theta self.x = self._window.x self.F = self._obstacle.F state_vars = [self.i, self.omega, self.theta, self.x, self.F] algebraic_functions = {} AbstractSimulationUnit.__init__(self, name, algebraic_functions, state_vars, input_vars)
return 1.0 if time < 6 else 0.0 def env_down(time): return 0.0 if time < 6 else 1.0 START_STEP_SIZE = 0.001 FMU_START_RATE = 10 STOP_TIME = 1.0 power = PowerFMU("power", 1e-08, 1e-08, START_STEP_SIZE / FMU_START_RATE, J=0.085, b=5, K=7.45, R=0.15, L=0.036, V_a=12) window = WindowFMU("window", 1e-08, 1e-08, START_STEP_SIZE / FMU_START_RATE, r=0.11, b=10) power.enterInitMode() window.enterInitMode()
l.setLevel(logging.DEBUG) START_STEP_SIZE = 0.001 FMU_START_RATE = 1 STOP_TIME = 6 environment = EnvironmentStatechartFMU_CTInOut("env", NUM_RTOL, NUM_ATOL) controller = DriverControllerStatechartFMU_CTInOut("controller", NUM_RTOL, NUM_ATOL) power = PowerFMU("power", NUM_RTOL, NUM_ATOL, START_STEP_SIZE / FMU_START_RATE, J=0.085, b=5, K=7.45, R=0.15, L=0.036, V_a=12) armature_threshold = 5 adapt_armature = InacurateControllerArmatureAdaptation_CT( "arm_adapt", NUM_RTOL, NUM_ATOL, armature_threshold, True) window = WindowFMU("window", NUM_RTOL, NUM_ATOL, START_STEP_SIZE / FMU_START_RATE, r=0.11, b=10)
l.setLevel(logging.DEBUG) def env_up(time): return 1.0 if time < 6 else 0.0 def env_down(time): return 0.0 if time < 6 else 1.0 power = PowerFMU("power", 1e-08, 1e-05, 0.001, J=0.085, b=5, K=1.8, R=0.15, L=0.036, V_a=12) power.enterInitMode() power.setValues( 0, 0, { power.i: 0.0, power.omega: 0.0, power.theta: 0.0, power.tau: 0.0, power.up: env_up(0.0), power.down: env_down(0.0)
class AlgebraicAdaptation_Power_Window_Obstacle(AbstractSimulationUnit): """ This is the adaptation that realizes the strong coupling between the power, window, and obstacle units. """ def __init__(self, name, num_rtol, num_atol, START_STEP_SIZE, FMU_START_RATE): self._num_rtol = num_rtol self._num_atol = num_atol self._max_iterations = 100 self._power = PowerFMU("power", num_rtol, num_atol, START_STEP_SIZE / FMU_START_RATE, J=0.085, b=5, K=7.45, R=0.15, L=0.036, V_a=12) self.omega = self._power.omega self.theta = self._power.theta self._window = WindowFMU("window", num_rtol, num_atol, START_STEP_SIZE / FMU_START_RATE, r=0.11, b=10) self._obstacle = ObstacleFMU("obstacle", num_rtol, num_atol, START_STEP_SIZE / FMU_START_RATE, c=1e5, fixed_x=0.45) self.up = self._power.up self.down = self._power.down input_vars = [self.down, self.up] self.i = self._power.i self.omega = self._power.omega self.theta = self._power.theta self.x = self._window.x self.F = self._obstacle.F state_vars = [self.i, self.omega, self.theta, self.x, self.F] algebraic_functions = {} AbstractSimulationUnit.__init__(self, name, algebraic_functions, state_vars, input_vars) def _isClose(self, a, b): return numpy.isclose(a, b, self._num_rtol, self._num_atol) def _biggerThan(self, a, b): return not numpy.isclose(a, b, self._num_rtol, self._num_atol) and a > b def _doInternalSteps(self, time, step, iteration, step_size): l.debug(">%s._doInternalSteps(%f, %d, %d, %f)", self._name, time, step, iteration, step_size) assert step_size > 0.0, "step_size too small: {0}".format(step_size) #assert self._biggerThan(step_size, 0), "step_size too small: {0}".format(step_size) assert iteration == 0, "Fixed point iterations not supported outside of this component." converged = False internal_iteration = 0 cOut = self.getValues(step, iteration, [self.up, self.down]) wOut = self._window.getValues(step - 1, iteration, [self._window.x, self._window.tau]) pOut = None while not converged and internal_iteration < self._max_iterations: self._power.setValues( step, iteration, { self._power.tau: wOut[self._window.tau], # Delayed input self._power.up: cOut[self.up], self._power.down: cOut[self.down] }) self._power.doStep(time, step, iteration, step_size) pOut = self._power.getValues( step, iteration, [self._power.omega, self._power.theta, self._power.i]) self._obstacle.setValues( step, iteration, {self._obstacle.x: wOut[self._window.x]}) # Delayed input self._obstacle.doStep(time, step, iteration, step_size) oOut = self._obstacle.getValues(step, iteration, [self._obstacle.F]) self._window.setValues( step, iteration, { self._window.omega_input: pOut[self._power.omega], self._window.theta_input: pOut[self._power.theta], self._window.F_obj: oOut[self._obstacle.F] }) self._window.doStep(time, step, iteration, step_size) wOut_corrected = self._window.getValues( step, iteration, [self._window.x, self._window.tau]) l.debug("Iteration step completed:") l.debug("wOut=%s;", wOut) l.debug("wOut_corrected=%s.", wOut_corrected) if self._isClose(wOut[self._window.x], wOut_corrected[self._window.x]) \ and self._isClose(wOut[self._window.tau], wOut_corrected[self._window.tau]): converged = True internal_iteration = internal_iteration + 1 wOut = wOut_corrected if converged: l.debug("Fixed point found after %d iterations", internal_iteration) else: l.debug("Fixed point not found after %d iterations", internal_iteration) raise RuntimeError("Fixed point not found") AbstractSimulationUnit.setValues( self, step, iteration, { self.i: pOut[self._power.i], self.theta: pOut[self._power.theta], self.omega: pOut[self._power.omega], self.x: wOut[self._window.x], self.F: oOut[self._obstacle.F] }) l.debug("<%s._doInternalSteps() = (%s, %d)", self._name, STEP_ACCEPT, step_size) return (STEP_ACCEPT, step_size) def setValues(self, step, iteration, values): l.debug( ">%s.AlgebraicAdaptation_Power_Window_Obstacle.setValues(%d, %d, %s)", self._name, step, iteration, values) # Filter just the inputs. inputs = {self.up: values[self.up], self.down: values[self.down]} AbstractSimulationUnit.setValues(self, step, iteration, inputs) if self._mode == INIT_MODE: # Initialize the internal FMUs and compute the value of the armature. l.debug("Initializing strong component...") step = iteration = 0 wOut_tau_delayed = 0.0 wOut_x_delayed = 0.0 # Set power inputs (or initial state, given by values) self._power.setValues(step, iteration, values) self._power.setValues(step, iteration, {self._power.tau: wOut_tau_delayed}) # Get power initial outputs pOut = self._power.getValues( step, iteration, [self._power.omega, self._power.theta, self._power.i]) # Set obstacle initial inputs # Assume they are zero because the outputs of the window are delayed. self._obstacle.setValues(step, iteration, {self._obstacle.x: wOut_x_delayed}) # Get obstacle outputs oOut = self._obstacle.getValues(step, iteration, [self._obstacle.F]) # Set window inputs self._window.setValues( step, iteration, { self._window.omega_input: pOut[self._power.omega], self._window.theta_input: pOut[self._power.theta], self._window.F_obj: oOut[self._obstacle.F] }) # Get window outputs wOut = self._window.getValues(step, iteration, [self._window.x, self._window.tau]) # Set corrected power windows self._power.setValues( step, iteration, { self._power.tau: wOut[self._window.tau] # Delayed input from window }) # We know that convergence is easily achieved for this initialisation assert self._isClose(wOut[self._window.tau], wOut_tau_delayed) assert self._isClose(wOut[self._window.x], wOut_x_delayed) # Record the outputs AbstractSimulationUnit.setValues( self, step, iteration, { self.i: pOut[self._power.i], self.theta: pOut[self._power.theta], self.omega: pOut[self._power.omega], self.x: wOut[self._window.x], self.F: oOut[self._obstacle.F] }) l.debug("Strong component initialized.") l.debug("<%s.AlgebraicAdaptation_Power_Window_Obstacle.setValues()", self._name) def enterInitMode(self): l.debug( ">%s.AlgebraicAdaptation_Power_Window_Obstacle.enterInitMode()", self._name) AbstractSimulationUnit.enterInitMode(self) self._power.enterInitMode() self._window.enterInitMode() self._obstacle.enterInitMode() l.debug( "<%s.AlgebraicAdaptation_Power_Window_Obstacle.enterInitMode()", self._name) def exitInitMode(self): l.debug(">%s.AlgebraicAdaptation_Power_Window_Obstacle.exitInitMode()", self._name) AbstractSimulationUnit.exitInitMode(self) self._power.exitInitMode() self._window.exitInitMode() self._obstacle.exitInitMode() l.debug("<%s.AlgebraicAdaptation_Power_Window_Obstacle.exitInitMode()", self._name)
MIN_STEPS_BEFORE_INCREASE_STEP_SIZE = 10 STEP_SIZE_INCREASE_RATE = 10 # e.g, 10% FMU_START_RATE = 10 STOP_TIME = 6 environment = EnvironmentStatechartFMU_CTInOut("env", NUM_RTOL, NUM_ATOL) controller = DriverControllerStatechartFMU_CTInOut("controller", NUM_RTOL, NUM_ATOL) power = PowerFMU("power", NUM_RTOL, NUM_ATOL, START_STEP_SIZE / FMU_START_RATE, J=0.085, b=5, K=7.45, R=0.15, L=0.036, V_a=12) armature_threshold = 5 # This was the initial threshold, but did not work. adapt_armature = AccurateControllerArmatureAdaptation("arm_adapt", NUM_RTOL, NUM_ATOL, armature_threshold, True) window = WindowFMU("window", NUM_RTOL, NUM_ATOL, START_STEP_SIZE / FMU_START_RATE, r=0.11,
l = logging.getLogger() l.setLevel(logging.DEBUG) START_STEP_SIZE = 0.001 FMU_START_RATE = 10 STOP_TIME = 10; environment = EnvironmentStatechartFMU_Event("env", NUM_RTOL, NUM_ATOL) controller = DriverControllerStatechartFMU_Event("controller", NUM_RTOL, NUM_ATOL) power = PowerFMU("power", NUM_RTOL, NUM_ATOL, START_STEP_SIZE/FMU_START_RATE, J=0.085, b=5, K=1.8, R=0.15, L=0.036, V_a=12) armature_threshold = 20.0 adapt_armature = InacurateControllerArmatureAdaptation_Event("arm_adapt", NUM_RTOL, NUM_ATOL, armature_threshold, True) adapt_power_input = PowerInputAdaptation_Event("power_adapt") window = WindowFMU("window", NUM_RTOL, NUM_ATOL, START_STEP_SIZE/FMU_START_RATE, J=0.085, r=0.017, b = 150, c = 1e3) # c = 1e5 makes this an unstable system.
def __init__(self, name, num_rtol, num_atol, start_rate, start_step_size): self.in_power_up = "in_power_up" self.in_power_down = "in_power_down" self.out_power_i = "out_power_i" self.out_window_x = "out_window_x" self.out_obs_F = "out_obs_F" power = PowerFMU(name + ":" + "power", num_rtol, num_atol, start_step_size / start_rate, J=0.085, b=5, K=7.45, R=0.15, L=0.036, V_a=12) window = WindowFMU(name + ":" + "window", num_rtol, num_atol, start_step_size / start_rate, r=0.11, b=10) obstacle = ObstacleFMU(name + ":" + "obstacle", num_rtol, num_atol, start_step_size / start_rate, c=1e5, fixed_x=0.45) delay_reaction_torque = DecoupleAdaptation(name + ":" + "delay_reaction_torque") delay_height = DecoupleAdaptation(name + ":" + "delay_height") zoh_up = ZOHAdaptation(name + ":" + "zoh_up", "in_ext_up", "out_ext_up") zoh_down = ZOHAdaptation(name + ":" + "zoh_down", "in_ext_down", "out_ext_down") units = [ power, # 0 window, # 1 obstacle, # 2 delay_height, # 3 delay_reaction_torque, # 4 zoh_up, # 5 zoh_down # 6 ] order = [5, 6, 3, 4, 2, 0, 1] initial_state = [{ power.omega: 0.0, power.theta: 0.0, power.i: 0.0 }, None, None, { delay_height.out_v: 0.0 }, { delay_reaction_torque.out_v: 0.0 }, None, None] def coupling_power(y): zohUpOut = y[5] zohDownOut = y[6] dtauOut = y[4] return { power.up: zohUpOut[zoh_up.output_var], power.down: zohDownOut[zoh_down.output_var], power.tau: dtauOut[delay_reaction_torque.out_v] } def coupling_window(y): pOut = y[0] oOut = y[2] return { window.omega_input: pOut[power.omega], window.theta_input: pOut[power.theta], window.F_obj: oOut[obstacle.F] } def coupling_obstacle(y): dheightOut = y[3] return {obstacle.x: dheightOut[delay_height.out_v]} def coupling_delay_torque(y): wOut = y[1] return { delay_reaction_torque.in_v: wOut[window.tau] } if wOut != None else None def coupling_delay_height(y): wOut = y[1] return { delay_height.in_v: wOut[window.x] } if wOut != None else None def coupling_zoh_up(y): last_known_inputs = self._inputs output = None if last_known_inputs != None: output = { zoh_up.input_var: last_known_inputs[self.in_power_up] } return output def coupling_zoh_down(y): last_known_inputs = self._inputs output = None if last_known_inputs != None: output = { zoh_down.input_var: last_known_inputs[self.in_power_down] } return output def external_coupling(y): pOut = y[0] wOut = y[1] oOut = y[2] return { self.out_power_i: pOut[power.i], self.out_window_x: wOut[window.x], self.out_obs_F: oOut[obstacle.F] } couplings = [ coupling_power, coupling_window, coupling_obstacle, coupling_delay_height, coupling_delay_torque, coupling_zoh_up, coupling_zoh_down ] MultiRateAdaptationUnit.__init__(self, name, num_rtol, num_atol, order, units, couplings, external_coupling, start_rate, initial_state)