Skip to content

Commit

Permalink
Merge pull request #130 from ipa-nhg/Ros2CppNode
Browse files Browse the repository at this point in the history
Cpp code genrators for ROS2 nodes
  • Loading branch information
ipa-nhg authored May 27, 2021
2 parents 42a7161 + 8dbbac9 commit faa441b
Show file tree
Hide file tree
Showing 9 changed files with 303 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
cmake_minimum_required(VERSION 3.5)
project(test_pkg)

# 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)
find_package(Boost REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_srvs REQUIRED)
find_package(sensor_msgs REQUIRED)

add_executable(test_node src/test_node.cpp)
ament_target_dependencies(test_node rclcpp std_srvs sensor_msgs )

install(TARGETS
test_node
DESTINATION lib/${PROJECT_NAME})

ament_package()
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?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>test_pkg</name>
<version>0.0.0</version>
<description>This package contains the implementation of the node test_node</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>

<depend>boost</depend>
<depend>rclcpp</depend>
<depend>std_srvs</depend>
<depend>sensor_msgs</depend>

<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>

<export>
<build_type>ament_cmake</build_type>
</export>
</package>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
cmake_minimum_required(VERSION 3.0.2)
project(test_pkg)

find_package(catkin REQUIRED COMPONENTS roscpp std_srvs sensor_msgs )

catkin_package(
CATKIN_DEPENDS roscpp std_srvs sensor_msgs
)

### Build ###

include_directories(${catkin_INCLUDE_DIRS})

add_executable(test_node src/test_node.cpp)
add_dependencies(test_node ${catkin_EXPORTED_TARGETS})
target_link_libraries(test_node ${catkin_LIBRARIES})

### Install ###
install(TARGETS test_node
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?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>test_pkg</name>
<version>0.0.0</version>
<description>This package contains the implementation of the node test_node</description>
<maintainer email="[email protected]">Jane Doe</maintainer>
<author email="[email protected]">Jane Doe</author>
<license>Apache 2.0</license>

<buildtool_depend>catkin</buildtool_depend>

<depend>boost</depend>
<depend>roscpp</depend>
<depend>std_srvs</depend>
<depend>sensor_msgs</depend>

</package>
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,20 @@ class RosGeneratorTest {

val resourceSet = rosTestingUtils.getMessagesResourceSet
val fileContent = new String(Files.readAllBytes(Paths.get(RESOURCES_BASE_DIR, 'test.ros')))

val model = parseHelper.parse(fileContent, resourceSet)

val fsa = new InMemoryFileSystemAccess
rosGenerator.doGenerate(model.eResource, fsa, new GeneratorContext)

Assert.assertTrue(fsa.textFiles.containsKey(CustomOutputProvider::DEFAULT_OUTPUT + "test_node.cpp"))
Assert.assertTrue(fsa.textFiles.containsKey(CustomOutputProvider::DEFAULT_OUTPUT + "test_pkg/package.xml"))
Assert.assertEquals(
new String(Files.readAllBytes(Paths.get(RESOURCES_BASE_DIR, 'rosgenerator/test_pkg/src/','test_node.cpp'))).trim,
fsa.textFiles.get(CustomOutputProvider::DEFAULT_OUTPUT + "test_pkg/src/test_node.cpp").toString.trim)
Assert.assertEquals(
new String(Files.readAllBytes(Paths.get(RESOURCES_BASE_DIR, 'rosgenerator/test_pkg/','CMakeLists.txt'))).trim,
fsa.textFiles.get(CustomOutputProvider::DEFAULT_OUTPUT + "test_pkg/CMakeLists.txt").toString.trim)
Assert.assertEquals(
new String(Files.readAllBytes(Paths.get(RESOURCES_BASE_DIR, 'rosgenerator', 'test_node.cpp'))).trim,
fsa.textFiles.get(CustomOutputProvider::DEFAULT_OUTPUT + "test_node.cpp").toString.trim)
new String(Files.readAllBytes(Paths.get(RESOURCES_BASE_DIR, 'rosgenerator/test_pkg/','package.xml'))).trim,
fsa.textFiles.get(CustomOutputProvider::DEFAULT_OUTPUT + "test_pkg/package.xml").toString.trim)
}

