Game Controller Protocol¶
This page describes the layers that deliver and decode the game state protocol to and from the field. This protocol is partly bidirectional — teams may optionally talk back to the Game Controller to request a keeper change, a timeout, or a substitution.
League Software¶
There is one piece of league maintained software that manages game state and produces this protocol:
If you’re actively trying to connect to a field, you’ll need to make sure it’s running. Automatic referee implementations are separate, optional software that talk to the Game Controller over the same protocol described below — see the referee protocol page for how their filtered game state gets used.
Transport¶
A team is never required to reply to the Game Controller. Teams can and do play full matches only receiving game state. The Game Controller talks to teams two ways: a one-way broadcast every team should listen to, and an optional two-way TCP connection only needed if a team wants to actively request something.
Referee Broadcast¶
The Game Controller publishes overall game state (stage, command, scores, cards) as a one-way UDP multicast stream. The
league defines this multicast group as having an address of 224.5.23.1 at port 10003. You join a multicast group
just like you connect to any IP address and port combo, though you may need to pass some additional options when binding
the socket.
---
config:
layout: elk
elk:
nodePlacementStrategy: NETWORK_SIMPLEX
---
flowchart TD
Team["Team Client<br/>IGMP join only"] -- "IGMP Join<br/>224.5.23.1:10003" --> Net["Switch / Router<br/>duplicates stream"]
GC["Game Controller"] -- "Referee<br/>UDP multicast, continuous, no ack" --> Net
Net -- "Referee" --> Team
classDef purple fill:#faf5ff,stroke:#9333ea,color:#581c87;
classDef cyan fill:#ecfeff,stroke:#0891b2,color:#164e63;
classDef gray fill:#f1f5f9,stroke:#64748b,color:#1e293b;
class Team purple;
class GC cyan;
class Net gray;
Once you’ve joined, you should expect to receive a Referee packet on a regular interval, independent of any camera
framerate. Do not assume the game is running the current command until you’ve received a Referee packet saying so.
Field data delivery is not guaranteed here either — a dropped packet is not re-transmitted, and packet loss should be
well below 1%.
%%{init: {"sequence": {"useMaxWidth": false, "actorMargin": 220, "messageMargin": 40}}}%%
sequenceDiagram
participant Team as Team Client
participant Net as Switch / Router<br/>(multicast group 224.5.23.1:10003)
participant GC as Game Controller
Team->>Net: IGMP Join 224.5.23.1:10003
Note over Team,GC: No handshake — Team is now another multicast receiver
GC->>Net: Referee (stage, command, scores)
Net->>Team: Referee (stage, command, scores)
GC->>Net: Referee
Net--xTeam: Referee — dropped
Note over Team: No retransmission — team just waits for the next packet
GC->>Net: Referee
Net->>Team: Referee
Remote Control “rcon” Channels (Optional)¶
If a team’s software/AI wants to request a keeper change, respond to an advantage choice, or request a substitution, it opens a TCP connection to the Game Controller and registers. Again, many of these functions can be done by the human robot handler and physical remote control provided by the event organizer/field. There are three separate rcon channels, each on its own port: one for teams, one for autoRefs, and one for physical remote controls. Registration and signing are described in ssl_gc_rcon.proto; signatures are optional and only needed for secure/verified communication.
Unlike the broadcast channel, opening a TCP connection requires knowing the Game Controller’s actual IP. You don’t
need to guess this or hardcode a hostname — read it off the
source address field of the IP packets carrying the Referee
broadcast you’re already receiving. Whatever machine that traffic comes from is the Game Controller.
%%{init: {"sequence": {"useMaxWidth": false, "actorMargin": 220, "messageMargin": 40}}}%%
sequenceDiagram
participant Team as Team Client
participant GC as Game Controller
Team->>GC: TCP connect :10008 (or :10108 for TLS)
Team->>GC: TeamRegistration (team_name[, signature])
GC->>Team: ControllerReply (status_code=OK, next_token)
Note over Team,GC: Connection stays open — one registration, then repeated exchanges.<br/>next_token must be echoed back in the next Signature if using secure comms.
Team->>GC: TeamToController (ping)
GC->>Team: ControllerToTeam (controller_reply)
Team->>GC: TeamToController (desired_keeper)
GC->>Team: ControllerToTeam (controller_reply)
The connection stays open — registration happens once, then the team sends further requests and receives replies over
the same socket for as long as it stays connected. If a team never connects, it simply never receives a
ControllerReply and never gets to make requests; the game continues based on the referee’s broadcast state alone.
Connections Table¶
The following table contains connection information for the broadcast channel and the team/remote-control rcon channels. AutoRef connections use the same rcon flow but are documented on the referee protocol page instead, alongside the rest of the autoRef-specific content.
Protocol |
Protobuf |
Type |
Address |
Port |
|---|---|---|---|---|
SSL-Game-Controller (GC) |
UDP Multicast |
224.5.23.1 |
10003 |
|
Team -> GC |
TCP |
GC |
10008 |
|
Team -> GC |
TCP + SSL |
GC |
10108 |
|
Remote Control -> GC |
TCP |
GC |
10011 |
|
Remote Control -> GC |
TCP + SSL |
GC |
10111 |
Message Format¶
The league uses google protobuf to define the data format for this protocol too. The interface
definitions are in the same league protobuf repository used for
vision. The image below shows the hierarchy of the broadcast Referee message — the one every team decodes, whether or
not it ever opens an rcon connection.
---
config:
layout: elk
elk:
nodePlacementStrategy: NETWORK_SIMPLEX
---
flowchart TD
Referee["Referee<br/>one packet per broadcast"]
Referee --> Stage["stage, command,<br/>packet_timestamp"]
Referee --> Yellow["yellow<br/>Referee.TeamInfo"]
Referee --> Blue["blue<br/>Referee.TeamInfo"]
Referee --> Pos["designated_position<br/>Referee.Point"]
Referee --> Events["game_events[]<br/>GameEvent"]
Referee --> Proposals["game_event_proposals[]<br/>GameEventProposalGroup"]
classDef slate fill:#f8fafc,stroke:#475569,color:#0f172a;
classDef cyan fill:#ecfeff,stroke:#0891b2,color:#164e63;
classDef purple fill:#faf5ff,stroke:#9333ea,color:#581c87;
classDef amber fill:#fffbeb,stroke:#d97706,color:#78350f;
class Referee slate;
class Stage cyan;
class Yellow,Blue purple;
class Pos,Events,Proposals amber;
Referee is the single top level structure sent on the broadcast channel. It carries the coarse game stage and
fine-grained command teams must obey, a Referee.TeamInfo for each of yellow and blue (score, cards, timeouts,
keeper id), an optional designated_position for ball placement, and any game_events/game_event_proposals the
active autoRef has reported.
The table below contains links to the specific proto files needed to decode the broadcast message and the three rcon channels. It’s recommended you include the entire ssl-protocol-defs repository as a submodule in your code, rather than copying the files directly.
Message |
Proto File |
|---|---|
Referee, Referee.TeamInfo, Referee.Point |
|
GameEvent, GameEventProposalGroup |
|
ControllerReply, Signature |
|
TeamRegistration, TeamToController, ControllerToTeam |
|
AutoRefRegistration, AutoRefToController, ControllerToAutoRef |
|
RemoteControlRegistration, RemoteControlToController, ControllerToRemoteControl, RemoteControlTeamState |
|
Team, RobotId, Division |
Team Sides¶
This protocol shares its coordinate frame and units with the vision protocol — see
vision’s coordinate system for the full breakdown (mm, radians, CCW from +X). The only
game-controller-specific piece is blue_team_on_positive_half, which tells you which side of the field’s +X axis the
blue team currently defends. This flips between halves — do not hardcode a side. designated_position (used for
ball placement) is a Referee.Point in the same field frame.
Registration Channels¶
The Game Controller’s rcon interface is split into three independent TCP channels — team, autoRef, and remote control — each on its own port, each with its own registration message and message types. This means if your software wants to act as more than one role (for example, a team client that is also a remote control), it needs a separate TCP connection and registration per role; they are not multiplexed over one socket.
The referee protocol page documents how teams can use the game_events an automatic referee reports
over this protocol.
Network Flow¶
The diagram below is the same competition network fan-out shown in the
field network documentation, with the machines involved in the game controller
protocol highlighted and the vision-only machines (cameras, Truss NUC, Vision Computer) muted. The Game Controller
publishes the 224.5.23.1:10003 broadcast and serves the three rcon channels; team PCs, remotes, the status board, and
the officiating/broadcast machines that read referee state all consume it. The router and switch are highlighted too —
they maintain the multicast group and carry the rcon TCP connections.