Commit b698b47b authored by Nils Kaminski's avatar Nils Kaminski
Browse files

Adding EMAMOpt tests

parent 81df71af
package de.monticore.lang.monticar.generator.cpp.mathopt;
import de.monticore.lang.math._symboltable.expression.MathExpressionSymbol;
import de.monticore.lang.mathopt._symboltable.MathOptimizationStatementSymbol;
import de.monticore.lang.monticar.generator.BaseMathFunctionFixerHandler;
import de.monticore.lang.monticar.generator.cpp.BluePrintCPP;
/**
* fixes math optimization functions
*
* @author Christoph Richter
*/
public class MathOptFunctionFixer extends BaseMathFunctionFixerHandler {
@Override
protected boolean canFixMathSymbol(MathExpressionSymbol symbol) {
boolean canHandle = false;
if (symbol instanceof MathOptimizationStatementSymbol)
canHandle = true;
return canHandle;
}
@Override
protected void doFixMathFunction(MathExpressionSymbol symbol, BluePrintCPP bluePrintCPP) {
// nothing to fix here
}
@Override
public String getRole() {
return "MathOptFunctionFixer";
}
}
package de.monticore.lang.monticar.generator.mathopt;
//import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol;
//import de.monticore.lang.monticar.generator.cpp.EMAMOpt2CPPSymbolTableHelper;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.AbstractSymtabTest;
import de.monticore.lang.monticar.generator.cpp.GeneratorCPP;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.List;
import static org.junit.Assert.assertNotNull;
public class CarModelGenerationTest extends AbstractSymtabTest {
// private static TaggingResolver symtab = EMAMOpt2CPPSymbolTableHelper.getInstance().createSymTabAndTaggingResolver("src/test/resources");
protected static List<File> doGenerateModel(String fullModelName) throws IOException {
TaggingResolver symtab = createSymTabAndTaggingResolver("src/test/resources/mathopt");
EMAComponentInstanceSymbol componentInstanceSymbol = symtab.<EMAComponentInstanceSymbol>resolve(fullModelName, EMAComponentInstanceSymbol.KIND).orElse(null);
assertNotNull(componentInstanceSymbol);
GeneratorCPP generatorCPP = new GeneratorCPP();
generatorCPP.useArmadilloBackend();
generatorCPP.setGenerationTargetPath("./target/generated-sources-cpp/mathopt/carmodel/" + fullModelName.substring(fullModelName.lastIndexOf(".") + 1, fullModelName.length()));
return generatorCPP.generateFiles(componentInstanceSymbol, symtab);
}
@Test
public void carModelInstanceTest() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.carmodel.carModelInstanceTest");
}
}
package de.monticore.lang.monticar.generator.mathopt;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.AbstractSymtabTest;
import de.monticore.lang.monticar.generator.cpp.GeneratorCPP;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.List;
import static org.junit.Assert.assertNotNull;
/**
* Test class for Cplex solver
*
* @author Christoph Richter
*/
public class GeneratorCplexSolverTest extends AbstractSymtabTest {
/**
* symbol table as static class variable so it must be created only once
*/
// private static TaggingResolver symtab = createSymTabAndTaggingResolver("src/test/resources/mathopt");
protected static List<File> doGenerateModel(String fullModelName) throws IOException {
TaggingResolver symtab = createSymTabAndTaggingResolver("src/test/resources/mathopt");
EMAComponentInstanceSymbol componentInstanceSymbol = symtab.<EMAComponentInstanceSymbol>resolve(fullModelName, EMAComponentInstanceSymbol.KIND).orElse(null);
assertNotNull(componentInstanceSymbol);
GeneratorCPP generator = new GeneratorCPP();
//TODO adding solver for opt! and uncomment test
// for (GeneratorImpl gi : generator.getGeneratorImpls()) {
// if (gi instanceof GeneratorEMAMOpt2CPP) {
// GeneratorEMAMOpt2CPP g = (GeneratorEMAMOpt2CPP) gi;
// g.setPreferedSolver(Solver.Cplex);
// g.setForceUsePreferredSolver(true);
// }
// }
generator.setGenerationTargetPath("./target/generated-sources-cpp/mathopt/cplex/" + fullModelName.substring(fullModelName.lastIndexOf(".") + 1, fullModelName.length()) + "/src/");
return generator.generateFiles(componentInstanceSymbol, symtab);
}
@Test
public void scalarMinimizationCMakeTest() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.optimization.scalarMinimizationTest");
}
@Test
public void scalarMaximizationCMakeTest() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.optimization.scalarMaximizationTest");
}
@Test
public void transportationProblemCMakeTest() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.optimization.transportationProblem");
}
@Test
public void constraintTest() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.optimization.constraintTest");
}
}
\ No newline at end of file
package de.monticore.lang.monticar.generator.mathopt;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.AbstractSymtabTest;
import de.monticore.lang.monticar.generator.cpp.GeneratorCPP;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
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;
/**
* Test class for GeneratorEMAMOpt2CMake
* @author Christoph Richter
*/
public class GeneratorEMAMOpt2CMakeTest extends AbstractSymtabTest {
protected static List<File> doGenerateModel(String fullModelName) throws IOException {
TaggingResolver symtab = createSymTabAndTaggingResolver("src/test/resources/mathopt");
EMAComponentInstanceSymbol componentInstanceSymbol = symtab.<EMAComponentInstanceSymbol>resolve(fullModelName, EMAComponentInstanceSymbol.KIND).orElse(null);
assertNotNull(componentInstanceSymbol);
GeneratorCPP generator = new GeneratorCPP();
generator.setGenerationTargetPath("./target/generated-sources-cpp/mathopt/cmake/" + fullModelName.substring(fullModelName.lastIndexOf(".") + 1, fullModelName.length()) );
//TODO adding solver for opt! and uncomment test
// for (GeneratorImpl g : generator.getGeneratorImpls()) {
// GeneratorEMAMOpt2CPP gen = (GeneratorEMAMOpt2CPP) g;
// gen.setGenerateCMake(true);
// gen.setGenerateTests(true);
// gen.setCheckModelDir(true);
// gen.setModelsDirPath(Paths.get("src/test/resources"));
// }
generator.useArmadilloBackend();
generator.setGenerateCMake(true);
generator.setGenerateTests(true);
generator.setCheckModelDir(true);
generator.setModelsDirPath(Paths.get("src/test/resources/mathopt"));
return generator.generateFiles(componentInstanceSymbol, symtab);
}
@Test
public void scalarMinimizationCMakeTest() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.optimization.scalarMinimizationTest");
}
@Test
public void scalarMaximizationCMakeTest() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.optimization.scalarMaximizationTest");
}
@Test
public void hs71TestCMakeTest() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.optimization.hS71");
}
@Test
public void transportationProblemCMakeTest() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.optimization.transportationProblem");
}
@Test
public void boundedConditionsCMakeTest() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.optimization.boundedConditionsTest");
}
@Test
public void forLoopConditionsCMakeTest() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.optimization.forLoopConditionsTest");
}
@Test
public void existingOptimizationVariableCMakeTest() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.optimization.existingOptimizationVariableTest");
}
@Test
public void matrixSumMinimization1Test() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.optimization.matrixSumMinimizationTest1");
}
@Test
public void matrixSumMinimization2Test() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.optimization.matrixSumMinimizationTest2");
}
@Test
public void constMatrixSumMinimizationTest() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.optimization.constMatrixSumMinimizationTest");
}
@Test
public void colRowMinTest() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.optimization.colRowMinTest");
}
@Test
public void scalarMultMinTest() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.optimization.scalarMultMinTest");
}
@Test
public void matrixTransposeMinimizationTest() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.optimization.matrixTransposeMinimizationTest");
}
@Test
public void constraintTest() throws IOException {
List<File> files = doGenerateModel("de.rwth.monticar.optimization.constraintTest");
}
}
\ No newline at end of file
package de.monticore.lang.monticar.generator.mathopt;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.AbstractSymtabTest;
import de.monticore.lang.monticar.generator.cpp.GeneratorCPP;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.List;
import static org.junit.Assert.assertNotNull;
/**
* Some unit test for generating code for a optimization problem.
*
* @author Christoph Richter
*/
public class GeneratorEMAMOpt2CPPTest extends AbstractSymtabTest {
/**
* helper method to generate optimization models in CPP code
*/
protected static List<File> doGenerateOptimizationModel(String modelName) throws IOException {
TaggingResolver symtab = createSymTabAndTaggingResolver("src/test/resources/mathopt");
EMAComponentInstanceSymbol componentSymbol = symtab.<EMAComponentInstanceSymbol>resolve(String.format("de.rwth.monticar.optimization.%s", modelName), EMAComponentInstanceSymbol.KIND).orElse(null);
assertNotNull(componentSymbol);
GeneratorCPP generator = new GeneratorCPP();
generator.setGenerationTargetPath("./target/generated-sources-cpp/mathopt/generator/" + modelName);
List<File> files = generator.generateFiles(symtab, componentSymbol, symtab);
return files;
}
/**
* Simple quadratic problem min x^2-2x+1 s.t. x >= 0
*/
@Test
public void testScalarMinimizationTest() throws IOException {
List<File> files = doGenerateOptimizationModel("scalarMinimizationTest");
// TODO: create reference solution
// String restPath = "testMath/optimizationSolver/";
// testFilesAreEqual(files, restPath);
}
/**
* Simple quadratic problem max x^2-2x+1 s.t. x >= 0
*/
@Test
public void testScalarMaximizationTest() throws IOException {
List<File> files = doGenerateOptimizationModel("scalarMaximizationTest");
// TODO: create reference solution
// String restPath = "testMath/optimizationSolver/";
// testFilesAreEqual(files, restPath);
}
/**
* example problem, number 71 from the Hock-Schittkowsky test suite
* min_{x \in \R^4} x_1 x_4 (x_1 + x_2 + x_3) + x_3
* s.t.
* x_1 x_2 x_3 x_4 \ge 25
* x_1^2 + x_2^2 + x_3^2 + x_4^2 = 40
* 1 \leq x_1, x_2, x_3, x_4 \leq 5
*/
@Test
public void testStandardIpoptOptimizationTest() throws IOException {
List<File> files = doGenerateOptimizationModel("hS71");
// TODO: create reference solution
// String restPath = "testMath/optimizationSolver/";
// testFilesAreEqual(files, restPath);
}
/**
* instance of the transportation problem (linear)
* see https://www.gams.com/products/simple-example/
*/
@Test
public void testLPOptimizationTest() throws IOException {
List<File> files = doGenerateOptimizationModel("transportationProblem");
// TODO: create reference solution
// String restPath = "testMath/optimizationSolver/";
// testFilesAreEqual(files, restPath);
}
/**
* test loops in conditions
*/
@Test
public void testForLoopConditions() throws IOException {
List<File> files = doGenerateOptimizationModel("forLoopConditionsTest");
// TODO: create reference solution
// String restPath = "testMath/optimizationSolver/";
// testFilesAreEqual(files, restPath);
}
/**
* test conditions of form lower bound <= value <= upper bound
*/
@Test
public void testBoundedConditions() throws IOException {
List<File> files = doGenerateOptimizationModel("boundedConditionsTest");
// TODO: create reference solution
// String restPath = "testMath/optimizationSolver/";
// testFilesAreEqual(files, restPath);
}
/**
* test models which use a already declared optimization variable
*/
@Test
public void existingOptimizationVariable() throws IOException {
List<File> files = doGenerateOptimizationModel("existingOptimizationVariableTest");
// TODO: create reference solution
// String restPath = "testMath/optimizationSolver/";
// testFilesAreEqual(files, restPath);
}
@Test
public void matrixSumMinimization1Test() throws IOException {
List<File> files = doGenerateOptimizationModel("matrixSumMinimizationTest1");
}
@Test
public void matrixSumMinimization2Test() throws IOException {
List<File> files = doGenerateOptimizationModel("matrixSumMinimizationTest2");
}
@Test
public void constMatrixSumMinimizationTest() throws IOException {
List<File> files = doGenerateOptimizationModel("constMatrixSumMinimizationTest");
}
@Test
public void colRowMinTest() throws IOException {
List<File> files = doGenerateOptimizationModel("colRowMinTest");
}
@Test
public void scalarMultMinTest() throws IOException {
List<File> files = doGenerateOptimizationModel("scalarMultMinTest");
}
@Test
public void matrixTransposeMinimizationTest() throws IOException {
List<File> files = doGenerateOptimizationModel("matrixTransposeMinimizationTest");
}
}
\ No newline at end of file
package de.monticore.lang.monticar.generator.mathopt;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.AbstractSymtabTest;
import de.monticore.lang.monticar.generator.Generator;
import de.monticore.lang.monticar.generator.cpp.GeneratorCPP;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.List;
import static org.junit.Assert.assertNotNull;
public class TrajectoryControllerTest extends AbstractSymtabTest {
@Test
public void generateTrajectoryControllerMPCBicycle() throws IOException {
TaggingResolver symtab = createSymTabAndTaggingResolver("src/test/resources/mathopt");
EMAComponentInstanceSymbol componentInstanceSymbol = symtab.<EMAComponentInstanceSymbol>resolve("de.rwth.monticar.mpc.trajectoryControllerMPC", EMAComponentInstanceSymbol.KIND).orElse(null);
assertNotNull(componentInstanceSymbol);
GeneratorCPP generator = new GeneratorCPP();
generator.setGenerateAutopilotAdapter(true);
generator.setGenerateServerWrapper(false);
generator.setGenerateCMake(true);
generator.setGenerationTargetPath("./target/generated-sources-cpp/TrajectoryControllerMPC/src/");
//TODO: fix errors
// generator.setPreferedSolver(Solver.Ipopt);
// generator.getSolverOptions().put("String derivative_test", "none");
// generator.getSolverOptions().put("Integer print_level", "3");
// generator.getSolverOptions().put("Numeric tol", "0.01");
// generator.getSolverOptions().put("Integer max_iter", "50");
List<File> files = generator.generateFiles(componentInstanceSymbol, symtab);
}
}
package de.rwth.monticar.carmodel;
component CarModelInstanceTest {
instance KinematicBicycleCarModel<0.1 s, 1 m, 1 m> kinematicBicycleCarModel;
instance MatlabCarModel<0.1 s, 2000 kg, 1.5 m, 1.5 m, 150000, 40000, 0.5> matlabCarModel;
}
package de.rwth.monticar.carmodel;
component KinematicBicycleCarModel<Q dt = 0.1 s, Q l_f = 1 m, Q l_r = 1 m>
{
ports
// current vehicle state
in Q currentXPosition,
in Q currentYPosition,
in Q currentYawAngle,
in Q currentVelocity,
// control input
in Q (-1.5 m/s^2 : 1 m/s^2) acceleration,
in Q (-37° : 37°) steeringAngle,
// output
out Q predictedXPosition,
out Q predictedYPosition,
out Q predictedYawAngle,
out Q predictedVelocity;
implementation Math
{
// calculate state delta
Q beta = atan((l_r/(l_f + l_r) * tan(steeringAngle)));
Q dx = currentVelocity * cos(currentYawAngle + beta) * dt;
Q dy = currentVelocity * sin(currentYawAngle + beta) * dt;
Q dpsi = currentVelocity / l_r * sin(beta) * dt;
Q dv = acceleration * dt;
// assign output
predictedXPosition = currentXPosition + dx;
predictedYPosition = currentYPosition + dy;
predictedYawAngle = currentYawAngle + dpsi;
predictedVelocity = currentVelocity + dv;
}
}
\ No newline at end of file
package de.rwth.monticar.carmodel;
component MatlabCarModel<Q dt = 0.1 s, Q m = 2000 kg, Q a = 1.5 m, Q b = 1.5 m, Q cx = 150000, Q cy = 40000, Q ca = 0.5>
{
ports
// current vehicle state
in Q currentVelocityX,
in Q currentVelocityY,
in Q currentYawRate,
// input
in Q (-37° : 37°) steeringAngle,
in Q^{4} tireSlipRatio, // front left, front right, rear left, rear right
// output
out Q predictedVelocityX,
out Q predictedVelocityY,
out Q predictedYawRate;
implementation Math
{
// calculate state delta
Q dvx = currentVelocityY * currentYawRate + 1/m *(cx* (tireSlipRatio(1) + tireSlipRatio(2)) * cos(steeringAngle)
- 2 * cy * (steeringAngle - (currentVelocityY + a * currentYawRate) / currentVelocityX ) * sin(steeringAngle)
+ cx*(tireSlipRatio(3) + tireSlipRatio(4)) - ca * currentVelocityX * currentVelocityX);
Q dvy = -currentVelocityX * currentYawRate + 1/m * (cx * (tireSlipRatio(1) + tireSlipRatio(2)) * sin(steeringAngle)
+ 2 * cy * (steeringAngle - (currentVelocityY + a* currentYawRate) / currentVelocityX)*cos(steeringAngle)
+ 2 * cy * (b * currentYawRate - currentVelocityY) / currentVelocityX);
Q dYawRate = 1 / ((0.5 * (a + b)) * (0.5 * (a + b)) * m)
* (a * (cx * (tireSlipRatio(1) + tireSlipRatio(2) * sin(steeringAngle)
+ 2 * cy * (steeringAngle - (currentVelocityY + a * currentYawRate) / currentVelocityX) * cos(steeringAngle))))
- (2 * b * cy * (b * currentYawRate - currentVelocityY) / currentVelocityX);
// assign predicted state
predictedVelocityX = currentVelocityX + dvx * dt;
predictedVelocityY = currentVelocityY + dvy * dt;
predictedYawRate = currentYawRate + dYawRate * dt;
}
}
\ No newline at end of file
// acceleration and steering angle to actuators steering, engine, break
// @author Christoph Richter
package de.rwth.monticar.mpc;
component ActuatorController
{
ports
// control outputs
in Q (-3.0 m/s^2 : 2.5 m/s^2) acceleration,
in Q (-0.785 rad : 0.001 rad : 0.785 rad) steering_angle,
// output
out Q (0.0 m/s^2 : 0.001 m/s^2 : 2.5 m/s^2) engine,
out Q (-0.785 rad : 0.001 rad : 0.785 rad) steering,
out Q (0.0 m/s^2 : 0.001 m/s^2 : 3.0 m/s^2) brakes;
implementation Math
{
// steering angle is trivial
steering = steering_angle;
// if acceleration should be positive => engine
// else break