Skip to content

Commit

Permalink
Update launch packages generator
Browse files Browse the repository at this point in the history
  • Loading branch information
ipa-nhg committed Nov 28, 2023
1 parent d38445d commit 04d8a1e
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import ros.PackageDependency
import system.Component
import system.RosNode
import ros.impl.AmentPackageImpl
import system.impl.RosNodeImpl
import system.SubSystem

class GeneratorHelpers {

Expand All @@ -29,23 +31,58 @@ class GeneratorHelpers {
List<CharSequence> PkgsList
String Pkg
RosNode node
String[] FromFileInfo


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 <Components> getNodes (System rossystem) {
val nodeList = new ArrayList<RosNode>
for (component: rossystem.components) {
if (component.class.toString.contains("RosNode")){
nodeList.add(component as RosNode)
}
}
return nodeList
}

def <Systems> getSubsystems (System rossystem) {
val subSystemsList = new ArrayList<System>
for (component: rossystem.components) {
if (component.class.toString.contains("SubSystem")){
subSystemsList.add((component as SubSystem).system)
}
}
return subSystemsList
}

def <String> getPkgsDependencies (System rossystem){
PkgsList = new ArrayList()
if (rossystem.fromFile.isNullOrEmpty) {
for (component: getNodes(rossystem)){
init_pkg()
node = component as RosNode
Pkg = node.compile_pkg.toString()
if (!PkgsList.contains(Pkg)){
PkgsList.add(Pkg)
}
}
for (component: getSubsystems(rossystem)){
if (component.fromFile.isNullOrEmpty){
PkgsList.add(component.name)
} else {
PkgsList.add(component.fromFile.split("/",2).get(0))
}
}
}
else {
FromFileInfo = rossystem.fromFile.split("/",2);
PkgsList.add(FromFileInfo.get(0))
}

return PkgsList;
}

def compile_pkg(RosNode component)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,36 @@
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
import system.Connection
import org.eclipse.emf.common.util.EList
import system.RosConnection
import system.impl.RosConnectionImpl
import system.impl.RosSystemConnectionImpl
import java.util.ArrayList
import system.impl.RosPublisherReferenceImpl
import system.impl.RosInterfaceImpl
import system.impl.RosSubscriberReferenceImpl
import system.RosInterface
import system.impl.RosServiceServerReferenceImpl
import system.impl.RosServiceClientReferenceImpl
import system.impl.RosActionServerReferenceImpl
import system.impl.RosActionClientReferenceImpl
import com.google.inject.Inject

class LaunchFileCompiler_ROS2 {

@Inject extension GeneratorHelpers


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

«IF !getSubsystems(system).empty»from ament_index_python.packages import get_package_share_directory
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource«ENDIF»
def generate_launch_description():
ld = LaunchDescription()

«FOR component:system.components»
«FOR component:getNodes(system)»
«(component as RosNode).name» = Node(
package="«((component as RosNode).from.eContainer.eContainer as AmentPackageImpl).name»",
executable="«((component as RosNode).from.eContainer as Artifact).name»",
Expand All @@ -41,9 +40,23 @@ def generate_launch_description():
)

«ENDFOR»

«FOR subsystem:getSubsystems(system
«IF subsystem.fromFile.nullOrEmpty»
include_«subsystem.name»= IncludeLaunchDescription(
PythonLaunchDescriptionSource([ get_package_share_directory('«subsystem.name»') + '/launch/«subsystem.name».launch.py'])
)
«ELSE»
include_«subsystem.name»= IncludeLaunchDescription(
PythonLaunchDescriptionSource([get_package_share_directory('«subsystem.fromFile.split("/",2).get(0)»') + '/«subsystem.fromFile.split("/",2).get(1)»'])
)
«ENDIF»
«ENDFOR»

«FOR component:system.components»
«FOR component:getNodes(system)»
ld.add_action(«(component as RosNode).name»)
«ENDFOR»«FOR subsystem:getSubsystems(system
ld.add_action(include_«subsystem.name»)
«ENDFOR»

return ld
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,32 @@ import system.impl.RosPublisherReferenceImpl
import system.impl.RosServiceClientReferenceImpl
import system.impl.RosServiceServerReferenceImpl
import system.impl.RosSubscriberReferenceImpl
import com.google.inject.Inject

class READMECompiler {


@Inject extension GeneratorHelpers

def compile_toREADME(System system) '''
# «system.name»

This package has be created automatically using the [RosTooling](https://github.com/ipa320/RosTooling).


It holds the launch file to run the following nodes:
«FOR node:system.components»
«FOR node:getNodes(system)»
- «(node as RosNode).name»
«ENDFOR»

The listed nodes offer the following connections:
«FOR node:system.components»«FOR port:(node as RosNode).rosinterfaces»
«FOR node:getNodes(system)»«FOR port:(node as RosNode).rosinterfaces»
«getPortInfo(port
«ENDFOR»«ENDFOR»

## Usage

«IF system.fromFile.nullOrEmpty»

This package can be copied to a valid ROS 2 workspace. Then the worksapce must be compiled using the common ROS 2 build command:

```
Expand All @@ -41,6 +46,21 @@ To execute the launch file, the following command can be called:
```
ros2 launch «system.name» «system.name».launch.py
```
«ELSE»
To launch this system there is already an existing package that contains the launch file.

The package can be easily installed with the following command:

```
sudo apt install ros-ROSDISTRO-«system.fromFile.split("/",2).get(0).replace("_","-")»
```

And the system started by executing:

```
ros2 launch «system.fromFile.split("/",2).get(0)» «system.fromFile.substring(system.fromFile.lastIndexOf('-') + 1)»
```
«ENDIF»


'''
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,33 @@ class RosSystemGenerator extends AbstractGenerator {
system.getName().toLowerCase+"/README.md",
compile_toREADME(system).toString().replace("\t"," ")
)
fsa.generateFile(
system.getName().toLowerCase+"/launch/"+system.getName()+".launch.py",
compile_toROS2launch(system).toString().replace("\t"," ")
)
fsa.generateFile(
system.getName().toLowerCase+"/package.xml",
compile_package_xml_format3(system)
)
fsa.generateFile(
system.getName().toLowerCase+"/CMakeLists.txt",
compile_CMakeLists_ROS2(system)
)
fsa.generateFile(
system.getName().toLowerCase+"/setup.py",
compile_setup_py(system)
)
fsa.generateFile(
system.getName().toLowerCase+"/resource/" + system.getName().toLowerCase,
""
)
fsa.generateFile(
system.getName().toLowerCase+"/" + system.getName().toLowerCase + "/__init__.py",
""
)
if (system.fromFile.isNullOrEmpty) {
fsa.generateFile(
system.getName().toLowerCase+"/launch/"+system.getName()+".launch.py",
compile_toROS2launch(system).toString().replace("\t"," ")
)
fsa.generateFile(
system.getName().toLowerCase+"/package.xml",
compile_package_xml_format3(system)
)
fsa.generateFile(
system.getName().toLowerCase+"/CMakeLists.txt",
compile_CMakeLists_ROS2(system)
)
fsa.generateFile(
system.getName().toLowerCase+"/setup.py",
compile_setup_py(system)
)
fsa.generateFile(
system.getName().toLowerCase+"/resource/" + system.getName().toLowerCase,
""
)
fsa.generateFile(
system.getName().toLowerCase+"/" + system.getName().toLowerCase + "/__init__.py",
""
)
}
}
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class RosSystemValidator extends AbstractRosSystemValidator {
public static val NOT_IN_THE_SYSTEM = "The element is not part of the system"
public static val NOT_VALID_PATTERN = "The element has not a valid type"
public static val TYPE_NOT_MATCH = "The ports have different types"
public static val FROM_FILE_PATH = "FromFile"

Object from_type
Object to_type

Expand All @@ -62,6 +64,18 @@ class RosSystemValidator extends AbstractRosSystemValidator {
}
}
}

@Check
def fromFileHelper(System system ) {
if (!system.fromFile.empty){
info('The format for the FromFile attribute is: "NameOfThePackage/Path/to/ExecutableLaunchFile.launch.py"'
,null,NOT_IN_THE_SYSTEM)
}
if (!system.fromFile.toString.contains("/")){
error('Path not valid, the format for the FromFile attribute is: "NameOfThePackage/Path/to/ExecutableLaunchFile.launch.py"'
,null,NOT_IN_THE_SYSTEM)
}
}

@Check
def checkIfInterfaceInSystem(Connection connection) {
Expand Down

0 comments on commit 04d8a1e

Please sign in to comment.