docs(toolchain): Remove old docs generator. Note dev.xml is path to common (#2445)

This commit is contained in:
Hamish Willee
2026-03-25 10:09:07 +11:00
committed by GitHub
parent 4107d822c9
commit 2abff2cb58
4 changed files with 2 additions and 601 deletions
+1 -3
View File
@@ -11,10 +11,8 @@ Deprecated files
- **mavlink.php**: Generates online documentation from MAVLink XML - http://mavlink.org/messages/common
- **mavlink_to_html_table.xsl**: XSL transform used by **mavlink.php** (Deprecated)
- **mavlink.css**: CSS used by online documentation (Deprecated)
- **mavlink_gitbook.py** (Deprecated): Generates documentation from MAVLink XML that can be imported into gitbook - replaced by mavlink_xml_to_markdown.py
- **mavlink_to_html_table_gitbook.xsl** (Deprecated): XSL transform used by **mavlink_gitbook.py**
For more information, please visit: https://mavlink.io/en/
(c) 2009-2023 Lorenz Meier / PIXHAWK Team
(c) 2009-2026 Lorenz Meier / PIXHAWK Team
-324
View File
@@ -1,324 +0,0 @@
#! /usr/bin/python
"""
This script generates markdown files for all the MAVLink message definition XML at:
https://github.com/mavlink/mavlink/tree/master/message_definitions/v1.0
The files can be imported into a gitbook to display the messages as HTML
The script runs on both Python2 and Python 3. The following libraries must be imported: lxml, requests, bs4.
The file is run in mavlink/doc/ with no arguments. It writes the files to /messages/
"""
import lxml.etree as ET
from bs4 import BeautifulSoup as bs
import re
import os # for walk
xsl_file_name = "mavlink_to_html_table_gitbook.xsl"
xml_message_definitions_dir_name = "../message_definitions/v1.0/"
output_dir = "./messages/"
output_dir_html=output_dir+"_html/"
if not os.path.exists(output_dir_html):
os.makedirs(output_dir_html)
# File for index
index_file_name = "README.md"
index_file_name = output_dir + index_file_name
# Get XSLT
with open(xsl_file_name, 'r') as content_file:
xsl_file = content_file.read()
xslt = ET.fromstring(xsl_file)
#initialise text for index file.
index_text="""<!-- THIS FILE IS AUTO-GENERATED (DO NOT UPDATE GITBOOK): https://github.com/mavlink/mavlink/blob/master/doc/mavlink_gitbook.py -->
# XML Definition Files & Dialects
MAVLink definitions files can be found in [mavlink/message definitions](https://github.com/mavlink/mavlink/blob/master/message_definitions/).
These can roughly be divided into:
- [Standard definitions](#standard-definitions) - core definitions shared by many flight stacks
- [Test definitions](#test-definitions) - definitions to support testing and validation
- [Dialects](#dialects) - *protocol-* and *vendor-specific* messages, enums and commands
## Standard Definitions
The following XML definition files are considered standard/core (i.e. not dialects):
- [minimal.xml](minimal.md) - the minimum set of entities (messages, enums, MAV_CMD) required to set up a MAVLink network.
- [standard.xml](standard.md) - the standard set of entities that are implemented by almost all flight stacks (at least 2, in a compatible way).
This `includes` [minimal.xml](minimal.md).
- [common.xml](../messages/common.md) - the set of entities that have been implemented in at least one core flight stack.
This `includes` [standard.xml](minimal.md)
> **Note** We are still working towards moving the truly standard entities from **common.xml** to **standard.xml**
Currently you should include [common.xml](../messages/common.md)
In addition:
- [development.xml](development.md) - XML definitions that are _proposed_ for inclusion in the standard definitions.
These are work in progress.
## Test Definitions
The following definitions are used for testing and dialect validation:
- [all.xml](all.md) - This includes all other XML files, and is used to verify that there are no ID clashes (and can potentially be used by GCS to communicate with any core dialect).
- [test.xml](test.md) - Test XML definition file.
## Dialects {#dialects}
MAVLink *dialects* are XML definition files that define *protocol-* and *vendor-specific* messages, enums and commands.
> **Note** Vendor forks of MAVLink may contain XML entities that have not yet been pushed into the main repository (and will not be documented).
Dialects may *include* other MAVLink XML files, which may in turn contain other XML files (up to 5 levels of XML file nesting are allowed - see `MAXIMUM_INCLUDE_FILE_NESTING` in [mavgen.py](https://github.com/ArduPilot/pymavlink/blob/master/generator/mavgen.py#L44)).
A typical pattern is for a dialect to include [common.xml](../messages/common.md) (containing the *MAVLink standard definitions*), extending it with vendor or protocol specific messages.
The dialect definitions are:
"""
index_text_trailer="""
"""
#Fix up the BeautifulSoup output so to fix build-link errors in the generated gitbook.
## BS puts each tag/content in its own line. Gitbook generates anchors using the spaces/newlines.
## This puts displayed text content immediately within tags so that anchors/links generate properly
def fix_content_in_tags(input_html):
#print("fix_content_in_tags was called")
def remove_space_between_content_tags(matchobj):
stripped_string=matchobj.group(1).strip()
return '>%s<' % stripped_string
input_html=re.sub(r'\>(\s+?\w+?.*?)\<', remove_space_between_content_tags, input_html,flags=re.DOTALL)
return input_html
def fix_external_dialect_link(input_html):
#print("fix_external_dialect_link was called")
def fixupexternaldialecturls(matchobj):
return matchobj.group(1).strip()
input_html=re.sub(r'<a href="../../external/.*?>(.*?)</a>', fixupexternaldialecturls, input_html,flags=re.DOTALL)
return input_html
def fix_include_file_extension(input_html):
## Fixes up file extension .xml.md.unlikely (easier than fixing up the XSLT to strip file extensions!)
input_html=input_html.replace('.xml.md.unlikely','.md')
return input_html
def fix_replace_space_marker(input_html):
## Above we remove hidden space. I can't seem to regexp just that type of space, so use space markers in text
input_html=input_html.replace('xxx_space_xxx',' ')
return input_html
def strip_text_before_string(original_text,strip_text):
# Strip out all text before some string
index=original_text.find(strip_text)
stripped_string=original_text
if index !=-1 :
stripped_string = stripped_string[index:]
return stripped_string
def fix_add_implicit_links_items(input_html):
# Makes screaming snake case into anchors. Special fix for MAV_CMD.
#print("fix_add_implicit_link was called")
def make_text_to_link(matchobj):
#print("make_entry_to_link was called: %s" % matchobj.group(0))
item_string = matchobj.group(2)
item_url=item_string
if item_string == 'MAV_CMD':
item_url='mav_commands'
returnString = '%s<a href="#%s">%s</a>%s' % (matchobj.group(1),item_url,item_string,matchobj.group(3))
#print("returnstring: %s" % returnString)
return returnString
input_html=re.sub(r'([\`\(\s,]|^)([A-Z]{2,}(?:_[A-Z0-9]+)+)([\`\)\s\.,:]|$)', make_text_to_link, input_html,flags=re.DOTALL)
return input_html
def inject_top_level_docs(input_html,filename):
#Inject top level heading and other details.
print('FILENAME (prefix): %s' % filename)
insert_text='<!-- THIS FILE IS AUTO-GENERATED: https://github.com/mavlink/mavlink/blob/master/doc/mavlink_gitbook.py -->'
if filename == 'common':
insert_text+="""
# MAVLINK Common Message Set
The MAVLink *common* message set contains *standard* definitions that are managed by the MAVLink project.
The definitions cover functionality that is considered useful to most ground control stations and autopilots.
MAVLink-compatible systems are expected to use these definitions where possible (if an appropriate message exists) rather than rolling out variants in their own [dialects](../messages/README.md).
The original definitions are defined in [common.xml](https://github.com/mavlink/mavlink/blob/master/message_definitions/v1.0/common.xml).
> **Tip** The common set `includes` [minimal.xml](minimal.md), which contains the *minimal set* of definitions for any MAVLink system.
These definitions are [reproduced at the end of this topic](#minimal).
"""
elif filename == 'minimal':
insert_text+="""
# MAVLink Minimal Set
The MAVLink *minimal* set contains the minimal set of definitions for a viable MAVLink system.
The message set is defined in [minimal.xml](https://github.com/mavlink/mavlink/blob/master/message_definitions/v1.0/minimal.xml) and is managed by the MAVLink project.
> **Tip** The minimal set is included (imported into) other xml definition files, including the [MAVLink Common Message Set (common.xml)](minimal.md).
"""
elif filename == 'ardupilotmega':
insert_text+="""
# Dialect: ArduPilotMega
These messages define the ArduPilot specific message set, which is custom to [http://ardupilot.org](http://ardupilot.org).
This topic is a human-readable form of the XML definition file: [ardupilotmega.xml](https://github.com/mavlink/mavlink/blob/master/message_definitions/v1.0/ardupilotmega.xml).
> **Warning** The ArduPilot MAVLink fork of [ardupilotmega.xml](https://github.com/ArduPilot/mavlink/blob/master/message_definitions/v1.0/ardupilotmega.xml) may contain messages that have not yet been merged into this documentation.
"""
elif filename == 'development':
insert_text+="""
# Dialect: development
This dialect contains messages that are proposed for inclusion in the [standard set](standard.md), in order to ease development of prototype implementations.
They should be considered a 'work in progress' and not included in production builds.
This topic is a human-readable form of the XML definition file: [development.xml](https://github.com/mavlink/mavlink/blob/master/message_definitions/v1.0/development.xml).
"""
elif filename == 'all':
insert_text+="""
# Dialect: all
This dialect is intended to `include` all other [dialects](../messages/README.md) in the mavlink/mavlink repository (including [external dialects](https://github.com/mavlink/mavlink/tree/master/external/dialects#mavlink-external-dialects)).
Dialects that are in **all.xml** are guaranteed to not have clashes in messages, enums, enum ids, and MAV_CMDs.
This ensure that:
- Systems based on these dialects can co-exist on the same MAVLink network.
- A Ground Station might (optionally) use libraries generated from **all.xml** to communicate using any of the dialects.
> **Warning** New dialect files in the official repository must be added to **all.xml** and restrict themselves to using ids in their own allocated range.
A few older dialects are not included because these operate in completely closed networks or because they are only used for tests.
This topic is a human-readable form of the XML definition file: [all.xml](https://github.com/mavlink/mavlink/blob/master/message_definitions/v1.0/all.xml).
"""
else:
insert_text+='\n# Dialect: %s' % filename.rsplit('.',1)[0]
insert_text+='\n\n*This is a human-readable form of the XML definition file: [%s](https://github.com/mavlink/mavlink/blob/master/message_definitions/v1.0/%s).*' % (filename, filename)
insert_text+="""
<span></span>
> **Note** MAVLink 2 messages have an ID > 255 and are marked up using **(MAVLink 2)** in their description.
<span id="mav2_extension_field"></span>
> **Note** MAVLink 2 extension fields that have been added to MAVLink 1 messages are displayed in blue.
<style>
td {
vertical-align:top;
}
</style>
"""
# Include HTML in generated content
insert_text+='\n\n{%% include "_html/%s.html" %%}' % filename
input_html=insert_text+'\n\n'+input_html
if filename == 'common':
input_html+="""
# Minimal.xml {#minimal}
The minimal set of definitions required for any MAVLink system are included from [minimal.xml](minimal.md).
These are listed below.
{% include "_html/minimal.html" %}"""
#print(input_html)
return input_html
dialect_files = set()
all_files = set()
for subdir, dirs, files in os.walk(xml_message_definitions_dir_name):
#Generate html for all the XML files
for file in files:
print(file)
if not file.endswith('.xml'): #only process xml files.
continue
xml_file_name = xml_message_definitions_dir_name+file
with open(xml_file_name, 'r') as content_file:
xml_file = content_file.read()
dom = ET.fromstring(xml_file)
transform = ET.XSLT(xslt)
newdom = transform(dom)
#Prettify the HTML using BeautifulSoup
soup=bs(str(newdom), "lxml")
prettyHTML=soup.prettify()
#Strip out text before <html> tag in XSLT output
prettyHTML=strip_text_before_string(prettyHTML,'<html>')
prettyHTML = fix_content_in_tags(prettyHTML)
#Replace invalid file extensions (workaround for xslt)
prettyHTML = fix_include_file_extension(prettyHTML)
#Replace space markers with intentional space
prettyHTML = fix_replace_space_marker(prettyHTML)
#Fix up links to external dialects to not be links
prettyHTML = fix_external_dialect_link(prettyHTML)
#Fix up plain text mav symbols to be internal links
prettyHTML = fix_add_implicit_links_items(prettyHTML)
#Write output html file
output_file_name_html = file.rsplit('.',1)[0]+".html"
output_file_name_html_withdir = output_dir_html+output_file_name_html
print("Output filename (html): %s" % output_file_name_html)
with open(output_file_name_html_withdir, 'w') as out:
out.write(prettyHTML)
# Create sortable list of output file names
#Write output markdown file
output_file_name_prefix = file.rsplit('.',1)[0]
all_files.add(output_file_name_prefix)
if not file=='common.xml' and not file=='standard.xml' and not file=='minimal.xml' and not file=='test.xml' and not file=='development.xml':
dialect_files.add(output_file_name_prefix)
# Generate the markdown files
for file_prefix in all_files:
print(file_prefix)
markdown_text=''
#Inject a heading and doc-type intro (markdown format)
markdown_text = inject_top_level_docs(markdown_text,file_prefix)
output_file_name_md_withdir = output_dir+file_prefix+'.md'
print("Output filename (md): %s" % output_file_name_md_withdir)
with open(output_file_name_md_withdir, 'w') as out:
out.write(markdown_text)
for the_file in sorted(dialect_files):
index_text+='\n* [%s.xml](%s.md)' % (the_file,the_file)
index_text+='\n\n'
index_text+=index_text_trailer
#Write the index
with open(index_file_name, 'w') as content_file:
content_file.write(index_text)
print("COMPLETED")
-273
View File
@@ -1,273 +0,0 @@
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="//include">
<p><strong>MAVLink Include Files: </strong> <a><xsl:attribute name="href"><xsl:value-of select="."/>.md.unlikely</xsl:attribute><xsl:value-of select="." /></a> </p>
</xsl:template>
<xsl:template match="//enums">
<h2 id="enums">MAVLink Type Enumerations</h2>
<xsl:apply-templates select="enum[@name!='MAV_CMD']" />
<a id="MAV_CMD"></a>
<h2 id="mav_commands">MAVLink Commands (MAV_CMD)</h2>
<blockquote class="alert alert-info clearfix"><strong class="fa fa-2x fa-edit"></strong><p>MAVLink commands (MAV_CMD) and messages are different! These commands define the values of up to 7 parameters that are packaged INSIDE specific messages used in the Mission Protocol and Command Protocol. Use commands for actions in missions or if you need acknowledgment and/or retry logic from a request. Otherwise use messages.</p></blockquote>
<xsl:apply-templates select="enum[@name='MAV_CMD']" mode="params"/>
</xsl:template>
<xsl:template match="//messages">
<h2 id="messages">MAVLink Messages</h2>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="//message">
<h3> <!-- mavlink_message_name -->
<xsl:attribute name="id"><xsl:value-of select="@name"/></xsl:attribute>
<xsl:value-of select="@name" /> (
<a>
<xsl:attribute name="href">#<xsl:value-of select="@name"/></xsl:attribute>
#<xsl:value-of select="@id" />
</a>
)</h3>
<xsl:apply-templates select="wip" />
<xsl:apply-templates select="deprecated" />
<p> <!-- description --><a href="#messages">[Message]</a>
<xsl:if test='@id > 255'><strong>(MAVLink 2) </strong></xsl:if>
<xsl:value-of select="description" /></p>
<table class="sortable">
<thead>
<tr> <!-- mavlink_field_header -->
<th>Field Name</th>
<th>Type</th>
<xsl:if test='*/@units'>
<th>Units</th>
</xsl:if>
<xsl:if test='*/@enum'>
<th>Values</th>
</xsl:if>
<th>Description</th>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="field" />
</tbody>
</table>
</xsl:template>
<xsl:template match="//field">
<tr> <!-- mavlink_field -->
<xsl:choose>
<xsl:when test="preceding-sibling::extensions">
<td style="color:blue;"><xsl:value-of select="@name" />&#160;<a href="#mav2_extension_field" title="MAVLink2 extension field">**</a></td> <!-- mavlink_name -->
</xsl:when>
<xsl:otherwise>
<td><xsl:value-of select="@name" /></td> <!-- mavlink_name -->
</xsl:otherwise>
</xsl:choose>
<td><xsl:value-of select="@type" /></td> <!-- mavlink_type -->
<xsl:if test='../*/@units'>
<td><xsl:value-of select="@units" /></td> <!-- mavlink_units -->
</xsl:if>
<xsl:if test='../*/@enum'>
<td><xsl:if test='@enum'>
<a><xsl:attribute name="href">#<xsl:value-of select="@enum" /></xsl:attribute><xsl:value-of select="@enum" /></a>
</xsl:if>
</td> <!-- mavlink_value -->
</xsl:if>
<td><xsl:value-of select="." /></td> <!-- mavlink_comment -->
</tr>
</xsl:template>
<xsl:template match="//version">
<h2>MAVLink Protocol Version</h2>
<p>The current MAVLink version is 2.<xsl:value-of select="." />. The minor version numbers (after the dot) range from 1-255. </p>
</xsl:template>
<xsl:template match="//dialect">
<p>This file has protocol dialect: <xsl:value-of select="." />.</p>
</xsl:template>
<xsl:template match="//enum">
<h3> <!-- mavlink_enum_name -->
<xsl:attribute name="id"><xsl:value-of select="@name"/></xsl:attribute>
<xsl:value-of select="@name" /></h3>
<xsl:apply-templates select="deprecated" />
<p><a href="#enums">[Enum]</a><xsl:value-of select="description" /></p> <!-- description -->
<table class="sortable">
<thead>
<tr> <!-- mavlink_field_header -->
<th>Value</th>
<th>Field Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="entry" />
</tbody>
</table>
</xsl:template>
<xsl:template match="//enum" mode="params">
<p><xsl:value-of select="description" /> </p>
<xsl:apply-templates select="entry" mode="params" />
</xsl:template>
<xsl:template match="//entry" mode="params">
<h3 id="{@name}"><xsl:value-of select="@name" /> (<a><xsl:attribute name="href">#<xsl:value-of select="@name"/></xsl:attribute><xsl:value-of select="@value" /></a>)</h3>
<xsl:apply-templates select="deprecated" />
<xsl:apply-templates select="wip" />
<p><a href="#mav_commands">[Command]</a><xsl:value-of select="description" /> </p> <!-- mavlink_comment -->
<xsl:if test='@hasLocation = "true" or @isDestination = "true"'>
<p>Send this command in a COMMAND_INT (if supported by your flight stack), as it specifies positional information.
If sent in a COMMAND_LONG, no frame of reference can be set, and lat/lon values in param 5/6 are less precise.</p>
</xsl:if>
<table class="sortable">
<thead>
<tr> <!-- mavlink_field_header -->
<th>Param (:Label)</th>
<th>Description</th>
<xsl:if test='*/@enum or */@minValue or */@maxValue or */@increment'>
<th>Values</th>
</xsl:if>
<xsl:if test='*/@units'>
<th>Units</th>
</xsl:if>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="param" mode="params" />
</tbody>
</table>
</xsl:template>
<xsl:template match="//entry">
<tr id="{@name}"> <!-- mavlink_field -->
<td><xsl:value-of select="@value" /></td> <!-- mavlink_type -->
<td>
<a><xsl:attribute name="href">#<xsl:value-of select="@name"/></xsl:attribute><xsl:value-of select="@name" /></a>
<xsl:apply-templates select="deprecated" />
<xsl:apply-templates select="wip" />
</td> <!-- mavlink_name -->
<td><xsl:value-of select="description" /></td> <!-- mavlink_comment -->
</tr>
<xsl:if test='param'>
<tr>
<td></td>
<xsl:apply-templates select="param" />
</tr>
<tr>
<td colspan="3"><br /></td>
</tr>
</xsl:if>
</xsl:template>
<xsl:template match="//param" mode="params">
<tr>
<td><xsl:value-of select="@index" />
<xsl:if test='@label'>: <xsl:value-of select="@label" /></xsl:if>
</td> <!-- mission_param -->
<td><xsl:if test='@reserved = "true"'>Reserved (set to <xsl:if test='@default'><xsl:value-of select="@default" /></xsl:if><xsl:if test='not(@default)'>0</xsl:if>)</xsl:if><xsl:value-of select="." />
<xsl:if test='@decimalPlaces'><br /><strong>GCS display settings:</strong>
<xsl:if test='@label'><em>Label:</em> <xsl:value-of select="@label" />, </xsl:if>
<xsl:if test='@decimalPlaces'><em>decimalPlaces:</em> <xsl:value-of select="@decimalPlaces" /></xsl:if>
</xsl:if>
</td>
<xsl:if test='../*/@enum or ../*/@minValue or ../*/@maxValue or ../*/@increment'>
<td>
<xsl:choose>
<xsl:when test="@enum">
<a><xsl:attribute name="href">#<xsl:value-of select="@enum" /></xsl:attribute><xsl:value-of select="@enum" /></a>
</xsl:when>
<xsl:when test="@minValue or @maxValue or @increment ">
<xsl:if test='@minValue'><em>min:</em><xsl:value-of select="@minValue" /><xsl:text>xxx_space_xxx</xsl:text></xsl:if>
<xsl:if test='@maxValue'><em>max:</em><xsl:value-of select="@maxValue" /><xsl:text>xxx_space_xxx</xsl:text></xsl:if>
<xsl:if test='@increment'><em>increment:</em><xsl:value-of select="@increment" /></xsl:if>
</xsl:when>
</xsl:choose>
</td>
</xsl:if>
<xsl:if test='../*/@units'>
<td><xsl:value-of select="@units" /></td> <!-- mavlink_units -->
</xsl:if>
</tr>
</xsl:template>
<xsl:template match="//param">
<tr>
<td></td>
<td>Param #<xsl:value-of select="@index" /></td> <!-- mission_param -->
<td>
<xsl:value-of select="." />
<xsl:choose>
<xsl:when test="@enum">
<br /><strong>Possible values:</strong> <xsl:value-of select="@enum" />
</xsl:when>
<xsl:when test="@minValue or @maxValue or @increment or @units">
<br /><strong>Values:</strong>
<xsl:if test='@units'><em>units:</em> <xsl:value-of select="@minValue" />, </xsl:if>
<xsl:if test='@minValue'><em>min:</em><xsl:value-of select="@minValue" />, </xsl:if>
<xsl:if test='@maxValue'><em>max:</em><xsl:value-of select="@maxValue" />, </xsl:if>
<xsl:if test='@increment'><em>increment:</em><xsl:value-of select="@increment" /></xsl:if>
</xsl:when>
</xsl:choose>
<xsl:if test='@label or @decimalPlaces'><br /><strong>GCS display settings:</strong>
<xsl:if test='@label'><em>Label:</em> <xsl:value-of select="@label" />, </xsl:if>
<xsl:if test='@decimalPlaces'><em>decimalPlaces:</em> <xsl:value-of select="@decimalPlaces" /></xsl:if>
</xsl:if>
</td> <!-- mavlink_comment -->
</tr>
</xsl:template>
<xsl:template match="//wip">
<p style="color:red"><strong>WORK IN PROGRESS:</strong><xsl:text>xxx_space_xxx</xsl:text>Do not use in stable production environments (it may change).</p>
</xsl:template>
<xsl:template match="//deprecated">
<p style="color:red"><strong>DEPRECATED:</strong><xsl:text>xxx_space_xxx</xsl:text>Replaced by <xsl:value-of select="@replaced_by" /> (<xsl:value-of select="@since" />).
<xsl:if test='.'>
<xsl:value-of select="." />
</xsl:if>
</p>
</xsl:template>
</xsl:stylesheet>
+1 -1
View File
@@ -311,7 +311,7 @@ The original definitions are defined in [standard.xml](https://github.com/mavlin
insert_text += """
# Dialect: development
This dialect contains messages that are proposed for inclusion in the [standard set](standard.md), in order to ease development of prototype implementations.
This dialect contains messages that are proposed for inclusion in the [common set](common.md), in order to ease development of prototype implementations.
They should be considered a 'work in progress' and not included in production builds.
This topic is a human-readable form of the XML definition file: [development.xml](https://github.com/mavlink/mavlink/blob/master/message_definitions/v1.0/development.xml).