diff --git a/sros2/package.xml b/sros2/package.xml
index 92bf25ef..5772b3db 100644
--- a/sros2/package.xml
+++ b/sros2/package.xml
@@ -15,6 +15,7 @@
python3-lxml
python3-cryptography
+ python3-pandas
ament_copyright
ament_flake8
diff --git a/sros2/scripts/dds_sql_to_sros2_policy.py b/sros2/scripts/dds_sql_to_sros2_policy.py
new file mode 100755
index 00000000..63d0aafb
--- /dev/null
+++ b/sros2/scripts/dds_sql_to_sros2_policy.py
@@ -0,0 +1,151 @@
+#! /usr/bin/env python3
+
+import argparse
+import os
+import pandas as pd
+import sqlite3
+import sys
+
+from lxml import etree
+
+from sros2.policy import (
+ get_policy_schema,
+ get_transport_schema,
+ get_transport_template,
+ POLICY_VERSION,
+)
+
+node_query = """
+SELECT DISTINCT
+ DCPSParticipant.ParticipantData_key,
+ DCPSParticipant.ParticipantData_user_data
+FROM DCPSParticipant
+WHERE DCPSParticipant.ParticipantData_user_data IS NOT NULL;
+"""
+
+_query = """
+SELECT DISTINCT
+ DCPSParticipant.ParticipantData_key,
+ DCPSParticipant.ParticipantData_user_data,
+ DCPS{mode}.{mode}Data_topic_name
+FROM DCPSParticipant
+INNER JOIN DCPS{mode} ON
+ DCPSParticipant.ParticipantData_key = DCPS{mode}.{mode}Data_participant_key
+AND DCPSParticipant.ParticipantData_user_data IS NOT NULL;
+"""
+
+node_pub_query = _query.format(mode="Publication")
+node_sub_query = _query.format(mode="Subscription")
+
+
+def user_bytes_to_dict(user_bytes):
+ try:
+ user_string = user_bytes.decode('utf8')
+ key_value_list = user_string[:-2].split(';')
+ key_value_dict = dict()
+ for key_values in key_value_list:
+ key, value = key_values.split('=', 1)
+ key_value_dict[key] = value
+ return key_value_dict
+ except:
+ return None
+
+
+def translate_df(df):
+ _df = df['ParticipantData_user_data'] \
+ .apply(user_bytes_to_dict) \
+ .apply(pd.Series)
+ df = pd.concat([df, _df], axis=1)
+ return df
+
+
+def db_to_df(db):
+ node_df = translate_df(pd.read_sql_query(node_query, db))
+ pub_df = translate_df(pd.read_sql_query(node_pub_query, db))
+ sub_df = translate_df(pd.read_sql_query(node_sub_query, db))
+
+ pub_df = pub_df.assign(mode='publish')
+ pub_df = pub_df.rename(columns={"PublicationData_topic_name": "dds_topic"})
+ sub_df = sub_df.assign(mode='subscribe')
+ sub_df = sub_df.rename(columns={"SubscriptionData_topic_name": "dds_topic"})
+
+ df = pd.concat([node_df, pub_df, sub_df])
+ df = df[df['namespace'].notnull()]
+ df.set_index(['namespace', 'name', 'mode'], inplace=True)
+ return df
+
+
+def df_to_dds_policy(df):
+ dds_policy = etree.Element('policy')
+ dds_policy.set("version", POLICY_VERSION,)
+ profiles = etree.SubElement(dds_policy, 'profiles')
+
+ for namespace in df.index.get_level_values('namespace').unique():
+ _df = df.loc[namespace, :, :]
+ for name in _df.index.get_level_values('name').unique():
+ profile = etree.SubElement(profiles, 'profile')
+ profile.set("ns", namespace)
+ profile.set("node", name)
+ __df = df.loc[namespace, name, :]
+ for mode in __df.index.get_level_values('mode').unique():
+ if not pd.isna(mode):
+ topics = etree.SubElement(profile, 'raws')
+ topics.set(mode, "ALLOW")
+ for dds_topic in df['dds_topic'].loc[namespace, name, mode]:
+ topic = etree.SubElement(topics, 'raw')
+ topic.text = dds_topic
+ return dds_policy
+
+
+def dds_policy_to_sros2_policy(dds_policy):
+
+ # Parse files
+ sros2_policy_xsd = etree.XMLSchema(
+ etree.parse(
+ get_policy_schema('policy.xsd')))
+ dds_policy_xsd = etree.XMLSchema(
+ etree.parse(
+ get_transport_schema('dds', 'policy.xsd')))
+ dds_demangle_xsl = etree.XSLT(
+ etree.parse(
+ get_transport_template('dds', 'demangle.xsl')))
+
+ # Validate input schema
+ dds_policy_xsd.assertValid(dds_policy)
+
+ # Transform policy
+ sros2_policy = dds_demangle_xsl(dds_policy)
+
+ # Validate output schema
+ sros2_policy_xsd.assertValid(sros2_policy)
+
+ return sros2_policy
+
+
+def main(argv=sys.argv[1:]):
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+ parser.add_argument(
+ '-i', '--input-db', required=True,
+ help='path to SQLite3 database with discovery data')
+ parser.add_argument(
+ '-o', '--output-policy',
+ help='path to XML policy file with generated output')
+ args = parser.parse_args(argv)
+
+ db_uri = 'file:{}?mode=ro'.format(args.input_db)
+ with sqlite3.connect(db_uri, uri=True) as db:
+ df = db_to_df(db)
+
+ dds_policy = df_to_dds_policy(df)
+ sros2_policy = dds_policy_to_sros2_policy(dds_policy)
+
+ if args.output_policy is not None:
+ with open(args.output_policy, 'wb') as f:
+ f.write(etree.tostring(sros2_policy, pretty_print=True))
+ else:
+ print(etree.tostring(sros2_policy, pretty_print=True).decode())
+
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/sros2/sros2/policy/schemas/dds/policy.xsd b/sros2/sros2/policy/schemas/dds/policy.xsd
new file mode 100644
index 00000000..96698c19
--- /dev/null
+++ b/sros2/sros2/policy/schemas/dds/policy.xsd
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sros2/sros2/policy/templates/dds/demangle.xsl b/sros2/sros2/policy/templates/dds/demangle.xsl
new file mode 100644
index 00000000..3cbdb1b7
--- /dev/null
+++ b/sros2/sros2/policy/templates/dds/demangle.xsl
@@ -0,0 +1,494 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sros2/sros2/policy/templates/dds/permissions.xsl b/sros2/sros2/policy/templates/dds/permissions.xsl
index 8a243da2..5b346843 100644
--- a/sros2/sros2/policy/templates/dds/permissions.xsl
+++ b/sros2/sros2/policy/templates/dds/permissions.xsl
@@ -73,6 +73,9 @@
+
+
+
@@ -90,6 +93,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+