-
Notifications
You must be signed in to change notification settings - Fork 111
Pytest validation #3123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Pytest validation #3123
Changes from all commits
d2140c1
c101d0a
1efe449
679f5b5
bddfc6d
6cd7863
84ad9e4
caf5522
2aea34d
3b3f270
e7f15c3
6b2b5ad
4a6d5b8
caf6175
0ee4e2f
0f2d160
9e0ecea
bb41198
634f4ff
da16d0e
0f8fc26
b34dcf4
f4c09df
7791e35
b3b813b
be83cd7
0594740
24dfaf2
bffbe18
2526709
1eac5a6
1ea49a6
b20c9e9
43b87b7
3758960
2583f58
a7be834
3927b21
aae3ba8
29b8ebc
6b8c492
6c3ea41
b366b5c
4f5e18f
2538d9b
eb67efa
6e4ab7d
c7a7d2d
6a149fe
22121c6
1de63b0
98687d6
43906bc
af77463
bc891f7
87d2827
deb4d21
f3930bf
590719f
d405467
f7fa44a
91c000e
0966c4d
1ff45af
06080b3
16c411e
da100d5
bfb8626
ee7846c
a3a4344
e38f098
1cb1eeb
12d5d0e
0a18f61
91564d1
c660224
f2d4024
8050615
82a89c1
810d8f8
468fa4d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,89 +4,173 @@ | |
|
||
import software.python_bindings as tbots_cpp | ||
from proto.play_pb2 import Play, PlayName | ||
from software.simulated_tests.robot_enters_region import * | ||
from software.simulated_tests.ball_enters_region import * | ||
from software.simulated_tests.ball_moves_from_rest import * | ||
from proto.import_all_protos import * | ||
from proto.message_translation.tbots_protobuf import create_world_state | ||
from proto.ssl_gc_common_pb2 import Team | ||
from software.simulated_tests.or_validation import OrValidation | ||
|
||
|
||
@pytest.mark.parametrize("is_friendly_test", [True, False]) | ||
def test_kickoff_play(simulated_test_runner, is_friendly_test): | ||
def setup(*args): | ||
# starting point must be Point | ||
ball_initial_pos = tbots_cpp.Point(0, 0) | ||
|
||
# Setup Bots | ||
blue_bots = [ | ||
tbots_cpp.Point(-3, 2.5), | ||
tbots_cpp.Point(-3, 1.5), | ||
tbots_cpp.Point(-3, 0.5), | ||
tbots_cpp.Point(-3, -0.5), | ||
tbots_cpp.Point(-3, -1.5), | ||
tbots_cpp.Point(-3, -2.5), | ||
] | ||
|
||
yellow_bots = [ | ||
tbots_cpp.Point(1, 0), | ||
tbots_cpp.Point(1, 2.5), | ||
tbots_cpp.Point(1, -2.5), | ||
tbots_cpp.Field.createSSLDivisionBField().enemyGoalCenter(), | ||
tbots_cpp.Field.createSSLDivisionBField() | ||
.enemyDefenseArea() | ||
.negXNegYCorner(), | ||
tbots_cpp.Field.createSSLDivisionBField() | ||
.enemyDefenseArea() | ||
.negXPosYCorner(), | ||
] | ||
|
||
blue_play = Play() | ||
yellow_play = Play() | ||
|
||
# Game Controller Setup | ||
ball_initial_pos = tbots_cpp.Point(0, 0) | ||
|
||
# Setup Bots | ||
blue_bots = [ | ||
tbots_cpp.Point(-3, 2.5), | ||
tbots_cpp.Point(-3, 1.5), | ||
tbots_cpp.Point(-3, 0.5), | ||
tbots_cpp.Point(-3, -0.5), | ||
tbots_cpp.Point(-3, -1.5), | ||
tbots_cpp.Point(-3, -2.5), | ||
] | ||
|
||
yellow_bots = [ | ||
tbots_cpp.Point(1, 0), | ||
tbots_cpp.Point(1, 2.5), | ||
tbots_cpp.Point(1, -2.5), | ||
tbots_cpp.Field.createSSLDivisionBField().enemyGoalCenter(), | ||
tbots_cpp.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), | ||
tbots_cpp.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), | ||
] | ||
|
||
blue_play = Play() | ||
yellow_play = Play() | ||
|
||
# Game Controller Setup | ||
simulated_test_runner.gamecontroller.send_gc_command( | ||
gc_command=Command.Type.STOP, team=Team.UNKNOWN | ||
) | ||
|
||
if is_friendly_test: | ||
simulated_test_runner.gamecontroller.send_gc_command( | ||
gc_command=Command.Type.STOP, team=Team.UNKNOWN | ||
gc_command=Command.Type.KICKOFF, team=Team.BLUE | ||
) | ||
blue_play.name = PlayName.KickoffFriendlyPlay | ||
yellow_play.name = PlayName.KickoffEnemyPlay | ||
else: | ||
simulated_test_runner.gamecontroller.send_gc_command( | ||
gc_command=Command.Type.NORMAL_START, team=Team.BLUE | ||
gc_command=Command.Type.KICKOFF, team=Team.YELLOW | ||
) | ||
if is_friendly_test: | ||
simulated_test_runner.gamecontroller.send_gc_command( | ||
gc_command=Command.Type.KICKOFF, team=Team.BLUE | ||
blue_play.name = PlayName.KickoffEnemyPlay | ||
yellow_play.name = PlayName.KickoffFriendlyPlay | ||
|
||
simulated_test_runner.gamecontroller.send_gc_command( | ||
gc_command=Command.Type.NORMAL_START, team=Team.BLUE | ||
) | ||
|
||
# Force play override here | ||
simulated_test_runner.blue_full_system_proto_unix_io.send_proto(Play, blue_play) | ||
simulated_test_runner.yellow_full_system_proto_unix_io.send_proto(Play, yellow_play) | ||
|
||
# Create world state | ||
simulated_test_runner.simulator_proto_unix_io.send_proto( | ||
WorldState, | ||
create_world_state( | ||
yellow_robot_locations=yellow_bots, | ||
blue_robot_locations=blue_bots, | ||
ball_location=ball_initial_pos, | ||
ball_velocity=tbots_cpp.Vector(0, 0), | ||
), | ||
) | ||
|
||
# Always Validation | ||
always_validation_sequence_set = [[]] | ||
if is_friendly_test: | ||
# Checks that either 0 or 1 robots are in centerCircle OR ball moves from center point | ||
always_validation_sequence_set[0].append( | ||
OrValidation( | ||
[ | ||
BallAlwaysMovesFromRest( | ||
position=tbots_cpp.Point(0, 0), threshold=0.01 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SSL Robocup threshold is 0.05 m https://robocup-ssl.github.io/ssl-rules/sslrules.html#_double_touch |
||
), | ||
NumberOfRobotsAlwaysStaysInRegion( | ||
regions=[ | ||
tbots_cpp.Field.createSSLDivisionBField().centerCircle() | ||
], | ||
req_robot_cnt=0, | ||
), | ||
NumberOfRobotsAlwaysStaysInRegion( | ||
regions=[ | ||
tbots_cpp.Field.createSSLDivisionBField().centerCircle() | ||
], | ||
req_robot_cnt=1, | ||
), | ||
] | ||
) | ||
blue_play.name = PlayName.KickoffFriendlyPlay | ||
yellow_play.name = PlayName.KickoffEnemyPlay | ||
else: | ||
simulated_test_runner.gamecontroller.send_gc_command( | ||
gc_command=Command.Type.KICKOFF, team=Team.YELLOW | ||
) | ||
|
||
# Checks that there are 6 friendly robots in friendlyHalf + centerCircle + friendlyGoal OR ball moves from center point | ||
always_validation_sequence_set[0].append( | ||
OrValidation( | ||
[ | ||
BallAlwaysMovesFromRest( | ||
position=tbots_cpp.Point(0, 0), threshold=0.01 | ||
), | ||
NumberOfRobotsAlwaysStaysInRegion( | ||
regions=[ | ||
tbots_cpp.Field.createSSLDivisionBField().friendlyHalf(), | ||
tbots_cpp.Field.createSSLDivisionBField().friendlyGoal(), | ||
tbots_cpp.Field.createSSLDivisionBField().centerCircle(), | ||
], | ||
req_robot_cnt=6, | ||
), | ||
] | ||
) | ||
) | ||
|
||
else: | ||
# Checks that 0 robots are in centerCircle OR ball moves from center point | ||
always_validation_sequence_set[0].append( | ||
OrValidation( | ||
[ | ||
BallAlwaysMovesFromRest( | ||
position=tbots_cpp.Point(0, 0), threshold=0.01 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The SSL Robocup threshold is 0.05 m: https://robocup-ssl.github.io/ssl-rules/sslrules.html#_double_touch |
||
), | ||
NumberOfRobotsAlwaysStaysInRegion( | ||
regions=[ | ||
tbots_cpp.Field.createSSLDivisionBField().centerCircle() | ||
], | ||
req_robot_cnt=0, | ||
), | ||
] | ||
) | ||
blue_play.name = PlayName.KickoffEnemyPlay | ||
yellow_play.name = PlayName.KickoffFriendlyPlay | ||
) | ||
|
||
# Force play override here | ||
simulated_test_runner.blue_full_system_proto_unix_io.send_proto(Play, blue_play) | ||
simulated_test_runner.yellow_full_system_proto_unix_io.send_proto( | ||
Play, yellow_play | ||
# Checks that there are 6 enemy robots in friendlyHalf + centerCircle + friendlyGoal OR ball moves from center point | ||
always_validation_sequence_set[0].append( | ||
OrValidation( | ||
[ | ||
BallAlwaysMovesFromRest( | ||
position=tbots_cpp.Point(0, 0), threshold=0.01 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the SSL robocup threshold is |
||
), | ||
NumberOfRobotsAlwaysStaysInRegion( | ||
regions=[ | ||
tbots_cpp.Field.createSSLDivisionBField().friendlyHalf(), | ||
tbots_cpp.Field.createSSLDivisionBField().friendlyGoal(), | ||
], | ||
req_robot_cnt=6, | ||
), | ||
] | ||
) | ||
) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you could reduce the duplication in this code a bit:
|
||
|
||
# Create world state | ||
simulated_test_runner.simulator_proto_unix_io.send_proto( | ||
WorldState, | ||
create_world_state( | ||
yellow_robot_locations=yellow_bots, | ||
blue_robot_locations=blue_bots, | ||
ball_location=ball_initial_pos, | ||
ball_velocity=tbots_cpp.Vector(0, 0), | ||
), | ||
eventually_validation_sequence_set = [[]] | ||
|
||
# Eventually Validation | ||
if is_friendly_test: | ||
# Checks that ball leaves center point by 0.05 meters within 10 seconds of kickoff | ||
eventually_validation_sequence_set[0].append( | ||
BallEventuallyExitsRegion( | ||
regions=[tbots_cpp.Circle(ball_initial_pos, 0.05)] | ||
) | ||
) | ||
|
||
# TODO- #2809 Validation | ||
# params just have to be a list of length 1 to ensure the test runs at least once | ||
simulated_test_runner.run_test( | ||
setup=setup, | ||
params=[0], | ||
inv_always_validation_sequence_set=[[]], | ||
inv_eventually_validation_sequence_set=[[]], | ||
ag_always_validation_sequence_set=[[]], | ||
ag_eventually_validation_sequence_set=[[]], | ||
inv_eventually_validation_sequence_set=eventually_validation_sequence_set, | ||
inv_always_validation_sequence_set=always_validation_sequence_set, | ||
test_timeout_s=10, | ||
) | ||
|
||
|
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -6,7 +6,13 @@ | |||||||
|
||||||||
class OrValidation(Validation): | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is really neat! 💯 |
||||||||
def __init__(self, validations): | ||||||||
"""An or extension to the validation function""" | ||||||||
"""An OR extension to the validation function""" | ||||||||
assert len(validations) > 0 | ||||||||
validation_type_initial = validations[0].get_validation_type() | ||||||||
for validation in validations: | ||||||||
validation_type = validation.get_validation_type() | ||||||||
if validation_type != validation_type_initial: | ||||||||
raise TypeError("Type of validation instances is not consistent") | ||||||||
self.validations = validations | ||||||||
|
||||||||
def get_validation_status(self, world): | ||||||||
|
@@ -32,10 +38,4 @@ def get_validation_geometry(self, world): | |||||||
return validation_geometry | ||||||||
|
||||||||
def get_validation_type(self, world): | ||||||||
validation_type_initial = self.validations[0].get_validation_type | ||||||||
|
||||||||
for validation in self.validations: | ||||||||
validation_type = validation.get_validation_type | ||||||||
if validation_type != validation_type_initial: | ||||||||
raise TypeError("type of validation instances is not consistent") | ||||||||
return validation_type_initial | ||||||||
return ValidationType | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. bump There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the constructor should check that the validation types are consistent
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do validation types put into the function need to be consistent? If we wanted to check if either an always validation or eventually validation are passing, then the OrValidation class would not be able to support this (provided that this check is kept). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Our underlying validation code doesn't support mixing eventually and always validations:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this if statement could probably be condensed a bit, so this can be common between both branches:
and you can just append this to the OR validation in the friendly case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done