Browse Source

lazy and controller semantic adaptations

Cláudio Gomes 4 years ago
parent
commit
b31b7668d9

+ 73 - 0
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.tests/input/power_window_case_study/controller.sa

@@ -0,0 +1,73 @@
+module Controller_SA
+
+semantic adaptation reactive moore ControllerSA controller_sa
+at "./path/to/ControllerSA.fmu"
+
+	for inner fmu LazySA lazy
+	at "./path/to/LazySA.fmu"
+	with input ports obj_detected, passenger_up, passenger_down, passenger_stop, driver_up, driver_down, driver_stop
+	with output ports up, down, stop
+
+input ports armature_current -> lazy.obj_detected, 
+			passenger_up -> lazy.passenger_up, 
+			passenger_down -> lazy.passenger_down,
+			passenger_stop -> lazy.passenger_stop,
+			driver_up -> lazy.driver_up, 
+			driver_down -> lazy.driver_down,
+			driver_stop -> lazy.driver_stop
+
+output ports	u,
+				d
+
+param	RTOL := 0.0001,
+		ATOL := 1e-8,
+		T := 5.0,
+		INIT_V := 0.0;
+
+control var	c := false,
+			p_v := INIT_V;
+control rules {
+	var step_size := H;
+	var aux_obj_detected := false;
+	var crossedTooFar := false;
+	if ((not is_close(p_v, T, RTOL, ATOL) and p_v < T)
+				and (not is_close(f_v, T, RTOL, ATOL) and f_v > T)) {
+		crossedTooFar := true;
+		var negative_value := p_v - T;
+		var positive_value := f_v - T;
+		step_size := (H * (- negative_value)) / (positive_value - negative_value);
+	} else {
+		if ((not is_close(p_v, T, RTOL, ATOL) and p_v < T)
+					and is_close(f_v, T, RTOL, ATOL )) { 
+			c := true;
+		}
+	}
+	
+	if (not crossedTooFar){
+		step_size := do_step(lazy, t, H);
+	}
+	
+	if (is_close(step_size, H, RTOL, ATOL)) {
+		p_v := f_v;
+	}
+	return step_size;
+}
+
+in var	f_v := INIT_V;
+in rules {
+	true -> {
+		f_v := controller_sa.armature_current;
+	} --> {
+		lazy.obj_detected := c;
+	};
+}
+
+out rules {
+	lazy.up -> { } --> {controller_sa.u := 1.0; };
+	not lazy.up -> { } --> {controller_sa.u := 0.0; };
+	
+	lazy.down -> { } --> {controller_sa.d := 1.0; };
+	not lazy.down -> { } --> {controller_sa.d := 0.0; };
+	
+	lazy.stop -> { } --> {controller_sa.u := 0.0 ; controller_sa.d := 0.0; };
+}

+ 80 - 0
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.tests/input/power_window_case_study/controller_sa_commented.sa

@@ -0,0 +1,80 @@
+module Controller_SA
+
+semantic adaptation reactive moore ControllerSA controller_sa
+at "./path/to/ControllerSA.fmu"
+
+	for inner fmu LazySA lazy
+	at "./path/to/LazySA.fmu"
+	with input ports obj_detected, passenger_up, passenger_down, passenger_stop, driver_up, driver_down, driver_stop
+	with output ports up, down, stop
+
+/*
+At some point in the future, we support for simple wildcars in the input ports.
+According to Casper and Kenneth, some FMUs have thousands of ports...
+*/
+input ports armature_current -> lazy.obj_detected, 
+			passenger_up -> lazy.passenger_up, // You could write passenger_* here.
+			passenger_down -> lazy.passenger_down,
+			passenger_stop -> lazy.passenger_stop,
+			driver_up -> lazy.driver_up, // You could write driver_* here.
+			driver_down -> lazy.driver_down,
+			driver_stop -> lazy.driver_stop
+
+output ports	u,
+				d
+
+param	REL_TOL := 0.0001,
+		ABS_TOL := 1e-8,
+		CROSSING := 5.0,
+		INIT_ARMATURE_CURRENT := 0.0;
+
+control var	aux_obj_detected := 0,
+			previous_arm_current := INIT_ARMATURE_CURRENT;
+control rules {
+	var step_size := H;
+	var aux_obj_detected := false;
+	var crossedTooFar := false;
+	if ((not is_close(previous_arm_current, CROSSING, REL_TOL, ABS_TOL) and previous_arm_current < CROSSING)
+				and (not is_close(future_arm_current, CROSSING, REL_TOL, ABS_TOL) and future_arm_current > CROSSING)) { // crossing, but not within tolerance
+		crossedTooFar := true;
+		var negative_value := previous_arm_current - CROSSING;
+		var positive_value := future_arm_current - CROSSING;
+		step_size := (H * (- negative_value)) / (positive_value - negative_value);
+	} else {
+		if ((not is_close(previous_arm_current, CROSSING, REL_TOL, ABS_TOL) and previous_arm_current < CROSSING)
+					and is_close(future_arm_current, CROSSING, REL_TOL, ABS_TOL )) { // crossing within tolerance found
+			aux_obj_detected := true;
+		}
+	}
+	
+	if (not crossedTooFar){
+		step_size := do_step(lazy, t, H);
+	}
+	
+	if (is_close(step_size, H, REL_TOL, ABS_TOL)) {
+		// Step accepted, so store the known input.
+		// We cannot store the armature current at the in rules because we may not accept the step and because they may be called multiple times. 
+		// If that happens, we want to still have the old value of armature current, to compare it with the new one.
+		previous_arm_current := future_arm_current;
+	}
+	return step_size;
+}
+
+in var	future_arm_current := INIT_ARMATURE_CURRENT;
+in rules {
+	true -> {
+		future_arm_current := armature_current;
+	} --> {
+		obj_detected := aux_obj_detected; // Sets this input to the FMU 
+	};
+}
+
+out rules {
+	lazy.up -> { } --> {u := 1.0; };
+	not lazy.up -> { } --> {u := 0.0; };
+	
+	lazy.down -> { } --> {d := 1.0; };
+	not lazy.down -> { } --> {d := 0.0; };
+	
+	lazy.stop -> { } --> {u := 0.0 ; d := 0.0; };
+}

