Skip to content

Commit

Permalink
First draft for a working version of the code generator for ROS2 laun…
Browse files Browse the repository at this point in the history
…ch files
  • Loading branch information
ipa-nhg committed Sep 19, 2023
1 parent 1deda5d commit a0da77a
Show file tree
Hide file tree
Showing 6 changed files with 351 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package de.fraunhofer.ipa.rossystem.generator

import com.google.inject.Inject
import system.System

class CMakeListsCompiler {

@Inject extension GeneratorHelpers


// def compile_CMakeLists_ROS1(RosSystem system, ComponentStack stack) '''«init_pkg()»
//cmake_minimum_required(VERSION 2.8.3)
//project(«IF stack===null»«system.name.toLowerCase»«ELSE»«system.name.toLowerCase»_«stack.name.toLowerCase»«ENDIF»)
//
//find_package(catkin REQUIRED)
//
//catkin_package()
//
//
//### INSTALL ###
//install(DIRECTORY launch
// DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
//)'''

def compile_CMakeLists_ROS2(System system) '''«init_pkg()»
cmake_minimum_required(VERSION 3.5)
projectsystem.name.toLowerCase»)

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 14)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()

find_package(ament_cmake REQUIRED)

### INSTALL ###
install(DIRECTORY launch
DESTINATION share/${PROJECT_NAME}
)

ament_package()
'''


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package de.fraunhofer.ipa.rossystem.generator

import java.util.ArrayList
import ros.ActionClient
import ros.ActionServer
import ros.Parameter
import ros.Publisher
import ros.ServiceClient
import ros.ServiceServer
import ros.Subscriber
import system.System
import java.util.List
import ros.Node
import ros.impl.PackageImpl
import org.eclipse.emf.ecore.EObject
import java.util.Set
import java.util.HashSet
import ros.Dependency
import ros.PackageDependency
import system.Component
import system.RosNode
import ros.impl.AmentPackageImpl

class GeneratorHelpers {

boolean PackageSet

AmentPackageImpl package_impl
List<CharSequence> PkgsList
String Pkg
RosNode node

def void init_pkg(){
PackageSet=false
}

def <String> getPkgsDependencies (System rossystem){
PkgsList = new ArrayList()
for (component: rossystem.components){
init_pkg()
node = component as RosNode
Pkg = node.compile_pkg.toString()
if (!PkgsList.contains(Pkg)){
PkgsList.add(Pkg)
}
return PkgsList;
}

}

def compile_pkg(RosNode component)
'''«IF !(component.from===null)»«component.from.getPackage_node.name»«ENDIF»'''

// def PackageImpl get_pkg(ComponentInterface component) {
// if (component.fromRosNode!==null){
// return getPackage_node(component.fromRosNode)
// } else if(!component.rospublisher.empty){
// return getPacakge_fromObject(component.rospublisher.get(0).publisher)
// } else if (!component.rossubscriber.empty){
// return getPacakge_fromObject(component.rossubscriber.get(0).subscriber)
// } else if (!component.rosserviceclient.empty){
// return getPacakge_fromObject(component.rosserviceclient.get(0).srvclient)
// } else if (!component.rosserviceserver.empty){
// return getPacakge_fromObject(component.rosserviceserver.get(0).srvserver)
// } else if (!component.rosactionclient.empty){
// return getPacakge_fromObject(component.rosactionclient.get(0).actclient)
// } else if (!component.rosactionserver.empty){
// return getPacakge_fromObject(component.rosactionserver.get(0).actserver)
// } else if (!component.rosparameter.empty){
// return getPacakge_fromObject(component.rosparameter.get(0).parameter)
// }
// }
//
// def getPacakge_fromObject (EObject object){
// package_impl = object.eContainer.eContainer.eContainer as PackageImpl;
// return package_impl;
// }
//
// def getPackage_pub(Publisher publisher){
// package_impl = publisher.eContainer.eContainer.eContainer as PackageImpl;
// return package_impl;
// }
// def getPackage_sub(Subscriber subscriber){
// package_impl = subscriber.eContainer.eContainer.eContainer as PackageImpl;
// return package_impl;
// }
// def getPackage_srvserv(ServiceServer serviceserver){
// package_impl = serviceserver.eContainer.eContainer.eContainer as PackageImpl;
// return package_impl;
// }
// def getPackage_srvcli(ServiceClient serviceclient){
// package_impl = serviceclient.eContainer.eContainer.eContainer as PackageImpl;
// return package_impl;
// }
// def getPackage_actserver(ActionServer actionserver){
// package_impl = actionserver.eContainer.eContainer.eContainer as PackageImpl;
// return package_impl;
// }
// def getPackage_actclient(ActionClient actionclient){
// package_impl = actionclient.eContainer.eContainer.eContainer as PackageImpl;
// return package_impl;
// }
// def getPackage_rosparam (Parameter param){
// package_impl = param.eContainer.eContainer.eContainer as PackageImpl;
// return package_impl;
// }
def getPackage_node (Node node){
package_impl = node.eContainer.eContainer as AmentPackageImpl;
return package_impl;
}

//Launch files generators
// def check_ns(ComponentInterface component){
// if (component.hasNS){
// return component.get_ns();
// }else {
// return "";
// }
// }
// def boolean hasNS(ComponentInterface component){
// if(!component.nameSpace.nullOrEmpty){
// return true;
// }else{
// return false
// }
// }
// def String get_ns(ComponentInterface component){
// return component.nameSpace.replaceFirst("/","");
// }
//
// def compile_pkg_type(ComponentInterface component)
//'''«IF !(component.fromRosNode===null) »«component.fromRosNode.getPackageType_node»«ELSEIF !PackageSet && !component.rospublisher.empty»«FOR Rospublisher:component.rospublisher»«IF !PackageSet»«Rospublisher.publisher.getPackageType_pub()»«ENDIF»«ENDFOR»«ELSEIF !PackageSet && !component.rossubscriber.empty»«FOR Rossubscriber:component.rossubscriber»«IF !PackageSet»«Rossubscriber.subscriber.getPackageType_sub()»«ENDIF»«ENDFOR»«ELSEIF !PackageSet && !component.rosserviceserver.empty»«FOR Rosserviceserver:component.rosserviceserver»«IF !PackageSet»«Rosserviceserver.srvserver.getPackageType_srvserv()»«ENDIF»«ENDFOR»«ELSEIF !PackageSet && !component.rosserviceclient.empty»«FOR Rosserviceclient:component.rosserviceclient»«IF !PackageSet»«Rosserviceclient.srvclient.getPackageType_srvcli()»«ENDIF»«ENDFOR»«ELSEIF !PackageSet && !component.rosparameter.empty»«FOR Rosparameter:component.rosparameter»«IF !PackageSet»«Rosparameter.parameter.getPackageType_rosparam()»«ENDIF»«ENDFOR»«ELSEIF !PackageSet && !component.rosactionserver.empty»«FOR RosActionSever:component.rosactionserver»«IF !PackageSet»«RosActionSever.actserver.getPackageType_actserver()»«ENDIF»«ENDFOR»«ELSEIF !PackageSet && !component.rosactionclient.empty»«FOR RosActionClient:component.rosactionclient»«IF !PackageSet»«RosActionClient.actclient.getPackageType_actclient()»«ENDIF»«ENDFOR»«ENDIF»'''
//
// def getPackageType_pub(Publisher publisher){
// return publisher.eContainer.eContainer.eContainer as PackageImpl;
// }
// def getPackageType_sub(Subscriber subscriber){
// return subscriber.eContainer.eContainer.eContainer as PackageImpl;
// }
// def getPackageType_srvserv(ServiceServer serviceserver){
// return serviceserver.eContainer.eContainer.eContainer as PackageImpl;
// }
// def getPackageType_srvcli(ServiceClient serviceclient){
// return serviceclient.eContainer.eContainer.eContainer as PackageImpl;
// }
// def getPackageType_actserver(ActionServer actionserver){
// return actionserver.eContainer.eContainer.eContainer as PackageImpl;
// }
// def getPackageType_actclient(ActionClient actionclient){
// return actionclient.eContainer.eContainer.eContainer as PackageImpl;
// }
// def getPackageType_rosparam (Parameter param){
// return param.eContainer.eContainer.eContainer as PackageImpl;
// }
// def getPackageType_node (Node node){
// return node.eContainer.eContainer as PackageImpl;
// }


}
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,39 @@ package de.fraunhofer.ipa.rossystem.generator
import system.RosNode
import ros.RosPackage
import ros.Artifact
import system.Rossystem
import system.System
import ros.AmentPackage
import ros.impl.AmentPackageImpl

class LaunchFileCompiler_ROS2 {


def compile_toROS2launch(Rossystem system) '''
def compile_toROS2launch(System system) '''
from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
ld = LaunchDescription()

«FOR component:system.components»«IF component.eClass=="RosNode"»
«FOR component:system.components»
«(component as RosNode).name» = Node(
package="«((component as RosNode).from.eContainer.eContainer as RosPackage).name»",
package="«((component as RosNode).from.eContainer.eContainer as AmentPackageImpl).name»",
executable="«((component as RosNode).from.eContainer as Artifact).name»",
name="«(component as RosNode).name»"
)
«ENDIF»

«ENDFOR»

«FOR component:system.components»«IF component.eClass=="RosNode"»
«FOR component:system.components»
ld.add_action(«(component as RosNode).name»)
«ENDIF»
«ENDFOR»

return ld
'''

// def void compile_list_of_ROS2components(RosSystem system, ComponentStack stack) {
// components_tmp_.clear;
// Ros2components.clear;
// Ros2components.clear;
// if (stack === null){
// components_tmp_ = system.rosComponent;
// } else {
Expand Down Expand Up @@ -123,7 +124,7 @@ def generate_launch_description():
// } else {
// param_str += "{ \"" + rosParameter.parameter.name + "\" : " + get_param_value(rosParameter.value, rosParameter.parameter.name);
// }
// if (param_count > 1){
// if (param_count > 1){
// param_str +=" },\n"
// } else {
// param_str +=" }\n";
Expand All @@ -145,7 +146,7 @@ def generate_launch_description():
// param_str += "{ \"" + name + "/" + member.getName() + "\" : " + param_val;
// }
// elem_count--;
// if (elem_count > 0){
// if (elem_count > 0){
// param_str +=" },\n"
// }
// }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package de.fraunhofer.ipa.rossystem.generator

import system.System
import com.google.inject.Inject

class PackageXmlCompiler{

@Inject extension GeneratorHelpers

// def compile_package_xml_format2(System system) '''«init_pkg()»
//<package format="2">
// <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 «IF stack===null»«system.name»«ELSE»«system.name.toLowerCase»_«stack.name»«ENDIF»</description>
//
// <license>Apache 2.0</license>
//
// <url type="website">http://wiki.ros.org/</url>
//
//
// <maintainer email="[email protected]">Jane Doe</maintainer>
// <author email="[email protected]">Jane Doe</author>
//
// <buildtool_depend>catkin</buildtool_depend>
// «FOR pkg:getPkgsDependencies(system, stack)»
// <exec_depend>«pkg»</exec_depend>
// «ENDFOR»
// <!--test_depend>roslaunch</test_depend-->
//
//</package>'''


def compile_package_xml_format3(System system) '''«init_pkg()»
<?xml version="1.0"?>
<?xml-model
href="http://download.ros.org/schema/package_format3.xsd"
schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>«system.name.toLowerCase»</name>
<version>0.0.1</version>
<description>This package provides launch file for operating «system.name»</description>
<maintainer email="[email protected]">Jane Doe</maintainer>
<author email="[email protected]">Jane Doe</author>
<license>Apache 2.0</license>

<buildtool_depend>ament_cmake</buildtool_depend>

<exec_depend>ament_index_python</exec_depend>
<exec_depend>launch</exec_depend>
«FOR pkg:system.getPkgsDependencies»
<exec_depend>«pkg»</exec_depend>
«ENDFOR»

<!--test_depend>ament_copyright</test_depend>
<test_depend>ament_flake8</test_depend>
<test_depend>ament_pep257</test_depend>
<test_depend>launch</test_depend>
<test_depend>python3-pytest</test_depend-->

<export>
<build_type>ament_python</build_type>
</export>
</package>
'''


}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.xtext.generator.AbstractGenerator
import org.eclipse.xtext.generator.IFileSystemAccess2
import org.eclipse.xtext.generator.IGeneratorContext
import system.System
import com.google.inject.Inject
import system.Rossystem

/**
* Generates code from your model files on save.
Expand All @@ -17,10 +17,36 @@ import system.Rossystem
*/
class RosSystemGenerator extends AbstractGenerator {
@Inject extension LaunchFileCompiler_ROS2

@Inject extension SetupPyCompiler
@Inject extension PackageXmlCompiler
@Inject extension CMakeListsCompiler

override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
for (system : resource.allContents.toIterable.filter(Rossystem)){
fsa.generateFile(system.getName().toLowerCase+"_ros2/launch/"+system.getName()+".launch.py",compile_toROS2launch(system).toString().replace("\t"," "))
for (system : resource.allContents.toIterable.filter(System)){
fsa.generateFile(
system.getName().toLowerCase+"_ros2/launch/"+system.getName()+".launch.py",
compile_toROS2launch(system).toString().replace("\t"," ")
)
fsa.generateFile(
system.getName().toLowerCase+"_ros2/package.xml",
compile_package_xml_format3(system)
)
fsa.generateFile(
system.getName().toLowerCase+"_ros2/CMakeLists.txt",
compile_CMakeLists_ROS2(system)
)
fsa.generateFile(
system.getName().toLowerCase+"_ros2/setup.py",
compile_setup_py(system)
)
fsa.generateFile(
system.getName().toLowerCase+"_ros2/resource/" + system.getName().toLowerCase,
""
)
fsa.generateFile(
system.getName().toLowerCase+"_ros2/" + system.getName().toLowerCase + "/__init__.py",
""
)
}
}
}
Loading

0 comments on commit a0da77a

Please sign in to comment.