From d2140c1a9204e7bbe1374ad245343be7e587fdcb Mon Sep 17 00:00:00 2001 From: Phil Date: Thu, 2 Jun 2022 19:14:49 -0700 Subject: [PATCH 01/83] crease defense and offense updates --- .../crease_defense_play_test.py | 84 +++++++++++++++++++ .../hl/stp/play/offense/offense_play_test.py | 83 ++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py create mode 100644 src/software/ai/hl/stp/play/offense/offense_play_test.py diff --git a/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py b/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py new file mode 100644 index 0000000000..c5a29ff988 --- /dev/null +++ b/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py @@ -0,0 +1,84 @@ +import sys + +import pytest + +import software.python_bindings as tbots +from proto.play_pb2 import Play +from software.simulated_tests.ball_enters_region import * +from software.simulated_tests.simulated_test_fixture import simulated_test_runner +from proto.message_translation.tbots_protobuf import create_world_state +from proto.ssl_gc_common_pb2 import Team + +# TODO issue #2599 - Remove Duration parameter from test +# @pytest.mark.parametrize("run_enemy_ai,test_duration", [(False, 20), (True, 20)]) +def test_offense_play(simulated_test_runner): + + # starting point must be Point + ball_initial_pos = tbots.Point(-4.4, 2.9) + # placement point must be Vector2 to work with game controller + tbots.Point(-3, -2) + + # Setup Bots + blue_bots = [ + tbots.Point(-4.5, 0), + tbots.Point(-3, 1.5), + tbots.Point(-3, 0.5), + tbots.Point(-3, -0.5), + tbots.Point(-3, -1.5), + tbots.Point(-3, -3.0), + ] + + yellow_bots = [ + tbots.Point(1, 3), + tbots.Point(1, -0.25), + tbots.Point(1, -1.25), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + ] + + # Game Controller Setup + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.STOP, team=Team.UNKNOWN + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.FORCE_START, team=Team.BLUE + ) + + # Force play override here + blue_play = Play() + blue_play.name = Play.CreaseDefensePlay + + yellow_play = Play() + yellow_play.name = Play.HaltPlay + + 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.Vector(0, 0), + ), + ) + + # Always Validation + always_validation_sequence_set = [[]] + + # Eventually Validation + eventually_validation_sequence_set = [[]] + + simulated_test_runner.run_test( + eventually_validation_sequence_set=eventually_validation_sequence_set, + always_validation_sequence_set=always_validation_sequence_set, + test_timeout_s=25, + ) + + +if name == "main": + # Run the test, -s disables all capturing at -vv increases verbosity + sys.exit(pytest.main([file, "-svv"])) diff --git a/src/software/ai/hl/stp/play/offense/offense_play_test.py b/src/software/ai/hl/stp/play/offense/offense_play_test.py new file mode 100644 index 0000000000..e3399a8cdb --- /dev/null +++ b/src/software/ai/hl/stp/play/offense/offense_play_test.py @@ -0,0 +1,83 @@ +import sys + +import pytest + +import software.python_bindings as tbots +from proto.play_pb2 import Play +from software.simulated_tests.ball_enters_region import * +from software.simulated_tests.simulated_test_fixture import simulated_test_runner +from proto.message_translation.tbots_protobuf import create_world_state +from proto.ssl_gc_common_pb2 import Team + +# TODO issue #2599 - Remove Duration parameter from test +# @pytest.mark.parametrize("run_enemy_ai,test_duration", [(False, 20), (True, 20)]) +def test_offense_play(simulated_test_runner): + + # starting point must be Point + ball_initial_pos = tbots.Point(-4.4, 2.9) + # placement point must be Vector2 to work with game controller + tbots.Point(-3, -2) + + # Setup Bots + blue_bots = [ + tbots.Point(-4.5, 3.0), + tbots.Point(-2, 1.5), + tbots.Point(-2, 0.5), + tbots.Point(-2, -1.7), + tbots.Point(-2, -1.5), + ] + + yellow_bots = [ + tbots.Point(1, 0), + tbots.Point(1, 2.5), + tbots.Point(1, -2.5), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + ] + + # Game Controller Setup + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.STOP, team=Team.UNKNOWN + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.FORCE_START, team=Team.BLUE + ) + + # Force play override here + blue_play = Play() + blue_play.name = Play.OffensePlay + + yellow_play = Play() + yellow_play.name = Play.HaltPlay + + 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.Vector(0, 0), + ), + ) + + # Always Validation + always_validation_sequence_set = [[]] + + # Eventually Validation + eventually_validation_sequence_set = [[]] + + simulated_test_runner.run_test( + eventually_validation_sequence_set=eventually_validation_sequence_set, + always_validation_sequence_set=always_validation_sequence_set, + test_timeout_s=25, + ) + + +if __name__ == "__main__": + # Run the test, -s disables all capturing at -vv increases verbosity + sys.exit(pytest.main([__file__, "-svv"])) From c101d0ae8ddd37255ff9c7d86c3f49383f3a2887 Mon Sep 17 00:00:00 2001 From: Phil Date: Thu, 2 Jun 2022 19:15:26 -0700 Subject: [PATCH 02/83] more test updates --- src/software/ai/hl/stp/play/BUILD | 36 +++++++++++++++++-- .../ai/hl/stp/play/crease_defense/BUILD | 20 ++++++++++- .../crease_defense_play_test.py | 14 ++++---- src/software/ai/hl/stp/play/offense/BUILD | 20 ++++++++++- .../hl/stp/play/offense/offense_play_test.py | 7 ++-- 5 files changed, 83 insertions(+), 14 deletions(-) diff --git a/src/software/ai/hl/stp/play/BUILD b/src/software/ai/hl/stp/play/BUILD index f3486b2634..9e22e17613 100644 --- a/src/software/ai/hl/stp/play/BUILD +++ b/src/software/ai/hl/stp/play/BUILD @@ -359,7 +359,7 @@ cc_test( ) cc_test( - name = "corner_kick_play_test", + name = "corner_kick_play_cpp_test", srcs = ["corner_kick_play_test.cpp"], deps = [ "//shared/test_util:tbots_gtest_main", @@ -373,8 +373,24 @@ cc_test( ], ) +py_test( + name = "corner_kick_play_test.py", + srcs = [ + "corner_kick_play_test.py", + ], + # TODO (#2619) Remove tag to run in parallel + tags = [ + "exclusive", + ], + deps = [ + "//software/simulated_tests:simulated_test_fixture", + "//software/simulated_tests:validation", + requirement("pytest"), + ], +) + cc_test( - name = "defense_play_test", + name = "defense_play_cpp_test", srcs = ["defense_play_test.cpp"], deps = [ "//shared/test_util:tbots_gtest_main", @@ -389,6 +405,22 @@ cc_test( ], ) +py_test( + name = "defense_play_test", + srcs = [ + "defense_play_test.py", + ], + # TODO (#2619) Remove tag to run in parallel + tags = [ + "exclusive", + ], + deps = [ + "//software/simulated_tests:simulated_test_fixture", + "//software/simulated_tests:validation", + requirement("pytest"), + ], +) + cc_test( name = "enemy_ball_placement_play_test", srcs = ["enemy_ball_placement_play_test.cpp"], diff --git a/src/software/ai/hl/stp/play/crease_defense/BUILD b/src/software/ai/hl/stp/play/crease_defense/BUILD index 9b9f9f8bfb..92c7b64585 100644 --- a/src/software/ai/hl/stp/play/crease_defense/BUILD +++ b/src/software/ai/hl/stp/play/crease_defense/BUILD @@ -1,5 +1,7 @@ package(default_visibility = ["//visibility:public"]) +load("@simulated_tests_deps//:requirements.bzl", "requirement") + # We force linking for all plays so that the static variables required for the # "factory" design pattern to work are linked in # https://www.bfilipek.com/2018/02/static-vars-static-lib.html @@ -26,8 +28,24 @@ cc_library( alwayslink = True, ) -cc_test( +py_test( name = "crease_defense_play_test", + srcs = [ + "crease_defense_play_test.py", + ], + # TODO (#2619) Remove tag to run in parallel + tags = [ + "exclusive", + ], + deps = [ + "//software/simulated_tests:simulated_test_fixture", + "//software/simulated_tests:validation", + requirement("pytest"), + ], +) + +cc_test( + name = "crease_defense_play_cpp_test", srcs = ["crease_defense_play_test.cpp"], deps = [ ":crease_defense_play", diff --git a/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py b/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py index c5a29ff988..68a9985098 100644 --- a/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py +++ b/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py @@ -3,7 +3,7 @@ import pytest import software.python_bindings as tbots -from proto.play_pb2 import Play +from proto.play_pb2 import Play, PlayName from software.simulated_tests.ball_enters_region import * from software.simulated_tests.simulated_test_fixture import simulated_test_runner from proto.message_translation.tbots_protobuf import create_world_state @@ -11,10 +11,10 @@ # TODO issue #2599 - Remove Duration parameter from test # @pytest.mark.parametrize("run_enemy_ai,test_duration", [(False, 20), (True, 20)]) -def test_offense_play(simulated_test_runner): +def test_crease_defense_play(simulated_test_runner): # starting point must be Point - ball_initial_pos = tbots.Point(-4.4, 2.9) + ball_initial_pos = tbots.Point(0.9, 2.85) # placement point must be Vector2 to work with game controller tbots.Point(-3, -2) @@ -47,10 +47,10 @@ def test_offense_play(simulated_test_runner): # Force play override here blue_play = Play() - blue_play.name = Play.CreaseDefensePlay + blue_play.name = PlayName.CreaseDefensePlay yellow_play = Play() - yellow_play.name = Play.HaltPlay + yellow_play.name = PlayName.HaltPlay 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) @@ -79,6 +79,6 @@ def test_offense_play(simulated_test_runner): ) -if name == "main": +if __name__ == "__main__": # Run the test, -s disables all capturing at -vv increases verbosity - sys.exit(pytest.main([file, "-svv"])) + sys.exit(pytest.main([__file__, "-svv"])) diff --git a/src/software/ai/hl/stp/play/offense/BUILD b/src/software/ai/hl/stp/play/offense/BUILD index 05ecb60531..50400782f7 100644 --- a/src/software/ai/hl/stp/play/offense/BUILD +++ b/src/software/ai/hl/stp/play/offense/BUILD @@ -1,5 +1,7 @@ package(default_visibility = ["//visibility:public"]) +load("@simulated_tests_deps//:requirements.bzl", "requirement") + # We force linking for all plays so that the static variables required for the # "factory" design pattern to work are linked in # https://www.bfilipek.com/2018/02/static-vars-static-lib.html @@ -26,8 +28,24 @@ cc_library( alwayslink = True, ) -cc_test( +py_test( name = "offense_play_test", + srcs = [ + "offense_play_test.py", + ], + # TODO (#2619) Remove tag to run in parallel + tags = [ + "exclusive", + ], + deps = [ + "//software/simulated_tests:simulated_test_fixture", + "//software/simulated_tests:validation", + requirement("pytest"), + ], +) + +cc_test( + name = "offense_play_cpp_test", srcs = ["offense_play_test.cpp"], deps = [ ":offense_play", diff --git a/src/software/ai/hl/stp/play/offense/offense_play_test.py b/src/software/ai/hl/stp/play/offense/offense_play_test.py index e3399a8cdb..1e2e7ba276 100644 --- a/src/software/ai/hl/stp/play/offense/offense_play_test.py +++ b/src/software/ai/hl/stp/play/offense/offense_play_test.py @@ -3,7 +3,7 @@ import pytest import software.python_bindings as tbots -from proto.play_pb2 import Play +from proto.play_pb2 import Play, PlayName from software.simulated_tests.ball_enters_region import * from software.simulated_tests.simulated_test_fixture import simulated_test_runner from proto.message_translation.tbots_protobuf import create_world_state @@ -25,6 +25,7 @@ def test_offense_play(simulated_test_runner): tbots.Point(-2, 0.5), tbots.Point(-2, -1.7), tbots.Point(-2, -1.5), + tbots.Point(-2,-0.5), ] yellow_bots = [ @@ -46,10 +47,10 @@ def test_offense_play(simulated_test_runner): # Force play override here blue_play = Play() - blue_play.name = Play.OffensePlay + blue_play.name = PlayName.OffensePlay yellow_play = Play() - yellow_play.name = Play.HaltPlay + yellow_play.name = PlayName.HaltPlay 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) From 1efe4493322ba51c77f45f6ff25e7df92de30d7b Mon Sep 17 00:00:00 2001 From: Phil Date: Thu, 2 Jun 2022 19:35:30 -0700 Subject: [PATCH 03/83] more stuff --- src/software/ai/hl/stp/play/BUILD | 2 +- src/software/simulated_tests/simulated_test_fixture.py | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/software/ai/hl/stp/play/BUILD b/src/software/ai/hl/stp/play/BUILD index 9e22e17613..f4abb7bcac 100644 --- a/src/software/ai/hl/stp/play/BUILD +++ b/src/software/ai/hl/stp/play/BUILD @@ -560,7 +560,7 @@ py_test( ) cc_test( - name = "ball_placement_play_test_old", + name = "ball_placement_play_cpp_test", srcs = ["ball_placement_play_test.cpp"], deps = [ "//shared/test_util:tbots_gtest_main", diff --git a/src/software/simulated_tests/simulated_test_fixture.py b/src/software/simulated_tests/simulated_test_fixture.py index b1434c343f..9ef1fcc81e 100644 --- a/src/software/simulated_tests/simulated_test_fixture.py +++ b/src/software/simulated_tests/simulated_test_fixture.py @@ -68,6 +68,7 @@ def __init__( self.last_exception = None self.world_buffer = ThreadSafeBuffer(buffer_size=1, protobuf_type=World) + self.primitive_set_buffer = ThreadSafeBuffer(buffer_size=1, protobuf_type=PrimitiveSet) self.last_exception = None self.ssl_wrapper_buffer = ThreadSafeBuffer( @@ -166,6 +167,9 @@ def __runner(): self.blue_full_system_proto_unix_io.send_proto( RobotStatus, robot_status ) + self.primitive_set_buffer.get( + block=True, timeout=WORLD_BUFFER_TIMEOUT + ) # Validate ( @@ -367,7 +371,8 @@ def simulated_test_runner(): # Only validate on the blue worlds blue_full_system_proto_unix_io.register_observer(World, runner.world_buffer) - + blue_full_system_proto_unix_io.register_observer(PrimitiveSet, + runner.primitive_set_buffer) # Setup proto loggers. # # NOTE: Its important we use the test runners time provider because From 679f5b51617eefe502bdcfbbab1d37eb899ff65b Mon Sep 17 00:00:00 2001 From: Phil Date: Thu, 2 Jun 2022 19:35:51 -0700 Subject: [PATCH 04/83] more tests --- .../ai/hl/stp/play/corner_kick_play_test.py | 152 ++++++++++++ .../ai/hl/stp/play/defense_play_test.py | 217 ++++++++++++++++++ src/software/ai/hl/stp/play/halt_play_test.py | 152 ++++++++++++ .../ai/hl/stp/play/kickoff_enemy_play_test.py | 84 +++++++ 4 files changed, 605 insertions(+) create mode 100644 src/software/ai/hl/stp/play/corner_kick_play_test.py create mode 100644 src/software/ai/hl/stp/play/defense_play_test.py create mode 100644 src/software/ai/hl/stp/play/halt_play_test.py create mode 100644 src/software/ai/hl/stp/play/kickoff_enemy_play_test.py diff --git a/src/software/ai/hl/stp/play/corner_kick_play_test.py b/src/software/ai/hl/stp/play/corner_kick_play_test.py new file mode 100644 index 0000000000..936d840143 --- /dev/null +++ b/src/software/ai/hl/stp/play/corner_kick_play_test.py @@ -0,0 +1,152 @@ +import sys + +import pytest + +import software.python_bindings as tbots +from proto.play_pb2 import Play, PlayName +from software.simulated_tests.ball_enters_region import * +from software.simulated_tests.simulated_test_fixture import simulated_test_runner +from proto.message_translation.tbots_protobuf import create_world_state +from proto.ssl_gc_common_pb2 import Team + +# TODO issue #2599 - Remove Duration parameter from test +# @pytest.mark.parametrize("run_enemy_ai,test_duration", [(False, 20), (True, 20)]) +def test_corner_kick_play_bottom_left(simulated_test_runner): + + # starting point must be Point + ball_initial_pos = tbots.Point(4.5, -3) + + # Setup Bots + blue_bots = [ + tbots.Point(-3, 2.5), + tbots.Point(-3, 1.5), + tbots.Point(-3, 0.5), + tbots.Point(-3, -0.5), + tbots.Point(-3, -1.5), + tbots.Point(4.6, -3.1), + ] + + yellow_bots = [ + tbots.Point(1, 0), + tbots.Point(1, 2.5), + tbots.Point(1, -2.5), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + ] + + # Game Controller Setup + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.STOP, team=Team.UNKNOWN + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.NORMAL_START, team=Team.BLUE + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.CORNER_KICK, team=Team.BLUE + ) + + # Force play override here + blue_play = Play() + blue_play.name = PlayName.CornerKickPlay + + yellow_play = Play() + yellow_play.name = PlayName.HaltPlay + + 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.Vector(0, 0), + ), + ) + + # Always Validation + always_validation_sequence_set = [[]] + + # Eventually Validation + eventually_validation_sequence_set = [[]] + + simulated_test_runner.run_test( + eventually_validation_sequence_set=eventually_validation_sequence_set, + always_validation_sequence_set=always_validation_sequence_set, + test_timeout_s=25, + ) + +def test_corner_kick_play_top_right(simulated_test_runner): + + # starting point must be Point + ball_initial_pos = tbots.Point(4.5, 3) + + # Setup Bots + blue_bots = [ + tbots.Point(-3, 2.5), + tbots.Point(0, 1.5), + tbots.Point(0, 0.5), + tbots.Point(0, -0.5), + tbots.Point(0, -1.5), + tbots.Point(4.6, 3.1), + ] + + yellow_bots = [ + tbots.Point(1, 0), + tbots.Point(1, 2.5), + tbots.Point(1, -2.5), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + ] + + # Game Controller Setup + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.STOP, team=Team.UNKNOWN + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.NORMAL_START, team=Team.BLUE + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.CORNER_KICK, team=Team.BLUE + ) + + # Force play override here + blue_play = Play() + blue_play.name = PlayName.CornerKickPlay + + yellow_play = Play() + yellow_play.name = PlayName.HaltPlay + + 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.Vector(0, 0), + ), + ) + + # Always Validation + always_validation_sequence_set = [[]] + + # Eventually Validation + eventually_validation_sequence_set = [[]] + + simulated_test_runner.run_test( + eventually_validation_sequence_set=eventually_validation_sequence_set, + always_validation_sequence_set=always_validation_sequence_set, + test_timeout_s=25, + ) + +if __name__ == "__main__": + # Run the test, -s disables all capturing at -vv increases verbosity + sys.exit(pytest.main([__file__, "-svv"])) diff --git a/src/software/ai/hl/stp/play/defense_play_test.py b/src/software/ai/hl/stp/play/defense_play_test.py new file mode 100644 index 0000000000..edf3c39153 --- /dev/null +++ b/src/software/ai/hl/stp/play/defense_play_test.py @@ -0,0 +1,217 @@ +import sys + +import pytest + +import software.python_bindings as tbots +from proto.play_pb2 import Play, PlayName +from software.simulated_tests.ball_enters_region import * +from software.simulated_tests.simulated_test_fixture import simulated_test_runner +from proto.message_translation.tbots_protobuf import create_world_state +from proto.ssl_gc_common_pb2 import Team + +# TODO issue #2599 - Remove Duration parameter from test +# @pytest.mark.parametrize("run_enemy_ai,test_duration", [(False, 20), (True, 20)]) +def test_defense_play(simulated_test_runner): + + # starting point must be Point + ball_initial_pos = tbots.Point(0.9, 2.85) + + # Setup Bots + blue_bots = [ + tbots.Point(-4.5, 0), + tbots.Point(-3, 1.5), + tbots.Point(-3, 0.5), + tbots.Point(-3, -0.5), + tbots.Point(-3, -1.5), + tbots.Point(-3, -3.0), + ] + + yellow_bots = [ + tbots.Point(1, 3), + tbots.Point(1, -0.25), + tbots.Point(1, -1.25), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + ] + + # Game Controller Setup + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.STOP, team=Team.UNKNOWN + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.FORCE_START, team=Team.BLUE + ) + + # Force play override here + blue_play = Play() + blue_play.name = PlayName.DefensePlay + + yellow_play = Play() + yellow_play.name = PlayName.HaltPlay + + 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.Vector(0, 0), + ), + ) + + # Always Validation + always_validation_sequence_set = [[]] + + # Eventually Validation + eventually_validation_sequence_set = [[]] + + simulated_test_runner.run_test( + eventually_validation_sequence_set=eventually_validation_sequence_set, + always_validation_sequence_set=always_validation_sequence_set, + test_timeout_s=10, + ) + +# TODO issue #2599 - Remove Duration parameter from test +# @pytest.mark.parametrize("run_enemy_ai,test_duration", [(False, 20), (True, 20)]) +def test_defense_play_one_threat(simulated_test_runner): + + # starting point must be Point + ball_initial_pos = tbots.Point(0.9, 2.85) + + # Setup Bots + blue_bots = [ + tbots.Point(-4.5, 0), + tbots.Point(-3, 1.5), + tbots.Point(-3, 0.5), + tbots.Point(-3, -0.5), + tbots.Point(-3, -1.5), + tbots.Point(-3, -3.0), + ] + + yellow_bots = [ + tbots.Point(1, 3), + tbots.Point(1, -0.25), + tbots.Point(1, -1.25), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().posXNegYCorner(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().posXPosYCorner(), + ] + + # Game Controller Setup + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.STOP, team=Team.UNKNOWN + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.FORCE_START, team=Team.BLUE + ) + + # Force play override here + blue_play = Play() + blue_play.name = PlayName.DefensePlay + + yellow_play = Play() + yellow_play.name = PlayName.HaltPlay + + 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.Vector(0, 0), + ), + ) + + # Always Validation + always_validation_sequence_set = [[]] + + # Eventually Validation + eventually_validation_sequence_set = [[]] + + simulated_test_runner.run_test( + eventually_validation_sequence_set=eventually_validation_sequence_set, + always_validation_sequence_set=always_validation_sequence_set, + test_timeout_s=10, + ) + +# TODO issue #2599 - Remove Duration parameter from test +# @pytest.mark.parametrize("run_enemy_ai,test_duration", [(False, 20), (True, 20)]) +def test_defense_play_close_to_net(simulated_test_runner): + + # starting point must be Point + ball_initial_pos = tbots.Point(0.9, 2.85) + + # Setup Bots + blue_bots = [ + tbots.Point(-4.5, 0), + tbots.Point(-3, 1.5), + tbots.Point(-3, 0.5), + tbots.Point(-3, -0.5), + tbots.Point(-3, -1.5), + tbots.Point(-3, -3.0), + ] + + yellow_bots = [ + tbots.Point(-2, 1.05), + tbots.Point(-3.5, 2), + tbots.Point(-1.5, 0), + tbots.Point(-2.3, -1), + tbots.Point(-3.8,-2), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + ] + + # Game Controller Setup + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.STOP, team=Team.UNKNOWN + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.FORCE_START, team=Team.BLUE + ) + + # Force play override here + blue_play = Play() + blue_play.name = PlayName.DefensePlay + + yellow_play = Play() + yellow_play.name = PlayName.HaltPlay + + 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.Vector(0, 0), + ), + ) + + # Always Validation + always_validation_sequence_set = [[]] + + # Eventually Validation + eventually_validation_sequence_set = [[]] + + simulated_test_runner.run_test( + eventually_validation_sequence_set=eventually_validation_sequence_set, + always_validation_sequence_set=always_validation_sequence_set, + test_timeout_s=10, + ) + +if __name__ == "__main__": + # Run the test, -s disables all capturing at -vv increases verbosity + sys.exit(pytest.main([__file__, "-svv"])) diff --git a/src/software/ai/hl/stp/play/halt_play_test.py b/src/software/ai/hl/stp/play/halt_play_test.py new file mode 100644 index 0000000000..54f509b089 --- /dev/null +++ b/src/software/ai/hl/stp/play/halt_play_test.py @@ -0,0 +1,152 @@ +import sys + +import pytest + +import software.python_bindings as tbots +from proto.play_pb2 import Play, PlayName +from software.simulated_tests.ball_enters_region import * +from software.simulated_tests.simulated_test_fixture import simulated_test_runner +from proto.message_translation.tbots_protobuf import create_world_state +from proto.ssl_gc_common_pb2 import Team + +# TODO issue #2599 - Remove Duration parameter from test +# @pytest.mark.parametrize("run_enemy_ai,test_duration", [(False, 20), (True, 20)]) +def test_halt_play(simulated_test_runner): + + # starting point must be Point + ball_initial_pos = tbots.Point(4.5, -3) + + # Setup Bots + blue_bots = [ + tbots.Point(-3, 2.5), + tbots.Point(-3, 1.5), + tbots.Point(-3, 0.5), + tbots.Point(-3, -0.5), + tbots.Point(-3, -1.5), + tbots.Point(4.6, -3.1), + ] + + yellow_bots = [ + tbots.Point(1, 0), + tbots.Point(1, 2.5), + tbots.Point(1, -2.5), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + ] + + # Game Controller Setup + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.STOP, team=Team.UNKNOWN + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.NORMAL_START, team=Team.BLUE + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.CORNER_KICK, team=Team.BLUE + ) + + # Force play override here + blue_play = Play() + blue_play.name = PlayName.CornerKickPlay + + yellow_play = Play() + yellow_play.name = PlayName.HaltPlay + + 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.Vector(0, 0), + ), + ) + + # Always Validation + always_validation_sequence_set = [[]] + + # Eventually Validation + eventually_validation_sequence_set = [[]] + + simulated_test_runner.run_test( + eventually_validation_sequence_set=eventually_validation_sequence_set, + always_validation_sequence_set=always_validation_sequence_set, + test_timeout_s=25, + ) + +def test_corner_kick_play_top_right(simulated_test_runner): + + # starting point must be Point + ball_initial_pos = tbots.Point(4.5, 3) + + # Setup Bots + blue_bots = [ + tbots.Point(-3, 2.5), + tbots.Point(0, 1.5), + tbots.Point(0, 0.5), + tbots.Point(0, -0.5), + tbots.Point(0, -1.5), + tbots.Point(4.6, 3.1), + ] + + yellow_bots = [ + tbots.Point(1, 0), + tbots.Point(1, 2.5), + tbots.Point(1, -2.5), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + ] + + # Game Controller Setup + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.STOP, team=Team.UNKNOWN + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.NORMAL_START, team=Team.BLUE + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.CORNER_KICK, team=Team.BLUE + ) + + # Force play override here + blue_play = Play() + blue_play.name = PlayName.CornerKickPlay + + yellow_play = Play() + yellow_play.name = PlayName.HaltPlay + + 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.Vector(0, 0), + ), + ) + + # Always Validation + always_validation_sequence_set = [[]] + + # Eventually Validation + eventually_validation_sequence_set = [[]] + + simulated_test_runner.run_test( + eventually_validation_sequence_set=eventually_validation_sequence_set, + always_validation_sequence_set=always_validation_sequence_set, + test_timeout_s=25, + ) + +if __name__ == "__main__": + # Run the test, -s disables all capturing at -vv increases verbosity + sys.exit(pytest.main([__file__, "-svv"])) diff --git a/src/software/ai/hl/stp/play/kickoff_enemy_play_test.py b/src/software/ai/hl/stp/play/kickoff_enemy_play_test.py new file mode 100644 index 0000000000..a5129ded15 --- /dev/null +++ b/src/software/ai/hl/stp/play/kickoff_enemy_play_test.py @@ -0,0 +1,84 @@ +import sys + +import pytest + +import software.python_bindings as tbots +from proto.play_pb2 import Play, PlayName +from software.simulated_tests.ball_enters_region import * +from software.simulated_tests.simulated_test_fixture import simulated_test_runner +from proto.message_translation.tbots_protobuf import create_world_state +from proto.ssl_gc_common_pb2 import Team + +# TODO issue #2599 - Remove Duration parameter from test +# @pytest.mark.parametrize("run_enemy_ai,test_duration", [(False, 20), (True, 20)]) +def test_kickoff_enemy_play(simulated_test_runner): + + # starting point must be Point + ball_initial_pos = tbots.Point(0, 0) + + # Setup Bots + blue_bots = [ + tbots.Point(-3, 2.5), + tbots.Point(-3, 1.5), + tbots.Point(-3, 0.5), + tbots.Point(-3, -0.5), + tbots.Point(-3, -1.5), + tbots.Point(-3, -2.5), + ] + + yellow_bots = [ + tbots.Point(1, 0), + tbots.Point(1, 2.5), + tbots.Point(1, -2.5), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + ] + + # Game Controller Setup + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.STOP, team=Team.UNKNOWN + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.NORMAL_START, team=Team.BLUE + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.KICKOFF, team=Team.YELLOW + ) + + # Force play override here + blue_play = Play() + blue_play.name = PlayName.KickoffEnemyPlay + + yellow_play = Play() + yellow_play.name = PlayName.HaltPlay + + 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.Vector(0, 0), + ), + ) + + # Always Validation + always_validation_sequence_set = [[]] + + # Eventually Validation + eventually_validation_sequence_set = [[]] + + simulated_test_runner.run_test( + eventually_validation_sequence_set=eventually_validation_sequence_set, + always_validation_sequence_set=always_validation_sequence_set, + test_timeout_s=25, + ) + +if __name__ == "__main__": + # Run the test, -s disables all capturing at -vv increases verbosity + sys.exit(pytest.main([__file__, "-svv"])) From bddfc6d301f29f1968bab0b2870817f054e2c873 Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 8 Jun 2022 21:50:43 -0700 Subject: [PATCH 05/83] play updates --- src/software/ai/hl/stp/play/ball_placement_play_test.py | 2 +- src/software/ai/hl/stp/play/defense_play_test.py | 7 +++++-- src/software/simulated_tests/robot_halt.py | 0 3 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 src/software/simulated_tests/robot_halt.py diff --git a/src/software/ai/hl/stp/play/ball_placement_play_test.py b/src/software/ai/hl/stp/play/ball_placement_play_test.py index e5562ec901..4f48923005 100644 --- a/src/software/ai/hl/stp/play/ball_placement_play_test.py +++ b/src/software/ai/hl/stp/play/ball_placement_play_test.py @@ -11,7 +11,7 @@ from proto.ssl_gc_geometry_pb2 import Vector2 # TODO issue #2599 - Remove Duration parameter from test -@pytest.mark.parametrize("run_enemy_ai,test_duration", [(False, 20), (True, 20)]) +@pytest.mark.parametrize("run_enemy_ai,test_duration", [[False,20],(True, 10)]) def test_two_ai_ball_placement(simulated_test_runner, run_enemy_ai, test_duration): # starting point must be Point diff --git a/src/software/ai/hl/stp/play/defense_play_test.py b/src/software/ai/hl/stp/play/defense_play_test.py index edf3c39153..6bf8d3c5f3 100644 --- a/src/software/ai/hl/stp/play/defense_play_test.py +++ b/src/software/ai/hl/stp/play/defense_play_test.py @@ -5,6 +5,7 @@ import software.python_bindings as tbots from proto.play_pb2 import Play, PlayName from software.simulated_tests.ball_enters_region import * +from software.simulated_tests.ball_enters_region import * from software.simulated_tests.simulated_test_fixture import simulated_test_runner from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team @@ -204,8 +205,10 @@ def test_defense_play_close_to_net(simulated_test_runner): always_validation_sequence_set = [[]] # Eventually Validation - eventually_validation_sequence_set = [[]] - + eventually_validation_sequence_set = [ + [ + BallEventuallyEntersRegion(regions=[]),] + ] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, diff --git a/src/software/simulated_tests/robot_halt.py b/src/software/simulated_tests/robot_halt.py new file mode 100644 index 0000000000..e69de29bb2 From 84ad9e447559c37b91f883b4f7b2b378af1cb6b3 Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 22 Jun 2022 00:10:09 -0700 Subject: [PATCH 06/83] test_updates --- src/software/ai/hl/stp/play/BUILD | 53 ++++++++++- .../hl/stp/play/ball_placement_play_test.py | 2 +- .../ai/hl/stp/play/corner_kick_play_test.py | 13 +-- .../ai/hl/stp/play/defense_play_test.py | 34 ++++--- ...my_play_test.py => free_kick_play_test.py} | 36 +++---- src/software/ai/hl/stp/play/halt_play_test.py | 95 +++---------------- .../hl/stp/play/offense/offense_play_test.py | 5 +- src/software/simulated_tests/BUILD | 2 + .../simulated_tests/friendly_goal_scored.py | 53 +++++++++++ .../simulated_tests/robot_enters_region.py | 53 +++++++++++ src/software/simulated_tests/robot_halt.py | 49 ++++++++++ .../simulated_tests/simulated_test_fixture.py | 20 ++++ 12 files changed, 289 insertions(+), 126 deletions(-) rename src/software/ai/hl/stp/play/{kickoff_enemy_play_test.py => free_kick_play_test.py} (65%) create mode 100644 src/software/simulated_tests/friendly_goal_scored.py diff --git a/src/software/ai/hl/stp/play/BUILD b/src/software/ai/hl/stp/play/BUILD index f4abb7bcac..d39701858a 100644 --- a/src/software/ai/hl/stp/play/BUILD +++ b/src/software/ai/hl/stp/play/BUILD @@ -326,7 +326,7 @@ cc_test( ) cc_test( - name = "kickoff_friendly_play_test", + name = "kickoff_friendly_play_cpp_test", srcs = ["kickoff_friendly_play_test.cpp"], deps = [ "//shared/test_util:tbots_gtest_main", @@ -342,7 +342,7 @@ cc_test( ) cc_test( - name = "kickoff_enemy_play_test", + name = "kickoff_enemy_play_cpp_test", srcs = ["kickoff_enemy_play_test.cpp"], deps = [ "//shared/test_util:tbots_gtest_main", @@ -358,6 +358,22 @@ cc_test( ], ) +py_test( + name = "kickoff_test", + srcs = [ + "kickoff_test.py", + ], + # TODO (#2619) Remove tag to run in parallel + tags = [ + "exclusive", + ], + deps = [ + "//software/simulated_tests:simulated_test_fixture", + "//software/simulated_tests:validation", + requirement("pytest"), + ], +) + cc_test( name = "corner_kick_play_cpp_test", srcs = ["corner_kick_play_test.cpp"], @@ -374,7 +390,7 @@ cc_test( ) py_test( - name = "corner_kick_play_test.py", + name = "corner_kick_play_test", srcs = [ "corner_kick_play_test.py", ], @@ -469,7 +485,7 @@ cc_test( ) cc_test( - name = "halt_play_test", + name = "halt_play_cpp_test", srcs = ["halt_play_test.cpp"], deps = [ "//shared/test_util:tbots_gtest_main", @@ -483,8 +499,24 @@ cc_test( ], ) +py_test( + name = "halt_play_test", + srcs = [ + "halt_play_test.py", + ], + # TODO (#2619) Remove tag to run in parallel + tags = [ + "exclusive", + ], + deps = [ + "//software/simulated_tests:simulated_test_fixture", + "//software/simulated_tests:validation", + requirement("pytest"), + ], +) + cc_test( - name = "free_kick_play_test", + name = "free_kick_play_cpp_test", srcs = ["free_kick_play_test.cpp"], deps = [ "//shared/test_util:tbots_gtest_main", @@ -497,6 +529,17 @@ cc_test( ], ) +py_test( + name = "free_kick_play_test", + srcs = ["free_kick_play_test.py"], + tags = ["exclusive",], + deps = [ + "//software/simulated_tests:simulated_test_fixture", + "//software/simulated_tests:validation", + requirement("pytest"), + ], +) + cc_test( name = "shoot_or_chip_play_test", srcs = ["shoot_or_chip_play_test.cpp"], diff --git a/src/software/ai/hl/stp/play/ball_placement_play_test.py b/src/software/ai/hl/stp/play/ball_placement_play_test.py index 8e459b5a9f..3388fcd6cf 100644 --- a/src/software/ai/hl/stp/play/ball_placement_play_test.py +++ b/src/software/ai/hl/stp/play/ball_placement_play_test.py @@ -12,7 +12,7 @@ from proto.ssl_gc_geometry_pb2 import Vector2 # TODO issue #2599 - Remove Duration parameter from test -@pytest.mark.parametrize("run_enemy_ai,test_duration", [[False,20],(True, 10)]) +@pytest.mark.parametrize("run_enemy_ai,test_duration", [[False,10],(True, 10)]) def test_two_ai_ball_placement(simulated_test_runner, run_enemy_ai, test_duration): # starting point must be Point diff --git a/src/software/ai/hl/stp/play/corner_kick_play_test.py b/src/software/ai/hl/stp/play/corner_kick_play_test.py index 936d840143..0525f48fc3 100644 --- a/src/software/ai/hl/stp/play/corner_kick_play_test.py +++ b/src/software/ai/hl/stp/play/corner_kick_play_test.py @@ -5,6 +5,7 @@ import software.python_bindings as tbots from proto.play_pb2 import Play, PlayName from software.simulated_tests.ball_enters_region import * +from software.simulated_tests.friendly_goal_scored import * from software.simulated_tests.simulated_test_fixture import simulated_test_runner from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team @@ -43,7 +44,7 @@ def test_corner_kick_play_bottom_left(simulated_test_runner): gc_command=Command.Type.NORMAL_START, team=Team.BLUE ) simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.CORNER_KICK, team=Team.BLUE + gc_command=Command.Type.DIRECT, team=Team.BLUE ) # Force play override here @@ -68,10 +69,10 @@ def test_corner_kick_play_bottom_left(simulated_test_runner): ) # Always Validation - always_validation_sequence_set = [[]] + always_validation_sequence_set = [] # Eventually Validation - eventually_validation_sequence_set = [[]] + eventually_validation_sequence_set = [[FriendlyGoalEventuallyScored()]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, @@ -111,7 +112,7 @@ def test_corner_kick_play_top_right(simulated_test_runner): gc_command=Command.Type.NORMAL_START, team=Team.BLUE ) simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.CORNER_KICK, team=Team.BLUE + gc_command=Command.Type.DIRECT, team=Team.BLUE ) # Force play override here @@ -136,10 +137,10 @@ def test_corner_kick_play_top_right(simulated_test_runner): ) # Always Validation - always_validation_sequence_set = [[]] + always_validation_sequence_set = [] # Eventually Validation - eventually_validation_sequence_set = [[]] + eventually_validation_sequence_set = [[FriendlyGoalEventuallyScored()]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, diff --git a/src/software/ai/hl/stp/play/defense_play_test.py b/src/software/ai/hl/stp/play/defense_play_test.py index 6bf8d3c5f3..56ef0a06c8 100644 --- a/src/software/ai/hl/stp/play/defense_play_test.py +++ b/src/software/ai/hl/stp/play/defense_play_test.py @@ -4,8 +4,8 @@ import software.python_bindings as tbots from proto.play_pb2 import Play, PlayName -from software.simulated_tests.ball_enters_region import * -from software.simulated_tests.ball_enters_region import * +from software.simulated_tests.robot_halt import * +from software.simulated_tests.robot_enters_region import * from software.simulated_tests.simulated_test_fixture import simulated_test_runner from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team @@ -40,9 +40,9 @@ def test_defense_play(simulated_test_runner): simulated_test_runner.gamecontroller.send_ci_input( gc_command=Command.Type.STOP, team=Team.UNKNOWN ) - simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.FORCE_START, team=Team.BLUE - ) + #simulated_test_runner.gamecontroller.send_ci_input( + # gc_command=Command.Type.FORCE_START, team=Team.BLUE + #) # Force play override here blue_play = Play() @@ -67,9 +67,24 @@ def test_defense_play(simulated_test_runner): # Always Validation always_validation_sequence_set = [[]] - + # Eventually Validation - eventually_validation_sequence_set = [[]] + eventually_validation_sequence_set = [ + [ + RobotHaltEventually(), + RobotEventuallyEntersRegion( + [ + tbots.Rectangle(tbots.Point(0,2.85), + tbots.Point(0.9,2)), + tbots.Rectangle(tbots.Point(0.5,2.5), + tbots.Point(1,2)), + tbots.Rectangle(tbots.Point(-2,-0.75), + tbots.Point(-1.5,-1.25)), + ] + ), + + ] + ] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, @@ -205,10 +220,7 @@ def test_defense_play_close_to_net(simulated_test_runner): always_validation_sequence_set = [[]] # Eventually Validation - eventually_validation_sequence_set = [ - [ - BallEventuallyEntersRegion(regions=[]),] - ] + eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, diff --git a/src/software/ai/hl/stp/play/kickoff_enemy_play_test.py b/src/software/ai/hl/stp/play/free_kick_play_test.py similarity index 65% rename from src/software/ai/hl/stp/play/kickoff_enemy_play_test.py rename to src/software/ai/hl/stp/play/free_kick_play_test.py index a5129ded15..10c666a8c9 100644 --- a/src/software/ai/hl/stp/play/kickoff_enemy_play_test.py +++ b/src/software/ai/hl/stp/play/free_kick_play_test.py @@ -5,25 +5,26 @@ import software.python_bindings as tbots from proto.play_pb2 import Play, PlayName from software.simulated_tests.ball_enters_region import * +from software.simulated_tests.friendly_goal_scored import * from software.simulated_tests.simulated_test_fixture import simulated_test_runner from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team -# TODO issue #2599 - Remove Duration parameter from test -# @pytest.mark.parametrize("run_enemy_ai,test_duration", [(False, 20), (True, 20)]) -def test_kickoff_enemy_play(simulated_test_runner): +# We want to test friendly half, enemy half, and at the border of the field +@pytest.mark.parametrize("ball_pos",[tbots.Point(1.5,-2.75),tbots.Point(-1.5,-2.75),tbots.Point(1.5,-3)]) +def test_free_kick_play(simulated_test_runner, ball_pos): # starting point must be Point - ball_initial_pos = tbots.Point(0, 0) + ball_initial_pos = ball_pos # Setup Bots blue_bots = [ - tbots.Point(-3, 2.5), + tbots.Point(-4.5, 0), tbots.Point(-3, 1.5), tbots.Point(-3, 0.5), tbots.Point(-3, -0.5), tbots.Point(-3, -1.5), - tbots.Point(-3, -2.5), + tbots.Point(4, -2.5), ] yellow_bots = [ @@ -43,18 +44,18 @@ def test_kickoff_enemy_play(simulated_test_runner): gc_command=Command.Type.NORMAL_START, team=Team.BLUE ) simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.KICKOFF, team=Team.YELLOW + gc_command=Command.Type.DIRECT, team=Team.BLUE ) # Force play override here - blue_play = Play() - blue_play.name = PlayName.KickoffEnemyPlay + # blue_play = Play() + # blue_play.name = PlayName.FreeKickPlay - yellow_play = Play() - yellow_play.name = PlayName.HaltPlay + # yellow_play = Play() + # yellow_play.name = PlayName.HaltPlay - 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) + # 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( @@ -68,17 +69,18 @@ def test_kickoff_enemy_play(simulated_test_runner): ) # Always Validation - always_validation_sequence_set = [[]] + always_validation_sequence_set = [] # Eventually Validation - eventually_validation_sequence_set = [[]] + # We should always score against robots which are standing still + eventually_validation_sequence_set = [[FriendlyGoalEventuallyScored()]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, - test_timeout_s=25, + test_timeout_s=10, ) if __name__ == "__main__": # Run the test, -s disables all capturing at -vv increases verbosity - sys.exit(pytest.main([__file__, "-svv"])) + sys.exit(pytest.main([__file__, "-svv"])) \ No newline at end of file diff --git a/src/software/ai/hl/stp/play/halt_play_test.py b/src/software/ai/hl/stp/play/halt_play_test.py index 54f509b089..a7c411ca20 100644 --- a/src/software/ai/hl/stp/play/halt_play_test.py +++ b/src/software/ai/hl/stp/play/halt_play_test.py @@ -4,7 +4,7 @@ import software.python_bindings as tbots from proto.play_pb2 import Play, PlayName -from software.simulated_tests.ball_enters_region import * +from software.simulated_tests.robot_halt import * from software.simulated_tests.simulated_test_fixture import simulated_test_runner from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team @@ -14,7 +14,7 @@ def test_halt_play(simulated_test_runner): # starting point must be Point - ball_initial_pos = tbots.Point(4.5, -3) + ball_initial_pos = tbots.Point(0, 0) # Setup Bots blue_bots = [ @@ -23,7 +23,7 @@ def test_halt_play(simulated_test_runner): tbots.Point(-3, 0.5), tbots.Point(-3, -0.5), tbots.Point(-3, -1.5), - tbots.Point(4.6, -3.1), + tbots.Point(-3, -2.5), ] yellow_bots = [ @@ -40,89 +40,15 @@ def test_halt_play(simulated_test_runner): gc_command=Command.Type.STOP, team=Team.UNKNOWN ) simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.NORMAL_START, team=Team.BLUE + gc_command=Command.Type.FORCE_START, team=Team.UNKNOWN ) - simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.CORNER_KICK, team=Team.BLUE - ) - - # Force play override here - blue_play = Play() - blue_play.name = PlayName.CornerKickPlay - - yellow_play = Play() - yellow_play.name = PlayName.HaltPlay - - 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.Vector(0, 0), - ), - ) - - # Always Validation - always_validation_sequence_set = [[]] - - # Eventually Validation - eventually_validation_sequence_set = [[]] - - simulated_test_runner.run_test( - eventually_validation_sequence_set=eventually_validation_sequence_set, - always_validation_sequence_set=always_validation_sequence_set, - test_timeout_s=25, - ) - -def test_corner_kick_play_top_right(simulated_test_runner): - - # starting point must be Point - ball_initial_pos = tbots.Point(4.5, 3) - - # Setup Bots - blue_bots = [ - tbots.Point(-3, 2.5), - tbots.Point(0, 1.5), - tbots.Point(0, 0.5), - tbots.Point(0, -0.5), - tbots.Point(0, -1.5), - tbots.Point(4.6, 3.1), - ] - - yellow_bots = [ - tbots.Point(1, 0), - tbots.Point(1, 2.5), - tbots.Point(1, -2.5), - tbots.Field.createSSLDivisionBField().enemyGoalCenter(), - tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), - tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), - ] - - # Game Controller Setup - simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.STOP, team=Team.UNKNOWN - ) - simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.NORMAL_START, team=Team.BLUE - ) - simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.CORNER_KICK, team=Team.BLUE - ) - - # Force play override here - blue_play = Play() - blue_play.name = PlayName.CornerKickPlay - yellow_play = Play() - yellow_play.name = PlayName.HaltPlay + # Structure for a delayed call is tuple (delay in seconds, command, team) + blue_delayed_ci_call = (3,Command.Type.HALT, Team.BLUE) + yellow_delayed_ci_call = (3,Command.Type.HALT, Team.YELLOW) - 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) + # No plays to override. AI does whatever for 3 seconds before HALT CMD + # is issued # Create world state simulated_test_runner.simulator_proto_unix_io.send_proto( @@ -139,12 +65,13 @@ def test_corner_kick_play_top_right(simulated_test_runner): always_validation_sequence_set = [[]] # Eventually Validation - eventually_validation_sequence_set = [[]] + eventually_validation_sequence_set = [[RobotEventuallyHalt()]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, test_timeout_s=25, + ci_cmd_with_delay=[blue_delayed_ci_call, yellow_delayed_ci_call] ) if __name__ == "__main__": diff --git a/src/software/ai/hl/stp/play/offense/offense_play_test.py b/src/software/ai/hl/stp/play/offense/offense_play_test.py index 1e2e7ba276..fe882af80e 100644 --- a/src/software/ai/hl/stp/play/offense/offense_play_test.py +++ b/src/software/ai/hl/stp/play/offense/offense_play_test.py @@ -4,6 +4,7 @@ import software.python_bindings as tbots from proto.play_pb2 import Play, PlayName +from software.simulated_tests.friendly_goal_scored import * from software.simulated_tests.ball_enters_region import * from software.simulated_tests.simulated_test_fixture import simulated_test_runner from proto.message_translation.tbots_protobuf import create_world_state @@ -67,10 +68,10 @@ def test_offense_play(simulated_test_runner): ) # Always Validation - always_validation_sequence_set = [[]] + always_validation_sequence_set = [[BallAlwaysStaysInRegion([tbots.Field.createSSLDivisionBField().fieldLines()])]] # Eventually Validation - eventually_validation_sequence_set = [[]] + eventually_validation_sequence_set = [[FriendlyGoalEventuallyScored()]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, diff --git a/src/software/simulated_tests/BUILD b/src/software/simulated_tests/BUILD index 509b8b3548..2f1eb8793d 100644 --- a/src/software/simulated_tests/BUILD +++ b/src/software/simulated_tests/BUILD @@ -67,6 +67,8 @@ py_library( "robot_enters_region.py", "robot_speed_threshold.py", "validation.py", + "robot_halt.py", + "friendly_goal_scored.py" ], data = [ "//software:py_constants.so", diff --git a/src/software/simulated_tests/friendly_goal_scored.py b/src/software/simulated_tests/friendly_goal_scored.py new file mode 100644 index 0000000000..33ed11d9eb --- /dev/null +++ b/src/software/simulated_tests/friendly_goal_scored.py @@ -0,0 +1,53 @@ +import software.python_bindings as tbots +from proto.import_all_protos import * + +from software.simulated_tests.validation import ( + Validation, + create_validation_geometry, + create_validation_types, +) + + +class FriendlyGoalScored(Validation): + + """Checks if a ball enters the enemy goal.""" + + def __init__(self): + self.region = tbots.Field.createSSLDivisionBField().enemyGoal() + + def get_validation_status(self, world) -> ValidationStatus: + """Checks if the ball enters the provided regions + + :param world: The world msg to validate + :returns: FAILING until a ball enters the enemy goal + PASSING when a ball enters + """ + + if tbots.contains( + self.region, tbots.createPoint(world.ball.current_state.global_position) + ): + return ValidationStatus.PASSING + + return ValidationStatus.FAILING + + def get_validation_geometry(self, world) -> ValidationGeometry: + """Returns the underlying geometry this validation is checking + + :param world: The world msg to create v alidation geometry from + :returns: ValidationGeometry containing geometry to visualize + + """ + return create_validation_geometry([self.region]) + + def __repr__(self): + return "Checking ball in " + ",".join( + repr(self.region) + ) + + +( + FriendlyGoalEventuallyScored, + FriendlyGoalEventuallyRemoved, # These two don't make much sense + FriendlyGoalAlwaysScored, # These two don't make much sense + FriendlyGoalNeverScored, +) = create_validation_types(FriendlyGoalScored) diff --git a/src/software/simulated_tests/robot_enters_region.py b/src/software/simulated_tests/robot_enters_region.py index 1fa0aa31e3..4ad33ce485 100644 --- a/src/software/simulated_tests/robot_enters_region.py +++ b/src/software/simulated_tests/robot_enters_region.py @@ -49,3 +49,56 @@ def __repr__(self): RobotAlwaysStaysInRegion, RobotNeverEntersRegion, ) = create_validation_types(RobotEntersRegion) + +class NumberOfRobotsEntersRegion(Validation): + + """Checks if a certain number of Robots enters a specific region.""" + + def __init__(self, region, req_robot_cnt): + self.region = region + self.req_robot_cnt = req_robot_cnt + # map to keep track of robot positions + self.robot_in_zone = {} + + def get_validation_status(self, world) -> ValidationStatus: + """Checks if a specific number of robots enter the provided region + + :param world: The world msg to validate + :returns: FAILING until req_robot_cnt robots enter the region + PASSING when req_robot_cnt robots enters + """ + # Update the map with latest robot status + for robot in world.friendly_team.team_robots: + self.robot_in_zone[robot.id()] = tbots.contains( + self.region, tbots.createPoint(robot.current_state.global_position) + ) + # Check if there are at least req_robot_cnt number of robots in zone + curr_cnt = 0 + for robot_id in self.robot_in_zone: + if self.robot_in_zone[robot_id]: + curr_cnt +=1 + + # Validate on curr_cnt + if curr_cnt == self.req_robot_cnt: + return ValidationStatus.PASSING + else: + return ValidationStatus.FAILING + + def get_validation_geometry(self, world) -> ValidationGeometry: + """ + (override) shows region to enter + """ + return create_validation_geometry([self.region]) + + def __repr__(self): + return "Check for " + str(self.req_robot_cnt) + " robots in region " + ",".join( + repr(self.region) + ) + + +( + NumberOfRobotsEventuallyEntersRegion, + NumberOfRobotsEventuallyExitsRegion, + NumberOfRobotsAlwaysStaysInRegion, + NumberOfRobotsNeverEntersRegion, +) = create_validation_types(NumberOfRobotsEntersRegion) diff --git a/src/software/simulated_tests/robot_halt.py b/src/software/simulated_tests/robot_halt.py index e69de29bb2..6e517fcc1d 100644 --- a/src/software/simulated_tests/robot_halt.py +++ b/src/software/simulated_tests/robot_halt.py @@ -0,0 +1,49 @@ +import software.python_bindings as tbots +from proto.import_all_protos import * + +from software.simulated_tests.validation import ( + Validation, + create_validation_geometry, + create_validation_types, +) + + +class RobotHalt(Validation): + + """Checks if the friendly robots' are halted.""" + + def __init__(self): + """ + :param speed_threshold: The speed threshold + """ + + def get_validation_status(self, world) -> ValidationStatus: + """Checks if the friendly robots' are stopped + + :param world: The world msg to validate + :returns: FAILING if the friendly robots' speed is above 1e-3 + PASSING if the friendly robots' speed is at or below 1e-3 + """ + for robot in world.friendly_team.team_robots: + if ( + tbots.createVector(robot.current_state.global_velocity).length() + > 1e-3 + ): + return ValidationStatus.FAILING + return ValidationStatus.PASSING + + def get_validation_geometry(self, world) -> ValidationGeometry: + """override""" + # TODO (#2556): visualize + return create_validation_geometry([]) + + def __repr__(self): + return "Check that the friendly robots' halted " + + +( + RobotEventuallyHalt, + RobotEventuallyMoves, + RobotAlwaysHalt, + RobotAlwaysMoves, +) = create_validation_types(RobotHalt) diff --git a/src/software/simulated_tests/simulated_test_fixture.py b/src/software/simulated_tests/simulated_test_fixture.py index 0e4d278205..3857100df7 100644 --- a/src/software/simulated_tests/simulated_test_fixture.py +++ b/src/software/simulated_tests/simulated_test_fixture.py @@ -101,6 +101,7 @@ def run_test( eventually_validation_sequence_set=[[]], test_timeout_s=3, tick_duration_s=0.0166, # Default to 60hz + ci_cmd_with_delay=[], ): """Run a test @@ -111,6 +112,13 @@ def run_test( :param test_timeout_s: The timeout for the test, if any eventually_validations remain after the timeout, the test fails. :param tick_duration_s: The simulation step duration + :param ci_cmd_with_delay: A list consisting of a duration, and a + tuple forming a ci command + { + (time, command, team), + (time, command, team), + ... + } """ @@ -133,6 +141,18 @@ def __runner(): time_elapsed_s = 0 while time_elapsed_s < test_timeout_s: + + # Check for new CI commands at this time step + for (delay,cmd,team) in ci_cmd_with_delay: + # If delay matches time + if delay <= time_elapsed_s: + # send command + self.gamecontroller.send_ci_input( + cmd, team + ) + # remove command from the list + ci_cmd_with_delay.remove((delay,cmd,team)) + # Update the timestamp logged by the ProtoLogger with self.timestamp_mutex: From 2aea34d5f05a69410b7046a6c5cd1a536975ce9b Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 22 Jun 2022 00:18:14 -0700 Subject: [PATCH 07/83] minor cleanup --- src/software/ai/hl/stp/play/defense_play_test.py | 6 +++--- src/software/ai/hl/stp/play/free_kick_play_test.py | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/software/ai/hl/stp/play/defense_play_test.py b/src/software/ai/hl/stp/play/defense_play_test.py index 56ef0a06c8..dd51023616 100644 --- a/src/software/ai/hl/stp/play/defense_play_test.py +++ b/src/software/ai/hl/stp/play/defense_play_test.py @@ -40,9 +40,9 @@ def test_defense_play(simulated_test_runner): simulated_test_runner.gamecontroller.send_ci_input( gc_command=Command.Type.STOP, team=Team.UNKNOWN ) - #simulated_test_runner.gamecontroller.send_ci_input( - # gc_command=Command.Type.FORCE_START, team=Team.BLUE - #) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.FORCE_START, team=Team.BLUE + ) # Force play override here blue_play = Play() diff --git a/src/software/ai/hl/stp/play/free_kick_play_test.py b/src/software/ai/hl/stp/play/free_kick_play_test.py index 10c666a8c9..1f462b8b4f 100644 --- a/src/software/ai/hl/stp/play/free_kick_play_test.py +++ b/src/software/ai/hl/stp/play/free_kick_play_test.py @@ -48,14 +48,14 @@ def test_free_kick_play(simulated_test_runner, ball_pos): ) # Force play override here - # blue_play = Play() - # blue_play.name = PlayName.FreeKickPlay + blue_play = Play() + blue_play.name = PlayName.FreeKickPlay - # yellow_play = Play() - # yellow_play.name = PlayName.HaltPlay + yellow_play = Play() + yellow_play.name = PlayName.HaltPlay - # 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) + 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( From 3b3f270b909ae51542077f1ada73803da67cea7f Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 22 Jun 2022 22:37:15 -0700 Subject: [PATCH 08/83] kickoff_play test concept --- src/software/ai/hl/stp/play/kickoff_test.py | 155 ++++++++++++++++++ .../simulated_tests/robot_enters_region.py | 2 +- 2 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 src/software/ai/hl/stp/play/kickoff_test.py diff --git a/src/software/ai/hl/stp/play/kickoff_test.py b/src/software/ai/hl/stp/play/kickoff_test.py new file mode 100644 index 0000000000..4fffa10564 --- /dev/null +++ b/src/software/ai/hl/stp/play/kickoff_test.py @@ -0,0 +1,155 @@ +import sys + +import pytest + +import software.python_bindings as tbots +from proto.play_pb2 import Play, PlayName +from software.simulated_tests.friendly_has_ball_possession import * +from software.simulated_tests.robot_enters_region import * +from software.simulated_tests.simulated_test_fixture import simulated_test_runner +from proto.message_translation.tbots_protobuf import create_world_state +from proto.ssl_gc_common_pb2 import Team + +kickoff_friendly_always_validation = [ + [ + RobotNeverEntersRegion([tbots.Field.createSSLDivisionBField().enemyHalf()]), + FriendlyNeverHasBallPossession() + ] +] + +kickoff_friendly_eventually_validation = [ + [ + # Robot in center circle + NumberOfRobotsEventuallyEntersRegion( + tbots.Field.createSSLDivisionBField().centerCircle(), + 1 + ), + # Attacking Robot Placement + NumberOfRobotsEventuallyEntersRegion( + tbots.Rectangle(tbots.Point(-0.5, 2.5), tbots.Point(-1.5, -2.5)), + 2 + ), + # Defending Robot Placement + NumberOfRobotsEventuallyEntersRegion( + tbots.Rectangle(tbots.Point(-3.2, 1.1), tbots.Point(-3.51, -1.1)), + 3 + ) + ] +] + +kickoff_enemy_always_validation = [ + [ + RobotNeverEntersRegion([ + tbots.Field.createSSLDivisionBField().enemyHalf(), + tbots.Field.createSSLDivisionBField().centerCircle() + ] + ), + FriendlyNeverHasBallPossession() + ] +] + +kickoff_enemy_eventually_validation = [ + [ + # Front 3 robots spread out in 3 zones + NumberOfRobotsEventuallyEntersRegion( + tbots.Rectangle(tbots.Point(-0.2, 1), tbots.Point(-0.4, 0.25)), + 1 + ), + NumberOfRobotsEventuallyEntersRegion( + tbots.Rectangle(tbots.Point(-0.2, -1), tbots.Point(-0.4, -0.25)), + 1 + ), + NumberOfRobotsEventuallyEntersRegion( + tbots.Rectangle(tbots.Point(-0.6, 0.1), tbots.Point(-0.9,-0.1)), + 1 + ), + # 2 robots Defend the box + NumberOfRobotsEventuallyEntersRegion( + tbots.Rectangle(tbots.Point(-3.2,1.1), tbots.Point(-3.5, -1.1)), + 2 + ) + ] +] + +@pytest.mark.parametrize("always_validation_list,eventually_validation_list,is_friendly_test", [ + (kickoff_friendly_always_validation,kickoff_friendly_eventually_validation, True), + (kickoff_enemy_always_validation,kickoff_enemy_eventually_validation, False), + ] +) +def test_kickoff_play(simulated_test_runner, always_validation_list, eventually_validation_list, is_friendly_test): + + # starting point must be Point + ball_initial_pos = tbots.Point(0, 0) + + # Setup Bots + blue_bots = [ + tbots.Point(-3, 2.5), + tbots.Point(-3, 1.5), + tbots.Point(-3, 0.5), + tbots.Point(-3, -0.5), + tbots.Point(-3, -1.5), + tbots.Point(-3, -2.5), + ] + + yellow_bots = [ + tbots.Point(1, 0), + tbots.Point(1, 2.5), + tbots.Point(1, -2.5), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + ] + + blue_play = Play() + yellow_play = Play() + + # Game Controller Setup + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.STOP, team=Team.UNKNOWN + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.NORMAL_START, team=Team.BLUE + ) + if is_friendly_test: + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.KICKOFF, team=Team.BLUE + ) + blue_play.name = PlayName.KickoffFriendlyPlay + yellow_play.name = PlayName.KickoffEnemyPlay + else: + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.KICKOFF, team=Team.YELLOW + ) + 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) + + # 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.Vector(0, 0), + ), + ) + + # Always Validation + always_validation_sequence_set = always_validation_list + + # Eventually Validation + eventually_validation_sequence_set = eventually_validation_list + + simulated_test_runner.run_test( + eventually_validation_sequence_set=eventually_validation_sequence_set, + always_validation_sequence_set=always_validation_sequence_set, + test_timeout_s=10, + ) + +if __name__ == "__main__": + # Run the test, -s disables all capturing at -vv increases verbosity + sys.exit(pytest.main([__file__, "-svv"])) diff --git a/src/software/simulated_tests/robot_enters_region.py b/src/software/simulated_tests/robot_enters_region.py index 4ad33ce485..fbb829e791 100644 --- a/src/software/simulated_tests/robot_enters_region.py +++ b/src/software/simulated_tests/robot_enters_region.py @@ -69,7 +69,7 @@ def get_validation_status(self, world) -> ValidationStatus: """ # Update the map with latest robot status for robot in world.friendly_team.team_robots: - self.robot_in_zone[robot.id()] = tbots.contains( + self.robot_in_zone[robot.id] = tbots.contains( self.region, tbots.createPoint(robot.current_state.global_position) ) # Check if there are at least req_robot_cnt number of robots in zone From 6b2b5ad07714b2ca18f74c986010baf232a4e50d Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 29 Jun 2022 21:48:19 -0700 Subject: [PATCH 09/83] updated free kick play test --- .../ai/hl/stp/play/free_kick_play_test.py | 207 +++++++++++++++--- 1 file changed, 182 insertions(+), 25 deletions(-) diff --git a/src/software/ai/hl/stp/play/free_kick_play_test.py b/src/software/ai/hl/stp/play/free_kick_play_test.py index 1f462b8b4f..ee1d10612a 100644 --- a/src/software/ai/hl/stp/play/free_kick_play_test.py +++ b/src/software/ai/hl/stp/play/free_kick_play_test.py @@ -11,51 +11,207 @@ from proto.ssl_gc_common_pb2 import Team # We want to test friendly half, enemy half, and at the border of the field +# @pytest.mark.parametrize("ball_pos",[tbots.Point(1.5,-2.75),tbots.Point(-1.5,-2.75),tbots.Point(1.5,-3)]) +# def test_free_kick_play_friendly(simulated_test_runner, ball_pos): + +# # starting point must be Point +# ball_initial_pos = ball_pos + +# # Setup Bots +# blue_bots = [ +# tbots.Point(-4.5, 0), +# tbots.Point(-3, 1.5), +# tbots.Point(-3, 0.5), +# tbots.Point(-3, -0.5), +# tbots.Point(-3, -1.5), +# tbots.Point(4, -2.5), +# ] + +# yellow_bots = [ +# tbots.Point(1, 0), +# tbots.Point(1, 2.5), +# tbots.Point(1, -2.5), +# tbots.Field.createSSLDivisionBField().enemyGoalCenter(), +# tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), +# tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), +# ] + +# # Game Controller Setup +# simulated_test_runner.gamecontroller.send_ci_input( +# gc_command=Command.Type.STOP, team=Team.UNKNOWN +# ) +# simulated_test_runner.gamecontroller.send_ci_input( +# gc_command=Command.Type.NORMAL_START, team=Team.BLUE +# ) +# simulated_test_runner.gamecontroller.send_ci_input( +# gc_command=Command.Type.DIRECT, team=Team.BLUE +# ) + +# # Force play override here +# blue_play = Play() +# blue_play.name = PlayName.FreeKickPlay + +# yellow_play = Play() +# yellow_play.name = PlayName.HaltPlay + +# 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.Vector(0, 0), +# ), +# ) + +# # Always Validation +# always_validation_sequence_set = [] + +# # Eventually Validation +# # We should always score against robots which are standing still +# eventually_validation_sequence_set = [[FriendlyGoalEventuallyScored()]] + +# simulated_test_runner.run_test( +# eventually_validation_sequence_set=eventually_validation_sequence_set, +# always_validation_sequence_set=always_validation_sequence_set, +# test_timeout_s=10, +# ) + +# @pytest.mark.parametrize("ball_pos,yellow_bot_pos", +# [ +# # not close to our net +# ( +# tbots.Point(0.9,2.85), +# [ +# tbots.Point(1, 3), +# tbots.Point(-2, -1.25), +# tbots.Point(-1, -0.25), +# tbots.Field.createSSLDivisionBField().enemyGoalCenter(), +# tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), +# tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), +# ], +# ), +# # close to our net +# ( +# tbots.Point(-2.4,1), +# [ +# tbots.Point(-2.3, 1.05), +# tbots.Point(-3.5, 2), +# tbots.Point(-1.2, 0), +# tbots.Point(-2.3,-1), +# tbots.Point(-3.8, -2), +# tbots.Field.createSSLDivisionBField().enemyGoalCenter(), +# ], +# ), +# ] +# ) +# def test_free_kick_play_enemy(simulated_test_runner, ball_pos, yellow_bot_pos): + +# # starting point must be Point +# ball_initial_pos = ball_pos + +# # Setup Bots +# blue_bots = [ +# tbots.Point(-4.5, 0), +# tbots.Point(-3, 1.5), +# tbots.Point(-3, 0.5), +# tbots.Point(-3, -0.5), +# tbots.Point(-3, -1.5), +# tbots.Point(4, -2.5), +# ] + +# yellow_bots = yellow_bot_pos +# # Game Controller Setup +# simulated_test_runner.gamecontroller.send_ci_input( +# gc_command=Command.Type.STOP, team=Team.UNKNOWN +# ) +# simulated_test_runner.gamecontroller.send_ci_input( +# gc_command=Command.Type.NORMAL_START, team=Team.BLUE +# ) +# simulated_test_runner.gamecontroller.send_ci_input( +# gc_command=Command.Type.DIRECT, team=Team.BLUE +# ) + +# # Force play override here +# blue_play = Play() +# blue_play.name = PlayName.EnemyFreekickPlay + +# yellow_play = Play() +# yellow_play.name = PlayName.HaltPlay + +# 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.Vector(0, 0), +# ), +# ) + +# # Always Validation +# always_validation_sequence_set = [] + +# # Eventually Validation +# # We should always score against robots which are standing still +# eventually_validation_sequence_set = [[FriendlyGoalEventuallyScored()]] + +# simulated_test_runner.run_test( +# eventually_validation_sequence_set=eventually_validation_sequence_set, +# always_validation_sequence_set=always_validation_sequence_set, +# test_timeout_s=10, +# ) + @pytest.mark.parametrize("ball_pos",[tbots.Point(1.5,-2.75),tbots.Point(-1.5,-2.75),tbots.Point(1.5,-3)]) -def test_free_kick_play(simulated_test_runner, ball_pos): +def test_free_kick_play_both(simulated_test_runner, ball_pos): - # starting point must be Point - ball_initial_pos = ball_pos + ball_initial_pos=ball_pos - # Setup Bots blue_bots = [ - tbots.Point(-4.5, 0), + tbots.Point(-3, 0.25), tbots.Point(-3, 1.5), tbots.Point(-3, 0.5), tbots.Point(-3, -0.5), tbots.Point(-3, -1.5), - tbots.Point(4, -2.5), + tbots.Point(-3, -0.25), ] yellow_bots = [ - tbots.Point(1, 0), - tbots.Point(1, 2.5), - tbots.Point(1, -2.5), - tbots.Field.createSSLDivisionBField().enemyGoalCenter(), - tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), - tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + tbots.Point(3, 0.25), + tbots.Point(3, 1.5), + tbots.Point(3, 0.5), + tbots.Point(3, -0.5), + tbots.Point(3, -1.5), + tbots.Point(3, -0.25), ] # Game Controller Setup simulated_test_runner.gamecontroller.send_ci_input( gc_command=Command.Type.STOP, team=Team.UNKNOWN ) - simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.NORMAL_START, team=Team.BLUE - ) - simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.DIRECT, team=Team.BLUE - ) + + delayed_ci_call = [ + (4, Command.Type.NORMAL_START, Team.BLUE), + (2, Command.Type.DIRECT, Team.BLUE) + ] # Force play override here - blue_play = Play() - blue_play.name = PlayName.FreeKickPlay + # blue_play = Play() + # blue_play.name = PlayName.EnemyFreekickPlay - yellow_play = Play() - yellow_play.name = PlayName.HaltPlay + # yellow_play = Play() + # yellow_play.name = PlayName.HaltPlay - 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) + # 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( @@ -78,7 +234,8 @@ def test_free_kick_play(simulated_test_runner, ball_pos): simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, - test_timeout_s=10, + test_timeout_s=15, + ci_cmd_with_delay=delayed_ci_call ) if __name__ == "__main__": From 4a6d5b81ca0f35f2db9784e4e75dc2365ee39ec5 Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 29 Jun 2022 21:56:28 -0700 Subject: [PATCH 10/83] even more free_kick_play updates --- .../ai/hl/stp/play/free_kick_play_test.py | 341 +++++++++--------- 1 file changed, 169 insertions(+), 172 deletions(-) diff --git a/src/software/ai/hl/stp/play/free_kick_play_test.py b/src/software/ai/hl/stp/play/free_kick_play_test.py index ee1d10612a..457119fc3e 100644 --- a/src/software/ai/hl/stp/play/free_kick_play_test.py +++ b/src/software/ai/hl/stp/play/free_kick_play_test.py @@ -11,164 +11,164 @@ from proto.ssl_gc_common_pb2 import Team # We want to test friendly half, enemy half, and at the border of the field -# @pytest.mark.parametrize("ball_pos",[tbots.Point(1.5,-2.75),tbots.Point(-1.5,-2.75),tbots.Point(1.5,-3)]) -# def test_free_kick_play_friendly(simulated_test_runner, ball_pos): - -# # starting point must be Point -# ball_initial_pos = ball_pos - -# # Setup Bots -# blue_bots = [ -# tbots.Point(-4.5, 0), -# tbots.Point(-3, 1.5), -# tbots.Point(-3, 0.5), -# tbots.Point(-3, -0.5), -# tbots.Point(-3, -1.5), -# tbots.Point(4, -2.5), -# ] - -# yellow_bots = [ -# tbots.Point(1, 0), -# tbots.Point(1, 2.5), -# tbots.Point(1, -2.5), -# tbots.Field.createSSLDivisionBField().enemyGoalCenter(), -# tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), -# tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), -# ] - -# # Game Controller Setup -# simulated_test_runner.gamecontroller.send_ci_input( -# gc_command=Command.Type.STOP, team=Team.UNKNOWN -# ) -# simulated_test_runner.gamecontroller.send_ci_input( -# gc_command=Command.Type.NORMAL_START, team=Team.BLUE -# ) -# simulated_test_runner.gamecontroller.send_ci_input( -# gc_command=Command.Type.DIRECT, team=Team.BLUE -# ) - -# # Force play override here -# blue_play = Play() -# blue_play.name = PlayName.FreeKickPlay - -# yellow_play = Play() -# yellow_play.name = PlayName.HaltPlay - -# 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.Vector(0, 0), -# ), -# ) - -# # Always Validation -# always_validation_sequence_set = [] - -# # Eventually Validation -# # We should always score against robots which are standing still -# eventually_validation_sequence_set = [[FriendlyGoalEventuallyScored()]] - -# simulated_test_runner.run_test( -# eventually_validation_sequence_set=eventually_validation_sequence_set, -# always_validation_sequence_set=always_validation_sequence_set, -# test_timeout_s=10, -# ) - -# @pytest.mark.parametrize("ball_pos,yellow_bot_pos", -# [ -# # not close to our net -# ( -# tbots.Point(0.9,2.85), -# [ -# tbots.Point(1, 3), -# tbots.Point(-2, -1.25), -# tbots.Point(-1, -0.25), -# tbots.Field.createSSLDivisionBField().enemyGoalCenter(), -# tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), -# tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), -# ], -# ), -# # close to our net -# ( -# tbots.Point(-2.4,1), -# [ -# tbots.Point(-2.3, 1.05), -# tbots.Point(-3.5, 2), -# tbots.Point(-1.2, 0), -# tbots.Point(-2.3,-1), -# tbots.Point(-3.8, -2), -# tbots.Field.createSSLDivisionBField().enemyGoalCenter(), -# ], -# ), -# ] -# ) -# def test_free_kick_play_enemy(simulated_test_runner, ball_pos, yellow_bot_pos): - -# # starting point must be Point -# ball_initial_pos = ball_pos - -# # Setup Bots -# blue_bots = [ -# tbots.Point(-4.5, 0), -# tbots.Point(-3, 1.5), -# tbots.Point(-3, 0.5), -# tbots.Point(-3, -0.5), -# tbots.Point(-3, -1.5), -# tbots.Point(4, -2.5), -# ] - -# yellow_bots = yellow_bot_pos -# # Game Controller Setup -# simulated_test_runner.gamecontroller.send_ci_input( -# gc_command=Command.Type.STOP, team=Team.UNKNOWN -# ) -# simulated_test_runner.gamecontroller.send_ci_input( -# gc_command=Command.Type.NORMAL_START, team=Team.BLUE -# ) -# simulated_test_runner.gamecontroller.send_ci_input( -# gc_command=Command.Type.DIRECT, team=Team.BLUE -# ) - -# # Force play override here -# blue_play = Play() -# blue_play.name = PlayName.EnemyFreekickPlay - -# yellow_play = Play() -# yellow_play.name = PlayName.HaltPlay - -# 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.Vector(0, 0), -# ), -# ) - -# # Always Validation -# always_validation_sequence_set = [] - -# # Eventually Validation -# # We should always score against robots which are standing still -# eventually_validation_sequence_set = [[FriendlyGoalEventuallyScored()]] - -# simulated_test_runner.run_test( -# eventually_validation_sequence_set=eventually_validation_sequence_set, -# always_validation_sequence_set=always_validation_sequence_set, -# test_timeout_s=10, -# ) +@pytest.mark.parametrize("ball_pos",[tbots.Point(1.5,-2.75),tbots.Point(-1.5,-2.75),tbots.Point(1.5,-3)]) +def test_free_kick_play_friendly(simulated_test_runner, ball_pos): + + # starting point must be Point + ball_initial_pos = ball_pos + + # Setup Bots + blue_bots = [ + tbots.Point(-4.5, 0), + tbots.Point(-3, 1.5), + tbots.Point(-3, 0.5), + tbots.Point(-3, -0.5), + tbots.Point(-3, -1.5), + tbots.Point(4, -2.5), + ] + + yellow_bots = [ + tbots.Point(1, 0), + tbots.Point(1, 2.5), + tbots.Point(1, -2.5), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + ] + + # Game Controller Setup + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.STOP, team=Team.UNKNOWN + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.NORMAL_START, team=Team.BLUE + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.DIRECT, team=Team.BLUE + ) + + # Force play override here + blue_play = Play() + blue_play.name = PlayName.FreeKickPlay + + yellow_play = Play() + yellow_play.name = PlayName.HaltPlay + + 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.Vector(0, 0), + ), + ) + + # Always Validation + always_validation_sequence_set = [] + + # Eventually Validation + # We should always score against robots which are standing still + eventually_validation_sequence_set = [[FriendlyGoalEventuallyScored()]] + + simulated_test_runner.run_test( + eventually_validation_sequence_set=eventually_validation_sequence_set, + always_validation_sequence_set=always_validation_sequence_set, + test_timeout_s=10, + ) + +@pytest.mark.parametrize("ball_pos,yellow_bot_pos", + [ + # not close to our net + ( + tbots.Point(0.9,2.85), + [ + tbots.Point(1, 3), + tbots.Point(-2, -1.25), + tbots.Point(-1, -0.25), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + ], + ), + # close to our net + ( + tbots.Point(-2.4,1), + [ + tbots.Point(-2.3, 1.05), + tbots.Point(-3.5, 2), + tbots.Point(-1.2, 0), + tbots.Point(-2.3,-1), + tbots.Point(-3.8, -2), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + ], + ), + ] +) +def test_free_kick_play_enemy(simulated_test_runner, ball_pos, yellow_bot_pos): + + # starting point must be Point + ball_initial_pos = ball_pos + + # Setup Bots + blue_bots = [ + tbots.Point(-4.5, 0), + tbots.Point(-3, 1.5), + tbots.Point(-3, 0.5), + tbots.Point(-3, -0.5), + tbots.Point(-3, -1.5), + tbots.Point(4, -2.5), + ] + + yellow_bots = yellow_bot_pos + # Game Controller Setup + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.STOP, team=Team.UNKNOWN + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.NORMAL_START, team=Team.BLUE + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.DIRECT, team=Team.BLUE + ) + + # Force play override here + blue_play = Play() + blue_play.name = PlayName.EnemyFreekickPlay + + yellow_play = Play() + yellow_play.name = PlayName.HaltPlay + + 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.Vector(0, 0), + ), + ) + + # Always Validation + always_validation_sequence_set = [] + + # Eventually Validation + # TODO + eventually_validation_sequence_set = [[]] + + simulated_test_runner.run_test( + eventually_validation_sequence_set=eventually_validation_sequence_set, + always_validation_sequence_set=always_validation_sequence_set, + test_timeout_s=10, + ) @pytest.mark.parametrize("ball_pos",[tbots.Point(1.5,-2.75),tbots.Point(-1.5,-2.75),tbots.Point(1.5,-3)]) def test_free_kick_play_both(simulated_test_runner, ball_pos): @@ -197,21 +197,19 @@ def test_free_kick_play_both(simulated_test_runner, ball_pos): simulated_test_runner.gamecontroller.send_ci_input( gc_command=Command.Type.STOP, team=Team.UNKNOWN ) - - delayed_ci_call = [ - (4, Command.Type.NORMAL_START, Team.BLUE), - (2, Command.Type.DIRECT, Team.BLUE) - ] + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.FORCE_START, team=Team.UNKNOWN + ) # Force play override here - # blue_play = Play() - # blue_play.name = PlayName.EnemyFreekickPlay + blue_play = Play() + blue_play.name = PlayName.FreeKickPlay - # yellow_play = Play() - # yellow_play.name = PlayName.HaltPlay + yellow_play = Play() + yellow_play.name = PlayName.EnemyFreekickPlay - # 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) + 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( @@ -228,14 +226,13 @@ def test_free_kick_play_both(simulated_test_runner, ball_pos): always_validation_sequence_set = [] # Eventually Validation - # We should always score against robots which are standing still - eventually_validation_sequence_set = [[FriendlyGoalEventuallyScored()]] + # TODO + eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, test_timeout_s=15, - ci_cmd_with_delay=delayed_ci_call ) if __name__ == "__main__": From caf6175b5c2242952e86ab1625b4178e5f67f954 Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 6 Jul 2022 21:57:06 -0700 Subject: [PATCH 11/83] added penalty_kick_play_test --- src/software/ai/hl/stp/play/BUILD | 35 ++++++- .../hl/stp/play/enemy_ball_placement_play.cpp | 35 ++++++- .../play/enemy_ball_placement_play_test.py | 97 +++++++++++++++++++ .../ai/hl/stp/play/penalty_kick_play_test.cpp | 4 +- .../ai/hl/stp/play/penalty_kick_play_test.py | 80 +++++++++++++++ 5 files changed, 244 insertions(+), 7 deletions(-) create mode 100644 src/software/ai/hl/stp/play/enemy_ball_placement_play_test.py create mode 100644 src/software/ai/hl/stp/play/penalty_kick_play_test.py diff --git a/src/software/ai/hl/stp/play/BUILD b/src/software/ai/hl/stp/play/BUILD index 54ba078514..247a9a7a4c 100644 --- a/src/software/ai/hl/stp/play/BUILD +++ b/src/software/ai/hl/stp/play/BUILD @@ -438,7 +438,7 @@ py_test( ) cc_test( - name = "enemy_ball_placement_play_test", + name = "enemy_ball_placement_play_cpp_test", srcs = ["enemy_ball_placement_play_test.cpp"], deps = [ "//shared/test_util:tbots_gtest_main", @@ -453,6 +453,18 @@ cc_test( ], ) +py_test( + name = "enemy_ball_placement_play_test", + srcs = [ + "enemy_ball_placement_play_test.py", + ], + deps = [ + "//software/simulated_tests:simulated_test_fixture", + "//software/simulated_tests:validation", + requirement("pytest"), + ], +) + cc_test( name = "enemy_free_kick_play_test", srcs = ["enemy_free_kick_play_test.cpp"], @@ -532,7 +544,7 @@ cc_test( py_test( name = "free_kick_play_test", srcs = ["free_kick_play_test.py"], - tags = ["exclusive",], + tags = ["exclusive"], deps = [ "//software/simulated_tests:simulated_test_fixture", "//software/simulated_tests:validation", @@ -555,7 +567,7 @@ cc_test( ) cc_test( - name = "penalty_kick_play_test", + name = "penalty_kick_play_cpp_test", srcs = ["penalty_kick_play_test.cpp"], deps = [ "//shared/test_util:tbots_gtest_main", @@ -570,6 +582,23 @@ cc_test( ], ) +py_test( + name = "penalty_kick_play_test", + srcs = [ + "penalty_kick_play_test.py", + ], + # TODO (#2619) Remove tag to run in parallel + tags = [ + "exclusive", + ], + deps = [ + "//software/simulated_tests:simulated_test_fixture", + "//software/simulated_tests:validation", + requirement("pytest"), + ], +) + + cc_test( name = "penalty_kick_enemy_play_test", srcs = ["penalty_kick_enemy_play_test.cpp"], diff --git a/src/software/ai/hl/stp/play/enemy_ball_placement_play.cpp b/src/software/ai/hl/stp/play/enemy_ball_placement_play.cpp index 7e1023833a..90becb6011 100644 --- a/src/software/ai/hl/stp/play/enemy_ball_placement_play.cpp +++ b/src/software/ai/hl/stp/play/enemy_ball_placement_play.cpp @@ -37,6 +37,8 @@ void EnemyBallPlacementPlay::ballPlacementWithShadow( */ auto shadow_enemy = std::make_shared(); + bool enemy_at_ball = false; + do { auto enemy_threats = getAllEnemyThreats(world.field(), world.friendlyTeam(), @@ -56,10 +58,40 @@ void EnemyBallPlacementPlay::ballPlacementWithShadow( tactics_to_run[0].emplace_back(crease_defenders[1]); tactics_to_run[0].emplace_back(crease_defenders[2]); + Vector ball_to_net = (world.ball().position() - world.field().friendlyGoalCenter()) + .normalize(-0.75 - ROBOT_MAX_RADIUS_METERS); + Vector placement_to_net = (placement_point - world.field().friendlyGoalCenter()) .normalize(-0.75 - ROBOT_MAX_RADIUS_METERS); + + // If the enemy hasn't reached the ball yet, we use this flag to avoid shadowing + // so that we don't interfere with the enemy robots going to pick up the ball + if(!enemy_at_ball) + { + move_tactics[0]->updateControlParams( + world.ball().position() + ball_to_net + + ball_to_net.perpendicular().normalize(1.25 * + ROBOT_MAX_RADIUS_METERS), + ball_to_net.orientation() + Angle::half(), 0); + move_tactics[1]->updateControlParams( + world.ball().position() + ball_to_net - + ball_to_net.perpendicular().normalize(1.25 * + ROBOT_MAX_RADIUS_METERS), + ball_to_net.orientation() + Angle::half(), 0); + tactics_to_run[0].emplace_back(move_tactics[0]); + tactics_to_run[0].emplace_back(move_tactics[1]); + + // Check to update flag + for(auto enemy_robot : world.enemyTeam().getAllRobotsExceptGoalie()) + { + if(std::abs((enemy_robot.position() - world.ball().position()).length()) < 0.25) + { + enemy_at_ball = true; + } + } + } // if no threats, send two robots near placement point - if (enemy_threats.size() == 0) + else if (enemy_threats.size() == 0) { move_tactics[0]->updateControlParams( placement_point + placement_to_net + @@ -74,7 +106,6 @@ void EnemyBallPlacementPlay::ballPlacementWithShadow( tactics_to_run[0].emplace_back(move_tactics[0]); tactics_to_run[0].emplace_back(move_tactics[1]); } - // if there are threats, send one robot to placement point, and one shadows else { diff --git a/src/software/ai/hl/stp/play/enemy_ball_placement_play_test.py b/src/software/ai/hl/stp/play/enemy_ball_placement_play_test.py new file mode 100644 index 0000000000..f63a6a1197 --- /dev/null +++ b/src/software/ai/hl/stp/play/enemy_ball_placement_play_test.py @@ -0,0 +1,97 @@ +import pytest + +import software.python_bindings as tbots +from proto.play_pb2 import Play, PlayName +from software.simulated_tests.ball_enters_region import * +from software.simulated_tests.simulated_test_fixture import ( + simulated_test_runner, + pytest_main, +) +from proto.message_translation.tbots_protobuf import create_world_state +from proto.ssl_gc_common_pb2 import Team + +def test_two_ai_ball_placement(simulated_test_runner): + + # starting point must be Point + ball_initial_pos = tbots.Point(2, 2) + # placement point must be Vector2 to work with game controller + ball_final_pos = tbots.Point(-3, -2) + + # Setup Bots + blue_bots = [ + tbots.Point(-2.75, 2.5), + tbots.Point(-2.75, 1.5), + tbots.Point(-2.75, 0.5), + tbots.Point(-2.75, -0.5), + tbots.Point(-2.75, -1.5), + tbots.Point(4.6, -3.1), + ] + + yellow_bots = [ + tbots.Point(1, 0), + tbots.Point(1, 2.5), + tbots.Point(1, -2.5), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + ] + + # Game Controller Setup + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.STOP, team=Team.UNKNOWN + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.FORCE_START, team=Team.BLUE + ) + # Pass in placement point here - not required for all play tests + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.BALL_PLACEMENT, + team=Team.YELLOW, + final_ball_placement_point=ball_final_pos, + ) + + # Force play override here + blue_play = Play() + blue_play.name = PlayName.EnemyBallPlacementPlay + + simulated_test_runner.blue_full_system_proto_unix_io.send_proto(Play, blue_play) + + + yellow_play = Play() + yellow_play.name = PlayName.BallPlacementPlay + + 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.Vector(0, 0), + ), + ) + + # Always Validation + always_validation_sequence_set = [[]] + + # Eventually Validation + eventually_validation_sequence_set = [ + [ + # Ball should arrive within 5cm of placement point + # BallEventuallyEntersRegion(regions=[tbots.Circle(ball_final_pos, 0.05)]), + ] + ] + + simulated_test_runner.run_test( + eventually_validation_sequence_set=eventually_validation_sequence_set, + always_validation_sequence_set=always_validation_sequence_set, + test_timeout_s=15, + ) + + +if __name__ == "__main__": + pytest_main(__file__) diff --git a/src/software/ai/hl/stp/play/penalty_kick_play_test.cpp b/src/software/ai/hl/stp/play/penalty_kick_play_test.cpp index 941544cb69..5a4eb5a6e5 100644 --- a/src/software/ai/hl/stp/play/penalty_kick_play_test.cpp +++ b/src/software/ai/hl/stp/play/penalty_kick_play_test.cpp @@ -23,7 +23,7 @@ class PenaltyKickPlayTest : public SimulatedErForceSimPlayTestFixture }; // TODO (#2602): test failing since a robot isn't avoiding the ball -TEST_F(PenaltyKickPlayTest, DISABLED_test_penalty_kick_setup) +TEST_F(PenaltyKickPlayTest, /*DISABLED_*/test_penalty_kick_setup) { BallState ball_state(field.friendlyPenaltyMark(), Vector(0, 0)); auto friendly_robots = TestUtil::createStationaryRobotStatesWithId( @@ -67,7 +67,7 @@ TEST_F(PenaltyKickPlayTest, DISABLED_test_penalty_kick_setup) } // TODO (#2167): disabled due to physics simulator bug causing failure -TEST_F(PenaltyKickPlayTest, DISABLED_test_penalty_kick_take) +TEST_F(PenaltyKickPlayTest, /*DISABLED_*/test_penalty_kick_take) { Vector behind_ball_direction = (field.friendlyPenaltyMark() - field.enemyGoalCenter()).normalize(); diff --git a/src/software/ai/hl/stp/play/penalty_kick_play_test.py b/src/software/ai/hl/stp/play/penalty_kick_play_test.py new file mode 100644 index 0000000000..280fc0dccf --- /dev/null +++ b/src/software/ai/hl/stp/play/penalty_kick_play_test.py @@ -0,0 +1,80 @@ +import sys + +import pytest + +import software.python_bindings as tbots +from proto.play_pb2 import Play, PlayName +from software.simulated_tests.friendly_has_ball_possession import * +from software.simulated_tests.robot_enters_region import * +from software.simulated_tests.simulated_test_fixture import simulated_test_runner +from proto.message_translation.tbots_protobuf import create_world_state +from proto.ssl_gc_common_pb2 import Team + +def test_kickoff_play(simulated_test_runner): + + # starting point must be Point + ball_initial_pos = tbots.Field.createSSLDivisionBField().friendlyPenaltyMark() + + # Setup Bots + blue_bots = [ + tbots.Point(-2,-2), + tbots.Point(-3,-1), + tbots.Point(-3, 0), + tbots.Point(-3, 1), + tbots.Point(-3, 2), + tbots.Point(2, 2.5), + ] + + yellow_bots = [ + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + ] + + blue_play = Play() + yellow_play = Play() + + # Game Controller Setup + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.STOP, team=Team.UNKNOWN + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.PENALTY, team=Team.BLUE + ) + # simulated_test_runner.gamecontroller.send_ci_input( + # gc_command=Command.Type.NORMAL_START, team=Team.BLUE + # ) + + delayed_ci_call = (4, Command.Type.NORMAL_START, Team.BLUE) + blue_play.name = PlayName.PenaltyKickPlay + yellow_play.name = PlayName.HaltPlay + + # 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.Vector(0, 0), + ), + ) + + # Always Validation + always_validation_sequence_set = [[]] + + # Eventually Validation + eventually_validation_sequence_set = [[]] + + simulated_test_runner.run_test( + eventually_validation_sequence_set=eventually_validation_sequence_set, + always_validation_sequence_set=always_validation_sequence_set, + test_timeout_s=10, + ci_cmd_with_delay=[delayed_ci_call] + ) + +if __name__ == "__main__": + # Run the test, -s disables all capturing at -vv increases verbosity + sys.exit(pytest.main([__file__, "-svv"])) \ No newline at end of file From 0ee4e2f84927e92d0ef7457cbd6904a1b5ed980b Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 6 Jul 2022 22:36:19 -0700 Subject: [PATCH 12/83] validated penalty kick --- .../ai/hl/stp/play/penalty_kick_play_test.py | 78 +++++++++++++++++-- src/software/simulated_tests/BUILD | 2 +- 2 files changed, 73 insertions(+), 7 deletions(-) diff --git a/src/software/ai/hl/stp/play/penalty_kick_play_test.py b/src/software/ai/hl/stp/play/penalty_kick_play_test.py index 280fc0dccf..2d6a01eb9f 100644 --- a/src/software/ai/hl/stp/play/penalty_kick_play_test.py +++ b/src/software/ai/hl/stp/play/penalty_kick_play_test.py @@ -2,15 +2,19 @@ import pytest + import software.python_bindings as tbots from proto.play_pb2 import Play, PlayName -from software.simulated_tests.friendly_has_ball_possession import * -from software.simulated_tests.robot_enters_region import * +from software.py_constants import BALL_MAX_RADIUS_METERS +from software.simulated_tests.ball_enters_region import * +from software.simulated_tests.ball_moves_forward import * +from software.simulated_tests.excessive_dribbling import * +from software.simulated_tests.friendly_goal_scored import * from software.simulated_tests.simulated_test_fixture import simulated_test_runner from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team -def test_kickoff_play(simulated_test_runner): +def test_kickoff_play_ready(simulated_test_runner): # starting point must be Point ball_initial_pos = tbots.Field.createSSLDivisionBField().friendlyPenaltyMark() @@ -43,7 +47,7 @@ def test_kickoff_play(simulated_test_runner): # gc_command=Command.Type.NORMAL_START, team=Team.BLUE # ) - delayed_ci_call = (4, Command.Type.NORMAL_START, Team.BLUE) + # delayed_ci_call = (4, Command.Type.NORMAL_START, Team.BLUE) blue_play.name = PlayName.PenaltyKickPlay yellow_play.name = PlayName.HaltPlay @@ -63,7 +67,7 @@ def test_kickoff_play(simulated_test_runner): ) # Always Validation - always_validation_sequence_set = [[]] + always_validation_sequence_set = [[BallAlwaysStaysInRegion([tbots.Circle(ball_initial_pos,BALL_MAX_RADIUS_METERS)])]] # Eventually Validation eventually_validation_sequence_set = [[]] @@ -71,7 +75,69 @@ def test_kickoff_play(simulated_test_runner): simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, - test_timeout_s=10, + test_timeout_s=15, + # ci_cmd_with_delay=[delayed_ci_call] + ) + +def test_kickoff_play_kicking(simulated_test_runner): + + # starting point must be Point + ball_initial_pos = tbots.Field.createSSLDivisionBField().friendlyPenaltyMark() + + # Setup Bots + blue_bots = [ + tbots.Point(-2,-2), + tbots.Point(-3,-1), + tbots.Point(-3, 0), + tbots.Point(-3, 1), + tbots.Point(-3, 2), + tbots.Point(2, 2.5), + ] + + yellow_bots = [ + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + ] + + blue_play = Play() + yellow_play = Play() + + # Game Controller Setup + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.STOP, team=Team.UNKNOWN + ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.PENALTY, team=Team.BLUE + ) + + delayed_ci_call = (4, Command.Type.NORMAL_START, Team.BLUE) + blue_play.name = PlayName.PenaltyKickPlay + yellow_play.name = PlayName.HaltPlay + + # 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.Vector(0, 0), + ), + ) + + # Always Validation + always_validation_sequence_set = [[NeverExcessivelyDribbles()]] + + # Eventually Validation + eventually_validation_sequence_set = [[FriendlyGoalEventuallyScored()]] + + simulated_test_runner.run_test( + eventually_validation_sequence_set=eventually_validation_sequence_set, + always_validation_sequence_set=always_validation_sequence_set, + test_timeout_s=15, ci_cmd_with_delay=[delayed_ci_call] ) diff --git a/src/software/simulated_tests/BUILD b/src/software/simulated_tests/BUILD index bb26120abb..eed8a36027 100644 --- a/src/software/simulated_tests/BUILD +++ b/src/software/simulated_tests/BUILD @@ -86,7 +86,7 @@ py_library( "robot_speed_threshold.py", "validation.py", "robot_halt.py", - "friendly_goal_scored.py" + "friendly_goal_scored.py", ], data = [ "//software:py_constants.so", From 9e0eceaccdec064d7608bd0d9a1caf236fc3ae5f Mon Sep 17 00:00:00 2001 From: Phil Date: Sat, 8 Oct 2022 14:24:07 -0700 Subject: [PATCH 13/83] removed comment --- src/software/ai/hl/stp/play/corner_kick_play_test.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/software/ai/hl/stp/play/corner_kick_play_test.py b/src/software/ai/hl/stp/play/corner_kick_play_test.py index 0525f48fc3..a94db8408f 100644 --- a/src/software/ai/hl/stp/play/corner_kick_play_test.py +++ b/src/software/ai/hl/stp/play/corner_kick_play_test.py @@ -10,8 +10,6 @@ from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team -# TODO issue #2599 - Remove Duration parameter from test -# @pytest.mark.parametrize("run_enemy_ai,test_duration", [(False, 20), (True, 20)]) def test_corner_kick_play_bottom_left(simulated_test_runner): # starting point must be Point @@ -77,7 +75,7 @@ def test_corner_kick_play_bottom_left(simulated_test_runner): simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, - test_timeout_s=25, + test_timeout_s=15, ) def test_corner_kick_play_top_right(simulated_test_runner): @@ -145,7 +143,7 @@ def test_corner_kick_play_top_right(simulated_test_runner): simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, - test_timeout_s=25, + test_timeout_s=15, ) if __name__ == "__main__": From 634f4ff3bf903c025aa01b949b72a088a39202de Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 12 Oct 2022 23:00:51 -0700 Subject: [PATCH 14/83] removed validation --- .../hl/stp/play/ball_placement_play_test.py | 10 ++----- .../ai/hl/stp/play/corner_kick_play_test.py | 12 +++++--- .../crease_defense_play_test.py | 5 ++-- .../ai/hl/stp/play/defense_play_test.py | 30 +++++-------------- .../play/enemy_ball_placement_play_test.py | 9 ++---- .../ai/hl/stp/play/free_kick_play_test.py | 16 ++++++---- src/software/ai/hl/stp/play/kickoff_test.py | 6 ++-- .../hl/stp/play/offense/offense_play_test.py | 9 +++--- .../ai/hl/stp/play/penalty_kick_play_test.py | 9 ++++-- 9 files changed, 50 insertions(+), 56 deletions(-) diff --git a/src/software/ai/hl/stp/play/ball_placement_play_test.py b/src/software/ai/hl/stp/play/ball_placement_play_test.py index 3388fcd6cf..f60d146f9e 100644 --- a/src/software/ai/hl/stp/play/ball_placement_play_test.py +++ b/src/software/ai/hl/stp/play/ball_placement_play_test.py @@ -11,7 +11,6 @@ from proto.ssl_gc_common_pb2 import Team from proto.ssl_gc_geometry_pb2 import Vector2 -# TODO issue #2599 - Remove Duration parameter from test @pytest.mark.parametrize("run_enemy_ai,test_duration", [[False,10],(True, 10)]) def test_two_ai_ball_placement(simulated_test_runner, run_enemy_ai, test_duration): @@ -80,15 +79,12 @@ def test_two_ai_ball_placement(simulated_test_runner, run_enemy_ai, test_duratio ) # Always Validation + #TODO- #2753 Validation always_validation_sequence_set = [[]] # Eventually Validation - eventually_validation_sequence_set = [ - [ - # Ball should arrive within 5cm of placement point - BallEventuallyEntersRegion(regions=[tbots.Circle(ball_final_pos, 0.05)]), - ] - ] + #TODO- #2753 Validation + eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, diff --git a/src/software/ai/hl/stp/play/corner_kick_play_test.py b/src/software/ai/hl/stp/play/corner_kick_play_test.py index a94db8408f..23e6ff61bd 100644 --- a/src/software/ai/hl/stp/play/corner_kick_play_test.py +++ b/src/software/ai/hl/stp/play/corner_kick_play_test.py @@ -67,10 +67,12 @@ def test_corner_kick_play_bottom_left(simulated_test_runner): ) # Always Validation - always_validation_sequence_set = [] + #TODO- #2753 Validation + always_validation_sequence_set = [[]] # Eventually Validation - eventually_validation_sequence_set = [[FriendlyGoalEventuallyScored()]] + #TODO- #2753 Validation + eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, @@ -135,10 +137,12 @@ def test_corner_kick_play_top_right(simulated_test_runner): ) # Always Validation - always_validation_sequence_set = [] + #TODO- #2753 Validation + always_validation_sequence_set = [[]] # Eventually Validation - eventually_validation_sequence_set = [[FriendlyGoalEventuallyScored()]] + #TODO- #2753 Validation + eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, diff --git a/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py b/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py index 68a9985098..2727cced26 100644 --- a/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py +++ b/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py @@ -9,8 +9,7 @@ from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team -# TODO issue #2599 - Remove Duration parameter from test -# @pytest.mark.parametrize("run_enemy_ai,test_duration", [(False, 20), (True, 20)]) + def test_crease_defense_play(simulated_test_runner): # starting point must be Point @@ -67,9 +66,11 @@ def test_crease_defense_play(simulated_test_runner): ) # Always Validation + #TODO- #2753 Validation always_validation_sequence_set = [[]] # Eventually Validation + #TODO- #2753 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( diff --git a/src/software/ai/hl/stp/play/defense_play_test.py b/src/software/ai/hl/stp/play/defense_play_test.py index dd51023616..cf1aa68997 100644 --- a/src/software/ai/hl/stp/play/defense_play_test.py +++ b/src/software/ai/hl/stp/play/defense_play_test.py @@ -10,8 +10,7 @@ from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team -# TODO issue #2599 - Remove Duration parameter from test -# @pytest.mark.parametrize("run_enemy_ai,test_duration", [(False, 20), (True, 20)]) + def test_defense_play(simulated_test_runner): # starting point must be Point @@ -66,25 +65,12 @@ def test_defense_play(simulated_test_runner): ) # Always Validation + #TODO- #2753 Validation always_validation_sequence_set = [[]] # Eventually Validation - eventually_validation_sequence_set = [ - [ - RobotHaltEventually(), - RobotEventuallyEntersRegion( - [ - tbots.Rectangle(tbots.Point(0,2.85), - tbots.Point(0.9,2)), - tbots.Rectangle(tbots.Point(0.5,2.5), - tbots.Point(1,2)), - tbots.Rectangle(tbots.Point(-2,-0.75), - tbots.Point(-1.5,-1.25)), - ] - ), - - ] - ] + #TODO- #2753 Validation + eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, @@ -92,8 +78,6 @@ def test_defense_play(simulated_test_runner): test_timeout_s=10, ) -# TODO issue #2599 - Remove Duration parameter from test -# @pytest.mark.parametrize("run_enemy_ai,test_duration", [(False, 20), (True, 20)]) def test_defense_play_one_threat(simulated_test_runner): # starting point must be Point @@ -150,9 +134,11 @@ def test_defense_play_one_threat(simulated_test_runner): ) # Always Validation + #TODO- #2753 Validation always_validation_sequence_set = [[]] # Eventually Validation + #TODO- #2753 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( @@ -161,8 +147,6 @@ def test_defense_play_one_threat(simulated_test_runner): test_timeout_s=10, ) -# TODO issue #2599 - Remove Duration parameter from test -# @pytest.mark.parametrize("run_enemy_ai,test_duration", [(False, 20), (True, 20)]) def test_defense_play_close_to_net(simulated_test_runner): # starting point must be Point @@ -217,9 +201,11 @@ def test_defense_play_close_to_net(simulated_test_runner): ) # Always Validation + #TODO- #2753 Validation always_validation_sequence_set = [[]] # Eventually Validation + #TODO- #2753 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, diff --git a/src/software/ai/hl/stp/play/enemy_ball_placement_play_test.py b/src/software/ai/hl/stp/play/enemy_ball_placement_play_test.py index f63a6a1197..1cb1522854 100644 --- a/src/software/ai/hl/stp/play/enemy_ball_placement_play_test.py +++ b/src/software/ai/hl/stp/play/enemy_ball_placement_play_test.py @@ -76,15 +76,12 @@ def test_two_ai_ball_placement(simulated_test_runner): ) # Always Validation + #TODO- #2753 Validation always_validation_sequence_set = [[]] # Eventually Validation - eventually_validation_sequence_set = [ - [ - # Ball should arrive within 5cm of placement point - # BallEventuallyEntersRegion(regions=[tbots.Circle(ball_final_pos, 0.05)]), - ] - ] + #TODO- #2753 Validation + eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, diff --git a/src/software/ai/hl/stp/play/free_kick_play_test.py b/src/software/ai/hl/stp/play/free_kick_play_test.py index 457119fc3e..db2e23e1cd 100644 --- a/src/software/ai/hl/stp/play/free_kick_play_test.py +++ b/src/software/ai/hl/stp/play/free_kick_play_test.py @@ -69,11 +69,13 @@ def test_free_kick_play_friendly(simulated_test_runner, ball_pos): ) # Always Validation - always_validation_sequence_set = [] + #TODO- #2753 Validation + always_validation_sequence_set = [[]] # Eventually Validation # We should always score against robots which are standing still - eventually_validation_sequence_set = [[FriendlyGoalEventuallyScored()]] + #TODO- #2753 Validation + eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, @@ -158,10 +160,11 @@ def test_free_kick_play_enemy(simulated_test_runner, ball_pos, yellow_bot_pos): ) # Always Validation - always_validation_sequence_set = [] + # TODO- #2753 Validation + always_validation_sequence_set = [[]] # Eventually Validation - # TODO + # TODO- #2753 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( @@ -223,10 +226,11 @@ def test_free_kick_play_both(simulated_test_runner, ball_pos): ) # Always Validation - always_validation_sequence_set = [] + # TODO- #2753 Validation + always_validation_sequence_set = [[]] # Eventually Validation - # TODO + # TODO- #2753 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( diff --git a/src/software/ai/hl/stp/play/kickoff_test.py b/src/software/ai/hl/stp/play/kickoff_test.py index 4fffa10564..9fffb3fe8e 100644 --- a/src/software/ai/hl/stp/play/kickoff_test.py +++ b/src/software/ai/hl/stp/play/kickoff_test.py @@ -139,10 +139,12 @@ def test_kickoff_play(simulated_test_runner, always_validation_list, eventually_ ) # Always Validation - always_validation_sequence_set = always_validation_list + # TODO- #2753 Validation + always_validation_sequence_set = [[]] # Eventually Validation - eventually_validation_sequence_set = eventually_validation_list + # TODO- #2753 Validation + eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, diff --git a/src/software/ai/hl/stp/play/offense/offense_play_test.py b/src/software/ai/hl/stp/play/offense/offense_play_test.py index fe882af80e..bb2eab4fab 100644 --- a/src/software/ai/hl/stp/play/offense/offense_play_test.py +++ b/src/software/ai/hl/stp/play/offense/offense_play_test.py @@ -10,8 +10,7 @@ from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team -# TODO issue #2599 - Remove Duration parameter from test -# @pytest.mark.parametrize("run_enemy_ai,test_duration", [(False, 20), (True, 20)]) + def test_offense_play(simulated_test_runner): # starting point must be Point @@ -68,10 +67,12 @@ def test_offense_play(simulated_test_runner): ) # Always Validation - always_validation_sequence_set = [[BallAlwaysStaysInRegion([tbots.Field.createSSLDivisionBField().fieldLines()])]] + #TODO- #2753 Validation + always_validation_sequence_set = [[]] # Eventually Validation - eventually_validation_sequence_set = [[FriendlyGoalEventuallyScored()]] + #TODO- #2753 Validation + eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, diff --git a/src/software/ai/hl/stp/play/penalty_kick_play_test.py b/src/software/ai/hl/stp/play/penalty_kick_play_test.py index 2d6a01eb9f..59fbdbea06 100644 --- a/src/software/ai/hl/stp/play/penalty_kick_play_test.py +++ b/src/software/ai/hl/stp/play/penalty_kick_play_test.py @@ -67,7 +67,8 @@ def test_kickoff_play_ready(simulated_test_runner): ) # Always Validation - always_validation_sequence_set = [[BallAlwaysStaysInRegion([tbots.Circle(ball_initial_pos,BALL_MAX_RADIUS_METERS)])]] + # TODO- #2753 Validation + always_validation_sequence_set = [[]] # Eventually Validation eventually_validation_sequence_set = [[]] @@ -129,10 +130,12 @@ def test_kickoff_play_kicking(simulated_test_runner): ) # Always Validation - always_validation_sequence_set = [[NeverExcessivelyDribbles()]] + # TODO- #2753 Validation + always_validation_sequence_set = [[]] # Eventually Validation - eventually_validation_sequence_set = [[FriendlyGoalEventuallyScored()]] + # TODO- #2753 Validation + eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, From da16d0e09c785b0725377d30938347d7055e1fd9 Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 12 Oct 2022 23:12:35 -0700 Subject: [PATCH 15/83] formatting and small test exclusions --- src/software/ai/hl/stp/play/BUILD | 19 +----- .../hl/stp/play/ball_placement_play_test.py | 7 ++- .../ai/hl/stp/play/corner_kick_play_test.py | 11 ++-- .../crease_defense_play_test.py | 4 +- .../ai/hl/stp/play/defense_play_test.py | 21 ++++--- .../hl/stp/play/enemy_ball_placement_play.cpp | 27 ++++---- .../play/enemy_ball_placement_play_test.py | 10 ++- .../ai/hl/stp/play/free_kick_play_test.py | 40 ++++++++---- src/software/ai/hl/stp/play/halt_play_test.py | 7 ++- src/software/ai/hl/stp/play/kickoff_test.py | 61 +++++++++++-------- .../hl/stp/play/offense/offense_play_test.py | 6 +- .../ai/hl/stp/play/penalty_kick_play_test.cpp | 4 +- .../ai/hl/stp/play/penalty_kick_play_test.py | 25 ++++---- src/software/simulated_tests/BUILD | 4 +- .../simulated_tests/friendly_goal_scored.py | 8 +-- .../simulated_tests/robot_enters_region.py | 10 ++- src/software/simulated_tests/robot_halt.py | 5 +- .../simulated_tests/simulated_test_fixture.py | 20 +++--- 18 files changed, 151 insertions(+), 138 deletions(-) diff --git a/src/software/ai/hl/stp/play/BUILD b/src/software/ai/hl/stp/play/BUILD index 247a9a7a4c..7521aa0e4e 100644 --- a/src/software/ai/hl/stp/play/BUILD +++ b/src/software/ai/hl/stp/play/BUILD @@ -567,7 +567,7 @@ cc_test( ) cc_test( - name = "penalty_kick_play_cpp_test", + name = "penalty_kick_play_test", srcs = ["penalty_kick_play_test.cpp"], deps = [ "//shared/test_util:tbots_gtest_main", @@ -582,23 +582,6 @@ cc_test( ], ) -py_test( - name = "penalty_kick_play_test", - srcs = [ - "penalty_kick_play_test.py", - ], - # TODO (#2619) Remove tag to run in parallel - tags = [ - "exclusive", - ], - deps = [ - "//software/simulated_tests:simulated_test_fixture", - "//software/simulated_tests:validation", - requirement("pytest"), - ], -) - - cc_test( name = "penalty_kick_enemy_play_test", srcs = ["penalty_kick_enemy_play_test.cpp"], diff --git a/src/software/ai/hl/stp/play/ball_placement_play_test.py b/src/software/ai/hl/stp/play/ball_placement_play_test.py index f60d146f9e..30d30d9c5b 100644 --- a/src/software/ai/hl/stp/play/ball_placement_play_test.py +++ b/src/software/ai/hl/stp/play/ball_placement_play_test.py @@ -11,7 +11,8 @@ from proto.ssl_gc_common_pb2 import Team from proto.ssl_gc_geometry_pb2 import Vector2 -@pytest.mark.parametrize("run_enemy_ai,test_duration", [[False,10],(True, 10)]) + +@pytest.mark.parametrize("run_enemy_ai,test_duration", [[False, 10], (True, 10)]) def test_two_ai_ball_placement(simulated_test_runner, run_enemy_ai, test_duration): # starting point must be Point @@ -79,11 +80,11 @@ def test_two_ai_ball_placement(simulated_test_runner, run_enemy_ai, test_duratio ) # Always Validation - #TODO- #2753 Validation + # TODO- #2753 Validation always_validation_sequence_set = [[]] # Eventually Validation - #TODO- #2753 Validation + # TODO- #2753 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( diff --git a/src/software/ai/hl/stp/play/corner_kick_play_test.py b/src/software/ai/hl/stp/play/corner_kick_play_test.py index 23e6ff61bd..5ec31570af 100644 --- a/src/software/ai/hl/stp/play/corner_kick_play_test.py +++ b/src/software/ai/hl/stp/play/corner_kick_play_test.py @@ -10,6 +10,7 @@ from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team + def test_corner_kick_play_bottom_left(simulated_test_runner): # starting point must be Point @@ -67,11 +68,11 @@ def test_corner_kick_play_bottom_left(simulated_test_runner): ) # Always Validation - #TODO- #2753 Validation + # TODO- #2753 Validation always_validation_sequence_set = [[]] # Eventually Validation - #TODO- #2753 Validation + # TODO- #2753 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( @@ -80,6 +81,7 @@ def test_corner_kick_play_bottom_left(simulated_test_runner): test_timeout_s=15, ) + def test_corner_kick_play_top_right(simulated_test_runner): # starting point must be Point @@ -137,11 +139,11 @@ def test_corner_kick_play_top_right(simulated_test_runner): ) # Always Validation - #TODO- #2753 Validation + # TODO- #2753 Validation always_validation_sequence_set = [[]] # Eventually Validation - #TODO- #2753 Validation + # TODO- #2753 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( @@ -150,6 +152,7 @@ def test_corner_kick_play_top_right(simulated_test_runner): test_timeout_s=15, ) + if __name__ == "__main__": # Run the test, -s disables all capturing at -vv increases verbosity sys.exit(pytest.main([__file__, "-svv"])) diff --git a/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py b/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py index 2727cced26..6876e4202c 100644 --- a/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py +++ b/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py @@ -66,11 +66,11 @@ def test_crease_defense_play(simulated_test_runner): ) # Always Validation - #TODO- #2753 Validation + # TODO- #2753 Validation always_validation_sequence_set = [[]] # Eventually Validation - #TODO- #2753 Validation + # TODO- #2753 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( diff --git a/src/software/ai/hl/stp/play/defense_play_test.py b/src/software/ai/hl/stp/play/defense_play_test.py index cf1aa68997..7416c22cff 100644 --- a/src/software/ai/hl/stp/play/defense_play_test.py +++ b/src/software/ai/hl/stp/play/defense_play_test.py @@ -40,7 +40,7 @@ def test_defense_play(simulated_test_runner): gc_command=Command.Type.STOP, team=Team.UNKNOWN ) simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.FORCE_START, team=Team.BLUE + gc_command=Command.Type.FORCE_START, team=Team.BLUE ) # Force play override here @@ -65,11 +65,11 @@ def test_defense_play(simulated_test_runner): ) # Always Validation - #TODO- #2753 Validation + # TODO- #2753 Validation always_validation_sequence_set = [[]] - + # Eventually Validation - #TODO- #2753 Validation + # TODO- #2753 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( @@ -78,6 +78,7 @@ def test_defense_play(simulated_test_runner): test_timeout_s=10, ) + def test_defense_play_one_threat(simulated_test_runner): # starting point must be Point @@ -134,11 +135,11 @@ def test_defense_play_one_threat(simulated_test_runner): ) # Always Validation - #TODO- #2753 Validation + # TODO- #2753 Validation always_validation_sequence_set = [[]] # Eventually Validation - #TODO- #2753 Validation + # TODO- #2753 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( @@ -147,6 +148,7 @@ def test_defense_play_one_threat(simulated_test_runner): test_timeout_s=10, ) + def test_defense_play_close_to_net(simulated_test_runner): # starting point must be Point @@ -167,7 +169,7 @@ def test_defense_play_close_to_net(simulated_test_runner): tbots.Point(-3.5, 2), tbots.Point(-1.5, 0), tbots.Point(-2.3, -1), - tbots.Point(-3.8,-2), + tbots.Point(-3.8, -2), tbots.Field.createSSLDivisionBField().enemyGoalCenter(), ] @@ -201,11 +203,11 @@ def test_defense_play_close_to_net(simulated_test_runner): ) # Always Validation - #TODO- #2753 Validation + # TODO- #2753 Validation always_validation_sequence_set = [[]] # Eventually Validation - #TODO- #2753 Validation + # TODO- #2753 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, @@ -213,6 +215,7 @@ def test_defense_play_close_to_net(simulated_test_runner): test_timeout_s=10, ) + if __name__ == "__main__": # Run the test, -s disables all capturing at -vv increases verbosity sys.exit(pytest.main([__file__, "-svv"])) diff --git a/src/software/ai/hl/stp/play/enemy_ball_placement_play.cpp b/src/software/ai/hl/stp/play/enemy_ball_placement_play.cpp index 90becb6011..a67297aef1 100644 --- a/src/software/ai/hl/stp/play/enemy_ball_placement_play.cpp +++ b/src/software/ai/hl/stp/play/enemy_ball_placement_play.cpp @@ -58,33 +58,34 @@ void EnemyBallPlacementPlay::ballPlacementWithShadow( tactics_to_run[0].emplace_back(crease_defenders[1]); tactics_to_run[0].emplace_back(crease_defenders[2]); - Vector ball_to_net = (world.ball().position() - world.field().friendlyGoalCenter()) - .normalize(-0.75 - ROBOT_MAX_RADIUS_METERS); + Vector ball_to_net = + (world.ball().position() - world.field().friendlyGoalCenter()) + .normalize(-0.75 - ROBOT_MAX_RADIUS_METERS); Vector placement_to_net = (placement_point - world.field().friendlyGoalCenter()) .normalize(-0.75 - ROBOT_MAX_RADIUS_METERS); // If the enemy hasn't reached the ball yet, we use this flag to avoid shadowing // so that we don't interfere with the enemy robots going to pick up the ball - if(!enemy_at_ball) + if (!enemy_at_ball) { move_tactics[0]->updateControlParams( - world.ball().position() + ball_to_net + - ball_to_net.perpendicular().normalize(1.25 * - ROBOT_MAX_RADIUS_METERS), - ball_to_net.orientation() + Angle::half(), 0); + world.ball().position() + ball_to_net + + ball_to_net.perpendicular().normalize(1.25 * ROBOT_MAX_RADIUS_METERS), + ball_to_net.orientation() + Angle::half(), 0); move_tactics[1]->updateControlParams( - world.ball().position() + ball_to_net - - ball_to_net.perpendicular().normalize(1.25 * - ROBOT_MAX_RADIUS_METERS), - ball_to_net.orientation() + Angle::half(), 0); + world.ball().position() + ball_to_net - + ball_to_net.perpendicular().normalize(1.25 * ROBOT_MAX_RADIUS_METERS), + ball_to_net.orientation() + Angle::half(), 0); tactics_to_run[0].emplace_back(move_tactics[0]); tactics_to_run[0].emplace_back(move_tactics[1]); // Check to update flag - for(auto enemy_robot : world.enemyTeam().getAllRobotsExceptGoalie()) + for (auto enemy_robot : world.enemyTeam().getAllRobotsExceptGoalie()) { - if(std::abs((enemy_robot.position() - world.ball().position()).length()) < 0.25) + if (std::abs( + (enemy_robot.position() - world.ball().position()).length()) < + 0.25) { enemy_at_ball = true; } diff --git a/src/software/ai/hl/stp/play/enemy_ball_placement_play_test.py b/src/software/ai/hl/stp/play/enemy_ball_placement_play_test.py index 1cb1522854..d941df6027 100644 --- a/src/software/ai/hl/stp/play/enemy_ball_placement_play_test.py +++ b/src/software/ai/hl/stp/play/enemy_ball_placement_play_test.py @@ -10,6 +10,7 @@ from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team + def test_two_ai_ball_placement(simulated_test_runner): # starting point must be Point @@ -56,13 +57,10 @@ def test_two_ai_ball_placement(simulated_test_runner): simulated_test_runner.blue_full_system_proto_unix_io.send_proto(Play, blue_play) - yellow_play = Play() yellow_play.name = PlayName.BallPlacementPlay - simulated_test_runner.yellow_full_system_proto_unix_io.send_proto( - Play, yellow_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( @@ -76,11 +74,11 @@ def test_two_ai_ball_placement(simulated_test_runner): ) # Always Validation - #TODO- #2753 Validation + # TODO- #2753 Validation always_validation_sequence_set = [[]] # Eventually Validation - #TODO- #2753 Validation + # TODO- #2753 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( diff --git a/src/software/ai/hl/stp/play/free_kick_play_test.py b/src/software/ai/hl/stp/play/free_kick_play_test.py index db2e23e1cd..92d3c38811 100644 --- a/src/software/ai/hl/stp/play/free_kick_play_test.py +++ b/src/software/ai/hl/stp/play/free_kick_play_test.py @@ -11,7 +11,10 @@ from proto.ssl_gc_common_pb2 import Team # We want to test friendly half, enemy half, and at the border of the field -@pytest.mark.parametrize("ball_pos",[tbots.Point(1.5,-2.75),tbots.Point(-1.5,-2.75),tbots.Point(1.5,-3)]) +@pytest.mark.parametrize( + "ball_pos", + [tbots.Point(1.5, -2.75), tbots.Point(-1.5, -2.75), tbots.Point(1.5, -3)], +) def test_free_kick_play_friendly(simulated_test_runner, ball_pos): # starting point must be Point @@ -69,12 +72,12 @@ def test_free_kick_play_friendly(simulated_test_runner, ball_pos): ) # Always Validation - #TODO- #2753 Validation + # TODO- #2753 Validation always_validation_sequence_set = [[]] # Eventually Validation # We should always score against robots which are standing still - #TODO- #2753 Validation + # TODO- #2753 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( @@ -83,33 +86,39 @@ def test_free_kick_play_friendly(simulated_test_runner, ball_pos): test_timeout_s=10, ) -@pytest.mark.parametrize("ball_pos,yellow_bot_pos", + +@pytest.mark.parametrize( + "ball_pos,yellow_bot_pos", [ # not close to our net ( - tbots.Point(0.9,2.85), + tbots.Point(0.9, 2.85), [ tbots.Point(1, 3), tbots.Point(-2, -1.25), tbots.Point(-1, -0.25), tbots.Field.createSSLDivisionBField().enemyGoalCenter(), - tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), - tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + tbots.Field.createSSLDivisionBField() + .enemyDefenseArea() + .negXNegYCorner(), + tbots.Field.createSSLDivisionBField() + .enemyDefenseArea() + .negXPosYCorner(), ], ), # close to our net ( - tbots.Point(-2.4,1), + tbots.Point(-2.4, 1), [ tbots.Point(-2.3, 1.05), tbots.Point(-3.5, 2), tbots.Point(-1.2, 0), - tbots.Point(-2.3,-1), + tbots.Point(-2.3, -1), tbots.Point(-3.8, -2), tbots.Field.createSSLDivisionBField().enemyGoalCenter(), ], ), - ] + ], ) def test_free_kick_play_enemy(simulated_test_runner, ball_pos, yellow_bot_pos): @@ -173,10 +182,14 @@ def test_free_kick_play_enemy(simulated_test_runner, ball_pos, yellow_bot_pos): test_timeout_s=10, ) -@pytest.mark.parametrize("ball_pos",[tbots.Point(1.5,-2.75),tbots.Point(-1.5,-2.75),tbots.Point(1.5,-3)]) + +@pytest.mark.parametrize( + "ball_pos", + [tbots.Point(1.5, -2.75), tbots.Point(-1.5, -2.75), tbots.Point(1.5, -3)], +) def test_free_kick_play_both(simulated_test_runner, ball_pos): - ball_initial_pos=ball_pos + ball_initial_pos = ball_pos blue_bots = [ tbots.Point(-3, 0.25), @@ -239,6 +252,7 @@ def test_free_kick_play_both(simulated_test_runner, ball_pos): test_timeout_s=15, ) + if __name__ == "__main__": # Run the test, -s disables all capturing at -vv increases verbosity - sys.exit(pytest.main([__file__, "-svv"])) \ No newline at end of file + sys.exit(pytest.main([__file__, "-svv"])) diff --git a/src/software/ai/hl/stp/play/halt_play_test.py b/src/software/ai/hl/stp/play/halt_play_test.py index a7c411ca20..5db7f7a8e8 100644 --- a/src/software/ai/hl/stp/play/halt_play_test.py +++ b/src/software/ai/hl/stp/play/halt_play_test.py @@ -44,8 +44,8 @@ def test_halt_play(simulated_test_runner): ) # Structure for a delayed call is tuple (delay in seconds, command, team) - blue_delayed_ci_call = (3,Command.Type.HALT, Team.BLUE) - yellow_delayed_ci_call = (3,Command.Type.HALT, Team.YELLOW) + blue_delayed_ci_call = (3, Command.Type.HALT, Team.BLUE) + yellow_delayed_ci_call = (3, Command.Type.HALT, Team.YELLOW) # No plays to override. AI does whatever for 3 seconds before HALT CMD # is issued @@ -71,9 +71,10 @@ def test_halt_play(simulated_test_runner): eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, test_timeout_s=25, - ci_cmd_with_delay=[blue_delayed_ci_call, yellow_delayed_ci_call] + ci_cmd_with_delay=[blue_delayed_ci_call, yellow_delayed_ci_call], ) + if __name__ == "__main__": # Run the test, -s disables all capturing at -vv increases verbosity sys.exit(pytest.main([__file__, "-svv"])) diff --git a/src/software/ai/hl/stp/play/kickoff_test.py b/src/software/ai/hl/stp/play/kickoff_test.py index 9fffb3fe8e..7cb52f3aad 100644 --- a/src/software/ai/hl/stp/play/kickoff_test.py +++ b/src/software/ai/hl/stp/play/kickoff_test.py @@ -13,7 +13,7 @@ kickoff_friendly_always_validation = [ [ RobotNeverEntersRegion([tbots.Field.createSSLDivisionBField().enemyHalf()]), - FriendlyNeverHasBallPossession() + FriendlyNeverHasBallPossession(), ] ] @@ -21,62 +21,68 @@ [ # Robot in center circle NumberOfRobotsEventuallyEntersRegion( - tbots.Field.createSSLDivisionBField().centerCircle(), - 1 + tbots.Field.createSSLDivisionBField().centerCircle(), 1 ), # Attacking Robot Placement NumberOfRobotsEventuallyEntersRegion( - tbots.Rectangle(tbots.Point(-0.5, 2.5), tbots.Point(-1.5, -2.5)), - 2 + tbots.Rectangle(tbots.Point(-0.5, 2.5), tbots.Point(-1.5, -2.5)), 2 ), # Defending Robot Placement NumberOfRobotsEventuallyEntersRegion( - tbots.Rectangle(tbots.Point(-3.2, 1.1), tbots.Point(-3.51, -1.1)), - 3 - ) + tbots.Rectangle(tbots.Point(-3.2, 1.1), tbots.Point(-3.51, -1.1)), 3 + ), ] ] kickoff_enemy_always_validation = [ [ - RobotNeverEntersRegion([ - tbots.Field.createSSLDivisionBField().enemyHalf(), - tbots.Field.createSSLDivisionBField().centerCircle() + RobotNeverEntersRegion( + [ + tbots.Field.createSSLDivisionBField().enemyHalf(), + tbots.Field.createSSLDivisionBField().centerCircle(), ] ), - FriendlyNeverHasBallPossession() + FriendlyNeverHasBallPossession(), ] ] kickoff_enemy_eventually_validation = [ - [ + [ # Front 3 robots spread out in 3 zones NumberOfRobotsEventuallyEntersRegion( - tbots.Rectangle(tbots.Point(-0.2, 1), tbots.Point(-0.4, 0.25)), - 1 + tbots.Rectangle(tbots.Point(-0.2, 1), tbots.Point(-0.4, 0.25)), 1 ), NumberOfRobotsEventuallyEntersRegion( - tbots.Rectangle(tbots.Point(-0.2, -1), tbots.Point(-0.4, -0.25)), - 1 + tbots.Rectangle(tbots.Point(-0.2, -1), tbots.Point(-0.4, -0.25)), 1 ), NumberOfRobotsEventuallyEntersRegion( - tbots.Rectangle(tbots.Point(-0.6, 0.1), tbots.Point(-0.9,-0.1)), - 1 + tbots.Rectangle(tbots.Point(-0.6, 0.1), tbots.Point(-0.9, -0.1)), 1 ), # 2 robots Defend the box NumberOfRobotsEventuallyEntersRegion( - tbots.Rectangle(tbots.Point(-3.2,1.1), tbots.Point(-3.5, -1.1)), - 2 - ) + tbots.Rectangle(tbots.Point(-3.2, 1.1), tbots.Point(-3.5, -1.1)), 2 + ), ] ] -@pytest.mark.parametrize("always_validation_list,eventually_validation_list,is_friendly_test", [ - (kickoff_friendly_always_validation,kickoff_friendly_eventually_validation, True), - (kickoff_enemy_always_validation,kickoff_enemy_eventually_validation, False), - ] + +@pytest.mark.parametrize( + "always_validation_list,eventually_validation_list,is_friendly_test", + [ + ( + kickoff_friendly_always_validation, + kickoff_friendly_eventually_validation, + True, + ), + (kickoff_enemy_always_validation, kickoff_enemy_eventually_validation, False), + ], ) -def test_kickoff_play(simulated_test_runner, always_validation_list, eventually_validation_list, is_friendly_test): +def test_kickoff_play( + simulated_test_runner, + always_validation_list, + eventually_validation_list, + is_friendly_test, +): # starting point must be Point ball_initial_pos = tbots.Point(0, 0) @@ -152,6 +158,7 @@ def test_kickoff_play(simulated_test_runner, always_validation_list, eventually_ test_timeout_s=10, ) + if __name__ == "__main__": # Run the test, -s disables all capturing at -vv increases verbosity sys.exit(pytest.main([__file__, "-svv"])) diff --git a/src/software/ai/hl/stp/play/offense/offense_play_test.py b/src/software/ai/hl/stp/play/offense/offense_play_test.py index bb2eab4fab..0da9c84f38 100644 --- a/src/software/ai/hl/stp/play/offense/offense_play_test.py +++ b/src/software/ai/hl/stp/play/offense/offense_play_test.py @@ -25,7 +25,7 @@ def test_offense_play(simulated_test_runner): tbots.Point(-2, 0.5), tbots.Point(-2, -1.7), tbots.Point(-2, -1.5), - tbots.Point(-2,-0.5), + tbots.Point(-2, -0.5), ] yellow_bots = [ @@ -67,11 +67,11 @@ def test_offense_play(simulated_test_runner): ) # Always Validation - #TODO- #2753 Validation + # TODO- #2753 Validation always_validation_sequence_set = [[]] # Eventually Validation - #TODO- #2753 Validation + # TODO- #2753 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( diff --git a/src/software/ai/hl/stp/play/penalty_kick_play_test.cpp b/src/software/ai/hl/stp/play/penalty_kick_play_test.cpp index 5a4eb5a6e5..1ebb99e781 100644 --- a/src/software/ai/hl/stp/play/penalty_kick_play_test.cpp +++ b/src/software/ai/hl/stp/play/penalty_kick_play_test.cpp @@ -23,7 +23,7 @@ class PenaltyKickPlayTest : public SimulatedErForceSimPlayTestFixture }; // TODO (#2602): test failing since a robot isn't avoiding the ball -TEST_F(PenaltyKickPlayTest, /*DISABLED_*/test_penalty_kick_setup) +TEST_F(PenaltyKickPlayTest, /*DISABLED_*/ test_penalty_kick_setup) { BallState ball_state(field.friendlyPenaltyMark(), Vector(0, 0)); auto friendly_robots = TestUtil::createStationaryRobotStatesWithId( @@ -67,7 +67,7 @@ TEST_F(PenaltyKickPlayTest, /*DISABLED_*/test_penalty_kick_setup) } // TODO (#2167): disabled due to physics simulator bug causing failure -TEST_F(PenaltyKickPlayTest, /*DISABLED_*/test_penalty_kick_take) +TEST_F(PenaltyKickPlayTest, /*DISABLED_*/ test_penalty_kick_take) { Vector behind_ball_direction = (field.friendlyPenaltyMark() - field.enemyGoalCenter()).normalize(); diff --git a/src/software/ai/hl/stp/play/penalty_kick_play_test.py b/src/software/ai/hl/stp/play/penalty_kick_play_test.py index 59fbdbea06..61a3f7a2f0 100644 --- a/src/software/ai/hl/stp/play/penalty_kick_play_test.py +++ b/src/software/ai/hl/stp/play/penalty_kick_play_test.py @@ -14,6 +14,7 @@ from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team + def test_kickoff_play_ready(simulated_test_runner): # starting point must be Point @@ -21,8 +22,8 @@ def test_kickoff_play_ready(simulated_test_runner): # Setup Bots blue_bots = [ - tbots.Point(-2,-2), - tbots.Point(-3,-1), + tbots.Point(-2, -2), + tbots.Point(-3, -1), tbots.Point(-3, 0), tbots.Point(-3, 1), tbots.Point(-3, 2), @@ -43,11 +44,11 @@ def test_kickoff_play_ready(simulated_test_runner): simulated_test_runner.gamecontroller.send_ci_input( gc_command=Command.Type.PENALTY, team=Team.BLUE ) - # simulated_test_runner.gamecontroller.send_ci_input( - # gc_command=Command.Type.NORMAL_START, team=Team.BLUE - # ) + simulated_test_runner.gamecontroller.send_ci_input( + gc_command=Command.Type.NORMAL_START, team=Team.BLUE + ) - # delayed_ci_call = (4, Command.Type.NORMAL_START, Team.BLUE) + delayed_ci_call = (4, Command.Type.NORMAL_START, Team.BLUE) blue_play.name = PlayName.PenaltyKickPlay yellow_play.name = PlayName.HaltPlay @@ -77,9 +78,10 @@ def test_kickoff_play_ready(simulated_test_runner): eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, test_timeout_s=15, - # ci_cmd_with_delay=[delayed_ci_call] + ci_cmd_with_delay=[delayed_ci_call], ) + def test_kickoff_play_kicking(simulated_test_runner): # starting point must be Point @@ -87,8 +89,8 @@ def test_kickoff_play_kicking(simulated_test_runner): # Setup Bots blue_bots = [ - tbots.Point(-2,-2), - tbots.Point(-3,-1), + tbots.Point(-2, -2), + tbots.Point(-3, -1), tbots.Point(-3, 0), tbots.Point(-3, 1), tbots.Point(-3, 2), @@ -141,9 +143,10 @@ def test_kickoff_play_kicking(simulated_test_runner): eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, test_timeout_s=15, - ci_cmd_with_delay=[delayed_ci_call] + ci_cmd_with_delay=[delayed_ci_call], ) + if __name__ == "__main__": # Run the test, -s disables all capturing at -vv increases verbosity - sys.exit(pytest.main([__file__, "-svv"])) \ No newline at end of file + sys.exit(pytest.main([__file__, "-svv"])) diff --git a/src/software/simulated_tests/BUILD b/src/software/simulated_tests/BUILD index eed8a36027..447ba031cf 100644 --- a/src/software/simulated_tests/BUILD +++ b/src/software/simulated_tests/BUILD @@ -81,12 +81,12 @@ py_library( "ball_speed_threshold.py", "ball_stops_in_region.py", "excessive_dribbling.py", + "friendly_goal_scored.py", "friendly_has_ball_possession.py", "robot_enters_region.py", + "robot_halt.py", "robot_speed_threshold.py", "validation.py", - "robot_halt.py", - "friendly_goal_scored.py", ], data = [ "//software:py_constants.so", diff --git a/src/software/simulated_tests/friendly_goal_scored.py b/src/software/simulated_tests/friendly_goal_scored.py index 33ed11d9eb..9d06028c23 100644 --- a/src/software/simulated_tests/friendly_goal_scored.py +++ b/src/software/simulated_tests/friendly_goal_scored.py @@ -40,14 +40,12 @@ def get_validation_geometry(self, world) -> ValidationGeometry: return create_validation_geometry([self.region]) def __repr__(self): - return "Checking ball in " + ",".join( - repr(self.region) - ) + return "Checking ball in " + ",".join(repr(self.region)) ( FriendlyGoalEventuallyScored, - FriendlyGoalEventuallyRemoved, # These two don't make much sense - FriendlyGoalAlwaysScored, # These two don't make much sense + FriendlyGoalEventuallyRemoved, # These two don't make much sense + FriendlyGoalAlwaysScored, # These two don't make much sense FriendlyGoalNeverScored, ) = create_validation_types(FriendlyGoalScored) diff --git a/src/software/simulated_tests/robot_enters_region.py b/src/software/simulated_tests/robot_enters_region.py index fbb829e791..422e05b087 100644 --- a/src/software/simulated_tests/robot_enters_region.py +++ b/src/software/simulated_tests/robot_enters_region.py @@ -50,6 +50,7 @@ def __repr__(self): RobotNeverEntersRegion, ) = create_validation_types(RobotEntersRegion) + class NumberOfRobotsEntersRegion(Validation): """Checks if a certain number of Robots enters a specific region.""" @@ -76,7 +77,7 @@ def get_validation_status(self, world) -> ValidationStatus: curr_cnt = 0 for robot_id in self.robot_in_zone: if self.robot_in_zone[robot_id]: - curr_cnt +=1 + curr_cnt += 1 # Validate on curr_cnt if curr_cnt == self.req_robot_cnt: @@ -91,8 +92,11 @@ def get_validation_geometry(self, world) -> ValidationGeometry: return create_validation_geometry([self.region]) def __repr__(self): - return "Check for " + str(self.req_robot_cnt) + " robots in region " + ",".join( - repr(self.region) + return ( + "Check for " + + str(self.req_robot_cnt) + + " robots in region " + + ",".join(repr(self.region)) ) diff --git a/src/software/simulated_tests/robot_halt.py b/src/software/simulated_tests/robot_halt.py index 6e517fcc1d..528edd11bc 100644 --- a/src/software/simulated_tests/robot_halt.py +++ b/src/software/simulated_tests/robot_halt.py @@ -25,10 +25,7 @@ def get_validation_status(self, world) -> ValidationStatus: PASSING if the friendly robots' speed is at or below 1e-3 """ for robot in world.friendly_team.team_robots: - if ( - tbots.createVector(robot.current_state.global_velocity).length() - > 1e-3 - ): + if tbots.createVector(robot.current_state.global_velocity).length() > 1e-3: return ValidationStatus.FAILING return ValidationStatus.PASSING diff --git a/src/software/simulated_tests/simulated_test_fixture.py b/src/software/simulated_tests/simulated_test_fixture.py index 34c4c2715d..9d82d8855a 100644 --- a/src/software/simulated_tests/simulated_test_fixture.py +++ b/src/software/simulated_tests/simulated_test_fixture.py @@ -69,7 +69,9 @@ def __init__( self.last_exception = None self.world_buffer = ThreadSafeBuffer(buffer_size=1, protobuf_type=World) - self.primitive_set_buffer = ThreadSafeBuffer(buffer_size=1, protobuf_type=PrimitiveSet) + self.primitive_set_buffer = ThreadSafeBuffer( + buffer_size=1, protobuf_type=PrimitiveSet + ) self.last_exception = None self.ssl_wrapper_buffer = ThreadSafeBuffer( @@ -141,18 +143,15 @@ def __runner(): time_elapsed_s = 0 while time_elapsed_s < test_timeout_s: - + # Check for new CI commands at this time step - for (delay,cmd,team) in ci_cmd_with_delay: + for (delay, cmd, team) in ci_cmd_with_delay: # If delay matches time if delay <= time_elapsed_s: # send command - self.gamecontroller.send_ci_input( - cmd, team - ) + self.gamecontroller.send_ci_input(cmd, team) # remove command from the list - ci_cmd_with_delay.remove((delay,cmd,team)) - + ci_cmd_with_delay.remove((delay, cmd, team)) # Update the timestamp logged by the ProtoLogger with self.timestamp_mutex: @@ -412,8 +411,9 @@ def simulated_test_runner(): # Only validate on the blue worlds blue_full_system_proto_unix_io.register_observer(World, runner.world_buffer) - blue_full_system_proto_unix_io.register_observer(PrimitiveSet, - runner.primitive_set_buffer) + blue_full_system_proto_unix_io.register_observer( + PrimitiveSet, runner.primitive_set_buffer + ) # Setup proto loggers. # # NOTE: Its important we use the test runners time provider because From 0f8fc26ab5e148c099e78328f79bfcf430a7251d Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 12 Oct 2022 23:17:29 -0700 Subject: [PATCH 16/83] disabled penalty kick play --- .../ai/hl/stp/play/penalty_kick_play_test.cpp | 4 +- .../ai/hl/stp/play/penalty_kick_play_test.py | 152 ------------------ 2 files changed, 2 insertions(+), 154 deletions(-) delete mode 100644 src/software/ai/hl/stp/play/penalty_kick_play_test.py diff --git a/src/software/ai/hl/stp/play/penalty_kick_play_test.cpp b/src/software/ai/hl/stp/play/penalty_kick_play_test.cpp index 1ebb99e781..941544cb69 100644 --- a/src/software/ai/hl/stp/play/penalty_kick_play_test.cpp +++ b/src/software/ai/hl/stp/play/penalty_kick_play_test.cpp @@ -23,7 +23,7 @@ class PenaltyKickPlayTest : public SimulatedErForceSimPlayTestFixture }; // TODO (#2602): test failing since a robot isn't avoiding the ball -TEST_F(PenaltyKickPlayTest, /*DISABLED_*/ test_penalty_kick_setup) +TEST_F(PenaltyKickPlayTest, DISABLED_test_penalty_kick_setup) { BallState ball_state(field.friendlyPenaltyMark(), Vector(0, 0)); auto friendly_robots = TestUtil::createStationaryRobotStatesWithId( @@ -67,7 +67,7 @@ TEST_F(PenaltyKickPlayTest, /*DISABLED_*/ test_penalty_kick_setup) } // TODO (#2167): disabled due to physics simulator bug causing failure -TEST_F(PenaltyKickPlayTest, /*DISABLED_*/ test_penalty_kick_take) +TEST_F(PenaltyKickPlayTest, DISABLED_test_penalty_kick_take) { Vector behind_ball_direction = (field.friendlyPenaltyMark() - field.enemyGoalCenter()).normalize(); diff --git a/src/software/ai/hl/stp/play/penalty_kick_play_test.py b/src/software/ai/hl/stp/play/penalty_kick_play_test.py deleted file mode 100644 index 61a3f7a2f0..0000000000 --- a/src/software/ai/hl/stp/play/penalty_kick_play_test.py +++ /dev/null @@ -1,152 +0,0 @@ -import sys - -import pytest - - -import software.python_bindings as tbots -from proto.play_pb2 import Play, PlayName -from software.py_constants import BALL_MAX_RADIUS_METERS -from software.simulated_tests.ball_enters_region import * -from software.simulated_tests.ball_moves_forward import * -from software.simulated_tests.excessive_dribbling import * -from software.simulated_tests.friendly_goal_scored import * -from software.simulated_tests.simulated_test_fixture import simulated_test_runner -from proto.message_translation.tbots_protobuf import create_world_state -from proto.ssl_gc_common_pb2 import Team - - -def test_kickoff_play_ready(simulated_test_runner): - - # starting point must be Point - ball_initial_pos = tbots.Field.createSSLDivisionBField().friendlyPenaltyMark() - - # Setup Bots - blue_bots = [ - tbots.Point(-2, -2), - tbots.Point(-3, -1), - tbots.Point(-3, 0), - tbots.Point(-3, 1), - tbots.Point(-3, 2), - tbots.Point(2, 2.5), - ] - - yellow_bots = [ - tbots.Field.createSSLDivisionBField().enemyGoalCenter(), - ] - - blue_play = Play() - yellow_play = Play() - - # Game Controller Setup - simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.STOP, team=Team.UNKNOWN - ) - simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.PENALTY, team=Team.BLUE - ) - simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.NORMAL_START, team=Team.BLUE - ) - - delayed_ci_call = (4, Command.Type.NORMAL_START, Team.BLUE) - blue_play.name = PlayName.PenaltyKickPlay - yellow_play.name = PlayName.HaltPlay - - # 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.Vector(0, 0), - ), - ) - - # Always Validation - # TODO- #2753 Validation - always_validation_sequence_set = [[]] - - # Eventually Validation - eventually_validation_sequence_set = [[]] - - simulated_test_runner.run_test( - eventually_validation_sequence_set=eventually_validation_sequence_set, - always_validation_sequence_set=always_validation_sequence_set, - test_timeout_s=15, - ci_cmd_with_delay=[delayed_ci_call], - ) - - -def test_kickoff_play_kicking(simulated_test_runner): - - # starting point must be Point - ball_initial_pos = tbots.Field.createSSLDivisionBField().friendlyPenaltyMark() - - # Setup Bots - blue_bots = [ - tbots.Point(-2, -2), - tbots.Point(-3, -1), - tbots.Point(-3, 0), - tbots.Point(-3, 1), - tbots.Point(-3, 2), - tbots.Point(2, 2.5), - ] - - yellow_bots = [ - tbots.Field.createSSLDivisionBField().enemyGoalCenter(), - ] - - blue_play = Play() - yellow_play = Play() - - # Game Controller Setup - simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.STOP, team=Team.UNKNOWN - ) - simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.PENALTY, team=Team.BLUE - ) - - delayed_ci_call = (4, Command.Type.NORMAL_START, Team.BLUE) - blue_play.name = PlayName.PenaltyKickPlay - yellow_play.name = PlayName.HaltPlay - - # 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.Vector(0, 0), - ), - ) - - # Always Validation - # TODO- #2753 Validation - always_validation_sequence_set = [[]] - - # Eventually Validation - # TODO- #2753 Validation - eventually_validation_sequence_set = [[]] - - simulated_test_runner.run_test( - eventually_validation_sequence_set=eventually_validation_sequence_set, - always_validation_sequence_set=always_validation_sequence_set, - test_timeout_s=15, - ci_cmd_with_delay=[delayed_ci_call], - ) - - -if __name__ == "__main__": - # Run the test, -s disables all capturing at -vv increases verbosity - sys.exit(pytest.main([__file__, "-svv"])) From b34dcf41835f005a9295ce23f2b8a03399c3ef9c Mon Sep 17 00:00:00 2001 From: suchirss Date: Fri, 14 Oct 2022 14:48:09 -0700 Subject: [PATCH 17/83] Updated GPIO to follow codebase naming guidelines. Ex: instances of "GPIO" are now updated to "Gpio". --- src/software/jetson_nano/display/robot_ui.py | 2 +- .../display/rotary_encoder/rotary_encoder.py | 42 +++++++++---------- src/software/jetson_nano/gpio.cpp | 14 +++---- src/software/jetson_nano/gpio.h | 6 +-- src/software/jetson_nano/services/motor.cpp | 20 ++++----- src/software/jetson_nano/services/motor.h | 10 ++--- src/software/jetson_nano/setup_nano.sh | 2 +- 7 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/software/jetson_nano/display/robot_ui.py b/src/software/jetson_nano/display/robot_ui.py index eca66f4521..8ed782bbbb 100644 --- a/src/software/jetson_nano/display/robot_ui.py +++ b/src/software/jetson_nano/display/robot_ui.py @@ -147,7 +147,7 @@ def poll_redis(self, timeout=3): time.sleep(timeout) def stop(self): - """ Cleanup the GPIO pins """ + """ Cleanup the Gpio pins """ self.shutdown = True self.rotary_encoder.stop() diff --git a/src/software/jetson_nano/display/rotary_encoder/rotary_encoder.py b/src/software/jetson_nano/display/rotary_encoder/rotary_encoder.py index 0acdf7fc19..d3ff86a277 100644 --- a/src/software/jetson_nano/display/rotary_encoder/rotary_encoder.py +++ b/src/software/jetson_nano/display/rotary_encoder/rotary_encoder.py @@ -1,4 +1,4 @@ -import Jetson.GPIO as GPIO # pip install Jetson.GPIO +import Jetson.Gpio as Gpio # pip install Jetson.Gpio """ The naming convention for the pins used to determine rotation state follow the labels @@ -72,19 +72,19 @@ def __init__( self.transitions_per_rotation = len(STATES) - 1 def setup(self): - """ Initialize GPIO pins and rotary encoder state """ + """ Initialize Gpio pins and rotary encoder state """ - # Set the GPIO mode if it has not been set - if not GPIO.getmode(): - GPIO.setmode(GPIO.BOARD) + # Set the Gpio mode if it has not been set + if not Gpio.getmode(): + Gpio.setmode(Gpio.BOARD) # These pins will need external pullups set up - GPIO.setup(self.PIN_1, GPIO.IN) - GPIO.setup(self.PIN_2, GPIO.IN) - GPIO.setup(self.BUTTON_PIN, GPIO.IN) + Gpio.setup(self.PIN_1, Gpio.IN) + Gpio.setup(self.PIN_2, Gpio.IN) + Gpio.setup(self.BUTTON_PIN, Gpio.IN) - pin_1_state = GPIO.input(self.PIN_1) - pin_2_state = GPIO.input(self.PIN_2) + pin_1_state = Gpio.input(self.PIN_1) + pin_2_state = Gpio.input(self.PIN_2) self.curr_state = (pin_1_state, pin_2_state) self.dir = CLOCKWISE @@ -93,8 +93,8 @@ def setup(self): def rot_state(self): """ Update the current state and count state transitions """ - pin_1_state = GPIO.input(self.PIN_1) - pin_2_state = GPIO.input(self.PIN_2) + pin_1_state = Gpio.input(self.PIN_1) + pin_2_state = Gpio.input(self.PIN_2) next_state = (pin_1_state, pin_2_state) prev_state = self.curr_state @@ -108,7 +108,7 @@ def rot_state(self): self.dir = COUNTERCLOCKWISE def start(self): - """ Start listening to GPIO pins to trigger callback functions """ + """ Start listening to Gpio pins to trigger callback functions """ def on_rotation(channel): """ Update rotation state and call user defined callback functions after complete rotation """ @@ -126,26 +126,26 @@ def on_rotation(channel): def button_pressed(channel): """ Call the user defined callback when button is pressed """ - if not GPIO.input(self.BUTTON_PIN): + if not Gpio.input(self.BUTTON_PIN): self.on_click() self.setup() # add callback to be called when rotating encoder - GPIO.add_event_detect(self.PIN_1, GPIO.BOTH, callback=on_rotation, bouncetime=0) - GPIO.add_event_detect(self.PIN_2, GPIO.BOTH, callback=on_rotation, bouncetime=0) + Gpio.add_event_detect(self.PIN_1, Gpio.BOTH, callback=on_rotation, bouncetime=0) + Gpio.add_event_detect(self.PIN_2, Gpio.BOTH, callback=on_rotation, bouncetime=0) # add callback to be called when button is pressed - GPIO.add_event_detect( + Gpio.add_event_detect( self.BUTTON_PIN, - GPIO.FALLING, + Gpio.FALLING, callback=button_pressed, bouncetime=BOUNCETIME, ) def stop(self): - """ clean up the GPIO pins that we were using for this class """ - GPIO.cleanup() + """ clean up the Gpio pins that we were using for this class """ + Gpio.cleanup() if __name__ == "__main__": @@ -161,7 +161,7 @@ def on_counterclockwise_rotate(): BUTTON_PIN = 40 # BOARD 35, TEGRA_SOC: 'DAP4_FS' PIN_1 = 33 # BOARD 40, TEGRA_SOC: 'DAP4_DOUT' - PIN_2 = 35 # BOARD 33, TEGRA_SOC: 'GPIO_PE6' + PIN_2 = 35 # BOARD 33, TEGRA_SOC: 'Gpio_PE6' rot = RotaryEncoder( PIN_1, diff --git a/src/software/jetson_nano/gpio.cpp b/src/software/jetson_nano/gpio.cpp index 8084d49232..1bf02b57a5 100644 --- a/src/software/jetson_nano/gpio.cpp +++ b/src/software/jetson_nano/gpio.cpp @@ -10,9 +10,9 @@ #include "software/logger/logger.h" -GPIO::GPIO(std::string gpio_number, GpioDirection direction, GpioState initial_state) +Gpio::Gpio(std::string gpio_number, GpioDirection direction, GpioState initial_state) { - // Setup the provided GPIO pin + // Setup the provided Gpio pin gpio_number_ = gpio_number; auto export_gpio_fs = std::ofstream("/sys/class/gpio/export"); @@ -39,14 +39,14 @@ GPIO::GPIO(std::string gpio_number, GpioDirection direction, GpioState initial_s set_direction_fs.close(); setValue(initial_state); - LOG(DEBUG) << "GPIO " << gpio_number_ << " online"; + LOG(DEBUG) << "Gpio " << gpio_number_ << " online"; } -void GPIO::setValue(GpioState state) +void Gpio::setValue(GpioState state) { std::ofstream gpio_fs("/sys/class/gpio/gpio" + gpio_number_ + "/value"); - CHECK(gpio_fs.is_open()) << "Could not set GPIO pin " << gpio_number_; + CHECK(gpio_fs.is_open()) << "Could not set Gpio pin " << gpio_number_; switch (state) { @@ -68,12 +68,12 @@ void GPIO::setValue(GpioState state) } } -GpioState GPIO::getValue() +GpioState Gpio::getValue() { std::ifstream gpio_fs("/sys/class/gpio/gpio" + gpio_number_ + "/value"); std::string level; - CHECK(gpio_fs.is_open()) << "Could not read GPIO pin"; + CHECK(gpio_fs.is_open()) << "Could not read Gpio pin"; std::getline(gpio_fs, level); if (level.compare("0") == 0) diff --git a/src/software/jetson_nano/gpio.h b/src/software/jetson_nano/gpio.h index 4db10a5fe7..35bf2e50f6 100644 --- a/src/software/jetson_nano/gpio.h +++ b/src/software/jetson_nano/gpio.h @@ -11,11 +11,11 @@ MAKE_ENUM(GpioState, LOW, HIGH); MAKE_ENUM(GpioDirection, INPUT, OUTPUT); -class GPIO +class Gpio { public: /* - * GPIO Sysfs Wrapper + * Gpio Sysfs Wrapper * * See https://www.kernel.org/doc/Documentation/gpio/sysfs.txt * @@ -23,7 +23,7 @@ class GPIO * @param direction The direction to configure this gpio in * @param initial_state The initial GpioState of the pin */ - GPIO(std::string gpio_number, GpioDirection direction, GpioState initial_state); + Gpio(std::string gpio_number, GpioDirection direction, GpioState initial_state); /** * Set the value to the provided state diff --git a/src/software/jetson_nano/services/motor.cpp b/src/software/jetson_nano/services/motor.cpp index daab974fd0..761c1d981f 100644 --- a/src/software/jetson_nano/services/motor.cpp +++ b/src/software/jetson_nano/services/motor.cpp @@ -44,11 +44,11 @@ static const uint8_t DRIBBLER_MOTOR_CHIP_SELECT = 4; static const char* SPI_PATHS[] = {"/dev/spidev0.0", "/dev/spidev0.1", "/dev/spidev0.2", "/dev/spidev0.3", "/dev/spidev0.4"}; -static const char* SPI_CS_DRIVER_TO_CONTROLLER_MUX_0_GPIO = "51"; -static const char* SPI_CS_DRIVER_TO_CONTROLLER_MUX_1_GPIO = "76"; -static const char* MOTOR_DRIVER_RESET_GPIO = "168"; -static const char* DRIVER_CONTROL_ENABLE_GPIO = "194"; -static const char* HEARTBEAT_GPIO = "216"; +static const char* SPI_CS_DRIVER_TO_CONTROLLER_MUX_0_Gpio = "51"; +static const char* SPI_CS_DRIVER_TO_CONTROLLER_MUX_1_Gpio = "76"; +static const char* MOTOR_DRIVER_RESET_Gpio = "168"; +static const char* DRIVER_CONTROL_ENABLE_Gpio = "194"; +static const char* HEARTBEAT_Gpio = "216"; extern "C" { @@ -72,14 +72,14 @@ extern "C" MotorService::MotorService(const RobotConstants_t& robot_constants, int control_loop_frequency_hz) - : spi_demux_select_0(SPI_CS_DRIVER_TO_CONTROLLER_MUX_0_GPIO, GpioDirection::OUTPUT, + : spi_demux_select_0(SPI_CS_DRIVER_TO_CONTROLLER_MUX_0_Gpio, GpioDirection::OUTPUT, GpioState::LOW), - spi_demux_select_1(SPI_CS_DRIVER_TO_CONTROLLER_MUX_1_GPIO, GpioDirection::OUTPUT, + spi_demux_select_1(SPI_CS_DRIVER_TO_CONTROLLER_MUX_1_Gpio, GpioDirection::OUTPUT, GpioState::LOW), - driver_control_enable_gpio(DRIVER_CONTROL_ENABLE_GPIO, GpioDirection::OUTPUT, + driver_control_enable_gpio(DRIVER_CONTROL_ENABLE_Gpio, GpioDirection::OUTPUT, GpioState::HIGH), - reset_gpio(MOTOR_DRIVER_RESET_GPIO, GpioDirection::OUTPUT, GpioState::HIGH), - heartbeat_gpio(HEARTBEAT_GPIO, GpioDirection::OUTPUT, GpioState::HIGH), + reset_gpio(MOTOR_DRIVER_RESET_Gpio, GpioDirection::OUTPUT, GpioState::HIGH), + heartbeat_gpio(HEARTBEAT_Gpio, GpioDirection::OUTPUT, GpioState::HIGH), euclidean_to_four_wheel(control_loop_frequency_hz, robot_constants) { robot_constants_ = robot_constants; diff --git a/src/software/jetson_nano/services/motor.h b/src/software/jetson_nano/services/motor.h index acfbbd3616..c4be0222bd 100644 --- a/src/software/jetson_nano/services/motor.h +++ b/src/software/jetson_nano/services/motor.h @@ -161,13 +161,13 @@ class MotorService bool checkDriverFault(uint8_t motor); // Select between driver and controller gpio - GPIO spi_demux_select_0; - GPIO spi_demux_select_1; + Gpio spi_demux_select_0; + Gpio spi_demux_select_1; // Enable driver gpio - GPIO driver_control_enable_gpio; - GPIO reset_gpio; - GPIO heartbeat_gpio; + Gpio driver_control_enable_gpio; + Gpio reset_gpio; + Gpio heartbeat_gpio; // Transfer Buffers uint8_t tx[5] = {0}; diff --git a/src/software/jetson_nano/setup_nano.sh b/src/software/jetson_nano/setup_nano.sh index e0d5183c0d..58acb90bd2 100755 --- a/src/software/jetson_nano/setup_nano.sh +++ b/src/software/jetson_nano/setup_nano.sh @@ -33,7 +33,7 @@ pip_libaries=( adafruit-circuitpython-rgb-display==3.10.9 Adafruit-PlatformDetect==3.18.0 Adafruit-PureIO==1.1.9 - Jetson.GPIO==2.0.17 + Jetson.Gpio==2.0.17 Pillow==9.1.0 redis==4.1.4 ) From 7791e35e9050a534eec6c285b42e35354c85a337 Mon Sep 17 00:00:00 2001 From: Phil Date: Thu, 19 Jan 2023 16:58:28 -0800 Subject: [PATCH 18/83] fixed up comments, still some to go --- src/software/ai/hl/stp/play/BUILD | 4 +- .../hl/stp/play/ball_placement_play_test.py | 4 +- .../ai/hl/stp/play/corner_kick_play_test.py | 12 +- .../crease_defense_play_test.py | 6 +- .../ai/hl/stp/play/defense_play_test.py | 158 ++---------------- .../play/enemy_ball_placement_play_test.py | 10 +- src/software/ai/hl/stp/play/halt_play_test.py | 6 +- .../{kickoff_test.py => kickoff_play_test.py} | 78 +-------- .../hl/stp/play/offense/offense_play_test.py | 6 +- .../simulated_tests/friendly_goal_scored.py | 8 +- 10 files changed, 48 insertions(+), 244 deletions(-) rename src/software/ai/hl/stp/play/{kickoff_test.py => kickoff_play_test.py} (55%) diff --git a/src/software/ai/hl/stp/play/BUILD b/src/software/ai/hl/stp/play/BUILD index 7521aa0e4e..12c5015444 100644 --- a/src/software/ai/hl/stp/play/BUILD +++ b/src/software/ai/hl/stp/play/BUILD @@ -359,9 +359,9 @@ cc_test( ) py_test( - name = "kickoff_test", + name = "kickoff_play_test", srcs = [ - "kickoff_test.py", + "kickoff_play_test.py", ], # TODO (#2619) Remove tag to run in parallel tags = [ diff --git a/src/software/ai/hl/stp/play/ball_placement_play_test.py b/src/software/ai/hl/stp/play/ball_placement_play_test.py index 30d30d9c5b..e5e8aa9ae4 100644 --- a/src/software/ai/hl/stp/play/ball_placement_play_test.py +++ b/src/software/ai/hl/stp/play/ball_placement_play_test.py @@ -80,11 +80,11 @@ def test_two_ai_ball_placement(simulated_test_runner, run_enemy_ai, test_duratio ) # Always Validation - # TODO- #2753 Validation + # TODO- #2780 Validation always_validation_sequence_set = [[]] # Eventually Validation - # TODO- #2753 Validation + # TODO- #2780 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( diff --git a/src/software/ai/hl/stp/play/corner_kick_play_test.py b/src/software/ai/hl/stp/play/corner_kick_play_test.py index 5ec31570af..7592a80eb7 100644 --- a/src/software/ai/hl/stp/play/corner_kick_play_test.py +++ b/src/software/ai/hl/stp/play/corner_kick_play_test.py @@ -68,17 +68,17 @@ def test_corner_kick_play_bottom_left(simulated_test_runner): ) # Always Validation - # TODO- #2753 Validation + # TODO- #2781 Validation always_validation_sequence_set = [[]] # Eventually Validation - # TODO- #2753 Validation + # TODO- #2781 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, - test_timeout_s=15, + test_timeout_s=10, ) @@ -139,17 +139,17 @@ def test_corner_kick_play_top_right(simulated_test_runner): ) # Always Validation - # TODO- #2753 Validation + # TODO- #2781 Validation always_validation_sequence_set = [[]] # Eventually Validation - # TODO- #2753 Validation + # TODO- #2781 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, - test_timeout_s=15, + test_timeout_s=7.5, ) diff --git a/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py b/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py index 6876e4202c..aafdaec323 100644 --- a/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py +++ b/src/software/ai/hl/stp/play/crease_defense/crease_defense_play_test.py @@ -4,7 +4,7 @@ import software.python_bindings as tbots from proto.play_pb2 import Play, PlayName -from software.simulated_tests.ball_enters_region import * +from proto.import_all_protos import * from software.simulated_tests.simulated_test_fixture import simulated_test_runner from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team @@ -66,11 +66,11 @@ def test_crease_defense_play(simulated_test_runner): ) # Always Validation - # TODO- #2753 Validation + # TODO- #2778 Validation always_validation_sequence_set = [[]] # Eventually Validation - # TODO- #2753 Validation + # TODO- #2778 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( diff --git a/src/software/ai/hl/stp/play/defense_play_test.py b/src/software/ai/hl/stp/play/defense_play_test.py index 7416c22cff..053cd74ce8 100644 --- a/src/software/ai/hl/stp/play/defense_play_test.py +++ b/src/software/ai/hl/stp/play/defense_play_test.py @@ -11,145 +11,25 @@ from proto.ssl_gc_common_pb2 import Team -def test_defense_play(simulated_test_runner): - - # starting point must be Point - ball_initial_pos = tbots.Point(0.9, 2.85) - - # Setup Bots - blue_bots = [ - tbots.Point(-4.5, 0), - tbots.Point(-3, 1.5), - tbots.Point(-3, 0.5), - tbots.Point(-3, -0.5), - tbots.Point(-3, -1.5), - tbots.Point(-3, -3.0), - ] - - yellow_bots = [ +@pytest.mark.parametrize("yellow_positions", [ + [ tbots.Point(1, 3), tbots.Point(1, -0.25), tbots.Point(1, -1.25), tbots.Field.createSSLDivisionBField().enemyGoalCenter(), tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), - ] - - # Game Controller Setup - simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.STOP, team=Team.UNKNOWN - ) - simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.FORCE_START, team=Team.BLUE - ) - - # Force play override here - blue_play = Play() - blue_play.name = PlayName.DefensePlay - - yellow_play = Play() - yellow_play.name = PlayName.HaltPlay - - 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.Vector(0, 0), - ), - ) - - # Always Validation - # TODO- #2753 Validation - always_validation_sequence_set = [[]] - - # Eventually Validation - # TODO- #2753 Validation - eventually_validation_sequence_set = [[]] - - simulated_test_runner.run_test( - eventually_validation_sequence_set=eventually_validation_sequence_set, - always_validation_sequence_set=always_validation_sequence_set, - test_timeout_s=10, - ) - - -def test_defense_play_one_threat(simulated_test_runner): - - # starting point must be Point - ball_initial_pos = tbots.Point(0.9, 2.85) - - # Setup Bots - blue_bots = [ - tbots.Point(-4.5, 0), - tbots.Point(-3, 1.5), - tbots.Point(-3, 0.5), - tbots.Point(-3, -0.5), - tbots.Point(-3, -1.5), - tbots.Point(-3, -3.0), - ] - - yellow_bots = [ - tbots.Point(1, 3), - tbots.Point(1, -0.25), - tbots.Point(1, -1.25), + ], + [ + tbots.Point(-2, 1.05), + tbots.Point(-3.5, 2), + tbots.Point(-1.5, 0), + tbots.Point(-2.3, -1), + tbots.Point(-3.8, -2), tbots.Field.createSSLDivisionBField().enemyGoalCenter(), - tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), - tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), - tbots.Field.createSSLDivisionBField().enemyDefenseArea().posXNegYCorner(), - tbots.Field.createSSLDivisionBField().enemyDefenseArea().posXPosYCorner(), ] - - # Game Controller Setup - simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.STOP, team=Team.UNKNOWN - ) - simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.FORCE_START, team=Team.BLUE - ) - - # Force play override here - blue_play = Play() - blue_play.name = PlayName.DefensePlay - - yellow_play = Play() - yellow_play.name = PlayName.HaltPlay - - 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.Vector(0, 0), - ), - ) - - # Always Validation - # TODO- #2753 Validation - always_validation_sequence_set = [[]] - - # Eventually Validation - # TODO- #2753 Validation - eventually_validation_sequence_set = [[]] - - simulated_test_runner.run_test( - eventually_validation_sequence_set=eventually_validation_sequence_set, - always_validation_sequence_set=always_validation_sequence_set, - test_timeout_s=10, - ) - - -def test_defense_play_close_to_net(simulated_test_runner): +]) +def test_defense_play(simulated_test_runner, yellow_positions): # starting point must be Point ball_initial_pos = tbots.Point(0.9, 2.85) @@ -164,15 +44,6 @@ def test_defense_play_close_to_net(simulated_test_runner): tbots.Point(-3, -3.0), ] - yellow_bots = [ - tbots.Point(-2, 1.05), - tbots.Point(-3.5, 2), - tbots.Point(-1.5, 0), - tbots.Point(-2.3, -1), - tbots.Point(-3.8, -2), - tbots.Field.createSSLDivisionBField().enemyGoalCenter(), - ] - # Game Controller Setup simulated_test_runner.gamecontroller.send_ci_input( gc_command=Command.Type.STOP, team=Team.UNKNOWN @@ -195,7 +66,7 @@ def test_defense_play_close_to_net(simulated_test_runner): simulated_test_runner.simulator_proto_unix_io.send_proto( WorldState, create_world_state( - yellow_robot_locations=yellow_bots, + yellow_robot_locations=yellow_positions, blue_robot_locations=blue_bots, ball_location=ball_initial_pos, ball_velocity=tbots.Vector(0, 0), @@ -203,12 +74,13 @@ def test_defense_play_close_to_net(simulated_test_runner): ) # Always Validation - # TODO- #2753 Validation + # TODO- #2782 Validation always_validation_sequence_set = [[]] # Eventually Validation - # TODO- #2753 Validation + # TODO- #2782 Validation eventually_validation_sequence_set = [[]] + simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, diff --git a/src/software/ai/hl/stp/play/enemy_ball_placement_play_test.py b/src/software/ai/hl/stp/play/enemy_ball_placement_play_test.py index d941df6027..83bc5b23a3 100644 --- a/src/software/ai/hl/stp/play/enemy_ball_placement_play_test.py +++ b/src/software/ai/hl/stp/play/enemy_ball_placement_play_test.py @@ -13,9 +13,9 @@ def test_two_ai_ball_placement(simulated_test_runner): - # starting point must be Point + # Initial position is from Blue's perspective ball_initial_pos = tbots.Point(2, 2) - # placement point must be Vector2 to work with game controller + # Final point is going to be from yellow's perspective (since yellow will be the one placing) ball_final_pos = tbots.Point(-3, -2) # Setup Bots @@ -74,17 +74,17 @@ def test_two_ai_ball_placement(simulated_test_runner): ) # Always Validation - # TODO- #2753 Validation + # TODO- #2783 Validation always_validation_sequence_set = [[]] # Eventually Validation - # TODO- #2753 Validation + # TODO- #2783 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, - test_timeout_s=15, + test_timeout_s=7.5, ) diff --git a/src/software/ai/hl/stp/play/halt_play_test.py b/src/software/ai/hl/stp/play/halt_play_test.py index 5db7f7a8e8..18f60a381e 100644 --- a/src/software/ai/hl/stp/play/halt_play_test.py +++ b/src/software/ai/hl/stp/play/halt_play_test.py @@ -4,7 +4,7 @@ import software.python_bindings as tbots from proto.play_pb2 import Play, PlayName -from software.simulated_tests.robot_halt import * +from software.simulated_tests.robot_speed_threshold import * from software.simulated_tests.simulated_test_fixture import simulated_test_runner from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team @@ -65,12 +65,12 @@ def test_halt_play(simulated_test_runner): always_validation_sequence_set = [[]] # Eventually Validation - eventually_validation_sequence_set = [[RobotEventuallyHalt()]] + eventually_validation_sequence_set = [[RobotSpeedEventuallyBelowThreshold(1e-3)]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, - test_timeout_s=25, + test_timeout_s=5, ci_cmd_with_delay=[blue_delayed_ci_call, yellow_delayed_ci_call], ) diff --git a/src/software/ai/hl/stp/play/kickoff_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py similarity index 55% rename from src/software/ai/hl/stp/play/kickoff_test.py rename to src/software/ai/hl/stp/play/kickoff_play_test.py index 7cb52f3aad..aeee08aa24 100644 --- a/src/software/ai/hl/stp/play/kickoff_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -4,84 +4,16 @@ import software.python_bindings as tbots from proto.play_pb2 import Play, PlayName -from software.simulated_tests.friendly_has_ball_possession import * -from software.simulated_tests.robot_enters_region import * +from proto.import_all_protos import * from software.simulated_tests.simulated_test_fixture import simulated_test_runner from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team -kickoff_friendly_always_validation = [ - [ - RobotNeverEntersRegion([tbots.Field.createSSLDivisionBField().enemyHalf()]), - FriendlyNeverHasBallPossession(), - ] -] - -kickoff_friendly_eventually_validation = [ - [ - # Robot in center circle - NumberOfRobotsEventuallyEntersRegion( - tbots.Field.createSSLDivisionBField().centerCircle(), 1 - ), - # Attacking Robot Placement - NumberOfRobotsEventuallyEntersRegion( - tbots.Rectangle(tbots.Point(-0.5, 2.5), tbots.Point(-1.5, -2.5)), 2 - ), - # Defending Robot Placement - NumberOfRobotsEventuallyEntersRegion( - tbots.Rectangle(tbots.Point(-3.2, 1.1), tbots.Point(-3.51, -1.1)), 3 - ), - ] -] - -kickoff_enemy_always_validation = [ - [ - RobotNeverEntersRegion( - [ - tbots.Field.createSSLDivisionBField().enemyHalf(), - tbots.Field.createSSLDivisionBField().centerCircle(), - ] - ), - FriendlyNeverHasBallPossession(), - ] -] -kickoff_enemy_eventually_validation = [ - [ - # Front 3 robots spread out in 3 zones - NumberOfRobotsEventuallyEntersRegion( - tbots.Rectangle(tbots.Point(-0.2, 1), tbots.Point(-0.4, 0.25)), 1 - ), - NumberOfRobotsEventuallyEntersRegion( - tbots.Rectangle(tbots.Point(-0.2, -1), tbots.Point(-0.4, -0.25)), 1 - ), - NumberOfRobotsEventuallyEntersRegion( - tbots.Rectangle(tbots.Point(-0.6, 0.1), tbots.Point(-0.9, -0.1)), 1 - ), - # 2 robots Defend the box - NumberOfRobotsEventuallyEntersRegion( - tbots.Rectangle(tbots.Point(-3.2, 1.1), tbots.Point(-3.5, -1.1)), 2 - ), - ] -] - - -@pytest.mark.parametrize( - "always_validation_list,eventually_validation_list,is_friendly_test", - [ - ( - kickoff_friendly_always_validation, - kickoff_friendly_eventually_validation, - True, - ), - (kickoff_enemy_always_validation, kickoff_enemy_eventually_validation, False), - ], -) +@pytest.mark.parametrize("is_friendly_test", [True, False]) def test_kickoff_play( simulated_test_runner, - always_validation_list, - eventually_validation_list, - is_friendly_test, + is_friendly_test ): # starting point must be Point @@ -145,11 +77,11 @@ def test_kickoff_play( ) # Always Validation - # TODO- #2753 Validation + # TODO- #2809 Validation always_validation_sequence_set = [[]] # Eventually Validation - # TODO- #2753 Validation + # TODO- #2809 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( diff --git a/src/software/ai/hl/stp/play/offense/offense_play_test.py b/src/software/ai/hl/stp/play/offense/offense_play_test.py index 0da9c84f38..f1eb90ea41 100644 --- a/src/software/ai/hl/stp/play/offense/offense_play_test.py +++ b/src/software/ai/hl/stp/play/offense/offense_play_test.py @@ -67,17 +67,17 @@ def test_offense_play(simulated_test_runner): ) # Always Validation - # TODO- #2753 Validation + # TODO- #2779 Validation always_validation_sequence_set = [[]] # Eventually Validation - # TODO- #2753 Validation + # TODO- #2779 Validation eventually_validation_sequence_set = [[]] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, - test_timeout_s=25, + test_timeout_s=15, ) diff --git a/src/software/simulated_tests/friendly_goal_scored.py b/src/software/simulated_tests/friendly_goal_scored.py index 9d06028c23..0fcd25472c 100644 --- a/src/software/simulated_tests/friendly_goal_scored.py +++ b/src/software/simulated_tests/friendly_goal_scored.py @@ -44,8 +44,8 @@ def __repr__(self): ( - FriendlyGoalEventuallyScored, - FriendlyGoalEventuallyRemoved, # These two don't make much sense - FriendlyGoalAlwaysScored, # These two don't make much sense - FriendlyGoalNeverScored, + FriendlyTeamEventuallyScored, + _FriendlyTeamGoalEventuallyRemoved, # These two don't make much sense + _FriendlyTeamAlwaysScored, # These two don't make much sense + FriendlyTeamNeverScored, ) = create_validation_types(FriendlyGoalScored) From b3b813b664a9bba41b0bfcfa42e1ff559d2112d8 Mon Sep 17 00:00:00 2001 From: suchirss Date: Thu, 26 Jan 2023 19:41:02 -0800 Subject: [PATCH 19/83] Just added a comment on line 79 that clarifies my task. --- src/software/ai/hl/stp/play/kickoff_play_test.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index aeee08aa24..05e605b9e1 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -76,6 +76,8 @@ def test_kickoff_play( ), ) + # [SUCHIR] - create two sets of always and eventually validation: 1) set up (not touching the ball yet) and 2) kicking off + # Always Validation # TODO- #2809 Validation always_validation_sequence_set = [[]] From be83cd7d613a2b4edf89f3e743f47376a814c51a Mon Sep 17 00:00:00 2001 From: suchirss Date: Sun, 19 Feb 2023 10:46:07 -0800 Subject: [PATCH 20/83] Added always-validation for 6 robots in friendly half. Fixes that need to be made in future commits: - build errors across several validation testing files - unnecessary comments need to be erased --- .../ai/hl/stp/play/kickoff_play_test.py | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 05e605b9e1..91660e758c 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -4,6 +4,7 @@ import software.python_bindings as tbots from proto.play_pb2 import Play, PlayName +from software.simulated_tests.robot_enters_region import * from proto.import_all_protos import * from software.simulated_tests.simulated_test_fixture import simulated_test_runner from proto.message_translation.tbots_protobuf import create_world_state @@ -11,10 +12,7 @@ @pytest.mark.parametrize("is_friendly_test", [True, False]) -def test_kickoff_play( - simulated_test_runner, - is_friendly_test -): +def test_kickoff_play(simulated_test_runner, is_friendly_test): # starting point must be Point ball_initial_pos = tbots.Point(0, 0) @@ -77,10 +75,28 @@ def test_kickoff_play( ) # [SUCHIR] - create two sets of always and eventually validation: 1) set up (not touching the ball yet) and 2) kicking off + # questions: + # am I validating just our team or both our team and the enemy team? + + # things to check: + # - robots must move to their own half of the field (excluding the center circle) + # > note that one robot of the attacking team is allowed to be within the whole center circle + # - ball must be kicked within 10 seconds + # - ball moves 0.05m from kick-off + + # 02/18/2023 + # should I change the simulated test to be named "robots_enter_region" instead + # is there a format to the comments in the simulated_test file (I wanna add comments) # Always Validation # TODO- #2809 Validation - always_validation_sequence_set = [[]] + always_validation_sequence_set = [ + [ + NumberOfRobotsAlwaysStaysInRegion( + region=[tbots.field.friendlyHalf()], req_robot_cnt=6 + ) + ] + ] # Eventually Validation # TODO- #2809 Validation From 0594740626d3b143fa5903ec6c25c93d6a8a2c4e Mon Sep 17 00:00:00 2001 From: suchirss Date: Sun, 19 Feb 2023 10:56:45 -0800 Subject: [PATCH 21/83] Removed unnecessary comments. Bugs: - several validation files don't build --- src/software/ai/hl/stp/play/kickoff_play_test.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 91660e758c..90bafca389 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -74,20 +74,6 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): ), ) - # [SUCHIR] - create two sets of always and eventually validation: 1) set up (not touching the ball yet) and 2) kicking off - # questions: - # am I validating just our team or both our team and the enemy team? - - # things to check: - # - robots must move to their own half of the field (excluding the center circle) - # > note that one robot of the attacking team is allowed to be within the whole center circle - # - ball must be kicked within 10 seconds - # - ball moves 0.05m from kick-off - - # 02/18/2023 - # should I change the simulated test to be named "robots_enter_region" instead - # is there a format to the comments in the simulated_test file (I wanna add comments) - # Always Validation # TODO- #2809 Validation always_validation_sequence_set = [ From 24dfaf2d82ec78aac250d0ec1feddd7acf959303 Mon Sep 17 00:00:00 2001 From: suchirss Date: Thu, 15 Jun 2023 17:46:30 -0700 Subject: [PATCH 22/83] test commit --- .../multiple_robots_enter_region.py | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/software/simulated_tests/multiple_robots_enter_region.py diff --git a/src/software/simulated_tests/multiple_robots_enter_region.py b/src/software/simulated_tests/multiple_robots_enter_region.py new file mode 100644 index 0000000000..10e54e5130 --- /dev/null +++ b/src/software/simulated_tests/multiple_robots_enter_region.py @@ -0,0 +1,109 @@ +import software.python_bindings as tbots +from proto.import_all_protos import * + +from software.simulated_tests.validation import ( + Validation, + create_validation_geometry, + create_validation_types, +) + + +class RobotEntersRegion(Validation): + + """Checks if a Robot enters any of the provided regions.""" + + def __init__(self, regions=None, count=1): + self.regions = regions if regions else [] + self.count = count + + def get_validation_status(self, world) -> ValidationStatus: + """Checks if _any_ robot enters the provided regions + + :param world: The world msg to validate + :returns: FAILING until a robot enters any of the regions + PASSING when a robot enters + """ + for region in self.regions: + for robot in world.friendly_team.team_robots: + if tbots.contains( + region, tbots.createPoint(robot.current_state.global_position) + ): + return ValidationStatus.PASSING + + return ValidationStatus.FAILING + + def get_validation_geometry(self, world) -> ValidationGeometry: + """ + (override) shows regions to enter + """ + return create_validation_geometry(self.regions) + + def __repr__(self): + return "Check for robot in regions " + ",".join( + repr(region) for region in self.regions + ) + + +( + RobotEventuallyEntersRegion, + RobotEventuallyExitsRegion, + RobotAlwaysStaysInRegion, + RobotNeverEntersRegion, +) = create_validation_types(RobotEntersRegion) + + +class NumberOfRobotsEntersRegion(Validation): + + """Checks if a certain number of Robots enters a specific region.""" + + def __init__(self, region, req_robot_cnt): + self.region = region + self.req_robot_cnt = req_robot_cnt + # map to keep track of robot positions + self.robot_in_zone = {} + + def get_validation_status(self, world) -> ValidationStatus: + """Checks if a specific number of robots enter the provided region + + :param world: The world msg to validate + :returns: FAILING until req_robot_cnt robots enter the region + PASSING when req_robot_cnt robots enters + """ + # Update the map with latest robot status + for robot in world.friendly_team.team_robots: + self.robot_in_zone[robot.id] = tbots.contains( + self.region, tbots.createPoint(robot.current_state.global_position) + ) + # Check if there are at least req_robot_cnt number of robots in zone + curr_cnt = 0 + for robot_id in self.robot_in_zone: + if self.robot_in_zone[robot_id]: + curr_cnt += 1 + + # Validate on curr_cnt + if curr_cnt == self.req_robot_cnt: + return ValidationStatus.PASSING + else: + return ValidationStatus.FAILING + + def get_validation_geometry(self, world) -> ValidationGeometry: + """ + (override) shows region to enter + """ + return create_validation_geometry([self.region]) + + def __repr__(self): + return ( + "Check for " + + str(self.req_robot_cnt) + + " robots in region " + + ",".join(repr(self.region)) + ) + + +( + NumberOfRobotsEventuallyEntersRegion, + NumberOfRobotsEventuallyExitsRegion, + NumberOfRobotsAlwaysStaysInRegion, + NumberOfRobotsNeverEntersRegion, +) = create_validation_types(NumberOfRobotsEntersRegion) From bffbe1852c5cd0477287160750cc100e6c3db526 Mon Sep 17 00:00:00 2001 From: suchirss Date: Thu, 15 Jun 2023 20:38:43 -0700 Subject: [PATCH 23/83] added eventually validation for ball exiting center circle --- .../ai/hl/stp/play/defense_play_test.py | 35 ++++++++++--------- .../ai/hl/stp/play/kickoff_play_test.py | 13 +++++-- .../simulated_tests/robot_enters_region.py | 11 ++++-- .../thunderscope/binary_context_managers.py | 2 +- 4 files changed, 39 insertions(+), 22 deletions(-) diff --git a/src/software/ai/hl/stp/play/defense_play_test.py b/src/software/ai/hl/stp/play/defense_play_test.py index 053cd74ce8..6a7834de8a 100644 --- a/src/software/ai/hl/stp/play/defense_play_test.py +++ b/src/software/ai/hl/stp/play/defense_play_test.py @@ -11,24 +11,27 @@ from proto.ssl_gc_common_pb2 import Team -@pytest.mark.parametrize("yellow_positions", [ +@pytest.mark.parametrize( + "yellow_positions", [ - tbots.Point(1, 3), - tbots.Point(1, -0.25), - tbots.Point(1, -1.25), - tbots.Field.createSSLDivisionBField().enemyGoalCenter(), - tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), - tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + [ + tbots.Point(1, 3), + tbots.Point(1, -0.25), + tbots.Point(1, -1.25), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + ], + [ + tbots.Point(-2, 1.05), + tbots.Point(-3.5, 2), + tbots.Point(-1.5, 0), + tbots.Point(-2.3, -1), + tbots.Point(-3.8, -2), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + ], ], - [ - tbots.Point(-2, 1.05), - tbots.Point(-3.5, 2), - tbots.Point(-1.5, 0), - tbots.Point(-2.3, -1), - tbots.Point(-3.8, -2), - tbots.Field.createSSLDivisionBField().enemyGoalCenter(), - ] -]) +) def test_defense_play(simulated_test_runner, yellow_positions): # starting point must be Point diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 90bafca389..55188e1997 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -5,6 +5,7 @@ import software.python_bindings as tbots from proto.play_pb2 import Play, PlayName from software.simulated_tests.robot_enters_region import * +from software.simulated_tests.ball_enters_region import * from proto.import_all_protos import * from software.simulated_tests.simulated_test_fixture import simulated_test_runner from proto.message_translation.tbots_protobuf import create_world_state @@ -74,19 +75,27 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): ), ) + + # Always Validation # TODO- #2809 Validation always_validation_sequence_set = [ [ NumberOfRobotsAlwaysStaysInRegion( - region=[tbots.field.friendlyHalf()], req_robot_cnt=6 + region=[tbots.field.friendlyHalf], req_robot_cnt=6 ) ] ] # Eventually Validation # TODO- #2809 Validation - eventually_validation_sequence_set = [[]] + eventually_validation_sequence_set = [ + [ + BallEventuallyExitsRegion( + region=[tbots.field.centerCircle] + ) + ] + ] simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, diff --git a/src/software/simulated_tests/robot_enters_region.py b/src/software/simulated_tests/robot_enters_region.py index 422e05b087..89a805e11b 100644 --- a/src/software/simulated_tests/robot_enters_region.py +++ b/src/software/simulated_tests/robot_enters_region.py @@ -12,8 +12,9 @@ class RobotEntersRegion(Validation): """Checks if a Robot enters any of the provided regions.""" - def __init__(self, regions=None): + def __init__(self, regions=None, num_robots=1): self.regions = regions if regions else [] + self.num_robots = num_robots def get_validation_status(self, world) -> ValidationStatus: """Checks if _any_ robot enters the provided regions @@ -22,12 +23,16 @@ def get_validation_status(self, world) -> ValidationStatus: :returns: FAILING until a robot enters any of the regions PASSING when a robot enters """ + count = 0 + for region in self.regions: for robot in world.friendly_team.team_robots: if tbots.contains( - region, tbots.createPoint(robot.current_state.global_position) + region, tbots.createPoint(robot.current_stateS.global_position) ): - return ValidationStatus.PASSING + count += 1 + if count == self.num_robots: + return ValidationStatus.PASSING return ValidationStatus.FAILING diff --git a/src/software/thunderscope/binary_context_managers.py b/src/software/thunderscope/binary_context_managers.py index 7e2d1000a3..5bc6fd0b80 100644 --- a/src/software/thunderscope/binary_context_managers.py +++ b/src/software/thunderscope/binary_context_managers.py @@ -359,7 +359,7 @@ class Gamecontroller(object): """ Gamecontroller Context Manager """ - CI_MODE_LAUNCH_DELAY_S = 0.3 + CI_MODE_LAUNCH_DELAY_S = 1 REFEREE_IP = "224.5.23.1" CI_MODE_OUTPUT_RECEIVE_BUFFER_SIZE = 9000 From 25267092f53e0bd5a5a110044f3d0adde203bdf1 Mon Sep 17 00:00:00 2001 From: suchirss Date: Mon, 19 Jun 2023 00:09:44 -0700 Subject: [PATCH 24/83] Decided on new validation strategy where a certain amount of robots do not enter a region. Incomplete process but committing prior to laptop dying. --- src/software/ai/hl/stp/play/kickoff_play_test.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 55188e1997..9107cb7bd9 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -82,7 +82,13 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): always_validation_sequence_set = [ [ NumberOfRobotsAlwaysStaysInRegion( - region=[tbots.field.friendlyHalf], req_robot_cnt=6 + region=tbots.field.friendlyHalf(), req_robot_cnt=5 + ), + NumberOfRobotsAlwaysStaysInRegion( + region=tbots.field.centreCircle(), req_robot_cnt=1 + ), + NumberOfRobotsNeverEntersRegion( + region=tbots.field.enemyHalf(), req_robot_cnt=2 ) ] ] @@ -92,7 +98,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): eventually_validation_sequence_set = [ [ BallEventuallyExitsRegion( - region=[tbots.field.centerCircle] + region=tbots.field.centreCircle() ) ] ] From 1eac5a6a43eee24b33fc035f874205eac3c96025 Mon Sep 17 00:00:00 2001 From: suchirss Date: Mon, 19 Jun 2023 12:37:58 -0700 Subject: [PATCH 25/83] changed centreCircle() to centerCircle() (spelling issue) --- src/software/ai/hl/stp/play/kickoff_play_test.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 9107cb7bd9..aeec20b060 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -81,12 +81,6 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): # TODO- #2809 Validation always_validation_sequence_set = [ [ - NumberOfRobotsAlwaysStaysInRegion( - region=tbots.field.friendlyHalf(), req_robot_cnt=5 - ), - NumberOfRobotsAlwaysStaysInRegion( - region=tbots.field.centreCircle(), req_robot_cnt=1 - ), NumberOfRobotsNeverEntersRegion( region=tbots.field.enemyHalf(), req_robot_cnt=2 ) @@ -98,7 +92,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): eventually_validation_sequence_set = [ [ BallEventuallyExitsRegion( - region=tbots.field.centreCircle() + region=tbots.field.centerCircle() ) ] ] From 1ea49a67da6b3febaa58d541112c5799479636bb Mon Sep 17 00:00:00 2001 From: suchirss Date: Tue, 20 Jun 2023 13:50:35 -0700 Subject: [PATCH 26/83] Ran formatting script --- src/software/ai/hl/stp/play/kickoff_play_test.py | 8 +------- src/software/simulated_tests/ball_enters_region.py | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index aeec20b060..3a66b1f156 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -75,8 +75,6 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): ), ) - - # Always Validation # TODO- #2809 Validation always_validation_sequence_set = [ @@ -90,11 +88,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): # Eventually Validation # TODO- #2809 Validation eventually_validation_sequence_set = [ - [ - BallEventuallyExitsRegion( - region=tbots.field.centerCircle() - ) - ] + [BallEventuallyExitsRegion(region=tbots.field.centerCircle())] ] simulated_test_runner.run_test( diff --git a/src/software/simulated_tests/ball_enters_region.py b/src/software/simulated_tests/ball_enters_region.py index 34cf852fe8..85613fb0e9 100644 --- a/src/software/simulated_tests/ball_enters_region.py +++ b/src/software/simulated_tests/ball_enters_region.py @@ -33,7 +33,7 @@ def get_validation_status(self, world) -> ValidationStatus: def get_validation_geometry(self, world) -> ValidationGeometry: """Returns the underlying geometry this validation is checking - :param world: The world msg to create v alidation geometry from + :param world: The world msg to create validation geometry from :returns: ValidationGeometry containing geometry to visualize """ From b20c9e9d017dfae3529fa2048bda8316ae34b122 Mon Sep 17 00:00:00 2001 From: suchirss Date: Mon, 26 Jun 2023 00:41:02 -0700 Subject: [PATCH 27/83] Implemented pytest parametrize feature in always validation set. Added enemy validation. --- .../ai/hl/stp/play/kickoff_play_test.py | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 3a66b1f156..1fd86d095b 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -14,7 +14,6 @@ @pytest.mark.parametrize("is_friendly_test", [True, False]) def test_kickoff_play(simulated_test_runner, is_friendly_test): - # starting point must be Point ball_initial_pos = tbots.Point(0, 0) @@ -77,20 +76,32 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): # Always Validation # TODO- #2809 Validation - always_validation_sequence_set = [ - [ + always_validation_sequence_set = [[]] + + if is_friendly_test: + always_validation_sequence_set[0].append( NumberOfRobotsNeverEntersRegion( - region=tbots.field.enemyHalf(), req_robot_cnt=2 + region=[tbots.field.enemyHalf(), tbots.field.centerCircle()], req_robot_cnt=2 ) - ] - ] + ) + else: + always_validation_sequence_set[0].append( + NumberOfRobotsNeverEntersRegion( + region=[tbots.field.friendlyHalf(), tbots.field.centerCircle()], req_robot_cnt=2 + ) + ) # Eventually Validation # TODO- #2809 Validation eventually_validation_sequence_set = [ - [BallEventuallyExitsRegion(region=tbots.field.centerCircle())] + [ + BallEventuallyExitsRegion( + region=[tbots.circle()] + ) + ] ] + simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, From 43b87b7d1d6d0b45a8b41c4969af3b0fcd53beb3 Mon Sep 17 00:00:00 2001 From: suchirss Date: Mon, 26 Jun 2023 00:55:44 -0700 Subject: [PATCH 28/83] Added circular region of 0.05 radius with focus at (0,0) to BallEventuallyExitsRegion() eventually validation. --- src/software/ai/hl/stp/play/kickoff_play_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 1fd86d095b..21029bbfbe 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -96,7 +96,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): eventually_validation_sequence_set = [ [ BallEventuallyExitsRegion( - region=[tbots.circle()] + region=[tbots.circle(ball_initial_pos, 0.05)] ) ] ] From 375896052d3fa830d201b760f6f7744f8008bfa7 Mon Sep 17 00:00:00 2001 From: suchirss Date: Mon, 26 Jun 2023 01:24:21 -0700 Subject: [PATCH 29/83] Revert "added eventually validation for ball exiting center circle" This reverts commit bffbe1852c5cd0477287160750cc100e6c3db526. # Conflicts: # src/software/ai/hl/stp/play/kickoff_play_test.py --- .../ai/hl/stp/play/defense_play_test.py | 35 +++++++++---------- .../simulated_tests/robot_enters_region.py | 11 ++---- .../thunderscope/binary_context_managers.py | 2 +- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/src/software/ai/hl/stp/play/defense_play_test.py b/src/software/ai/hl/stp/play/defense_play_test.py index 6a7834de8a..053cd74ce8 100644 --- a/src/software/ai/hl/stp/play/defense_play_test.py +++ b/src/software/ai/hl/stp/play/defense_play_test.py @@ -11,27 +11,24 @@ from proto.ssl_gc_common_pb2 import Team -@pytest.mark.parametrize( - "yellow_positions", +@pytest.mark.parametrize("yellow_positions", [ [ - [ - tbots.Point(1, 3), - tbots.Point(1, -0.25), - tbots.Point(1, -1.25), - tbots.Field.createSSLDivisionBField().enemyGoalCenter(), - tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), - tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), - ], - [ - tbots.Point(-2, 1.05), - tbots.Point(-3.5, 2), - tbots.Point(-1.5, 0), - tbots.Point(-2.3, -1), - tbots.Point(-3.8, -2), - tbots.Field.createSSLDivisionBField().enemyGoalCenter(), - ], + tbots.Point(1, 3), + tbots.Point(1, -0.25), + tbots.Point(1, -1.25), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), ], -) + [ + tbots.Point(-2, 1.05), + tbots.Point(-3.5, 2), + tbots.Point(-1.5, 0), + tbots.Point(-2.3, -1), + tbots.Point(-3.8, -2), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + ] +]) def test_defense_play(simulated_test_runner, yellow_positions): # starting point must be Point diff --git a/src/software/simulated_tests/robot_enters_region.py b/src/software/simulated_tests/robot_enters_region.py index 89a805e11b..422e05b087 100644 --- a/src/software/simulated_tests/robot_enters_region.py +++ b/src/software/simulated_tests/robot_enters_region.py @@ -12,9 +12,8 @@ class RobotEntersRegion(Validation): """Checks if a Robot enters any of the provided regions.""" - def __init__(self, regions=None, num_robots=1): + def __init__(self, regions=None): self.regions = regions if regions else [] - self.num_robots = num_robots def get_validation_status(self, world) -> ValidationStatus: """Checks if _any_ robot enters the provided regions @@ -23,16 +22,12 @@ def get_validation_status(self, world) -> ValidationStatus: :returns: FAILING until a robot enters any of the regions PASSING when a robot enters """ - count = 0 - for region in self.regions: for robot in world.friendly_team.team_robots: if tbots.contains( - region, tbots.createPoint(robot.current_stateS.global_position) + region, tbots.createPoint(robot.current_state.global_position) ): - count += 1 - if count == self.num_robots: - return ValidationStatus.PASSING + return ValidationStatus.PASSING return ValidationStatus.FAILING diff --git a/src/software/thunderscope/binary_context_managers.py b/src/software/thunderscope/binary_context_managers.py index 5bc6fd0b80..7e2d1000a3 100644 --- a/src/software/thunderscope/binary_context_managers.py +++ b/src/software/thunderscope/binary_context_managers.py @@ -359,7 +359,7 @@ class Gamecontroller(object): """ Gamecontroller Context Manager """ - CI_MODE_LAUNCH_DELAY_S = 1 + CI_MODE_LAUNCH_DELAY_S = 0.3 REFEREE_IP = "224.5.23.1" CI_MODE_OUTPUT_RECEIVE_BUFFER_SIZE = 9000 From 3927b21ea85328c0ebbf09a23b0efabe58d3e13b Mon Sep 17 00:00:00 2001 From: suchirss Date: Mon, 26 Jun 2023 02:58:31 -0700 Subject: [PATCH 30/83] Ran formatting script --- .../ai/hl/stp/play/defense_play_test.py | 35 ++++++++++--------- .../ai/hl/stp/play/kickoff_play_test.py | 13 +++---- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/software/ai/hl/stp/play/defense_play_test.py b/src/software/ai/hl/stp/play/defense_play_test.py index 053cd74ce8..6a7834de8a 100644 --- a/src/software/ai/hl/stp/play/defense_play_test.py +++ b/src/software/ai/hl/stp/play/defense_play_test.py @@ -11,24 +11,27 @@ from proto.ssl_gc_common_pb2 import Team -@pytest.mark.parametrize("yellow_positions", [ +@pytest.mark.parametrize( + "yellow_positions", [ - tbots.Point(1, 3), - tbots.Point(1, -0.25), - tbots.Point(1, -1.25), - tbots.Field.createSSLDivisionBField().enemyGoalCenter(), - tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), - tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + [ + tbots.Point(1, 3), + tbots.Point(1, -0.25), + tbots.Point(1, -1.25), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), + tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + ], + [ + tbots.Point(-2, 1.05), + tbots.Point(-3.5, 2), + tbots.Point(-1.5, 0), + tbots.Point(-2.3, -1), + tbots.Point(-3.8, -2), + tbots.Field.createSSLDivisionBField().enemyGoalCenter(), + ], ], - [ - tbots.Point(-2, 1.05), - tbots.Point(-3.5, 2), - tbots.Point(-1.5, 0), - tbots.Point(-2.3, -1), - tbots.Point(-3.8, -2), - tbots.Field.createSSLDivisionBField().enemyGoalCenter(), - ] -]) +) def test_defense_play(simulated_test_runner, yellow_positions): # starting point must be Point diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 21029bbfbe..a1fbac586e 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -81,27 +81,24 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): if is_friendly_test: always_validation_sequence_set[0].append( NumberOfRobotsNeverEntersRegion( - region=[tbots.field.enemyHalf(), tbots.field.centerCircle()], req_robot_cnt=2 + region=[tbots.field.enemyHalf(), tbots.field.centerCircle()], + req_robot_cnt=2, ) ) else: always_validation_sequence_set[0].append( NumberOfRobotsNeverEntersRegion( - region=[tbots.field.friendlyHalf(), tbots.field.centerCircle()], req_robot_cnt=2 + region=[tbots.field.friendlyHalf(), tbots.field.centerCircle()], + req_robot_cnt=2, ) ) # Eventually Validation # TODO- #2809 Validation eventually_validation_sequence_set = [ - [ - BallEventuallyExitsRegion( - region=[tbots.circle(ball_initial_pos, 0.05)] - ) - ] + [BallEventuallyExitsRegion(region=[tbots.circle(ball_initial_pos, 0.05)])] ] - simulated_test_runner.run_test( eventually_validation_sequence_set=eventually_validation_sequence_set, always_validation_sequence_set=always_validation_sequence_set, From aae3ba85e524a6edada73ce5cc3078d9bae9a11b Mon Sep 17 00:00:00 2001 From: suchirss Date: Mon, 26 Jun 2023 11:40:00 -0700 Subject: [PATCH 31/83] Changed attributes to have correct capitalization (i.e: tbots.Field instead of tbots.field). --- src/software/ai/hl/stp/play/kickoff_play_test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index a1fbac586e..dbc0cdf649 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -81,14 +81,14 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): if is_friendly_test: always_validation_sequence_set[0].append( NumberOfRobotsNeverEntersRegion( - region=[tbots.field.enemyHalf(), tbots.field.centerCircle()], + region=[tbots.Field.EnemyHalf(), tbots.Field.CenterCircle()], req_robot_cnt=2, ) ) else: always_validation_sequence_set[0].append( NumberOfRobotsNeverEntersRegion( - region=[tbots.field.friendlyHalf(), tbots.field.centerCircle()], + region=[tbots.Field.FriendlyHalf(), tbots.Field.CenterCircle()], req_robot_cnt=2, ) ) @@ -96,7 +96,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): # Eventually Validation # TODO- #2809 Validation eventually_validation_sequence_set = [ - [BallEventuallyExitsRegion(region=[tbots.circle(ball_initial_pos, 0.05)])] + [BallEventuallyExitsRegion(region=[tbots.Circle(ball_initial_pos, 0.05)])] ] simulated_test_runner.run_test( From 29b8ebc1141cdc54302640192acd46d92fbb9a1b Mon Sep 17 00:00:00 2001 From: suchirss Date: Mon, 26 Jun 2023 12:25:24 -0700 Subject: [PATCH 32/83] Fixed some more capitalization --- src/software/ai/hl/stp/play/kickoff_play_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index dbc0cdf649..56ff890ba0 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -81,14 +81,14 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): if is_friendly_test: always_validation_sequence_set[0].append( NumberOfRobotsNeverEntersRegion( - region=[tbots.Field.EnemyHalf(), tbots.Field.CenterCircle()], + region=[tbots.Field.enemyHalf(), tbots.Field.centerCircle()], req_robot_cnt=2, ) ) else: always_validation_sequence_set[0].append( NumberOfRobotsNeverEntersRegion( - region=[tbots.Field.FriendlyHalf(), tbots.Field.CenterCircle()], + region=[tbots.Field.friendlyHalf(), tbots.Field.centerCircle()], req_robot_cnt=2, ) ) From 6b8c492c437c4b0f0f526c96e6253937b1b6e7ac Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 14 Oct 2023 21:15:55 -0700 Subject: [PATCH 33/83] Started creating orValidation.py extension which allows multiple validations to be checked against a boolean or operator. Note that the code for this new file is incomplete and incorrect at this time. --- src/software/ai/hl/stp/play/kickoff_play_test.py | 12 ++++++++++-- src/software/simulated_tests/or_validation.py | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 src/software/simulated_tests/or_validation.py diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 56ff890ba0..6694e53b87 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -74,27 +74,35 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): ), ) + + # Always Validation + # add always validation: ball is always within bounds + # req_robot_cnt returns pass if it is not equal to 2 - + # need to create new validation sequence that works on "at least" logic # TODO- #2809 Validation always_validation_sequence_set = [[]] if is_friendly_test: always_validation_sequence_set[0].append( NumberOfRobotsNeverEntersRegion( - region=[tbots.Field.enemyHalf(), tbots.Field.centerCircle()], + region=[tbots.Field.createSSLDivisionBField.enemyHalf(), + tbots.Field.createSSLDivisionBField.centerCircle()], req_robot_cnt=2, ) ) else: always_validation_sequence_set[0].append( NumberOfRobotsNeverEntersRegion( - region=[tbots.Field.friendlyHalf(), tbots.Field.centerCircle()], + region=[tbots.Field.createSSLDivisionBField().friendlyHalf(), + tbots.Field.createSSLDivisionBField.centerCircle()], req_robot_cnt=2, ) ) # Eventually Validation # TODO- #2809 Validation + # make only for friendly eventually_validation_sequence_set = [ [BallEventuallyExitsRegion(region=[tbots.Circle(ball_initial_pos, 0.05)])] ] diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py new file mode 100644 index 0000000000..829745222b --- /dev/null +++ b/src/software/simulated_tests/or_validation.py @@ -0,0 +1,15 @@ +import pytest + +import software.python_bindings as tbots +from proto.validation_pb2 import * +import validation + +class OrValidation(validation): + + """An or extension to the validation function""" + + def get_validation_status(self, world): + for validation in validation_set: + status = validation.get_validation_status() + if status: + From 6c3ea4119dcce5483b3ce4feaac7cf7db783c97a Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 11 Nov 2023 12:39:24 -0800 Subject: [PATCH 34/83] Futher developed get_validation_status, get_validation_type, and get_validation_geometry functions under the OrValidation class. --- src/software/simulated_tests/or_validation.py | 43 ++++++++++++++++--- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py index 829745222b..41e0bd57c3 100644 --- a/src/software/simulated_tests/or_validation.py +++ b/src/software/simulated_tests/or_validation.py @@ -2,14 +2,43 @@ import software.python_bindings as tbots from proto.validation_pb2 import * -import validation +from software.simulated_tests.validation import ( + Validation, + create_validation_geometry, + create_validation_types, +) -class OrValidation(validation): - - """An or extension to the validation function""" +class OrValidation(): + def __init__ (self, validation): + """An or extension to the validation function""" + self.validation = validation def get_validation_status(self, world): - for validation in validation_set: - status = validation.get_validation_status() - if status: + for validation in self.validation: # + if validation.get_validation_status(world) == ValidationStatus.PASSING: # should I be using ValidationStatus.PASSING or just == FAILING + return ValidationStatus.PASSING + return ValidationStatus.PASSING + + def get_validation_type(self, world): # do I need to return anything here or even include this at all + validation_type_initial = ValidationType + + for validation in self.validation: + 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 + + + def get_validation_geometry(self, world): + + validation_geometry = ValidationGeometry() + + for validation in self.validation: + validation.get_validation_geometry(world) # why is this needed + validation_geometry.polygons += validation.polygons + validation_geometry.circles += validation.circles + validation_geometry.vectors += validation.vectors + validation_geometry.segments += validation.segments + return validation_geometry \ No newline at end of file From b366b5c36175117bbcda3d0dc0dedc7b0f7cf8eb Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 11 Nov 2023 15:50:49 -0800 Subject: [PATCH 35/83] Further developed implementation of or validation within kickoff validation file. Fixed some issues in or_validation file. --- .../ai/hl/stp/play/kickoff_play_test.py | 15 +++++++---- src/software/simulated_tests/BUILD | 1 + src/software/simulated_tests/or_validation.py | 27 ++++++++++--------- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 6694e53b87..814ecb2636 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -85,11 +85,16 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): if is_friendly_test: always_validation_sequence_set[0].append( - NumberOfRobotsNeverEntersRegion( - region=[tbots.Field.createSSLDivisionBField.enemyHalf(), - tbots.Field.createSSLDivisionBField.centerCircle()], - req_robot_cnt=2, - ) + OrValidation( + [ + NumberOfRobotsAlwaysStaysInRegion( + region=[tbots.Field.createSSLDivisionBField.centerCircle()], + req_robot_cnt=0, + ), + NumberOfRobotsAlwaysStaysInRegion( + region=[tbots.Field.createSSLDivisionBField.centerCircle()], + req_robot_cnt=1, + )] ) else: always_validation_sequence_set[0].append( diff --git a/src/software/simulated_tests/BUILD b/src/software/simulated_tests/BUILD index 7eda760e7b..d2d7b72ba7 100644 --- a/src/software/simulated_tests/BUILD +++ b/src/software/simulated_tests/BUILD @@ -108,6 +108,7 @@ py_library( "friendly_goal_scored.py", "friendly_has_ball_possession.py", "friendly_team_scored.py", + "or_validation.py", "robot_enters_region.py", "robot_halt.py", "robot_speed_threshold.py", diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py index 41e0bd57c3..2b4f838d6b 100644 --- a/src/software/simulated_tests/or_validation.py +++ b/src/software/simulated_tests/or_validation.py @@ -7,6 +7,9 @@ create_validation_geometry, create_validation_types, ) +from software.simulated_tests import { + OrValidation +} class OrValidation(): def __init__ (self, validation): @@ -19,17 +22,6 @@ def get_validation_status(self, world): return ValidationStatus.PASSING return ValidationStatus.PASSING - def get_validation_type(self, world): # do I need to return anything here or even include this at all - validation_type_initial = ValidationType - - for validation in self.validation: - 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 - - def get_validation_geometry(self, world): validation_geometry = ValidationGeometry() @@ -41,4 +33,15 @@ def get_validation_geometry(self, world): validation_geometry.vectors += validation.vectors validation_geometry.segments += validation.segments - return validation_geometry \ No newline at end of file + return validation_geometry + + + def get_validation_type(self, world): + validation_type_initial = self.validation[0].get_validation_type + + for validation in self.validation: + validation_type = validation.get_validation_type + if validation_type != validation_type_initial: + raise TypeError("type of validation instances is not consistent") + # do I need to write a return statement or will the error account for this + return validation_type_initial \ No newline at end of file From 4f5e18f8e1699194871adb2138cc8cddafcba4b6 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 18 Nov 2023 14:58:08 -0800 Subject: [PATCH 36/83] Added validation of 6 robots within friendlyHalf + centreCircle in addition to OrValidation from previous commit. --- src/software/ai/hl/stp/play/kickoff_play_test.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 814ecb2636..eb77474a23 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -84,6 +84,14 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): always_validation_sequence_set = [[]] if is_friendly_test: + always_validation_sequence_set[0].append( + NumberOfRobotsAlwaysStaysInRegion( + region=[tbots.Field.createSSLDivisionBField.friendlyHalf(), + tbots.Field.createSSLDivisionBField.centerCircle], + req_robot_cnt=6, + ) + ) + always_validation_sequence_set[0].append( OrValidation( [ @@ -95,6 +103,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): region=[tbots.Field.createSSLDivisionBField.centerCircle()], req_robot_cnt=1, )] + ) ) else: always_validation_sequence_set[0].append( From 2538d9be15fc5f72e22252b01b52d1bcb2b46497 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 18 Nov 2023 16:33:08 -0800 Subject: [PATCH 37/83] Resolves some errors when running kickoff_play_test.py --- .../ai/hl/stp/play/kickoff_play_test.py | 38 +++++++++++-------- src/software/simulated_tests/or_validation.py | 4 +- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index eb77474a23..d53822a2f1 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -10,7 +10,7 @@ from software.simulated_tests.simulated_test_fixture import simulated_test_runner 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): @@ -86,8 +86,8 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): if is_friendly_test: always_validation_sequence_set[0].append( NumberOfRobotsAlwaysStaysInRegion( - region=[tbots.Field.createSSLDivisionBField.friendlyHalf(), - tbots.Field.createSSLDivisionBField.centerCircle], + regions=[tbots.Field.createSSLDivisionBField().friendlyHalf(), + tbots.Field.createSSLDivisionBField().centerCircle()], req_robot_cnt=6, ) ) @@ -96,38 +96,46 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): OrValidation( [ NumberOfRobotsAlwaysStaysInRegion( - region=[tbots.Field.createSSLDivisionBField.centerCircle()], + regions=[tbots.Field.createSSLDivisionBField().centerCircle()], req_robot_cnt=0, ), NumberOfRobotsAlwaysStaysInRegion( - region=[tbots.Field.createSSLDivisionBField.centerCircle()], + regions=[tbots.Field.createSSLDivisionBField().centerCircle()], req_robot_cnt=1, )] ) ) else: always_validation_sequence_set[0].append( - NumberOfRobotsNeverEntersRegion( - region=[tbots.Field.createSSLDivisionBField().friendlyHalf(), - tbots.Field.createSSLDivisionBField.centerCircle()], - req_robot_cnt=2, + NumberOfRobotsAlwaysStaysInRegion( + regions=[tbots.Field.createSSLDivisionBField().friendlyHalf(), + tbots.Field.createSSLDivisionBField().centerCircle()], + req_robot_cnt=6, + ) + ) + + always_validation_sequence_set[0].append( + NumberOfRobotsAlwaysStaysInRegion( + regions=[tbots.Field.createSSLDivisionBField().centerCircle()], + req_robot_cnt=0, ) ) # Eventually Validation # TODO- #2809 Validation # make only for friendly - eventually_validation_sequence_set = [ - [BallEventuallyExitsRegion(region=[tbots.Circle(ball_initial_pos, 0.05)])] - ] + eventually_validation_sequence_set = [[]] + + eventually_validation_sequence_set[0].append( + BallEventuallyExitsRegion(regions=tbots.Circle(ball_initial_pos, 0.05)) + ) simulated_test_runner.run_test( - eventually_validation_sequence_set=eventually_validation_sequence_set, - always_validation_sequence_set=always_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, ) - if __name__ == "__main__": # Run the test, -s disables all capturing at -vv increases verbosity sys.exit(pytest.main([__file__, "-svv"])) diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py index 2b4f838d6b..58677703f4 100644 --- a/src/software/simulated_tests/or_validation.py +++ b/src/software/simulated_tests/or_validation.py @@ -7,9 +7,7 @@ create_validation_geometry, create_validation_types, ) -from software.simulated_tests import { - OrValidation -} + class OrValidation(): def __init__ (self, validation): From eb67efa974a46fc4aa11283e56f1caa9d2fad7a9 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 20 Jan 2024 13:45:28 -0800 Subject: [PATCH 38/83] Modified NumberOfRobotsEnterRegion() in robot_enters_region.py to accept and work with a list of regions. Fixed TypeError in kickoff_play_test.py. --- .../ai/hl/stp/play/kickoff_play_test.py | 2 +- .../simulated_tests/robot_enters_region.py | 34 +++++++++---------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index d53822a2f1..792accd308 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -127,7 +127,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): eventually_validation_sequence_set = [[]] eventually_validation_sequence_set[0].append( - BallEventuallyExitsRegion(regions=tbots.Circle(ball_initial_pos, 0.05)) + BallEventuallyExitsRegion(regions=[tbots.Circle(ball_initial_pos, 0.05)]) ) simulated_test_runner.run_test( diff --git a/src/software/simulated_tests/robot_enters_region.py b/src/software/simulated_tests/robot_enters_region.py index 422e05b087..5cbda8791f 100644 --- a/src/software/simulated_tests/robot_enters_region.py +++ b/src/software/simulated_tests/robot_enters_region.py @@ -55,8 +55,8 @@ class NumberOfRobotsEntersRegion(Validation): """Checks if a certain number of Robots enters a specific region.""" - def __init__(self, region, req_robot_cnt): - self.region = region + def __init__(self, regions, req_robot_cnt): + self.regions = regions self.req_robot_cnt = req_robot_cnt # map to keep track of robot positions self.robot_in_zone = {} @@ -67,36 +67,34 @@ def get_validation_status(self, world) -> ValidationStatus: :param world: The world msg to validate :returns: FAILING until req_robot_cnt robots enter the region PASSING when req_robot_cnt robots enters - """ - # Update the map with latest robot status - for robot in world.friendly_team.team_robots: - self.robot_in_zone[robot.id] = tbots.contains( - self.region, tbots.createPoint(robot.current_state.global_position) - ) - # Check if there are at least req_robot_cnt number of robots in zone - curr_cnt = 0 - for robot_id in self.robot_in_zone: - if self.robot_in_zone[robot_id]: - curr_cnt += 1 + # """ + # Identify distinct robots within specified regions by ID + robots_in_regions = set() + for region in self.regions: + for robot in world.friendly_team.team_robots: + if(tbots.contains( + region, tbots.createPoint(robot.current_state.global_position) + )): + robots_in_regions.add(robot.id) # Validate on curr_cnt - if curr_cnt == self.req_robot_cnt: + if len(robots_in_regions) >= self.req_robot_cnt: return ValidationStatus.PASSING - else: - return ValidationStatus.FAILING + + return ValidationStatus.FAILING def get_validation_geometry(self, world) -> ValidationGeometry: """ (override) shows region to enter """ - return create_validation_geometry([self.region]) + return create_validation_geometry(self.regions) def __repr__(self): return ( "Check for " + str(self.req_robot_cnt) + " robots in region " - + ",".join(repr(self.region)) + + ",".join(repr(self.regions)) ) From 6e4ab7d449ef5bcb33bc652df2b554e9f839c36c Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 20 Jan 2024 15:05:41 -0800 Subject: [PATCH 39/83] Fixed geometry concatenation in get_validation_geometry in or_validation.py --- src/software/simulated_tests/or_validation.py | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py index 58677703f4..a4e46c7af2 100644 --- a/src/software/simulated_tests/or_validation.py +++ b/src/software/simulated_tests/or_validation.py @@ -9,27 +9,31 @@ ) -class OrValidation(): - def __init__ (self, validation): +class OrValidation(Validation): + def __init__(self, validation): """An or extension to the validation function""" self.validation = validation def get_validation_status(self, world): - for validation in self.validation: # - if validation.get_validation_status(world) == ValidationStatus.PASSING: # should I be using ValidationStatus.PASSING or just == FAILING + for validation in self.validation: + if validation.get_validation_status(world) == ValidationStatus.PASSING: return ValidationStatus.PASSING - return ValidationStatus.PASSING + return ValidationStatus.FAILING def get_validation_geometry(self, world): validation_geometry = ValidationGeometry() for validation in self.validation: - validation.get_validation_geometry(world) # why is this needed - validation_geometry.polygons += validation.polygons - validation_geometry.circles += validation.circles - validation_geometry.vectors += validation.vectors - validation_geometry.segments += validation.segments + individual_geometry = validation.get_validation_geometry(world) + for polygon in individual_geometry.polygons: + validation_geometry.polygons.append(polygon) + for circles in individual_geometry.circles: + validation_geometry.circles.append(circles) + for vectors in individual_geometry.vectors: + validation_geometry.vectors.append(vectors) + for segments in individual_geometry.segments: + validation_geometry.segments.append(segments) return validation_geometry @@ -41,5 +45,4 @@ def get_validation_type(self, world): validation_type = validation.get_validation_type if validation_type != validation_type_initial: raise TypeError("type of validation instances is not consistent") - # do I need to write a return statement or will the error account for this return validation_type_initial \ No newline at end of file From c7a7d2d1f315fb6780d7cbdd66a2d8f00e3c2ada Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 20 Jan 2024 16:28:13 -0800 Subject: [PATCH 40/83] Changed order of gamecontroller commands so NORMAL_START happens after KICKOFF. Made eventually validation only for friendly team. --- .../ai/hl/stp/play/kickoff_play_test.py | 20 +++++++++++++++---- .../simulated_tests/robot_enters_region.py | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 792accd308..334f74a987 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -17,6 +17,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): # starting point must be Point ball_initial_pos = tbots.Point(0, 0) + # Setup Bots blue_bots = [ tbots.Point(-3, 2.5), @@ -43,9 +44,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): simulated_test_runner.gamecontroller.send_ci_input( gc_command=Command.Type.STOP, team=Team.UNKNOWN ) - simulated_test_runner.gamecontroller.send_ci_input( - gc_command=Command.Type.NORMAL_START, team=Team.BLUE - ) + if is_friendly_test: simulated_test_runner.gamecontroller.send_ci_input( gc_command=Command.Type.KICKOFF, team=Team.BLUE @@ -59,6 +58,10 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): blue_play.name = PlayName.KickoffEnemyPlay yellow_play.name = PlayName.KickoffFriendlyPlay + simulated_test_runner.gamecontroller.send_ci_input( + 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) @@ -83,6 +86,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): # TODO- #2809 Validation always_validation_sequence_set = [[]] + if is_friendly_test: always_validation_sequence_set[0].append( NumberOfRobotsAlwaysStaysInRegion( @@ -92,6 +96,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): ) ) + always_validation_sequence_set[0].append( OrValidation( [ @@ -105,6 +110,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): )] ) ) + else: always_validation_sequence_set[0].append( NumberOfRobotsAlwaysStaysInRegion( @@ -114,6 +120,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): ) ) + always_validation_sequence_set[0].append( NumberOfRobotsAlwaysStaysInRegion( regions=[tbots.Field.createSSLDivisionBField().centerCircle()], @@ -124,12 +131,15 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): # Eventually Validation # TODO- #2809 Validation # make only for friendly - eventually_validation_sequence_set = [[]] + if(is_friendly_test): + eventually_validation_sequence_set = [[]] + eventually_validation_sequence_set[0].append( BallEventuallyExitsRegion(regions=[tbots.Circle(ball_initial_pos, 0.05)]) ) + simulated_test_runner.run_test( inv_eventually_validation_sequence_set=eventually_validation_sequence_set, inv_always_validation_sequence_set=always_validation_sequence_set, @@ -139,3 +149,5 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): if __name__ == "__main__": # Run the test, -s disables all capturing at -vv increases verbosity sys.exit(pytest.main([__file__, "-svv"])) + + diff --git a/src/software/simulated_tests/robot_enters_region.py b/src/software/simulated_tests/robot_enters_region.py index 5cbda8791f..177016c12e 100644 --- a/src/software/simulated_tests/robot_enters_region.py +++ b/src/software/simulated_tests/robot_enters_region.py @@ -77,7 +77,7 @@ def get_validation_status(self, world) -> ValidationStatus: )): robots_in_regions.add(robot.id) - # Validate on curr_cnt + # Validate on robots_in_regions if len(robots_in_regions) >= self.req_robot_cnt: return ValidationStatus.PASSING From 6a149fe29d937644be238a0420513b25e140ee03 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 20 Jan 2024 19:40:10 -0800 Subject: [PATCH 41/83] Disabled case of kickoff_play_test.py where is_friendly_test is False. Created TODO for issue #3319. Adjusted comments and ran formatting script. --- .../ai/hl/stp/play/kickoff_play_test.py | 68 +++++++++---------- src/software/simulated_tests/or_validation.py | 3 +- .../simulated_tests/robot_enters_region.py | 17 +++-- 3 files changed, 41 insertions(+), 47 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 334f74a987..10daad7d77 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -12,12 +12,12 @@ from proto.ssl_gc_common_pb2 import Team from software.simulated_tests.or_validation import OrValidation -@pytest.mark.parametrize("is_friendly_test", [True, False]) +# TODO 3119 Fix KickoffEnemyPlay +@pytest.mark.parametrize("is_friendly_test", [True, """False"""]) def test_kickoff_play(simulated_test_runner, is_friendly_test): # starting point must be Point ball_initial_pos = tbots.Point(0, 0) - # Setup Bots blue_bots = [ tbots.Point(-3, 2.5), @@ -77,50 +77,50 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): ), ) - - - # Always Validation - # add always validation: ball is always within bounds - # req_robot_cnt returns pass if it is not equal to 2 - - # need to create new validation sequence that works on "at least" logic - # TODO- #2809 Validation + # Always Validation: Check that robots are within centreCircle + friendlyHalf always_validation_sequence_set = [[]] - if is_friendly_test: + # Checks that all robots are in friendly half + center circle always_validation_sequence_set[0].append( NumberOfRobotsAlwaysStaysInRegion( - regions=[tbots.Field.createSSLDivisionBField().friendlyHalf(), - tbots.Field.createSSLDivisionBField().centerCircle()], + regions=[ + tbots.Field.createSSLDivisionBField().friendlyHalf(), + tbots.Field.createSSLDivisionBField().centerCircle(), + ], req_robot_cnt=6, ) ) - + # Checks that either 0 or 1 robots are in centerCircle always_validation_sequence_set[0].append( OrValidation( [ - NumberOfRobotsAlwaysStaysInRegion( - regions=[tbots.Field.createSSLDivisionBField().centerCircle()], - req_robot_cnt=0, - ), - NumberOfRobotsAlwaysStaysInRegion( - regions=[tbots.Field.createSSLDivisionBField().centerCircle()], - req_robot_cnt=1, - )] + NumberOfRobotsAlwaysStaysInRegion( + regions=[tbots.Field.createSSLDivisionBField().centerCircle()], + req_robot_cnt=0, + ), + NumberOfRobotsAlwaysStaysInRegion( + regions=[tbots.Field.createSSLDivisionBField().centerCircle()], + req_robot_cnt=1, + ), + ] ) ) else: + # Checks that all robots are in friendly half + center circle always_validation_sequence_set[0].append( NumberOfRobotsAlwaysStaysInRegion( - regions=[tbots.Field.createSSLDivisionBField().friendlyHalf(), - tbots.Field.createSSLDivisionBField().centerCircle()], + regions=[ + tbots.Field.createSSLDivisionBField().friendlyHalf(), + tbots.Field.createSSLDivisionBField().centerCircle(), + ], req_robot_cnt=6, ) ) - + # Checks that 0 robots are in centerCircle always_validation_sequence_set[0].append( NumberOfRobotsAlwaysStaysInRegion( regions=[tbots.Field.createSSLDivisionBField().centerCircle()], @@ -128,17 +128,14 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): ) ) - # Eventually Validation - # TODO- #2809 Validation - # make only for friendly - if(is_friendly_test): - eventually_validation_sequence_set = [[]] - - - eventually_validation_sequence_set[0].append( - BallEventuallyExitsRegion(regions=[tbots.Circle(ball_initial_pos, 0.05)]) - ) + 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.Circle(ball_initial_pos, 0.05)]) + ) simulated_test_runner.run_test( inv_eventually_validation_sequence_set=eventually_validation_sequence_set, @@ -146,8 +143,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): test_timeout_s=10, ) + if __name__ == "__main__": # Run the test, -s disables all capturing at -vv increases verbosity sys.exit(pytest.main([__file__, "-svv"])) - - diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py index a4e46c7af2..994e839dfe 100644 --- a/src/software/simulated_tests/or_validation.py +++ b/src/software/simulated_tests/or_validation.py @@ -37,7 +37,6 @@ def get_validation_geometry(self, world): return validation_geometry - def get_validation_type(self, world): validation_type_initial = self.validation[0].get_validation_type @@ -45,4 +44,4 @@ def get_validation_type(self, world): 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 \ No newline at end of file + return validation_type_initial diff --git a/src/software/simulated_tests/robot_enters_region.py b/src/software/simulated_tests/robot_enters_region.py index 177016c12e..f40f53d726 100644 --- a/src/software/simulated_tests/robot_enters_region.py +++ b/src/software/simulated_tests/robot_enters_region.py @@ -53,7 +53,7 @@ def __repr__(self): class NumberOfRobotsEntersRegion(Validation): - """Checks if a certain number of Robots enters a specific region.""" + """Checks if a certain number of Robots enters a specific set of regions.""" def __init__(self, regions, req_robot_cnt): self.regions = regions @@ -62,22 +62,21 @@ def __init__(self, regions, req_robot_cnt): self.robot_in_zone = {} def get_validation_status(self, world) -> ValidationStatus: - """Checks if a specific number of robots enter the provided region + """Checks if a specific number of robots enter the provided set of regions :param world: The world msg to validate - :returns: FAILING until req_robot_cnt robots enter the region - PASSING when req_robot_cnt robots enters + :returns: FAILING until req_robot_cnt robots enter the set of regions + PASSING when req_robot_cnt robots enter the set of regions # """ - # Identify distinct robots within specified regions by ID robots_in_regions = set() for region in self.regions: for robot in world.friendly_team.team_robots: - if(tbots.contains( - region, tbots.createPoint(robot.current_state.global_position) - )): + if tbots.contains( + region, tbots.createPoint(robot.current_state.global_position) + ): robots_in_regions.add(robot.id) - # Validate on robots_in_regions + # Validate on length of set robots_in_regions if len(robots_in_regions) >= self.req_robot_cnt: return ValidationStatus.PASSING From 1de63b0482bcee82ec8dd2349d7fbf6062c451d9 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 27 Jan 2024 14:35:19 -0800 Subject: [PATCH 42/83] Typo: changed BLU to BLUE. --- src/software/ai/hl/stp/play/kickoff_play_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 2541360d0f..5a6bf50c67 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -59,7 +59,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): yellow_play.name = PlayName.KickoffFriendlyPlay simulated_test_runner.gamecontroller.send_gc_command( - gc_command=Command.Type.NORMAL_START, team=Team.BLU + gc_command=Command.Type.NORMAL_START, team=Team.BLUE ) # Force play override here From 43906bc62c6bf875ceae7af358f3c1c712c50276 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 30 Mar 2024 13:24:42 -0700 Subject: [PATCH 43/83] PR changes: fixed some naming, deleted duplicate file. --- .../ai/hl/stp/play/kickoff_play_test.py | 3 +- src/software/simulated_tests/BUILD | 2 +- ...ed.py => friendly_team_has_scored_goal.py} | 6 +- .../multiple_robots_enter_region.py | 109 ------------------ src/software/simulated_tests/or_validation.py | 12 +- 5 files changed, 11 insertions(+), 121 deletions(-) rename src/software/simulated_tests/{friendly_goal_scored.py => friendly_team_has_scored_goal.py} (91%) delete mode 100644 src/software/simulated_tests/multiple_robots_enter_region.py diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 5a6bf50c67..74ebe4280b 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -2,7 +2,7 @@ import pytest -import software.python_bindings as tbots +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 * @@ -15,7 +15,6 @@ # TODO 3119 Fix KickoffEnemyPlay @pytest.mark.parametrize("is_friendly_test", [True, """False"""]) def test_kickoff_play(simulated_test_runner, is_friendly_test): - # starting point must be Point ball_initial_pos = tbots.Point(0, 0) # Setup Bots diff --git a/src/software/simulated_tests/BUILD b/src/software/simulated_tests/BUILD index 55e6570be6..dd4efecf66 100644 --- a/src/software/simulated_tests/BUILD +++ b/src/software/simulated_tests/BUILD @@ -111,7 +111,7 @@ py_library( "ball_speed_threshold.py", "ball_stops_in_region.py", "excessive_dribbling.py", - "friendly_goal_scored.py", + "friendly_team_has_scored_goal.py", "friendly_has_ball_possession.py", "friendly_team_scored.py", "or_validation.py", diff --git a/src/software/simulated_tests/friendly_goal_scored.py b/src/software/simulated_tests/friendly_team_has_scored_goal.py similarity index 91% rename from src/software/simulated_tests/friendly_goal_scored.py rename to src/software/simulated_tests/friendly_team_has_scored_goal.py index 0fcd25472c..eed746da0b 100644 --- a/src/software/simulated_tests/friendly_goal_scored.py +++ b/src/software/simulated_tests/friendly_team_has_scored_goal.py @@ -1,4 +1,4 @@ -import software.python_bindings as tbots +import software.python_bindings as tbots_cpp from proto.import_all_protos import * from software.simulated_tests.validation import ( @@ -8,7 +8,7 @@ ) -class FriendlyGoalScored(Validation): +class FriendlyTeamHasScoredGoal(Validation): """Checks if a ball enters the enemy goal.""" @@ -48,4 +48,4 @@ def __repr__(self): _FriendlyTeamGoalEventuallyRemoved, # These two don't make much sense _FriendlyTeamAlwaysScored, # These two don't make much sense FriendlyTeamNeverScored, -) = create_validation_types(FriendlyGoalScored) +) = create_validation_types(FriendlyTeamHasScoredGoal) diff --git a/src/software/simulated_tests/multiple_robots_enter_region.py b/src/software/simulated_tests/multiple_robots_enter_region.py deleted file mode 100644 index 10e54e5130..0000000000 --- a/src/software/simulated_tests/multiple_robots_enter_region.py +++ /dev/null @@ -1,109 +0,0 @@ -import software.python_bindings as tbots -from proto.import_all_protos import * - -from software.simulated_tests.validation import ( - Validation, - create_validation_geometry, - create_validation_types, -) - - -class RobotEntersRegion(Validation): - - """Checks if a Robot enters any of the provided regions.""" - - def __init__(self, regions=None, count=1): - self.regions = regions if regions else [] - self.count = count - - def get_validation_status(self, world) -> ValidationStatus: - """Checks if _any_ robot enters the provided regions - - :param world: The world msg to validate - :returns: FAILING until a robot enters any of the regions - PASSING when a robot enters - """ - for region in self.regions: - for robot in world.friendly_team.team_robots: - if tbots.contains( - region, tbots.createPoint(robot.current_state.global_position) - ): - return ValidationStatus.PASSING - - return ValidationStatus.FAILING - - def get_validation_geometry(self, world) -> ValidationGeometry: - """ - (override) shows regions to enter - """ - return create_validation_geometry(self.regions) - - def __repr__(self): - return "Check for robot in regions " + ",".join( - repr(region) for region in self.regions - ) - - -( - RobotEventuallyEntersRegion, - RobotEventuallyExitsRegion, - RobotAlwaysStaysInRegion, - RobotNeverEntersRegion, -) = create_validation_types(RobotEntersRegion) - - -class NumberOfRobotsEntersRegion(Validation): - - """Checks if a certain number of Robots enters a specific region.""" - - def __init__(self, region, req_robot_cnt): - self.region = region - self.req_robot_cnt = req_robot_cnt - # map to keep track of robot positions - self.robot_in_zone = {} - - def get_validation_status(self, world) -> ValidationStatus: - """Checks if a specific number of robots enter the provided region - - :param world: The world msg to validate - :returns: FAILING until req_robot_cnt robots enter the region - PASSING when req_robot_cnt robots enters - """ - # Update the map with latest robot status - for robot in world.friendly_team.team_robots: - self.robot_in_zone[robot.id] = tbots.contains( - self.region, tbots.createPoint(robot.current_state.global_position) - ) - # Check if there are at least req_robot_cnt number of robots in zone - curr_cnt = 0 - for robot_id in self.robot_in_zone: - if self.robot_in_zone[robot_id]: - curr_cnt += 1 - - # Validate on curr_cnt - if curr_cnt == self.req_robot_cnt: - return ValidationStatus.PASSING - else: - return ValidationStatus.FAILING - - def get_validation_geometry(self, world) -> ValidationGeometry: - """ - (override) shows region to enter - """ - return create_validation_geometry([self.region]) - - def __repr__(self): - return ( - "Check for " - + str(self.req_robot_cnt) - + " robots in region " - + ",".join(repr(self.region)) - ) - - -( - NumberOfRobotsEventuallyEntersRegion, - NumberOfRobotsEventuallyExitsRegion, - NumberOfRobotsAlwaysStaysInRegion, - NumberOfRobotsNeverEntersRegion, -) = create_validation_types(NumberOfRobotsEntersRegion) diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py index 994e839dfe..f387dab47b 100644 --- a/src/software/simulated_tests/or_validation.py +++ b/src/software/simulated_tests/or_validation.py @@ -10,12 +10,12 @@ class OrValidation(Validation): - def __init__(self, validation): + def __init__(self, validations): """An or extension to the validation function""" - self.validation = validation + self.validations = validations def get_validation_status(self, world): - for validation in self.validation: + for validation in self.validations: if validation.get_validation_status(world) == ValidationStatus.PASSING: return ValidationStatus.PASSING return ValidationStatus.FAILING @@ -24,7 +24,7 @@ def get_validation_geometry(self, world): validation_geometry = ValidationGeometry() - for validation in self.validation: + for validation in self.validations: individual_geometry = validation.get_validation_geometry(world) for polygon in individual_geometry.polygons: validation_geometry.polygons.append(polygon) @@ -38,9 +38,9 @@ def get_validation_geometry(self, world): return validation_geometry def get_validation_type(self, world): - validation_type_initial = self.validation[0].get_validation_type + validation_type_initial = self.validations[0].get_validation_type - for validation in self.validation: + 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") From af77463811961590fb5780f3182b33a8cafcd633 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 30 Mar 2024 13:35:23 -0700 Subject: [PATCH 44/83] Fixed GPIO naming. Gpio -> GPIO in comments. --- src/software/jetson_nano/display/robot_ui.py | 2 +- src/software/jetson_nano/gpio.cpp | 8 ++++---- src/software/jetson_nano/gpio.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/software/jetson_nano/display/robot_ui.py b/src/software/jetson_nano/display/robot_ui.py index f30af62e16..88c2f31be8 100644 --- a/src/software/jetson_nano/display/robot_ui.py +++ b/src/software/jetson_nano/display/robot_ui.py @@ -133,7 +133,7 @@ def poll_redis(self, timeout=0.1): time.sleep(timeout) def stop(self): - """ Cleanup the Gpio pins """ + """ Cleanup the GPIO pins """ self.shutdown = True self.rotary_encoder.stop() diff --git a/src/software/jetson_nano/gpio.cpp b/src/software/jetson_nano/gpio.cpp index 1bf02b57a5..1a896f0ff7 100644 --- a/src/software/jetson_nano/gpio.cpp +++ b/src/software/jetson_nano/gpio.cpp @@ -12,7 +12,7 @@ Gpio::Gpio(std::string gpio_number, GpioDirection direction, GpioState initial_state) { - // Setup the provided Gpio pin + // Setup the provided GPIO pin gpio_number_ = gpio_number; auto export_gpio_fs = std::ofstream("/sys/class/gpio/export"); @@ -39,14 +39,14 @@ Gpio::Gpio(std::string gpio_number, GpioDirection direction, GpioState initial_s set_direction_fs.close(); setValue(initial_state); - LOG(DEBUG) << "Gpio " << gpio_number_ << " online"; + LOG(DEBUG) << "GPIO " << gpio_number_ << " online"; } void Gpio::setValue(GpioState state) { std::ofstream gpio_fs("/sys/class/gpio/gpio" + gpio_number_ + "/value"); - CHECK(gpio_fs.is_open()) << "Could not set Gpio pin " << gpio_number_; + CHECK(gpio_fs.is_open()) << "Could not set GPIO pin " << gpio_number_; switch (state) { @@ -73,7 +73,7 @@ GpioState Gpio::getValue() std::ifstream gpio_fs("/sys/class/gpio/gpio" + gpio_number_ + "/value"); std::string level; - CHECK(gpio_fs.is_open()) << "Could not read Gpio pin"; + CHECK(gpio_fs.is_open()) << "Could not read GPIO pin"; std::getline(gpio_fs, level); if (level.compare("0") == 0) diff --git a/src/software/jetson_nano/gpio.h b/src/software/jetson_nano/gpio.h index 35bf2e50f6..8049d7ecae 100644 --- a/src/software/jetson_nano/gpio.h +++ b/src/software/jetson_nano/gpio.h @@ -15,7 +15,7 @@ class Gpio { public: /* - * Gpio Sysfs Wrapper + * GPIO Sysfs Wrapper * * See https://www.kernel.org/doc/Documentation/gpio/sysfs.txt * From bc891f76bcddbf361fd917fc06a079366fc89e21 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 30 Mar 2024 13:38:24 -0700 Subject: [PATCH 45/83] Deleted robot_halt.py and associated build string. --- src/software/simulated_tests/BUILD | 1 - src/software/simulated_tests/robot_halt.py | 46 ---------------------- 2 files changed, 47 deletions(-) delete mode 100644 src/software/simulated_tests/robot_halt.py diff --git a/src/software/simulated_tests/BUILD b/src/software/simulated_tests/BUILD index dd4efecf66..993bb8fb13 100644 --- a/src/software/simulated_tests/BUILD +++ b/src/software/simulated_tests/BUILD @@ -117,7 +117,6 @@ py_library( "or_validation.py", "robot_enters_region.py", "robot_enters_region_and_stops.py", - "robot_halt.py", "robot_speed_threshold.py", "validation.py", ], diff --git a/src/software/simulated_tests/robot_halt.py b/src/software/simulated_tests/robot_halt.py deleted file mode 100644 index 528edd11bc..0000000000 --- a/src/software/simulated_tests/robot_halt.py +++ /dev/null @@ -1,46 +0,0 @@ -import software.python_bindings as tbots -from proto.import_all_protos import * - -from software.simulated_tests.validation import ( - Validation, - create_validation_geometry, - create_validation_types, -) - - -class RobotHalt(Validation): - - """Checks if the friendly robots' are halted.""" - - def __init__(self): - """ - :param speed_threshold: The speed threshold - """ - - def get_validation_status(self, world) -> ValidationStatus: - """Checks if the friendly robots' are stopped - - :param world: The world msg to validate - :returns: FAILING if the friendly robots' speed is above 1e-3 - PASSING if the friendly robots' speed is at or below 1e-3 - """ - for robot in world.friendly_team.team_robots: - if tbots.createVector(robot.current_state.global_velocity).length() > 1e-3: - return ValidationStatus.FAILING - return ValidationStatus.PASSING - - def get_validation_geometry(self, world) -> ValidationGeometry: - """override""" - # TODO (#2556): visualize - return create_validation_geometry([]) - - def __repr__(self): - return "Check that the friendly robots' halted " - - -( - RobotEventuallyHalt, - RobotEventuallyMoves, - RobotAlwaysHalt, - RobotAlwaysMoves, -) = create_validation_types(RobotHalt) From 87d2827270dd2aa5c1c3a8092af12d12a330f500 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 30 Mar 2024 13:57:42 -0700 Subject: [PATCH 46/83] Took code segment that checks all robots are in friendly half + center circle outside of both the if and else blocks (eliminated redundancy). Also changed tbots -> tbots_cpp. --- .../ai/hl/stp/play/kickoff_play_test.py | 65 ++++++++----------- 1 file changed, 27 insertions(+), 38 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 74ebe4280b..eff0d1b14e 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -19,21 +19,21 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): # Setup Bots blue_bots = [ - tbots.Point(-3, 2.5), - tbots.Point(-3, 1.5), - tbots.Point(-3, 0.5), - tbots.Point(-3, -0.5), - tbots.Point(-3, -1.5), - tbots.Point(-3, -2.5), + 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.Point(1, 0), - tbots.Point(1, 2.5), - tbots.Point(1, -2.5), - tbots.Field.createSSLDivisionBField().enemyGoalCenter(), - tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXNegYCorner(), - tbots.Field.createSSLDivisionBField().enemyDefenseArea().negXPosYCorner(), + 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() @@ -72,35 +72,35 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): yellow_robot_locations=yellow_bots, blue_robot_locations=blue_bots, ball_location=ball_initial_pos, - ball_velocity=tbots.Vector(0, 0), + ball_velocity=tbots_cpp.Vector(0, 0), ), ) # Always Validation: Check that robots are within centreCircle + friendlyHalf always_validation_sequence_set = [[]] - if is_friendly_test: - # Checks that all robots are in friendly half + center circle - always_validation_sequence_set[0].append( - NumberOfRobotsAlwaysStaysInRegion( - regions=[ - tbots.Field.createSSLDivisionBField().friendlyHalf(), - tbots.Field.createSSLDivisionBField().centerCircle(), - ], - req_robot_cnt=6, - ) + # Checks that all robots are in friendly half + center circle + always_validation_sequence_set[0].append( + NumberOfRobotsAlwaysStaysInRegion( + regions=[ + tbots_cpp.Field.createSSLDivisionBField().friendlyHalf(), + tbots_cpp.Field.createSSLDivisionBField().centerCircle(), + ], + req_robot_cnt=6, ) + ) + if is_friendly_test: # Checks that either 0 or 1 robots are in centerCircle always_validation_sequence_set[0].append( OrValidation( [ NumberOfRobotsAlwaysStaysInRegion( - regions=[tbots.Field.createSSLDivisionBField().centerCircle()], + regions=[tbots_cpp.Field.createSSLDivisionBField().centerCircle()], req_robot_cnt=0, ), NumberOfRobotsAlwaysStaysInRegion( - regions=[tbots.Field.createSSLDivisionBField().centerCircle()], + regions=[tbots_cpp.Field.createSSLDivisionBField().centerCircle()], req_robot_cnt=1, ), ] @@ -108,21 +108,10 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): ) else: - # Checks that all robots are in friendly half + center circle - always_validation_sequence_set[0].append( - NumberOfRobotsAlwaysStaysInRegion( - regions=[ - tbots.Field.createSSLDivisionBField().friendlyHalf(), - tbots.Field.createSSLDivisionBField().centerCircle(), - ], - req_robot_cnt=6, - ) - ) - # Checks that 0 robots are in centerCircle always_validation_sequence_set[0].append( NumberOfRobotsAlwaysStaysInRegion( - regions=[tbots.Field.createSSLDivisionBField().centerCircle()], + regions=[tbots_cpp.Field.createSSLDivisionBField().centerCircle()], req_robot_cnt=0, ) ) @@ -133,7 +122,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): 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.Circle(ball_initial_pos, 0.05)]) + BallEventuallyExitsRegion(regions=[tbots_cpp.Circle(ball_initial_pos, 0.05)]) ) simulated_test_runner.run_test( From deb4d211b2e867d3b1782daecfdcac68764ba924 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 30 Mar 2024 14:05:27 -0700 Subject: [PATCH 47/83] More naming changes. Tbots -> tbots_cpp. --- src/software/ai/hl/stp/play/kickoff_play_test.py | 2 +- .../simulated_tests/friendly_team_has_scored_goal.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index eff0d1b14e..81e0b586c3 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -15,7 +15,7 @@ # TODO 3119 Fix KickoffEnemyPlay @pytest.mark.parametrize("is_friendly_test", [True, """False"""]) def test_kickoff_play(simulated_test_runner, is_friendly_test): - ball_initial_pos = tbots.Point(0, 0) + ball_initial_pos = tbots_cpp.Point(0, 0) # Setup Bots blue_bots = [ diff --git a/src/software/simulated_tests/friendly_team_has_scored_goal.py b/src/software/simulated_tests/friendly_team_has_scored_goal.py index eed746da0b..d70d86c8f9 100644 --- a/src/software/simulated_tests/friendly_team_has_scored_goal.py +++ b/src/software/simulated_tests/friendly_team_has_scored_goal.py @@ -13,7 +13,7 @@ class FriendlyTeamHasScoredGoal(Validation): """Checks if a ball enters the enemy goal.""" def __init__(self): - self.region = tbots.Field.createSSLDivisionBField().enemyGoal() + self.region = tbots_cpp.Field.createSSLDivisionBField().enemyGoal() def get_validation_status(self, world) -> ValidationStatus: """Checks if the ball enters the provided regions @@ -23,8 +23,8 @@ def get_validation_status(self, world) -> ValidationStatus: PASSING when a ball enters """ - if tbots.contains( - self.region, tbots.createPoint(world.ball.current_state.global_position) + if tbots_cpp.contains( + self.region, tbots_cpp.createPoint(world.ball.current_state.global_position) ): return ValidationStatus.PASSING From f3930bffd45479b9e6cc639dbf0fc5d398fdcf43 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 30 Mar 2024 14:45:37 -0700 Subject: [PATCH 48/83] Made RobotEntersRegion a child class of NumberOfRobotEntersRegion --- .../simulated_tests/robot_enters_region.py | 58 ++++--------------- 1 file changed, 12 insertions(+), 46 deletions(-) diff --git a/src/software/simulated_tests/robot_enters_region.py b/src/software/simulated_tests/robot_enters_region.py index ed81cf4eed..ac1d5cf4cd 100644 --- a/src/software/simulated_tests/robot_enters_region.py +++ b/src/software/simulated_tests/robot_enters_region.py @@ -8,51 +8,6 @@ ) -class RobotEntersRegion(Validation): - - """Checks if a Robot enters any of the provided regions.""" - - def __init__(self, regions=None): - self.regions = regions if regions else [] - self.passing_robot = None - - def get_validation_status(self, world) -> ValidationStatus: - """Checks if _any_ robot enters the provided regions - - :param world: The world msg to validate - :returns: FAILING until a robot enters any of the regions - PASSING when a robot enters - """ - for region in self.regions: - for robot in world.friendly_team.team_robots: - if tbots_cpp.contains( - region, tbots_cpp.createPoint(robot.current_state.global_position) - ): - self.passing_robot = robot - return ValidationStatus.PASSING - - self.passing_robot = None - return ValidationStatus.FAILING - - def get_validation_geometry(self, world) -> ValidationGeometry: - """ - (override) shows regions to enter - """ - return create_validation_geometry(self.regions) - - def __repr__(self): - return "Check for robot in regions " + ",".join( - repr(region) for region in self.regions - ) - - -( - RobotEventuallyEntersRegion, - RobotEventuallyExitsRegion, - RobotAlwaysStaysInRegion, - RobotNeverEntersRegion, -) = create_validation_types(RobotEntersRegion) - class NumberOfRobotsEntersRegion(Validation): @@ -99,10 +54,21 @@ def __repr__(self): + ",".join(repr(self.regions)) ) - ( NumberOfRobotsEventuallyEntersRegion, NumberOfRobotsEventuallyExitsRegion, NumberOfRobotsAlwaysStaysInRegion, NumberOfRobotsNeverEntersRegion, ) = create_validation_types(NumberOfRobotsEntersRegion) + + +class RobotEntersRegion(NumberOfRobotsEntersRegion): + def __init__(self, regions): + super(RobotEntersRegion, self).__init__(regions, 1) + +( + RobotEventuallyEntersRegion, + RobotEventuallyExitsRegion, + RobotAlwaysStaysInRegion, + RobotNeverEntersRegion, +) = create_validation_types(RobotEntersRegion) From 590719f826f618f0ad95b9720615cf652e5f67c5 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 30 Mar 2024 16:59:04 -0700 Subject: [PATCH 49/83] Renamed NumberOfRobotsEntersRegion to MinNumberOfRobotsEntersRegion. Delated friendly_team_has_scored_goal.py. --- src/software/simulated_tests/BUILD | 1 - .../friendly_team_has_scored_goal.py | 51 ------------------- .../simulated_tests/robot_enters_region.py | 6 +-- 3 files changed, 3 insertions(+), 55 deletions(-) delete mode 100644 src/software/simulated_tests/friendly_team_has_scored_goal.py diff --git a/src/software/simulated_tests/BUILD b/src/software/simulated_tests/BUILD index 993bb8fb13..dd0752b91e 100644 --- a/src/software/simulated_tests/BUILD +++ b/src/software/simulated_tests/BUILD @@ -111,7 +111,6 @@ py_library( "ball_speed_threshold.py", "ball_stops_in_region.py", "excessive_dribbling.py", - "friendly_team_has_scored_goal.py", "friendly_has_ball_possession.py", "friendly_team_scored.py", "or_validation.py", diff --git a/src/software/simulated_tests/friendly_team_has_scored_goal.py b/src/software/simulated_tests/friendly_team_has_scored_goal.py deleted file mode 100644 index d70d86c8f9..0000000000 --- a/src/software/simulated_tests/friendly_team_has_scored_goal.py +++ /dev/null @@ -1,51 +0,0 @@ -import software.python_bindings as tbots_cpp -from proto.import_all_protos import * - -from software.simulated_tests.validation import ( - Validation, - create_validation_geometry, - create_validation_types, -) - - -class FriendlyTeamHasScoredGoal(Validation): - - """Checks if a ball enters the enemy goal.""" - - def __init__(self): - self.region = tbots_cpp.Field.createSSLDivisionBField().enemyGoal() - - def get_validation_status(self, world) -> ValidationStatus: - """Checks if the ball enters the provided regions - - :param world: The world msg to validate - :returns: FAILING until a ball enters the enemy goal - PASSING when a ball enters - """ - - if tbots_cpp.contains( - self.region, tbots_cpp.createPoint(world.ball.current_state.global_position) - ): - return ValidationStatus.PASSING - - return ValidationStatus.FAILING - - def get_validation_geometry(self, world) -> ValidationGeometry: - """Returns the underlying geometry this validation is checking - - :param world: The world msg to create v alidation geometry from - :returns: ValidationGeometry containing geometry to visualize - - """ - return create_validation_geometry([self.region]) - - def __repr__(self): - return "Checking ball in " + ",".join(repr(self.region)) - - -( - FriendlyTeamEventuallyScored, - _FriendlyTeamGoalEventuallyRemoved, # These two don't make much sense - _FriendlyTeamAlwaysScored, # These two don't make much sense - FriendlyTeamNeverScored, -) = create_validation_types(FriendlyTeamHasScoredGoal) diff --git a/src/software/simulated_tests/robot_enters_region.py b/src/software/simulated_tests/robot_enters_region.py index ac1d5cf4cd..a3b18bfa9e 100644 --- a/src/software/simulated_tests/robot_enters_region.py +++ b/src/software/simulated_tests/robot_enters_region.py @@ -9,7 +9,7 @@ -class NumberOfRobotsEntersRegion(Validation): +class MinNumberOfRobotsEntersRegion(Validation): """Checks if a certain number of Robots enters a specific set of regions.""" @@ -59,10 +59,10 @@ def __repr__(self): NumberOfRobotsEventuallyExitsRegion, NumberOfRobotsAlwaysStaysInRegion, NumberOfRobotsNeverEntersRegion, -) = create_validation_types(NumberOfRobotsEntersRegion) +) = create_validation_types(MinNumberOfRobotsEntersRegion) -class RobotEntersRegion(NumberOfRobotsEntersRegion): +class RobotEntersRegion(MinNumberOfRobotsEntersRegion): def __init__(self, regions): super(RobotEntersRegion, self).__init__(regions, 1) From f7fa44ad9d3b75b4e3e121db18ff3ab46a9b4a35 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 30 Mar 2024 17:27:03 -0700 Subject: [PATCH 50/83] Ran formatting script --- src/software/ai/hl/stp/play/kickoff_play_test.py | 12 +++++++++--- src/software/simulated_tests/robot_enters_region.py | 3 ++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 81e0b586c3..980608d0d8 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -96,11 +96,15 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): OrValidation( [ NumberOfRobotsAlwaysStaysInRegion( - regions=[tbots_cpp.Field.createSSLDivisionBField().centerCircle()], + regions=[ + tbots_cpp.Field.createSSLDivisionBField().centerCircle() + ], req_robot_cnt=0, ), NumberOfRobotsAlwaysStaysInRegion( - regions=[tbots_cpp.Field.createSSLDivisionBField().centerCircle()], + regions=[ + tbots_cpp.Field.createSSLDivisionBField().centerCircle() + ], req_robot_cnt=1, ), ] @@ -122,7 +126,9 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): 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)]) + BallEventuallyExitsRegion( + regions=[tbots_cpp.Circle(ball_initial_pos, 0.05)] + ) ) simulated_test_runner.run_test( diff --git a/src/software/simulated_tests/robot_enters_region.py b/src/software/simulated_tests/robot_enters_region.py index a3b18bfa9e..29d2296171 100644 --- a/src/software/simulated_tests/robot_enters_region.py +++ b/src/software/simulated_tests/robot_enters_region.py @@ -8,7 +8,6 @@ ) - class MinNumberOfRobotsEntersRegion(Validation): """Checks if a certain number of Robots enters a specific set of regions.""" @@ -54,6 +53,7 @@ def __repr__(self): + ",".join(repr(self.regions)) ) + ( NumberOfRobotsEventuallyEntersRegion, NumberOfRobotsEventuallyExitsRegion, @@ -66,6 +66,7 @@ class RobotEntersRegion(MinNumberOfRobotsEntersRegion): def __init__(self, regions): super(RobotEntersRegion, self).__init__(regions, 1) + ( RobotEventuallyEntersRegion, RobotEventuallyExitsRegion, From 91c000ec850fbd3048fc155fb6139e81379b01e2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Sun, 31 Mar 2024 00:29:59 +0000 Subject: [PATCH 51/83] [pre-commit.ci lite] apply automatic fixes --- src/software/ai/hl/stp/play/kickoff_play_test.py | 12 +++++++++--- src/software/simulated_tests/robot_enters_region.py | 3 ++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 81e0b586c3..980608d0d8 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -96,11 +96,15 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): OrValidation( [ NumberOfRobotsAlwaysStaysInRegion( - regions=[tbots_cpp.Field.createSSLDivisionBField().centerCircle()], + regions=[ + tbots_cpp.Field.createSSLDivisionBField().centerCircle() + ], req_robot_cnt=0, ), NumberOfRobotsAlwaysStaysInRegion( - regions=[tbots_cpp.Field.createSSLDivisionBField().centerCircle()], + regions=[ + tbots_cpp.Field.createSSLDivisionBField().centerCircle() + ], req_robot_cnt=1, ), ] @@ -122,7 +126,9 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): 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)]) + BallEventuallyExitsRegion( + regions=[tbots_cpp.Circle(ball_initial_pos, 0.05)] + ) ) simulated_test_runner.run_test( diff --git a/src/software/simulated_tests/robot_enters_region.py b/src/software/simulated_tests/robot_enters_region.py index a3b18bfa9e..29d2296171 100644 --- a/src/software/simulated_tests/robot_enters_region.py +++ b/src/software/simulated_tests/robot_enters_region.py @@ -8,7 +8,6 @@ ) - class MinNumberOfRobotsEntersRegion(Validation): """Checks if a certain number of Robots enters a specific set of regions.""" @@ -54,6 +53,7 @@ def __repr__(self): + ",".join(repr(self.regions)) ) + ( NumberOfRobotsEventuallyEntersRegion, NumberOfRobotsEventuallyExitsRegion, @@ -66,6 +66,7 @@ class RobotEntersRegion(MinNumberOfRobotsEntersRegion): def __init__(self, regions): super(RobotEntersRegion, self).__init__(regions, 1) + ( RobotEventuallyEntersRegion, RobotEventuallyExitsRegion, From 0966c4d58de915f185f91c8bb359d38049c111d1 Mon Sep 17 00:00:00 2001 From: suchirss Date: Tue, 7 May 2024 23:49:53 -0700 Subject: [PATCH 52/83] Fixed GPIO casing issue. --- src/software/jetson_nano/setup_nano.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/software/jetson_nano/setup_nano.sh b/src/software/jetson_nano/setup_nano.sh index c7c206f5d4..87b9200d2b 100755 --- a/src/software/jetson_nano/setup_nano.sh +++ b/src/software/jetson_nano/setup_nano.sh @@ -34,7 +34,7 @@ pip_libaries=( adafruit-circuitpython-rgb-display==3.10.9 Adafruit-PlatformDetect==3.18.0 Adafruit-PureIO==1.1.9 - Jetson.Gpio==2.0.17 + Jetson.GPIO==2.0.17 Pillow==9.1.0 redis==4.1.4 platformio==6.0.2 From 1ff45af9b2b3724e995a36b5322467f652ff3722 Mon Sep 17 00:00:00 2001 From: suchirss Date: Tue, 7 May 2024 23:53:12 -0700 Subject: [PATCH 53/83] Removed unused imports. Ran formatting script. --- src/software/simulated_tests/or_validation.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py index f387dab47b..89b4abcbf8 100644 --- a/src/software/simulated_tests/or_validation.py +++ b/src/software/simulated_tests/or_validation.py @@ -1,7 +1,3 @@ -import pytest - -import software.python_bindings as tbots -from proto.validation_pb2 import * from software.simulated_tests.validation import ( Validation, create_validation_geometry, From 06080b37eba5200ed6849e6ff0f888e2cffb57e0 Mon Sep 17 00:00:00 2001 From: suchirss Date: Wed, 8 May 2024 00:04:49 -0700 Subject: [PATCH 54/83] Added back import in or_validation.py. --- src/software/simulated_tests/or_validation.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py index 89b4abcbf8..4ae7e129c2 100644 --- a/src/software/simulated_tests/or_validation.py +++ b/src/software/simulated_tests/or_validation.py @@ -1,3 +1,4 @@ +from proto.validation_pb2 import * from software.simulated_tests.validation import ( Validation, create_validation_geometry, From bfb8626772a5ca88ab5865df6e1e2001bda17a43 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 11 May 2024 22:38:56 -0700 Subject: [PATCH 55/83] Moved TypeError check to initialization function in or_validation.py. Added documentation to two functions in robot_enters_region.py. --- src/software/simulated_tests/or_validation.py | 16 ++++++++-------- .../simulated_tests/robot_enters_region.py | 13 +++++++++++++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py index 4ae7e129c2..836ca9a8ec 100644 --- a/src/software/simulated_tests/or_validation.py +++ b/src/software/simulated_tests/or_validation.py @@ -7,9 +7,15 @@ class OrValidation(Validation): - def __init__(self, validations): + def __init__(self, validations, validation_type_initial): """An or extension to the validation function""" self.validations = validations + self.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") def get_validation_status(self, world): for validation in self.validations: @@ -35,10 +41,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 self.validation_type_initial diff --git a/src/software/simulated_tests/robot_enters_region.py b/src/software/simulated_tests/robot_enters_region.py index 29d2296171..54a5466b8b 100644 --- a/src/software/simulated_tests/robot_enters_region.py +++ b/src/software/simulated_tests/robot_enters_region.py @@ -13,6 +13,12 @@ class MinNumberOfRobotsEntersRegion(Validation): """Checks if a certain number of Robots enters a specific set of regions.""" def __init__(self, regions, req_robot_cnt): + """ + Initializes the validation class with a set of regions and required count of robots + + :param regions: the regions that will be checked for robot count + :param req_robot_cnt: the minimum number of unique robots that must be in the given regions + """ self.regions = regions self.req_robot_cnt = req_robot_cnt # map to keep track of robot positions @@ -63,7 +69,14 @@ def __repr__(self): class RobotEntersRegion(MinNumberOfRobotsEntersRegion): + + """Checks if at least one robot is contained within the given regions""" + def __init__(self, regions): + """Initializes the validation class with a set of regions + + :param regions: the regions that will be checked to contain at least one robot + """ super(RobotEntersRegion, self).__init__(regions, 1) From a3a43444fe7b00a546d209cd8bdf703a2c7f07d3 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sun, 12 May 2024 01:45:26 -0700 Subject: [PATCH 56/83] Fixed or_validation.py such that kickoff_play_test.py passes when tested. Fixed by calling get_validation_status() correctly. --- src/software/simulated_tests/or_validation.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py index 836ca9a8ec..d76b6323e0 100644 --- a/src/software/simulated_tests/or_validation.py +++ b/src/software/simulated_tests/or_validation.py @@ -7,13 +7,14 @@ class OrValidation(Validation): - def __init__(self, validations, validation_type_initial): + def __init__(self, validations): """An or extension to the validation function""" self.validations = validations - self.validation_type_initial = self.validations[0].get_validation_type + + validation_type_initial = self.validations[0].get_validation_type() for validation in self.validations: - validation_type = validation.get_validation_type + validation_type = validation.get_validation_type() if validation_type != validation_type_initial: raise TypeError("type of validation instances is not consistent") @@ -41,4 +42,4 @@ def get_validation_geometry(self, world): return validation_geometry def get_validation_type(self, world): - return self.validation_type_initial + return ValidationType From 1cb1eeb85afd071965341192860bb2abb0b24277 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Sat, 11 Jan 2025 06:23:18 +0000 Subject: [PATCH 57/83] [pre-commit.ci lite] apply automatic fixes --- .../ai/hl/stp/play/kickoff_play_test.py | 1 + .../simulated_tests/ball_enters_region.py | 1 - src/software/simulated_tests/or_validation.py | 3 --- .../simulated_tests/robot_enters_region.py | 18 +++++++----------- 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 9d3f002e9d..0665f470a6 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -11,6 +11,7 @@ from proto.ssl_gc_common_pb2 import Team from software.simulated_tests.or_validation import OrValidation + # TODO 3119 Fix KickoffEnemyPlay @pytest.mark.parametrize("is_friendly_test", [True, """False"""]) def test_kickoff_play(simulated_test_runner, is_friendly_test): diff --git a/src/software/simulated_tests/ball_enters_region.py b/src/software/simulated_tests/ball_enters_region.py index 4c8d22a2e6..4792ad6bb7 100644 --- a/src/software/simulated_tests/ball_enters_region.py +++ b/src/software/simulated_tests/ball_enters_region.py @@ -9,7 +9,6 @@ class BallEntersRegion(Validation): - """Checks if a ball enters any of the provided regions.""" def __init__(self, regions=None): diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py index d76b6323e0..d72606d9b4 100644 --- a/src/software/simulated_tests/or_validation.py +++ b/src/software/simulated_tests/or_validation.py @@ -1,8 +1,6 @@ from proto.validation_pb2 import * from software.simulated_tests.validation import ( Validation, - create_validation_geometry, - create_validation_types, ) @@ -25,7 +23,6 @@ def get_validation_status(self, world): return ValidationStatus.FAILING def get_validation_geometry(self, world): - validation_geometry = ValidationGeometry() for validation in self.validations: diff --git a/src/software/simulated_tests/robot_enters_region.py b/src/software/simulated_tests/robot_enters_region.py index 54a5466b8b..54c5052edc 100644 --- a/src/software/simulated_tests/robot_enters_region.py +++ b/src/software/simulated_tests/robot_enters_region.py @@ -9,16 +9,14 @@ class MinNumberOfRobotsEntersRegion(Validation): - """Checks if a certain number of Robots enters a specific set of regions.""" def __init__(self, regions, req_robot_cnt): - """ - Initializes the validation class with a set of regions and required count of robots + """Initializes the validation class with a set of regions and required count of robots - :param regions: the regions that will be checked for robot count - :param req_robot_cnt: the minimum number of unique robots that must be in the given regions - """ + :param regions: the regions that will be checked for robot count + :param req_robot_cnt: the minimum number of unique robots that must be in the given regions + """ self.regions = regions self.req_robot_cnt = req_robot_cnt # map to keep track of robot positions @@ -30,7 +28,8 @@ def get_validation_status(self, world) -> ValidationStatus: :param world: The world msg to validate :returns: FAILING until req_robot_cnt robots enter the set of regions PASSING when req_robot_cnt robots enter the set of regions - # """ + # + """ robots_in_regions = set() for region in self.regions: for robot in world.friendly_team.team_robots: @@ -46,9 +45,7 @@ def get_validation_status(self, world) -> ValidationStatus: return ValidationStatus.FAILING def get_validation_geometry(self, world) -> ValidationGeometry: - """ - (override) shows region to enter - """ + """(override) shows region to enter""" return create_validation_geometry(self.regions) def __repr__(self): @@ -69,7 +66,6 @@ def __repr__(self): class RobotEntersRegion(MinNumberOfRobotsEntersRegion): - """Checks if at least one robot is contained within the given regions""" def __init__(self, regions): From 12d5d0e93d7929c6be3549db38ecbc5a0c12ac93 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 11 Jan 2025 12:01:48 -0800 Subject: [PATCH 58/83] Removed check that all validation class inputs must be of the same type. Ex: ALWAYS validation and EVENTUALLY validation can both be passed to or_validation. --- src/software/simulated_tests/or_validation.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py index d76b6323e0..94cfbe080e 100644 --- a/src/software/simulated_tests/or_validation.py +++ b/src/software/simulated_tests/or_validation.py @@ -11,13 +11,6 @@ def __init__(self, validations): """An or extension to the validation function""" self.validations = validations - 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") - def get_validation_status(self, world): for validation in self.validations: if validation.get_validation_status(world) == ValidationStatus.PASSING: From 0a18f61da0bf59ba7c0463256d46330c180a5883 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 11 Jan 2025 12:07:12 -0800 Subject: [PATCH 59/83] Removed check that all validation class inputs must be of the same type. Ex: ALWAYS validation and EVENTUALLY validation can both be passed to or_validation. --- src/software/simulated_tests/or_validation.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py index 94cfbe080e..11447194b4 100644 --- a/src/software/simulated_tests/or_validation.py +++ b/src/software/simulated_tests/or_validation.py @@ -1,8 +1,6 @@ from proto.validation_pb2 import * from software.simulated_tests.validation import ( Validation, - create_validation_geometry, - create_validation_types, ) @@ -18,7 +16,6 @@ def get_validation_status(self, world): return ValidationStatus.FAILING def get_validation_geometry(self, world): - validation_geometry = ValidationGeometry() for validation in self.validations: From f2d40241c764fa6d0e168430d588791da6f14f1a Mon Sep 17 00:00:00 2001 From: suchirss Date: Mon, 17 Feb 2025 12:23:56 -0800 Subject: [PATCH 60/83] Modified kickoff_play_test so the validation that checks that all robots are in friendlyHalf + centerCircle is now within the if is_friendly_test and else blocks. Added BallAlwaysMoveFromRest() validation to OrValidation() with NumberOfRobotsAlwaysStaysInRegion() so that once the ball moves, the test still passes if the robots enters regions that would have previously made the test fail. Added debugging statements to ball_moves_from_rest and or_validation. Pending removal. --- .../ai/hl/stp/play/kickoff_play_test.py | 73 +++++++++++++------ .../simulated_tests/ball_moves_from_rest.py | 1 + src/software/simulated_tests/or_validation.py | 2 + 3 files changed, 54 insertions(+), 22 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 0665f470a6..a1c619a1cd 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -6,14 +6,13 @@ 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 - -# TODO 3119 Fix KickoffEnemyPlay -@pytest.mark.parametrize("is_friendly_test", [True, """False"""]) +@pytest.mark.parametrize("is_friendly_test", [True, False]) def test_kickoff_play(simulated_test_runner, is_friendly_test): ball_initial_pos = tbots_cpp.Point(0, 0) @@ -76,25 +75,14 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): ), ) - # Always Validation: Check that robots are within centreCircle + friendlyHalf + # Always Validation always_validation_sequence_set = [[]] - - # Checks that all robots are in friendly half + center circle - always_validation_sequence_set[0].append( - NumberOfRobotsAlwaysStaysInRegion( - regions=[ - tbots_cpp.Field.createSSLDivisionBField().friendlyHalf(), - tbots_cpp.Field.createSSLDivisionBField().centerCircle(), - ], - req_robot_cnt=6, - ) - ) - if is_friendly_test: - # Checks that either 0 or 1 robots are in centerCircle + # 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), NumberOfRobotsAlwaysStaysInRegion( regions=[ tbots_cpp.Field.createSSLDivisionBField().centerCircle() @@ -106,20 +94,61 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): tbots_cpp.Field.createSSLDivisionBField().centerCircle() ], req_robot_cnt=1, - ), + ) + ] + ) + ) + + # 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 + # Checks that 0 robots are in centerCircle OR ball moves from center point always_validation_sequence_set[0].append( - NumberOfRobotsAlwaysStaysInRegion( - regions=[tbots_cpp.Field.createSSLDivisionBField().centerCircle()], - req_robot_cnt=0, + OrValidation( + [ + BallAlwaysMovesFromRest(position=tbots_cpp.Point(0, 0), threshold=0.01), + NumberOfRobotsAlwaysStaysInRegion( + regions=[ + tbots_cpp.Field.createSSLDivisionBField().centerCircle() + ], + req_robot_cnt=0, + ) + ] ) ) + # 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), + # NumberOfRobotsAlwaysStaysInRegion( + # regions=[ + # tbots_cpp.Field.createSSLDivisionBField().friendlyHalf(), + # tbots_cpp.Field.createSSLDivisionBField().friendlyGoal(), + # tbots_cpp.Field.createSSLDivisionBField().centerCircle() + # ], + # req_robot_cnt=6, + # ) + # ] + # ) + # ) + eventually_validation_sequence_set = [[]] # Eventually Validation diff --git a/src/software/simulated_tests/ball_moves_from_rest.py b/src/software/simulated_tests/ball_moves_from_rest.py index 5334159c2d..ca70cbb02d 100644 --- a/src/software/simulated_tests/ball_moves_from_rest.py +++ b/src/software/simulated_tests/ball_moves_from_rest.py @@ -37,6 +37,7 @@ def get_validation_status(self, world) -> ValidationStatus: ).length() > self.threshold: validation_status = ValidationStatus.PASSING + print(f"V-Status: {validation_status, (self.initial_ball_position - current_ball_position).length()}") return validation_status def get_validation_geometry(self, world) -> ValidationGeometry: diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py index 11447194b4..cd7401b400 100644 --- a/src/software/simulated_tests/or_validation.py +++ b/src/software/simulated_tests/or_validation.py @@ -12,7 +12,9 @@ def __init__(self, validations): def get_validation_status(self, world): for validation in self.validations: if validation.get_validation_status(world) == ValidationStatus.PASSING: + print(f"OR Validation PASSING {validation}") return ValidationStatus.PASSING + print(f"OR Validation Failing: {validation}") return ValidationStatus.FAILING def get_validation_geometry(self, world): From 80506159edd72dad954d6dfcd6e191d459908234 Mon Sep 17 00:00:00 2001 From: suchirss Date: Fri, 28 Feb 2025 16:44:36 -0800 Subject: [PATCH 61/83] Kickoff validation areas and friendly robot behaviour corrected. Remaining issues: - enemy robot performs kickoff during friendly kickoff - friendly robots enter enemy region when test is running with -t --- .../ai/hl/stp/play/kickoff_play_test.py | 29 +++++++++---------- .../simulated_tests/ball_moves_from_rest.py | 1 - src/software/simulated_tests/or_validation.py | 2 -- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index a1c619a1cd..1c9439c895 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -133,21 +133,20 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): ) # 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), - # NumberOfRobotsAlwaysStaysInRegion( - # regions=[ - # tbots_cpp.Field.createSSLDivisionBField().friendlyHalf(), - # tbots_cpp.Field.createSSLDivisionBField().friendlyGoal(), - # tbots_cpp.Field.createSSLDivisionBField().centerCircle() - # ], - # req_robot_cnt=6, - # ) - # ] - # ) - # ) + 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() + ], + req_robot_cnt=6, + ) + ] + ) + ) eventually_validation_sequence_set = [[]] diff --git a/src/software/simulated_tests/ball_moves_from_rest.py b/src/software/simulated_tests/ball_moves_from_rest.py index ca70cbb02d..5334159c2d 100644 --- a/src/software/simulated_tests/ball_moves_from_rest.py +++ b/src/software/simulated_tests/ball_moves_from_rest.py @@ -37,7 +37,6 @@ def get_validation_status(self, world) -> ValidationStatus: ).length() > self.threshold: validation_status = ValidationStatus.PASSING - print(f"V-Status: {validation_status, (self.initial_ball_position - current_ball_position).length()}") return validation_status def get_validation_geometry(self, world) -> ValidationGeometry: diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py index cd7401b400..11447194b4 100644 --- a/src/software/simulated_tests/or_validation.py +++ b/src/software/simulated_tests/or_validation.py @@ -12,9 +12,7 @@ def __init__(self, validations): def get_validation_status(self, world): for validation in self.validations: if validation.get_validation_status(world) == ValidationStatus.PASSING: - print(f"OR Validation PASSING {validation}") return ValidationStatus.PASSING - print(f"OR Validation Failing: {validation}") return ValidationStatus.FAILING def get_validation_geometry(self, world): From 82a89c1b5be68ffe11aa7bcef1ff7a534b5e118a Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 1 Mar 2025 00:50:50 -0800 Subject: [PATCH 62/83] Added back validation type consistency check to OrValidation class. --- src/software/simulated_tests/or_validation.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py index 11447194b4..cc716dfba1 100644 --- a/src/software/simulated_tests/or_validation.py +++ b/src/software/simulated_tests/or_validation.py @@ -6,7 +6,13 @@ class OrValidation(Validation): 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): From 468fa4d01fdaaeebf64f92accdcc10791d08863a Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 1 Mar 2025 01:01:50 -0800 Subject: [PATCH 63/83] Ran formatting script --- .../ai/hl/stp/play/kickoff_play_test.py | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index 1c9439c895..acf1b89f66 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -12,6 +12,7 @@ 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): ball_initial_pos = tbots_cpp.Point(0, 0) @@ -82,7 +83,9 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): always_validation_sequence_set[0].append( OrValidation( [ - BallAlwaysMovesFromRest(position=tbots_cpp.Point(0, 0), threshold=0.01), + BallAlwaysMovesFromRest( + position=tbots_cpp.Point(0, 0), threshold=0.01 + ), NumberOfRobotsAlwaysStaysInRegion( regions=[ tbots_cpp.Field.createSSLDivisionBField().centerCircle() @@ -94,7 +97,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): tbots_cpp.Field.createSSLDivisionBField().centerCircle() ], req_robot_cnt=1, - ) + ), ] ) ) @@ -103,15 +106,17 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): always_validation_sequence_set[0].append( OrValidation( [ - BallAlwaysMovesFromRest(position=tbots_cpp.Point(0, 0), threshold=0.01), + 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() + tbots_cpp.Field.createSSLDivisionBField().centerCircle(), ], req_robot_cnt=6, - ) + ), ] ) ) @@ -121,13 +126,15 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): always_validation_sequence_set[0].append( OrValidation( [ - BallAlwaysMovesFromRest(position=tbots_cpp.Point(0, 0), threshold=0.01), + BallAlwaysMovesFromRest( + position=tbots_cpp.Point(0, 0), threshold=0.01 + ), NumberOfRobotsAlwaysStaysInRegion( regions=[ tbots_cpp.Field.createSSLDivisionBField().centerCircle() ], req_robot_cnt=0, - ) + ), ] ) ) @@ -136,14 +143,16 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): always_validation_sequence_set[0].append( OrValidation( [ - BallAlwaysMovesFromRest(position=tbots_cpp.Point(0, 0), threshold=0.01), + 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().friendlyGoal(), ], req_robot_cnt=6, - ) + ), ] ) ) From 8ad62757290b455278e89c089959789da2379f81 Mon Sep 17 00:00:00 2001 From: suchirss Date: Fri, 1 Aug 2025 11:23:59 -0700 Subject: [PATCH 64/83] Changed distance threshold to 0.05m --- src/software/ai/hl/stp/play/kickoff_play_test.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index acf1b89f66..a6d4f24fcd 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -84,7 +84,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): OrValidation( [ BallAlwaysMovesFromRest( - position=tbots_cpp.Point(0, 0), threshold=0.01 + position=tbots_cpp.Point(0, 0), threshold=0.05 ), NumberOfRobotsAlwaysStaysInRegion( regions=[ @@ -107,7 +107,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): OrValidation( [ BallAlwaysMovesFromRest( - position=tbots_cpp.Point(0, 0), threshold=0.01 + position=tbots_cpp.Point(0, 0), threshold=0.05 ), NumberOfRobotsAlwaysStaysInRegion( regions=[ @@ -127,7 +127,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): OrValidation( [ BallAlwaysMovesFromRest( - position=tbots_cpp.Point(0, 0), threshold=0.01 + position=tbots_cpp.Point(0, 0), threshold=0.05 ), NumberOfRobotsAlwaysStaysInRegion( regions=[ @@ -144,7 +144,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): OrValidation( [ BallAlwaysMovesFromRest( - position=tbots_cpp.Point(0, 0), threshold=0.01 + position=tbots_cpp.Point(0, 0), threshold=0.05 ), NumberOfRobotsAlwaysStaysInRegion( regions=[ @@ -177,4 +177,4 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): if __name__ == "__main__": # Run the test, -s disables all capturing at -vv increases verbosity - sys.exit(pytest.main([__file__, "-svv"])) + sys.exit(pytest.main([__file__, "-svv"])) \ No newline at end of file From cc8a98588ad6b78034abe640b8bae31fd30bddc4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 18:38:41 +0000 Subject: [PATCH 65/83] [pre-commit.ci lite] apply automatic fixes --- src/software/ai/hl/stp/play/kickoff_play_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index a6d4f24fcd..d64edc6f80 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -177,4 +177,4 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): if __name__ == "__main__": # Run the test, -s disables all capturing at -vv increases verbosity - sys.exit(pytest.main([__file__, "-svv"])) \ No newline at end of file + sys.exit(pytest.main([__file__, "-svv"])) From 038e0a42d6e08cd31213856d77ddabcecf38f0a6 Mon Sep 17 00:00:00 2001 From: muk Date: Wed, 6 Aug 2025 11:49:39 -0700 Subject: [PATCH 66/83] working fsm --- src/software/ai/hl/stp/play/BUILD | 40 +---- .../ai/hl/stp/play/kickoff_friendly/BUILD | 42 +++++ .../kickoff_friendly_play.cpp | 35 ++++ .../kickoff_friendly_play.h | 17 +- .../kickoff_friendly_play_fsm.cpp | 157 ++++++++++++++++++ .../kickoff_friendly_play_fsm.h | 132 +++++++++++++++ .../kickoff_friendly_play_test.cpp | 2 +- .../ai/hl/stp/play/kickoff_friendly_play.cpp | 138 --------------- src/software/ai/play_selection_fsm.cpp | 2 +- 9 files changed, 387 insertions(+), 178 deletions(-) create mode 100644 src/software/ai/hl/stp/play/kickoff_friendly/BUILD create mode 100644 src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play.cpp rename src/software/ai/hl/stp/play/{ => kickoff_friendly}/kickoff_friendly_play.h (50%) create mode 100644 src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.cpp create mode 100644 src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.h rename src/software/ai/hl/stp/play/{ => kickoff_friendly}/kickoff_friendly_play_test.cpp (97%) delete mode 100644 src/software/ai/hl/stp/play/kickoff_friendly_play.cpp diff --git a/src/software/ai/hl/stp/play/BUILD b/src/software/ai/hl/stp/play/BUILD index bd9c16119d..3485482476 100644 --- a/src/software/ai/hl/stp/play/BUILD +++ b/src/software/ai/hl/stp/play/BUILD @@ -24,22 +24,6 @@ cc_library( alwayslink = True, ) -cc_library( - name = "kickoff_friendly_play", - srcs = ["kickoff_friendly_play.cpp"], - hdrs = ["kickoff_friendly_play.h"], - deps = [ - ":play", - "//shared:constants", - "//software/ai/evaluation:enemy_threat", - "//software/ai/hl/stp/tactic/chip:chip_tactic", - "//software/ai/hl/stp/tactic/move:move_tactic", - "//software/logger", - "//software/util/generic_factory", - ], - alwayslink = True, -) - cc_library( name = "shoot_or_chip_play", srcs = ["shoot_or_chip_play.cpp"], @@ -106,7 +90,6 @@ cc_library( name = "all_plays", deps = [ ":kickoff_enemy_play", - ":kickoff_friendly_play", ":shoot_or_chip_play", ":stop_play", "//software/ai/hl/stp/play/ball_placement:ball_placement_play", @@ -116,6 +99,7 @@ cc_library( "//software/ai/hl/stp/play/enemy_free_kick:enemy_free_kick_play", "//software/ai/hl/stp/play/example:example_play", "//software/ai/hl/stp/play/free_kick:free_kick_play", + "//software/ai/hl/stp/play/kickoff_friendly:kickoff_friendly_play", "//software/ai/hl/stp/play/halt_play", "//software/ai/hl/stp/play/hardware_challenge_plays:dribbling_parcour_play", "//software/ai/hl/stp/play/hardware_challenge_plays:pass_endurance_play", @@ -128,22 +112,6 @@ cc_library( ], ) -cc_test( - name = "kickoff_friendly_play_cpp_test", - srcs = ["kickoff_friendly_play_test.cpp"], - deps = [ - "//shared/test_util:tbots_gtest_main", - "//software/ai/hl/stp/play:kickoff_friendly_play", - "//software/simulated_tests:simulated_er_force_sim_play_test_fixture", - "//software/simulated_tests/non_terminating_validation_functions", - "//software/simulated_tests/terminating_validation_functions", - "//software/simulated_tests/validation:validation_function", - "//software/test_util", - "//software/time:duration", - "//software/world", - ], -) - cc_test( name = "kickoff_enemy_play_cpp_test", srcs = ["kickoff_enemy_play_test.cpp"], @@ -162,9 +130,9 @@ cc_test( ) py_test( - name = "kickoff_play_test", + name = "kickoff_enemy_play_test", srcs = [ - "kickoff_play_test.py", + "kickoff_enemy_play_test.py", ], # TODO (#2619) Remove tag to run in parallel tags = [ @@ -276,4 +244,4 @@ py_test( "//software/simulated_tests:validation", requirement("pytest"), ], -) +) \ No newline at end of file diff --git a/src/software/ai/hl/stp/play/kickoff_friendly/BUILD b/src/software/ai/hl/stp/play/kickoff_friendly/BUILD new file mode 100644 index 0000000000..04de9f6ee0 --- /dev/null +++ b/src/software/ai/hl/stp/play/kickoff_friendly/BUILD @@ -0,0 +1,42 @@ +package(default_visibility = ["//visibility:public"]) + +load("@simulated_tests_deps//:requirements.bzl", "requirement") + +cc_library( + name = "kickoff_friendly_play", + srcs = [ + "kickoff_friendly_play.cpp", + "kickoff_friendly_play_fsm.cpp", + ], + hdrs = [ + "kickoff_friendly_play.h", + "kickoff_friendly_play_fsm.h", + ], + deps = [ + "//software/ai/hl/stp/play", + "//shared:constants", + "//software/ai/evaluation:enemy_threat", + "//software/ai/hl/stp/tactic/chip:chip_tactic", + "//software/ai/hl/stp/tactic/move:move_tactic", + "//software/ai/evaluation:find_open_areas", + "//software/logger", + "//software/util/generic_factory", + ], + alwayslink = True, +) + +cc_test( + name = "kickoff_friendly_play_cpp_test", + srcs = ["kickoff_friendly_play_test.cpp"], + deps = [ + "//shared/test_util:tbots_gtest_main", + "//software/ai/hl/stp/play/kickoff_friendly:kickoff_friendly_play", + "//software/simulated_tests:simulated_er_force_sim_play_test_fixture", + "//software/simulated_tests/non_terminating_validation_functions", + "//software/simulated_tests/terminating_validation_functions", + "//software/simulated_tests/validation:validation_function", + "//software/test_util", + "//software/time:duration", + "//software/world", + ], +) diff --git a/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play.cpp b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play.cpp new file mode 100644 index 0000000000..4061d9e700 --- /dev/null +++ b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play.cpp @@ -0,0 +1,35 @@ +#include "software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play.h" + +#include "shared/constants.h" +#include "software/util/generic_factory/generic_factory.h" + + +KickoffFriendlyPlay::KickoffFriendlyPlay(TbotsProto::AiConfig config) + : Play(config, true), fsm{KickoffFriendlyPlayFSM{config}}, control_params{} +{ +} + +void KickoffFriendlyPlay::getNextTactics(TacticCoroutine::push_type &yield, + const WorldPtr &world_ptr) +{ + // Does not get called. + while (true) + { + yield({{}}); + } +} + +void KickoffFriendlyPlay::updateTactics(const PlayUpdate &play_update) +{ + fsm.process_event(KickoffFriendlyPlayFSM::Update(control_params, play_update)); +} + +std::vector KickoffFriendlyPlay::getState() +{ + std::vector state; + state.emplace_back(objectTypeName(*this) + " - " + getCurrentFullStateName(fsm)); + return state; +} + +// Register this play in the genericFactory +static TGenericFactory factory; \ No newline at end of file diff --git a/src/software/ai/hl/stp/play/kickoff_friendly_play.h b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play.h similarity index 50% rename from src/software/ai/hl/stp/play/kickoff_friendly_play.h rename to src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play.h index fda2ea59fe..88cf97f73e 100644 --- a/src/software/ai/hl/stp/play/kickoff_friendly_play.h +++ b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play.h @@ -1,17 +1,30 @@ #pragma once #include "proto/parameters.pb.h" +#include "software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.h" #include "software/ai/hl/stp/play/play.h" /** * A play that runs when its currently the friendly kick off, * only one robot grabs the ball and passes to another robot. */ + class KickoffFriendlyPlay : public Play { - public: +public: + /** + * Creates a friendly kickoff play + * + * @param ai_config the play config for this play + */ KickoffFriendlyPlay(TbotsProto::AiConfig config); void getNextTactics(TacticCoroutine::push_type &yield, const WorldPtr &world_ptr) override; -}; + void updateTactics(const PlayUpdate &play_update) override; + std::vector getState() override; + +private: + FSM fsm; + KickoffFriendlyPlayFSM::ControlParams control_params; +}; \ No newline at end of file diff --git a/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.cpp b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.cpp new file mode 100644 index 0000000000..e13e5a8c8e --- /dev/null +++ b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.cpp @@ -0,0 +1,157 @@ +#include "software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.h" + +KickoffFriendlyPlayFSM::KickoffFriendlyPlayFSM(const TbotsProto::AiConfig &ai_config) + : ai_config(ai_config), + kickoff_chip_tactic(std::make_shared()), + shoot_tactic(std::make_shared()), + move_tactics({ + std::make_shared(), // for robot 1 + std::make_shared(), // for robot 2 + std::make_shared(), // for robot 3 + std::make_shared(), // for robot 4 + std::make_shared() // for robot 5 + }) +{ + +} + +void KickoffFriendlyPlayFSM::createKickoffSetupPositions(const WorldPtr &world_ptr) +{ + // Since we only have 6 robots at the maximum, the number one priority + // is the robot doing the kickoff up front. The goalie is the second most + // important, followed by 3 and 4 setup for offense. 5 and 6 will stay + // back near the goalie just in case the ball quickly returns to the friendly + // side of the field. + // + // +--------------------+--------------------+ + // | | | + // | 3 | | + // | | | + // +--+ 5 | +--+ + // | | | | | + // | | +-+-+ | | + // |2 | |1 | | | + // | | +-+-+ | | + // | | | | | + // +--+ 6 | +--+ + // | | | + // | 4 | | + // | | | + // +--------------------+--------------------+ + // + + if (kickoff_setup_positions.empty()) + { + kickoff_setup_positions = { + // Robot 1 + Point(world_ptr->field().centerPoint() + + Vector(-world_ptr->field().centerCircleRadius(), 0)), + // Robot 2 + // Goalie positions will be handled by the goalie tactic + // Robot 3 + Point( + world_ptr->field().centerPoint() + + Vector(-world_ptr->field().centerCircleRadius() - 4 * ROBOT_MAX_RADIUS_METERS, + -1.0 / 3.0 * world_ptr->field().yLength())), + // Robot 4 + Point( + world_ptr->field().centerPoint() + + Vector(-world_ptr->field().centerCircleRadius() - 4 * ROBOT_MAX_RADIUS_METERS, + 1.0 / 3.0 * world_ptr->field().yLength())), + // Robot 5 + Point(world_ptr->field().friendlyGoalpostPos().x() + + world_ptr->field().defenseAreaXLength() + 2 * ROBOT_MAX_RADIUS_METERS, + world_ptr->field().friendlyGoalpostPos().y()), + // Robot 6 + Point(world_ptr->field().friendlyGoalpostNeg().x() + + world_ptr->field().defenseAreaXLength() + 2 * ROBOT_MAX_RADIUS_METERS, + world_ptr->field().friendlyGoalpostNeg().y()), + }; + } +} + + +void KickoffFriendlyPlayFSM::setupKickoff(const Update &event) +{ + createKickoffSetupPositions(event.common.world_ptr); + + PriorityTacticVector tactics_to_run = {{}}; + + // first priority requires the ability to kick and chip. + move_tactics.at(0)->mutableRobotCapabilityRequirements() = { + RobotCapability::Kick, RobotCapability::Chip}; + + // set each tactic to its movement location. + for (unsigned i = 0; i < kickoff_setup_positions.size(); i++) + { + move_tactics.at(i)->updateControlParams(kickoff_setup_positions.at(i), + Angle::zero()); + tactics_to_run[0].emplace_back(move_tactics.at(i)); + } + + event.common.set_tactics(tactics_to_run); +} + +// taken from free kick fsm. +void KickoffFriendlyPlayFSM::shootBall(const Update &event) +{ + WorldPtr world_ptr = event.common.world_ptr; + PriorityTacticVector tactics_to_run = {{}}; + + Point ball_pos = world_ptr->ball().position(); + + shoot_tactic->updateControlParams( + ball_pos, (shot->getPointToShootAt() - ball_pos).orientation(), + BALL_MAX_SPEED_METERS_PER_SECOND); + tactics_to_run[0].emplace_back(shoot_tactic); + + + event.common.set_tactics(tactics_to_run); +} + +void KickoffFriendlyPlayFSM::chipBall(const Update &event) +{ + WorldPtr world_ptr = event.common.world_ptr; + + PriorityTacticVector tactics_to_run = {{}}; + + // TODO (#2612): This needs to be adjusted post field testing, ball needs to land + // exactly in the middle of the enemy field + kickoff_chip_tactic->updateControlParams( + world_ptr->ball().position(), + world_ptr->field().centerPoint() + + Vector(world_ptr->field().xLength() / 6, 0)); + + tactics_to_run[0].emplace_back(kickoff_chip_tactic); + + event.common.set_tactics(tactics_to_run); +} + +bool KickoffFriendlyPlayFSM::isSetupDone(const Update &event) +{ + return !event.common.world_ptr->gameState().isSetupState(); +} + +// not used currently. +bool KickoffFriendlyPlayFSM::canKick(const Update& event) +{ + return event.common.world_ptr->gameState().canKick(); +} + +bool KickoffFriendlyPlayFSM::isPlaying(const Update& event) +{ + return event.common.world_ptr->gameState().isPlaying(); +} + +// taken from freekickplayfsm +bool KickoffFriendlyPlayFSM::shotFound(const Update &event) +{ + shot = calcBestShotOnGoal(event.common.world_ptr->field(), + event.common.world_ptr->friendlyTeam(), + event.common.world_ptr->enemyTeam(), + event.common.world_ptr->ball().position(), TeamType::ENEMY); + return shot.has_value() && + shot->getOpenAngle() > + Angle::fromDegrees( + ai_config.attacker_tactic_config().min_open_angle_for_shot_deg()); +} \ No newline at end of file diff --git a/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.h b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.h new file mode 100644 index 0000000000..920549b771 --- /dev/null +++ b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.h @@ -0,0 +1,132 @@ +#pragma once + +#include "proto/parameters.pb.h" +#include "shared/constants.h" +#include "software/ai/evaluation/enemy_threat.h" +#include "software/ai/hl/stp/play/play.h" +#include "software/ai/hl/stp/play/play_fsm.h" +#include "software/ai/hl/stp/tactic/kick/kick_tactic.h" +#include "software/ai/hl/stp/tactic/move/move_tactic.h" +#include "software/ai/hl/stp/tactic/chip/chip_tactic.h" +#include "software/ai/evaluation/find_open_areas.h" +#include "software/logger/logger.h" + +struct KickoffFriendlyPlayFSM +{ + class SetupState; + class ShootState; + class ChipState; + + struct ControlParams + { + }; + + DEFINE_PLAY_UPDATE_STRUCT_WITH_CONTROL_AND_COMMON_PARAMS + + /** + * Creates a kickoff friendly play FSM + * + * @param ai_config the play config for this play FSM + */ + explicit KickoffFriendlyPlayFSM(const TbotsProto::AiConfig& ai_config); + + /** + * create a vector of setup positions if not already existing. + * + * @param world_ptr the world pointer + */ + void createKickoffSetupPositions(const WorldPtr &world_ptr); + + /** + * Action to move robots to starting positions + * + * @param event the FreeKickPlayFSM Update event + */ + void setupKickoff(const Update& event); + + /** + * Action to shoot the ball at the net. + * + * @param event the FreeKickPlayFSM Update event + */ + void shootBall(const Update& event); + + /** + * Action to chip the ball forward over the defenders. + * + * @param event the FreeKickPlayFSM Update event + */ + void chipBall(const Update& event); + + /** + * Guard that checks if positions are set up. + * + * @param event the FreeKickPlayFSM Update event + */ + bool isSetupDone(const Update& event); + + /** + * Guard that checks if the ball can be kicked. + * + * @param event the FreeKickPlayFSM Update event + */ + bool canKick(const Update& event); + + /** + * Guard that checks if game has started (ball kicked). + * + * @param event the FreeKickPlayFSM Update event + */ + bool isPlaying(const Update& event); + + /** + * Guard that checks if a direct shot on the net is possible. + * + * @param event the FreeKickPlayFSM Update event + */ + bool shotFound(const Update& event); + + auto operator()() + { + using namespace boost::sml; + + DEFINE_SML_STATE(SetupState) + DEFINE_SML_STATE(ShootState) + DEFINE_SML_STATE(ChipState) + + DEFINE_SML_EVENT(Update) + + DEFINE_SML_ACTION(setupKickoff) + DEFINE_SML_ACTION(shootBall) + DEFINE_SML_ACTION(chipBall) + + DEFINE_SML_GUARD(isSetupDone) + DEFINE_SML_GUARD(shotFound) + DEFINE_SML_GUARD(isPlaying) + + return make_transition_table( + // src_state + event [guard] / action = dest_state + // PlaySelectionFSM will transition to OffensePlay after the kick. + *SetupState_S + Update_E[!isSetupDone_G] / setupKickoff_A = SetupState_S, + + // shoot directly at net if possible. + SetupState_S + Update_E[shotFound_G] = ShootState_S, + ShootState_S + Update_E[!isPlaying_G] / shootBall_A = ShootState_S, + ShootState_S + Update_E[isPlaying_G] = X, + + // else chip over the defenders. + SetupState_S + Update_E = ChipState_S, + ChipState_S + Update_E[!isPlaying_G] / chipBall_A = ChipState_S, + ChipState_S + Update_E[isPlaying_G] = X, + + X + Update_E = X); + } + +private: + TbotsProto::AiConfig ai_config; + std::shared_ptr kickoff_chip_tactic; + std::shared_ptr shoot_tactic; + std::vector> move_tactics; + std::vector kickoff_setup_positions; + std::optional shot; +}; \ No newline at end of file diff --git a/src/software/ai/hl/stp/play/kickoff_friendly_play_test.cpp b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_test.cpp similarity index 97% rename from src/software/ai/hl/stp/play/kickoff_friendly_play_test.cpp rename to src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_test.cpp index 26b164fcdf..73a5dab569 100644 --- a/src/software/ai/hl/stp/play/kickoff_friendly_play_test.cpp +++ b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_test.cpp @@ -1,4 +1,4 @@ -#include "software/ai/hl/stp/play/kickoff_friendly_play.h" +#include "software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play.h" #include diff --git a/src/software/ai/hl/stp/play/kickoff_friendly_play.cpp b/src/software/ai/hl/stp/play/kickoff_friendly_play.cpp deleted file mode 100644 index bec6ac1cc5..0000000000 --- a/src/software/ai/hl/stp/play/kickoff_friendly_play.cpp +++ /dev/null @@ -1,138 +0,0 @@ -#include "software/ai/hl/stp/play/kickoff_friendly_play.h" - -#include "shared/constants.h" -#include "software/ai/evaluation/enemy_threat.h" -#include "software/ai/hl/stp/tactic/chip/chip_tactic.h" -#include "software/ai/hl/stp/tactic/move/move_tactic.h" -#include "software/util/generic_factory/generic_factory.h" - -KickoffFriendlyPlay::KickoffFriendlyPlay(TbotsProto::AiConfig config) : Play(config, true) -{ -} - -void KickoffFriendlyPlay::getNextTactics(TacticCoroutine::push_type &yield, - const WorldPtr &world_ptr) -{ - // Since we only have 6 robots at the maximum, the number one priority - // is the robot doing the kickoff up front. The goalie is the second most - // important, followed by 3 and 4 setup for offense. 5 and 6 will stay - // back near the goalie just in case the ball quickly returns to the friendly - // side of the field. - // - // +--------------------+--------------------+ - // | | | - // | 3 | | - // | | | - // +--+ 5 | +--+ - // | | | | | - // | | +-+-+ | | - // |2 | |1 | | | - // | | +-+-+ | | - // | | | | | - // +--+ 6 | +--+ - // | | | - // | 4 | | - // | | | - // +--------------------+--------------------+ - // - // This is a two part play: - // Part 1: Get into position, but don't touch the ball (ref kickoff) - // Part 2: Chip the ball over the defender (ref normal start) - - // the following positions are in the same order as the positions shown above, - // excluding the goalie for part 1 of this play - std::vector kickoff_setup_positions = { - // Robot 1 - Point(world_ptr->field().centerPoint() + - Vector(-world_ptr->field().centerCircleRadius(), 0)), - // Robot 2 - // Goalie positions will be handled by the goalie tactic - // Robot 3 - Point( - world_ptr->field().centerPoint() + - Vector(-world_ptr->field().centerCircleRadius() - 4 * ROBOT_MAX_RADIUS_METERS, - -1.0 / 3.0 * world_ptr->field().yLength())), - // Robot 4 - Point( - world_ptr->field().centerPoint() + - Vector(-world_ptr->field().centerCircleRadius() - 4 * ROBOT_MAX_RADIUS_METERS, - 1.0 / 3.0 * world_ptr->field().yLength())), - // Robot 5 - Point(world_ptr->field().friendlyGoalpostPos().x() + - world_ptr->field().defenseAreaXLength() + 2 * ROBOT_MAX_RADIUS_METERS, - world_ptr->field().friendlyGoalpostPos().y()), - // Robot 6 - Point(world_ptr->field().friendlyGoalpostNeg().x() + - world_ptr->field().defenseAreaXLength() + 2 * ROBOT_MAX_RADIUS_METERS, - world_ptr->field().friendlyGoalpostNeg().y()), - }; - - // move tactics to use to move to positions defined above - std::vector> move_tactics = { - std::make_shared(), std::make_shared(), - std::make_shared(), std::make_shared(), - std::make_shared()}; - - // specific tactics - auto kickoff_chip_tactic = std::make_shared(); - - // Part 1: setup state (move to key positions) - while (world_ptr->gameState().isSetupState()) - { - auto enemy_threats = - getAllEnemyThreats(world_ptr->field(), world_ptr->friendlyTeam(), - world_ptr->enemyTeam(), world_ptr->ball(), false); - - PriorityTacticVector result = {{}}; - - // set the requirement that Robot 1 must be able to kick and chip - move_tactics.at(0)->mutableRobotCapabilityRequirements() = { - RobotCapability::Kick, RobotCapability::Chip}; - - // setup 5 kickoff positions in order of priority - for (unsigned i = 0; i < kickoff_setup_positions.size(); i++) - { - move_tactics.at(i)->updateControlParams(kickoff_setup_positions.at(i), - Angle::zero()); - result[0].emplace_back(move_tactics.at(i)); - } - - // yield the Tactics this Play wants to run, in order of priority - yield(result); - } - - // Part 2: not normal play, currently ready state (chip the ball) - while (!world_ptr->gameState().isPlaying()) - { - auto enemy_threats = - getAllEnemyThreats(world_ptr->field(), world_ptr->friendlyTeam(), - world_ptr->enemyTeam(), world_ptr->ball(), false); - - PriorityTacticVector result = {{}}; - - // TODO (#2612): This needs to be adjusted post field testing, ball needs to land - // exactly in the middle of the enemy field - kickoff_chip_tactic->updateControlParams( - world_ptr->ball().position(), - world_ptr->field().centerPoint() + - Vector(world_ptr->field().xLength() / 6, 0)); - result[0].emplace_back(kickoff_chip_tactic); - - // the robot at position 0 will be closest to the ball, so positions starting from - // 1 will be assigned to the rest of the robots - for (unsigned i = 1; i < kickoff_setup_positions.size(); i++) - { - move_tactics.at(i)->updateControlParams(kickoff_setup_positions.at(i), - Angle::zero()); - result[0].emplace_back(move_tactics.at(i)); - } - - // yield the Tactics this Play wants to run, in order of priority - yield(result); - } -} - - -// Register this play in the genericFactory -static TGenericFactory - factory; diff --git a/src/software/ai/play_selection_fsm.cpp b/src/software/ai/play_selection_fsm.cpp index c60e00a7c6..85caad5611 100644 --- a/src/software/ai/play_selection_fsm.cpp +++ b/src/software/ai/play_selection_fsm.cpp @@ -6,7 +6,7 @@ #include "software/ai/hl/stp/play/free_kick/free_kick_play.h" #include "software/ai/hl/stp/play/halt_play/halt_play.h" #include "software/ai/hl/stp/play/kickoff_enemy_play.h" -#include "software/ai/hl/stp/play/kickoff_friendly_play.h" +#include "software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play.h" #include "software/ai/hl/stp/play/offense/offense_play.h" #include "software/ai/hl/stp/play/penalty_kick/penalty_kick_play.h" #include "software/ai/hl/stp/play/penalty_kick_enemy/penalty_kick_enemy_play.h" From 90598732e623f98854acf5592d436e5f3b7b812f Mon Sep 17 00:00:00 2001 From: muk Date: Fri, 8 Aug 2025 05:15:27 -0700 Subject: [PATCH 67/83] implemented new chip --- .../kickoff_friendly_play_fsm.cpp | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.cpp b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.cpp index e13e5a8c8e..59905d65ea 100644 --- a/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.cpp +++ b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.cpp @@ -109,18 +109,39 @@ void KickoffFriendlyPlayFSM::shootBall(const Update &event) event.common.set_tactics(tactics_to_run); } +/*TODO change chip ball to use location generated from find open circle, pick the biggest circle [0] and get the center. + * That will be the chip target. Good luck. + * + * + */ void KickoffFriendlyPlayFSM::chipBall(const Update &event) { WorldPtr world_ptr = event.common.world_ptr; PriorityTacticVector tactics_to_run = {{}}; + // sort targets by distance to enemy goal center. + std::vector potential_chip_targets = findGoodChipTargets(*world_ptr); + std::sort(potential_chip_targets.begin(), potential_chip_targets.end(), + [world_ptr](const Circle& first_circle, const Circle& second_circle) { + + return distance(world_ptr->field().enemyGoalCenter(), first_circle.origin()) < + distance(world_ptr->field().enemyGoalCenter(), second_circle.origin()); + }); + // TODO (#2612): This needs to be adjusted post field testing, ball needs to land - // exactly in the middle of the enemy field + // exactly in the middle of the enemy field (as a default) + Point target = world_ptr->field().centerPoint() + Vector(world_ptr->field().xLength() / 6, 0); + + if (!potential_chip_targets.empty()) + { + target = potential_chip_targets[0].origin(); + } + kickoff_chip_tactic->updateControlParams( world_ptr->ball().position(), - world_ptr->field().centerPoint() + - Vector(world_ptr->field().xLength() / 6, 0)); + target + ); tactics_to_run[0].emplace_back(kickoff_chip_tactic); From ce99e2b3a6001dfee25e6e287b82112bd128f784 Mon Sep 17 00:00:00 2001 From: muk Date: Sat, 23 Aug 2025 13:10:09 -0700 Subject: [PATCH 68/83] kick off friendly play fsm works. --- .../kickoff_friendly_play_fsm.cpp | 19 ++++++++++--------- .../kickoff_friendly_play_fsm.h | 3 ++- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.cpp b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.cpp index 59905d65ea..f3eac7c6a7 100644 --- a/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.cpp +++ b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.cpp @@ -109,19 +109,23 @@ void KickoffFriendlyPlayFSM::shootBall(const Update &event) event.common.set_tactics(tactics_to_run); } -/*TODO change chip ball to use location generated from find open circle, pick the biggest circle [0] and get the center. - * That will be the chip target. Good luck. - * - * - */ void KickoffFriendlyPlayFSM::chipBall(const Update &event) { WorldPtr world_ptr = event.common.world_ptr; PriorityTacticVector tactics_to_run = {{}}; + // adjust with testing to give us enough space to catch the ball before it goes out of bounds + double ballX = world_ptr->ball().position().x(); + double fieldX = world_ptr->field().enemyGoalCenter().x() - 2; + double negFieldY = world_ptr->field().enemyCornerNeg().y() + 0.3; + double posFieldY = world_ptr->field().enemyCornerPos().y() - 0.3; + + Rectangle target_area_rectangle = + Rectangle(Point(ballX, negFieldY), Point(fieldX, posFieldY)); + // sort targets by distance to enemy goal center. - std::vector potential_chip_targets = findGoodChipTargets(*world_ptr); + std::vector potential_chip_targets = findGoodChipTargets(*world_ptr, target_area_rectangle); std::sort(potential_chip_targets.begin(), potential_chip_targets.end(), [world_ptr](const Circle& first_circle, const Circle& second_circle) { @@ -129,8 +133,6 @@ void KickoffFriendlyPlayFSM::chipBall(const Update &event) distance(world_ptr->field().enemyGoalCenter(), second_circle.origin()); }); - // TODO (#2612): This needs to be adjusted post field testing, ball needs to land - // exactly in the middle of the enemy field (as a default) Point target = world_ptr->field().centerPoint() + Vector(world_ptr->field().xLength() / 6, 0); if (!potential_chip_targets.empty()) @@ -164,7 +166,6 @@ bool KickoffFriendlyPlayFSM::isPlaying(const Update& event) return event.common.world_ptr->gameState().isPlaying(); } -// taken from freekickplayfsm bool KickoffFriendlyPlayFSM::shotFound(const Update &event) { shot = calcBestShotOnGoal(event.common.world_ptr->field(), diff --git a/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.h b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.h index 920549b771..0c38518bed 100644 --- a/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.h +++ b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.h @@ -22,7 +22,6 @@ struct KickoffFriendlyPlayFSM }; DEFINE_PLAY_UPDATE_STRUCT_WITH_CONTROL_AND_COMMON_PARAMS - /** * Creates a kickoff friendly play FSM * @@ -37,6 +36,8 @@ struct KickoffFriendlyPlayFSM */ void createKickoffSetupPositions(const WorldPtr &world_ptr); + + /** * Action to move robots to starting positions * From 1c656c23d6b95da6ba2ad14273c3e6d51ac771da Mon Sep 17 00:00:00 2001 From: muk Date: Sat, 23 Aug 2025 13:52:21 -0700 Subject: [PATCH 69/83] clean up --- .../play/kickoff_friendly/kickoff_friendly_play_fsm.cpp | 6 ------ .../stp/play/kickoff_friendly/kickoff_friendly_play_fsm.h | 7 ------- 2 files changed, 13 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.cpp b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.cpp index f3eac7c6a7..12eb65ac54 100644 --- a/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.cpp +++ b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.cpp @@ -155,12 +155,6 @@ bool KickoffFriendlyPlayFSM::isSetupDone(const Update &event) return !event.common.world_ptr->gameState().isSetupState(); } -// not used currently. -bool KickoffFriendlyPlayFSM::canKick(const Update& event) -{ - return event.common.world_ptr->gameState().canKick(); -} - bool KickoffFriendlyPlayFSM::isPlaying(const Update& event) { return event.common.world_ptr->gameState().isPlaying(); diff --git a/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.h b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.h index 0c38518bed..7b4dce9cdf 100644 --- a/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.h +++ b/src/software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play_fsm.h @@ -66,13 +66,6 @@ struct KickoffFriendlyPlayFSM */ bool isSetupDone(const Update& event); - /** - * Guard that checks if the ball can be kicked. - * - * @param event the FreeKickPlayFSM Update event - */ - bool canKick(const Update& event); - /** * Guard that checks if game has started (ball kicked). * From 6a31d6ff7c17998bfa64483fc4aa31f15d8f6ef4 Mon Sep 17 00:00:00 2001 From: suchirss Date: Mon, 1 Sep 2025 16:45:43 -0700 Subject: [PATCH 70/83] refactored kickoff_play_test to remove duplicate code instances --- .../ai/hl/stp/play/kickoff_play_test.py | 112 +++++++----------- 1 file changed, 42 insertions(+), 70 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index a6d4f24fcd..f6efa87c14 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -78,84 +78,56 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): # 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.05 - ), - NumberOfRobotsAlwaysStaysInRegion( - regions=[ - tbots_cpp.Field.createSSLDivisionBField().centerCircle() - ], - req_robot_cnt=0, - ), - NumberOfRobotsAlwaysStaysInRegion( - regions=[ - tbots_cpp.Field.createSSLDivisionBField().centerCircle() - ], - req_robot_cnt=1, - ), - ] - ) + + ball_moves_at_rest_validation = BallAlwaysMovesFromRest( + position=tbots_cpp.Point(0, 0), threshold=0.05 + ) + + expected_center_circle_or_validation_set = [ + ball_moves_at_rest_validation, + NumberOfRobotsAlwaysStaysInRegion( + regions=[ + tbots_cpp.Field.createSSLDivisionBField().centerCircle() + ], + req_robot_cnt=0, ) + ] + + friendly_half = tbots_cpp.Field.createSSLDivisionBField().friendlyHalf() + friendly_goal = tbots_cpp.Field.createSSLDivisionBField().friendlyGoal() + center_circle = tbots_cpp.Field.createSSLDivisionBField().centerCircle() + + friendly_regions = [friendly_half, friendly_goal, center_circle] - # 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.05 - ), - NumberOfRobotsAlwaysStaysInRegion( - regions=[ - tbots_cpp.Field.createSSLDivisionBField().friendlyHalf(), - tbots_cpp.Field.createSSLDivisionBField().friendlyGoal(), - tbots_cpp.Field.createSSLDivisionBField().centerCircle(), - ], - req_robot_cnt=6, - ), - ] + if is_friendly_test: + # this expected_center_circle_or_validation_set version checks + # that either 0 or 1 robots are in centerCircle OR ball moves from center point + expected_center_circle_or_validation_set.append( + NumberOfRobotsAlwaysStaysInRegion( + regions=[ + tbots_cpp.Field.createSSLDivisionBField().centerCircle() + ], + req_robot_cnt=1, ) ) - 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.05 - ), - NumberOfRobotsAlwaysStaysInRegion( - regions=[ - tbots_cpp.Field.createSSLDivisionBField().centerCircle() - ], - req_robot_cnt=0, - ), - ] - ) + friendly_regions.remove(center_circle) + + # Checks that there are 6 friendly robots in friendly_regions + # friendly_regions definition depends on if/else case above + expected_robot_regions_or_validations_set = [ + ball_moves_at_rest_validation, + NumberOfRobotsAlwaysStaysInRegion( + regions=friendly_regions, + req_robot_cnt=6, ) + ] - # 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.05 - ), - NumberOfRobotsAlwaysStaysInRegion( - regions=[ - tbots_cpp.Field.createSSLDivisionBField().friendlyHalf(), - tbots_cpp.Field.createSSLDivisionBField().friendlyGoal(), - ], - req_robot_cnt=6, - ), - ] - ) - ) + always_validation_sequence_set[0] = [ + OrValidation(expected_center_circle_or_validation_set), + OrValidation(expected_robot_regions_or_validations_set) + ] eventually_validation_sequence_set = [[]] From 7e9f371cb19eb5966b6e01af5ad0f67deab5c81e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 00:15:30 +0000 Subject: [PATCH 71/83] [pre-commit.ci lite] apply automatic fixes --- src/software/ai/hl/stp/play/kickoff_play_test.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/software/ai/hl/stp/play/kickoff_play_test.py b/src/software/ai/hl/stp/play/kickoff_play_test.py index d70c1c213f..31e3a2fa3c 100644 --- a/src/software/ai/hl/stp/play/kickoff_play_test.py +++ b/src/software/ai/hl/stp/play/kickoff_play_test.py @@ -86,11 +86,9 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): expected_center_circle_or_validation_set = [ ball_moves_at_rest_validation, NumberOfRobotsAlwaysStaysInRegion( - regions=[ - tbots_cpp.Field.createSSLDivisionBField().centerCircle() - ], + regions=[tbots_cpp.Field.createSSLDivisionBField().centerCircle()], req_robot_cnt=0, - ) + ), ] friendly_half = tbots_cpp.Field.createSSLDivisionBField().friendlyHalf() @@ -104,9 +102,7 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): # that either 0 or 1 robots are in centerCircle OR ball moves from center point expected_center_circle_or_validation_set.append( NumberOfRobotsAlwaysStaysInRegion( - regions=[ - tbots_cpp.Field.createSSLDivisionBField().centerCircle() - ], + regions=[tbots_cpp.Field.createSSLDivisionBField().centerCircle()], req_robot_cnt=1, ) ) @@ -121,12 +117,12 @@ def test_kickoff_play(simulated_test_runner, is_friendly_test): NumberOfRobotsAlwaysStaysInRegion( regions=friendly_regions, req_robot_cnt=6, - ) + ), ] always_validation_sequence_set[0] = [ OrValidation(expected_center_circle_or_validation_set), - OrValidation(expected_robot_regions_or_validations_set) + OrValidation(expected_robot_regions_or_validations_set), ] eventually_validation_sequence_set = [[]] From d4efedc8b18844fa2653017335f877ffcbfc9c0b Mon Sep 17 00:00:00 2001 From: suchirss <65541635+suchirss@users.noreply.github.com> Date: Mon, 1 Sep 2025 18:47:40 -0700 Subject: [PATCH 72/83] Update src/software/simulated_tests/or_validation.py Co-authored-by: itsarune <42703774+itsarune@users.noreply.github.com> --- src/software/simulated_tests/or_validation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py index cc716dfba1..a7edeeb96e 100644 --- a/src/software/simulated_tests/or_validation.py +++ b/src/software/simulated_tests/or_validation.py @@ -38,4 +38,4 @@ def get_validation_geometry(self, world): return validation_geometry def get_validation_type(self, world): - return ValidationType + return self.validations[0].get_validation_type(world) From c9c85f13296968a231dc7ab3385ef1a2dea0c551 Mon Sep 17 00:00:00 2001 From: suchirss Date: Tue, 9 Sep 2025 21:16:23 -0700 Subject: [PATCH 73/83] Changed test_example_play to use list input to regions parameter in NumberOfRobotsEventuallyEntersRegion() as required. --- src/software/ai/hl/stp/play/example/example_play_test.py | 4 ++-- src/software/simulated_tests/robot_enters_region.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/software/ai/hl/stp/play/example/example_play_test.py b/src/software/ai/hl/stp/play/example/example_play_test.py index ef5560feb1..6dfb008106 100644 --- a/src/software/ai/hl/stp/play/example/example_play_test.py +++ b/src/software/ai/hl/stp/play/example/example_play_test.py @@ -82,10 +82,10 @@ def setup(*args): inv_eventually_validation_sequence_set=[ [ NumberOfRobotsEventuallyEntersRegion( - region=tbots_cpp.Circle(ball_initial_pos, 1.1), req_robot_cnt=6 + regions=[tbots_cpp.Circle(ball_initial_pos, 1.1)], req_robot_cnt=6 ), NumberOfRobotsEventuallyExitsRegion( - region=tbots_cpp.Circle(ball_initial_pos, 0.9), req_robot_cnt=6 + regions=[tbots_cpp.Circle(ball_initial_pos, 0.9)], req_robot_cnt=6 ), ] ], diff --git a/src/software/simulated_tests/robot_enters_region.py b/src/software/simulated_tests/robot_enters_region.py index 54c5052edc..d36b054d2f 100644 --- a/src/software/simulated_tests/robot_enters_region.py +++ b/src/software/simulated_tests/robot_enters_region.py @@ -75,7 +75,6 @@ def __init__(self, regions): """ super(RobotEntersRegion, self).__init__(regions, 1) - ( RobotEventuallyEntersRegion, RobotEventuallyExitsRegion, From 310a09f0bac6232c50dbd769e2fe4d0dd12a53b1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Wed, 10 Sep 2025 04:39:51 +0000 Subject: [PATCH 74/83] [pre-commit.ci lite] apply automatic fixes --- src/software/simulated_tests/robot_enters_region.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/software/simulated_tests/robot_enters_region.py b/src/software/simulated_tests/robot_enters_region.py index d36b054d2f..54c5052edc 100644 --- a/src/software/simulated_tests/robot_enters_region.py +++ b/src/software/simulated_tests/robot_enters_region.py @@ -75,6 +75,7 @@ def __init__(self, regions): """ super(RobotEntersRegion, self).__init__(regions, 1) + ( RobotEventuallyEntersRegion, RobotEventuallyExitsRegion, From f151132e75e3eaa34aa6a2fca0150cf8651d6af6 Mon Sep 17 00:00:00 2001 From: muk Date: Wed, 10 Sep 2025 14:02:48 -0700 Subject: [PATCH 75/83] kickoff enemy play converted to fsm success --- src/software/ai/hl/stp/play/BUILD | 53 +----- .../ai/hl/stp/play/kickoff_enemy/BUILD | 60 +++++++ .../play/kickoff_enemy/kickoff_enemy_play.cpp | 35 ++++ .../play/kickoff_enemy/kickoff_enemy_play.h | 29 +++ .../kickoff_enemy/kickoff_enemy_play_fsm.cpp | 165 ++++++++++++++++++ .../kickoff_enemy/kickoff_enemy_play_fsm.h | 102 +++++++++++ .../kickoff_enemy_play_test.cpp | 2 +- .../ai/hl/stp/play/kickoff_enemy_play.cpp | 151 ---------------- .../ai/hl/stp/play/kickoff_enemy_play.h | 19 -- src/software/ai/play_selection_fsm.cpp | 2 +- 10 files changed, 396 insertions(+), 222 deletions(-) create mode 100644 src/software/ai/hl/stp/play/kickoff_enemy/BUILD create mode 100644 src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play.cpp create mode 100644 src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play.h create mode 100644 src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play_fsm.cpp create mode 100644 src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play_fsm.h rename src/software/ai/hl/stp/play/{ => kickoff_enemy}/kickoff_enemy_play_test.cpp (97%) delete mode 100644 src/software/ai/hl/stp/play/kickoff_enemy_play.cpp delete mode 100644 src/software/ai/hl/stp/play/kickoff_enemy_play.h diff --git a/src/software/ai/hl/stp/play/BUILD b/src/software/ai/hl/stp/play/BUILD index 3485482476..266992e0ed 100644 --- a/src/software/ai/hl/stp/play/BUILD +++ b/src/software/ai/hl/stp/play/BUILD @@ -6,24 +6,6 @@ load("@simulated_tests_deps//:requirements.bzl", "requirement") # "factory" design pattern to work are linked in # https://www.bfilipek.com/2018/02/static-vars-static-lib.html -cc_library( - name = "kickoff_enemy_play", - srcs = ["kickoff_enemy_play.cpp"], - hdrs = ["kickoff_enemy_play.h"], - deps = [ - ":play", - "//shared:constants", - "//software/ai/evaluation:enemy_threat", - "//software/ai/evaluation:possession", - "//software/ai/hl/stp/tactic/goalie:goalie_tactic", - "//software/ai/hl/stp/tactic/move:move_tactic", - "//software/ai/hl/stp/tactic/shadow_enemy:shadow_enemy_tactic", - "//software/logger", - "//software/util/generic_factory", - ], - alwayslink = True, -) - cc_library( name = "shoot_or_chip_play", srcs = ["shoot_or_chip_play.cpp"], @@ -89,7 +71,6 @@ cc_library( cc_library( name = "all_plays", deps = [ - ":kickoff_enemy_play", ":shoot_or_chip_play", ":stop_play", "//software/ai/hl/stp/play/ball_placement:ball_placement_play", @@ -100,6 +81,7 @@ cc_library( "//software/ai/hl/stp/play/example:example_play", "//software/ai/hl/stp/play/free_kick:free_kick_play", "//software/ai/hl/stp/play/kickoff_friendly:kickoff_friendly_play", + "//software/ai/hl/stp/play/kickoff_enemy:kickoff_enemy_play", "//software/ai/hl/stp/play/halt_play", "//software/ai/hl/stp/play/hardware_challenge_plays:dribbling_parcour_play", "//software/ai/hl/stp/play/hardware_challenge_plays:pass_endurance_play", @@ -112,38 +94,9 @@ cc_library( ], ) -cc_test( - name = "kickoff_enemy_play_cpp_test", - srcs = ["kickoff_enemy_play_test.cpp"], - deps = [ - "//shared/test_util:tbots_gtest_main", - "//software/ai/hl/stp/play:kickoff_enemy_play", - "//software/geom/algorithms", - "//software/simulated_tests:simulated_er_force_sim_play_test_fixture", - "//software/simulated_tests/non_terminating_validation_functions", - "//software/simulated_tests/terminating_validation_functions", - "//software/simulated_tests/validation:validation_function", - "//software/test_util", - "//software/time:duration", - "//software/world", - ], -) -py_test( - name = "kickoff_enemy_play_test", - srcs = [ - "kickoff_enemy_play_test.py", - ], - # TODO (#2619) Remove tag to run in parallel - tags = [ - "exclusive", - ], - deps = [ - "//software:conftest", - "//software/simulated_tests:validation", - requirement("pytest"), - ], -) + + cc_test( name = "stop_play_test", diff --git a/src/software/ai/hl/stp/play/kickoff_enemy/BUILD b/src/software/ai/hl/stp/play/kickoff_enemy/BUILD new file mode 100644 index 0000000000..f9b9170a53 --- /dev/null +++ b/src/software/ai/hl/stp/play/kickoff_enemy/BUILD @@ -0,0 +1,60 @@ +package(default_visibility = ["//visibility:public"]) + +load("@simulated_tests_deps//:requirements.bzl", "requirement") + +cc_library( + name = "kickoff_enemy_play", + srcs = [ + "kickoff_enemy_play.cpp", + "kickoff_enemy_play_fsm.cpp" + ], + hdrs = [ + "kickoff_enemy_play.h", + "kickoff_enemy_play_fsm.h", + ], + deps = [ + "//software/ai/hl/stp/play", + "//shared:constants", + "//software/ai/evaluation:enemy_threat", + "//software/ai/evaluation:possession", + "//software/ai/hl/stp/tactic/goalie:goalie_tactic", + "//software/ai/hl/stp/tactic/move:move_tactic", + "//software/ai/hl/stp/tactic/shadow_enemy:shadow_enemy_tactic", + "//software/logger", + "//software/util/generic_factory", + ], + alwayslink = True, +) + +py_test( + name = "kickoff_enemy_play_test", + srcs = [ + "kickoff_enemy_play_test.py", + ], + # TODO (#2619) Remove tag to run in parallel + tags = [ + "exclusive", + ], + deps = [ + "//software:conftest", + "//software/simulated_tests:validation", + requirement("pytest"), + ], +) + +cc_test( + name = "kickoff_enemy_play_cpp_test", + srcs = ["kickoff_enemy_play_test.cpp"], + deps = [ + "//shared/test_util:tbots_gtest_main", + "//software/ai/hl/stp/play:kickoff_enemy_play", + "//software/geom/algorithms", + "//software/simulated_tests:simulated_er_force_sim_play_test_fixture", + "//software/simulated_tests/non_terminating_validation_functions", + "//software/simulated_tests/terminating_validation_functions", + "//software/simulated_tests/validation:validation_function", + "//software/test_util", + "//software/time:duration", + "//software/world", + ], +) diff --git a/src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play.cpp b/src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play.cpp new file mode 100644 index 0000000000..34e222f646 --- /dev/null +++ b/src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play.cpp @@ -0,0 +1,35 @@ +#include "software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play.h" + +#include "shared/constants.h" +#include "software/util/generic_factory/generic_factory.h" + +KickoffEnemyPlay::KickoffEnemyPlay(TbotsProto::AiConfig config) + : Play(config, true), fsm{KickoffEnemyPlayFSM{config}}, control_params{} +{ +} + +void KickoffEnemyPlay::getNextTactics(TacticCoroutine::push_type &yield, + const WorldPtr &world_ptr) +{ + // Does not get called. + while (true) + { + yield({{}}); + } +} + +void KickoffEnemyPlay::updateTactics(const PlayUpdate &play_update) +{ + fsm.process_event(KickoffEnemyPlayFSM::Update(control_params, play_update)); +} + +std::vector KickoffEnemyPlay::getState() +{ + std::vector state; + state.emplace_back(objectTypeName(*this) + " - " + getCurrentFullStateName(fsm)); + return state; +} + + +// Register this play in the genericFactory +static TGenericFactory factory; diff --git a/src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play.h b/src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play.h new file mode 100644 index 0000000000..f41d898387 --- /dev/null +++ b/src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play.h @@ -0,0 +1,29 @@ +#pragma once + +#include "proto/parameters.pb.h" +#include "software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play_fsm.h" +#include "software/ai/hl/stp/play/play.h" + +/** + * A play that runs when its currently the enemy kick off. + */ + +class KickoffEnemyPlay : public Play +{ +public: + /** + * Creates an enemy kickoff play + * + * @param ai_config the play config for this play + */ + KickoffEnemyPlay(TbotsProto::AiConfig config); + + void getNextTactics(TacticCoroutine::push_type &yield, + const WorldPtr &world_ptr) override; + void updateTactics(const PlayUpdate &play_update) override; + std::vector getState() override; + +private: + FSM fsm; + KickoffEnemyPlayFSM::ControlParams control_params; +}; \ No newline at end of file diff --git a/src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play_fsm.cpp b/src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play_fsm.cpp new file mode 100644 index 0000000000..fb7229f112 --- /dev/null +++ b/src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play_fsm.cpp @@ -0,0 +1,165 @@ +#include "software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play_fsm.h" + +KickoffEnemyPlayFSM::KickoffEnemyPlayFSM(const TbotsProto::AiConfig &ai_config) + : ai_config(ai_config), + shadow_enemy_tactics({ + std::make_shared(), + std::make_shared() + }), + move_tactics({ + std::make_shared(), // for robot 1 + std::make_shared(), // for robot 2 + std::make_shared(), // for robot 3 + std::make_shared(), // for robot 4 + std::make_shared() // for robot 5 + }) +{ + +} + +void KickoffEnemyPlayFSM::createKickoffSetupPositions(const WorldPtr &world_ptr) +{ + // these positions are picked according to the followicreateKickoffSetupPositions();ng slide + // https://images.slideplayer.com/32/9922349/slides/slide_2.jpg + // since we only have 6 robots at the maximum, 3 robots will shadow threats + // up front, 1 robot is dedicated as the goalie, and the other 2 robots will defend + // either post (as show in the image) + // + // Positions 1,2 are the most important, 3,4,5 are a fallback + // if there aren't as many threats to shadow. Robots will be assigned + // to those positions in order of priority. The 5 positions shown below + // are in the same order as in the defense_position vector. + // + // +--------------------+--------------------+ + // | | | + // | | | + // | | | + // +--+ 2 4 | +--+ + // | | | | | + // | | +-+-+ | | + // | | 3 | | | | + // | | +-+-+ | | + // | | | | | + // +--+ 1 5 | +--+ + // | | | + // | | | + // | | | + // +--------------------+--------------------+ + if (!kickoff_setup_positions.empty()) { + return; + } + + kickoff_setup_positions = { + Point(world_ptr->field().friendlyGoalpostNeg().x() + + world_ptr->field().defenseAreaXLength() + 2 * ROBOT_MAX_RADIUS_METERS, + -world_ptr->field().defenseAreaYLength() / 2.0), + Point(world_ptr->field().friendlyGoalpostPos().x() + + world_ptr->field().defenseAreaXLength() + 2 * ROBOT_MAX_RADIUS_METERS, + world_ptr->field().defenseAreaYLength() / 2.0), + Point(world_ptr->field().friendlyGoalCenter().x() + + world_ptr->field().defenseAreaXLength() + 2 * ROBOT_MAX_RADIUS_METERS, + world_ptr->field().friendlyGoalCenter().y()), + Point(-(world_ptr->field().centerCircleRadius() + 2 * ROBOT_MAX_RADIUS_METERS), + world_ptr->field().defenseAreaYLength() / 2.0), + Point(-(world_ptr->field().centerCircleRadius() + 2 * ROBOT_MAX_RADIUS_METERS), + -world_ptr->field().defenseAreaYLength() / 2.0), + }; +} + +void KickoffEnemyPlayFSM::assignShadowing( + const std::vector &enemy_threats, + PriorityTacticVector &tactics_to_run, + size_t &defense_position_index + ) +{ + const auto shadower_count = std::min(2, enemy_threats.size()); + + for (size_t i = 0; i < shadower_count; i++) + { + // Assign the first 2 robots to shadow enemies, if the enemies exist + auto enemy_threat = enemy_threats.at(i); + // Shadow with a distance slightly more than the distance from the enemy + // robot to the center line, so we are always just on our side of the + // center line + double shadow_dist = std::fabs(enemy_threat.robot.position().x()) + + 2 * ROBOT_MAX_RADIUS_METERS; + // We shadow assuming the robots do not pass so we do not try block passes + // while shadowing, since we can't go on the enemy side to block the pass + // anyway + shadow_enemy_tactics.at(i)->updateControlParams(enemy_threat, + shadow_dist); + + tactics_to_run[0].emplace_back(shadow_enemy_tactics.at(i)); + } +} + +void KickoffEnemyPlayFSM::assignDefenders( + PriorityTacticVector &tactics_to_run, + size_t &defense_position_index + ) +{ + while (defense_position_index < move_tactics.size() - 1 && defense_position_index < kickoff_setup_positions.size()) + { + move_tactics.at(defense_position_index) + ->updateControlParams(kickoff_setup_positions.at(defense_position_index), + Angle::zero()); + tactics_to_run[0].emplace_back(move_tactics.at(defense_position_index)); + defense_position_index++; + } +} + +void KickoffEnemyPlayFSM::assignGoalBlocker( + const WorldPtr &world_ptr, + PriorityTacticVector &tactics_to_run, + size_t &defense_position_index + ) +{ + move_tactics.back() + ->updateControlParams( + calculateBlockCone(world_ptr->field().friendlyGoalpostPos(), + world_ptr->field().friendlyGoalpostNeg(), + world_ptr->field().centerPoint(), + ROBOT_MAX_RADIUS_METERS), + Angle::zero(), TbotsProto::MaxAllowedSpeedMode::PHYSICAL_LIMIT, + TbotsProto::ObstacleAvoidanceMode::AGGRESSIVE); + tactics_to_run[0].emplace_back(move_tactics.at(defense_position_index)); + defense_position_index++; +} + +void KickoffEnemyPlayFSM::kickoff(const Update &event) +{ + createKickoffSetupPositions(event.common.world_ptr); + WorldPtr world_ptr = event.common.world_ptr; + Team enemy_team = world_ptr->enemyTeam(); + PriorityTacticVector tactics_to_run = {{}}; + + // TODO: (Mathew): Minor instability with defenders and goalie when the ball and + // attacker are in the middle of the net + + // We find the nearest enemy robot closest to (0,0) then ignore it from the enemy + // team. Since the center circle is a motion constraint during enemy kickoff, the + // shadowing robot will navigate to the closest point that it can to shadow, which + // might not be ideal. (i.e robot won't block a straight shot on net) + auto robot = Team::getNearestRobot(world_ptr->enemyTeam().getAllRobots(), + world_ptr->field().centerPoint()); + if (robot.has_value()) + { + int robot_id = robot.value().id(); + enemy_team.removeRobotWithId(robot_id); + } + else + { + LOG(WARNING) << "No Robot on the Field!"; + } + + auto enemy_threats = + getAllEnemyThreats(world_ptr->field(), world_ptr->friendlyTeam(), + world_ptr->enemyTeam(), world_ptr->ball(), false); + + size_t defense_position_index = 0; + assignShadowing(enemy_threats, tactics_to_run, defense_position_index); + assignDefenders(tactics_to_run, defense_position_index); + assignGoalBlocker(world_ptr, tactics_to_run, defense_position_index); + + event.common.set_tactics(tactics_to_run); +} diff --git a/src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play_fsm.h b/src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play_fsm.h new file mode 100644 index 0000000000..5495d81fda --- /dev/null +++ b/src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play_fsm.h @@ -0,0 +1,102 @@ +#pragma once + +#include "proto/parameters.pb.h" +#include "shared/constants.h" +#include "software/ai/evaluation/enemy_threat.h" +#include "software/ai/hl/stp/play/play.h" +#include "software/ai/hl/stp/play/play_fsm.h" +#include "software/ai/evaluation/possession.h" +#include "software/ai/hl/stp/tactic/shadow_enemy/shadow_enemy_tactic.h" +#include "software/geom/algorithms/calculate_block_cone.h" +#include "software/ai/hl/stp/tactic/move/move_tactic.h" +#include "software/logger/logger.h" + + + +struct KickoffEnemyPlayFSM +{ + class SetupState; + + struct ControlParams + { + }; + + DEFINE_PLAY_UPDATE_STRUCT_WITH_CONTROL_AND_COMMON_PARAMS + /** + * Creates a kickoff enemy play FSM + * + * @param ai_config the play config for this play FSM + */ + explicit KickoffEnemyPlayFSM(const TbotsProto::AiConfig& ai_config); + + /** + * create a vector of setup positions if not already existing. + * + * @param world_ptr the world pointer + */ + void createKickoffSetupPositions(const WorldPtr &world_ptr); + + /** + * add shadowing robots to tactics to run. + * + * @param enemy_threats the enemies that must be shadowed. + * @param tactics_to_run vector of tactics to run. + * @param defense_position_index index of robot for priority. + */ + void assignShadowing(const std::vector &enemy_threats, + PriorityTacticVector &tactics_to_run, + size_t &defense_position_index); + + /** + * add defenders to tactics to run. + * + * @param tactics_to_run vector of tactics to run. + * @param defense_position_index index of robot for priority. + */ + void assignDefenders(PriorityTacticVector &tactics_to_run, size_t &defense_position_index); + + /** + * add a goal blocker to tactics to run. + * + * @param world_ptr the world pointer + * @param tactics_to_run vector of tactics to run. + * @param defense_position_index index of robot for priority. + */ + void assignGoalBlocker( + const WorldPtr &world_ptr, + PriorityTacticVector &tactics_to_run, + size_t &defense_position_index + ); + + /** + * Action to organize the bots to be ready for enemy kickoff. + * + * @param event the FreeKickPlayFSM Update event + */ + void kickoff(const Update& event); + + + auto operator()() + { + using namespace boost::sml; + + DEFINE_SML_STATE(SetupState) + + DEFINE_SML_EVENT(Update) + + DEFINE_SML_ACTION(kickoff) + + + return make_transition_table( + // src_state + event [guard] / action = dest_state + // PlaySelectionFSM will transition to OffensePlay after the kick. + *SetupState_S + Update_E / kickoff_A = SetupState_S + ); + } + +private: + TbotsProto::AiConfig ai_config; + std::vector> shadow_enemy_tactics; + std::vector> move_tactics; + std::vector kickoff_setup_positions; +}; \ No newline at end of file diff --git a/src/software/ai/hl/stp/play/kickoff_enemy_play_test.cpp b/src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play_test.cpp similarity index 97% rename from src/software/ai/hl/stp/play/kickoff_enemy_play_test.cpp rename to src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play_test.cpp index e9ca71ca24..6a363cceaf 100644 --- a/src/software/ai/hl/stp/play/kickoff_enemy_play_test.cpp +++ b/src/software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play_test.cpp @@ -1,4 +1,4 @@ -#include "software/ai/hl/stp/play/kickoff_enemy_play.h" +#include "software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play.h" #include diff --git a/src/software/ai/hl/stp/play/kickoff_enemy_play.cpp b/src/software/ai/hl/stp/play/kickoff_enemy_play.cpp deleted file mode 100644 index 694a0c6401..0000000000 --- a/src/software/ai/hl/stp/play/kickoff_enemy_play.cpp +++ /dev/null @@ -1,151 +0,0 @@ -#include "software/ai/hl/stp/play/kickoff_enemy_play.h" - -#include "proto/parameters.pb.h" -#include "shared/constants.h" -#include "software/ai/evaluation/enemy_threat.h" -#include "software/ai/evaluation/possession.h" -#include "software/ai/hl/stp/tactic/move/move_tactic.h" -#include "software/ai/hl/stp/tactic/shadow_enemy/shadow_enemy_tactic.h" -#include "software/geom/algorithms/calculate_block_cone.h" -#include "software/util/generic_factory/generic_factory.h" - -KickoffEnemyPlay::KickoffEnemyPlay(TbotsProto::AiConfig config) : Play(config, true) {} - -void KickoffEnemyPlay::getNextTactics(TacticCoroutine::push_type &yield, - const WorldPtr &world_ptr) -{ - // 3 robots assigned to shadow enemies. Other robots will be assigned positions - // on the field to be evenly spread out - std::vector> shadow_enemy_tactics = { - std::make_shared(), std::make_shared()}; - - // these positions are picked according to the following slide - // https://images.slideplayer.com/32/9922349/slides/slide_2.jpg - // since we only have 6 robots at the maximum, 3 robots will shadow threats - // up front, 1 robot is dedicated as the goalie, and the other 2 robots will defend - // either post (as show in the image) - // - // Positions 1,2 are the most important, 3,4,5 are a fallback - // if there aren't as many threats to shadow. Robots will be assigned - // to those positions in order of priority. The 5 positions shown below - // are in the same order as in the defense_position vector. - // - // +--------------------+--------------------+ - // | | | - // | | | - // | | | - // +--+ 2 4 | +--+ - // | | | | | - // | | +-+-+ | | - // | | 3 | | | | - // | | +-+-+ | | - // | | | | | - // +--+ 1 5 | +--+ - // | | | - // | | | - // | | | - // +--------------------+--------------------+ - - std::vector defense_positions = { - Point(world_ptr->field().friendlyGoalpostNeg().x() + - world_ptr->field().defenseAreaXLength() + 2 * ROBOT_MAX_RADIUS_METERS, - -world_ptr->field().defenseAreaYLength() / 2.0), - Point(world_ptr->field().friendlyGoalpostPos().x() + - world_ptr->field().defenseAreaXLength() + 2 * ROBOT_MAX_RADIUS_METERS, - world_ptr->field().defenseAreaYLength() / 2.0), - Point(world_ptr->field().friendlyGoalCenter().x() + - world_ptr->field().defenseAreaXLength() + 2 * ROBOT_MAX_RADIUS_METERS, - world_ptr->field().friendlyGoalCenter().y()), - Point(-(world_ptr->field().centerCircleRadius() + 2 * ROBOT_MAX_RADIUS_METERS), - world_ptr->field().defenseAreaYLength() / 2.0), - Point(-(world_ptr->field().centerCircleRadius() + 2 * ROBOT_MAX_RADIUS_METERS), - -world_ptr->field().defenseAreaYLength() / 2.0), - }; - // these move tactics will be used to go to those positions - std::vector> move_tactics = { - std::make_shared(), std::make_shared(), - std::make_shared(), std::make_shared(), - std::make_shared()}; - - // created an enemy_team for mutation - Team enemy_team = world_ptr->enemyTeam(); - - do - { - // TODO: (Mathew): Minor instability with defenders and goalie when the ball and - // attacker are in the middle of the net - - // We find the nearest enemy robot closest to (0,0) then ignore it from the enemy - // team. Since the center circle is a motion constraint during enemy kickoff, the - // shadowing robot will navigate to the closest point that it can to shadow, which - // might not be ideal. (i.e robot won't block a straight shot on net) - auto robot = Team::getNearestRobot(world_ptr->enemyTeam().getAllRobots(), - world_ptr->field().centerPoint()); - if (robot.has_value()) - { - int robot_id = robot.value().id(); - enemy_team.removeRobotWithId(robot_id); - } - else - { - LOG(WARNING) << "No Robot on the Field!"; - } - - auto enemy_threats = - getAllEnemyThreats(world_ptr->field(), world_ptr->friendlyTeam(), - world_ptr->enemyTeam(), world_ptr->ball(), false); - - PriorityTacticVector result = {{}}; - - // keeps track of the next defense position to assign - int defense_position_index = 0; - for (unsigned i = 0; i < defense_positions.size() - 1; ++i) - { - if (i < 2 && i < enemy_threats.size()) - { - // Assign the first 2 robots to shadow enemies, if the enemies exist - auto enemy_threat = enemy_threats.at(i); - // Shadow with a distance slightly more than the distance from the enemy - // robot to the center line, so we are always just on our side of the - // center line - double shadow_dist = std::fabs(enemy_threat.robot.position().x()) + - 2 * ROBOT_MAX_RADIUS_METERS; - // We shadow assuming the robots do not pass so we do not try block passes - // while shadowing, since we can't go on the enemy side to block the pass - // anyway - shadow_enemy_tactics.at(i)->updateControlParams(enemy_threat, - shadow_dist); - - result[0].emplace_back(shadow_enemy_tactics.at(i)); - } - else - { - // Once we are out of enemies to shadow, or are already shadowing 2 - // enemies, we move the rest of the robots to the defense positions - // listed above - move_tactics.at(defense_position_index) - ->updateControlParams(defense_positions.at(defense_position_index), - Angle::zero()); - result[0].emplace_back(move_tactics.at(defense_position_index)); - defense_position_index++; - } - } - - // update robot 3 to be directly between the ball and the friendly net - move_tactics.at(defense_position_index) - ->updateControlParams( - calculateBlockCone(world_ptr->field().friendlyGoalpostPos(), - world_ptr->field().friendlyGoalpostNeg(), - world_ptr->field().centerPoint(), - ROBOT_MAX_RADIUS_METERS), - Angle::zero(), TbotsProto::MaxAllowedSpeedMode::PHYSICAL_LIMIT, - TbotsProto::ObstacleAvoidanceMode::AGGRESSIVE); - result[0].emplace_back(move_tactics.at(defense_position_index)); - - // yield the Tactics this Play wants to run, in order of priority - yield(result); - } while (true); -} - -// Register this play in the genericFactory -static TGenericFactory factory; diff --git a/src/software/ai/hl/stp/play/kickoff_enemy_play.h b/src/software/ai/hl/stp/play/kickoff_enemy_play.h deleted file mode 100644 index b6eac6e826..0000000000 --- a/src/software/ai/hl/stp/play/kickoff_enemy_play.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "proto/parameters.pb.h" -#include "software/ai/hl/stp/play/play.h" - -/** - * A play that runs when its currently the enemies kick off, - * prioritizes defending the net and shadowing the robot - * that is nearest to the ball. Any remaining bots will block - * some odd angles to the net. - */ -class KickoffEnemyPlay : public Play -{ - public: - KickoffEnemyPlay(TbotsProto::AiConfig config); - - void getNextTactics(TacticCoroutine::push_type &yield, - const WorldPtr &world_ptr) override; -}; diff --git a/src/software/ai/play_selection_fsm.cpp b/src/software/ai/play_selection_fsm.cpp index 85caad5611..6af378b4db 100644 --- a/src/software/ai/play_selection_fsm.cpp +++ b/src/software/ai/play_selection_fsm.cpp @@ -5,7 +5,7 @@ #include "software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play.h" #include "software/ai/hl/stp/play/free_kick/free_kick_play.h" #include "software/ai/hl/stp/play/halt_play/halt_play.h" -#include "software/ai/hl/stp/play/kickoff_enemy_play.h" +#include "software/ai/hl/stp/play/kickoff_enemy/kickoff_enemy_play.h" #include "software/ai/hl/stp/play/kickoff_friendly/kickoff_friendly_play.h" #include "software/ai/hl/stp/play/offense/offense_play.h" #include "software/ai/hl/stp/play/penalty_kick/penalty_kick_play.h" From 10c5c2cc27d991e4ed8706e7fcb912b0cc6b0165 Mon Sep 17 00:00:00 2001 From: suchirss Date: Fri, 12 Sep 2025 23:56:04 -0700 Subject: [PATCH 76/83] disabled enemy_free_kick_play_test.py using pytest.skip() because OrValidation is incorrectly passed both AlwaysValidation and EventuallyValidation --- .../ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py b/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py index c32e4c3dff..0062b25ef6 100644 --- a/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py +++ b/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py @@ -19,6 +19,7 @@ from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team +pytest.skip("Disabling this test until OrValidation does not mix always and eventually validations") @pytest.mark.parametrize( "blue_bots,yellow_bots,ball_initial_pos", From 234cfec8b415fc416cfb1f75e9a63045a3d2b166 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Sat, 13 Sep 2025 07:09:47 +0000 Subject: [PATCH 77/83] [pre-commit.ci lite] apply automatic fixes --- .../hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py b/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py index 0062b25ef6..ed9c2a1d73 100644 --- a/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py +++ b/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py @@ -19,7 +19,10 @@ from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team -pytest.skip("Disabling this test until OrValidation does not mix always and eventually validations") +pytest.skip( + "Disabling this test until OrValidation does not mix always and eventually validations" +) + @pytest.mark.parametrize( "blue_bots,yellow_bots,ball_initial_pos", From 76e48860240c482dd4953b3f7f65b568b5ebd569 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 13 Sep 2025 20:19:05 -0700 Subject: [PATCH 78/83] Reverted pytest.skip() in enemy_free_kick_play_test.py since CI treats skipped tests as failed. --- .../ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py b/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py index 0062b25ef6..3e3d8b9886 100644 --- a/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py +++ b/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py @@ -19,8 +19,6 @@ from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team -pytest.skip("Disabling this test until OrValidation does not mix always and eventually validations") - @pytest.mark.parametrize( "blue_bots,yellow_bots,ball_initial_pos", [ From d3b0403abf4ba825185524162631e992a5cbc093 Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 13 Sep 2025 20:33:36 -0700 Subject: [PATCH 79/83] Using @pytest.mark.skip instead to disable enemy_free_kick_play_test since pytest.skip() causes CI to fail. --- .../ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py b/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py index 3e3d8b9886..35eb8ba173 100644 --- a/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py +++ b/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py @@ -93,6 +93,8 @@ ), ], ) + +@pytest.mark.skip("Disabling this test because OrValidation is passed both an always validation and eventually validation") def test_enemy_free_kick_play( simulated_test_runner, blue_bots, yellow_bots, ball_initial_pos ): From f9985a7d72f4a43f619b9637e167589882866b95 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Sun, 14 Sep 2025 03:47:21 +0000 Subject: [PATCH 80/83] [pre-commit.ci lite] apply automatic fixes --- .../stp/play/enemy_free_kick/enemy_free_kick_play_test.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py b/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py index 35eb8ba173..56d195c732 100644 --- a/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py +++ b/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py @@ -19,6 +19,7 @@ from proto.message_translation.tbots_protobuf import create_world_state from proto.ssl_gc_common_pb2 import Team + @pytest.mark.parametrize( "blue_bots,yellow_bots,ball_initial_pos", [ @@ -93,8 +94,9 @@ ), ], ) - -@pytest.mark.skip("Disabling this test because OrValidation is passed both an always validation and eventually validation") +@pytest.mark.skip( + "Disabling this test because OrValidation is passed both an always validation and eventually validation" +) def test_enemy_free_kick_play( simulated_test_runner, blue_bots, yellow_bots, ball_initial_pos ): From 21f7fa0f6cbe38cd4b21c8dcc35578f65060adee Mon Sep 17 00:00:00 2001 From: suchirss Date: Sat, 4 Oct 2025 02:01:36 -0700 Subject: [PATCH 81/83] Tagged TODO #3503 in enemy_free_kick_play_test.py --- .../ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py b/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py index 56d195c732..85e1942f22 100644 --- a/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py +++ b/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py @@ -94,6 +94,8 @@ ), ], ) + +# TODO: #3503 @pytest.mark.skip( "Disabling this test because OrValidation is passed both an always validation and eventually validation" ) From 9a43c107eb566f7cbb5319e7655d61b0a5c93ab3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 05:28:08 +0000 Subject: [PATCH 82/83] [pre-commit.ci lite] apply automatic fixes --- .../ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py b/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py index 85e1942f22..61a003eb1b 100644 --- a/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py +++ b/src/software/ai/hl/stp/play/enemy_free_kick/enemy_free_kick_play_test.py @@ -94,7 +94,6 @@ ), ], ) - # TODO: #3503 @pytest.mark.skip( "Disabling this test because OrValidation is passed both an always validation and eventually validation" From 3368e68b0a6c95812e7432eaede58a672504b4ac Mon Sep 17 00:00:00 2001 From: muk Date: Mon, 13 Oct 2025 15:16:53 -0700 Subject: [PATCH 83/83] patch to fix or_validation --- src/software/ai/hl/stp/play/BUILD | 18 +++++++++++++++++- src/software/simulated_tests/or_validation.py | 3 +++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/software/ai/hl/stp/play/BUILD b/src/software/ai/hl/stp/play/BUILD index 5cae02eaea..45ec31107d 100644 --- a/src/software/ai/hl/stp/play/BUILD +++ b/src/software/ai/hl/stp/play/BUILD @@ -197,4 +197,20 @@ py_test( "//software/simulated_tests:validation", requirement("pytest"), ], -) \ No newline at end of file +) + +py_test( + name = "kickoff_play_test", + srcs = [ + "kickoff_play_test.py", + ], + # TODO (#2619) Remove tag to run in parallel + tags = [ + "exclusive", + ], + deps = [ + "//software:conftest", + "//software/simulated_tests:validation", + requirement("pytest"), + ], +) diff --git a/src/software/simulated_tests/or_validation.py b/src/software/simulated_tests/or_validation.py index a7edeeb96e..b59dd1c391 100644 --- a/src/software/simulated_tests/or_validation.py +++ b/src/software/simulated_tests/or_validation.py @@ -39,3 +39,6 @@ def get_validation_geometry(self, world): def get_validation_type(self, world): return self.validations[0].get_validation_type(world) + + def __repr__(self): + return "PLACEHOLDER"