Skip to content

Commit d202dab

Browse files
committed
Supervise number of robots on the field
1 parent 5a39b22 commit d202dab

File tree

10 files changed

+415
-246
lines changed

10 files changed

+415
-246
lines changed

config/ssl-game-controller.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ server:
1717
game:
1818
state-store-file: state-store.json.stream
1919
yellow-card-duration: 2m
20+
yellow-card-bot-removal-time: 10s
2021
multiple-card-step: 2
2122
multiple-foul-step: 3
2223
multiple-placement-failures: 5

internal/app/config/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ type Geometry struct {
3636
// Game holds configs that are valid for the whole game
3737
type Game struct {
3838
YellowCardDuration time.Duration `yaml:"yellow-card-duration"`
39+
YellowCardBotRemovalTime time.Duration `yaml:"yellow-card-bot-removal-time"`
3940
DefaultDivision Division `yaml:"default-division"`
4041
Normal Special `yaml:"normal"`
4142
Overtime Special `yaml:"overtime"`
@@ -152,6 +153,7 @@ func DefaultControllerConfig() (c Controller) {
152153
c.Network.TrackerAddress = "224.5.23.2:10010"
153154
c.Game.StateStoreFile = "state-store.json.stream"
154155
c.Game.YellowCardDuration = 2 * time.Minute
156+
c.Game.YellowCardBotRemovalTime = 10 * time.Second
155157
c.Game.TeamChoiceTimeout = 200 * time.Millisecond
156158
c.Game.MultipleCardStep = 2
157159
c.Game.MultipleFoulStep = 3

internal/app/config/testdata/config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ server:
1717
game:
1818
state-store-file: state-store.json.stream
1919
yellow-card-duration: 2m
20+
yellow-card-bot-removal-time: 10s
2021
multiple-card-step: 2
2122
multiple-foul-step: 3
2223
multiple-placement-failures: 5

internal/app/engine/engine.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ func (e *Engine) processChanges() {
172172
e.noProgressDetector.process()
173173
e.ballPlacementCoordinator.process()
174174
e.processPrepare()
175-
e.processBotRemoved()
175+
e.processBotNumber()
176176
}
177177
}
178178
}
Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,61 @@
11
package engine
22

3-
func (e *Engine) processBotRemoved() {
4-
// TODO check that bot limit fulfilled within 10s after a yellow card
5-
// check bot number in general as well
3+
import (
4+
"github.com/RoboCup-SSL/ssl-game-controller/internal/app/geom"
5+
"github.com/RoboCup-SSL/ssl-game-controller/internal/app/state"
6+
"github.com/golang/protobuf/ptypes"
7+
"time"
8+
)
9+
10+
func (e *Engine) processBotNumber() {
11+
for _, team := range state.BothTeams() {
12+
e.processBotNumberPerTeam(team)
13+
}
14+
}
15+
16+
func (e *Engine) processBotNumberPerTeam(team state.Team) {
17+
18+
teamInfo := e.currentState.TeamState[team.String()]
19+
newCards := newActiveYellowCards(
20+
teamInfo.YellowCards,
21+
e.gameConfig.YellowCardDuration-e.gameConfig.YellowCardBotRemovalTime,
22+
)
23+
24+
numBots := numRobotsOfTeam(e.gcState.TrackerStateGc.Robots, team)
25+
numBotsAllowed := *teamInfo.MaxAllowedBots + newCards
26+
if numBots > numBotsAllowed {
27+
var ballPos *geom.Vector2
28+
if e.gcState.TrackerStateGc.Ball != nil {
29+
ballPos = e.gcState.TrackerStateGc.Ball.Pos.ToVector2()
30+
}
31+
e.Enqueue(createGameEventChange(state.GameEvent_TOO_MANY_ROBOTS, state.GameEvent{
32+
Event: &state.GameEvent_TooManyRobots_{
33+
TooManyRobots: &state.GameEvent_TooManyRobots{
34+
ByTeam: e.currentState.Command.ForTeam,
35+
NumRobotsAllowed: &numBotsAllowed,
36+
NumRobotsOnField: &numBots,
37+
BallLocation: ballPos,
38+
},
39+
},
40+
}))
41+
}
42+
}
43+
44+
func newActiveYellowCards(cards []*state.YellowCard, minRemaining time.Duration) (count int32) {
45+
for _, c := range cards {
46+
d, _ := ptypes.Duration(c.TimeRemaining)
47+
if d > minRemaining {
48+
count++
49+
}
50+
}
51+
return
52+
}
53+
54+
func numRobotsOfTeam(robots []*Robot, team state.Team) (count int32) {
55+
for _, robot := range robots {
56+
if *robot.Id.Team == team {
57+
count++
58+
}
59+
}
60+
return
661
}

internal/app/state/ssl_gc_game_event.pb.go

Lines changed: 230 additions & 201 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/app/statemachine/change_gameevent.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,8 @@ func (s *StateMachine) nextCommandForEvent(newState *state.State, gameEvent *sta
215215
return state.NewCommand(state.Command_PENALTY, gameEvent.ByTeam().Opposite())
216216
case state.GameEvent_GOAL:
217217
return state.NewCommand(state.Command_KICKOFF, gameEvent.ByTeam().Opposite())
218-
case state.GameEvent_NO_PROGRESS_IN_GAME:
218+
case state.GameEvent_NO_PROGRESS_IN_GAME,
219+
state.GameEvent_TOO_MANY_ROBOTS:
219220
return state.NewCommand(state.Command_FORCE_START, state.Team_UNKNOWN)
220221
default:
221222
return newState.NextCommand
@@ -288,6 +289,7 @@ func stopsTheGame(gameEvent state.GameEvent_Type) bool {
288289
state.GameEvent_BOT_HELD_BALL_DELIBERATELY,
289290
state.GameEvent_BOT_TIPPED_OVER,
290291
// others
292+
state.GameEvent_TOO_MANY_ROBOTS,
291293
state.GameEvent_PLACEMENT_SUCCEEDED:
292294
return true
293295
}

internal/app/statemachine/placementPos.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ func (s *BallPlacementPosDeterminer) Location() *geom.Vector2 {
8282
return s.validateLocation(s.Event.GetNoProgressInGame().Location)
8383
case state.GameEvent_PLACEMENT_FAILED:
8484
return s.validateLocation(s.CurrentPlacementPos)
85+
case state.GameEvent_TOO_MANY_ROBOTS:
86+
return s.validateLocation(s.Event.GetTooManyRobots().BallLocation)
8587
default:
8688
return s.validateLocation(nil)
8789
}

proto/ssl_gc_game_event.proto

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ message GameEvent {
6969
MultipleCards multiple_cards = 32;
7070
MultipleFouls multiple_fouls = 34;
7171
BotSubstitution bot_substitution = 37;
72+
TooManyRobots too_many_robots = 38;
7273

7374
// Events triggered by the human referee through the GC only
7475

@@ -82,8 +83,6 @@ message GameEvent {
8283

8384
// replaced by ready_to_continue flag
8485
Prepared prepared = 1 [deprecated = true];
85-
// event not raised explicitly
86-
TooManyRobots too_many_robots = 38 [deprecated = true];
8786
// obsolete
8887
IndirectGoal indirect_goal = 9 [deprecated = true];
8988
// replaced by the meta-information in the possible_goal event
@@ -445,6 +444,12 @@ message GameEvent {
445444
message TooManyRobots {
446445
// the team that has too many robots
447446
required Team by_team = 1;
447+
// number of robots allowed at the moment
448+
optional int32 num_robots_allowed = 2;
449+
// number of robots currently on the field
450+
optional int32 num_robots_on_field = 3;
451+
// the location of the ball at the moment when this foul occurred
452+
optional Vector2 ball_location = 4;
448453
}
449454
// a robot chipped the ball over the field boundary out of the playing surface
450455
message BoundaryCrossing {
@@ -502,6 +507,7 @@ message GameEvent {
502507
MULTIPLE_CARDS = 32;
503508
MULTIPLE_FOULS = 34;
504509
BOT_SUBSTITUTION = 37;
510+
TOO_MANY_ROBOTS = 38;
505511

506512
// Events triggered by the human referee through the GC only
507513

@@ -514,7 +520,6 @@ message GameEvent {
514520
// Deprecated events
515521

516522
PREPARED = 1 [deprecated = true];
517-
TOO_MANY_ROBOTS = 38 [deprecated = true];
518523
INDIRECT_GOAL = 9 [deprecated = true];
519524
CHIPPED_GOAL = 10 [deprecated = true];
520525
KICK_TIMEOUT = 12 [deprecated = true];

0 commit comments

Comments
 (0)