Browse Source

added ctrl test and fixed ambiguity between control var and control block.

Cláudio Gomes 4 years ago
parent
commit
be5406f4be

+ 108 - 0
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.tests/input/power_window_case_study/window_obstacle_sa_flat.BASE.sa

@@ -0,0 +1,108 @@
+module WindowObstacleLoop_SA
+
+semantic adaptation reactive mealy WindowObstableLoopSA adaptedFMU
+at "./path/to/WindowObstableLoopSA.fmu"
+
+	for inner fmu WindowSA window_sa
+		at "./path/to/WindowSA.fmu"
+		with input ports displacement (rad), speed (rad/s), reaction_force (N)
+		with output ports disp (m), tau (N.m)
+	
+	for inner fmu Obstacle obstacle
+		at "./path/to/Obstacle.fmu"
+		with input ports disp (m)
+		with output ports reaction_force (m)
+	
+	/*
+	This is the information that was missing before: how the semantic adaptation window_sa, which is an FMU, connects to the obstacle FMU.
+	*/
+	with window_sa.disp -> obstacle.disp
+	with obstacle.reaction_force -> window_sa.reaction_force
+
+/*
+Declares the external ports of the semantic adaptation
+Notice that window_sa.displacement is a dangling input port, so an extra input port will exist in the adapted FMU.
+*/
+input ports speed
+output ports tau 
+
+param 	RATE := 10, 
+		MAXITER := 10, 
+		REL_TOL := 1e-05, 
+		ABS_TOL := 1e-05;
+
+ctrl var previous_speed := 0, future_speed := 0;
+control {
+	var inner_dt := H/RATE;
+	/*
+	The two instructions below need to be made, because previously they were made in the sa_in block, but multiple calls to the sa_in block would make them fail.
+	*/
+	previous_speed := future_speed;
+	future_speed := current_speed; // you cannot access input ports of the adapted FMU here.
+	
+	for (var iter in 0 .. RATE) { // multi-rate loop
+		var prev_disp := window_sa.disp;
+		var inner_time := t;
+		for (var iter in 0 .. MAXITER) {
+			save_state(obstacle);
+			save_state(window_sa);
+			do_step(obstacle,inner_time,inner_dt);
+			do_step(window_sa,inner_time,inner_dt);
+			
+			if (is_close(prev_disp, disp, REL_TOL, ABS_TOL)) {
+				break;
+			} else {
+				prev_disp := disp;
+				rollback(obstacle);
+				rollback(window_sa);
+			}
+			
+			/*
+			The above block of statements is equivalent to the following:
+			var obstacle_state := getState(obstacle)
+			var window_sa_state := getState(window_sa)
+			
+			obstacle.set("height", height)
+			obstacle.doStep(inner_time,h)
+			reaction_force := obstacle.get("reaction_force")
+			window_sa.set("reaction_force", reaction_force)
+			window_sa.doStep(inner_time,h)
+			height := window_sa.get("height")
+			if (is_close(prev_height, height, REL_TOL, ABS_TOL)) {
+				// The commits don't do anything, as far as I see. But they serve an analysis which ensures that states are correctly obtained and restored.
+				break;
+			} else {
+				prev_height := height;
+				obstacle.setState(obstacle_state);
+				window_sa.setState(window_sa_state);
+			}
+			*/
+		}
+		inner_time := t + inner_dt;	
+	}
+	return H;
+}
+
+in var current_speed := 0;
+in rules {
+	true -> {
+		/*
+		These instructions would violate the principle that multiple calls to setValues can be made:
+		previous_speed := future_speed;
+		future_speed := speed;
+		Upon execution, this block must call setValues of the original FMUs (window_sa and obstacle).
+		The correct thing then is to execute the next block and then do the setValues of the original FMUs.
+		*/
+		current_speed := speed;
+	} --> {
+		/*
+		This block will be called whenever any of the input ports that are unconnected in the original FMUs is read, in the control rules block.
+		The following variables are available in this block:
+			dt - In the control rules block, (t + dt) is the time that will be passed to the doStep function of the inner FMU. In the control rules block, this can be computed by doing dt := inner_time - t.
+			h - this is the communication step size that will be sent to the inner FMU.
+		
+		*/
+		window_sa.speed := previous_speed + (future_speed - previous_speed)*dt;
+	};
+}
+

