-
Notifications
You must be signed in to change notification settings - Fork 53
Pipeline for policy generation from DDS discovery data #153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
ruffsl
wants to merge
18
commits into
ros2:rolling
Choose a base branch
from
ruffsl:dds_to_sros_pipline
base: rolling
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
b594b76
Add initial template to demangle DDS to SROS2
ruffsl a0fae7e
Deduplicate and alpha sort elements/atrabutes
ruffsl ab536cb
Remove dead code
ruffsl eed8d6b
Set unique mode for substation
ruffsl 76242a4
Adding deduplicate namespace and compress for profiles
ruffsl cf64361
Check in initial discovery sqlite script
ruffsl 527bfc7
Fix typo for execute
ruffsl 3f8c81c
Fix typo for policy
ruffsl e06b247
Correct indexing to include mode
ruffsl 1fa8af4
Rename to dds/demangle.xml
ruffsl 350e37b
Clean up notebook into runnable script
ruffsl c6e061d
Fix unintended node and namespace combinatorial
ruffsl b0b6441
Declare python dependency for pandas
ruffsl 054dd80
Check for unintelligible or missing QoS data
ruffsl c1534d2
Fix typos in compression
ruffsl d71c75b
Fix file output
ruffsl 5e03e8d
Add raw permission type
ruffsl 850fedc
Separate raw changes into different schema for now
ruffsl File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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() | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <xs:schema | ||
| xmlns:xs="http://www.w3.org/2001/XMLSchema" | ||
| xmlns:xml="http://www.w3.org/XML/1998/namespace" | ||
| elementFormDefault="qualified" attributeFormDefault="unqualified"> | ||
| <xs:import namespace="http://www.w3.org/XML/1998/namespace" | ||
| schemaLocation="http://www.w3.org/2001/03/xml.xsd" /> | ||
| <!-- TODO: Use namespaces for xs:import so schemas can be DRY --> | ||
|
|
||
| <xs:element name="policy" type="Policy" /> | ||
| <xs:complexType name="Policy"> | ||
| <xs:sequence minOccurs="1" maxOccurs="1"> | ||
| <xs:element name="profiles" type="Profiles" /> | ||
| </xs:sequence> | ||
| <xs:attribute name="version" type="xs:string" use="required" /> | ||
| </xs:complexType> | ||
|
|
||
| <xs:complexType name="Profiles"> | ||
| <xs:sequence minOccurs="1" maxOccurs="unbounded"> | ||
| <xs:element name="profile" type="Profile" /> | ||
| </xs:sequence> | ||
| </xs:complexType> | ||
|
|
||
| <xs:complexType name="Profile"> | ||
| <xs:sequence minOccurs="0" maxOccurs="unbounded"> | ||
| <xs:choice minOccurs="1" maxOccurs="1"> | ||
| <xs:element name="raws" minOccurs="1" type="RawExpressionList" /> | ||
| </xs:choice> | ||
| </xs:sequence> | ||
| <xs:attribute name="ns" type="xs:string" use="required" /> | ||
| <xs:attribute name="node" type="xs:string" use="required" /> | ||
| <xs:attribute ref="xml:base" /> | ||
| </xs:complexType> | ||
|
|
||
| <xs:complexType name="RawExpressionList"> | ||
| <xs:sequence minOccurs="1" maxOccurs="unbounded"> | ||
| <xs:element name="raw" type="Expression" /> | ||
| </xs:sequence> | ||
| <xs:attribute name="publish" type="RuleQualifier" use="optional" /> | ||
| <xs:attribute name="relay" type="RuleQualifier" use="optional" /> | ||
| <xs:attribute name="subscribe" type="RuleQualifier" use="optional" /> | ||
| <xs:attribute ref="xml:base" /> | ||
| </xs:complexType> | ||
|
|
||
| <xs:simpleType name="Expression"> | ||
| <xs:restriction base="xs:string" /> | ||
| </xs:simpleType> | ||
|
|
||
| <xs:simpleType name="RuleQualifier"> | ||
| <xs:restriction base="xs:string"> | ||
| <xs:enumeration value="ALLOW" /> | ||
| <xs:enumeration value="DENY" /> | ||
| </xs:restriction> | ||
| </xs:simpleType> | ||
|
|
||
| </xs:schema> |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.