Skip to content
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

First implementation of the PlantUML generator #215

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 8 additions & 0 deletions docu/PlantUML.md
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -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)
}
}



Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,18 @@ 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) {
for (system : resource.allContents.toIterable.filter(System)){
fsa.generateFile(
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",
Expand Down
Loading