Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
monticore
EmbeddedMontiArc
generators
EMAM2Cpp
Commits
4b0c5dd7
Commit
4b0c5dd7
authored
Mar 25, 2018
by
Alexander Ryndin
Browse files
issue-47: impl. server wrapper
parent
74a423b2
Changes
8
Hide whitespace changes
Inline
Side-by-side
pom.xml
View file @
4b0c5dd7
...
...
@@ -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>
...
...
src/main/java/de/monticore/lang/monticar/generator/cpp/GeneratorCPP.java
View file @
4b0c5dd7
...
...
@@ -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"
);
}
}
src/main/java/de/monticore/lang/monticar/generator/cpp/GeneratorCppCli.java
View file @
4b0c5dd7
...
...
@@ -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
)
{
...
...
src/main/java/de/monticore/lang/monticar/generator/cpp/template/AllTemplates.java
View file @
4b0c5dd7
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
));
}
...
...
src/main/java/de/monticore/lang/monticar/generator/cpp/viewmodel/ServerWrapperViewModel.java
0 → 100644
View file @
4b0c5dd7
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
;
}
}
src/main/resources/template/serverwrapper/Makefile
0 → 100644
View file @
4b0c5dd7
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
src/main/resources/template/serverwrapper/ServerWrapper.ftl
0 → 100644
View file @
4b0c5dd7
<#
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
()->
C
opyFrom
(
make_actuation
(
engine
,
steering_angle
,
brakes
))
;
return
S
tatus
::
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;
}
src/main/resources/template/serverwrapper/model.proto
0 → 100644
View file @
4b0c5dd7
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
;
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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