Skip to content

Commit a2e0228

Browse files
committed
Implement processors/detectors for several game events
1 parent 49caea1 commit a2e0228

13 files changed

+426
-199
lines changed

config/ssl-game-controller.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ game:
3030
DIV_B: 10s
3131
ball-placement-time: 30s
3232
ball-placement-time-top-up: 10s
33+
ball-placement-required-distance: 1.0
34+
ball-placement-tolerance: 0.15
35+
ball-placement-min-distance-to-defense-area: 0.7
3336
normal:
3437
half-duration: 5m
3538
half-time-duration: 5m

internal/app/config/config.go

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,26 @@ type Geometry struct {
3434

3535
// Game holds configs that are valid for the whole game
3636
type Game struct {
37-
YellowCardDuration time.Duration `yaml:"yellow-card-duration"`
38-
DefaultDivision Division `yaml:"default-division"`
39-
Normal Special `yaml:"normal"`
40-
Overtime Special `yaml:"overtime"`
41-
TeamChoiceTimeout time.Duration `yaml:"team-choice-timeout"`
42-
DefaultGeometry map[Division]Geometry `yaml:"default-geometry"`
43-
MultipleCardStep int32 `yaml:"multiple-card-step"`
44-
MultipleFoulStep int32 `yaml:"multiple-foul-step"`
45-
MultiplePlacementFailures int32 `yaml:"multiple-placement-failures"`
46-
MaxBots map[Division]int32 `yaml:"max-bots"`
47-
AutoRefProposalTimeout time.Duration `yaml:"auto-ref-proposal-timeout"`
48-
PrepareTimeout time.Duration `yaml:"prepare-timeout"`
49-
FreeKickTimeout map[Division]time.Duration `yaml:"free-kick-timeout"`
50-
NoProgressTimeout map[Division]time.Duration `yaml:"no-progress-timeout"`
51-
BallPlacementTime time.Duration `yaml:"ball-placement-time"`
52-
BallPlacementTimeTopUp time.Duration `yaml:"ball-placement-time-top-up"`
53-
StateStoreFile string `yaml:"state-store-file"`
37+
YellowCardDuration time.Duration `yaml:"yellow-card-duration"`
38+
DefaultDivision Division `yaml:"default-division"`
39+
Normal Special `yaml:"normal"`
40+
Overtime Special `yaml:"overtime"`
41+
TeamChoiceTimeout time.Duration `yaml:"team-choice-timeout"`
42+
DefaultGeometry map[Division]Geometry `yaml:"default-geometry"`
43+
MultipleCardStep int32 `yaml:"multiple-card-step"`
44+
MultipleFoulStep int32 `yaml:"multiple-foul-step"`
45+
MultiplePlacementFailures int32 `yaml:"multiple-placement-failures"`
46+
MaxBots map[Division]int32 `yaml:"max-bots"`
47+
AutoRefProposalTimeout time.Duration `yaml:"auto-ref-proposal-timeout"`
48+
PrepareTimeout time.Duration `yaml:"prepare-timeout"`
49+
FreeKickTimeout map[Division]time.Duration `yaml:"free-kick-timeout"`
50+
NoProgressTimeout map[Division]time.Duration `yaml:"no-progress-timeout"`
51+
BallPlacementTime time.Duration `yaml:"ball-placement-time"`
52+
BallPlacementTimeTopUp time.Duration `yaml:"ball-placement-time-top-up"`
53+
StateStoreFile string `yaml:"state-store-file"`
54+
BallPlacementRequiredDistance float64 `yaml:"ball-placement-required-distance"`
55+
BallPlacementMinDistanceToDefenseArea float64 `yaml:"ball-placement-min-distance-to-defense-area"`
56+
BallPlacementTolerance float64 `yaml:"ball-placement-tolerance"`
5457
}
5558

5659
// Network holds configs for network communication
@@ -154,6 +157,9 @@ func DefaultControllerConfig() (c Controller) {
154157
c.Game.NoProgressTimeout = map[Division]time.Duration{DivA: time.Second * 5, DivB: time.Second * 10}
155158
c.Game.BallPlacementTime = time.Second * 30
156159
c.Game.BallPlacementTimeTopUp = time.Second * 10
160+
c.Game.BallPlacementRequiredDistance = 1.0
161+
c.Game.BallPlacementMinDistanceToDefenseArea = 0.7
162+
c.Game.BallPlacementTolerance = 0.15
157163

158164
c.Game.Normal.HalfDuration = 5 * time.Minute
159165
c.Game.Normal.HalfTimeDuration = 5 * time.Minute

internal/app/config/testdata/config.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ game:
3030
DIV_B: 10s
3131
ball-placement-time: 30s
3232
ball-placement-time-top-up: 10s
33+
ball-placement-required-distance: 1.0
34+
ball-placement-tolerance: 0.15
35+
ball-placement-min-distance-to-defense-area: 0.7
3336
normal:
3437
half-duration: 5m
3538
half-time-duration: 5m

internal/app/engine/autorefflags.go

Lines changed: 0 additions & 110 deletions
This file was deleted.

internal/app/engine/common.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package engine
2+
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/RoboCup-SSL/ssl-game-controller/internal/app/statemachine"
7+
"time"
8+
)
9+
10+
const ballSteadyThreshold = 0.2
11+
12+
func createGameEventChange(eventType state.GameEvent_Type, event state.GameEvent) *statemachine.Change {
13+
event.Type = &eventType
14+
event.Origin = []string{changeOriginEngine}
15+
return &statemachine.Change{
16+
Origin: &changeOriginEngine,
17+
Change: &statemachine.Change_AddGameEvent{
18+
AddGameEvent: &statemachine.AddGameEvent{
19+
GameEvent: &event,
20+
},
21+
},
22+
}
23+
}
24+
25+
func (e *Engine) readyToContinue() bool {
26+
// robot to ball distance
27+
// forTeam: > 0.05m
28+
// opponent: > 0.5m
29+
30+
// ball is stationary
31+
32+
// TODO
33+
return false
34+
}
35+
36+
func vector2ToLocation(v *geom.Vector2) state.Location {
37+
return state.NewLocation64(*v.X, *v.Y)
38+
}
39+
40+
func locationToVector2(l *state.Location) *geom.Vector2 {
41+
return geom.NewVector2(float64(*l.X), float64(*l.Y))
42+
}
43+
44+
func (e *Engine) timeSinceLastChange() time.Duration {
45+
if e.stateStore.LatestEntry() != nil {
46+
lastChangeTs := goTime(e.stateStore.LatestEntry().Timestamp)
47+
now := e.timeProvider()
48+
return now.Sub(lastChangeTs)
49+
}
50+
return 0
51+
}

internal/app/engine/engine.go

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,34 +18,38 @@ var changeOriginEngine = "Engine"
1818

1919
// Engine listens for changes and runs ticks to update the current state using the state machine
2020
type Engine struct {
21-
gameConfig config.Game
22-
stateStore *store.Store
23-
currentState *state.State
24-
stateMachine *statemachine.StateMachine
25-
queue chan *statemachine.Change
26-
hooks []chan *statemachine.StateChange
27-
timeProvider timer.TimeProvider
28-
lastTimeUpdate time.Time
29-
gcState *GcState
30-
gcStateMutex sync.Mutex
21+
gameConfig config.Game
22+
stateStore *store.Store
23+
currentState *state.State
24+
stateMachine *statemachine.StateMachine
25+
queue chan *statemachine.Change
26+
hooks []chan *statemachine.StateChange
27+
timeProvider timer.TimeProvider
28+
lastTimeUpdate time.Time
29+
gcState *GcState
30+
gcStateMutex sync.Mutex
31+
noProgressDetector NoProgressDetector
32+
ballPlacementCoordinator BallPlacementCoordinator
3133
}
3234

3335
// NewEngine creates a new engine
34-
func NewEngine(gameConfig config.Game) (s *Engine) {
35-
s = new(Engine)
36-
s.gameConfig = gameConfig
37-
s.stateStore = store.NewStore(gameConfig.StateStoreFile)
38-
s.stateMachine = statemachine.NewStateMachine(gameConfig)
39-
s.queue = make(chan *statemachine.Change, 100)
40-
s.hooks = []chan *statemachine.StateChange{}
41-
s.timeProvider = func() time.Time { return time.Now() }
42-
s.lastTimeUpdate = s.timeProvider()
43-
s.gcState = new(GcState)
44-
s.gcState.TeamState = map[string]*GcStateTeam{
36+
func NewEngine(gameConfig config.Game) (e *Engine) {
37+
e = new(Engine)
38+
e.gameConfig = gameConfig
39+
e.stateStore = store.NewStore(gameConfig.StateStoreFile)
40+
e.stateMachine = statemachine.NewStateMachine(gameConfig)
41+
e.queue = make(chan *statemachine.Change, 100)
42+
e.hooks = []chan *statemachine.StateChange{}
43+
e.timeProvider = func() time.Time { return time.Now() }
44+
e.lastTimeUpdate = e.timeProvider()
45+
e.gcState = new(GcState)
46+
e.gcState.TeamState = map[string]*GcStateTeam{
4547
state.Team_YELLOW.String(): new(GcStateTeam),
4648
state.Team_BLUE.String(): new(GcStateTeam),
4749
}
48-
s.gcState.AutoRefState = map[string]*GcStateAutoRef{}
50+
e.gcState.AutoRefState = map[string]*GcStateAutoRef{}
51+
e.noProgressDetector = NoProgressDetector{gcEngine: e}
52+
e.ballPlacementCoordinator = BallPlacementCoordinator{gcEngine: e}
4953
return
5054
}
5155

@@ -161,7 +165,11 @@ func (e *Engine) processChanges() {
161165
e.processChange(change)
162166
case <-time.After(10 * time.Millisecond):
163167
e.tick()
164-
e.processAutoRefFlags()
168+
169+
e.noProgressDetector.process()
170+
e.ballPlacementCoordinator.process()
171+
e.processPrepare()
172+
e.processBotRemoved()
165173
}
166174
}
167175
}
@@ -219,7 +227,7 @@ func (e *Engine) processChange(change *statemachine.Change) {
219227

220228
e.currentState = entry.State
221229

222-
e.postProcessChange(change)
230+
e.postProcessChange(entry)
223231

224232
for _, newChange := range newChanges {
225233
e.queue <- newChange
@@ -254,9 +262,15 @@ func (e *Engine) createInitialState() (s *state.State) {
254262
}
255263

256264
// postProcessChange performs synchronous post processing steps
257-
func (e *Engine) postProcessChange(change *statemachine.Change) {
265+
func (e *Engine) postProcessChange(entry statemachine.StateChange) {
266+
change := entry.Change
258267
if change.GetChangeStage() != nil &&
259268
*change.GetChangeStage().NewStage == state.Referee_NORMAL_FIRST_HALF {
260269
e.currentState.MatchTimeStart, _ = ptypes.TimestampProto(e.timeProvider())
261270
}
271+
if change.GetNewCommand() != nil &&
272+
*change.GetNewCommand().Command.Type == state.Command_STOP &&
273+
entry.StatePre.Command.IsRunning() {
274+
e.processRunningToStop()
275+
}
262276
}

0 commit comments

Comments
 (0)