+ 3 - 3
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.tests/input/power_window_case_study/window_sa.BASE.sa

@@ -43,13 +43,13 @@ In other words, the output at time t, only depends on the state at time t.
 
 	
 	/*
-	The definition for the wrappen FMU is now done here.
+	The definition for the wrapped FMU is now done here.
 	This is because, for adaptations that wrap multiple FMUs as well as other adaptations, the connection information cannot be fully completed in the senario description (see the window_obstacle.sa example).
 	*/
 	for inner fmu Window window
 		at "./path/to/WindowSA.fmu"
 		with input ports displacement (rad), speed (rad/s), reaction_force (N)
-		with output ports height (m), reaction_torque (N.m)
+		with output ports height (cm), reaction_torque (N.m)
 
 /*
 No need to have input ports declared for this model.
@@ -63,7 +63,7 @@ Declares two output ports, and specified how height is mapped to disp.
 Here, the units need to be specified, so that the conversion can take place.
 The units of disp can be either obtained from the scenario, or specified explicitly here.
 */
-output ports disp (cm)  <- height, tau
+output ports disp (m)  <- height, tau
 /*
 There are alternative ways that this can be interpreted:
 disp  := arbitrary_function(height) * 100 or arbitrary_function(height * 100) (they are not necessarily equal)

+ 1 - 1
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.tests/input/power_window_case_study/window_sa_canonical.BASE.sa

@@ -61,7 +61,7 @@ out rules {
 		stored_window_height := window.height;
 	} --> {
 		windowSA.tau := - stored_window_reaction_torque;
-		windowSA.disp := stored_window_height * 100;
+		windowSA.disp := stored_window_height / 100;
 	};
 }
 

+ 0 - 79
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.tests/input/window_sa_BASE.sa

@@ -1,79 +0,0 @@
-module Window_SA
-
-semantic adaptation reactive mealy WindowSA windowSA
-at "./path/to/WindowSA.fmu"
-
-/*
-Reactive means that the unit expects the following treatment:
-Supose the external master is at time t, and that there is an FMU f providing inputs to windowsa.
-Then,
-f.doStep(t, H) // f goes from t->t+H 
-u := f.getValues(...)
-windowsa.setValues(u) // Input provided from the future (t+H)
-windowsa.doStep(t, H) // windowsa goes from t->t+H
-v := windowsa.getValues(...)
-
-Delayed unit means that the unit expects the following treatment:
-Supose the external master is at time t, and that there is an FMU f providing inputs to windowsa.
-Then,
-pu := f.getValues(...)
-f.doStep(t, H) // f goes from t->t+H 
-windowsa.setValues(pu) // Input provided at the time t
-windowsa.doStep(t, H) // windowsa goes from t->t+H and does not need input at time (t+H)
-v := windowsa.getValues(...)
-
-
-Mealy unit means the following:
-windowsa.setValues(v1)  // values set at time t
-o1 = windowsa.getValues() // values set at time t
-assert v2 <> v1 // Assumption
-windowsa.setValues(v2)  // values set at time t
-o2 = windowsa.getValues() // values set at time t
-It is probably the case that o1 <> o2
-
-Moore unit means the following:
-windowsa.setValues(v1)  // values set at time t
-o1 = windowsa.getValues() // values set at time t
-assert v2 <> v1 // Assumption
-windowsa.setValues(v2)  // values set at time t
-o2 = windowsa.getValues() // values set at time t
-It must be the case that o1 == o2
-In other words, the output at time t, only depends on the state at time t.
-*/
-
-	
-	/*
-	The definition for the wrappen FMU is now done here.
-	This is because, for adaptations that wrap multiple FMUs as well as other adaptations, the connection information cannot be fully completed in the senario description (see the window_obstacle.sa example).
-	*/
-	for inner fmu Window window
-		at "./path/to/WindowSA.fmu"
-		with input ports displacement (rad), speed (rad/s), reaction_force (N)
-		with output ports height (m), reaction_torque (N.m)
-
-/*
-No need to have input ports declared for this model.
-Every input port of the original FMU will be automatically assumed to be an input port of the adapted FMU.
-
-If there is an input port window.p which is dangling, but is not declared here, then an input port windowsa.p will be created in the adapted FMU, and we will have that window.p -> windowsa.p.
-*/
-
-/*
-Declares two output ports, and specified how height is mapped to disp.
-Here, the units need to be specified, so that the conversion can take place.
-The units of disp can be either obtained from the scenario, or specified explicitly here.
-*/
-output ports disp (cm)  <- height, tau
-/*
-There are alternative ways that this can be interpreted:
-disp  := arbitrary_function(height) * 100 or arbitrary_function(height * 100) (they are not necessarily equal)
-We pick the first one, so what we have is this:
-aux_var := arbitrary_function(height);
-disp := aux_var*100; // This part never has to be coded.
-*/
-
-out rules {
-	true -> {} --> {
-		tau := -reaction_force;
-	};
-}

