Commit 4b0c5dd7 authored by Alexander Ryndin's avatar Alexander Ryndin

issue-47: impl. server wrapper

parent 74a423b2
......@@ -8,7 +8,7 @@
<groupId>de.monticore.lang.monticar</groupId>
<artifactId>embedded-montiarc-math-generator</artifactId>
<version>0.0.8-SNAPSHOT</version>
<version>0.0.9-SNAPSHOT</version>
<!-- == PROJECT DEPENDENCIES ============================================= -->
......@@ -300,35 +300,29 @@
</configuration>
</plugin>
<!--plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>${assembly.plugin}</version>
<dependencies>
<dependency>
<groupId>de.monticore</groupId>
<artifactId>mc-assemblies</artifactId>
<version>${mc.grammars.assembly.version}</version>
</dependency>
</dependencies>
<version>3.1.0</version>
<executions>
<execution>
<id>grammars</id>
<configuration>
<finalName>${project.artifactId}-${project.version}</finalName>
<descriptorRefs>
<descriptorRef>grammars-assembly</descriptorRef>
</descriptorRefs>
<formats>
<format>jar</format>
</formats>
</configuration>
<id>jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>de.monticore.lang.monticar.generator.cpp.GeneratorCppCli</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin -->
</plugin>
<!-- Source Jar Configuration -->
<plugin>
......
......@@ -11,6 +11,7 @@ import de.monticore.lang.monticar.generator.cpp.converter.MathConverter;
import de.monticore.lang.monticar.generator.cpp.converter.TypeConverter;
import de.monticore.lang.monticar.generator.cpp.template.AllTemplates;
import de.monticore.lang.monticar.generator.cpp.viewmodel.AutopilotAdapterViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.ServerWrapperViewModel;
import de.monticore.lang.monticar.ts.MCTypeSymbol;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import de.monticore.symboltable.Scope;
......@@ -34,6 +35,7 @@ public class GeneratorCPP implements Generator {
private Path modelsDirPath;
private boolean isGenerateTests = false;
private boolean isGenerateAutopilotAdapter = false;
private boolean isGenerateServerWrapper = false;
private final List<BluePrintCPP> bluePrints = new ArrayList<>();
protected String generationTargetPath = "./target/generated-sources-cpp/";
......@@ -154,6 +156,9 @@ public class GeneratorCPP implements Generator {
if (isGenerateAutopilotAdapter()) {
fileContents.addAll(getAutopilotAdapterFiles(componentSymbol));
}
if (isGenerateServerWrapper()) {
fileContents.addAll(getServerWrapperFiles(componentSymbol));
}
//System.out.println(fileContents);
if (getGenerationTargetPath().charAt(getGenerationTargetPath().length() - 1) != '/') {
setGenerationTargetPath(getGenerationTargetPath() + "/");
......@@ -307,6 +312,14 @@ public class GeneratorCPP implements Generator {
isGenerateAutopilotAdapter = generateAutopilotAdapter;
}
public boolean isGenerateServerWrapper() {
return isGenerateServerWrapper;
}
public void setGenerateServerWrapper(boolean generateServerWrapper) {
isGenerateServerWrapper = generateServerWrapper;
}
public boolean isCheckModelDir() {
return checkModelDir;
}
......@@ -337,4 +350,25 @@ public class GeneratorCPP implements Generator {
String fileContents = AllTemplates.generateAutopilotAdapter(vm);
return new FileContent(fileContents, "AutopilotAdapter.cpp");
}
private static List<FileContent> getServerWrapperFiles(ExpandedComponentInstanceSymbol componentSymbol) {
List<FileContent> result = new ArrayList<>();
String[] filesToCopy = new String[]{
"Makefile",
"model.proto"
};
for (String file : filesToCopy) {
String resourcePath = String.format("/template/serverwrapper/%s", file);
result.add(FileUtil.getResourceAsFile(resourcePath, file));
}
result.add(generateServerWrapper(componentSymbol));
return result;
}
private static FileContent generateServerWrapper(ExpandedComponentInstanceSymbol componentSymbol) {
ServerWrapperViewModel vm = new ServerWrapperViewModel();
vm.setMainModelName(GeneralHelperMethods.getTargetLanguageComponentName(componentSymbol.getFullName()));
String fileContents = AllTemplates.generateServerWrapper(vm);
return new FileContent(fileContents, "server.cc");
}
}
......@@ -70,6 +70,7 @@ public final class GeneratorCppCli {
.hasArg(false)
.required(false)
.build();
public static final Option OPTION_FLAG_CHECK_MODEL_DIR = Option.builder()
.longOpt("check-model-dir")
.desc("optional flag indicating if model dir should be checked for creation of component and stream list")
......@@ -77,6 +78,13 @@ public final class GeneratorCppCli {
.required(false)
.build();
public static final Option OPTION_FLAG_SERVER_WRAPPER = Option.builder()
.longOpt("flag-generate-server-wrapper")
.desc("optional flag indicating if model should be wrapped into a server")
.hasArg(false)
.required(false)
.build();
private GeneratorCppCli() {
}
......@@ -98,6 +106,7 @@ public final class GeneratorCppCli {
options.addOption(OPTION_FLAG_ARMADILLO);
options.addOption(OPTION_FLAG_AUTOPILOT_ADAPTER);
options.addOption(OPTION_FLAG_CHECK_MODEL_DIR);
options.addOption(OPTION_FLAG_SERVER_WRAPPER);
return options;
}
......@@ -129,6 +138,7 @@ public final class GeneratorCppCli {
g.useArmadilloBackend();
}
g.setCheckModelDir(cliArgs.hasOption(OPTION_FLAG_CHECK_MODEL_DIR.getLongOpt()));
g.setGenerateServerWrapper(cliArgs.hasOption(OPTION_FLAG_SERVER_WRAPPER.getLongOpt()));
g.setGenerateAutopilotAdapter(cliArgs.hasOption(OPTION_FLAG_AUTOPILOT_ADAPTER.getLongOpt()));
try {
if (componentSymbol != null) {
......
package de.monticore.lang.monticar.generator.cpp.template;
import de.monticore.lang.monticar.generator.cpp.GeneratorCPP;
import de.monticore.lang.monticar.generator.cpp.viewmodel.AutopilotAdapterViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.ComponentStreamTestViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.EnumViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.ServerWrapperViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.StructViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.TestsMainEntryViewModel;
import de.monticore.lang.monticar.generator.cpp.viewmodel.ViewModelBase;
......@@ -24,6 +24,7 @@ public final class AllTemplates {
private static final Template STRUCT;
private static final Template ENUM;
private static final Template AUTOPILOT_ADAPTER;
private static final Template SERVER_WRAPPER;
static {
Configuration conf = new Configuration(Configuration.VERSION_2_3_23);
......@@ -38,6 +39,7 @@ public final class AllTemplates {
STRUCT = conf.getTemplate("/type/Struct.ftl");
ENUM = conf.getTemplate("/type/Enum.ftl");
AUTOPILOT_ADAPTER = conf.getTemplate("/autopilotadapter/AutopilotAdapter.ftl");
SERVER_WRAPPER = conf.getTemplate("/serverwrapper/ServerWrapper.ftl");
} catch (IOException e) {
String msg = "could not load templates";
Log.error(msg, e);
......@@ -71,6 +73,10 @@ public final class AllTemplates {
return generate(AUTOPILOT_ADAPTER, viewModel);
}
public static String generateServerWrapper(ServerWrapperViewModel viewModel) {
return generate(SERVER_WRAPPER, viewModel);
}
private static String generate(Template template, ViewModelBase viewModelBase) {
return generate(template, TemplateHelper.getDataForTemplate(viewModelBase));
}
......
package de.monticore.lang.monticar.generator.cpp.viewmodel;
public final class ServerWrapperViewModel extends ViewModelBase {
private String mainModelName;
public String getMainModelName() {
return mainModelName;
}
public void setMainModelName(String mainModelName) {
this.mainModelName = mainModelName;
}
}
CXX = g++
CPPFLAGS += `pkg-config --cflags protobuf grpc`
CXXFLAGS += -std=c++11
LDFLAGS += -L/usr/local/lib `pkg-config --libs protobuf grpc++`\
-Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed\
-ldl
PROTOC = protoc
GRPC_CPP_PLUGIN = grpc_cpp_plugin
GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)`
all: server
server: model.pb.o model.grpc.pb.o server.o
$(CXX) $^ $(LDFLAGS) -o $@
.PRECIOUS: %.grpc.pb.cc
%.grpc.pb.cc: %.proto
$(PROTOC) -I . --grpc_out=. --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN_PATH) $<
.PRECIOUS: %.pb.cc
%.pb.cc: %.proto
$(PROTOC) -I . --cpp_out=. $<
clean:
rm -f *.o *.pb.cc *.pb.h server
<#include "/Common.ftl">
#include <chrono>
#include <iostream>
#include <memory>
#include <string>
#include "spdlog/spdlog.h"
#include <armadillo>
#include <grpcpp/grpcpp.h>
#include "model.grpc.pb.h"
#include "${viewModel.mainModelName}.h"
using arma::mat;
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using model::Actuation;
using model::Model;
using model::ModelInputs;
using model::ModelOutputs;
using model::SensorData;
using model::Trajectory;
using std::chrono::duration_cast;
using std::chrono::high_resolution_clock;
using std::chrono::milliseconds;
using std::chrono::time_point;
Actuation make_actuation(double engine, double steering_angle, double brakes)
{
Actuation p;
p.set_engine(engine);
p.set_steering_angle(steering_angle);
p.set_brakes(brakes);
return p;
}
class ServiceImplementation final : public Model::Service
{
private:
time_point<high_resolution_clock> start_time_;
int number_of_calls_;
const int calls_stats_frequency_;
std::shared_ptr<spdlog::logger> logger_;
${viewModel.mainModelName} model_;
void pass_inputs_to_model_(const ModelInputs *request)
{
model_.timeIncrement = request->time_increment();
if (request->has_sensor_data())
{
pass_sensor_data_(request->sensor_data());
}
else
{
logger_->warn("no sensor data is provided");
}
if (request->has_actuation())
{
pass_actuation_(request->actuation());
}
else
{
logger_->warn("no actuation is provided");
}
if (request->has_trajectory())
{
pass_trajectory_(request->trajectory());
}
else
{
logger_->warn("no trajectory is provided");
}
}
void pass_sensor_data_(const SensorData &sensor_data)
{
model_.currentVelocity = sensor_data.velocity();
if (sensor_data.has_position())
{
auto p = sensor_data.position();
model_.x = p.x();
model_.y = p.y();
}
else
{
logger_->warn("no position is provided");
}
model_.compass = sensor_data.compass();
}
void pass_actuation_(const Actuation &actuation)
{
model_.currentEngine = actuation.engine();
model_.currentSteering = actuation.steering_angle();
model_.currentBrakes = actuation.brakes();
}
void pass_trajectory_(const Trajectory &trajectory)
{
auto len = trajectory.points_size();
model_.trajectory_length = len;
if (len > 0)
{
mat &xs = model_.trajectory_x;
mat &ys = model_.trajectory_y;
for (auto i = 0; i < len; i++)
{
auto p = trajectory.points(i);
xs(0, i) = p.x();
ys(0, i) = p.y();
}
}
else
{
logger_->warn("trajectory is empty");
}
}
void log_call_()
{
number_of_calls_++;
if (number_of_calls_ % calls_stats_frequency_ == 0)
{
auto duration = duration_cast<milliseconds>(high_resolution_clock::now() - start_time_);
logger_->info("average response time = {} milliseconds", duration.count());
number_of_calls_ = 0;
start_time_ = high_resolution_clock::now();
}
}
public:
ServiceImplementation() : calls_stats_frequency_(10000), start_time_(high_resolution_clock::now())
{
number_of_calls_ = 0;
logger_ = spdlog::basic_logger_mt("ServiceImplementation", "/var/www/html/ServiceImplementation.log");
model_.init();
}
Status Execute(ServerContext *context, const ModelInputs *request, ModelOutputs *response) override
{
log_call_();
pass_inputs_to_model_(request);
model_.execute();
auto engine = model_.engine;
auto steering_angle = model_.steering;
auto brakes = model_.brakes;
response->mutable_actuation()->CopyFrom(make_actuation(engine, steering_angle, brakes));
return Status::OK;
}
};
void run_server()
{
std::cout << "initializing..." << std::endl
<< std::flush;
ServerBuilder builder;
std::string server_address("0.0.0.0:10247");
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
ServiceImplementation service;
builder.RegisterService(&service);
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "server is listening on " << server_address << std::endl
<< std::flush;
server->Wait();
}
int main(int argc, char **argv)
{
run_server();
return 0;
}
syntax = "proto3";
option java_multiple_files = true;
option java_package = "de.rwth.modelling";
option java_outer_classname = "ModelProtos";
package model;
service Model {
rpc Execute (ModelInputs) returns (ModelOutputs) {}
}
message ModelInputs {
double time_increment = 1;
Actuation actuation = 2;
SensorData sensor_data = 3;
Trajectory trajectory = 4;
}
message ModelOutputs {
Actuation actuation = 1;
}
message Actuation {
double engine = 1;
double steering_angle = 2;
double brakes = 3;
}
message SensorData {
double velocity = 1;
Point position = 2;
double compass = 3;
}
message Trajectory {
repeated Point points = 1;
}
message Point {
double x = 1;
double y = 2;
}
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