Note: Apparently my understanding of Socket.IO was a bit wrong. The analogy to Discord is wrong. But the general idea still holds. Please re-read the idea section if you have read it before.
AggregateBotState
StageState
Socket.io allows event-based bi-directional communication between server and clients. Servers and clients can send arbitrary JSONable objects on a given event channel.
// Server side
server.emit(eventName, object) // Broadcasts object to all clients
server.on("connection", (client) => {
// Handle client sending events
client.on(eventName, (obj)=>{
console.log(`${client.id} sent ${obj}`)
}
});
// Client side
client.emit(eventName, object) // Send to server. **Peers will NOT see this!**
client.on(eventName, (obj)=>{console.log(obj)}); // To listen
As seen from above, clients sending an event will only notify the server, so it is the serverâs role to rebroadcast whateverâs sent to the other clients. There are more ways to send messages server side (e.g., sending a message to everyone but a client, sending to only one client), please refer to this.
Our server will create two states that needs to be shared across clients:
/bot_state
- Will be used to synchronise one big state object, with bot IDs being keys, and the state of each bot being the value/stage_state
- Will synchronise an object describing the state of the stageA dumb way to be to send the full state of the system to all clients every time something changes. But this is inefficient as a lot of the data may be unchanged. Instead, we can send partial updates to the state, and the clients can combine the old state with the new partial update to get the new state.
However, for people just joining the channel, they will not have the old state. So when a new client joins, we will send the full state to them.
StageState
will be an actual object controlled by the bridge, and updates are only sent by the bridge.
AggregateBotState
is an object with bot IDs as keys. Initially, the AggregateBotState
will be empty, but as bots connect, they will send their partial state to the bridge (their key and value), which will add it to the AggregateBotState
.
AggregateBotState
, as each bot can aggregate the information on the channel itself! The advantage is that Socket.io can utilise P2P connections (though seemingly through an unmaintained package) to reduce the load on the bridge and reduce latency, which is crucial for robots.AggregateBotState
as a cache and source of truth, but it is not necessary.Additionally, we create two more channels for sending commands:
/bot_command
- For sending low level commands to particular bots (think "move to pose", "stop", etc.). Socket.io also allows for DM'ing on channels, so we can limit the commands to specific bots. Only the bridge should send messages to this channel./stage_command
- For sending high level / stage-level commands to the bridge (think "capture preset for the entire stage", "use a preset", "stop all robots", etc.). The web clients should send messages to this channel, and the bridge will send the appropriate commands to the bots./bot_state
/bot_command
/bot_state
to perform collision avoidance/stage_state
to know where to go and get stage boundaries/bot_state
and /stage_state
for visualization on the UI/stage_command
through the UI/stage_command
, keep the necessary state (i.e., saving bot positions for presets, keeping the stage boundary, etc.)