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
436b1694
Commit
436b1694
authored
Apr 04, 2019
by
Alexander David Hellwig
Browse files
Added generation of ROS/ROS2 Projects containing messges generated from structs
parent
86ac6853
Pipeline
#116329
passed with stages
in 2 minutes and 37 seconds
Changes
8
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
pom.xml
View file @
436b1694
...
...
@@ -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 @
436b1694
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.FileContent
;
import
de.monticore.lang.monticar.struct._symboltable.StructFieldDefinitionSymbol
;
...
...
@@ -8,11 +10,13 @@ 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
;
import
java.io.File
;
import
java.io.IOException
;
import
java.nio.file.Paths
;
import
java.util.*
;
import
java.util.stream.Collectors
;
...
...
@@ -53,7 +57,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 +81,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 +118,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 +232,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 +245,124 @@ 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
)
{
FileContent
cmakeLists
=
new
FileContent
();
cmakeLists
.
setFileName
(
"CMakeLists.txt"
);
StringBuilder
content
=
new
StringBuilder
();
content
.
append
(
"cmake_minimum_required(VERSION 3.5)\n"
);
content
.
append
(
"project(struct_msgs)\n"
);
content
.
append
(
"find_package(ament_cmake REQUIRED)\n"
);
content
.
append
(
"find_package(rosidl_default_generators REQUIRED)\n"
);
content
.
append
(
"# declare the message files to generate code for\n"
);
for
(
FileContent
fc
:
res
)
{
content
.
append
(
"LIST(APPEND msg_files \""
)
.
append
(
fc
.
getFileName
())
.
append
(
"\")\n"
);
}
content
.
append
(
"rosidl_generate_interfaces(${PROJECT_NAME} ${msg_files})\n"
);
content
.
append
(
"ament_export_dependencies(rosidl_default_runtime)\n"
);
content
.
append
(
"ament_package()\n"
);
content
.
append
(
"set(struct_msgs_LIBRARIES struct_msgs__rosidl_typesupport_cpp struct_msgs__rosidl_typesupport_fastrtps_cpp struct_msgs__rosidl_typesupport_introspection_cpp PARENT_SCOPE)\n"
);
content
.
append
(
"export(TARGETS struct_msgs__rosidl_typesupport_cpp struct_msgs__rosidl_typesupport_fastrtps_cpp struct_msgs__rosidl_typesupport_introspection_cpp FILE struct_msgs.cmake)\n"
);
cmakeLists
.
setFileContent
(
content
.
toString
());
return
cmakeLists
;
}
private
FileContent
getRos2PackageXml
(){
String
res
=
"<?xml version=\"1.0\"?>\n"
+
"<?xml-model href=\"http://download.ros.org/schema/package_format2.xsd\" schematypens=\"http://www.w3.org/2001/XMLSchema\"?>\n"
+
"<package format=\"3\">\n"
+
" <name>struct_msgs</name>\n"
+
" <version>0.0.0</version>\n"
+
" <description>Generated Messages from Struct</description>\n"
+
" <maintainer email=\"unknown@unknown.com\">Unknown</maintainer>\n"
+
" <license>Unknown</license>\n"
+
"\n"
+
" <buildtool_depend>ament_cmake</buildtool_depend>\n"
+
" <buildtool_depend>rosidl_default_generators</buildtool_depend>\n"
+
" <exec_depend>rosidl_default_runtime</exec_depend>\n"
+
"\n"
+
" <export>\n"
+
" <build_type>ament_cmake</build_type>\n"
+
" </export>\n"
+
" <member_of_group>rosidl_interface_packages</member_of_group>\n"
+
"</package>"
;
FileContent
fileContent
=
new
FileContent
();
fileContent
.
setFileName
(
"package.xml"
);
fileContent
.
setFileContent
(
res
);
return
fileContent
;
}
private
FileContent
getRosCMakeLists
(
ArrayList
<
FileContent
>
res
)
{
FileContent
cmakeLists
=
new
FileContent
();
cmakeLists
.
setFileName
(
"CMakeLists.txt"
);
StringBuilder
content
=
new
StringBuilder
();
content
.
append
(
"cmake_minimum_required(VERSION 2.8.12)\n"
);
content
.
append
(
"project(struct_msgs)\n"
);
content
.
append
(
"find_package(genmsg REQUIRED)\n\n"
);
res
.
stream
()
.
map
(
FileContent:
:
getFileName
)
.
map
(
fn
->
Paths
.
get
(
fn
).
getFileName
().
toString
())
.
map
(
fn
->
"add_message_files(FILES "
+
fn
+
")\n"
)
.
forEach
(
content:
:
append
);
content
.
append
(
"generate_messages()\n"
);
content
.
append
(
"set(struct_msgs_INCLUDE_DIRS ${struct_msgs_INCLUDE_DIRS} PARENT_SCOPE)\n"
);
cmakeLists
.
setFileContent
(
content
.
toString
());
return
cmakeLists
;
}
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
{
List
<
MCTypeReference
<?
extends
MCTypeSymbol
>>
typeReferences
=
component
.
getPortInstanceList
().
stream
()
.
map
(
EMAPortInstanceSymbol:
:
getTypeReference
)
.
filter
(
SymbolReference:
:
existsReferencedSymbol
)
.
filter
(
mcTypeReference
->
mcTypeReference
.
getReferencedSymbol
()
instanceof
StructSymbol
)
.
collect
(
Collectors
.
toList
());
return
generateProject
(
typeReferences
);
}
}
src/test/java/de/monticore/lang/monticar/generator/rosmsg/ProjectTest.java
0 → 100644
View file @
436b1694
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/projects/ros/basicStructComp/CMakeLists.txt
0 → 100644
View file @
436b1694
cmake_minimum_required
(
VERSION 2.8.12
)
project
(
struct_msgs
)
find_package
(
genmsg REQUIRED
)
add_message_files
(
FILES structs_BasicStruct.msg
)
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 @
436b1694
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 @
436b1694
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 @
436b1694
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 @
436b1694
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<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