@Test
Expand All @@ -63,10 +67,16 @@ class RosGeneratorTest {

val fsa = new InMemoryFileSystemAccess
ros2Generator.doGenerate(model.eResource, fsa, new GeneratorContext)
Assert.assertTrue(fsa.textFiles.containsKey(CustomOutputProvider::DEFAULT_OUTPUT + "test_node.cpp"))
Assert.assertTrue(fsa.textFiles.containsKey(CustomOutputProvider::DEFAULT_OUTPUT + "test_pkg/package.xml"))
Assert.assertEquals(
new String(Files.readAllBytes(Paths.get(RESOURCES_BASE_DIR, 'ros2generator/test_pkg/src/','test_node.cpp'))).trim,
fsa.textFiles.get(CustomOutputProvider::DEFAULT_OUTPUT + "test_pkg/src/test_node.cpp").toString.trim)
Assert.assertEquals(
new String(Files.readAllBytes(Paths.get(RESOURCES_BASE_DIR, 'ros2generator/test_pkg/','CMakeLists.txt'))).trim,
fsa.textFiles.get(CustomOutputProvider::DEFAULT_OUTPUT + "test_pkg/CMakeLists.txt").toString.trim)
Assert.assertEquals(
new String(Files.readAllBytes(Paths.get(RESOURCES_BASE_DIR, 'ros2generator', 'test_node.cpp'))).trim,
fsa.textFiles.get(CustomOutputProvider::DEFAULT_OUTPUT + "test_node.cpp").toString.trim)
new String(Files.readAllBytes(Paths.get(RESOURCES_BASE_DIR, 'ros2generator/test_pkg/','package.xml'))).trim,
fsa.textFiles.get(CustomOutputProvider::DEFAULT_OUTPUT + "test_pkg/package.xml").toString.trim)
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,110 @@
package de.fraunhofer.ipa.roscode.generator

import java.util.ArrayList
import java.util.HashSet
import java.util.List
import java.util.Set
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 org.eclipse.xtext.generator.IOutputConfigurationProvider
import org.eclipse.xtext.generator.OutputConfiguration
import java.util.Set
import ros.*


import ros.Node
import ros.Package

/**
* Generates code from your model files on save.
*
* See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation
*/
class Ros2CodeGenerator extends AbstractGenerator {


String resourcepath
String import_msgs
int char_i
Node node
List<String> PkgsList
Set<String> set


override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
resourcepath = resource.URI.toString();
if (! resourcepath.contains("/ros-input")) {
for (node : resource.allContents.toIterable.filter(Node)){
fsa.generateFile(node.getName()+".cpp",node.compile)
for (pkg : resource.allContents.toIterable.filter(Package)){
fsa.generateFile(pkg.getName().toLowerCase+"/package.xml",pkg.compile_package_xml)
fsa.generateFile(pkg.getName().toLowerCase+"/CMakeLists.txt",pkg.compile_CMakeLists)
for (art : pkg.artifact){
node = art.node
fsa.generateFile(pkg.getName().toLowerCase+"/src/"+node.name+".cpp",node.compile_node)

}
}
}
}
}

def compile(Node node) '''

def compile_package_xml(Package 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>«pkg.name»</name>
<version>0.0.0</version>
<description>This package contains the implementation of the node «pkg.artifact.get(0).node.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>

<depend>boost</depend>
<depend>rclcpp</depend>
«FOR depend_pkg:pkg.getPkgDependencies»
<depend>«depend_pkg»</depend>
«ENDFOR»

<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>

<export>
<build_type>ament_cmake</build_type>
</export>
</package>
'''

def compile_CMakeLists(Package pkg)'''
cmake_minimum_required(VERSION 3.5)
projectpkg.name»)

# 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)
find_package(Boost REQUIRED)
find_package(rclcpp REQUIRED)
«FOR depend_pkg:pkg.getPkgDependencies»
find_packagedepend_pkg» REQUIRED)
«ENDFOR»

«FOR art:pkg.artifact»
add_executableart.name» srcart.node.name».cpp)
ament_target_dependenciesart.name» rclcpp «FOR depend_pkg:pkg.getPkgDependencies»«depend_pkg» «ENDFOR»)

install(TARGETS
«art.name»
DESTINATION lib/${PROJECT_NAME})
«ENDFOR»

ament_package()
'''

def compile_node(Node node) '''
#include <chrono>
#include <cstdio>
#include <memory>
Expand Down Expand Up @@ -149,6 +221,20 @@ int main(int argc, char * argv[])
}
'''
def List<String> getPkgDependencies(Package pkg){
set=new HashSet<String>()
PkgsList = new ArrayList()
for (art:pkg.artifact){
node=art.node
for (pub:node.publisher){set.add(pub.message.package.name)}
for (sub:node.subscriber){set.add(sub.message.package.name)}
for (srvserver:node.serviceserver){set.add(srvserver.service.package.name)}
for (srvclient:node.serviceclient){set.add(srvclient.service.package.name)}
}
PkgsList.addAll(set)
return PkgsList
}
def String check_message_include(String message_name){
import_msgs = message_name.toFirstLower;
for (char_i =0; char_i < import_msgs.length; char_i++ ){
Expand Down
Loading

0 comments on commit faa441b

Please sign in to comment.