Skip to content

Commit 3772c44

Browse files
committed
feature: Update and tested remote-control API
1 parent 1bd94a7 commit 3772c44

20 files changed

+555
-222
lines changed

config/engine.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
"BOT_TIPPED_OVER": "BEHAVIOR_ACCEPT",
1818
"BOT_TOO_FAST_IN_STOP": "BEHAVIOR_ACCEPT",
1919
"BOUNDARY_CROSSING": "BEHAVIOR_ACCEPT",
20+
"CHALLENGE_FLAG": "BEHAVIOR_ACCEPT",
2021
"DEFENDER_IN_DEFENSE_AREA": "BEHAVIOR_ACCEPT",
2122
"DEFENDER_TOO_CLOSE_TO_KICK_POINT": "BEHAVIOR_ACCEPT",
23+
"EMERGENCY_STOP": "BEHAVIOR_ACCEPT",
2224
"GOAL": "BEHAVIOR_ACCEPT",
2325
"INVALID_GOAL": "BEHAVIOR_ACCEPT",
2426
"KEEPER_HELD_BALL": "BEHAVIOR_ACCEPT",

internal/app/engine/engine.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ func (e *Engine) filterGameEvent(change *statemachine.Change) *statemachine.Chan
110110
}
111111
case Config_BEHAVIOR_IGNORE:
112112
log.Printf("Ignoring game event: %v", *gameEvent)
113+
case Config_BEHAVIOR_UNKNOWN:
114+
log.Printf("Behavior for event %v unknown", *gameEvent.Type)
113115
}
114116
return nil
115117
}

internal/app/engine/process_emergencystop.go

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,56 @@ package engine
22

33
import (
44
"github.com/RoboCup-SSL/ssl-game-controller/internal/app/state"
5+
"github.com/RoboCup-SSL/ssl-game-controller/internal/app/statemachine"
6+
"time"
57
)
68

