From 5bf7330f3505d4ac7837766317fa8ed7ab44ad96 Mon Sep 17 00:00:00 2001 From: amzn-sean <75276488+amzn-sean@users.noreply.github.com> Date: Wed, 13 Oct 2021 12:50:11 +0100 Subject: [PATCH] made some physX tests less flaky (#4632) Joints_BallLeadFollowerCollide - changed the idle_wait to a wait_for_condition of the lead and follower colliding with a 10 second timeout. It was a 2 second timeout which is on the edge of the time from start to collision (~1.5sec). Joints_HingeNoLimitsConstrained - now measures the angle the joint is at and waits for the follower to raise up and over the lead, or fail after a 10sec timeout. This use to 'catch' the follower joint in a force region and check the position of the follower to determine pass/fail. Signed-off-by: amzn-sean <75276488+amzn-sean@users.noreply.github.com> --- .../joints/Joints_BallLeadFollowerCollide.py | 14 +---- .../joints/Joints_HingeNoLimitsConstrained.py | 59 +++++++++++++++---- .../Joints_HingeNoLimitsConstrained.ly | 4 +- 3 files changed, 54 insertions(+), 23 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallLeadFollowerCollide.py index 0e8d7ea255..1209cb6caf 100644 --- a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallLeadFollowerCollide.py +++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallLeadFollowerCollide.py @@ -52,9 +52,6 @@ def Joints_BallLeadFollowerCollide(): from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper - import azlmbr.legacy.general as general - import azlmbr.bus - from JointsHelper import JointEntityCollisionAware # Helper Entity class - self.collided flag is set when instance receives collision event. @@ -75,17 +72,12 @@ def Joints_BallLeadFollowerCollide(): lead = Entity("lead") follower = Entity("follower") - # 4) Wait for several seconds - general.idle_wait(2.0) # wait for lead and follower to move + # 4) Wait for collision between lead and follower or timeout + Report.critical_result(Tests.check_collision_happened, helper.wait_for_condition(lambda: lead.collided and follower.collided, 10.0)) - # 5) Check to see if lead and follower behaved as expected - Report.critical_result(Tests.check_collision_happened, lead.collided and follower.collided) - - # 6) Exit Game Mode + # 5) Exit Game Mode helper.exit_game_mode(Tests.exit_game_mode) - - if __name__ == "__main__": from editor_python_test_tools.utils import Report Report.start_test(Joints_BallLeadFollowerCollide) diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeNoLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeNoLimitsConstrained.py index 0870a807fc..0b3f88b4f6 100644 --- a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeNoLimitsConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeNoLimitsConstrained.py @@ -52,11 +52,13 @@ def Joints_HingeNoLimitsConstrained(): """ import os import sys + import math from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus + import azlmbr.math as azmath import JointsHelper from JointsHelper import JointEntity @@ -84,28 +86,65 @@ def Joints_HingeNoLimitsConstrained(): Report.info_vector3(lead.position, "lead initial position:") Report.info_vector3(follower.position, "follower initial position:") leadInitialPosition = lead.position - followerInitialPosition = follower.position - # 4) Wait for several seconds - general.idle_wait(4.0) # wait for lead and follower to move + # 4) Wait for the follower to move above and over the lead or Timeout + normalizedStartPos = JointsHelper.getRelativeVector(lead.position, follower.position) + normalizedStartPos = normalizedStartPos.GetNormalizedSafe() + + class WaitCondition: + ANGLE_CHECKPOINT_1 = math.radians(90) + ANGLE_CHECKPOINT_2 = math.radians(200) + + angleAchieved = 0.0 + followerMovedAbove90Deg = False #this is expected to be true to pass the test + followerMovedAbove200Deg = False #this is expected to be true to pass the test + + jointNormal = azmath.Vector3(0.0, -1.0, 0.0) # the joint rotates around the y axis + def checkConditionMet(self): + #calculate the current follower-lead vector + normalVec = JointsHelper.getRelativeVector(lead.position, follower.position) + normalVec = normalVec.GetNormalizedSafe() + + #triple product and get the angle + tripleProduct = normalizedStartPos.dot(normalVec.cross(self.jointNormal)) + currentAngle = math.acos(normalizedStartPos.Dot(normalVec)) + if tripleProduct < 0: + currentAngle = (2*math.pi) - currentAngle + + #if the angle is now less then last time, it is no longer rising, so end the test. + if currentAngle < self.angleAchieved: + return True + + #once we're passed the final check point, end the test + if currentAngle > self.ANGLE_CHECKPOINT_2: + self.followerMovedAbove200Deg = True + return True + + self.angleAchieved = currentAngle + self.followerMovedAbove90Deg = currentAngle > self.ANGLE_CHECKPOINT_1 + return False + + def isFollowerPositionCorrect(self): + return self.followerMovedAbove90Deg and self.followerMovedAbove200Deg + + waitCondition = WaitCondition() + + MAX_WAIT_TIME = 10.0 #seconds + conditionMet = helper.wait_for_condition(lambda: waitCondition.checkConditionMet(), MAX_WAIT_TIME) # 5) Check to see if lead and follower behaved as expected - Report.info_vector3(lead.position, "lead position after 1 second:") - Report.info_vector3(follower.position, "follower position after 1 second:") + Report.info_vector3(lead.position, "lead position after test run:") + Report.info_vector3(follower.position, "follower position after test run:") leadPositionDelta = lead.position.Subtract(leadInitialPosition) leadRemainedStill = JointsHelper.vector3SmallerThanScalar(leadPositionDelta, FLOAT_EPSILON) Report.critical_result(Tests.check_lead_position, leadRemainedStill) - followerSwingedOverLead = (follower.position.x < leadInitialPosition.x and - follower.position.z > leadInitialPosition.z) - Report.critical_result(Tests.check_follower_position, followerSwingedOverLead) + Report.critical_result(Tests.check_follower_position, conditionMet and waitCondition.isFollowerPositionCorrect()) # 6) Exit Game Mode helper.exit_game_mode(Tests.exit_game_mode) - - if __name__ == "__main__": from editor_python_test_tools.utils import Report Report.start_test(Joints_HingeNoLimitsConstrained) diff --git a/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly b/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly index 86dd941423..9babf84ba4 100644 --- a/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly +++ b/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:817bd8dd22e185136418b60fba5b3552993687515d3d5ae96791f2c3be907b92 -size 7233 +oid sha256:60276c07b45a734e4f71d695278167ea61e884f8b513906168c9642078ad5954 +size 6045