Skip to content

Commit dba004c

Browse files
annieisawesome2pre-commit-ci-lite[bot]williamckha
authored
Move keep away logic into its own tactic (UBC-Thunderbots#3439)
* wip * implemented and tested enemy_goal and friendly_goal constraints * implemented and tested enemy_goal and friendly_goal constraints * [pre-commit.ci lite] apply automatic fixes * implemented and tested enemy_goal and friendly_goal constraints * [pre-commit.ci lite] apply automatic fixes * implemented and tested enemy_goal and friendly_goal constraints * [pre-commit.ci lite] apply automatic fixes * testing * implemented and tested enemy_goal and friendly_goal constraints * implemented and tested enemy_goal and friendly_goal constraints * implemented and tested enemy_goal and friendly_goal constraints * implemented and tested enemy_goal and friendly_goal constraints * [pre-commit.ci lite] apply automatic fixes * implemented and tested enemy_goal and friendly_goal constraints * [pre-commit.ci lite] apply automatic fixes * Added extra transition and fixed doc * [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: williamckha <williamha@outlook.com> Co-authored-by: William Ha <60044853+williamckha@users.noreply.github.com>
1 parent 4e97b41 commit dba004c

9 files changed

Lines changed: 149 additions & 55 deletions

File tree

docs/fsm-diagrams.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,10 @@ classDef terminate fill:white,color:black,font-weight:bold
218218
direction LR
219219
[*] --> DribbleFSM
220220
DribbleFSM --> PivotKickFSM : [shouldKick]\n<i>pivotKick</i>
221-
DribbleFSM --> DribbleFSM : [!shouldKick]\n<i>keepAway</i>
221+
DribbleFSM --> KeepAwayFSM : [!shouldKick]\n<i>keepAway</i>
222+
KeepAwayFSM --> PivotKickFSM : [shouldKick]\n<i>pivotKick</i>
223+
KeepAwayFSM --> KeepAwayFSM : <i>keepAway</i>
224+
KeepAwayFSM --> DribbleFSM
222225
PivotKickFSM --> PivotKickFSM : <i>pivotKick</i>
223226
PivotKickFSM --> Terminate:::terminate
224227
Terminate:::terminate --> Terminate:::terminate : <i>SET_STOP_PRIMITIVE_ACTION</i>
@@ -342,6 +345,20 @@ Terminate:::terminate --> Terminate:::terminate : [stopDone]\n<i>updateStop</i>
342345
343346
```
344347

348+
## [KeepAwayFSM](/src/software/ai/hl/stp/tactic/keep_away/keep_away_fsm.h)
349+
350+
```mermaid
351+
352+
stateDiagram-v2
353+
classDef terminate fill:white,color:black,font-weight:bold
354+
direction LR
355+
[*] --> DribbleFSM
356+
DribbleFSM --> DribbleFSM : <i>keepAway</i>
357+
DribbleFSM --> Terminate:::terminate
358+
Terminate:::terminate --> Terminate:::terminate : <i>SET_STOP_PRIMITIVE_ACTION</i>
359+
360+
```
361+
345362
## [KickFSM](/src/software/ai/hl/stp/tactic/kick/kick_fsm.h)
346363

347364
```mermaid

src/software/ai/hl/stp/tactic/attacker/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ cc_library(
1515
"//software/ai/evaluation:keep_away",
1616
"//software/ai/hl/stp/tactic",
1717
"//software/ai/hl/stp/tactic/chip:chip_tactic",
18+
"//software/ai/hl/stp/tactic/keep_away:keep_away_tactic",
1819
"//software/ai/hl/stp/tactic/pivot_kick:pivot_kick_tactic",
1920
"//software/ai/passing:pass",
2021
"//software/logger",

src/software/ai/hl/stp/tactic/attacker/attacker_fsm.cpp

Lines changed: 6 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -40,54 +40,17 @@ void AttackerFSM::pivotKick(const Update& event,
4040
processEvent(PivotKickFSM::Update(control_params, event.common));
4141
}
4242

43+
4344
void AttackerFSM::keepAway(const Update& event,
44-
boost::sml::back::process<DribbleFSM::Update> processEvent)
45+
boost::sml::back::process<KeepAwayFSM::Update> processEvent)
4546
{
46-
// ball possession is threatened, get into a better position to take the
47-
// best pass so far
48-
DribbleFSM::ControlParams control_params;
49-
50-
auto best_pass_so_far = Pass(event.common.robot.position(),
51-
event.common.world_ptr->field().enemyGoalCenter(),
52-
BALL_MAX_SPEED_METERS_PER_SECOND);
53-
54-
if (event.control_params.best_pass_so_far)
55-
{
56-
best_pass_so_far = *event.control_params.best_pass_so_far;
57-
}
58-
else
59-
{
60-
// we didn't get a best_pass_so_far, so we will be using the default pass.
61-
LOG(INFO) << "Attacker FSM has no best pass so far, using default pass "
62-
<< "to enemy goal center.";
63-
}
64-
65-
auto keepaway_dribble_dest = findKeepAwayTargetPoint(
66-
*event.common.world_ptr, best_pass_so_far, ai_config.passing_config());
47+
KeepAwayFSM::ControlParams control_params{.best_pass_so_far =
48+
event.control_params.best_pass_so_far};
6749

68-
const auto& enemy_team = event.common.world_ptr->enemyTeam();
69-
const auto& ball = event.common.world_ptr->ball();
70-
71-
auto final_dribble_orientation = best_pass_so_far.passerOrientation();
72-
73-
// there is a robot on the enemy team close to us, face away from the nearest one
74-
auto nearest_enemy_robot = enemy_team.getNearestRobot(event.common.robot.position());
75-
if (nearest_enemy_robot.has_value() &&
76-
distance(ball.position(), nearest_enemy_robot->position()) <
77-
ai_config.attacker_tactic_config().enemy_about_to_steal_ball_radius())
78-
{
79-
auto dribble_orientation_vec = ball.position() - nearest_enemy_robot->position();
80-
final_dribble_orientation = dribble_orientation_vec.orientation();
81-
}
82-
83-
control_params = {.dribble_destination = keepaway_dribble_dest,
84-
.final_dribble_orientation = final_dribble_orientation,
85-
.allow_excessive_dribbling = false};
86-
87-
88-
processEvent(DribbleFSM::Update(control_params, event.common));
50+
processEvent(KeepAwayFSM::Update(control_params, event.common));
8951
}
9052

53+
9154
bool AttackerFSM::shouldKick(const Update& event)
9255
{
9356
return event.control_params.pass_committed || event.control_params.shot;

src/software/ai/hl/stp/tactic/attacker/attacker_fsm.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "software/ai/evaluation/keep_away.h"
55
#include "software/ai/evaluation/shot.h"
66
#include "software/ai/hl/stp/tactic/chip/chip_fsm.h"
7+
#include "software/ai/hl/stp/tactic/keep_away/keep_away_fsm.h"
78
#include "software/ai/hl/stp/tactic/pivot_kick/pivot_kick_fsm.h"
89
#include "software/ai/hl/stp/tactic/tactic.h"
910
#include "software/ai/passing/pass.h"
@@ -42,13 +43,13 @@ struct AttackerFSM
4243
boost::sml::back::process<PivotKickFSM::Update> processEvent);
4344

4445
/**
45-
* Action that updates the DribbleFSM to keep the ball away
46+
* Action that updates the KeepAwayFSM to keep the ball away
4647
*
4748
* @param event AttackerFSM::Update event
48-
* @param processEvent processes the DribbleFSM::Update
49+
* @param processEvent processes the KeepAwayFSM::Update
4950
*/
5051
void keepAway(const Update& event,
51-
boost::sml::back::process<DribbleFSM::Update> processEvent);
52+
boost::sml::back::process<KeepAwayFSM::Update> processEvent);
5253

5354
/**
5455
* Guard that checks if the ball should be kicked, which is when there's a nearby
@@ -60,28 +61,29 @@ struct AttackerFSM
6061
*/
6162
bool shouldKick(const Update& event);
6263

63-
6464
auto operator()()
6565
{
6666
using namespace boost::sml;
6767

6868
DEFINE_SML_STATE(PivotKickFSM)
69+
DEFINE_SML_STATE(KeepAwayFSM)
6970
DEFINE_SML_STATE(DribbleFSM)
71+
7072
DEFINE_SML_EVENT(Update)
7173

7274
DEFINE_SML_GUARD(shouldKick)
7375
DEFINE_SML_SUB_FSM_UPDATE_ACTION(pivotKick, PivotKickFSM)
74-
DEFINE_SML_SUB_FSM_UPDATE_ACTION(keepAway, DribbleFSM)
76+
DEFINE_SML_SUB_FSM_UPDATE_ACTION(keepAway, KeepAwayFSM)
7577

7678
return make_transition_table(
77-
// src_state + event [guard] / action = dest_state
7879
*DribbleFSM_S + Update_E[shouldKick_G] / pivotKick_A = PivotKickFSM_S,
79-
DribbleFSM_S + Update_E[!shouldKick_G] / keepAway_A,
80+
DribbleFSM_S + Update_E[!shouldKick_G] / keepAway_A = KeepAwayFSM_S,
81+
KeepAwayFSM_S + Update_E[shouldKick_G] / pivotKick_A = PivotKickFSM_S,
82+
KeepAwayFSM_S + Update_E / keepAway_A, KeepAwayFSM_S = DribbleFSM_S,
8083
PivotKickFSM_S + Update_E / pivotKick_A, PivotKickFSM_S = X,
8184
X + Update_E / SET_STOP_PRIMITIVE_ACTION = X);
8285
}
8386

8487
private:
85-
// the attacker tactic config
8688
TbotsProto::AiConfig ai_config;
8789
};

