Skip to content

Commit

Permalink
msgs: move generator code
Browse files Browse the repository at this point in the history
  • Loading branch information
vooon committed Sep 9, 2023
1 parent d9e3d8b commit db34cf6
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 118 deletions.
5 changes: 2 additions & 3 deletions mavros/test/test_quaternion_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@

#include <rclcpp/rclcpp.hpp>
#include <mavros/frame_tf.hpp>

#include <tf2/LinearMath/Quaternion.h>
#include <tf2/LinearMath/Matrix3x3.h>
#include <tf2/LinearMath/Quaternion.hpp>
#include <tf2/LinearMath/Matrix3x3.hpp>

using namespace mavros; // NOLINT

Expand Down
115 changes: 84 additions & 31 deletions mavros_cog.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
'''
"""
Module with common cog generators used several times.
Install:
ln -s $PWD/mavros_cog.py $HOME/.local/lib/python3.8/site-packages/
'''
"""

try:
import cog
Expand All @@ -17,25 +17,25 @@
import re
import typing
import xml.etree.ElementTree as ET # nosemgrep
from collections import OrderedDict
from xml.dom import minidom # nosemgrep

import attr
from comment_parser import comment_parser
from pymavlink.dialects.v20 import common

CPP_MIME = 'text/x-c++'
REGISTER_PLUGIN_RE = re.compile(
r'MAVROS_PLUGIN_REGISTER\((?P<klass>[a-zA-Z0-9_\:]+)\)')
PLUGIN_NAME_RE = re.compile(r'@plugin\ (?P<name>[a-z0-9_]+)')
PLUGIN_BRIEF_RE = re.compile(r'^@brief\ (?P<brief>.+)$')
CPP_MIME = "text/x-c++"
REGISTER_PLUGIN_RE = re.compile(r"MAVROS_PLUGIN_REGISTER\((?P<klass>[a-zA-Z0-9_\:]+)\)")
PLUGIN_NAME_RE = re.compile(r"@plugin\ (?P<name>[a-z0-9_]+)")
PLUGIN_BRIEF_RE = re.compile(r"^@brief\ (?P<brief>.+)$")

plugins_without_macro = {
"mavros/src/plugins/mission_protocol_base.cpp"
}
plugins_without_macro = {"mavros/src/plugins/mission_protocol_base.cpp"}

if _cog_present:

def dbg(s):
cog.msg(s)

else:

def dbg(s):
Expand All @@ -46,6 +46,7 @@ class NoPluginRegister(Exception):
"""
That Exception returned if plugin registration not found
"""

pass


Expand All @@ -54,6 +55,7 @@ class PluginInfo:
"""
Info parsed from plugin source file
"""

path: pathlib.Path
klass: str
name: str
Expand All @@ -66,11 +68,13 @@ def factory_klass(self) -> str:

@property
def as_xml(self) -> ET.Element:
ret = ET.Element('class',
name=self.name,
type=self.factory_klass,
base_class_type='mavros::plugin::PluginFactory')
desc = ET.SubElement(ret, 'description')
ret = ET.Element(
"class",
name=self.name,
type=self.factory_klass,
base_class_type="mavros::plugin::PluginFactory",
)
desc = ET.SubElement(ret, "description")
desc.text = self.description

if not self.is_example:
Expand All @@ -83,35 +87,37 @@ def sort_key(self):
return (not self.is_example, self.name)

@classmethod
def parse_file(cls, path: pathlib.Path) -> 'PluginInfo':
with path.open('r') as fd:
def parse_file(cls, path: pathlib.Path) -> "PluginInfo":
with path.open("r") as fd:
source = fd.read()

m = REGISTER_PLUGIN_RE.search(source)
if m is None:
raise NoPluginRegister(
f"plugin registration macro not found in file: {path}")
f"plugin registration macro not found in file: {path}"
)

klass = m.group('klass')
klass = m.group("klass")
comments = comment_parser.extract_comments_from_str(source, CPP_MIME)

# assume that only one plugin is allowed per file
comment = next(c.text() for c in comments if '@plugin' in c.text())
comment = next(c.text() for c in comments if "@plugin" in c.text())

# clean comment from *
def remove_prefix(line: str) -> str:
line = line.strip()
if line.startswith('*'):
if line.startswith("*"):
line = line[1:]
return line.strip()

comment = '\n'.join(
remove_prefix(line) for line in comment.splitlines()).strip()
comment = "\n".join(
remove_prefix(line) for line in comment.splitlines()
).strip()

m = PLUGIN_NAME_RE.search(comment)
name = m.group('name')
name = m.group("name")

is_example = '@example_plugin' in comment
is_example = "@example_plugin" in comment

# TODO(vooon): reformat comment for description

Expand All @@ -125,7 +131,7 @@ def remove_prefix(line: str) -> str:


def load_all_plugin_infos(dir: pathlib.Path) -> typing.Iterator[PluginInfo]:
for fl in dir.glob('*.cpp'):
for fl in dir.glob("*.cpp"):
try:
if str(fl) not in plugins_without_macro:
yield PluginInfo.parse_file(fl)
Expand All @@ -138,15 +144,15 @@ def load_all_plugin_infos(dir: pathlib.Path) -> typing.Iterator[PluginInfo]:
def et_to_str(root: ET.Element) -> str:
# XXX(vooon): pretty print
xml_ = ET.tostring(root)
xml_ = minidom.parseString(xml_).toprettyxml(indent=' ')
return '\n'.join(xml_.splitlines()[1:]) # remove <? header ?>
xml_ = minidom.parseString(xml_).toprettyxml(indent=" ")
return "\n".join(xml_.splitlines()[1:]) # remove <? header ?>


def cwd() -> pathlib.Path:
if _cog_present:
return pathlib.Path(cog.inFile).parent
else:
return pathlib.Path('.')
return pathlib.Path(".")


def outl(s: str):
Expand All @@ -157,8 +163,7 @@ def outl(s: str):


def outl_plugins_xml(dir: str, lib_path: str):
plugins = sorted(load_all_plugin_infos(cwd() / dir),
key=lambda p: p.sort_key)
plugins = sorted(load_all_plugin_infos(cwd() / dir), key=lambda p: p.sort_key)

root = ET.Element("library", path=lib_path)
for pl in plugins:
Expand All @@ -171,3 +176,51 @@ def outl_plugins_xml(dir: str, lib_path: str):
def outl_glob_files(dir: str, glob: str = "*.cpp"):
for f in sorted((cwd() / dir).glob(glob)):
outl(str(f.relative_to(cwd())))


def clear_desc(s):
return " ".join(v.strip() for v in s.splitlines() if v.strip())


def idl_decl_enum_mav_cmd(ename="MAV_CMD"):
def wr_enum(enum, ename, pfx="", bsz=16):
cog.outl("# " + ename + "_" + pfx)
for k, e in enum:
# exclude also deprecated commands
if "MAV_CMD" + "_" + pfx in e.name and not re.search(
"deprecated", e.description, re.IGNORECASE
):
sn = e.name[len("MAV_CMD") + 1 :]
l = "uint{bsz} {sn} = {k}".format(**locals())
if e.description:
l += " " * (50 - len(l)) + " # " + clear_desc(e.description)
cog.outl(l)
cog.out("\n")

enum = sorted(common.enums[ename].items())
enum.pop() # remove ENUM_END

enumt = []
# exception list of commands to not include
exlist = ["SPATIAL", "USER", "WAYPOINT"]
for k, e in enum:
enumt.extend(e.name[len(ename) + 1 :].split("_")[0:1])

enumt = sorted(set(enumt))
enumt = [word for word in enumt if word not in exlist]

for key in enumt:
wr_enum(enum, ename, key)


def idl_decl_enum(ename, pfx="", bsz=8):
enum = sorted(common.enums[ename].items())
enum.pop() # remove ENUM_END

cog.outl("# " + ename)
for k, e in enum:
sn = e.name[len(ename) + 1 :]
l = "uint{bsz} {pfx}{sn} = {k}".format(**locals())
if e.description:
l += " " * (40 - len(l)) + " # " + clear_desc(e.description)
cog.outl(l)
21 changes: 4 additions & 17 deletions mavros_msgs/msg/ADSBVehicle.msg
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,10 @@
# https://mavlink.io/en/messages/common.html#ADSB_VEHICLE

# [[[cog:
# from pymavlink.dialects.v20 import common
#
# def decl_enum(ename, pfx='', bsz=8):
# enum = sorted(common.enums[ename].items())
# enum.pop() # remove ENUM_END
#
# cog.outl("# " + ename)
# for k, e in enum:
# sn = e.name[len(ename) + 1:]
# l = "uint{bsz} {pfx}{sn} = {k}".format(**locals())
# if e.description:
# l += ' ' * (40 - len(l)) + ' # ' + e.description
# cog.outl(l)
#
# decl_enum('ADSB_ALTITUDE_TYPE', 'ALT_')
# decl_enum('ADSB_EMITTER_TYPE', 'EMITTER_')
# decl_enum('ADSB_FLAGS', 'FLAG_', 16)
# import mavros_cog
# mavros_cog.idl_decl_enum('ADSB_ALTITUDE_TYPE', 'ALT_')
# mavros_cog.idl_decl_enum('ADSB_EMITTER_TYPE', 'EMITTER_')
# mavros_cog.idl_decl_enum('ADSB_FLAGS', 'FLAG_', 16)
# ]]]
# ADSB_ALTITUDE_TYPE
uint8 ALT_PRESSURE_QNH = 0 # Altitude reported from a Baro source using QNH reference
Expand Down
38 changes: 2 additions & 36 deletions mavros_msgs/msg/CommandCode.msg
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,8 @@
# https://mavlink.io/en/messages/common.html#MAV_CMD

# [[[cog:
# from pymavlink.dialects.v20 import common
# from collections import OrderedDict
# import re
#
# def clear_desc(s):
# return ' '.join(v.strip() for v in s.splitlines() if v.strip())
#
# def wr_enum(enum, ename, pfx='', bsz=16):
# cog.outl("# " + ename + "_" + pfx)
# for k, e in enum:
# # exclude also deprecated commands
# if 'MAV_CMD' + "_" + pfx in e.name and not re.search('deprecated', e.description, re.IGNORECASE):
# sn = e.name[len('MAV_CMD') + 1:]
# l = "uint{bsz} {sn} = {k}".format(**locals())
# if e.description:
# l += ' ' * (50 - len(l)) + ' # ' + clear_desc(e.description)
# cog.outl(l)
# cog.out('\n')
#
# def decl_enum(ename):
# enum = sorted(common.enums[ename].items())
# enum.pop() # remove ENUM_END
#
# enumt = []
# # exception list of commands to not include
# exlist = ['SPATIAL', 'USER', 'WAYPOINT']
# for k, e in enum:
# enumt.extend(e.name[len(ename) + 1:].split('_')[0:1])
#
# enumt = sorted(set(enumt))
# enumt = [word for word in enumt if word not in exlist]
#
# for key in enumt:
# wr_enum(enum, ename, key)
#
# decl_enum('MAV_CMD')
# import mavros_cog
# mavros_cog.idl_decl_enum_mav_cmd()
# ]]]
# MAV_CMD_AIRFRAME
uint16 AIRFRAME_CONFIGURATION = 2520
Expand Down
2 changes: 1 addition & 1 deletion mavros_msgs/msg/GPSRAW.msg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# FCU GPS RAW message for the gps_status plugin
# A merge of <a href="https://mavlink.io/en/messages/common.html#GPS_RAW_INT">mavlink GPS_RAW_INT</a> and
# A merge of <a href="https://mavlink.io/en/messages/common.html#GPS_RAW_INT">mavlink GPS_RAW_INT</a> and
# <a href="https://mavlink.io/en/messages/common.html#GPS2_RAW">mavlink GPS2_RAW</a> messages.

std_msgs/Header header
Expand Down
17 changes: 2 additions & 15 deletions mavros_msgs/msg/Tunnel.msg
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,8 @@ uint8 payload_length
uint8[128] payload

# [[[cog:
# from pymavlink.dialects.v20 import common
#
# def decl_enum(ename, pfx='', bsz=8):
# enum = sorted(common.enums[ename].items())
# enum.pop() # remove ENUM_END
#
# cog.outl("# " + ename)
# for k, e in enum:
# sn = e.name[len(ename) + 1:]
# l = "uint{bsz} {pfx}{sn} = {k}".format(**locals())
# if e.description:
# l += ' ' * (40 - len(l)) + ' # ' + e.description
# cog.outl(l)
#
# decl_enum('MAV_TUNNEL_PAYLOAD_TYPE', 'PAYLOAD_TYPE_', 16)
# import mavros_cog
# mavros_cog.idl_decl_enum('MAV_TUNNEL_PAYLOAD_TYPE', 'PAYLOAD_TYPE_', 16)
# ]]]
# MAV_TUNNEL_PAYLOAD_TYPE
uint16 PAYLOAD_TYPE_UNKNOWN = 0 # Encoding of payload unknown.
Expand Down
17 changes: 2 additions & 15 deletions mavros_msgs/srv/SetMavFrame.srv
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,8 @@
# XXX DEPRECATED

# [[[cog:
# from pymavlink.dialects.v20 import common
#
# def decl_enum(ename, pfx='', bsz=8):
# enum = sorted(common.enums[ename].items())
# enum.pop() # remove ENUM_END
#
# cog.outl("# " + ename)
# for k, e in enum:
# sn = e.name[len(ename) + 1:]
# l = "uint{bsz} {pfx}{sn} = {k}".format(**locals())
# if e.description:
# l += ' ' * (40 - len(l)) + ' # ' + e.description
# cog.outl(l)
#
# decl_enum('MAV_FRAME', 'FRAME_')
# import mavros_cog
# mavros_cog.idl_decl_enum('MAV_FRAME', 'FRAME_')
# ]]]
# MAV_FRAME
uint8 FRAME_GLOBAL = 0 # Global (WGS84) coordinate frame + MSL altitude. First value / x: latitude, second value / y: longitude, third value / z: positive altitude over mean sea level (MSL).
Expand Down

0 comments on commit db34cf6

Please sign in to comment.