16 releases (9 breaking)

0.10.0 Nov 6, 2020
0.8.0 Jul 4, 2020
0.5.0 Mar 23, 2020
0.2.0 Nov 10, 2019

#141 in WebSocket

MIT license

42KB
676 lines

Mavlink2Rest

Build Test Cargo download Crate info Documentation

mavlink2rest creates a REST server that provides mavlink information from a mavlink source.

The current version supports the ardupilotmega dialect, that includes common, icarous and uavionix.

Install ⚡

  • ⚙️ Cargo Install: cargo install mavlink2rest

Downloads 📦

Continuous builds:

For others or different releases, check the releases menu.

Endpoints

Pages

  • Main webpage: GET /
    • Provides information about mavlink2rest and available messages.

API

  • MAVLink JSON:
    • GET /mavlink|/mavlink/*. The output is a JSON that you get each nested key individually, E.g:

    • POST /mavlink. Sends the message to a specific vehicle.

    • GET /helper/message/MAVLINK_MESSAGE_NAME: Helper endpoint to create JSON compatible MAVLink messages, where MAVLINK_MESSAGE_NAME is the mavlink message name. E.g:

      • http://0.0.0.0:8088/helper/message/COMMAND_LONG
        {
            "header": {
                "system_id": 255,
                "component_id": 0,
                "sequence": 0
            },
            "message": {
                "type": "COMMAND_LONG",
                "param1": 0.0,
                "param2": 0.0,
                "param3": 0.0,
                "param4": 0.0,
                "param5": 0.0,
                "param6": 0.0,
                "param7": 0.0,
                "command": {
                    "type": "MAV_CMD_NAV_WAYPOINT" // Random value
                },
                "target_system": 0,
                "target_component": 0,
                "confirmation": 0
            }
        }
        

Examples

Get all messages:
curl --request GET http://0.0.0.0:8088/mavlink\?pretty\=true
# The output is huge, you can get it here: https://gist.github.com/patrickelectric/26a407c4e7749cdaa58d06b52212cb1e
Get attitude:
curl --request GET http://0.0.0.0:8088/mavlink/ATTITUDE?pretty=true
{
  "message_information": {
    "counter": 46460,
    "frequency": 7.966392517089844,
    "time": {
      "first_message": "2020-03-28T12:47:52.315383-03:00",
      "last_message": "2020-03-28T14:25:04.905914-03:00"
    }
  },
  "pitch": 0.004207547288388014,
  "pitchspeed": 0.0010630330070853233,
  "roll": 0.004168820567429066,
  "rollspeed": 0.0009180732304230332,
  "time_boot_ms": 6185568,
  "type": "ATTITUDE",
  "yaw": -1.5562472343444824,
  "yawspeed": 0.0009576341835781932
}
Get time of last ATTITUDE message:
curl --request GET http://0.0.0.0:8088/mavlink/ATTITUDE/message_information/time/last_message?pretty=true
"2020-03-28T14:28:51.577853-03:00"
Get a message structure example:
curl --request GET http://0.0.0.0:8088/helper/message/ATTITUDE\?pretty\=true
{
  "header": {
    "system_id": 255,
    "component_id": 0,
    "sequence": 0
  },
  "message": {
    "type": "ATTITUDE",
    "time_boot_ms": 0,
    "roll": 0.0,
    "pitch": 0.0,
    "yaw": 0.0,
    "rollspeed": 0.0,
    "pitchspeed": 0.0,
    "yawspeed": 0.0
  }
}
Request vehicle to be armed:
# ARM: param1 is 1.0
curl --request POST http://0.0.0.0:8088/mavlink -H "Content-Type: application/json" --data \
'{
  "header": {
    "system_id": 1,
    "component_id": 1,
    "sequence": 0
  },
  "message": {
    "type":"COMMAND_LONG",
    "param1":1.0,
    "param2":0.0,"param3":0.0,"param4":0.0,"param5":0.0,"param6":0.0,"param7":0.0,
    "command":{
      "type":"MAV_CMD_COMPONENT_ARM_DISARM"
    },
    "target_system":0,
    "target_component":0,
    "confirmation":0
  }
}'
Request vehicle to be disarmed:
# ARM: param1 is 0.0
curl --request POST http://0.0.0.0:8088/mavlink -H "Content-Type: application/json" --data \
'{
  "header": {
    "system_id": 1,
    "component_id": 1,
    "sequence": 0
  },
  "message": {
    "type":"COMMAND_LONG",
    "param1":0.0,
    "param2":0.0,"param3":0.0,"param4":0.0,"param5":0.0,"param6":0.0,"param7":0.0,
    "command":{
      "type":"MAV_CMD_COMPONENT_ARM_DISARM"
    },
    "target_system":0,
    "target_component":0,
    "confirmation":0
  }
}'

Note: For any invalid GET, you'll receive a 404 response with the error message. Note: The endpoints that allow GET and provides a JSON output, also allow the usage of the query parameter pretty with a boolean value true or false, E.g: http://0.0.0.0:8088/helper/message/COMMAND_LONG?pretty=true

Websocket

It's also possible to connect multiple websockets with the following path /ws/mavlink, the endpoint also accepts the query parameter filter, the filter value should be a regex that matches MAVLink message names, E.g: /ws/mavlink?filter=.* for all messages, /ws/mavlink?filter=RC_.* will match RC_CHANNELS_RAW and RC_CHANNELS, resulting in the following output:

{ // First message
  "chan10_raw": 0,
  "chan11_raw": 0,
  "chan12_raw": 0,
  "chan13_raw": 0,
  "chan14_raw": 0,
  "chan15_raw": 0,
  "chan16_raw": 0,
  "chan17_raw": 0,
  "chan18_raw": 0,
  "chan1_raw": 1500,
  "chan2_raw": 1500,
  "chan3_raw": 1500,
  "chan4_raw": 1500,
  "chan5_raw": 1500,
  "chan6_raw": 1500,
  "chan7_raw": 1500,
  "chan8_raw": 1500,
  "chan9_raw": 0,
  "chancount": 16,
  "message_information": {
    "counter": 3732,
    "frequency": 4.0,
    "time": {
      "first_message": "2020-09-01T20:36:24.088099-03:00",
      "last_message": "2020-09-01T20:51:57.278901-03:00"
    }
  },
  "rssi": 0,
  "time_boot_ms": 3122812,
  "type": "RC_CHANNELS"
}
{ // Second message
  "chan1_raw": 1500,
  "chan2_raw": 1500,
  "chan3_raw": 1500,
  "chan4_raw": 1500,
  "chan5_raw": 1500,
  "chan6_raw": 1500,
  "chan7_raw": 1500,
  "chan8_raw": 1500,
  "message_information": {
    "counter": 3732,
    "frequency": 4.0,
    "time": {
      "first_message": "2020-09-01T20:36:24.088310-03:00",
      "last_message": "2020-09-01T20:51:57.279438-03:00"
    }
  },
  "port": 0,
  "rssi": 0,
  "time_boot_ms": 3122812,
  "type": "RC_CHANNELS_RAW"
}

For a demonstration, please check the example under the examples filder: websocket_client.py

Benchmark

The following benchmarks were extracted from a raspberry pi 3 connected to a pixhawk running ArduSub.

  • In idle.

    6% CPU usage
    
  • 1 client requesting all mavlink messages at 10Hz

    9% CPU usage
    
  • 1 client requesting all mavlink messages at 100Hz

    20% CPU usage (~5% each core)
    
  • 1 websocket with no filters

    11% CPU usage
    
  • 5 websockets with no filters

    24% CPU usage (14% @ 1 core, ~3% @ 3 cores)
    
  • 20 websockets with filter only for ATTITUDE message (receiving at 10Hz)

    9% CPU usage
    
  • 20 websockets with filter only for NAMED_VALUE_FLOAT message (receiving at 70Hz)

    17% CPU usage (9% @ 1 core, ~2% @ 3 cores)
    
  • 20 websockets with no filters

    48% CPU usage (20% @ 1 core, ~9% @ 3 cores)
    
  • 1 client requesting all mavlink messages 1000 times

    60% CPU usage (~15% each core)
    Time taken for tests      3.7 seconds
    Total requests            1000
    Successful requests       1000
    Failed requests           0
    Requests per second       273.60 [#/sec]
    Median time per request   3ms
    Average time per request  4ms
    
  • 10 clients requesting all mavlink messages, 100 requests for each client.

    140% CPU usage (~46% each core)
    Time taken for tests      1.4 seconds
    Total requests            1000
    Successful requests       1000
    Failed requests           0
    Requests per second       733.14 [#/sec]
    Median time per request   13ms
    Average time per request  13ms
    Sample standard deviation 3ms
    
  • 100 clients requesting all mavlink messages, 1000 requests for each client.

    140% CPU usage (~46% each core)
    Time taken for tests      13.8 seconds
    Total requests            10000
    Successful requests       10000
    Failed requests           0
    Requests per second       725.83 [#/sec]
    Median time per request   132ms
    Average time per request  137ms
    Sample standard deviation 54ms
    

Dependencies

~30MB
~619K SLoC