src/software/ai/hl/stp/tactic/attacker/attacker_fsm_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ TEST(AttackerFSMTest, test_transitions)
1717

1818
TbotsProto::AiConfig ai_config;
1919
FSM<AttackerFSM> fsm{DribbleFSM(ai_config.dribble_tactic_config()),
20-
AttackerFSM(ai_config)};
20+
KeepAwayFSM(ai_config), AttackerFSM(ai_config)};
2121
EXPECT_TRUE(fsm.is(boost::sml::state<DribbleFSM>));
2222

2323
// robot far from attacker point

src/software/ai/hl/stp/tactic/attacker/attacker_tactic.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ AttackerTactic::AttackerTactic(TbotsProto::AiConfig ai_config)
1717
for (RobotId id = 0; id < MAX_ROBOT_IDS; id++)
1818
{
1919
fsm_map[id] = std::make_unique<FSM<AttackerFSM>>(
20-
DribbleFSM(ai_config.dribble_tactic_config()), AttackerFSM(ai_config));
20+
DribbleFSM(ai_config.dribble_tactic_config()), KeepAwayFSM(ai_config),
21+
AttackerFSM(ai_config));
2122
}
2223
}
2324

@@ -44,7 +45,8 @@ void AttackerTactic::updatePrimitive(const TacticUpdate& tactic_update, bool res
4445
if (reset_fsm)
4546
{
4647
fsm_map[tactic_update.robot.id()] = std::make_unique<FSM<AttackerFSM>>(
47-
DribbleFSM(ai_config.dribble_tactic_config()), AttackerFSM(ai_config));
48+
DribbleFSM(ai_config.dribble_tactic_config()), KeepAwayFSM(ai_config),
49+
AttackerFSM(ai_config));
4850
}
4951

