Skip to content

Commit dd57b51

Browse files
committed
Add continuation issues to UI
1 parent b57aebc commit dd57b51

File tree

8 files changed

+320
-236
lines changed

8 files changed

+320
-236
lines changed

internal/app/engine/common.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@ func createGameEventChange(eventType state.GameEvent_Type, event *state.GameEven
2626
}
2727
}
2828

29-
func (e *Engine) robotsInsideRadius(robots []*Robot, pos *geom.Vector2, radius float64) bool {
29+
func (e *Engine) findRobotInsideRadius(robots []*Robot, pos *geom.Vector2, radius float64) *Robot {
3030
for _, robot := range robots {
3131
distance := robot.Pos.DistanceTo(pos)
3232
if distance < radius {
33-
return true
33+
return robot
3434
}
3535
}
3636

37-
return false
37+
return nil
3838
}
3939

4040
func goDur(duration *durationpb.Duration) time.Duration {

internal/app/engine/process_continue.go

Lines changed: 104 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package engine
22

33
import (
4+
"fmt"
45
"github.com/RoboCup-SSL/ssl-game-controller/internal/app/geom"
56
"github.com/RoboCup-SSL/ssl-game-controller/internal/app/state"
67
"github.com/RoboCup-SSL/ssl-game-controller/internal/app/statemachine"
@@ -15,98 +16,133 @@ func (e *Engine) processContinue() {
1516
*e.currentState.Command.Type == state.Command_STOP ||
1617
(e.gameConfig.ContinueFromHalt && *e.currentState.Command.Type == state.Command_HALT)) ||
1718
e.gcState.TrackerStateGc.Ball == nil {
19+
// Reset ready to continue
1820
e.gcState.ReadyToContinue = nil
21+
e.gcState.ContinuationIssues = []string{}
1922
return
2023
}
2124

22-
readyToContinue := false
25+
e.gcState.ContinuationIssues = e.findIssueForContinuation()
26+
readyToContinue := len(e.gcState.ContinuationIssues) == 0
27+
e.gcState.ReadyToContinue = &readyToContinue
2328

24-
defer func() {
25-
// set at the end of this function when the flag has its final value
26-
e.gcState.ReadyToContinue = &readyToContinue
27-
}()
29+
if readyToContinue && e.currentState.GetAutoContinue() {
30+
e.Enqueue(&statemachine.Change{
31+
Origin: &changeOriginEngine,
32+
Change: &statemachine.Change_Continue{
33+
Continue: &statemachine.Continue{},
34+
},
35+
})
36+
}
37+
}
2838

29-
if e.timeSinceLastChange() < minPreparationTime {
30-
// Too early
31-
return
39+
func (e *Engine) findIssueForContinuation() (issues []string) {
40+
preparationTimeLeft := e.timeSinceLastChange() - minPreparationTime
41+
if preparationTimeLeft < 0 {
42+
issues = append(issues, fmt.Sprintf("%.1fs left for preparation", -preparationTimeLeft.Seconds()))
3243
}
3344

3445
if *e.currentState.Command.Type == state.Command_KICKOFF {
35-
// ball in center circle
36-
if e.gcState.TrackerStateGc.Ball.Pos.ToVector2().Length() > e.getGeometry().CenterCircleRadius {
37-
return
38-
}
39-
40-
// bots on wrong side
41-
for _, robot := range e.gcState.TrackerStateGc.Robots {
42-
if *e.currentState.TeamState[robot.Id.Team.String()].OnPositiveHalf {
43-
if *robot.Pos.X < robotRadius {
44-
return
45-
}
46-
} else if *robot.Pos.X > -robotRadius {
47-
return
48-
}
49-
}
46+
issues = append(issues, e.readyToContinueKickoff()...)
5047
}
5148

5249
if *e.currentState.Command.Type == state.Command_PENALTY {
53-
keeperId := e.penaltyKeeperId()
54-
if keeperId == nil {
55-
return
56-
}
57-
keeperPos := e.robotPos(keeperId)
58-
if keeperPos == nil || !e.posInsideGoal(keeperPos) {
59-
return
60-
}
50+
issues = append(issues, e.readyToContinuePenalty()...)
51+
}
6152

62-
keeperTeamInfo := e.currentState.TeamState[keeperId.Team.String()]
63-
ballPos := e.gcState.TrackerStateGc.Ball.Pos
53+
if *e.currentState.Command.Type == state.Command_STOP {
54+
issues = append(issues, e.readyToContinueFromStop()...)
55+
}
6456

65-
numAttackersInFrontOfBall := 0
66-
for _, robot := range e.gcState.TrackerStateGc.Robots {
67-
if *robot.Id.Id == *keeperId.Id && *robot.Id.Team == *keeperId.Team {
68-
// its the keeper
69-
continue
70-
}
71-
if *keeperTeamInfo.OnPositiveHalf &&
72-
*robot.Pos.X < *ballPos.X-distanceToBallDuringPenalty {
73-
continue
74-
} else if !*keeperTeamInfo.OnPositiveHalf &&
75-
*robot.Pos.X > *ballPos.X+distanceToBallDuringPenalty {
76-
continue
77-
}
78-
if *robot.Id.Team == *keeperId.Team {
79-
return
80-
} else if numAttackersInFrontOfBall >= 1 {
81-
return
82-
} else {
83-
numAttackersInFrontOfBall++
57+
return
58+
}
59+
60+
func (e *Engine) readyToContinueKickoff() (issues []string) {
61+
ballToCenterCircleDist := e.gcState.TrackerStateGc.Ball.Pos.ToVector2().Length() - e.getGeometry().CenterCircleRadius
62+
if ballToCenterCircleDist > 0 {
63+
issues = append(issues, fmt.Sprintf("Ball is %.1f m away from center circle", ballToCenterCircleDist))
64+
}
65+
66+
for _, robot := range e.gcState.TrackerStateGc.Robots {
67+
if *e.currentState.TeamState[robot.Id.Team.String()].OnPositiveHalf {
68+
if *robot.Pos.X < robotRadius {
69+
issues = append(issues, fmt.Sprintf("Robot %s is not in its own half", robot.Id.PrettyString()))
8470
}
71+
} else if *robot.Pos.X > -robotRadius {
72+
issues = append(issues, fmt.Sprintf("Robot %s is not in its own half", robot.Id.PrettyString()))
8573
}
8674
}
75+
return issues
76+
}
8777

88-
if *e.currentState.Command.Type == state.Command_STOP &&
89-
(e.currentState.NextCommand == nil ||
90-
!e.readyToContinueFromStop()) {
78+
func (e *Engine) readyToContinuePenalty() (issues []string) {
79+
keeperId := e.penaltyKeeperId()
80+
if keeperId == nil {
81+
issues = append(issues, "There is no keeper")
9182
return
9283
}
93-
94-
if *e.currentState.Command.Type == state.Command_STOP &&
95-
(e.currentState.NextCommand == nil ||
96-
!e.readyToContinueFromHalt()) {
97-
return
84+
keeperPos := e.robotPos(keeperId)
85+
if keeperPos == nil {
86+
issues = append(issues, "Keeper position is unknown")
87+
} else if !e.posInsideGoal(keeperPos) {
88+
issues = append(issues, "Keeper is not inside goal")
9889
}
9990

100-
readyToContinue = true
91+
keeperTeamInfo := e.currentState.TeamState[keeperId.Team.String()]
92+
ballPos := e.gcState.TrackerStateGc.Ball.Pos
10193

102-
if e.currentState.GetAutoContinue() {
103-
e.Enqueue(&statemachine.Change{
104-
Origin: &changeOriginEngine,
105-
Change: &statemachine.Change_Continue{
106-
Continue: &statemachine.Continue{},
107-
},
108-
})
94+
numAttackersInFrontOfBall := 0
95+
for _, robot := range e.gcState.TrackerStateGc.Robots {
96+
if *robot.Id.Id == *keeperId.Id && *robot.Id.Team == *keeperId.Team {
97+
// it's the keeper
98+
continue
99+
}
100+
if *keeperTeamInfo.OnPositiveHalf &&
101+
*robot.Pos.X < *ballPos.X-distanceToBallDuringPenalty {
102+
continue
103+
} else if !*keeperTeamInfo.OnPositiveHalf &&
104+
*robot.Pos.X > *ballPos.X+distanceToBallDuringPenalty {
105+
continue
106+
}
107+
if *robot.Id.Team == *keeperId.Team {
108+
issues = append(issues, fmt.Sprintf(
109+
"Robot %s does not keep required distance to ball", robot.Id.PrettyString()))
110+
} else if numAttackersInFrontOfBall >= 1 {
111+
issues = append(issues, fmt.Sprintf(
112+
"Robot %s does not keep required distance to ball", robot.Id.PrettyString()))
113+
} else {
114+
numAttackersInFrontOfBall++
115+
}
109116
}
117+
return
118+
}
119+
120+
func (e *Engine) readyToContinueFromStop() (issues []string) {
121+
if e.tooManyRobots(state.Team_YELLOW) {
122+
issues = append(issues, "Yellow team has too many robots")
123+
}
124+
if e.tooManyRobots(state.Team_BLUE) {
125+
issues = append(issues, "Blue team has too many robots")
126+
}
127+
radius := e.gameConfig.DistanceToBallInStop + robotRadius - distanceThreshold
128+
robotNearBall := e.findRobotInsideRadius(e.gcState.TrackerStateGc.Robots, e.gcState.TrackerStateGc.Ball.Pos.ToVector2(), radius)
129+
if robotNearBall != nil {
130+
issues = append(issues, fmt.Sprintf("Robot %s is too close to ball", robotNearBall.Id.PrettyString()))
131+
}
132+
if e.currentState.PlacementPos != nil {
133+
ballToPlacementPosDist := e.currentState.PlacementPos.DistanceTo(e.gcState.TrackerStateGc.Ball.Pos.ToVector2())
134+
if ballToPlacementPosDist > e.gameConfig.BallPlacementTolerance {
135+
issues = append(issues, fmt.Sprintf("Ball is %.1fm (>%.1fm) away from placement pos",
136+
ballToPlacementPosDist, e.gameConfig.BallPlacementTolerance))
137+
}
138+
}
139+
if !e.ballSteady() {
140+
issues = append(issues, "Ball position is not steady")
141+
}
142+
if e.currentState.NextCommand == nil {
143+
issues = append(issues, "No next command")
144+
}
145+
return
110146
}
111147

112148
func (e *Engine) penaltyKeeperId() *state.RobotId {
@@ -136,28 +172,6 @@ func (e *Engine) posInsideGoal(pos *geom.Vector2) bool {
136172
return goalArea.IsPointInside(pos)
137173
}
138174

139-
func (e *Engine) readyToContinueFromStop() bool {
140-
radius := e.gameConfig.DistanceToBallInStop + robotRadius - distanceThreshold
141-
if e.gcState.TrackerStateGc.Ball == nil ||
142-
!e.ballSteady() ||
143-
e.robotsInsideRadius(e.gcState.TrackerStateGc.Robots, e.gcState.TrackerStateGc.Ball.Pos.ToVector2(), radius) {
144-
return false
145-
}
146-
return true
147-
}
148-
149-
func (e *Engine) readyToContinueFromHalt() bool {
150-
if e.gcState.TrackerStateGc.Ball == nil ||
151-
e.currentState.PlacementPos == nil ||
152-
!e.ballSteady() ||
153-
e.currentState.PlacementPos.DistanceTo(e.gcState.TrackerStateGc.Ball.Pos.ToVector2()) > e.gameConfig.BallPlacementTolerance ||
154-
e.tooManyRobots(state.Team_BLUE) ||
155-
e.tooManyRobots(state.Team_YELLOW) {
156-
return false
157-
}
158-
return true
159-
}
160-
161175
func (e *Engine) tooManyRobots(team state.Team) bool {
162176
maxAllowed := *e.currentState.TeamState[team.String()].MaxAllowedBots
163177
current := numRobotsOfTeam(e.gcState.TrackerStateGc.Robots, team)

0 commit comments

Comments
 (0)