diff --git a/README.md b/README.md index c57ba7937..ae23c7d52 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ Publications: - Combine components to form a ROS System - [Create manually a new RosSystem description](docu/RosSystemModelDescription.md) + - [Visualize a system using PlantUML](docu/PlantUML.md) - Examples: - [Simple publisher-subscriber](docu/Example_PubSub.md) diff --git a/docu/PlantUML.md b/docu/PlantUML.md new file mode 100644 index 000000000..1e2f0034b --- /dev/null +++ b/docu/PlantUML.md @@ -0,0 +1,8 @@ +## System Models visualization + +The visualization of the models is built on top of the [PlantUML](https://plantuml.com/eclipse) viewer for Eclipse. To install this plugin the Eclipse Marketplace can be used. This tool can be easily opened under the menu Help->Eclipse Marketplace. Then Search the "PlantUML plugin" and install it. + +The RosTooling will generate for every rossystem file a new PlaUML textual model compatible with the viewer. By default, the RosSystem compiler creates for every valid system model a file under src-gen/**SystemName**/resources/ called **SystemName**.puml. + +The file can be opened with a standard textual editor and the corresponding model can be visualized by opening the visualizer, under "Window"->"Show View"->"Other" and searching for "PlantUML". +:bangbang the file with the extension *.puml must be open, otherwise, the visualizer will not detect it. diff --git a/plugins/de.fraunhofer.ipa.ros.feature/feature.xml b/plugins/de.fraunhofer.ipa.ros.feature/feature.xml index 8d90d5703..3c88c1a73 100644 --- a/plugins/de.fraunhofer.ipa.ros.feature/feature.xml +++ b/plugins/de.fraunhofer.ipa.ros.feature/feature.xml @@ -66,135 +66,82 @@ POSSIBILITY OF SUCH DAMAGE. + version="3.0.0.qualifier"/> + version="3.0.0.qualifier"/> + version="3.0.0.qualifier"/> + version="3.0.0.qualifier"/> + version="3.0.0.qualifier"/> + version="3.0.0.qualifier"/> + version="3.0.0.qualifier"/> + version="3.0.0.qualifier"/> + version="3.0.0.qualifier"/> + version="3.0.0.qualifier"/> + version="3.0.0.qualifier"/> + version="3.0.0.qualifier"/> + version="3.0.0.qualifier"/> + version="3.0.0.qualifier"/> + version="3.0.0.qualifier"/> + version="3.0.0.qualifier"/> + version="3.0.0.qualifier"/> + version="3.0.0.qualifier"/> + version="3.0.0.qualifier"/> + + diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/.classpath b/plugins/de.fraunhofer.ipa.ros.sirius/.classpath new file mode 100644 index 000000000..39810b7d6 --- /dev/null +++ b/plugins/de.fraunhofer.ipa.ros.sirius/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/.project b/plugins/de.fraunhofer.ipa.ros.sirius/.project new file mode 100644 index 000000000..1cb0d20a5 --- /dev/null +++ b/plugins/de.fraunhofer.ipa.ros.sirius/.project @@ -0,0 +1,28 @@ + + + de.fraunhofer.ipa.ros.sirius + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/META-INF/MANIFEST.MF b/plugins/de.fraunhofer.ipa.ros.sirius/META-INF/MANIFEST.MF new file mode 100644 index 000000000..e7b9c2dfa --- /dev/null +++ b/plugins/de.fraunhofer.ipa.ros.sirius/META-INF/MANIFEST.MF @@ -0,0 +1,23 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: de.fraunhofer.ipa.ros.sirius;singleton:=true +Bundle-Version: 3.0.0.qualifier +Bundle-Activator: de.fraunhofer.ipa.ros.sirius.Activator +Bundle-Localization: plugin +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.core.resources, + org.eclipse.sirius, + org.eclipse.sirius.common.acceleo.aql, + de.fraunhofer.ipa.ros, + org.eclipse.ui.workbench, + org.eclipse.ui.ide, + org.eclipse.sirius.common, + org.eclipse.sirius.diagram.ui, + de.fraunhofer.ipa.rossystem +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-19 +Bundle-Vendor: Fraunhofer IPA +Automatic-Module-Name: de.fraunhofer.ipa.ros.sirius +Export-Package: de.fraunhofer.ipa.ros.sirius diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/build.properties b/plugins/de.fraunhofer.ipa.ros.sirius/build.properties new file mode 100644 index 000000000..ec79d6f85 --- /dev/null +++ b/plugins/de.fraunhofer.ipa.ros.sirius/build.properties @@ -0,0 +1,8 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + description/,\ + icons/,\ + plugin.properties,\ + plugin.xml diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/description/ros.odesign b/plugins/de.fraunhofer.ipa.ros.sirius/description/ros.odesign new file mode 100644 index 000000000..3284da905 --- /dev/null +++ b/plugins/de.fraunhofer.ipa.ros.sirius/description/ros.odesign @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/icons/action_icon.png b/plugins/de.fraunhofer.ipa.ros.sirius/icons/action_icon.png new file mode 100644 index 000000000..9c55be371 Binary files /dev/null and b/plugins/de.fraunhofer.ipa.ros.sirius/icons/action_icon.png differ diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/icons/component.gif b/plugins/de.fraunhofer.ipa.ros.sirius/icons/component.gif new file mode 100644 index 000000000..38c86d700 Binary files /dev/null and b/plugins/de.fraunhofer.ipa.ros.sirius/icons/component.gif differ diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/icons/component.svg b/plugins/de.fraunhofer.ipa.ros.sirius/icons/component.svg new file mode 100644 index 000000000..a0833a9f8 --- /dev/null +++ b/plugins/de.fraunhofer.ipa.ros.sirius/icons/component.svg @@ -0,0 +1,85 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/icons/parameters.png b/plugins/de.fraunhofer.ipa.ros.sirius/icons/parameters.png new file mode 100644 index 000000000..d416b0639 Binary files /dev/null and b/plugins/de.fraunhofer.ipa.ros.sirius/icons/parameters.png differ diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/icons/parameters_scale.png b/plugins/de.fraunhofer.ipa.ros.sirius/icons/parameters_scale.png new file mode 100644 index 000000000..dc7f646e4 Binary files /dev/null and b/plugins/de.fraunhofer.ipa.ros.sirius/icons/parameters_scale.png differ diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/icons/ros_logo.png b/plugins/de.fraunhofer.ipa.ros.sirius/icons/ros_logo.png new file mode 100644 index 000000000..3362fc8c8 Binary files /dev/null and b/plugins/de.fraunhofer.ipa.ros.sirius/icons/ros_logo.png differ diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/icons/service_icon.png b/plugins/de.fraunhofer.ipa.ros.sirius/icons/service_icon.png new file mode 100644 index 000000000..f12579237 Binary files /dev/null and b/plugins/de.fraunhofer.ipa.ros.sirius/icons/service_icon.png differ diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/icons/tools.png b/plugins/de.fraunhofer.ipa.ros.sirius/icons/tools.png new file mode 100644 index 000000000..eedac5f3e Binary files /dev/null and b/plugins/de.fraunhofer.ipa.ros.sirius/icons/tools.png differ diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/icons/topic_icon.png b/plugins/de.fraunhofer.ipa.ros.sirius/icons/topic_icon.png new file mode 100644 index 000000000..f46018756 Binary files /dev/null and b/plugins/de.fraunhofer.ipa.ros.sirius/icons/topic_icon.png differ diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/plugin.properties b/plugins/de.fraunhofer.ipa.ros.sirius/plugin.properties new file mode 100644 index 000000000..3d2dd03b6 --- /dev/null +++ b/plugins/de.fraunhofer.ipa.ros.sirius/plugin.properties @@ -0,0 +1,3 @@ +pluginName = de.fraunhofer.ipa.ros.sirius +providerName = Fraunhofer IPA +viewpointName = MyViewpoint diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/plugin.xml b/plugins/de.fraunhofer.ipa.ros.sirius/plugin.xml new file mode 100644 index 000000000..d0f3d8277 --- /dev/null +++ b/plugins/de.fraunhofer.ipa.ros.sirius/plugin.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/pom.xml b/plugins/de.fraunhofer.ipa.ros.sirius/pom.xml new file mode 100644 index 000000000..a32cf1464 --- /dev/null +++ b/plugins/de.fraunhofer.ipa.ros.sirius/pom.xml @@ -0,0 +1,12 @@ + + 4.0.0 + + de.fraunhofer.ipa.ros + de.fraunhofer.ipa.ros.parent + 2.0.0-SNAPSHOT + ../de.fraunhofer.ipa.ros.parent/pom.xml + + de.fraunhofer.ipa.ros.sirius + eclipse-plugin + diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/src/de/fraunhofer/ipa/ros/sirius/Activator.java b/plugins/de.fraunhofer.ipa.ros.sirius/src/de/fraunhofer/ipa/ros/sirius/Activator.java new file mode 100644 index 000000000..34c320476 --- /dev/null +++ b/plugins/de.fraunhofer.ipa.ros.sirius/src/de/fraunhofer/ipa/ros/sirius/Activator.java @@ -0,0 +1,66 @@ +package de.fraunhofer.ipa.ros.sirius; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.sirius.business.api.componentization.ViewpointRegistry; +import org.eclipse.sirius.viewpoint.description.Viewpoint; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + // The plug-in ID + public static final String PLUGIN_ID = "de.fraunhofer.ipa.ros.sirius"; + + // The shared instance + private static Activator plugin; + + private static Set viewpoints; + + /** + * The constructor + */ + public Activator() { + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + viewpoints = new HashSet(); + viewpoints.addAll(ViewpointRegistry.getInstance().registerFromPlugin(PLUGIN_ID + "/description/ros.odesign")); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + if (viewpoints != null) { + for (final Viewpoint viewpoint: viewpoints) { + ViewpointRegistry.getInstance().disposeFromPlugin(viewpoint); + } + viewpoints.clear(); + viewpoints = null; + } + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } +} diff --git a/plugins/de.fraunhofer.ipa.ros.sirius/src/de/fraunhofer/ipa/ros/sirius/Services.java b/plugins/de.fraunhofer.ipa.ros.sirius/src/de/fraunhofer/ipa/ros/sirius/Services.java new file mode 100644 index 000000000..b66fddb9e --- /dev/null +++ b/plugins/de.fraunhofer.ipa.ros.sirius/src/de/fraunhofer/ipa/ros/sirius/Services.java @@ -0,0 +1,17 @@ +package de.fraunhofer.ipa.ros.sirius; + +import org.eclipse.emf.ecore.EObject; + +/** + * The services class used by VSM. + */ +public class Services { + + /** + * See http://help.eclipse.org/neon/index.jsp?topic=%2Forg.eclipse.sirius.doc%2Fdoc%2Findex.html&cp=24 for documentation on how to write service methods. + */ + public EObject myService(EObject self, String arg) { + // TODO Auto-generated code + return self; + } +} diff --git a/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/PlantUMLCompiler.xtend b/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/PlantUMLCompiler.xtend new file mode 100644 index 000000000..8562d882c --- /dev/null +++ b/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/PlantUMLCompiler.xtend @@ -0,0 +1,86 @@ +package de.fraunhofer.ipa.rossystem.generator + +import system.System +import com.google.inject.Inject +import system.RosNode +import system.impl.RosInterfaceImpl +import system.RosInterface +import system.impl.RosSystemConnectionImpl + +class PlantUMLCompiler{ + + @Inject extension GeneratorHelpers + + def compile_plantuml(System system) '''«init_pkg()» +@startuml + +/'SUBSYSTEMS'/ +«FOR subsystem:system.subsystems» +component «subsystem.name» { +«FOR component:getNodes(subsystem)» +«compile_ports(component)» +«ENDFOR» } +«ENDFOR» + +«FOR component:getNodes(system)» +«compile_ports(component)» +«ENDFOR» +«FOR connection:system.connections» «get_connection_port((connection as RosSystemConnectionImpl).from)» --> «get_connection_port((connection as RosSystemConnectionImpl).to)» +«ENDFOR» + +@enduml''' + + + def compile_ports(RosNode component)''' + component «(component as RosNode).name» { + + /' PORTS DEFINED AS AVAILABLE IN THE ROSSYSTEM FILE '/ + «FOR port:(component as RosNode).rosinterfaces» + «IF port_type(port)=="INPUT"» portin «get_valid_name(component.name, port.name)» as "«port.name»"« + IF (port as RosInterfaceImpl).reference.toString.contains("RosSubscriberReference")» #blue«ENDIF»« + IF (port as RosInterfaceImpl).reference.toString.contains("RosServiceServerReference")» #orange«ENDIF»« + IF (port as RosInterfaceImpl).reference.toString.contains("RosActionServerReference")» #green«ENDIF»«ENDIF» + «IF port_type(port)=="OUTPUT"» portout «get_valid_name(component.name, port.name)» as "«port.name»"« + IF (port as RosInterfaceImpl).reference.toString.contains("RosPublisherReference")» #blue«ENDIF»« + IF (port as RosInterfaceImpl).reference.toString.contains("RosServiceClientReference")» #orange«ENDIF»« + IF (port as RosInterfaceImpl).reference.toString.contains("RosActionClientReference")» #green«ENDIF»«ENDIF» + «ENDFOR» + + /' PORTS FROM THE ORIGINAL NODE '/ +««« «FOR sub:(component as RosNode).from.subscriber» portin «get_valid_name(component.name, sub.name)» as "«sub.name»" #line:blue +««« «ENDFOR» +««« «FOR ss:(component as RosNode).from.serviceserver» portin «get_valid_name(component.name, ss.name)» as "«ss.name»" #line:orange +««« «ENDFOR» +««« «FOR acts:(component as RosNode).from.actionserver» portin «get_valid_name(component.name, acts.name)» as "«acts.name»" #line:green +««« «ENDFOR» +««« «FOR pub:(component as RosNode).from.publisher» portout «get_valid_name(component.name, pub.name)» as "«pub.name»" #line:blue +««« «ENDFOR» +««« «FOR sc:(component as RosNode).from.serviceclient» portout «get_valid_name(component.name, sc.name)» as "«sc.name»" #line:orange +««« «ENDFOR» +««« «FOR actc:(component as RosNode).from.actionclient» portout «get_valid_name(component.name, actc.name)» as "«actc.name»" #line:green«ENDFOR» + } + + ''' + + def String port_type (RosInterface rosinterface){ + if ((rosinterface as RosInterfaceImpl).reference.toString.matches + (".*RosSubscriberReferenceImpl.*|.*RosServiceServerReference.*|.*RosActionServerReference.*")){ + return "INPUT" + }else { + return "OUTPUT" + } + } + + def get_valid_name (String componentName, String PortName){ + val identifier = (componentName+"."+PortName).replace("/","_").replace("~","_") + return identifier + } + + def get_connection_port (RosInterface port){ + val componentName=(port.eContainer as RosNode).name + return get_valid_name (componentName, port.name) + } +} + + + diff --git a/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/RosSystemGenerator.xtend b/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/RosSystemGenerator.xtend index 7d8132130..44a260392 100644 --- a/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/RosSystemGenerator.xtend +++ b/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/RosSystemGenerator.xtend @@ -23,6 +23,7 @@ class RosSystemGenerator extends AbstractGenerator { @Inject extension PackageXmlCompiler @Inject extension CMakeListsCompiler @Inject extension READMECompiler + @Inject extension PlantUMLCompiler override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) { var yaml_gen = false @@ -31,6 +32,10 @@ class RosSystemGenerator extends AbstractGenerator { system.getName().toLowerCase+"/README.md", compile_toREADME(system).toString().replace("\t"," ") ) + fsa.generateFile( + system.getName().toLowerCase+"/resource/" + system.getName().toLowerCase + ".puml", + compile_plantuml(system) + ) if (system.fromFile.isNullOrEmpty) { fsa.generateFile( system.getName().toLowerCase+"/launch/"+system.getName()+".launch.py",