5052
std::optional<Shot> shot = calcBestShotOnGoal(
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package(default_visibility = ["//visibility:public"])
2+
3+
cc_library(
4+
name = "keep_away_tactic",
5+
srcs = [
6+
"keep_away_fsm.cpp",
7+
],
8+
hdrs = [
9+
"keep_away_fsm.h",
10+
],
11+
deps = [
12+
"//software/ai/evaluation:keep_away",
13+
"//software/ai/hl/stp/tactic/dribble:dribble_tactic",
14+
],
15+
)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#include "software/ai/hl/stp/tactic/keep_away/keep_away_fsm.h"
2+
3+
void KeepAwayFSM::keepAway(const Update& event,
4+
boost::sml::back::process<DribbleFSM::Update> processEvent)
5+
{
6+
// ball possession is threatened, get into a better position to take the
7+
// best pass so far
8+
DribbleFSM::ControlParams control_params;
9+
10+
auto best_pass_so_far = Pass(event.common.robot.position(),
11+
event.common.world_ptr->field().enemyGoalCenter(),
12+
BALL_MAX_SPEED_METERS_PER_SECOND);
13+
14+
if (event.control_params.best_pass_so_far)
15+
{
16+
best_pass_so_far = *event.control_params.best_pass_so_far;
17+
}
18+
else
19+
{
20+
// we didn't get a best_pass_so_far, so we will be using the default pass.
21+
LOG(INFO) << "KeepAwayFSM has no best pass so far, using default pass "
22+
<< "to enemy goal center.";
23+
}
24+
25+
auto keepaway_dribble_dest = findKeepAwayTargetPoint(
26+
*event.common.world_ptr, best_pass_so_far, ai_config.passing_config());
27+
28+
const auto& enemy_team = event.common.world_ptr->enemyTeam();
29+
const auto& ball = event.common.world_ptr->ball();
30+
31+
auto final_dribble_orientation = best_pass_so_far.passerOrientation();
32+
33+
// there is a robot on the enemy team close to us, face away from the nearest one
34+
auto nearest_enemy_robot = enemy_team.getNearestRobot(event.common.robot.position());
35+
if (nearest_enemy_robot.has_value() &&
36+
distance(ball.position(), nearest_enemy_robot->position()) <
37+
ai_config.attacker_tactic_config().enemy_about_to_steal_ball_radius())
38+
{
39+
auto dribble_orientation_vec = ball.position() - nearest_enemy_robot->position();
40+
final_dribble_orientation = dribble_orientation_vec.orientation();
41+
}
42+
43+
control_params = {.dribble_destination = keepaway_dribble_dest,
44+
.final_dribble_orientation = final_dribble_orientation,
45+
.allow_excessive_dribbling = false};
46+
47+
processEvent(DribbleFSM::Update(control_params, event.common));
48+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#pragma once
2+
3+
#include "proto/parameters.pb.h"
4+
#include "software/ai/evaluation/keep_away.h"
5+
#include "software/ai/hl/stp/tactic/dribble/dribble_fsm.h"
6+
7+
struct KeepAwayFSM
8+
{
9+
/**
10+
* Constructor for KeepAwayFSM
11+
*
12+
* @param ai_config The config to fetch parameters from
13+
*/
14+
explicit KeepAwayFSM(const TbotsProto::AiConfig& ai_config) : ai_config(ai_config){};
15+
16+
struct ControlParams
17+
{
18+
std::optional<Pass> best_pass_so_far;
19+
};
20+
21+
DEFINE_TACTIC_UPDATE_STRUCT_WITH_CONTROL_AND_COMMON_PARAMS
22+
23+
/**
24+
* Action that updates the DribbleFSM to keep the ball away
25+
*
26+
* @param event KeepAwayFSM::Update event
27+
* @param processEvent processes the DribbleFSM::Update
28+
*/
29+
void keepAway(const Update& event,
30+
boost::sml::back::process<DribbleFSM::Update> processEvent);
31+
32+
auto operator()()
33+
{
34+
using namespace boost::sml;
35+
DEFINE_SML_EVENT(Update)
36+
DEFINE_SML_STATE(DribbleFSM)
37+
DEFINE_SML_SUB_FSM_UPDATE_ACTION(keepAway, DribbleFSM)
38+
39+
return make_transition_table(*DribbleFSM_S + Update_E / keepAway_A,
40+
DribbleFSM_S = X,
41+
X + Update_E / SET_STOP_PRIMITIVE_ACTION = X);
42+
}
43+
44+
private:
45+
TbotsProto::AiConfig ai_config;
46+
};

0 commit comments

Comments
 (0)