+ 1 - 0
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.tests/src/be/uantwerpen/ansymo/semanticadaptation/tests/SemanticAdaptationParsingTest.xtend

@@ -35,6 +35,7 @@ class SemanticAdaptationParsingTest extends AbstractSemanticAdaptationTest{
 //		print_ast(root)
 //	}
 
+	@Test def power_window__window_obstacle_sa_flat() { __parseNoErrors('input/power_window_case_study/window_obstacle_sa_flat.BASE.sa') }
 	@Test def power_window__window_sa() { __parseNoErrors('input/power_window_case_study/window_sa.BASE.sa') }
 	@Test def power_window__window_sa_canonical() { __parseNoErrors('input/power_window_case_study/window_sa_canonical.BASE.sa') }
 	@Ignore @Test def powerwindow_model_only() { __parseNoErrors('input/powerwindow_model_only.sa') }

+ 1 - 1
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation/examples/controller_sa.BASE.sa

@@ -37,7 +37,7 @@ in rules {
 		next_time_step := get_next_time_step(controller) + last_execution_time(controller); 
 		/*
 		The get_next_time_step(controller) function is equivalent to the following snippet:
-		transaction(controller);
+		save_state(controller);
 		internal_transition := do_step(controller, last_execution_time(controller), MAX);
 		next_time_step := last_execution_time(controller) + internal_transition;
 		rollback(controller);

+ 4 - 4
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation/src/be/uantwerpen/ansymo/semanticadaptation/SemanticAdaptation.xtext

@@ -111,13 +111,13 @@ InOutRules:
 	InRulesBlock | OutRulesBlock;
 
 InRulesBlock:
-	{InRulesBlock} ('in' globalvars+=Declaration)* 'in' 'rules' ('with' setting+=GeneralSetting (',' setting+=GeneralSetting)*)? '{' iterationvars+=Declaration* rules+=DataRule* '}';
+	{InRulesBlock} ('in' globalInVars+=Declaration)* 'in' 'rules' ('with' setting+=GeneralSetting (',' setting+=GeneralSetting)*)? '{' iterationvars+=Declaration* rules+=DataRule* '}';
 
 OutRulesBlock:
-	{OutRulesBlock} ('out' globalvars+=Declaration)* 'out' 'rules' ('with' setting+=GeneralSetting (',' setting+=GeneralSetting)*)? '{' iterationvars+=Declaration* rules+=DataRule* '}';
+	{OutRulesBlock} ('out' globalOutVars+=Declaration)* 'out' 'rules' ('with' setting+=GeneralSetting (',' setting+=GeneralSetting)*)? '{' iterationvars+=Declaration* rules+=DataRule* '}';
 
 ControlRuleBlock:
-	('control' globalvars+=Declaration)* rule=ControlRule; // TODO: multiple rules or just one?
+	('ctrl' globalCtrlVars+=Declaration)* rule=ControlRule; // TODO: multiple rules or just one?
 
 DataRule: // condition -> state transition --> output function
 	(((condition=RuleCondition "->" statetransitionfunction=StateTransitionFunction) | ConditionStateTransition | ConditionLessRule) ("-->" outputfunction=OutputFunction)? | AlgebraicLoopSolution) ';';
@@ -242,7 +242,7 @@ ParamDeclaration:
 ;
 
 SingleParamDeclaration:
-	name=ID ':=' expr=Expression ';'
+	name=ID ':=' expr=Expression
 ;
 
 ReturnStatement: