# Day 2: Communications (Whiteboard)
## Understanding Nested Publish/Subscribe
Three-layer:
- interthread: within a process
- interprocess: within a vehicle (ZeroMQ)
- intervehicle: within a squadron or cluster of vehicles
### Interprocess
- A single publisher
- A single subscriber
```mermaid
graph TB
publisher-->subscriber
```
In Goby3 interprocess:
```mermaid
graph TB
publisher-->gobyd-->subscriber
```
```mermaid
graph TB
publisher1-->subscriber1a & subscriber1b
publisher2-->subscriber2
```
less frequently:
```mermaid
graph TB
publisher1a & publisher1b --> subscriber1a & subscriber1b
```
All of these topologies are supported in Goby.
## Hands-on with one publisher / one subscriber in Goby3
### Interprocess
Copied the single thread pattern into two new binaries: goby3_course_interprocess_publisher/subscriber
#### Qualifying a publication in Goby
To publish in Goby:
- *layer*: interprocess
- *group*: similar to LCM *channel*, ROS *topic* or MOOS *variable*
- marshalling *scheme*: (Protobuf)
- data *type*. (Protobuf == Message ==> C++ Class : public google::protobuf::Message)
We still to decide on only two things now:
- *group*
- *type* (or Message)
GPSPosition -> `groups::gps1` and `groups::gps2`.
GPSDiagnostics -> `groups::gps1` and `groups::gps2`.
Publications on a particular layer are automatically published to all inner layers.
#### Anatomy of a goby::middleware::Group
Group
- thought of as a "union" of a string/integer (uint8_t).
- high bandwidth layers (interthread / interprocess): string + integer is used: "goby3_course::usv_nav;1"
- low bandwidth (intervehicle): integer is used.
Some examples:
```cpp
using goby::middleware::Group;
// valid for interprocess and interthread
constexpr Group foo1{"foo"};
// valid for all three of the layers: "foo;2", 2
constexpr Group foo2{"foo", 2};
// valid for all three layers: "3", 3
constexpr Group bar{3};
// bar == bar2 on intervehicle but not on interprocess/interthread
constexpr Group bar2{"bar", 3};
// 0 == "broadcast_group" ~= "no group"
constexpr Group bar_groupless{"bar", Group::broadcast_group};
```
Let's say we want send the vehicle's health.
Created a group `health_status`.
### Create a Protobuf message
Create a HealthStatus message.
### Add messages to Publisher code
Send our health status at 1 Hz.
### Add subscriber
Lambdas expressions.
```mermaid
graph TB
goby3_course_interprocess1_publisher -->|HealthStatus| goby3_course_interprocess1_subscriber
```
### Interthread
Convert the interprocess pair of applications into a single standalone process (application) with two threads.
MultiThreadApplication
- thread type is goby::middleware::Thread -> goby::middleware::SimpleThread (3-layer).
-`loop()` method
- `interthread()`, `interprocess()`, and `intervehicle()`
- configuration may differ from the parent application
```mermaid
graph TB
subgraph goby3_course_interthread1
Publisher -->|HealthStatus| Subscriber
end
```
### Cross layer: Interthread & Interprocess
```mermaid
graph TB
subgraph goby3_course_interthread1
Publisher --> Subscriber
end
Publisher-->goby3_course_interprocess1_subscriber
```
### Intervehicle
"Slow links": <= 1 Mbps, often much much less: acoustic modems, satcomms, etc.
```mermaid
graph TB
subgraph intervehicle / Goby Acomms
buffer[Dynamic Buffer]
dccl[DCCL]
amac1[AMAC, link 1]
driver1[Modem Driver, link1]
amac2[AMAC, link N]
driver2[Modem Driver, link N]
dccl-->buffer
buffer-->driver1
driver1-->buffer
amac1-->driver1
buffer-->driver2
driver2-->buffer
amac2-->driver2
end
```
### DCCL
libdccl.org
DCCL1 == XML definition
DCCL2+ == Protobuf definition
(DCCL3 is current version).
Protobuf (vanilla):
```protobuf
syntax="proto2";
message NavigationReport {
required double x = 1;
required double y = 2;
required double z = 3;
enum VehicleClass { AUV = 1; USV = 2; SHIP = 3; }
optional VehicleClass veh_class = 4;
optional bool battery_ok = 5;
}
```
DCCL:
```protobuf
syntax="proto2";
import "dccl/option_extensions.proto";
message NavigationReport {
option (dccl.msg) = { codec_version: 3
id: 124
max_bytes: 32
}
required double x = 1 [(dccl.field) = { min: -10000 max: 10000 precision: 1 }];
required double y = 2 [(dccl.field) = { min: -10000 max: 10000 precision: 1 }];
required double z = 3 [(dccl.field) = { min: -5000 max: 0 precision: 0 }];
enum VehicleClass { AUV = 1; USV = 2; SHIP = 3; }
optional VehicleClass veh_class = 4;
optional bool battery_ok = 5;
}
```
#### Setting up gobyd's InterVehiclePortal
Created some configuration directories.
Pick a driver: UDPMulticastDriver: UDP multicast
#### Subscription forwarding
(Note text aligns with arrows beneath)
```mermaid
sequenceDiagram
publisher->>publisher: data1
publisher->>publisher: data2
subscriber->>publisher: subscription message
publisher->>subscriber: data3
publisher->>subscriber: data4
```
```mermaid
graph TB
subgraph veh1
goby3_course_intervehicle1_publisher
end
subgraph veh2
goby3_course_intervehicle1_subscriber
end
goby3_course_intervehicle1_publisher-->goby3_course_intervehicle1_subscriber
```
#### Dynamic Buffer
Goby3 buffer is a priority queue:
- base priority value
- time sensitive priority (ttl)
Assume we have three messages type (1,2,3):
- 1: base value 1 and ttl: 1000 seconds ("vehicle status")
- 2: base value 2 and ttl: 2000 seconds ("sensor data")
- 3: base value 1 and ttl: 3000 seconds ("debug engineering data" or "health status IF good or nominal")

