# 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 --- ``` ```