Skip to content

Commit

Permalink
Implement generator templates (Xtend) for RosSystem models to support
Browse files Browse the repository at this point in the history
the new attribute ComponentStacks; the generation pipeline is
consequently adapted
  • Loading branch information
ipa-rwu authored and ipa-nhg committed Aug 26, 2021
1 parent d222602 commit e4f53e6
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ package de.fraunhofer.ipa.rossystem.generator

import com.google.inject.Inject
import rossystem.RosSystem
import rossystem.ComponentStack

class CMakeListsCompiler {

@Inject extension GeneratorHelpers


def compile_CMakeLists_ROS1(RosSystem system) '''«init_pkg()»
def compile_CMakeLists_ROS1(RosSystem system, ComponentStack stack) '''«init_pkg()»
cmake_minimum_required(VERSION 2.8.3)
projectsystem.name.toLowerCase»)
projectIF stack===null»«system.name.toLowerCase»«ELSE»«system.name.toLowerCase»_«stack.name.toLowerCase»«ENDIF»)

find_package(catkin REQUIRED)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package de.fraunhofer.ipa.rossystem.generator

import com.google.inject.Inject
import rossystem.RosSystem
import rossystem.ComponentStack

class DockerComposeCompiler {

@Inject extension GeneratorHelpers

def compile_toDockerCompose(RosSystem system) '''«init_pkg()»
version: "3.3"
networks:
ros:
driver: bridge

services:
ros-master:
image: ros:melodic-ros-core
command: stdbuf -o L roscore
networks:
- ros

«FOR stack:system.componentStack»
«" "»«system.name.toLowerCase»_«stack.name.toLowerCase»:
image: "«system.name.toLowerCase»_«stack.name.toLowerCase»:latest"
depends_on:
- ros-master
environment:
- "ROS_MASTER_URI=http://ros-master:11311"
- "ROS_HOSTNAME=«stack.name.toLowerCase»"
networks:
- ros
command: stdbuf -o L roslaunch «system.name.toLowerCase»_«stack.name.toLowerCase» «stack.name.toLowerCase».launch --wait

«ENDFOR»

'''
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@ package de.fraunhofer.ipa.rossystem.generator

import com.google.inject.Inject
import rossystem.RosSystem
import rossystem.ComponentStack

class DockerContainerCompiler {

@Inject extension GeneratorHelpers

def compile_toDockerContainer(RosSystem system) '''«init_pkg()»
def compile_toDockerContainer(RosSystem system, ComponentStack stack) '''«init_pkg()»
# syntax=docker/dockerfile:experimental
ARG SUFFIX=
ARG PREFIX=
FROM ros:melodic-ros-core as base
FROM ${PREFIX}builder${SUFFIX} as builder

FROM base as build
COPY . /root/ws/src/«system.name.toLowerCase»/
COPY . /root/ws/src/«IF stack===null»«system.name.toLowerCase»«ELSE»«system.name.toLowerCase»_«stack.name.toLowerCase»«ENDIF»/
RUN --mount=type=bind,from=builder,target=/builder \
apt-get update -qq && \
/builder/workspace.bash build_workspace /root/ws && \
Expand Down Expand Up @@ -47,7 +48,7 @@ RUN --mount=type=bind,from=builder,target=/builder --mount=type=bind,target=/roo
COPY --from=install /opt/ros/$ROS_DISTRO /opt/ros/$ROS_DISTRO
FROM deploy as launch
CMD ["roslaunch", "«system.name»", "«system.name».launch"]
«IF stack===null»CMD ["roslaunch", "«system.name»", "«system.name».launch"]«ELSE»CMD ["roslaunch", "«system.name.toLowerCase»_«stack.name.toLowerCase»", "«stack.name.toLowerCase».launch"]«ENDIF»
'''
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import rossystem.RosSystem
import java.util.List
import ros.Node
import ros.impl.PackageImpl
import rossystem.ComponentStack

class GeneratorHelpers {

Expand All @@ -21,14 +22,30 @@ class GeneratorHelpers {
PackageImpl package_impl
List<CharSequence> PkgsList
String Pkg
List<ComponentInterface> ComponentsList

def void init_pkg(){
PackageSet=false
}

def <String> getPkgsDependencies (RosSystem rossystem, ComponentStack stack){
if (stack===null){
return getPkgsDependencies(rossystem)
} else {
return getPkgsDependencies(stack)
}
}

def <String> getPkgsDependencies(RosSystem rossystem){
def <String> getPkgsDependencies(Object subsystem){
PkgsList = new ArrayList()
for (component:rossystem.rosComponent){
ComponentsList = new ArrayList<ComponentInterface>();

if (subsystem.class.toString.contains("RosSystemImpl")){
ComponentsList = (subsystem as RosSystem).rosComponent
} else if (subsystem.class.toString.contains("ComponentStackImpl")) {
ComponentsList = (subsystem as ComponentStack).rosComponent
}
for (component:ComponentsList){
init_pkg()
Pkg = component.compile_pkg.toString()
if (!PkgsList.contains(Pkg)){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import componentInterface.RosServiceClient
import componentInterface.RosActionClient
import rossystem.ActionConnection
import componentInterface.RosActionServer
import rossystem.ComponentStack

class LaunchFileCompiler_ROS1 {
@Inject extension GeneratorHelpers
Expand All @@ -29,13 +30,16 @@ class LaunchFileCompiler_ROS1 {
String tab_tmp=""
List<Integer> sizes_list = new ArrayList<Integer>();
List<EObject> param_list = new ArrayList<EObject>();
List<ComponentInterface> components = new ArrayList<ComponentInterface>();


int i=0;
int k=0;

def compile_toROS1launch(RosSystem system) '''«init_comp()»
def compile_toROS1launch(RosSystem system, ComponentStack stack) '''«init_comp()»
<?xml version="1.0"?>
<launch>
«IF stack===null»
«FOR ROSParameter:system.parameter»
«IF ROSParameter.type.toString.contains("ParameterStructType")»
<rosparam>
Expand All @@ -56,41 +60,11 @@ class LaunchFileCompiler_ROS1 {
«ELSE»
<param name="«ROSParameter.name»" value="«compile_param_value(ROSParameter.value)»"/>
«ENDIF»
«ENDFOR»
««« «FOR component:system.rosComponent»
««« «FOR rosPublisher:component.rospublisher»
««« «IF component.hasNS»«IF !rosPublisher.name.equals(compile_topic_name(rosPublisher.publisher,component.get_ns()))»
««« <remap from=«compile_topic_name(rosPublisher.publisher,component.get_ns())» to=«rosPublisher.name» />
««« «ENDIF»«ENDIF»
««« «ENDFOR»
««« «FOR rosSubscriber:component.rossubscriber»
««« «IF component.hasNS»«IF !rosSubscriber.name.equals(compile_topic_name(rosSubscriber.subscriber,component.get_ns()))»
««« <remap from=«compile_topic_name(rosSubscriber.subscriber,component.get_ns())» to=«rosSubscriber.name» />
««« «ENDIF»«ENDIF»
««« «ENDFOR»
««« «FOR rosServiceServer:component.rosserviceserver»
««« «IF component.hasNS»«IF !rosServiceServer.name.equals(compile_service_name(rosServiceServer.srvserver,component.get_ns()))»
««« <remap from=«compile_service_name(rosServiceServer.srvserver,component.get_ns())» to=«rosServiceServer.name» />
««« «ENDIF»«ENDIF»
««« «ENDFOR»
««« «FOR rosServiceClient:component.rosserviceclient»
««« «IF component.hasNS»«IF !rosServiceClient.name.equals(compile_service_name(rosServiceClient.srvclient,component.get_ns()))»
««« <remap from=«compile_service_name(rosServiceClient.srvclient,component.get_ns())» to=«rosServiceClient.name» />
««« «ENDIF»«ENDIF»
««« «ENDFOR»
««« «FOR rosActionServer:component.rosactionserver»
««« «IF component.hasNS»«IF !rosActionServer.name.equals(compile_action_name(rosActionServer.actserver,component.get_ns()))»
««« <remap from=«compile_action_name(rosActionServer.actserver,component.get_ns())» to=«rosActionServer.name» />
««« «ENDIF»«ENDIF»
««« «ENDFOR»
««« «FOR rosActionClient:component.rosactionclient»
««« «IF component.hasNS»«IF !rosActionClient.name.equals(compile_action_name(rosActionClient.actclient,component.get_ns()))»
««« <remap from=«compile_action_name(rosActionClient.actclient,component.get_ns())» to=«rosActionClient.name» />
««« «ENDIF»«ENDIF»
««« «ENDFOR»
««« «ENDFOR»
«ENDFOR»«ELSE»«FOR qa:stack.qualityAttribute»
<param name="«qa.name»" value="«compile_param_value(qa.value)»"/>
«ENDFOR»«ENDIF»

«FOR component:system.rosComponent»
«FOR component:compile_list_of_components(system,stack)»
<node pkg="«component.compile_pkg»«init_pkg»" type="«component.compile_art»«init_comp()»" name="«component.name»"«IF component.hasNS» ns="«component.get_ns»"«ENDIF» cwd="node" respawn="false" output="screen">«init_comp()»«init_pkg»
«FOR rosPublisher:component.rospublisher»
«remapping_function_pub(rosPublisher, component.hasNS, inTopicFromConnection(rosPublisher, system.topicConnections),component.check_ns)»
Expand Down Expand Up @@ -128,6 +102,16 @@ class LaunchFileCompiler_ROS1 {
</launch>
'''

def List<ComponentInterface> compile_list_of_components(RosSystem system, ComponentStack stack) {
components=null;
if (stack === null){
components = system.rosComponent;
} else {
components = stack.rosComponent;
}
return components;
}

// TOPICS REMAP
def String remapping_function_pub(RosPublisher rosPublisher, boolean HasNS, String inConnection, String NS) {
if(inConnection!==null){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@ package de.fraunhofer.ipa.rossystem.generator

import rossystem.RosSystem
import com.google.inject.Inject
import rossystem.ComponentStack
import java.util.List
import java.util.ArrayList

class PackageXmlCompiler{

@Inject extension GeneratorHelpers
List<CharSequence> depends_list


def compile_package_xml_format2(RosSystem system) '''«init_pkg()»
def compile_package_xml_format2(RosSystem system,ComponentStack stack) '''«init_pkg()»
<package format="2">
<name>«system.name.toLowerCase»</name>
<name>«IF stack===null»«system.name.toLowerCase»«ELSE»«system.name.toLowerCase»_«stack.name.toLowerCase»«ENDIF»</name>
<version>0.0.1</version>
<description>This package provides launch file for operating «system.name»</description>
<description>This package provides launch file for operating «IF stack===null»«system.name»«ELSE»«system.name.toLowerCase»_«stack.name»«ENDIF»</description>

<license>Apache 2.0</license>

Expand All @@ -22,15 +26,15 @@ class PackageXmlCompiler{
<maintainer email="[email protected]">Jane Doe</maintainer>
<author email="[email protected]">Jane Doe</author>


<buildtool_depend>catkin</buildtool_depend>
«FOR pkg:system.getPkgsDependencies»
«FOR pkg:getPkgsDependencies(system, stack)»
<exec_depend>«pkg»</exec_depend>
«ENDFOR»
<!--test_depend>roslaunch</test_depend-->

</package>'''


def compile_package_xml_format3(RosSystem system) '''«init_pkg()»
<?xml version="1.0"?>
<?xml-model
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ class RosSystemGenerator extends AbstractGenerator {
@Inject extension LaunchFileCompiler_ROS1
@Inject extension LaunchFileCompiler_ROS2
@Inject extension SetupPyCompile
@Inject extension DockerComposeCompiler
@Inject extension DockerContainerCompiler

//@Inject extension InstallScriptCompiler


Expand All @@ -60,41 +60,33 @@ class RosSystemGenerator extends AbstractGenerator {
// }


// ROS1 package
for (system : resource.allContents.toIterable.filter(RosSystem)){
fsa.generateFile(system.getName().toLowerCase+"/launch/"+system.getName()+".launch",system.compile_toROS1launch.toString().replace("\t"," "))
}
for (system : resource.allContents.toIterable.filter(RosSystem)){
fsa.generateFile(system.getName().toLowerCase+"/package.xml",system.compile_package_xml_format2)
}
// ROS1 package with docker composition for component Stacks
for (system : resource.allContents.toIterable.filter(RosSystem)){
fsa.generateFile(system.getName().toLowerCase+"/CMakeLists.txt",system.compile_CMakeLists_ROS1)
}
for (system : resource.allContents.toIterable.filter(RosSystem)){
fsa.generateFile(system.getName().toLowerCase+"/Dockerfile",system.compile_toDockerContainer)
}
if (system.componentStack.size==0){
fsa.generateFile(system.getName().toLowerCase+"/package.xml",compile_package_xml_format2(system, null))
fsa.generateFile(system.getName().toLowerCase+"/CMakeLists.txt",compile_CMakeLists_ROS1(system, null))
fsa.generateFile(system.getName().toLowerCase+"/launch/"+system.getName()+".launch",compile_toROS1launch(system, null).toString().replace("\t"," "))
fsa.generateFile(system.getName().toLowerCase+"/Dockerfile",compile_toDockerContainer(system, null))
} else {
for (stack : system.componentStack){
fsa.generateFile(String.join("/", system.getName().toLowerCase, system.name.toLowerCase+'_'+stack.name.toLowerCase, "package.xml"),compile_package_xml_format2(system, stack))
fsa.generateFile(String.join("/", system.getName().toLowerCase, system.name.toLowerCase+'_'+stack.name.toLowerCase, "CMakeLists.txt"),compile_CMakeLists_ROS1(system, stack))
fsa.generateFile(String.join("/", system.getName().toLowerCase, system.name.toLowerCase+'_'+stack.name.toLowerCase, "launch", stack.getName()+".launch"), compile_toROS1launch(system, stack).toString().replace("\t"," "))
fsa.generateFile(String.join("/", system.getName().toLowerCase, system.name.toLowerCase+'_'+stack.name.toLowerCase, "Dockerfile"),compile_toDockerContainer(system, stack))
}
fsa.generateFile(String.join("/", system.getName().toLowerCase, "docker-compose.yml"),compile_toDockerCompose(system))
}
}

//ROS2 package
for (system : resource.allContents.toIterable.filter(RosSystem)){
fsa.generateFile(system.getName().toLowerCase+"_ros2/launch/"+system.getName()+".launch.py",system.compile_toROS2launch.toString().replace("\t"," "))
}
for (system : resource.allContents.toIterable.filter(RosSystem)){
fsa.generateFile(system.getName().toLowerCase+"_ros2/package.xml",system.compile_package_xml_format3)
}
for (system : resource.allContents.toIterable.filter(RosSystem)){
fsa.generateFile(system.getName().toLowerCase+"_ros2/setup.py",system.compile_setup_py)
}
for (system : resource.allContents.toIterable.filter(RosSystem)){
fsa.generateFile(system.getName().toLowerCase+"_ros2/resource/" + system.getName().toLowerCase, "")
}
for (system : resource.allContents.toIterable.filter(RosSystem)){
fsa.generateFile(system.getName().toLowerCase+"_ros2/" + system.getName().toLowerCase + "/__init__.py", "")
}
// for (system : resource.allContents.toIterable.filter(RosSystem)){
// fsa.generateFile(system.getName().toLowerCase+"_ros2/CMakeLists.txt",system.compile_CMakeLists_ROS2)
// }


fsa.generateFile(system.getName().toLowerCase+"_ros2/launch/"+system.getName()+".launch.py",system.compile_toROS2launch.toString().replace("\t"," "))
fsa.generateFile(system.getName().toLowerCase+"_ros2/package.xml",system.compile_package_xml_format3)
fsa.generateFile(system.getName().toLowerCase+"_ros2/setup.py",system.compile_setup_py)
fsa.generateFile(system.getName().toLowerCase+"_ros2/resource/" + system.getName().toLowerCase, "")
fsa.generateFile(system.getName().toLowerCase+"_ros2/" + system.getName().toLowerCase + "/__init__.py", "")
fsa.generateFile(system.getName().toLowerCase+"_ros2/CMakeLists.txt",system.compile_CMakeLists_ROS2)
}
}
}

0 comments on commit e4f53e6

Please sign in to comment.