-
Notifications
You must be signed in to change notification settings - Fork 11
Communication Protocol
The referee box (refbox) is the software component of the RCLL competition tasked with automatic evaluation, monitoring, and control of the game. As such, it provides communication interfaces for referee-side frontends and for the robots of the participating teams. Because of their different usage scenarios, different methods of communication are used.
For referee-side frontends, typically a stable connection between the actual refbox and a frontend-client is assumed. Functionality provided by these interfaces allow full control of an appropriately configured refbox. These include setting the teams, switching phases, manually adding points and confirming deliveries.
For robots, the refbox is the single point of communication outside of team-internal communication. It provides all essential game information (i.e. ground truths for machine positions, game time, game phase, orders, machine configurations) and is the single point of instruction for all the machines on the field. Additionally, robots need to transmit beacon signals periodically to the refbox. Because of potentially unstable wifi setups in competition environments, a stable connection can not be assumed for robot <-> refbox communication.
Two different protocols are provided for refbox interaction. A Google protocol buffers based protocol is used for the robot <-> refbox communication. A simple web socket based protocol using JSON for data formatting can be used to implement frontend applications.
This section covers all information required to setup the communication between a robot and the referee box, hence it focuses on the protobuf interface of the refbox.
In order to establish a protobuf connection with the refbox, we recommend to check out the java library TODO or the C++ library protobuf-comm. The C++ tools of the refbox uses protobuf-comm and may may be a useful starting point to see how a protobuf connection with the refbox can be established, such that messages can be sent and received.
It is essential to match the peer configuration (used ports, broadcast addresses as well as the team-specific crypto-key) with the configuration of the refbox and to adapt the configuration as needed.
The refbox sends all relevant information out periodically with high frequency. Exact frequencies vary by message type, exact information can be found here.
Via the public channel it sends:
- Beacon Signals to indicate that the connection is alive
- Game State information, including the assignment between the team name and the team color, scores for each team and general information about game time, phase and state.
- Robot Info which is useful in order to get notified when a robot is put into maintenance. Note that pose information from robots is not published by the refbox.
- Order Info containing all orders that are active (only sent in PRODUCTION phase).
- Version Info contains information about the refbox and the started setup. Is only sent a few times whenever a new robot connects.
Via the team channel it sends:
- Machine Info for each machine in the own team. It provides the names, machine types, available ring colors (for ring stations) and (if exploration stage is over) the position of the machine (pose, zone, rotation). Other information defined in that message is not provided to the teams.
- Ring Info regarding the payments necessary for each ring color.
- Machine Report Info to provide feedback about reported machines during exploration.
And for the Challenge Track:
The refbox expects to receive:
- Beacon Signals for each robot. Optionally, a pose can be included which may be useful for frontends and visualization tools
- Prepare Machine messages whenever a machine should be prepared. The Machine Info sent by the refbox will include the changed state of the machine once the message has been processed.
- Reset Machine messages whenever a machine should be manually set to broken in order to reset its default state.
This method is used for robot <-> refbox interactions. In the following, the basic structure of messages and data transfer are explained.
Protocol Buffers (protobuf) are a data format used for serialisation of structured message data. The format is extensible and provides for basic data types, nesting, structure re-use, efficient serialization and deserialization, and variable-length lists. The message types are defined in a special definition language akin to C/C++ structs. In order to easily serialize and deserialize data in the protobuf format, special compilers are provided. These take the protobuf message definition and automatically create code for creating and reading messages in the provided protobuf definitions in common languages like C++, Java or Python. The protobuf definitions for all messages that can be used for communication with the refbox are part of this repository). Please refer to the official Google protobuf documentation for a more detailed description of the protobuf data format.
Since serialized protobuf message do not contain information about the message length or type, or additional space for additional meta data like encryption-related information, a framing protocol is used which wraps the serialized protobuf messages and allows for easier handling of the messages on the receiver's side. The protocol consists of two parts, a protocol frame which contains the message-related meta data and a message header.
Each message that is sent over the network is prepended by the headers. The receiver can use the definition of the header and the information contained within to read the following serialized protobuf message correctly.
Header messages must be 4-byte-aligned, i.e. the addresses of the data entries is evenly divisible by 4. The size of the frame header message structure sums up to exactly eight bytes when sent over the network, the message header will be exactly four bytes. All contained numbers must be encoded in network byte order (big endian, most significant bit first). The numbers are encoded as 8 (uint8 t), 16 (uint16 t) or 32 bit (uint32 t) unsigned integers respectively. When sending a message over the network, first the protobuf message is serialized (to determine the payload size). Then the frame and message headers are prepared with the appropriate component ID, message type, and the payload size as just determined. Then the frame header is sent, possibly followed by an encryption IV, again followed by the message header and the serialized message. Examples of the message layout are provided in the following two figures:
Figure 1: Packet layout diagram for unencrypted messages.
Figure 2: Packet layout diagram for encrypted messages.
The frame header corresponds to the following C++ struct:
typedef struct {
/// Frame header version
uint8_t header_version ;
/// One of PB_ENCRYPTION_ *
uint8_t cipher ;
/// reserved for future use
uint8_t reserved_2 ;
/// reserved for future use
uint8_t reserved_3 ;
/// payload size in bytes
/// includes message and
/// header , _not_ IV
uint32_t payload_size ;
} frame_header_t ;
The following fields are contained:
- protocol version: The version of the protocol. The current protocol version is 2
- cipher: Indicates the cipher suite that is used. The following values can be used:
Cypher | Byte | initialization vector size / Bytes |
---|---|---|
NONE | 0x00 | 0 |
AES_128_ECB | 0x01 | 0 |
AES_128_CBC | 0x02 | 16 |
AES_256_ECB | 0x03 | 0 |
AES_256_CBC | 0x04 | 16 |
- reserved: Currently unused for future extensions. Bytes must be set to 0.
- payload size: Size in bytes of the following payload. This does include the message header and the serialized protobuf message. It does not include an encryption IV header (if required by cipher). The payload size must be encoded in network byte order (big-endian). The fields must be contained in the given sizes and order but do not need to be implemented as a C++ struct.
The message header corresponds to the following C++ struct:
typedef struct {
/// component id ;
uint16_t component_id ;
/// message type
uint16_t msg_type ;
} message_header_t;
The following fields are contained:
- component ID: General ID, general addressee of message. For refbox message must be set to 2000 (as encoded in the protobuf messages’ COMP ID field of the CompType enum. If you use the refbox framing protocol for your own messages, choose a component ID different from the refbox ID. The component ID must be encoded in network byte order (big-endian).
- message type: Numeric message ID of the specific message serialized in the payload. Must be the ID encoded in the MSG TYPE field of the CompType enum. The message type is specific to the component ID. Different component IDs can have message of the same message type which are unrelated. The message type must be encoded in network byte order (big-endian).
The encryption currently implemented is intended to serve as a basic protection layer in particular to prevent accidental transmission of messages of the wrong team. For example, we do not insist on a time stamp within the encrypted part of the messages which would aid against replay attacks. This is done to avoid the need for time synchronization between the robots and the refbox. This might be added at a later point in time.
The framing protocol supports per-message encryption based on a symmetric block cipher. For now, the supported encryption modes are based on the AES2 with either 128 or 256 bit key length in either electronic code book (ECB) or cipher block chaining (CBC) mode. For the tournament, the referee box will be configured to use the AES-128-CBC mode. This means that there will be a 16 byte initialization vector (IV) which is used to generate different encrypted messages for the same input (as long as different IVs are provided).
The protobuf_comm library (standalone version) handles this transparently for you. All you need to do is to setup encryption on the team channel broadcast peer (see Section Communication Modes). Should you choose to create your own implementation, please still take protobuf comm’s BufferEncryptor and BufferDecryptor classes for reference. The IV must be different for each transmitted message.
Encryption on the team channels should be configured only if the refbox announced the respective team name for one of the two colors. Teams may never send messages on a private team channel if it is configured for a team different than their own.
The recommended flow for setting up encryption is like this:
- Listen to public channel for GameState messages
- If the own team name is received as the cyan or magenta team name in the GameState message, setup encryption on the respective channel
- Send messages on the team channel, never send messages on a channel of another team
An overview of the format of an encrypted message is given in the second figure above, contrasting the first figure which depicts an unencrypted message. It is similar to the unencrypted packet with two key differences. First, the initialization vector is placed between the frame and message headers. And second, the message header and protobuf payload are encrypted.
The refbox uses two communication modes. A TCP-connection-based streaming mode is used for communication between the refbox and controllers like the shell or GUI, because of the expected reliable (wired or same device) communication.
For robot<->refbox communication, which is realised wirelessly through WiFi, different considerations need to be made. Since WiFi is inherently unreliably, in particular during a RoboCup competition, connections can be lost at any time. In particular on a busy wireless network a TCP handshake can mean a high performance penalty, or can even mean reliable communication fails due to frequent re-transmissions. Therefore, for communication with the robots a UDP-based protocol was chosen. For now, we use broadcasting to communicate the information to all robots at once. In the future, this might be extended to Multicast.
Broadcast-based communication is further split up into three communication groups: public, team cyan, and team magenta. Generally, teams should only send on their private team channel and listen to both, the team and the public channel. The refbox will send its beacon signal and the game state on the public channel, as it is the same for both teams. Other messages like order information or exploration info is sent per team. The exact assignment is specified in the message descriptions.
Figure 3: Communication channels and groups for the refbox.
The refbox differentiates a total of four communication groups. These are visualized in Figure 3. Each team needs to open two and only two broadcast peer communication channels during the game. The four groups are:
- stream: The refbox accepts stream client connections on TCP port 4444. During the tournament, connections will most likely only be allowed from the local or selected hosts. Neither a robot nor any other team’s device may use the stream protocol to communicate with the refbox.
- public: The public broadcast channel is established on UDP port 4444. Teams may only listen to this channel, but never send.
- team channels: There are two team channels on UDP ports 4441 (cyan) and 4442 (magenta). Each channel will be encrypted with a team-specific encryption key that is created and provided to the teams at the beginning of the tournament (and might be re-configured later should the need arise). It is used for the private communication between the teams and the referee box.
While protobufs are a common and well established method for network communication in languages like C++, they are not the preferred technology in web development. The RCLL refbox frontend (which was developed with support from a grant provided by the RoboCup federation) had the following requirements for communication: web-native method, assumed stable connection (potentially same device), easy extendability and no unnecessary framing overhead.
The decision was made to use websockets as the method of communication and to use the JSON format (which is native to JavaScript) as the format for the data. Because of the assumed stable connection and small size, message are sent and received as one packet.
This communication method can be used to send instructions to the refbox to control the game and to receive information about the game which can be used for different visualization applications.
Websockets are a simple way of establishing a TCP-based socket connection through HTTP. They are an extension of normal HTTP requests that allow persistent connections of a web application with a server and thus can be viewed as a form of successor to REST and other non-persistent communication methods previously used in the development of web applications.
JSON is the native format of JavaScript for describing dictionary-like data structures. It specifically refers to the serialized plain-text representation of such objects which have become a common standard for simple data exchange protocols thanks to the wide support and human-readable format. Schemas can be used to define and validate JSON messages.
The message definitions (schemas) for all available messages can be found in the refbox repository (see message schemas).
No particular protocol is used for the websocket communication mode. The websocket communication method needs to be activated in the settings. Once the refbox starts, clients can connect to the specified port. Once they are connected they will receive updates from the refbox. First a set of semi-constant messages are sent, then regular updates will be sent. Instructions can be sent from clients directly after connection.
Messages are expected to be sent as one packet and received as such. To provide further error handling, messages can be received line-wise until a JSON object can be deserialized. The syntactic structure of JSON indicates the end of an object.
Two communication modes exist defined by the sending side. Messages that the refbox sends out represent the current state of the game and associated information. Messages that a client can send are instructions to the refbox. These are the only possible forms of communication using the websocket interface. No robot<->refbox communication through this method is supported.
The refbox sends the same messages to all connected clients. No special types of clients are acknowledged in terms of data that is sent out. Data packages coming from the refbox are dealt in a send-and-forget way. That means once the message is sent out, it is not known on the refbox side anymore. There is no need or way to acknowledge any of the incoming messages. This approach is used because data is sent out periodically with a high frequency. That means that in the unlikely event of data loss (given the envisioned usage scenario), the same or updated data will be sent out again after a short timespan.
Certain constant or semi-constant information is sent at once to a newly connected client once the connection was established. This includes the current information on the current state of the game (including points and point history, team names, and game phase), machine information and order information. Please refer to the code for examples and definitions of the messages.
Clients can send commands to the refbox to control the state of the game after establishing the websocket connection. The commands are in JSON format and are sent as plain text just like information that comes from the refbox. Any valid command message can be sent at any given time, but the correct behavior of the refbox can only be guaranteed for valid commands given its current state. The following instructions are possible:
- set game phase
- set game state
- set team name magenta/cyan
- randomize field
- add points manually
- start/pause game
- set bots to maintenance
Sending instructions to the refbox is currently unprotected. That means that any connected client can send instructions to the refbox. However, it is planned to use a simple on-connection password authentication in the future to restrict access to control functionality.
Usage
Documentation
Tutorials