+ 27 - 1
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.tests/input/power_window_case_study/lazy.sa

@@ -10,16 +10,26 @@ at "./path/to/LazySA.fmu"
 
 input ports obj_detected -> controller.obj_detected
 
+output ports up, down, stop
+
+param 	INIT_UP := 0.0,
+		INIT_DOWN := 0.0,
+		INIT_STOP := 0.0;
+
 control var	tn := -1.0,
-			tl := -1.0;
+			tl := -1.0,
+			refresh_outputs := true;
 
 control rules {
 	if (tl < 0.0){
 		tl := t;
 	}
 	
+	refresh_outputs := false;
+	
 	var step_size := min(H, tn - t); 
 	if (lazy_sa.obj_detected or (t+H) >= tn){
+		refresh_outputs := true; 
 		var step_to_be_done := (t+H-tl);
 		var step_done := do_step(controller, t, step_to_be_done); 
 		tn := tl + step_done + get_next_time_step(controller); 
@@ -30,3 +40,19 @@ control rules {
 	return step_size;
 }
 
+out var	stored_up := INIT_UP,
+		stored_down := INIT_DOWN,
+		stored_stop := INIT_STOP;
+out rules{
+	 true -> {
+		if (refresh_outputs){
+			stored_up := controller.up;
+			stored_down := controller.down;
+			stored_stop := controller.stop;
+		}
+	} --> {
+		lazy_sa.up := stored_up;
+		lazy_sa.down := stored_down;
+		lazy_sa.stop := stored_stop;
+	};
+}

+ 35 - 1
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.tests/input/power_window_case_study/lazy_sa_commented.sa

@@ -11,11 +11,19 @@ at "./path/to/LazySA.fmu"
 /*
  * We only need to declare one input port: the one we are interested in.
  * The others (both input and output ports) are bound by assumption.
+ * In addition, we do not need to do anything about the outputs of the inner FMU, because they are zero order holded by default.
  */
 input ports obj_detected -> controller.obj_detected
 
+output ports up, down, stop
+
+param 	INIT_UP := 0.0,
+		INIT_DOWN := 0.0,
+		INIT_STOP := 0.0;
+
 control var	tn := -1.0,
-			tl := -1.0;
+			tl := -1.0,
+			refresh_outputs := true;
 
 control rules {
 	// This initialisation covers simulations that start at a non-zero time.
@@ -23,13 +31,23 @@ control rules {
 		tl := t;
 	}
 	
+	refresh_outputs := false;
+	
 	var step_size := min(H, tn - t); // In case tn < t, this ensures that the controller will be run at the right time.
 	// Note that the expression lazy_sa.obj_detected gets replaced by the corresponding storage var in the canonical version.
 	if (lazy_sa.obj_detected or (t+H) >= tn){
+		refresh_outputs := true; // This is used in the mapOut rules, to refresh the outputs.
 		var step_to_be_done := (t+H-tl);
 		var step_done := do_step(controller, t, step_to_be_done); // calls the mapIn function that will take care of forwarding the values of the input ports to the internal FMU.
 		// We calculate these as if step_done == step_to_be_done. If that is not the case, a rollback will be done anyway.
 		tn := tl + step_done + get_next_time_step(controller); // calculates the next time step that is tolerated by the controller.
+		/*
+			The get_next_time_step(controller) function is equivalent to the following snippet:
+			save_state(controller);
+			internal_transition := do_step(controller, last_execution_time(controller), MAX);
+			next_time_step := last_execution_time(controller) + internal_transition;
+			rollback(controller);
+		 */
 		// This is the actual step size taken, from the outside world:
 		step_size := tl + step_done - t; // assert step_size <= H
 		tl := tl + step_done; // assert tl == t+H
@@ -38,3 +56,19 @@ control rules {
 	return step_size;
 }
 
+out var	stored_up := INIT_UP,
+		stored_down := INIT_DOWN,
+		stored_stop := INIT_STOP;
+out rules{
+	 true -> {
+		if (refresh_outputs){
+			stored_up := controller.up;
+			stored_down := controller.down;
+			stored_stop := controller.stop;
+		}
+	} --> {
+		lazy_sa.up := stored_up;
+		lazy_sa.down := stored_down;
+		lazy_sa.stop := stored_stop;
+	};
+}