```protobuf
message DynamicBufferConfig
{
optional bool ack_required = 2 [default = false];
// lowest value takes precedence
optional double blackout_time = 3 [
default = 0,
(dccl.field) =
{min: 0 max: 3600 precision: 0 units {base_dimensions: "T"}}
];
// larger value takes precedence
optional uint32 max_queue = 4
[default = 1000, (dccl.field) = {min: 1 max: 1000}];
// true takes precedence over false
optional bool newest_first = 5 [default = true];
// use average of values
optional double ttl = 6 [
default = 1800,
(dccl.field) =
{min: 1 max: 86400 precision: 0 units {base_dimensions: "T"}}
];
// use average of values
optional double value_base = 7
[default = 100, (dccl.field) = {min: 1 max: 1000 precision: 0}];
}
```
#### Modem Drivers
There are 8 drivers in the open source project (Goby3):
- WHOI Micro-Modem (v1, v2)
- Iridium 9523 and similar (RUDICS/SBD)
- Iridium RUDICS and DirectIP shore-side connections
- Benthos ATM900 Modems
- delResearch Popoto Modem
- UDP Point-to-point
- UDP Multicast (using now)
- ABC Driver (demo for writing new drivers)
https://github.com/GobySoft/goby3/pulls
(If contributing your own driver) Please don't worry if it's not "finished".
## Returning to the Trail example
N AUVs trailing 1 USV communicates to a topside (ship, shore station).
```mermaid
graph TD
auv0-->|"auv_nav;2"|usv
auv1-->|"auv_nav;2"|usv
auvN-->|"auv_nav;2"|usv
usv-->|"usv_nav;1"|auv0
usv-->|"usv_nav;1"|auv1
usv-->|"usv_nav;1"|auvN
usv==>|"usv_nav;1"|topside
usv==>|"auv_nav;2"|topside
```
Groups: `auv_nav;2`, `usv_nav;1`.
Message type: `Navigation Report`
1. goby3_course_auv_manager
1. goby3_course_usv_manager
1. goby3_course_topside_manager
```mermaid
graph TD
subgraph auvN
auvm[goby3_course_auv_manager]
end
subgraph usv
usvm[goby3_course_usv_manager]
end
subgraph topside
topsidem[goby3_course_topside_manager]
end
auvm-->|"auv_nav;2"|usvm-->|"usv_nav;1"|topsidem
usvm-->|"auv_nav;2"|topsidem
usvm-->|"usv_nav;1"|auvm
```
---
```
```