79
func (e *Engine) processEmergencyStop() {
8-
if *e.currentState.GameState.Type != state.GameState_RUNNING {
9-
return
10-
}
11-
1210
for _, team := range state.BothTeams() {
13-
emergencyStopSince := e.currentState.TeamInfo(team).RequestsEmergencyStopSince
14-
if emergencyStopSince != nil {
15-
now := e.timeProvider()
16-
if now.Sub(goTime(emergencyStopSince)) > e.gameConfig.EmergencyStopGracePeriod {
17-
eventType := state.GameEvent_EMERGENCY_STOP
18-
e.EnqueueGameEvent(&state.GameEvent{
19-
Type: &eventType,
20-
Event: &state.GameEvent_EmergencyStop_{
21-
EmergencyStop: &state.GameEvent_EmergencyStop{
22-
ByTeam: &team,
11+
if e.emergencyEventPresent(team) {
12+
continue
13+
}
14+
dueIn := e.EmergencyStopDueIn(team)
15+
if dueIn != nil &&
16+
(*e.currentState.GameState.Type != state.GameState_RUNNING || *dueIn <= 0) {
17+
eventType := state.GameEvent_EMERGENCY_STOP
18+
byTeam := team
19+
e.Enqueue(&statemachine.Change{
20+
Origin: &changeOriginEngine,
21+
Change: &statemachine.Change_AddGameEvent{
22+
AddGameEvent: &statemachine.AddGameEvent{
23+
GameEvent: &state.GameEvent{
24+
Type: &eventType,
25+
Event: &state.GameEvent_EmergencyStop_{
26+
EmergencyStop: &state.GameEvent_EmergencyStop{
27+
ByTeam: &byTeam,
28+
},
29+
},
2330
},
2431
},
25-
})
26-
}
32+
},
33+
})
34+
}
35+
}
36+
}
37+
38+
func (e *Engine) EmergencyStopDueIn(team state.Team) *time.Duration {
39+
now := e.timeProvider()
40+
emergencyStopSince := e.currentState.TeamInfo(team).RequestsEmergencyStopSince
41+
if emergencyStopSince == nil {
42+
return nil
43+
}
44+
timeSinceEmergencyStopRequest := now.Sub(goTime(emergencyStopSince))
45+
due := e.gameConfig.EmergencyStopGracePeriod - timeSinceEmergencyStopRequest
46+
return &due
47+
}
48+
49+
func (e *Engine) emergencyEventPresent(team state.Team) bool {
50+
for _, event := range e.currentState.GameEvents {
51+
if *event.Type == state.GameEvent_EMERGENCY_STOP &&
52+
event.ByTeam() == team {
53+
return true
2754
}
2855
}
56+
return false
2957
}

internal/app/engine/proposals.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@ func (e *Engine) EnqueueGameEvent(gameEvent *state.GameEvent) {
1717
}
1818
origin := gameEvent.Origin[0]
1919

20-
autoRefBehavior := e.config.AutoRefConfigs[origin].GameEventBehavior[gameEvent.Type.String()]
20+
var autoRefBehavior AutoRefConfig_Behavior
21+
if config, ok := e.config.AutoRefConfigs[origin]; ok {
22+
autoRefBehavior = config.GameEventBehavior[gameEvent.Type.String()]
23+
} else {
24+
autoRefBehavior = AutoRefConfig_BEHAVIOR_ACCEPT
25+
}
26+
2127
switch autoRefBehavior {
2228
case AutoRefConfig_BEHAVIOR_IGNORE:
2329
log.Printf("Ignoring game event from autoRef: %v", *gameEvent)

internal/app/rcon/server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ func (c *Client) addVerification(reply *ControllerReply) {
139139
}
140140

141141
func (c *Client) Reject(reason string) (reply ControllerReply) {
142-
log.Print("Reject connection: " + reason)
142+
log.Print("Reject request: " + reason)
143143
reply.StatusCode = new(ControllerReply_StatusCode)
144144
*reply.StatusCode = ControllerReply_REJECTED
145145
reply.Reason = new(string)

internal/app/rcon/server_remotecontrol.go

Lines changed: 68 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,10 @@ func (s *RemoteControlServer) handleClientConnection(conn net.Conn) {
109109
continue
110110
}
111111
}
112-
if err := s.processRequest(*client.team, req); err != nil {
112+
if response, err := s.processRequest(*client.team, req); err != nil {
113113
client.reply(client.Reject(err.Error()))
114114
} else {
115-
client.reply(client.Ok())
115+
client.replyWithPayload(client.Ok(), response)
116116
}
117117
}
118118
}
@@ -136,38 +136,60 @@ func (s *RemoteControlServer) SendRequest(teamName string, request ControllerToR
136136
func (c *RemoteControlClient) reply(reply ControllerReply) {
137137
response := ControllerToRemoteControl{ControllerReply: &reply}
138138

139-
teamState := c.gcEngine.CurrentState().TeamState[c.team.String()]
140-
response.Keeper = teamState.Goalkeeper
141-
response.SubstituteBot = timeSet(teamState.RequestsBotSubstitutionSince)
142-
response.EmergencyStop = c.gameEventPresent(state.GameEvent_EMERGENCY_STOP)
143-
response.Timeout = timeSet(teamState.RequestsTimeoutSince)
144-
response.ChallengeFlag = c.gameEventPresent(state.GameEvent_CHALLENGE_FLAG)
145-
146139
if err := sslconn.SendMessage(c.conn, &response); err != nil {
147140
log.Print("Failed to send reply: ", err)
148141
}
149142
}
150143

144+
func (c *RemoteControlClient) replyWithPayload(reply ControllerReply, response *ControllerToRemoteControl) {
145+
if response != nil {
146+
response.ControllerReply = &reply
147+
148+
if err := sslconn.SendMessage(c.conn, response); err != nil {
149+
log.Print("Failed to send reply: ", err)
150+
}
151+
} else {
152+
c.reply(reply)
153+
}
154+
}
155+
151156
func timeSet(t *timestamp.Timestamp) (set *bool) {
152157
set = new(bool)
153158
*set = t != nil
154159
return
155160
}
156161

157-
func (c *RemoteControlClient) gameEventPresent(eventType state.GameEvent_Type) (present *bool) {
162+
func gameEventPresent(events []*state.GameEvent, eventType state.GameEvent_Type, team state.Team) (present *bool) {
158163
present = new(bool)
159-
for _, event := range c.gcEngine.CurrentState().GameEvents {
160-
if *event.Type == eventType && event.ByTeam() == *c.team {
164+
for _, event := range events {
165+
if *event.Type == eventType && event.ByTeam() == team {
161166
*present = true
162167
}
163168
}
164169
return
165170
}
166171

167-
func (s *RemoteControlServer) processRequest(team state.Team, request RemoteControlToController) error {
172+
func (s *RemoteControlServer) processRequest(team state.Team, request RemoteControlToController) (*ControllerToRemoteControl, error) {
168173

169-
if request.GetPing() {
170-
return nil
174+
if request.GetRequest() == RemoteControlToController_PING {
175+
return nil, nil
176+
}
177+
if request.GetRequest() == RemoteControlToController_GET_STATE {
178+
teamState := s.gcEngine.CurrentState().TeamState[team.String()]
179+
emergencyStopDueIn := s.gcEngine.EmergencyStopDueIn(team)
180+
var emergencyStopIn *float32
181+
if emergencyStopDueIn != nil {
182+
emergencyStopIn = new(float32)
183+
*emergencyStopIn = float32(emergencyStopDueIn.Seconds())
184+
}
185+
return &ControllerToRemoteControl{
186+
Keeper: teamState.Goalkeeper,
187+
SubstituteBot: timeSet(teamState.RequestsBotSubstitutionSince),
188+
EmergencyStop: timeSet(teamState.RequestsEmergencyStopSince),
189+
EmergencyStopIn: emergencyStopIn,
190+
Timeout: timeSet(teamState.RequestsTimeoutSince),
191+
ChallengeFlag: gameEventPresent(s.gcEngine.CurrentState().GameEvents, state.GameEvent_CHALLENGE_FLAG, team),
192+
}, nil
171193
}
172194

173195
log.Print("Received request from remote-control: ", proto.MarshalTextString(&request))
@@ -177,7 +199,7 @@ func (s *RemoteControlServer) processRequest(team state.Team, request RemoteCont
177199

178200
if x, ok := request.GetMsg().(*RemoteControlToController_DesiredKeeper); ok && *teamState.Goalkeeper != x.DesiredKeeper {
179201
if err := mayChangeKeeper(s.gcEngine.CurrentGcState(), &teamState); err != nil {
180-
return errors.Wrap(err, "Remote control requests to change keeper, but: ")
202+
return nil, errors.Wrap(err, "Remote control requests to change keeper, but: ")
181203
}
182204
s.updateTeamConfig(team, &statemachine.UpdateTeamState{
183205
Goalkeeper: &x.DesiredKeeper,
@@ -190,7 +212,7 @@ func (s *RemoteControlServer) processRequest(team state.Team, request RemoteCont
190212
RequestsBotSubstitution: &x.SubstituteBot,
191213
})
192214
}
193-
return nil
215+
return nil, nil
194216
}
195217

196218
if x, ok := request.GetMsg().(*RemoteControlToController_Timeout); ok {
@@ -199,51 +221,54 @@ func (s *RemoteControlServer) processRequest(team state.Team, request RemoteCont
199221
RequestsTimeout: &x.Timeout,
200222
})
201223
}
202-
return nil
224+
return nil, nil
203225
}
204226

205-
if x, ok := request.GetMsg().(*RemoteControlToController_ChallengeFlag); ok {
206-
if x.ChallengeFlag {
207-
if *teamState.ChallengeFlags <= 0 {
208-
return errors.New("No more challenge flags left")
209-
} else if *teamState.TimeoutsLeft <= 0 {
210-
return errors.New("No more timeouts left")
211-
}
212-
eventType := state.GameEvent_CHALLENGE_FLAG
213-
s.gcEngine.EnqueueGameEvent(&state.GameEvent{
214-
Type: &eventType,
215-
Event: &state.GameEvent_ChallengeFlag_{
216-
ChallengeFlag: &state.GameEvent_ChallengeFlag{
217-
ByTeam: &team,
218-
},
219-
},
220-
})
227+
if request.GetRequest() == RemoteControlToController_CHALLENGE_FLAG {
228+
if *teamState.ChallengeFlags <= 0 {
229+
return nil, errors.New("No more challenge flags left")
230+
} else if *teamState.TimeoutsLeft <= 0 {
231+
return nil, errors.New("No more timeouts left")
221232
}
222-
return nil
233+
eventType := state.GameEvent_CHALLENGE_FLAG
234+
s.gcEngine.EnqueueGameEvent(&state.GameEvent{
235+
Type: &eventType,
236+
Origin: []string{*origin(team)},
237+
Event: &state.GameEvent_ChallengeFlag_{
238+
ChallengeFlag: &state.GameEvent_ChallengeFlag{
239+
ByTeam: &team,
240+
},
241+
},
242+
})
243+
return nil, nil
223244
}
224245

225246
if x, ok := request.GetMsg().(*RemoteControlToController_EmergencyStop); ok {
226-
if x.EmergencyStop {
227-
if teamState.RequestsEmergencyStopSince != nil {
228-
return errors.Errorf("Emergency stop already requested at %v", *teamState.RequestsEmergencyStopSince)
229-
}
247+
if *currentState.GameState.Type != state.GameState_RUNNING {
248+
return nil, errors.New("Game is not running, can not request emergency stop")
249+
}
250+
if *timeSet(teamState.RequestsEmergencyStopSince) != x.EmergencyStop {
230251
s.updateTeamConfig(team, &statemachine.UpdateTeamState{
231252
RequestsEmergencyStop: &x.EmergencyStop,
232253
})
233254
}
234-
return nil
255+
return nil, nil
235256
}
236257

237-
return nil
258+
return nil, nil
238259
}
239260

240261
func (s *RemoteControlServer) updateTeamConfig(team state.Team, update *statemachine.UpdateTeamState) {
241-
origin := "Remote Control " + team.String()
242262
update.ForTeam = &team
243263
s.gcEngine.Enqueue(&statemachine.Change{
244-
Origin: &origin,
264+
Origin: origin(team),
245265
Change: &statemachine.Change_UpdateTeamState{
246266
UpdateTeamState: update,
247267
},
248268
})
249269
}
270+
271+
func origin(team state.Team) *string {
272+
origin := "Remote Control " + team.String()
273+
return &origin
274+
}

0 commit comments

Comments
 (0)