-
Notifications
You must be signed in to change notification settings - Fork 11
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
Support nested variable groups #537
Changes from 3 commits
aca608f
c6c1a2a
1c6c578
8b4c155
94ce775
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -562,6 +562,7 @@ struct variable_group_description | |
std::string name; | ||
std::string type; | ||
std::vector<std::string> variables; | ||
std::vector<variable_group_description> variable_group_descriptions; | ||
}; | ||
|
||
struct extended_model_description | ||
|
@@ -582,19 +583,28 @@ struct extended_model_description | |
const auto variableGroupsElement = static_cast<xercesc::DOMElement*>(rootElement->getElementsByTagName(tc("VariableGroups").get())->item(0)); | ||
|
||
for (auto variableGroupElement = variableGroupsElement->getFirstElementChild(); variableGroupElement != nullptr; variableGroupElement = variableGroupElement->getNextElementSibling()) { | ||
variable_group_description vgd; | ||
vgd.name = tc(variableGroupElement->getAttribute(tc("name").get())).get(); | ||
vgd.type = tc(variableGroupElement->getAttribute(tc("type").get())).get(); | ||
variable_group_description vgd = create_variable_group_description(variableGroupElement); | ||
variableGroups[vgd.name] = std::move(vgd); | ||
} | ||
} | ||
|
||
auto variableElements = variableGroupElement->getElementsByTagName(tc("Variable").get()); | ||
for (size_t i = 0; i < variableElements->getLength(); i++) { | ||
auto variableElement = static_cast<xercesc::DOMElement*>(variableElements->item(i)); | ||
static variable_group_description create_variable_group_description(xercesc::DOMElement *variableGroupElement) { | ||
variable_group_description variableGroupDescription; | ||
|
||
std::string variableName = tc(variableElement->getAttribute(tc("name").get())).get(); | ||
vgd.variables.push_back(std::move(variableName)); | ||
variableGroupDescription.name = tc(variableGroupElement->getAttribute(tc("name").get())).get(); | ||
variableGroupDescription.type = tc(variableGroupElement->getTagName()).get(); | ||
|
||
for (auto variableGroupChildElement = variableGroupElement->getFirstElementChild(); variableGroupChildElement != nullptr; variableGroupChildElement = variableGroupChildElement->getNextElementSibling()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are some reeeeally long lines of code in this file, and it's actually a bit tricky to see the end of lines like this one due to how GitHub places the horizontal scroll bar. I'm not going to suggest that we use this PR to reformat the entire file, but it would be nice if added/modified code was made a tad more readable. ;) |
||
std::string tagName(tc(variableGroupChildElement->getTagName()).get()); | ||
if (tagName == "Variable") { | ||
std::string variableName = tc(variableGroupChildElement->getAttribute(tc("ref").get())).get(); | ||
variableGroupDescription.variables.push_back(std::move(variableName)); | ||
} else { | ||
variableGroupDescription.variable_group_descriptions.push_back(create_variable_group_description(variableGroupChildElement)); | ||
} | ||
variableGroups[vgd.name] = std::move(vgd); | ||
} | ||
|
||
return variableGroupDescription; | ||
} | ||
|
||
std::unordered_map<std::string, variable_group_description> variableGroups; | ||
|
@@ -722,13 +732,35 @@ std::vector<std::string> get_variable_group_variables( | |
{ | ||
auto groupIt = descriptions.find(connector); | ||
if (groupIt == descriptions.end()) { | ||
for (const auto& description : descriptions) { | ||
if (description.second.variable_group_descriptions.size() != 0) { | ||
std::unordered_map<std::string, variable_group_description> nestedDescriptions; | ||
for (const auto& variableGroupDescr : description.second.variable_group_descriptions) { | ||
nestedDescriptions.insert({variableGroupDescr.name, variableGroupDescr}); | ||
} | ||
return get_variable_group_variables(nestedDescriptions, element, connector); | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't like to build up the nestedDescription map here. If the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. Is there any reason to not make it a map? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't think so. Just didn't want to make changes in the parser now. Let's do this as a separate refactoring task for the ´cse_config_parser´ |
||
std::ostringstream oss; | ||
oss << "Cannot find variable group description: " << element << ":" << connector; | ||
throw std::out_of_range(oss.str()); | ||
} | ||
return groupIt->second.variables; | ||
} | ||
|
||
std::vector<cse::variable_group_description> get_variable_groups( | ||
const std::unordered_map<std::string, variable_group_description>& descriptions, | ||
const std::string& connector) | ||
{ | ||
auto groupIt = descriptions.find(connector); | ||
if (groupIt == descriptions.end()) { | ||
std::ostringstream oss; | ||
oss << "Cannot find variable group for " << connector; | ||
throw std::out_of_range(oss.str()); | ||
} | ||
return groupIt->second.variable_group_descriptions; | ||
} | ||
|
||
void connect_variable_groups( | ||
const std::vector<cse_config_parser::VariableConnection>& variableGroupConnections, | ||
const std::unordered_map<std::string, slave_info>& slaves, | ||
|
@@ -744,6 +776,23 @@ void connect_variable_groups( | |
const auto& variablesB = | ||
get_variable_group_variables(emdB.variableGroups, connection.variableB.simulator, connection.variableB.name); | ||
|
||
if (variablesA.size() == 0 || variablesB.size() == 0) { | ||
// Variables for the connection cannot be found directly under any of the variable groups. | ||
// The connection refers to a variableGroup with variableGroups. | ||
const auto& variableGroupsA = get_variable_groups(emdA.variableGroups, connection.variableA.name); | ||
const auto& variableGroupsB = get_variable_groups(emdB.variableGroups, connection.variableB.name); | ||
|
||
std::vector<cse_config_parser::VariableConnection> nestedVariableGroupConnections; | ||
// clang-format off | ||
for (std::size_t i = 0; i < variableGroupsA.size(); ++i) { | ||
nestedVariableGroupConnections.push_back({ | ||
{connection.variableA.simulator, variableGroupsA.at(i).name}, | ||
{connection.variableB.simulator, variableGroupsB.at(i).name}}); | ||
} | ||
// clang-format on | ||
connect_variable_groups(nestedVariableGroupConnections, slaves, execution, emds); | ||
} | ||
|
||
if (variablesA.size() != variablesB.size()) { | ||
std::ostringstream oss; | ||
oss << "Cannot create connection between variable groups. Variable group " | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,15 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<OspModelDescription xmlns="http://opensimulationplatform.com/MSMI/OSPModelDescription"> | ||
<VariableGroups> | ||
<VariableGroup type="generic" name="input"> | ||
<Variable name="input[0]"/> | ||
<Variable name="input[1]"/> | ||
<Variable name="input[2]"/> | ||
</VariableGroup> | ||
<VariableGroup type="generic" name="output"> | ||
<Variable name="output[0]"/> | ||
<Variable name="output[1]"/> | ||
<Variable name="output[2]"/> | ||
</VariableGroup> | ||
<Generic name="input"> | ||
<Variable ref="input[0]"/> | ||
<Variable ref="input[1]"/> | ||
<Variable ref="input[2]"/> | ||
</Generic> | ||
<Generic name="output"> | ||
<Variable ref="output[0]"/> | ||
<Variable ref="output[1]"/> | ||
<Variable ref="output[2]"/> | ||
</Generic> | ||
</VariableGroups> | ||
</OspModelDescription> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,68 +1,66 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" | ||
targetNamespace="http://opensimulationplatform.com/MSMI/OSPModelDescription" | ||
xmlns:osp="http://opensimulationplatform.com/MSMI/OSPModelDescription" | ||
xmlns="http://opensimulationplatform.com/MSMI/OSPModelDescription" | ||
version="0.1"> | ||
<xs:include schemaLocation="fmi2Unit.xsd"/> | ||
<xs:element name="OspModelDescription" type="osp:OspModelDescriptionType"/> | ||
<xs:element name="OspModelDescription" type="OspModelDescriptionType"/> | ||
<xs:complexType name="UnitDefinitionsType"> | ||
<xs:sequence minOccurs="0" maxOccurs="unbounded"> | ||
<xs:element type="osp:fmi2Unit" name="Unit"/> | ||
<xs:element type="fmi2Unit" name="Unit"/> | ||
</xs:sequence> | ||
</xs:complexType> | ||
<xs:complexType name="VariableType"> | ||
<xs:simpleContent> | ||
<xs:extension base="xs:string"> | ||
<xs:attribute type="xs:string" name="ref" use="required"/> | ||
<xs:attribute type="xs:string" name="unit"/> | ||
</xs:extension> | ||
</xs:simpleContent> | ||
</xs:complexType> | ||
<xs:complexType name="ForceType"> | ||
<xs:sequence> | ||
<xs:element type="VariableType" name="Variable" maxOccurs="3" minOccurs="1"/> | ||
</xs:sequence> | ||
<xs:attribute type="xs:string" name="name" use="required"/> | ||
<xs:attribute type="xs:string" name="unit" use="optional"/> | ||
</xs:complexType> | ||
<xs:complexType name="VariableGroupType"> | ||
<xs:choice maxOccurs="unbounded" minOccurs="0"> | ||
<xs:element type="osp:VariableType" name="Variable"/> | ||
<xs:element type="osp:VariableGroupType" name="VariableGroup"/> | ||
</xs:choice> | ||
<xs:complexType name="LinearVelocityType"> | ||
<xs:sequence> | ||
<xs:element type="VariableType" name="Variable" maxOccurs="3" minOccurs="1"/> | ||
</xs:sequence> | ||
<xs:attribute type="xs:string" name="name" use="required"/> | ||
<xs:attribute name="type" use="required"> | ||
<xs:simpleType> | ||
<xs:restriction base="xs:string"> | ||
<xs:enumeration value="generic"/> | ||
|
||
<xs:enumeration value="force"/> | ||
<xs:enumeration value="linear_velocity"/> | ||
<xs:enumeration value="linear_displacement"/> | ||
|
||
<xs:enumeration value="torque"/> | ||
<xs:enumeration value="angular_velocity"/> | ||
<xs:enumeration value="angular_displacement"/> | ||
|
||
<xs:enumeration value="voltage"/> | ||
<xs:enumeration value="current"/> | ||
<xs:enumeration value="charge"/> | ||
|
||
<xs:enumeration value="pressure"/> | ||
<xs:enumeration value="volume_rate_flow"/> | ||
<xs:enumeration value="volume"/> | ||
|
||
<xs:enumeration value="linear_mechanical_port"/> | ||
<xs:enumeration value="angular_mechanical_port"/> | ||
<xs:enumeration value="electromagnetic_port"/> | ||
<xs:enumeration value="hydraulic_port"/> | ||
</xs:restriction> | ||
</xs:simpleType> | ||
</xs:attribute> | ||
</xs:complexType> | ||
<xs:complexType name="VariableGroupsType"> | ||
<xs:sequence minOccurs="0" maxOccurs="unbounded"> | ||
<xs:element type="osp:VariableGroupType" name="VariableGroup"/> | ||
<xs:complexType name="LinearMechanicalPortType"> | ||
<xs:sequence> | ||
<xs:element type="ForceType" name="Force"/> | ||
<xs:element type="LinearVelocityType" name="LinearVelocity"/> | ||
</xs:sequence> | ||
<xs:attribute type="xs:string" name="name" use="required"/> | ||
</xs:complexType> | ||
<xs:complexType name="GenericType"> | ||
<xs:complexContent> | ||
<xs:extension base="VariableGroupSequenceType"> | ||
<xs:choice> | ||
<xs:element type="VariableType" name="Variable" maxOccurs="unbounded" minOccurs="0"/> | ||
</xs:choice> | ||
<xs:attribute type="xs:string" name="name" use="required"/> | ||
</xs:extension> | ||
</xs:complexContent> | ||
|
||
</xs:complexType> | ||
<xs:complexType name="VariableGroupSequenceType"> | ||
<xs:choice maxOccurs="unbounded" minOccurs="0"> | ||
<xs:element type="ForceType" name="Force"/> | ||
<xs:element type="LinearMechanicalPortType" name="LinearMechanicalPort"/> | ||
<xs:element type="LinearVelocityType" name="LinearVelocity"/> | ||
<xs:element type="GenericType" name="Generic"/> | ||
</xs:choice> | ||
</xs:complexType> | ||
<xs:complexType name="OspModelDescriptionType"> | ||
<xs:sequence> | ||
<xs:element type="osp:UnitDefinitionsType" name="UnitDefinitions" minOccurs="0"/> | ||
<xs:element type="osp:VariableGroupsType" name="VariableGroups"/> | ||
<xs:element type="UnitDefinitionsType" name="UnitDefinitions" minOccurs="0"/> | ||
<xs:element type="VariableGroupSequenceType" name="VariableGroups"/> | ||
</xs:sequence> | ||
<xs:attribute name="version" type="xs:string" use="required" fixed="0.1"> | ||
<xs:annotation> | ||
<xs:documentation>OspModelDescription version</xs:documentation> | ||
</xs:annotation> | ||
</xs:attribute> | ||
<xs:attribute type="xs:string" name="version"/> | ||
</xs:complexType> | ||
</xs:schema> | ||
</xs:schema> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think
groups
orsubgroups
would be a more descriptive name for this.