controller_sa_allInOne.sa 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. module Controller_SA
  2. /*
  3. * This file is not used in the case study.
  4. * The adaptations it does have been split.
  5. */
  6. semantic adaptation reactive moore ControllerSA controller_sa
  7. at "./path/to/ControllerSA.fmu"
  8. for inner fmu Controller controller
  9. at "./path/to/Controller.fmu"
  10. with input ports obj_detected, passenger_up, passenger_down, passenger_stop, driver_up, driver_down, driver_stop
  11. with output ports up, down, stop
  12. /*
  13. At some point in the future, we support for simple wildcars in the input ports.
  14. According to Casper and Kenneth, some FMUs have thousands of ports...
  15. */
  16. input ports armature_current -> controller.obj_detected,
  17. passenger_up -> controller.passenger_up, // You could write passenger_* here.
  18. passenger_down -> controller.passenger_down,
  19. passenger_stop -> controller.passenger_stop,
  20. driver_up -> controller.driver_up, // You could write driver_* here.
  21. driver_down -> controller.driver_down,
  22. driver_stop -> controller.driver_stop
  23. output ports u,
  24. d
  25. param REL_TOL := 0.0001,
  26. ABS_TOL := 1e-8,
  27. CROSSING := 5.0,
  28. INIT_ARMATURE_CURRENT := 0.0,
  29. INIT_U := 0.0,
  30. INIT_D := 0.0;
  31. control var aux_obj_detected := 0,
  32. get_next_step := true,
  33. previous_arm_current := INIT_ARMATURE_CURRENT;
  34. control rules {
  35. var step_size := H;
  36. aux_obj_detected := false;
  37. if ((not is_close(previous_arm_current, CROSSING, REL_TOL, ABS_TOL) and previous_arm_current < CROSSING)
  38. and (not is_close(future_arm_current, CROSSING, REL_TOL, ABS_TOL) and future_arm_current > CROSSING)) { // crossing, but not within tolerance
  39. var negative_value := previous_arm_current - CROSSING;
  40. var positive_value := future_arm_current - CROSSING;
  41. step_size := (H * (- negative_value)) / (positive_value - negative_value);
  42. } else {
  43. if ((not is_close(previous_arm_current, CROSSING, REL_TOL, ABS_TOL) and previous_arm_current < CROSSING)
  44. and is_close(future_arm_current, CROSSING, REL_TOL, ABS_TOL )) { // crossing within tolerance found
  45. aux_obj_detected := true;
  46. }
  47. }
  48. if (aux_obj_detected == true or t >= next_time_step) {
  49. var aux_h := do_step(controller, t-e, e); // do a step, then decide next internal transition
  50. //assert aux_h == e; this must always be the case, otherwise it is better not to use the timed transition adaptation.
  51. get_next_step := true; // next time the setValues is called, the internal transition will be set again.
  52. } else {
  53. get_next_step := false;
  54. }
  55. if (is_close(step_size, H, REL_TOL, ABS_TOL)) {
  56. // Step accepted, so store the known input.
  57. // 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.
  58. // If that happens, we want to still have the old value of armature current, to compare it with the new one.
  59. previous_arm_current := future_arm_current;
  60. }
  61. return step_size;
  62. }
  63. in var next_time_step := -1.0,
  64. future_arm_current := INIT_ARMATURE_CURRENT;
  65. in rules {
  66. get_next_step -> {
  67. next_time_step := get_next_time_step(controller) + last_execution_time(controller);
  68. /*
  69. The get_next_time_step(controller) function is equivalent to the following snippet:
  70. save_state(controller);
  71. internal_transition := do_step(controller, last_execution_time(controller), MAX);
  72. next_time_step := last_execution_time(controller) + internal_transition;
  73. rollback(controller);
  74. */
  75. } --> { };
  76. true -> {
  77. future_arm_current := armature_current;
  78. } --> {
  79. obj_detected := aux_obj_detected; // Sets this input to the FMU
  80. };
  81. }
  82. out var stored_up := INIT_U,
  83. stored_down := INIT_D;
  84. out rules {
  85. true -> {
  86. /*
  87. Previously, there was this intruction here:
  88. internal_transition := get_next_time_step(controller) + t
  89. However, it cannot be here, since there is no guarantee in the control rules block, that the doStep of the controller will be called.
  90. */
  91. } --> {};
  92. /*
  93. What does "otherwise var" mean?
  94. Suppose I have the following rules:
  95. var1 == true and var2 == false -> ...
  96. otherwise var1 -> ...
  97. controller.up == true -> { stored_up := 1; } --> { };
  98. otherwise up -> { } --> { };
  99. down == true -> { down := 1; } --> { };
  100. otherwise down -> { } --> { };
  101. stop == true -> { up := 0; down := 0; } --> { };
  102. otherwise stop -> { } --> { };
  103. true -> { up := stored_up; stored_up := up; } --> { };
  104. true -> { down := stored_down; stored_down := down; } --> { };
  105. */
  106. controller.up -> {stored_up := 1; } --> {u := stored_up; };
  107. not controller.up -> {stored_up := 0; } --> {u := stored_up; };
  108. controller.down -> {stored_down := 1; } --> {d := stored_down; };
  109. not controller.down -> {stored_down := 0; } --> {d := stored_down; };
  110. controller.stop -> {stored_down := 0; stored_up :=0; } --> {u := stored_up ; d := stored_down; };
  111. }