Material_DynamicFriction.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. """
  2. Copyright (c) Contributors to the Open 3D Engine Project.
  3. For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. SPDX-License-Identifier: Apache-2.0 OR MIT
  5. """
  6. # Test case ID : C4044459
  7. # Test Case Title : Verify the functionality of dynamic friction
  8. # fmt: off
  9. class Tests():
  10. enter_game_mode = ("Entered game mode", "Failed to enter game mode")
  11. find_ramp = ("Ramp entity found", "Ramp entity not found")
  12. find_box_zero = ("Box entity 'zero' found", "Box entity 'zero' not found")
  13. find_box_low = ("Box entity 'low' found", "Box entity 'low' not found")
  14. find_box_mid = ("Box entity 'mid' found", "Box entity 'mid' not found")
  15. find_box_high = ("Box entity 'high' found", "Box entity 'high' not found")
  16. box_at_rest_start_zero = ("Box 'zero' began test motionless", "Box 'zero' did not begin test motionless")
  17. box_at_rest_start_low = ("Box 'low' began test motionless", "Box 'low' did not begin test motionless")
  18. box_at_rest_start_mid = ("Box 'mid' began test motionless", "Box 'mid' did not begin test motionless")
  19. box_at_rest_start_high = ("Box 'high' began test motionless", "Box 'high' did not begin test motionless")
  20. box_was_pushed_zero = ("Box 'zero' moved", "Box 'zero' did not move before timeout")
  21. box_was_pushed_low = ("Box 'low' moved", "Box 'low' did not move before timeout")
  22. box_was_pushed_mid = ("Box 'mid' moved", "Box 'mid' did not move before timeout")
  23. box_was_pushed_high = ("Box 'high' moved", "Box 'high' did not move before timeout")
  24. box_at_rest_end_zero = ("Box 'zero' came to rest", "Box 'zero' did not come to rest before timeout")
  25. box_at_rest_end_low = ("Box 'low' came to rest", "Box 'low' did not come to rest before timeout")
  26. box_at_rest_end_mid = ("Box 'mid' came to rest", "Box 'mid' did not come to rest before timeout")
  27. box_at_rest_end_high = ("Box 'high' came to rest", "Box 'high' did not come to rest before timeout")
  28. distance_ordered = ("Boxes with greater dynamic friction traveled shorter", "Boxes with greater dynamic friction traveled further")
  29. exit_game_mode = ("Exited game mode", "Couldn't exit game mode")
  30. # fmt: on
  31. def Material_DynamicFriction():
  32. """
  33. Summary:
  34. Runs an automated test to ensure that greater dynamic friction coefficient settings on a physX material results in
  35. rigidbody entities (with that material) that require a greater force in order to remain in motion
  36. Level Description:
  37. Four boxes sit on a horizontal 'ramp'. The boxes are identical, save for their physX material:
  38. A new material library was created with 4 materials and their dynamic friction coefficient:
  39. zero_dynamic_friction: 0.00
  40. low_dynamic_friction: 0.50
  41. mid_dynamic_friction: 1.00
  42. high_dynamic_friction: 1.50
  43. Each material is identical otherwise.
  44. Each box is assigned its corresponding friction material
  45. Each box also has a PhysX box collider with default settings
  46. The COM of the boxes is placed on the plane (0, 0, -0.5), so as to remove any torque moments and resulting rotations
  47. Expected Behavior:
  48. For each box, this script will apply a force impulse in the world X direction
  49. Boxes with greater dynamic friction coefficients should travel a shorter distance along the ramp.
  50. Test Steps:
  51. 1) Open level
  52. 2) Enter game mode
  53. 3) Find the ramp
  54. For each box:
  55. 4) Find the box
  56. 5) Ensure the box is stationary
  57. 6) Push the box and wait for it to come to rest
  58. 7) Assert that greater coefficients result in a shorter distance travelled
  59. 8) Exit game mode
  60. 9) Close the editor
  61. Note:
  62. - This test file must be called from the Open 3D Engine Editor command terminal
  63. - Any passed and failed tests are written to the Editor.log file.
  64. Parsing the file or running a log_monitor are required to observe the test results.
  65. :return: None
  66. """
  67. import os
  68. import sys
  69. from editor_python_test_tools.utils import Report
  70. from editor_python_test_tools.utils import TestHelper as helper
  71. import azlmbr
  72. import azlmbr.legacy.general as general
  73. import azlmbr.bus as bus
  74. import azlmbr.math as lymath
  75. FORCE_IMPULSE = lymath.Vector3(10.0, 0.0, 0.0)
  76. TIMEOUT = 5
  77. class Box:
  78. def __init__(self, name, valid_test, stationary_start_test, moved_test, stationary_end_test):
  79. self.name = name
  80. self.id = general.find_game_entity(name)
  81. self.start_position = self.get_position()
  82. self.distance = 0.0
  83. self.valid_test = valid_test
  84. self.stationary_start_test = stationary_start_test
  85. self.moved_test = moved_test
  86. self.stationary_end_test = stationary_end_test
  87. def is_stationary(self):
  88. velocity = azlmbr.physics.RigidBodyRequestBus(bus.Event, "GetLinearVelocity", self.id)
  89. return vector_is_close_to_zero(velocity)
  90. def get_position(self):
  91. return azlmbr.components.TransformBus(bus.Event, "GetWorldTranslation", self.id)
  92. def vector_is_close_to_zero(vector):
  93. return abs(vector.x) <= 0.001 and abs(vector.y) <= 0.001 and abs(vector.z) <= 0.001
  94. def push(box):
  95. azlmbr.physics.RigidBodyRequestBus(bus.Event, "ApplyLinearImpulse", box.id, FORCE_IMPULSE)
  96. helper.init_idle()
  97. # 1) Open level
  98. helper.open_level("Physics", "Material_DynamicFriction")
  99. # 2) Enter game mode
  100. helper.enter_game_mode(Tests.enter_game_mode)
  101. # fmt: off
  102. # Set up our boxes
  103. box_zero = Box(
  104. name = "Zero",
  105. valid_test = Tests.find_box_zero,
  106. stationary_start_test = Tests.box_at_rest_start_zero,
  107. moved_test = Tests.box_was_pushed_zero,
  108. stationary_end_test = Tests.box_at_rest_end_zero
  109. )
  110. box_low = Box(
  111. name = "Low",
  112. valid_test = Tests.find_box_low,
  113. stationary_start_test = Tests.box_at_rest_start_low,
  114. moved_test = Tests.box_was_pushed_low,
  115. stationary_end_test = Tests.box_at_rest_end_low
  116. )
  117. box_mid = Box(
  118. name = "Mid",
  119. valid_test = Tests.find_box_mid,
  120. stationary_start_test = Tests.box_at_rest_start_mid,
  121. moved_test = Tests.box_was_pushed_mid,
  122. stationary_end_test = Tests.box_at_rest_end_mid
  123. )
  124. box_high = Box(
  125. name = "High",
  126. valid_test = Tests.find_box_high,
  127. stationary_start_test = Tests.box_at_rest_start_high,
  128. moved_test = Tests.box_was_pushed_high,
  129. stationary_end_test = Tests.box_at_rest_end_high
  130. )
  131. all_boxes = (box_zero, box_low, box_mid, box_high)
  132. # fmt: on
  133. # 3) Find the ramp
  134. ramp_id = general.find_game_entity("Ramp")
  135. Report.critical_result(Tests.find_ramp, ramp_id.IsValid())
  136. for box in all_boxes:
  137. Report.info("********Pushing Box {}********".format(box.name))
  138. # 4) Find the box
  139. Report.critical_result(box.valid_test, box.id.IsValid())
  140. # 5) Ensure the box is stationary
  141. Report.result(box.stationary_start_test, box.is_stationary())
  142. # 6) Push the box
  143. push(box)
  144. Report.result(box.moved_test, helper.wait_for_condition(lambda: not box.is_stationary(), TIMEOUT))
  145. Report.result(box.stationary_end_test, helper.wait_for_condition(lambda: box.is_stationary(), TIMEOUT))
  146. end_position = box.get_position()
  147. box.distance = end_position.GetDistance(box.start_position)
  148. Report.info("Box {} travelled {:.3f} meters".format(box.name, box.distance))
  149. # 7) Assert that greater coefficients result in shorter travelled distance
  150. distance_ordered = box_high.distance < box_mid.distance < box_low.distance < box_zero.distance
  151. Report.result(Tests.distance_ordered, distance_ordered)
  152. # 8) Exit game mode
  153. helper.exit_game_mode(Tests.exit_game_mode)
  154. if __name__ == "__main__":
  155. from editor_python_test_tools.utils import Report
  156. Report.start_test(Material_DynamicFriction)