Skip to content

Commit d9b2017

Browse files
someone2060pre-commit-ci-lite[bot]GrayHoangwilliamckha
authored
Convert ExamplePlay into an FSM play (UBC-Thunderbots#3402)
* Refactor `StopTactic` to `HaltTactic`, refactoring variables where necessary Files still need to be refactored, which will be done in the next commit * Rename `stop_tactic.cpp` and `stop_tactic.h` to `halt_tactic.cpp` and `halt_tactic.h`, renaming variables and strings where necessary Variables and strings renamed for consistency and to allow tests to successfully run * Rename `stop_tactic_test.cpp` to `halt_tactic_test.cpp` * Rename `stop_fsm` and `stop_fsm_test` to `halt_fsm` and `halt_fsm_test`, renaming where necessary * Rename `tactic/stop` folder to `tactic/halt`, renaming addresses where necessary * [pre-commit.ci lite] apply automatic fixes * Small consistency improvements * Small consistency improvements * Create `example` directory containing all example plays (fsm incomplete) * Create `example` directory containing all example plays (FSM incomplete) `example_play_fsm.cpp` and associated files have not been implemented; planned to be implemented next commit * Copy relevant code from other fsm plays to `example_play` files Still giving errors, as `example_play_fsm.cpp` has not been implemented * Remove `example_play_fsm_test.cpp` * Implement `example_play_fsm.cpp` and `example_play_fsm.h` Debugging still necessary, as the `example_play_test.cpp` is not passing * Debug `example_play_fsm.cpp` test case works now yippee * comment fix * [pre-commit.ci lite] apply automatic fixes * Remove `AIConfig` from example plays * Implement suggestions from @williamckha * [pre-commit.ci lite] apply automatic fixes * Create `example_play_fsm_test.cpp` Copied from UBC-Thunderbots#3398 by @potatoisagender * [pre-commit.ci lite] apply automatic fixes * temp push done so i can merge from remote * (try to) Merge master branch into own branch * Remove merge conflict in `play/example/BUILD` * Resolve `.BUILD` merge conflict * Adds pytests for example play * [pre-commit.ci lite] apply automatic fixes * Small fixes * [pre-commit.ci lite] apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Grayson Hoang <grayhoang@gmail.com> Co-authored-by: williamckha <williamha@outlook.com>
1 parent e945885 commit d9b2017

12 files changed

Lines changed: 342 additions & 88 deletions

docs/fsm-diagrams.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,19 @@ Terminate:::terminate --> Terminate:::terminate
106106
107107
```
108108

109+
## [ExamplePlayFSM](/src/software/ai/hl/stp/play/example/example_play_fsm.h)
110+
111+
```mermaid
112+
113+
stateDiagram-v2
114+
classDef terminate fill:white,color:black,font-weight:bold
115+
direction LR
116+
[*] --> MoveState
117+
MoveState --> MoveState : <i>moveToPosition</i>
118+
Terminate:::terminate --> Terminate:::terminate
119+
120+
```
121+
109122
## [FreeKickPlayFSM](/src/software/ai/hl/stp/play/free_kick/free_kick_play_fsm.h)
110123

111124
```mermaid

src/software/ai/hl/stp/play/BUILD

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,6 @@ load("@simulated_tests_deps//:requirements.bzl", "requirement")
66
# "factory" design pattern to work are linked in
77
# https://www.bfilipek.com/2018/02/static-vars-static-lib.html
88

9-
cc_library(
10-
name = "example_play",
11-
srcs = ["example_play.cpp"],
12-
hdrs = ["example_play.h"],
13-
deps = [
14-
":play",
15-
"//shared:constants",
16-
"//software/ai/hl/stp/tactic/move:move_tactic",
17-
"//software/logger",
18-
"//software/util/generic_factory",
19-
],
20-
alwayslink = True,
21-
)
22-
239
cc_library(
2410
name = "kickoff_enemy_play",
2511
srcs = ["kickoff_enemy_play.cpp"],
@@ -119,7 +105,6 @@ cc_library(
119105
cc_library(
120106
name = "all_plays",
121107
deps = [
122-
":example_play",
123108
":kickoff_enemy_play",
124109
":kickoff_friendly_play",
125110
":shoot_or_chip_play",
@@ -129,6 +114,7 @@ cc_library(
129114
"//software/ai/hl/stp/play/defense:defense_play",
130115
"//software/ai/hl/stp/play/enemy_ball_placement:enemy_ball_placement_play",
131116
"//software/ai/hl/stp/play/enemy_free_kick:enemy_free_kick_play",
117+
"//software/ai/hl/stp/play/example:example_play",
132118
"//software/ai/hl/stp/play/free_kick:free_kick_play",
133119
"//software/ai/hl/stp/play/halt_play",
134120
"//software/ai/hl/stp/play/hardware_challenge_plays:dribbling_parcour_play",
@@ -142,20 +128,6 @@ cc_library(
142128
],
143129
)
144130

145-
cc_test(
146-
name = "example_play_test",
147-
srcs = ["example_play_test.cpp"],
148-
deps = [
149-
"//shared/test_util:tbots_gtest_main",
150-
"//software/ai/hl/stp/play:example_play",
151-
"//software/simulated_tests:simulated_er_force_sim_play_test_fixture",
152-
"//software/simulated_tests/validation:validation_function",
153-
"//software/test_util",
154-
"//software/time:duration",
155-
"//software/world",
156-
],
157-
)
158-
159131
cc_test(
160132
name = "kickoff_friendly_play_cpp_test",
161133
srcs = ["kickoff_friendly_play_test.cpp"],
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package(default_visibility = ["//visibility:public"])
2+
3+
load("@simulated_tests_deps//:requirements.bzl", "requirement")
4+
5+
cc_library(
6+
name = "example_play",
7+
srcs = [
8+
"example_play.cpp",
9+
"example_play_fsm.cpp",
10+
],
11+
hdrs = [
12+
"example_play.h",
13+
"example_play_fsm.h",
14+
],
15+
deps = [
16+
"//shared:constants",
17+
"//software/ai/hl/stp/play",
18+
"//software/ai/hl/stp/tactic/move:move_tactic",
19+
"//software/logger",
20+
"//software/util/generic_factory",
21+
],
22+
alwayslink = True,
23+
)
24+
25+
cc_test(
26+
name = "example_play_test",
27+
srcs = ["example_play_test.cpp"],
28+
deps = [
29+
"//shared/test_util:tbots_gtest_main",
30+
"//software/ai/hl/stp/play/example:example_play",
31+
"//software/simulated_tests:simulated_er_force_sim_play_test_fixture",
32+
"//software/simulated_tests/validation:validation_function",
33+
"//software/test_util",
34+
"//software/time:duration",
35+
"//software/world",
36+
],
37+
)
38+
39+
cc_test(
40+
name = "example_play_fsm_test",
41+
srcs = ["example_play_fsm_test.cpp"],
42+
deps = [
43+
":example_play",
44+
"//shared/test_util:tbots_gtest_main",
45+
"//software/test_util",
46+
],
47+
)
48+
49+
py_test(
50+
name = "example_play_test_py",
51+
srcs = ["example_play_test.py"],
52+
main = "example_play_test.py",
53+
# TODO (#2619) Remove tag to run in parallel
54+
tags = [
55+
"exclusive",
56+
],
57+
deps = [
58+
"//software:conftest",
59+
"//software/simulated_tests:speed_threshold_helpers",
60+
"//software/simulated_tests:validation",
61+
requirement("pytest"),
62+
],
63+
)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include "software/ai/hl/stp/play/example/example_play.h"
2+
3+
#include "shared/constants.h"
4+
#include "software/util/generic_factory/generic_factory.h"
5+
6+
ExamplePlay::ExamplePlay(TbotsProto::AiConfig config)
7+
: Play(config, false), fsm{ExamplePlayFSM{}}, control_params{}
8+
{
9+
}
10+
11+
void ExamplePlay::getNextTactics(TacticCoroutine::push_type &yield,
12+
const WorldPtr &world_ptr)
13+
{
14+
// This function doesn't get called and it will be removed once coroutines are phased
15+
// out
16+
}
17+
18+
void ExamplePlay::updateTactics(const PlayUpdate &play_update)
19+
{
20+
fsm.process_event(ExamplePlayFSM::Update(control_params, play_update));
21+
}
22+
23+
std::vector<std::string> ExamplePlay::getState()
24+
{
25+
std::vector<std::string> state;
26+
state.emplace_back(objectTypeName(*this) + " - " + getCurrentFullStateName(fsm));
27+
return state;
28+
}
29+
30+
// Register this play in the genericFactory
31+
static TGenericFactory<std::string, Play, ExamplePlay, TbotsProto::AiConfig> factory;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#pragma once
2+
3+
#include "software/ai/hl/stp/play/example/example_play_fsm.h"
4+
5+
/**
6+
* An example play that moves the robots in a circle around the ball
7+
*/
8+
class ExamplePlay : public Play
9+
{
10+
public:
11+
/**
12+
* Creates an example play
13+
*
14+
* @param ai_config the play config for this play
15+
*/
16+
ExamplePlay(TbotsProto::AiConfig config);
17+
18+
void getNextTactics(TacticCoroutine::push_type &yield,
19+
const WorldPtr &world_ptr) override;
20+
void updateTactics(const PlayUpdate &play_update) override;
21+
std::vector<std::string> getState() override;
22+
23+
private:
24+
FSM<ExamplePlayFSM> fsm;
25+
ExamplePlayFSM::ControlParams control_params;
26+
};
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include "software/ai/hl/stp/play/example/example_play_fsm.h"
2+
3+
ExamplePlayFSM::ExamplePlayFSM() : move_tactics(DIV_A_NUM_ROBOTS)
4+
{
5+
std::generate(move_tactics.begin(), move_tactics.end(),
6+
[]() { return std::make_shared<MoveTactic>(); });
7+
}
8+
9+
void ExamplePlayFSM::moveToPosition(const Update &event)
10+
{
11+
// The angle between each robot spaced out in a circle around the ball
12+
Angle angle_between_robots = Angle::full() / static_cast<double>(move_tactics.size());
13+
14+
for (size_t k = 0; k < move_tactics.size(); k++)
15+
{
16+
move_tactics[k]->updateControlParams(
17+
event.common.world_ptr->ball().position() +
18+
Vector::createFromAngle(angle_between_robots *
19+
static_cast<double>(k + 1)),
20+
(angle_between_robots * static_cast<double>(k + 1)) + Angle::half());
21+
}
22+
23+
// Set the Tactics this Play wants to run, in order of priority.
24+
// If there are fewer robots in play, robots at the end of the list will not be
25+
// assigned
26+
TacticVector result = {};
27+
result.insert(result.end(), move_tactics.begin(), move_tactics.end());
28+
event.common.set_tactics({result});
29+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#pragma once
2+
3+
#include "proto/parameters.pb.h"
4+
#include "shared/constants.h"
5+
#include "software/ai/hl/stp/play/play.h"
6+
#include "software/ai/hl/stp/tactic/move/move_tactic.h"
7+
#include "software/logger/logger.h"
8+
9+
/**
10+
* An example play that moves the robots in a circle around the ball
11+
*/
12+
struct ExamplePlayFSM
13+
{
14+
class MoveState;
15+
16+
struct ControlParams
17+
{
18+
};
19+
20+
DEFINE_PLAY_UPDATE_STRUCT_WITH_CONTROL_AND_COMMON_PARAMS
21+
22+
/**
23+
* Creates an example play FSM
24+
*/
25+
explicit ExamplePlayFSM();
26+
27+
/**
28+
* Action that moves the robots to certain positions around the ball
29+
*
30+
* @param event the ExamplePlayFSM Update event
31+
*/
32+
void moveToPosition(const Update& event);
33+
34+
auto operator()()
35+
{
36+
using namespace boost::sml;
37+
38+
DEFINE_SML_STATE(MoveState)
39+
40+
DEFINE_SML_EVENT(Update)
41+
42+
DEFINE_SML_ACTION(moveToPosition)
43+
44+
return make_transition_table(
45+
// src_state + event [guard] / action = dest_state
46+
*MoveState_S + Update_E / moveToPosition_A = MoveState_S, X + Update_E = X);
47+
}
48+
49+
private:
50+
std::vector<std::shared_ptr<MoveTactic>> move_tactics;
51+
};
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include "software/ai/hl/stp/play/example/example_play_fsm.h"
2+
3+
#include <gtest/gtest.h>
4+
5+
#include "proto/parameters.pb.h"
6+
#include "software/test_util/equal_within_tolerance.h"
7+
#include "software/test_util/test_util.h"
8+
9+
TEST(ExamplePlayFSMTest, test_transitions)
10+
{
11+
std::shared_ptr<World> world = ::TestUtil::createBlankTestingWorld();
12+
TbotsProto::AiConfig ai_config;
13+
14+
FSM<ExamplePlayFSM> fsm(ExamplePlayFSM{});
15+
16+
EXPECT_TRUE(fsm.is(boost::sml::state<ExamplePlayFSM::MoveState>));
17+
18+
int num_tactics = 6;
19+
20+
fsm.process_event(ExamplePlayFSM::Update(
21+
ExamplePlayFSM::ControlParams{},
22+
PlayUpdate(
23+
world, num_tactics, [](PriorityTacticVector new_tactics) {},
24+
InterPlayCommunication{}, [](InterPlayCommunication comm) {})));
25+
26+
EXPECT_TRUE(fsm.is(boost::sml::state<ExamplePlayFSM::MoveState>));
27+
}

src/software/ai/hl/stp/play/example_play_test.cpp renamed to src/software/ai/hl/stp/play/example/example_play_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include "software/ai/hl/stp/play/example_play.h"
1+
#include "software/ai/hl/stp/play/example/example_play.h"
22

33
#include <gtest/gtest.h>
44

0 commit comments

Comments
 (0)