Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cpp code genrators for ROS2 nodes #130

Merged
merged 3 commits into from
May 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
project(«pkg.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_package(«depend_pkg» REQUIRED)
«ENDFOR»

«FOR art:pkg.artifact»
add_executable(«art.name» src/«art.node.name».cpp)
ament_target_dependencies(«art.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