window_obstacle_sa.BASE.sa 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import Window_SA
  2. module WindowObstacle_SA
  3. semantic adaptation reactive mealy window_obstacle_sa
  4. /*
  5. Notice that we're importing the Window_SA module... that's where the window_sa FMU is defined.
  6. However, it is not clear where is the information that describes how the window_sa is connected to the obstacle.
  7. It is not in the PowerWindowModel module, nor in the Window_SA module.
  8. As a result, I would suggest that we are able to describe these connections within this semantic adaptation.
  9. */
  10. for fmu WindowSA window_sa
  11. at "./path/to/Window_sa.fmu"
  12. input ports displacement (rad), speed (rad/s), reaction_force (N)
  13. output ports disp (m), tau (N.m);
  14. for fmu Obstacle obstacle
  15. at "./path/to/Obstacle.fmu"
  16. input ports disp (m),
  17. output ports reaction_force (m);
  18. /*
  19. This is the information that was missing before: how the semantic adaptation window_sa, which is an FMU, connects to the obstacle FMU.
  20. */
  21. window_sa.disp -> obstacle.disp,
  22. obstacle.reaction_force -> window_sa.reaction_force;
  23. /*
  24. Declares the external ports of the semantic adaptation
  25. */
  26. input ports displacement, speed;
  27. output ports tau;
  28. control var previous_speed := 0;
  29. control var future_speed := 0;
  30. in var current_speed := 0;
  31. param RATE := 10;
  32. in rules {
  33. true -> {
  34. /*
  35. These instructions would violate the principle that multiple calls to setValues can be made:
  36. previous_speed := future_speed;
  37. future_speed := speed;
  38. Upon execution, this block must call setValues of the original FMUs (window_sa and obstacle).
  39. The correct thing then is to execute the next block and then do the setValues of the original FMUs.
  40. */
  41. current_speed := speed
  42. } --> {
  43. /*
  44. 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.
  45. The following variables are available in this block:
  46. 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.
  47. h - this is the communication step size that will be sent to the inner FMU.
  48. As previously described, the displacement input port is taken care of automatically by the declaration "displacement -> displacement" in the input ports.
  49. So the declaration would be equivalent to having this intruction in this block.
  50. displacement := displacement;
  51. */
  52. window_sa.speed := previous_speed + (future_speed - previous_speed)*dt;
  53. }
  54. }
  55. control rules {
  56. var h := H/RATE
  57. /*
  58. 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.
  59. */
  60. previous_speed := future_speed;
  61. future_speed := current_speed; // you cannot access input ports of the adapted FMU here.
  62. for (var iter in 0 .. RATE) { // multi-rate loop
  63. var prev_height := window_sa.height
  64. var inner_time := t
  65. for (var iter in 0 .. MAXITER) {
  66. transaction(obstacle) // Inspired by transactions in databases.
  67. transaction(window_sa)
  68. obstacle.doStep(inner_time,h)
  69. window_sa.doStep(inner_time,h)
  70. if (is_close(prev_height, height, REL_TOL, ABS_TOL)) {
  71. commit(obstacle);
  72. commit(window_sa);
  73. break;
  74. } else {
  75. prev_height := height;
  76. rollback(obstacle)
  77. rollback(window_sa)
  78. }
  79. /*
  80. The above block of statements is equivalent to the following:
  81. var obstacle_state := getState(obstacle)
  82. var window_sa_state := getState(window_sa)
  83. obstacle.set("height", height)
  84. obstacle.doStep(inner_time,h)
  85. reaction_force := obstacle.get("reaction_force")
  86. window_sa.set("reaction_force", reaction_force)
  87. window_sa.doStep(inner_time,h)
  88. height := window_sa.get("height")
  89. if (is_close(prev_height, height, REL_TOL, ABS_TOL)) {
  90. // 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.
  91. break;
  92. } else {
  93. prev_height := height;
  94. obstacle.setState(obstacle_state);
  95. window_sa.setState(window_sa_state);
  96. }
  97. */
  98. }
  99. var inner_time := t + h;
  100. }
  101. }