-
Notifications
You must be signed in to change notification settings - Fork 127
Example play to FSM #3402
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Example play to FSM #3402
Changes from 36 commits
66303ec
d7f9452
00f3753
148d72a
629c067
835de96
3d7810f
922210f
fc27428
12d8ecc
e5f56d7
cca2c0b
95aeed1
c470919
82b4961
3585ac7
1d9248d
54afbb4
b579915
9631d55
e6d5f47
8d75313
b44573a
fb504d2
ad79923
de099bc
fceadea
328f774
55c6345
201be90
1d3c628
2d30eb1
67d1ee6
c2998e2
2bb773b
facfc19
3515714
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| package(default_visibility = ["//visibility:public"]) | ||
|
|
||
| load("@simulated_tests_deps//:requirements.bzl", "requirement") | ||
|
|
||
| cc_library( | ||
| name = "example_play", | ||
| srcs = [ | ||
| "example_play.cpp", | ||
| "example_play_fsm.cpp", | ||
| ], | ||
| hdrs = [ | ||
| "example_play.h", | ||
| "example_play_fsm.h", | ||
| ], | ||
| deps = [ | ||
| "//shared:constants", | ||
| "//software/ai/hl/stp/play", | ||
| "//software/ai/hl/stp/tactic/move:move_tactic", | ||
| "//software/logger", | ||
| "//software/util/generic_factory", | ||
| ], | ||
| alwayslink = True, | ||
| ) | ||
|
|
||
| cc_test( | ||
| name = "example_play_test", | ||
| srcs = ["example_play_test.cpp"], | ||
| deps = [ | ||
| "//shared/test_util:tbots_gtest_main", | ||
| "//software/ai/hl/stp/play/example:example_play", | ||
| "//software/simulated_tests:simulated_er_force_sim_play_test_fixture", | ||
| "//software/simulated_tests/validation:validation_function", | ||
| "//software/test_util", | ||
| "//software/time:duration", | ||
| "//software/world", | ||
| ], | ||
| ) | ||
|
|
||
| cc_test( | ||
| name = "example_play_fsm_test", | ||
| srcs = ["example_play_fsm_test.cpp"], | ||
| deps = [ | ||
| ":example_play", | ||
| "//shared/test_util:tbots_gtest_main", | ||
| "//software/test_util", | ||
| ], | ||
| ) | ||
|
|
||
| py_test( | ||
| name = "example_play_test_py", | ||
| srcs = ["example_play_test.py"], | ||
| main = "example_play_test.py", | ||
| # TODO (#2619) Remove tag to run in parallel | ||
| tags = [ | ||
| "exclusive", | ||
| ], | ||
| deps = [ | ||
| "//software:conftest", | ||
| "//software/simulated_tests:speed_threshold_helpers", | ||
| "//software/simulated_tests:validation", | ||
| requirement("pytest"), | ||
| ], | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| #include "software/ai/hl/stp/play/example/example_play.h" | ||
|
|
||
| #include "shared/constants.h" | ||
| #include "software/util/generic_factory/generic_factory.h" | ||
|
|
||
| ExamplePlay::ExamplePlay(TbotsProto::AiConfig config) | ||
| : Play(config, false), fsm{ExamplePlayFSM{}}, control_params{} | ||
| { | ||
| } | ||
|
|
||
| void ExamplePlay::getNextTactics(TacticCoroutine::push_type &yield, | ||
| const WorldPtr &world_ptr) | ||
| { | ||
| // This function doesn't get called and it will be removed once coroutines are phased | ||
| // out | ||
| } | ||
|
|
||
| void ExamplePlay::updateTactics(const PlayUpdate &play_update) | ||
| { | ||
| fsm.process_event(ExamplePlayFSM::Update(control_params, play_update)); | ||
| } | ||
|
|
||
| std::vector<std::string> ExamplePlay::getState() | ||
| { | ||
| std::vector<std::string> state; | ||
| state.emplace_back(objectTypeName(*this) + " - " + getCurrentFullStateName(fsm)); | ||
| return state; | ||
| } | ||
|
|
||
| // Register this play in the genericFactory | ||
| static TGenericFactory<std::string, Play, ExamplePlay, TbotsProto::AiConfig> factory; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| #pragma once | ||
|
|
||
| #include "software/ai/hl/stp/play/example/example_play_fsm.h" | ||
|
|
||
| /** | ||
| * An example play that moves the robots in a circle around the ball | ||
| */ | ||
| class ExamplePlay : public Play | ||
| { | ||
| public: | ||
| /** | ||
| * Creates an example play | ||
| * | ||
| * @param ai_config the play config for this play | ||
| */ | ||
| ExamplePlay(TbotsProto::AiConfig config); | ||
|
|
||
| void getNextTactics(TacticCoroutine::push_type &yield, | ||
| const WorldPtr &world_ptr) override; | ||
| void updateTactics(const PlayUpdate &play_update) override; | ||
| std::vector<std::string> getState() override; | ||
|
|
||
| private: | ||
| FSM<ExamplePlayFSM> fsm; | ||
| ExamplePlayFSM::ControlParams control_params; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| #include "software/ai/hl/stp/play/example/example_play_fsm.h" | ||
|
|
||
| ExamplePlayFSM::ExamplePlayFSM() : move_tactics(DIV_A_NUM_ROBOTS) | ||
| { | ||
| std::generate(move_tactics.begin(), move_tactics.end(), | ||
| []() { return std::make_shared<MoveTactic>(); }); | ||
| } | ||
|
|
||
| void ExamplePlayFSM::moveToPosition(const Update &event) | ||
| { | ||
| // The angle between each robot spaced out in a circle around the ball | ||
| Angle angle_between_robots = Angle::full() / static_cast<double>(move_tactics.size()); | ||
|
|
||
| for (size_t k = 0; k < move_tactics.size(); k++) | ||
| { | ||
| move_tactics[k]->updateControlParams( | ||
| event.common.world_ptr->ball().position() + | ||
| Vector::createFromAngle(angle_between_robots * | ||
| static_cast<double>(k + 1)), | ||
| (angle_between_robots * static_cast<double>(k + 1)) + Angle::half()); | ||
| } | ||
|
|
||
| // Set the Tactics this Play wants to run, in order of priority. | ||
| // If there are fewer robots in play, robots at the end of the list will not be | ||
| // assigned | ||
| TacticVector result = {}; | ||
| result.insert(result.end(), move_tactics.begin(), move_tactics.end()); | ||
| event.common.set_tactics({result}); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| #pragma once | ||
|
|
||
| #include "proto/parameters.pb.h" | ||
| #include "shared/constants.h" | ||
| #include "software/ai/hl/stp/play/play.h" | ||
| #include "software/ai/hl/stp/tactic/move/move_tactic.h" | ||
| #include "software/logger/logger.h" | ||
|
|
||
| /** | ||
| * An example play that moves the robots in a circle around the ball | ||
| */ | ||
| struct ExamplePlayFSM | ||
| { | ||
| class MoveState; | ||
|
|
||
| struct ControlParams | ||
| { | ||
| }; | ||
|
|
||
| DEFINE_PLAY_UPDATE_STRUCT_WITH_CONTROL_AND_COMMON_PARAMS | ||
|
|
||
| /** | ||
| * Creates an example play FSM | ||
| */ | ||
| explicit ExamplePlayFSM(); | ||
|
|
||
| /** | ||
| * Action that moves the robots to certain positions around the ball | ||
| * | ||
| * @param event the ExamplePlayFSM Update event | ||
| */ | ||
| void moveToPosition(const Update& event); | ||
|
|
||
| auto operator()() | ||
| { | ||
| using namespace boost::sml; | ||
|
|
||
| DEFINE_SML_STATE(MoveState) | ||
|
|
||
| DEFINE_SML_EVENT(Update) | ||
|
|
||
| DEFINE_SML_ACTION(moveToPosition) | ||
|
|
||
| return make_transition_table( | ||
| // src_state + event [guard] / action = dest_state | ||
| *MoveState_S + Update_E / moveToPosition_A = MoveState_S, | ||
| X + Update_E = X); | ||
| } | ||
|
|
||
| private: | ||
| std::vector<std::shared_ptr<MoveTactic>> move_tactics; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| #include "software/ai/hl/stp/play/example/example_play_fsm.h" | ||
|
|
||
| #include <gtest/gtest.h> | ||
|
|
||
| #include "proto/parameters.pb.h" | ||
| #include "software/test_util/equal_within_tolerance.h" | ||
| #include "software/test_util/test_util.h" | ||
|
|
||
| TEST(ExamplePlayFSMTest, test_transitions) | ||
| { | ||
| std::shared_ptr<World> world = ::TestUtil::createBlankTestingWorld(); | ||
| TbotsProto::AiConfig ai_config; | ||
|
|
||
| FSM<ExamplePlayFSM> fsm(ExamplePlayFSM{}); | ||
|
|
||
| EXPECT_TRUE(fsm.is(boost::sml::state<ExamplePlayFSM::MoveState>)); | ||
|
|
||
| int num_tactics = 6; | ||
|
|
||
| fsm.process_event(ExamplePlayFSM::Update( | ||
| ExamplePlayFSM::ControlParams{}, | ||
| PlayUpdate( | ||
| world, num_tactics, [](PriorityTacticVector new_tactics) {}, | ||
| InterPlayCommunication{}, [](InterPlayCommunication comm) {}))); | ||
|
|
||
| EXPECT_TRUE(fsm.is(boost::sml::state<ExamplePlayFSM::MoveState>)); | ||
| } |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you should also write a FSM test and a pytest for your changes. Take a look at Grayson's PR on how he does the FSM test: #3398
williamckha marked this conversation as resolved.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay some lore... This is a simulated test. Simulated tests execute your AI changes against a simulator to simulate the world. We have two forms of these tests: a C++ test fixture and a newer Python test fixture. We are in the process of phasing the C++ tests out and replacing them with Python. Could you make a new |
Uh oh!
There was an error while loading. Please reload this page.