From db34cf63902d9116fd716c08ae7196d3cadd1f81 Mon Sep 17 00:00:00 2001 From: Vladimir Ermakov Date: Sat, 9 Sep 2023 14:22:22 +0200 Subject: [PATCH] msgs: move generator code --- mavros/test/test_quaternion_utils.cpp | 5 +- mavros_cog.py | 115 +++++++++++++++++++------- mavros_msgs/msg/ADSBVehicle.msg | 21 +---- mavros_msgs/msg/CommandCode.msg | 38 +-------- mavros_msgs/msg/GPSRAW.msg | 2 +- mavros_msgs/msg/Tunnel.msg | 17 +--- mavros_msgs/srv/SetMavFrame.srv | 17 +--- 7 files changed, 97 insertions(+), 118 deletions(-) diff --git a/mavros/test/test_quaternion_utils.cpp b/mavros/test/test_quaternion_utils.cpp index 0316b368e..e5bb622b7 100644 --- a/mavros/test/test_quaternion_utils.cpp +++ b/mavros/test/test_quaternion_utils.cpp @@ -15,9 +15,8 @@ #include #include - -#include -#include +#include +#include using namespace mavros; // NOLINT diff --git a/mavros_cog.py b/mavros_cog.py index bf96fbbaf..eee78a3d0 100644 --- a/mavros_cog.py +++ b/mavros_cog.py @@ -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 @@ -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[a-zA-Z0-9_\:]+)\)') -PLUGIN_NAME_RE = re.compile(r'@plugin\ (?P[a-z0-9_]+)') -PLUGIN_BRIEF_RE = re.compile(r'^@brief\ (?P.+)$') +CPP_MIME = "text/x-c++" +REGISTER_PLUGIN_RE = re.compile(r"MAVROS_PLUGIN_REGISTER\((?P[a-zA-Z0-9_\:]+)\)") +PLUGIN_NAME_RE = re.compile(r"@plugin\ (?P[a-z0-9_]+)") +PLUGIN_BRIEF_RE = re.compile(r"^@brief\ (?P.+)$") -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): @@ -46,6 +46,7 @@ class NoPluginRegister(Exception): """ That Exception returned if plugin registration not found """ + pass @@ -54,6 +55,7 @@ class PluginInfo: """ Info parsed from plugin source file """ + path: pathlib.Path klass: str name: str @@ -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: @@ -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 @@ -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) @@ -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 + xml_ = minidom.parseString(xml_).toprettyxml(indent=" ") + return "\n".join(xml_.splitlines()[1:]) # remove def cwd() -> pathlib.Path: if _cog_present: return pathlib.Path(cog.inFile).parent else: - return pathlib.Path('.') + return pathlib.Path(".") def outl(s: str): @@ -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: @@ -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) diff --git a/mavros_msgs/msg/ADSBVehicle.msg b/mavros_msgs/msg/ADSBVehicle.msg index 430efe28f..44b9caafa 100644 --- a/mavros_msgs/msg/ADSBVehicle.msg +++ b/mavros_msgs/msg/ADSBVehicle.msg @@ -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 diff --git a/mavros_msgs/msg/CommandCode.msg b/mavros_msgs/msg/CommandCode.msg index cde585937..4ba3d661b 100644 --- a/mavros_msgs/msg/CommandCode.msg +++ b/mavros_msgs/msg/CommandCode.msg @@ -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 diff --git a/mavros_msgs/msg/GPSRAW.msg b/mavros_msgs/msg/GPSRAW.msg index d64da318e..7dad43db0 100644 --- a/mavros_msgs/msg/GPSRAW.msg +++ b/mavros_msgs/msg/GPSRAW.msg @@ -1,5 +1,5 @@ # FCU GPS RAW message for the gps_status plugin -# A merge of mavlink GPS_RAW_INT and +# A merge of mavlink GPS_RAW_INT and # mavlink GPS2_RAW messages. std_msgs/Header header diff --git a/mavros_msgs/msg/Tunnel.msg b/mavros_msgs/msg/Tunnel.msg index c840b4d56..a04dcd13d 100644 --- a/mavros_msgs/msg/Tunnel.msg +++ b/mavros_msgs/msg/Tunnel.msg @@ -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. diff --git a/mavros_msgs/srv/SetMavFrame.srv b/mavros_msgs/srv/SetMavFrame.srv index 342b8d39e..b12f76a0c 100644 --- a/mavros_msgs/srv/SetMavFrame.srv +++ b/mavros_msgs/srv/SetMavFrame.srv @@ -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).