---
# System prepended metadata

title: 'Day 3: Autonomy (Whiteboard)'

---

# Day 3: Autonomy (Whiteboard)

## Hands-on with goby_frontseat_interface

Publish/subscribe API:
- `data_from_frontseat`: data from frontseat -> backseat (payload). Could also include other data (sensor feeds)
- `desired_course`: usually desired heading, speed, depth, etc.
- `helm_state`: DRIVE or PARK
- `node_status`: convenience republish of the node_status field in `data_from_frontseat`
- `raw_in/raw_out`: The raw stream to/from the frontseat (NMEA-0183, binary protocol, "NMEA-0183")
- `status`: The states of the three subsystems.

### Basic Simulator driver

Each driver is an implementation of a base class: `goby::middleware::frontseat::InterfaceBase` 

Each driver must implement six virtual methods:

- `send_command_to_frontseat`: called when the interface receives an outgoing command (often desired course)
- `send_data_to_frontseat`: often nothing, sensor data connected to the payload that are needed by the frontseat
- `send_raw_to_frontseat`: for "backdoor" feature to send raw messages from other processes
- `frontseat_state()`: the driver must provide its understanding of the frontseat state
- `frontseat_providing_data()`: true if the frontseat is streaming "normal" data.
- `loop()`: analogous to the loop() in the Application: 10 Hz.

In response, the driver has to call 4 signals:

- `signal_command_response`: called when we get an ACK from the frontseat.
- `signal_data_from_frontseat`: called when we get data from the frontseat (node_status, nav data)
- `signal_raw_from/to_frontseat`: called with the raw message received/sent by the driver

`goby_basic_frontseat_simulator`: standalone C++ application w/ very simple dynamic simulator with an ASCII payload API:


```
> means message from goby_frontseat_interface (backseat) to goby_basic_frontseat_simulator (frontseat)
< means message from goby_basic_frontseat_simulator (frontseat) to goby_frontseat_interface (backseat)

- goby_basic_frontseat_simulator runs a TCP server.
- all messages are "\r\n" terminated

1. simulator init message
(duration = 0 means no timeout)
(duration, freq, accel, hdg_rate, z_rate, warp are optional)
FREQ = control loop frequency in hertz
ACCEL = vehicle acceleration in m/s
HDG_RATE = vehicle turn rate in deg/s
Z_RATE = vehicle dive rate in m/s
WARP = run this factor faster than real time
> START,LAT:42.1234,LON:-72,DURATION:600,FREQ:10,ACCEL:0.5,HDG_RATE:45,Z_RATE:1,WARP:1

2. frontseat state messages
  sent after successful START command
< CTRL,STATE:PAYLOAD 
  sent after DURATION is up in START command
< CTRL,STATE:IDLE

3. frontseat nav command
  generated from primitive dynamics model
< NAV,LAT:42.1234,LON:-72.5435,DEPTH:200,HEADING:223,SPEED:1.4

4. backseat desired course command
> CMD,HEADING:260,SPEED:1.5,DEPTH:100

5. frontseat response to backseat CMD
  CMD is good
< CMD,RESULT:OK
  error in the CMD
< CMD,RESULT:ERROR
```

