Added rclcpp/ros2 generator impl + basic tests

parent 488147f8
Pipeline #101058 passed with stages
in 8 minutes and 18 seconds
...@@ -5,16 +5,11 @@ import com.google.gson.stream.JsonReader; ...@@ -5,16 +5,11 @@ import com.google.gson.stream.JsonReader;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol; import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
import de.monticore.lang.embeddedmontiarc.tagging.middleware.ros.RosToEmamTagSchema; import de.monticore.lang.embeddedmontiarc.tagging.middleware.ros.RosToEmamTagSchema;
import de.monticore.lang.monticar.emadl.generator.EMADLAbstractSymtab; import de.monticore.lang.monticar.emadl.generator.EMADLAbstractSymtab;
import de.monticore.lang.monticar.emadl.generator.EMADLGeneratorCli; import de.monticore.lang.monticar.generator.middleware.impls.*;
import de.monticore.lang.monticar.generator.middleware.impls.CPPGenImpl;
import de.monticore.lang.monticar.generator.middleware.impls.EMADLGeneratorImpl;
import de.monticore.lang.monticar.generator.middleware.impls.ODVGenImpl;
import de.monticore.lang.monticar.generator.middleware.impls.RosCppGenImpl;
import de.monticore.lang.monticar.generator.order.simulator.AbstractSymtab; import de.monticore.lang.monticar.generator.order.simulator.AbstractSymtab;
import de.monticore.lang.monticar.generator.roscpp.helper.TagHelper; import de.monticore.lang.monticar.generator.roscpp.helper.TagHelper;
import de.monticore.lang.tagging._symboltable.TaggingResolver; import de.monticore.lang.tagging._symboltable.TaggingResolver;
import de.se_rwth.commons.logging.Log; import de.se_rwth.commons.logging.Log;
import org.apache.commons.cli.*;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileReader; import java.io.FileReader;
...@@ -24,7 +19,6 @@ import java.nio.file.Paths; ...@@ -24,7 +19,6 @@ import java.nio.file.Paths;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
public final class DistributedTargetGeneratorCli { public final class DistributedTargetGeneratorCli {
...@@ -48,6 +42,9 @@ public final class DistributedTargetGeneratorCli { ...@@ -48,6 +42,9 @@ public final class DistributedTargetGeneratorCli {
public static final String GENERATOR_EMADL = "emadlcpp"; public static final String GENERATOR_EMADL = "emadlcpp";
public static final String GENERATOR_ROSCPP = "roscpp"; public static final String GENERATOR_ROSCPP = "roscpp";
public static final String GENERATOR_ODV = "odv"; public static final String GENERATOR_ODV = "odv";
//ros2cpp is an alias for rclcpp
public static final String GENERATOR_RCLCPP = "rclcpp";
public static final String GENERATOR_ROS2CPP = "ros2cpp";
private DistributedTargetGeneratorCli() {} private DistributedTargetGeneratorCli() {}
...@@ -85,6 +82,8 @@ public final class DistributedTargetGeneratorCli { ...@@ -85,6 +82,8 @@ public final class DistributedTargetGeneratorCli {
res.add(GENERATOR_EMADL); res.add(GENERATOR_EMADL);
res.add(GENERATOR_ROSCPP); res.add(GENERATOR_ROSCPP);
res.add(GENERATOR_ODV); res.add(GENERATOR_ODV);
res.add(GENERATOR_ROS2CPP);
res.add(GENERATOR_RCLCPP);
return res; return res;
} }
...@@ -95,7 +94,8 @@ public final class DistributedTargetGeneratorCli { ...@@ -95,7 +94,8 @@ public final class DistributedTargetGeneratorCli {
} }
String fullModelsDirPath = expandHomeDir(cliParameters.getModelsDir()); String fullModelsDirPath = expandHomeDir(cliParameters.getModelsDir());
if(cliParameters.getGenerators().size() == 0){ Set<String> generators = cliParameters.getGenerators();
if(generators.size() == 0){
Log.error("0x6178E: No generator was specified!"); Log.error("0x6178E: No generator was specified!");
return; return;
} }
...@@ -106,7 +106,7 @@ public final class DistributedTargetGeneratorCli { ...@@ -106,7 +106,7 @@ public final class DistributedTargetGeneratorCli {
} }
TaggingResolver taggingResolver; TaggingResolver taggingResolver;
if (cliParameters.getGenerators().contains(GENERATOR_EMADL)) { if (generators.contains(GENERATOR_EMADL)) {
taggingResolver = EMADLAbstractSymtab.createSymTabAndTaggingResolver(fullModelsDirPath); taggingResolver = EMADLAbstractSymtab.createSymTabAndTaggingResolver(fullModelsDirPath);
} }
else{ else{
...@@ -118,9 +118,13 @@ public final class DistributedTargetGeneratorCli { ...@@ -118,9 +118,13 @@ public final class DistributedTargetGeneratorCli {
Set<String> validGenNames = getGeneratorNames(); Set<String> validGenNames = getGeneratorNames();
cliParameters.getGenerators().forEach(genName -> { generators.forEach(genName -> {
if (validGenNames.contains(genName)) { if (validGenNames.contains(genName)) {
Log.warn("Using generator " + genName); if(genName.equals(GENERATOR_ROS2CPP)) {
Log.warn("Using generator " + GENERATOR_RCLCPP + " since " + genName + " is an alias!");
}else {
Log.warn("Using generator " + genName);
}
} else { } else {
Log.error("0xE28B6: Not a valid generator Name:" + genName +"."); Log.error("0xE28B6: Not a valid generator Name:" + genName +".");
return; return;
...@@ -134,11 +138,11 @@ public final class DistributedTargetGeneratorCli { ...@@ -134,11 +138,11 @@ public final class DistributedTargetGeneratorCli {
return; return;
} }
if (cliParameters.getGenerators().contains(GENERATOR_CPP)) { if (generators.contains(GENERATOR_CPP)) {
generator.add(new CPPGenImpl(), "cpp"); generator.add(new CPPGenImpl(), "cpp");
} }
if (cliParameters.getGenerators().contains(GENERATOR_EMADL)) { if (generators.contains(GENERATOR_EMADL)) {
if(cliParameters.getEmadlBackend() != null && !cliParameters.getEmadlBackend().equals("")) { if(cliParameters.getEmadlBackend() != null && !cliParameters.getEmadlBackend().equals("")) {
generator.add(new EMADLGeneratorImpl(fullModelsDirPath, cliParameters.getEmadlBackend()), "cpp"); generator.add(new EMADLGeneratorImpl(fullModelsDirPath, cliParameters.getEmadlBackend()), "cpp");
}else{ }else{
...@@ -147,13 +151,19 @@ public final class DistributedTargetGeneratorCli { ...@@ -147,13 +151,19 @@ public final class DistributedTargetGeneratorCli {
} }
} }
if (cliParameters.getGenerators().contains(GENERATOR_ROSCPP)) { if (generators.contains(GENERATOR_ROSCPP)) {
generator.add(new RosCppGenImpl(), "roscpp"); generator.add(new RosCppGenImpl(), "roscpp");
RosToEmamTagSchema.registerTagTypes(taggingResolver); RosToEmamTagSchema.registerTagTypes(taggingResolver);
TagHelper.resolveTags(taggingResolver, componentInstanceSymbol); TagHelper.resolveTags(taggingResolver, componentInstanceSymbol);
} }
if (cliParameters.getGenerators().contains(GENERATOR_ODV)) { if (generators.contains(GENERATOR_RCLCPP) || generators.contains(GENERATOR_ROS2CPP)) {
generator.add(new RclCppGenImpl(), "rclcpp");
RosToEmamTagSchema.registerTagTypes(taggingResolver);
TagHelper.resolveTags(taggingResolver, componentInstanceSymbol);
}
if (generators.contains(GENERATOR_ODV)) {
generator.add(new ODVGenImpl(), "odv"); generator.add(new ODVGenImpl(), "odv");
} }
......
package de.monticore.lang.monticar.generator.middleware.impls;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAPortInstanceSymbol;
import de.monticore.lang.monticar.generator.roscpp.GeneratorRosCpp;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import de.se_rwth.commons.logging.Log;
import java.io.File;
import java.io.IOException;
import java.util.List;
public class RclCppGenImpl implements GeneratorImpl {
private String generationTargetPath;
private GeneratorRosCpp generatorRosCpp;
public RclCppGenImpl(){
generatorRosCpp = new GeneratorRosCpp();
generatorRosCpp.setGenerateCMake(true);
generatorRosCpp.setRos2Mode(true);
}
public void setGeneratorRosCpp(GeneratorRosCpp generatorRosCpp) {
this.generatorRosCpp = generatorRosCpp;
}
@Override
public List<File> generate(EMAComponentInstanceSymbol componentInstanceSymbol, TaggingResolver taggingResolver) throws IOException {
generatorRosCpp.setGenerationTargetPath(generationTargetPath);
return generatorRosCpp.generateFiles(componentInstanceSymbol, taggingResolver);
}
@Override
public void setGenerationTargetPath(String path) {
this.generationTargetPath = path;
}
@Override
public boolean willAccept(EMAComponentInstanceSymbol componentInstanceSymbol) {
boolean result = componentInstanceSymbol.getPortInstanceList().stream().anyMatch(EMAPortInstanceSymbol::isRosPort);
if(!result){
Log.warn("Generator rclcpp: No ROS Ports found! Ignoring component " + componentInstanceSymbol.getName());
}
return result;
}
}
...@@ -10,7 +10,6 @@ import java.io.File; ...@@ -10,7 +10,6 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
//TODO: make GeneratorRosCpp implement GeneratorImpl
public class RosCppGenImpl implements GeneratorImpl { public class RosCppGenImpl implements GeneratorImpl {
private String generationTargetPath; private String generationTargetPath;
private GeneratorRosCpp generatorRosCpp; private GeneratorRosCpp generatorRosCpp;
......
...@@ -286,4 +286,57 @@ public class CliTest { ...@@ -286,4 +286,57 @@ public class CliTest {
private boolean logContains(String errorCode) { private boolean logContains(String errorCode) {
return LogConfig.getFindings().stream().map(Finding::getMsg).anyMatch(msg -> msg.contains(errorCode)); return LogConfig.getFindings().stream().map(Finding::getMsg).anyMatch(msg -> msg.contains(errorCode));
} }
@Test
public void testRclcppGenerator(){
String targetDir = "target/cliTest/AllGenerators/";
String json = buildParameterJson(
VALID_MODELS_DIR_OPTION,
VALID_ROOT_MODEL_OPTION,
Arrays.asList("cpp","rclcpp"),
targetDir);
DistributedTargetGeneratorCli.main(new String[]{"-r", json});
String[] positiveFileNames = {
"CMakeLists.txt",
"tests_a_addComp/cpp/tests_a_addComp.h",
"tests_a_addComp/cpp/CMakeLists.txt",
"tests_a_addComp/coordinator/CMakeLists.txt",
"tests_a_addComp/coordinator/Coordinator_tests_a_addComp.cpp",
"tests_a_addComp/rclcpp/RosAdapter_tests_a_addComp.h",
"tests_a_addComp/rclcpp/CMakeLists.txt",
};
for (String positiveFileName : positiveFileNames) {
assertTrue(Files.exists(Paths.get(targetDir + positiveFileName)));
}
}
@Test
public void testRos2cppGenerator(){
String targetDir = "target/cliTest/AllGenerators/";
String json = buildParameterJson(
VALID_MODELS_DIR_OPTION,
VALID_ROOT_MODEL_OPTION,
Arrays.asList("cpp","ros2cpp"),
targetDir);
DistributedTargetGeneratorCli.main(new String[]{"-r", json});
String[] positiveFileNames = {
"CMakeLists.txt",
"tests_a_addComp/cpp/tests_a_addComp.h",
"tests_a_addComp/cpp/CMakeLists.txt",
"tests_a_addComp/coordinator/CMakeLists.txt",
"tests_a_addComp/coordinator/Coordinator_tests_a_addComp.cpp",
"tests_a_addComp/rclcpp/RosAdapter_tests_a_addComp.h",
"tests_a_addComp/rclcpp/CMakeLists.txt",
};
for (String positiveFileName : positiveFileNames) {
assertTrue(Files.exists(Paths.get(targetDir + positiveFileName)));
}
}
} }
...@@ -2,6 +2,7 @@ package de.monticore.lang.monticar.generator.middleware; ...@@ -2,6 +2,7 @@ package de.monticore.lang.monticar.generator.middleware;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._ast.ASTComponent; import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._ast.ASTComponent;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.cncModel.EMAComponentSymbol; import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.cncModel.EMAComponentSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.cncModel.EMAPortSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol; import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAPortInstanceSymbol; import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAPortInstanceSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarcmath.cocos.EmbeddedMontiArcMathCoCos; import de.monticore.lang.embeddedmontiarc.embeddedmontiarcmath.cocos.EmbeddedMontiArcMathCoCos;
...@@ -19,6 +20,7 @@ import org.junit.Test; ...@@ -19,6 +20,7 @@ import org.junit.Test;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static junit.framework.TestCase.assertTrue; import static junit.framework.TestCase.assertTrue;
...@@ -335,4 +337,20 @@ public class GenerationTest extends AbstractSymtabTest { ...@@ -335,4 +337,20 @@ public class GenerationTest extends AbstractSymtabTest {
assertFalse(filenames.stream().anyMatch(fn -> fn.endsWith("rosMsg/CMakeLists.txt"))); assertFalse(filenames.stream().anyMatch(fn -> fn.endsWith("rosMsg/CMakeLists.txt")));
} }
@Test
public void testRos2Generation() throws IOException {
TaggingResolver taggingResolver = createSymTabAndTaggingResolver(TEST_PATH);
EMAComponentInstanceSymbol componentInstanceSymbol = taggingResolver.<EMAComponentInstanceSymbol>resolve("tests.aRos2.addComp", EMAComponentInstanceSymbol.KIND).orElse(null);
RosToEmamTagSchema.registerTagTypes(taggingResolver);
assertNotNull(componentInstanceSymbol);
TagHelper.resolveTags(taggingResolver, componentInstanceSymbol);
DistributedTargetGenerator distributedTargetGenerator = new DistributedTargetGenerator();
distributedTargetGenerator.setGenerationTargetPath("./target/generated-sources-ros2/addComp/src");
distributedTargetGenerator.add(new CPPGenImpl(),"cpp");
distributedTargetGenerator.add(new RclCppGenImpl(), "rclcpp");
List<File> files = distributedTargetGenerator.generate(componentInstanceSymbol, taggingResolver);
}
} }
#ifndef HELPERA_H
#define HELPERA_H
#include <iostream>
#include "armadillo.h"
#include <stdarg.h>
#include <initializer_list>
#include <fstream>
using namespace arma;
#ifndef _FILESTRING_CONVERSION___A
#define _FILESTRING_CONVERSION___A
#include "armadillo.h"
using namespace arma;
void toFileString(std::ofstream& myfile, mat A){
myfile << "[";
for (int i = 0; i < A.n_rows; i++){
for (int j = 0; j < A.n_cols; j++){
myfile << A(i,j);
if(j + 1 < A.n_cols){
myfile << ", ";
}
}
if(i + 1 < A.n_rows){
myfile << ";";
}
}
myfile << "]";
}
void toFileString(std::ofstream& myfile, double A){
myfile << A;
}
void toFileString(std::ofstream& myfile, float A){
myfile << A;
}
void toFileString(std::ofstream& myfile, int A){
myfile << A;
}
void toFileString(std::ofstream& myfile, bool A){
myfile << A;
}
bool Is_close(mat& X, mat& Y, double tol)
{
// abs returns a mat type then max checks columns and returns a row_vec
// max used again will return the biggest element in the row_vec
bool close(false);
if(arma::max(arma::max(arma::abs(X-Y))) < tol)
{
close = true;
}
return close;
}
void rangeValueCheck(double A, double lower, double upper){
REQUIRE( A >= lower );
REQUIRE( A <= upper );
}
void rangeValueCheck(int A, double lower, double upper){
REQUIRE( A >= lower );
REQUIRE( A <= upper );
}
void rangeValueCheck(mat& A, mat& lower , mat& upper){
REQUIRE(Is_close(A, lower, 0.0001));
REQUIRE(Is_close(A, upper, 0.0001));
}
#endif
class HelperA{
public:
static mat getEigenVectors(mat A){
vec eigenValues;
mat eigenVectors;
eig_sym(eigenValues,eigenVectors,A);
return eigenVectors;
}
static vec getEigenValues(mat A){
vec eigenValues;
mat eigenVectors;
eig_sym(eigenValues,eigenVectors,A);
return eigenValues;
}
static mat getKMeansClusters(mat A, int k){
mat clusters;
kmeans(clusters,A.t(),k,random_subset,20,true);
/*printf("cluster centroid calculation done\n");
std::ofstream myfile;
myfile.open("data after cluster.txt");
myfile << A;
myfile.close();
std::ofstream myfile2;
myfile2.open("cluster centroids.txt");
myfile2 << clusters;
myfile2.close();*/
mat indexedData=getKMeansClustersIndexData(A.t(), clusters);
/*std::ofstream myfile3;
myfile3.open("data after index.txt");
myfile3 << indexedData;
myfile3.close();
*/
return indexedData;
}
static mat getKMeansClustersIndexData(mat A, mat centroids){
mat result=mat(A.n_cols, 1);
for(int i=0;i<A.n_cols;++i){
result(i, 0) = getIndexForClusterCentroids(A, i, centroids);
}
return result;
}
static int getIndexForClusterCentroids(mat A, int colIndex, mat centroids){
int index=1;
double lowestDistance=getEuclideanDistance(A, colIndex, centroids, 0);
for(int i=1;i<centroids.n_cols;++i){
double curDistance=getEuclideanDistance(A, colIndex, centroids, i);
if(curDistance<lowestDistance){
lowestDistance=curDistance;
index=i+1;
}
}
return index;
}
static double getEuclideanDistance(mat A, int colIndexA, mat B, int colIndexB){
double distance=0;
for(int i=0;i<A.n_rows;++i){
double elementA=A(i,colIndexA);
double elementB=B(i,colIndexB);
double diff=elementA-elementB;
distance+=diff*diff;
}
return sqrt(distance);
}
static mat getSqrtMat(mat A){
cx_mat result=sqrtmat(A);
return real(result);
}
static mat getSqrtMatDiag(mat A){
for(int i=0;i<A.n_rows;++i){
double curVal = A(i,i);
A(i,i) = sqrt(curVal);
}
return A;
}
static mat invertDiagMatrix(mat A){
for(int i=0;i<A.n_rows;++i){
double curVal = A(i,i);
A(i,i) = 1/curVal;
}
return A;
}
};
#endif
package tests.aRos2;
conforms to de.monticore.lang.monticar.generator.roscpp.RosToEmamTagSchema;
tags Add {
tag addComp.in1 with RosConnection = {topic = (/clock, std_msgs/msg/Float64), msgField = data};
tag addComp.out1 with RosConnection = {topic = (/echo, std_msgs/msg/Float64), msgField = data};
}
package tests.aRos2;
component AddComp{
ports in Q in1,
in Q in2,
out Q out1;
implementation Math{
out1 = in1 + in2;
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment