diff --git a/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/CMakeListsCompiler.xtend b/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/CMakeListsCompiler.xtend new file mode 100644 index 000000000..44acac9be --- /dev/null +++ b/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/CMakeListsCompiler.xtend @@ -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) +project(«system.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() +''' + + +} \ No newline at end of file diff --git a/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/GeneratorHelpers.xtend b/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/GeneratorHelpers.xtend new file mode 100644 index 000000000..37f5a4f5b --- /dev/null +++ b/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/GeneratorHelpers.xtend @@ -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 PkgsList + String Pkg + RosNode node + + def void init_pkg(){ + PackageSet=false + } + + def 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; +// } + + +} diff --git a/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/LaunchFileCompiler_ROS2.xtend b/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/LaunchFileCompiler_ROS2.xtend new file mode 100644 index 000000000..a57d5a56d --- /dev/null +++ b/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/LaunchFileCompiler_ROS2.xtend @@ -0,0 +1,184 @@ +package de.fraunhofer.ipa.rossystem.generator + +import system.RosNode +import ros.RosPackage +import ros.Artifact +import system.System +import ros.AmentPackage +import ros.impl.AmentPackageImpl + +class LaunchFileCompiler_ROS2 { + + + 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» + «(component as RosNode).name» = Node( + package="«((component as RosNode).from.eContainer.eContainer as AmentPackageImpl).name»", + executable="«((component as RosNode).from.eContainer as Artifact).name»", + name="«(component as RosNode).name»" + ) + + «ENDFOR» + + «FOR component:system.components» + ld.add_action(«(component as RosNode).name») + «ENDFOR» + + return ld + ''' + +// def void compile_list_of_ROS2components(RosSystem system, ComponentStack stack) { +// components_tmp_.clear; +// Ros2components.clear; +// if (stack === null){ +// components_tmp_ = system.rosComponent; +// } else { +// components_tmp_ = stack.rosComponent; +// } +// for(ComponentInterface component:components_tmp_){ +// if (component.compile_pkg_type.toString.contains("AmentPackage")){ +// Ros2components.add(component); +// } +// } +// } +// +// def check_ns(ComponentInterface component){ +// if (component.hasNS){ +// return component.get_ns(); +// }else { +// return ""; +// } +// } +// +// def List InterfaceDef(String name, String type){ +// ListInterfaceDef = new ArrayList() +// ListInterfaceDef.add(name.replace("/","_")) +// ListInterfaceDef.add(name) +// ListInterfaceDef.add(type) +// return ListInterfaceDef +// } +// +// 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 String compile_remappings_str(ComponentInterface component) { +// var remap_str = ""; +// val NS = component.check_ns(); +// for (rosPublisher : component.rospublisher) { +// if (!((prefix(NS)+rosPublisher.name).equals(compile_topic_name(rosPublisher.publisher, NS)))) { +// remap_str += "\t(\"" + rosPublisher.publisher.name + "\", \"" + rosPublisher.name + "\"),\n"; +// } +// } +// for (rosSubscriber : component.rossubscriber) { +// if (!((prefix(NS)+rosSubscriber.name).equals(compile_topic_name(rosSubscriber.subscriber, NS)))) { +// remap_str += "\t(\"" + rosSubscriber.subscriber.name + "\", \"" + rosSubscriber.name + "\"),\n"; +// } +// } +// for (rosServiceServer : component.rosserviceserver) { +// if (!((prefix(NS)+rosServiceServer.name).equals(compile_service_name(rosServiceServer.srvserver, NS)))) { +// remap_str += "\t(\"" + rosServiceServer.srvserver.name + "\", \"" + rosServiceServer.name + "\"),\n"; +// } +// } +// for (rosServiceClient : component.rosserviceclient) { +// if (!((prefix(NS)+rosServiceClient.name).equals(compile_service_name(rosServiceClient.srvclient, NS)))) { +// remap_str += "\t(\"" + rosServiceClient.srvclient.name + "\", \"" + rosServiceClient.name + "\"),\n"; +// } +// } +// for (rosActionServer : component.rosactionserver) { +// if (!((prefix(NS)+rosActionServer.name).equals(compile_action_name(rosActionServer.actserver, NS)))) { +// remap_str += "\t(\"" + rosActionServer.actserver.name + "\", \"" + rosActionServer.name + "\"),\n"; +// } +// } +// for (rosActionClient : component.rosactionclient) { +// if (!((prefix(NS)+rosActionClient.name).equals(compile_action_name(rosActionClient.actclient, NS)))) { +// remap_str += "\t(\"" + rosActionClient.actclient.name + "\", \"" + rosActionClient.name + "\"),\n"; +// } +// } +// if (!remap_str.empty) { +// remap_str = ",\nremappings=[\n" + remap_str.substring(0,remap_str.length-2) + "]\n"; +// } +// return remap_str; +// } +// +// def String compile_parameters_str(EList rosParameters) { +// param_count = rosParameters.length; +// var param_str = ""; +// for (rosParameter : rosParameters) { +// val param_count=param_count--; +// if (rosParameter.parameter.type instanceof ParameterStructTypeImpl) { +// param_str += compile_struct_str(rosParameter.value, rosParameter.parameter.name); +// } else { +// param_str += "{ \"" + rosParameter.parameter.name + "\" : " + get_param_value(rosParameter.value, rosParameter.parameter.name); +// } +// if (param_count > 1){ +// param_str +=" },\n" +// } else { +// param_str +=" }\n"; +// } +// } +// return param_str; +// } +// +// def String compile_struct_str(ParameterValue value, String name) { +// var param_str = ""; +// var elem_count = (value as ParameterSequenceImpl).eContents.length; +// +// for (elem : ((value as ParameterSequenceImpl).eContents)) { +// var member = ((elem as ParameterStructImpl).eContents.get(0) as ParameterStructMemberImpl); +// val param_val = get_param_value(member.getValue(), name + "/" + member.getName()); +// if (param_val.startsWith("{")) { +// param_str += param_val; +// } else { +// param_str += "{ \"" + name + "/" + member.getName() + "\" : " + param_val; +// } +// elem_count--; +// if (elem_count > 0){ +// param_str +=" },\n" +// } +// } +// return param_str; +// } +// +// def String get_param_value(ParameterValue value, String name) { +// var param_val = ""; +// if (value instanceof ParameterStringImpl) { +// param_val = "\"" + (value as ParameterStringImpl).getValue() + "\""; +// } else if (value instanceof ParameterIntegerImpl) { +// param_val = (value as ParameterIntegerImpl).getValue().toString; +// } else if (value instanceof ParameterDoubleImpl) { +// param_val = (value as ParameterDoubleImpl).getValue().toString; +// } else if (value instanceof ParameterBooleanImpl) { +// param_val = (value as ParameterBooleanImpl).isValue().toString; +// } else if (value instanceof ParameterSequenceImpl) { +// var elem_count = (value as ParameterSequenceImpl).eContents.length; +// if ((value as ParameterSequenceImpl).eContents.get(0) instanceof ParameterStructImpl) { +// param_val = compile_struct_str(value, name); +// } else { +// param_val += "["; +// for (elem : (value as ParameterSequenceImpl).eContents) { +// param_val += get_param_value(elem as ParameterValue, name); +// elem_count--; +// if (elem_count > 0){ +// param_val +=", " +// } +// } +// param_val += "]"; +// } +// } +// return param_val; +// } +} diff --git a/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/PackageXmlCompiler.xtend b/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/PackageXmlCompiler.xtend new file mode 100644 index 000000000..46be8ec03 --- /dev/null +++ b/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/PackageXmlCompiler.xtend @@ -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()» +// +// «IF stack===null»«system.name.toLowerCase»«ELSE»«system.name.toLowerCase»_«stack.name.toLowerCase»«ENDIF» +// 0.0.1 +// This package provides launch file for operating «IF stack===null»«system.name»«ELSE»«system.name.toLowerCase»_«stack.name»«ENDIF» +// +// Apache 2.0 +// +// http://wiki.ros.org/ +// +// +// Jane Doe +// Jane Doe +// +// catkin +// «FOR pkg:getPkgsDependencies(system, stack)» +// «pkg» +// «ENDFOR» +// +// +//''' + + + def compile_package_xml_format3(System system) '''«init_pkg()» + + + + «system.name.toLowerCase» + 0.0.1 + This package provides launch file for operating «system.name» + Jane Doe + Jane Doe + Apache 2.0 + + ament_cmake + + ament_index_python + launch + «FOR pkg:system.getPkgsDependencies» + «pkg» + «ENDFOR» + + + + + ament_python + + + ''' + + + } 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 560446d93..239b0b867 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 @@ -7,6 +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 /** * Generates code from your model files on save. @@ -14,12 +16,37 @@ import org.eclipse.xtext.generator.IGeneratorContext * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation */ 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) { -// fsa.generateFile('greetings.txt', 'People to greet: ' + -// resource.allContents -// .filter(Greeting) -// .map[name] -// .join(', ')) + 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", + "" + ) } } +} diff --git a/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/SetupPyCompiler.xtend b/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/SetupPyCompiler.xtend new file mode 100644 index 000000000..c3e523818 --- /dev/null +++ b/plugins/de.fraunhofer.ipa.rossystem.xtext/src/de/fraunhofer/ipa/rossystem/generator/SetupPyCompiler.xtend @@ -0,0 +1,34 @@ +package de.fraunhofer.ipa.rossystem.generator + +import system.System +import com.google.inject.Inject + +class SetupPyCompiler{ + + @Inject extension GeneratorHelpers + + + def compile_setup_py(System system) '''«init_pkg()» +import os +from glob import glob +from setuptools import setup + +PACKAGE_NAME = '«system.name.toLowerCase»' + +setup( + name=PACKAGE_NAME, + version='0.0.1', + packages=[PACKAGE_NAME], + data_files=[ + # Install marker file in the package index + ('share/ament_index/resource_index/packages', + ['resource/' + PACKAGE_NAME]), + # Include our package.xml file + (os.path.join('share', PACKAGE_NAME), ['package.xml']), + # Include all launch files. + (os.path.join('share', PACKAGE_NAME, 'launch'), glob(os.path.join('launch', '*.launch.py'))) + ], + install_requires=['setuptools'], + zip_safe=True +)''' + }