![](https://i.imgur.com/7lOFwMM.png)

### Running the frontseat interface

`goby_frontseat_interface` must have a driver

Plugin model:
```mermaid
flowchart TD
  basic_simulator_frontseat_driver.h & basic_simulator_frontseat_driver.cpp -->|compiler|libgoby_frontseat_basic_simulator.so
  libgoby_frontseat_basic_simulator.so -->|dlopen, runtime, from FRONTSEAT_DRIVER_LIBRARY| goby_frontseat_interface
```

## Goby / MOOS interface

`pHelmIvP`
- multi-objective (heading, speed, depth) behavior-based (plugin api for writing new behaviors: "follow waypoints", "avoid collisions", "trail another vehicle", "your own") decision engine (MOOS-IvP).
- MOOS application

So we need a "bridge" between MOOS and Goby


### goby::moos::Translator

- `goby::moos::Translator`  (actually a typedef for `BasicTranslator<goby::middleware::SimpleThread>`)
    - goby Thread (interthread/interprocess comms)
    - `CMOOSCommClient`: MOOS "interprocess" client

```mermaid
flowchart TD
   subgraph goby_moos_gateway or other MultiThreadApplication
   subgraph Translator
      CMOOSCommClient
      CMOOSCommClient <-->|your code| SimpleThread 
      SimpleThread
   end
   end
   CMOOSCommClient <--> MOOSDB
   pHelmIvP <--> MOOSDB
   SimpleThread <--> gobyd
   goby_app1 <--> gobyd
   goby_app2 <--> gobyd
```

You can have multiple Translators


```mermaid
flowchart TD
   subgraph goby_moos_gateway or other MultiThreadApplication
   subgraph FrontSeatTranslator
      CMOOSCommClient1[CMOOSCommClient]
      CMOOSCommClient1 <-->|your code| SimpleThread1
      SimpleThread1[SimpleThread]
   end
   subgraph MOOSSensorsTranslator
      CMOOSCommClient2[CMOOSCommClient]
      CMOOSCommClient2 <-->|your code| SimpleThread2
      SimpleThread2[SimpleThread]
   end
   end
   CMOOSCommClient1 <--> MOOSDB
   CMOOSCommClient2 <--> MOOSDB
   pHelmIvP <--> MOOSDB
   iSensor <--> MOOSDB
   SimpleThread1 <--> gobyd
   SimpleThread2 <--> gobyd
```

FrontSeatTranslation : BasicTranslator

```mermaid
flowchart TD
    subgraph MOOS/Goby
    subgraph goby_moos_gateway
    FrontSeatTranslation
    end
    end
    subgraph MOOS
    pHelmIvP[pHelmIvP]
    pHelmIvP -->|DESIRED_*, IVPHELM_STATE| FrontSeatTranslation 
    FrontSeatTranslation -->|NAV_*| pNodeReporter
    pNodeReporter -->|NODE_REPORT| pHelmIvP
    end
    subgraph Goby
    goby_frontseat_interface -->|node_status| FrontSeatTranslation
    FrontSeatTranslation -->|helm_state, desired_course| goby_frontseat_interface
    end
```

```bash
GOBY_MOOS_GATEWAY_PLUGINS=liblamss_goby3_gateway_plugin.so.0:libgoby_coroner_moos_gateway_plugin.so.30  goby_moos_gateway
```

We can just run the FrontSeatTranslation directly in `goby_frontseat_interface`:


```mermaid
flowchart TD
    
    subgraph Goby
    subgraph goby_frontseat_interface
    FrontSeatTranslation
    driver[frontseat::InterfaceBase implementation]
    end
    end
    subgraph MOOS
    pHelmIvP[pHelmIvP]
    pHelmIvP -->|DESIRED_*, IVPHELM_STATE| FrontSeatTranslation 
    FrontSeatTranslation -->|NAV_*| pNodeReporter
    pNodeReporter -->|NODE_REPORT| pHelmIvP
    end
    subgraph Goby
    driver -->|node_status| FrontSeatTranslation
    FrontSeatTranslation -->|helm_state| driver
    end
    driver <--> frontseat
```

## Command pHelmIvP through Goby

command from the topside to the USV.

Create a new `goby::moos::Translator` subclass `CommandTranslation` and we'll run this goby_moos_gateway.

```mermaid
flowchart TD
   subgraph topside
       goby_liaison
   end
   goby_liaison -->|usv_command|goby3_course_usv_manager

   subgraph usv
   goby3_course_usv_manager -->|usv_command| SimpleThread1
   subgraph goby_moos_gateway
   subgraph CommandTranslator
      CMOOSCommClient1[CMOOSCommClient]
      SimpleThread1 -->|convert| CMOOSCommClient1
      SimpleThread1[SimpleThread]
   end
   end
   CMOOSCommClient1 -->|DEPLOY_STATE, POLYGON_UPDATES| pHelmIvP
   end
```

- Added our new Loiter behavior to usv.bhv.in
- Wrote the new Translator thread
- Run our new Translator thread (within `goby_moos_gateway`)

### Time in Goby

C++11 and newer `std::chrono`

Goby is C++14

- point in time (e.g. right now) or duration (2 hours, 5 minutes) -> `std::chrono`
- date representation -> `boost::posix_time::ptime`
- serializable representation:
    - For points in time: seconds (double) or microseconds (int64_t or uint64_t) since the UNIX epoch (1 Jan 1970 midnight UTC) -> boost::units::quantity<...time>, typedef to `goby::time::MicroTime` (for `int64_t` microseconds) to `goby::time::SITime` (double seconds version)
    - For durations: seconds (double) or microseconds (int64_t) -> `goby::time::MicroTime` or the `SITime`.

Can be converted with the `goby::time::convert()` (for time points) and the `goby::time::convert_duration()` (for durations).

- `message_timestamp`: assume is a time point.
- `deploy_duration`: assume is a duration.

libdccl.org: more on the units


---
```





```