Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
monticore
EmbeddedMontiArc
generators
EMAM2RosMsg
Commits
5b91a754
Commit
5b91a754
authored
Apr 13, 2019
by
Alexander David Hellwig
Browse files
Merge branch 'MsgProjectGeneration' into 'master'
Msg project generation See merge request
!8
parents
86ac6853
55b65b9c
Pipeline
#118296
passed with stages
in 2 minutes and 41 seconds
Changes
16
Pipelines
1
Show whitespace changes
Inline
Side-by-side
pom.xml
View file @
5b91a754
...
...
@@ -9,7 +9,7 @@
<groupId>
de.monticore.lang.monticar
</groupId>
<artifactId>
embedded-montiarc-math-rosmsg-generator
</artifactId>
<version>
0.1.
2
-SNAPSHOT
</version>
<version>
0.1.
3
-SNAPSHOT
</version>
<!-- == PROJECT DEPENDENCIES ============================================= -->
...
...
src/main/java/de/monticore/lang/monticar/generator/rosmsg/GeneratorRosMsg.java
View file @
5b91a754
package
de.monticore.lang.monticar.generator.rosmsg
;
import
de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol
;
import
de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAPortInstanceSymbol
;
import
de.monticore.lang.monticar.common2._ast.ASTCommonMatrixType
;
import
de.monticore.lang.monticar.generator.rosmsg.util.CMakeListsViewModel
;
import
de.monticore.lang.monticar.generator.rosmsg.util.FileContent
;
import
de.monticore.lang.monticar.generator.rosmsg.util.RosMsgTemplates
;
import
de.monticore.lang.monticar.struct._symboltable.StructFieldDefinitionSymbol
;
import
de.monticore.lang.monticar.struct._symboltable.StructSymbol
;
import
de.monticore.lang.monticar.ts.MCASTTypeSymbol
;
import
de.monticore.lang.monticar.ts.MCTypeSymbol
;
import
de.monticore.lang.monticar.ts.MontiCarTypeSymbol
;
import
de.monticore.lang.monticar.ts.references.MCTypeReference
;
import
de.monticore.symboltable.references.SymbolReference
;
import
de.se_rwth.commons.logging.Log
;
import
org.apache.commons.io.FileUtils
;
...
...
@@ -15,6 +20,7 @@ import java.io.File;
import
java.io.IOException
;
import
java.util.*
;
import
java.util.stream.Collectors
;
import
java.util.stream.Stream
;
public
class
GeneratorRosMsg
{
private
String
path
;
...
...
@@ -53,7 +59,7 @@ public class GeneratorRosMsg {
public
List
<
FileContent
>
generateStrings
(
MCTypeReference
<?
extends
MCTypeSymbol
>
typeReference
)
{
//is typeReference basic type or struct?
if
(
getRosType
(
currentPackageName
,
typeReference
)
!=
null
)
{
if
(
getRosType
(
currentPackageName
,
typeReference
,
ros2mode
)
!=
null
)
{
MCTypeSymbol
type
=
typeReference
.
getReferencedSymbol
();
List
<
FileContent
>
res
=
new
ArrayList
<>();
if
(
type
instanceof
StructSymbol
)
{
...
...
@@ -77,7 +83,7 @@ public class GeneratorRosMsg {
String
definition
=
structSymbol
.
getStructFieldDefinitions
().
stream
()
.
filter
(
sfds
->
sfds
.
getType
().
existsReferencedSymbol
())
.
map
(
sfds
->
getInMsgRosType
(
currentPackageName
,
sfds
.
getType
().
getReferencedSymbol
(),
ros2mode
)
+
" "
+
sfds
.
getName
(
))
.
map
(
sfds
->
getInMsgRosType
(
currentPackageName
,
sfds
.
getType
().
getReferencedSymbol
(),
ros2mode
)
+
" "
+
getFieldName
(
sfds
,
ros2mode
))
.
collect
(
Collectors
.
joining
(
"\n"
));
FileContent
fc
=
new
FileContent
();
...
...
@@ -114,10 +120,9 @@ public class GeneratorRosMsg {
}
private
static
String
getFieldName
(
StructFieldDefinitionSymbol
sfds
,
boolean
ros2mode
)
{
if
(
ros2mode
){
if
(
ros2mode
)
{
return
sfds
.
getName
().
toLowerCase
();
}
else
{
}
else
{
return
sfds
.
getName
();
}
...
...
@@ -229,13 +234,12 @@ public class GeneratorRosMsg {
}
private
static
String
getTargetName
(
StructSymbol
structSymbol
,
boolean
ros2mode
)
{
if
(
ros2mode
){
if
(
ros2mode
)
{
return
Arrays
.
stream
(
structSymbol
.
getFullName
()
.
split
(
"\\."
))
.
map
(
fn
->
fn
.
substring
(
0
,
1
).
toUpperCase
()
+
fn
.
substring
(
1
))
.
collect
(
Collectors
.
joining
());
}
else
{
}
else
{
return
structSymbol
.
getFullName
().
replace
(
"."
,
"_"
);
}
}
...
...
@@ -243,4 +247,61 @@ public class GeneratorRosMsg {
private
static
String
getFullTargetName
(
String
packageName
,
StructSymbol
structSymbol
,
boolean
ros2mode
)
{
return
ros2mode
?
packageName
+
"/msg/"
+
getTargetName
(
structSymbol
,
ros2mode
)
:
packageName
+
"/"
+
getTargetName
(
structSymbol
,
ros2mode
);
}
public
List
<
FileContent
>
generateProjectStrings
(
List
<
MCTypeReference
<?
extends
MCTypeSymbol
>>
typeReferences
)
{
ArrayList
<
FileContent
>
res
=
new
ArrayList
<>();
// .msg files
for
(
MCTypeReference
<?
extends
MCTypeSymbol
>
tr
:
typeReferences
)
{
for
(
FileContent
fc
:
generateStrings
(
tr
))
{
fc
.
setFileName
(
"msg/"
+
fc
.
getFileName
());
res
.
add
(
fc
);
}
}
if
(!
ros2mode
)
{
res
.
add
(
getRosCMakeLists
(
res
));
}
else
{
res
.
add
(
getRos2CMakeLists
(
res
));
res
.
add
(
getRos2PackageXml
());
}
return
res
;
}
private
FileContent
getRos2CMakeLists
(
ArrayList
<
FileContent
>
res
)
{
return
new
FileContent
(
"CMakeLists.txt"
,
RosMsgTemplates
.
generateRos2CMakeLists
(
new
CMakeListsViewModel
(
res
)));
}
private
FileContent
getRos2PackageXml
()
{
return
new
FileContent
(
"package.xml"
,
RosMsgTemplates
.
generateRos2Package
());
}
private
FileContent
getRosCMakeLists
(
ArrayList
<
FileContent
>
res
)
{
return
new
FileContent
(
"CMakeLists.txt"
,
RosMsgTemplates
.
generateRosCMakeLists
(
new
CMakeListsViewModel
(
res
)));
}
public
List
<
File
>
generateProject
(
List
<
MCTypeReference
<?
extends
MCTypeSymbol
>>
typeReferences
)
throws
IOException
{
List
<
File
>
res
=
new
ArrayList
<>();
List
<
FileContent
>
fileContents
=
generateProjectStrings
(
typeReferences
);
for
(
FileContent
fileContent
:
fileContents
)
{
File
file
=
new
File
(
path
+
"/"
+
fileContent
.
getFileName
());
FileUtils
.
write
(
file
,
fileContent
.
getFileContent
());
res
.
add
(
file
);
}
return
res
;
}
public
List
<
File
>
generateProject
(
EMAComponentInstanceSymbol
component
)
throws
IOException
{
Stream
<
EMAPortInstanceSymbol
>
p
=
component
.
getPortInstanceList
().
stream
();
Stream
<
EMAPortInstanceSymbol
>
subp
=
component
.
getSubComponents
().
stream
().
flatMap
(
sc
->
sc
.
getPortInstanceList
().
stream
());
List
<
MCTypeReference
<?
extends
MCTypeSymbol
>>
typeReferences
=
Stream
.
concat
(
p
,
subp
)
.
map
(
EMAPortInstanceSymbol:
:
getTypeReference
)
.
filter
(
SymbolReference:
:
existsReferencedSymbol
)
.
filter
(
mcTypeReference
->
mcTypeReference
.
getReferencedSymbol
()
instanceof
StructSymbol
)
.
collect
(
Collectors
.
toList
());
return
generateProject
(
typeReferences
);
}
}
src/main/java/de/monticore/lang/monticar/generator/rosmsg/util/CMakeListsViewModel.java
0 → 100644
View file @
5b91a754
package
de.monticore.lang.monticar.generator.rosmsg.util
;
import
java.nio.file.Paths
;
import
java.util.List
;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
public
class
CMakeListsViewModel
{
public
List
<
String
>
getFileNamesWithPath
()
{
return
fileContents
.
stream
()
.
map
(
FileContent:
:
getFileName
)
.
collect
(
Collectors
.
toList
());
}
public
List
<
String
>
getFileNamesOnly
()
{
return
fileContents
.
stream
()
.
map
(
FileContent:
:
getFileName
)
.
map
(
fn
->
Paths
.
get
(
fn
).
getFileName
().
toString
())
.
collect
(
Collectors
.
toList
());
}
private
List
<
FileContent
>
fileContents
;
public
CMakeListsViewModel
(
List
<
FileContent
>
fileContents
)
{
this
.
fileContents
=
fileContents
;
}
}
src/main/java/de/monticore/lang/monticar/generator/rosmsg/util/FileContent.java
View file @
5b91a754
...
...
@@ -4,6 +4,14 @@ public class FileContent {
private
String
fileName
;
private
String
fileContent
;
public
FileContent
()
{
}
public
FileContent
(
String
fileName
,
String
fileContent
)
{
this
.
fileName
=
fileName
;
this
.
fileContent
=
fileContent
;
}
public
String
getFileName
()
{
return
fileName
;
}
...
...
src/main/java/de/monticore/lang/monticar/generator/rosmsg/util/RosMsgTemplates.java
0 → 100644
View file @
5b91a754
package
de.monticore.lang.monticar.generator.rosmsg.util
;
import
de.se_rwth.commons.logging.Log
;
import
freemarker.template.Configuration
;
import
freemarker.template.Template
;
import
freemarker.template.TemplateException
;
import
freemarker.template.TemplateExceptionHandler
;
import
java.io.IOException
;
import
java.io.StringWriter
;
import
java.util.HashMap
;
public
class
RosMsgTemplates
{
private
RosMsgTemplates
(){
}
private
static
final
Template
ROS2_CMAKELISTS
;
private
static
final
Template
ROS2_PACKAGE_XML
;
private
static
final
Template
ROS_CMAKELISTS
;
static
{
Configuration
conf
=
new
Configuration
(
Configuration
.
VERSION_2_3_23
);
conf
.
setDefaultEncoding
(
"UTF-8"
);
conf
.
setTemplateExceptionHandler
(
TemplateExceptionHandler
.
DEBUG_HANDLER
);
conf
.
setLogTemplateExceptions
(
false
);
conf
.
setClassForTemplateLoading
(
RosMsgTemplates
.
class
,
"/templates"
);
try
{
ROS2_CMAKELISTS
=
conf
.
getTemplate
(
"ros2.MsgGen.CMakeLists.ftl"
);
ROS_CMAKELISTS
=
conf
.
getTemplate
(
"ros.MsgGen.CMakeLists.ftl"
);
ROS2_PACKAGE_XML
=
conf
.
getTemplate
(
"ros2.MsgGen.Package.ftl"
);
}
catch
(
IOException
e
)
{
String
msg
=
"could not load templates"
;
Log
.
error
(
msg
,
e
);
throw
new
RuntimeException
(
msg
,
e
);
}
}
public
static
String
generateRos2CMakeLists
(
CMakeListsViewModel
viewModel
){
HashMap
<
String
,
Object
>
data
=
new
HashMap
<>();
data
.
put
(
"viewModel"
,
viewModel
);
return
generate
(
ROS2_CMAKELISTS
,
data
);
}
public
static
String
generateRosCMakeLists
(
CMakeListsViewModel
viewModel
){
HashMap
<
String
,
Object
>
data
=
new
HashMap
<>();
data
.
put
(
"viewModel"
,
viewModel
);
return
generate
(
ROS_CMAKELISTS
,
data
);
}
public
static
String
generateRos2Package
(){
return
generate
(
ROS2_PACKAGE_XML
,
new
HashMap
<>());
}
private
static
String
generate
(
Template
template
,
Object
dataForTemplate
)
{
Log
.
errorIfNull
(
template
);
Log
.
errorIfNull
(
dataForTemplate
);
StringWriter
sw
=
new
StringWriter
();
try
{
template
.
process
(
dataForTemplate
,
sw
);
}
catch
(
TemplateException
|
IOException
e
)
{
Log
.
error
(
"template generation failed, template: "
+
template
.
getName
(),
e
);
}
return
sw
.
toString
();
}
}
src/main/resources/templates/ros.MsgGen.CMakeLists.ftl
0 → 100644
View file @
5b91a754
# generated by ros.MsgGen.CMakeLists.ftl
cmake_minimum_required
(
VERSION
2.8.12)
project
(
struct_msgs
)
find_package
(
genmsg
REQUIRED)
<#
list
viewModel.getFileNamesOnly() as fileOnly>
add_message_files
(
FILES
$
{
fileOnly
}
)
</#
list
>
<#
noparse
>
set
(
CATKIN_MESSAGE_GENERATORS
gencpp)
generate_messages
()
set
(
struct_msgs_INCLUDE_DIRS
$
{
struct_msgs_INCLUDE_DIRS
}
PARENT_SCOPE)
</#
noparse
>
\ No newline at end of file
src/main/resources/templates/ros2.MsgGen.CMakeLists.ftl
0 → 100644
View file @
5b91a754
# generated by ros2.MsgGen.CMakeLists.ftl
cmake_minimum_required
(
VERSION
3.5)
project
(
struct_msgs
)
find_package
(
ament_cmake
REQUIRED)
find_package
(
rosidl_default_generators
REQUIRED)
# declare the message files to generate code for
<#
list
viewModel.getFileNamesWithPath() as fileWithPath>
LIST
(
APPEND
msg_files "$
{
fileWithPath
}
")
</#
list
>
<#
noparse
>
rosidl_generate_interfaces
(${
PROJECT_NAME
}
$
{
msg_files
}
)
ament_export_dependencies
(
rosidl_default_runtime
)
ament_package
()
set
(
struct_msgs_LIBRARIES
struct_msgs__rosidl_typesupport_cpp struct_msgs__rosidl_typesupport_fastrtps_cpp struct_msgs__rosidl_typesupport_introspection_cpp PARENT_SCOPE)
export
(
TARGETS
struct_msgs__rosidl_typesupport_cpp struct_msgs__rosidl_typesupport_fastrtps_cpp struct_msgs__rosidl_typesupport_introspection_cpp FILE struct_msgs.cmake)
</#
noparse
>
\ No newline at end of file
src/main/resources/templates/ros2.MsgGen.Package.ftl
0 → 100644
View file @
5b91a754
<?
xml
version="1.0"?>
<?
xml-model
href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<!-
-Generated
by ros2.MsgGen.Package.ftl-->
<
package
format="3">
<name>struct_msgs</name>
<version>0.0.0</version>
<description>Generated Messages from Struct</description>
<maintainer email="unknown@unknown.com">Unknown</maintainer>
<license>Unknown</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<buildtool_depend>rosidl_default_generators</buildtool_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
<member_of_group>rosidl_interface_packages</member_of_group>
</
package
>
\ No newline at end of file
src/test/java/de/monticore/lang/monticar/generator/rosmsg/AbstractSymtabTest.java
View file @
5b91a754
...
...
@@ -17,6 +17,7 @@ import de.monticore.lang.tagging._symboltable.TaggingResolver;
import
de.monticore.symboltable.GlobalScope
;
import
de.monticore.symboltable.Scope
;
import
de.se_rwth.commons.logging.Log
;
import
org.apache.commons.io.FilenameUtils
;
import
org.junit.Assert
;
import
java.io.File
;
...
...
src/test/java/de/monticore/lang/monticar/generator/rosmsg/ProjectTest.java
0 → 100644
View file @
5b91a754
package
de.monticore.lang.monticar.generator.rosmsg
;
import
de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol
;
import
de.monticore.symboltable.Scope
;
import
org.junit.Test
;
import
java.io.File
;
import
java.io.IOException
;
import
java.nio.file.Paths
;
import
java.util.List
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
public
class
ProjectTest
extends
AbstractSymtabTest
{
@Test
public
void
testRosProjectGeneration
()
throws
IOException
{
Scope
symtab
=
createSymTab
(
"src/test/resources/"
);
EMAComponentInstanceSymbol
component
=
symtab
.<
EMAComponentInstanceSymbol
>
resolve
(
"tests.basicStructComp"
,
EMAComponentInstanceSymbol
.
KIND
).
orElse
(
null
);
assertNotNull
(
component
);
GeneratorRosMsg
generatorRosMsg
=
new
GeneratorRosMsg
();
generatorRosMsg
.
setTarget
(
"target/projects/ros/basicStructComp"
,
"struct_msgs"
);
List
<
File
>
files
=
generatorRosMsg
.
generateProject
(
component
);
checkFilesAreEqual
(
files
,
Paths
.
get
(
"target/projects/ros/basicStructComp"
),
"projects/ros/basicStructComp/"
);
}
@Test
public
void
testRos2ProjectGeneration
()
throws
IOException
{
Scope
symtab
=
createSymTab
(
"src/test/resources/"
);
EMAComponentInstanceSymbol
component
=
symtab
.<
EMAComponentInstanceSymbol
>
resolve
(
"tests.basicStructComp"
,
EMAComponentInstanceSymbol
.
KIND
).
orElse
(
null
);
assertNotNull
(
component
);
GeneratorRosMsg
generatorRosMsg
=
new
GeneratorRosMsg
();
generatorRosMsg
.
setTarget
(
"target/projects/ros2/basicStructComp"
,
"struct_msgs"
);
generatorRosMsg
.
setRos2mode
(
true
);
List
<
File
>
files
=
generatorRosMsg
.
generateProject
(
component
);
checkFilesAreEqual
(
files
,
Paths
.
get
(
"target/projects/ros2/basicStructComp"
),
"projects/ros2/basicStructComp/"
);
}
}
src/test/resources/results/CMakeLists.txt
deleted
100644 → 0
View file @
86ac6853
cmake_minimum_required
(
VERSION 3.5
)
project
(
multinested
)
find_package
(
genmsg REQUIRED
)
FILE
(
GLOB MSG_FILES RELATIVE
${
CMAKE_CURRENT_SOURCE_DIR
}
*.msg
)
add_message_files
(
DIRECTORY
${
CMAKE_CURRENT_SOURCE_DIR
}
FILES
${
MSG_FILES
}
)
generate_messages
()
\ No newline at end of file
src/test/resources/results/projects/ros/basicStructComp/CMakeLists.txt
0 → 100644
View file @
5b91a754
# generated by ros.MsgGen.CMakeLists.ftl
cmake_minimum_required
(
VERSION 2.8.12
)
project
(
struct_msgs
)
find_package
(
genmsg REQUIRED
)
add_message_files
(
FILES structs_BasicStruct.msg
)
set
(
CATKIN_MESSAGE_GENERATORS gencpp
)
generate_messages
()
set
(
struct_msgs_INCLUDE_DIRS
${
struct_msgs_INCLUDE_DIRS
}
PARENT_SCOPE
)
src/test/resources/results/projects/ros/basicStructComp/msg/structs_BasicStruct.msg
0 → 100644
View file @
5b91a754
float64 fieldQ1
float64 fieldQ2
int32 fieldZ1
int32 fieldZ2
bool fieldB1
\ No newline at end of file
src/test/resources/results/projects/ros2/basicStructComp/CMakeLists.txt
0 → 100644
View file @
5b91a754
# generated by ros2.MsgGen.CMakeLists.ftl
cmake_minimum_required
(
VERSION 3.5
)
project
(
struct_msgs
)
find_package
(
ament_cmake REQUIRED
)
find_package
(
rosidl_default_generators REQUIRED
)
# declare the message files to generate code for
LIST
(
APPEND msg_files
"msg/StructsBasicStruct.msg"
)
rosidl_generate_interfaces
(
${
PROJECT_NAME
}
${
msg_files
}
)
ament_export_dependencies
(
rosidl_default_runtime
)
ament_package
()
set
(
struct_msgs_LIBRARIES struct_msgs__rosidl_typesupport_cpp struct_msgs__rosidl_typesupport_fastrtps_cpp struct_msgs__rosidl_typesupport_introspection_cpp PARENT_SCOPE
)
export
(
TARGETS struct_msgs__rosidl_typesupport_cpp struct_msgs__rosidl_typesupport_fastrtps_cpp struct_msgs__rosidl_typesupport_introspection_cpp FILE struct_msgs.cmake
)
src/test/resources/results/projects/ros2/basicStructComp/msg/StructsBasicStruct.msg
0 → 100644
View file @
5b91a754
float64 fieldq1
float64 fieldq2
int32 fieldz1
int32 fieldz2
bool fieldb1
\ No newline at end of file
src/test/resources/results/projects/ros2/basicStructComp/package.xml
0 → 100644
View file @
5b91a754
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<!--Generated by ros2.MsgGen.Package.ftl-->
<package
format=
"3"
>
<name>
struct_msgs
</name>
<version>
0.0.0
</version>
<description>
Generated Messages from Struct
</description>
<maintainer
email=
"unknown@unknown.com"
>
Unknown
</maintainer>
<license>
Unknown
</license>
<buildtool_depend>
ament_cmake
</buildtool_depend>
<buildtool_depend>
rosidl_default_generators
</buildtool_depend>
<exec_depend>
rosidl_default_runtime
</exec_depend>
<export>
<build_type>
ament_cmake
</build_type>
</export>
<member_of_group>
rosidl_interface_packages
</member_of_group>
</package>
\ No newline at end of file
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment