Commit e7b36f1a authored by Jean Meurice's avatar Jean Meurice
Browse files

HardwareEmulator integration

intall folder with ready to run setup.
parent a6a9ecae
Pipeline #111291 failed with stages
@REM
@REM
@REM ******************************************************************************
@REM MontiCAR Modeling Family, www.se-rwth.de
@REM Copyright (c) 2017, Software Engineering Group at RWTH Aachen,
@REM All rights reserved.
@REM
@REM This project is free software; you can redistribute it and/or
@REM modify it under the terms of the GNU Lesser General Public
@REM License as published by the Free Software Foundation; either
@REM version 3.0 of the License, or (at your option) any later version.
@REM This library is distributed in the hope that it will be useful,
@REM but WITHOUT ANY WARRANTY; without even the implied warranty of
@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
@REM Lesser General Public License for more details.
@REM
@REM You should have received a copy of the GNU Lesser General Public
@REM License along with this project. If not, see <http://www.gnu.org/licenses/>.
@REM *******************************************************************************
@REM
@REM Please replace this with the path to the Autopilot(s)
set AUTOPILOT_FOLDER=autopilots
@REM Change the port if you need to
set PORT=10101
\ No newline at end of file
@REM
@REM
@REM ******************************************************************************
@REM MontiCAR Modeling Family, www.se-rwth.de
@REM Copyright (c) 2017, Software Engineering Group at RWTH Aachen,
@REM All rights reserved.
@REM
@REM This project is free software; you can redistribute it and/or
@REM modify it under the terms of the GNU Lesser General Public
@REM License as published by the Free Software Foundation; either
@REM version 3.0 of the License, or (at your option) any later version.
@REM This library is distributed in the hope that it will be useful,
@REM but WITHOUT ANY WARRANTY; without even the implied warranty of
@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
@REM Lesser General Public License for more details.
@REM
@REM You should have received a copy of the GNU Lesser General Public
@REM License along with this project. If not, see <http://www.gnu.org/licenses/>.
@REM *******************************************************************************
@REM
@echo off
call config.bat
echo Starting RMIModelServer on port %PORT% with Autopilot folder: %AUTOPILOT_FOLDER%
java "-Djava.rmi.server.codebase=file:rmi-model-server.jar" "-Djava.rmi.server.hostname=127.0.0.1" -cp rmi-model-server.jar rwth.rmi.model.server.RMIServer %PORT% %AUTOPILOT_FOLDER%
pause
......@@ -54,10 +54,10 @@
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
......@@ -178,6 +178,7 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<workingDirectory>${project.basedir}/install</workingDirectory>
</configuration>
</plugin>
<plugin>
......
@REM
@REM
@REM ******************************************************************************
@REM MontiCAR Modeling Family, www.se-rwth.de
@REM Copyright (c) 2017, Software Engineering Group at RWTH Aachen,
@REM All rights reserved.
@REM
@REM This project is free software; you can redistribute it and/or
@REM modify it under the terms of the GNU Lesser General Public
@REM License as published by the Free Software Foundation; either
@REM version 3.0 of the License, or (at your option) any later version.
@REM This library is distributed in the hope that it will be useful,
@REM but WITHOUT ANY WARRANTY; without even the implied warranty of
@REM MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
@REM Lesser General Public License for more details.
@REM
@REM You should have received a copy of the GNU Lesser General Public
@REM License along with this project. If not, see <http://www.gnu.org/licenses/>.
@REM *******************************************************************************
@REM
pushd ..
call mvn clean install -s "settings.xml"
cd target
ren "rmi-model-server-1.0.1-SNAPSHOT-jar-with-dependencies.jar" "rmi-model-server.jar"
copy "rmi-model-server.jar" "..\install"
popd
\ No newline at end of file
......@@ -21,6 +21,7 @@
package rwth.rmi.model.server;
import org.I0Itec.zkclient.ZkClient;
import simulator.integration.HardwareEmulatorInterface;
import java.io.File;
import java.io.IOException;
......@@ -41,7 +42,7 @@ public class RMIServer {
public static void main(String[] args) throws UnknownHostException {
if (args.length < 2){
System.out.println("Please assign a port that the RMI server need to bind, also the path to AutopilotAdapter.dll");
System.out.println("Please assign a port that the RMI server need to bind, also the path to the autopilot(s)");
return;
}
......@@ -61,8 +62,8 @@ public class RMIServer {
if (zoo_servers == null){
zoo_servers = "localhost:2181";
}
ZkClient zk = new ZkClient(zoo_servers, 1000, 5000);
ModelManager manager = new ModelManager(args[1]);
//ZkClient zk = new ZkClient(zoo_servers, 1000, 5000);
HardwareEmulatorInterface manager = new HardwareEmulatorInterface(args[1]);
String host = InetAddress.getLocalHost().getHostName();
int port = Integer.valueOf(args[0]);
......@@ -73,18 +74,18 @@ public class RMIServer {
//bind the ModelManager to a stub, representing the remote object
registry.bind(MODEL_MANAGER, UnicastRemoteObject.exportObject(manager, port));
register(zk, host, port);
//register(zk, host, port);
System.out.println("RMIManager listening");
} catch (RemoteException | AlreadyBoundException e) {
e.printStackTrace();
}
Runtime.getRuntime().addShutdownHook(new Thread(){
/*Runtime.getRuntime().addShutdownHook(new Thread(){
@Override
public void run(){
unregister(zk, host, port);
}
});
});*/
}
public static boolean isPortAvailable(String portString) {
......
......@@ -28,11 +28,17 @@ import java.io.Serializable;
import java.util.HashMap;
public interface RMIManager extends Remote {
public Integer registerModel(String modelClass) throws RemoteException, AlreadyBoundException;
public HashMap<String, Serializable> executeModel(Integer modelId, HashMap<String, Serializable> inputs) throws RemoteException;
public int alloc_autopilot(String config) throws RemoteException;
public void free_autopilot(int id) throws RemoteException;
public void removeModel(Integer modelId) throws RemoteException;
public void update_bus(int id, HashMap<String, Serializable> inputs) throws RemoteException;
public void start_tick(long time_delta) throws RemoteException;
public void end_tick() throws RemoteException;
public HashMap<String, Serializable> get_outputs(int id) throws RemoteException;
public String querry(String msg) throws RemoteException;
public String querry_autopilot(int id, String msg) throws RemoteException;
}
/**
*
* ******************************************************************************
* MontiCAR Modeling Family, www.se-rwth.de
* Copyright (c) 2017, Software Engineering Group at RWTH Aachen,
* All rights reserved.
*
* This project is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this project. If not, see <http://www.gnu.org/licenses/>.
* *******************************************************************************
*/
package rwth.rmi.model.server.interfaces;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.io.Serializable;
public interface VehicleModel extends Remote {
public HashMap<String, Serializable> execute(HashMap<String, Serializable> inputs) throws RemoteException;
}
\ No newline at end of file
/**
*
* ******************************************************************************
* MontiCAR Modeling Family, www.se-rwth.de
* Copyright (c) 2017, Software Engineering Group at RWTH Aachen,
* All rights reserved.
*
* This project is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this project. If not, see <http://www.gnu.org/licenses/>.
* *******************************************************************************
*/
package simulator.integration;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.io.Serializable;
import rwth.rmi.model.server.interfaces.VehicleModel;
/**
* JNI binding to a CPP class generated for the native model.
*/
public class AutopilotAdapter implements VehicleModel {
public AutopilotAdapter(String libraryPath) {
super();
// Load AutopilotAdapter.dll from libraryPath
System.load(libraryPath);
initialize();
}
private boolean isInitialized = false;
public void execute() {
initialize();
exec();
}
public void initialize() {
if (!isInitialized) {
init();
isInitialized = true;
}
}
public native void set_timeIncrement(double timeIncrement);
public native void set_currentVelocity(double currentVelocity);
public native void set_x(double currentGpsLat);
public native void set_y(double currentGpsLon);
public native void set_compass(double compass);
public native void set_currentEngine(double currentEngine);
public native void set_currentSteering(double currentSteering);
public native void set_currentBrakes(double currentBrakes);
public native void set_trajectory_length(int length);
public native void set_trajectory_x(double[] x);
public native void set_trajectory_y(double[] y);
public native double get_engine();
public native double get_steering();
public native double get_brakes();
private native void exec();
private native void init();
@Override
/**
* Implementation of RMI interface of VehicleModel.
*
* @param inputs - a map denoting the methods to be executed and their params as a single object
* @return a map containing the outputs of the model
*/
public HashMap<String, Serializable> execute(HashMap<String, Serializable> inputs) throws RemoteException {
//set inputs
for(String key : inputs.keySet()) {
if(key.contentEquals("timeIncrement")) {
set_timeIncrement((double) inputs.get(key));
}else if(key.contentEquals("currentVelocity")) {
set_currentVelocity((double)inputs.get(key));
}else if(key.contentEquals("x")) {
set_x((double)inputs.get(key));
}else if(key.contentEquals("y")) {
set_y((double)inputs.get(key));
}else if(key.contentEquals("compass")) {
set_compass((double)inputs.get(key));
}else if(key.contentEquals("currentEngine")) {
set_currentEngine((double)inputs.get(key));
}else if(key.contentEquals("currentSteering")) {
set_currentSteering((double)inputs.get(key));
}else if(key.contentEquals("currentBrakes")) {
set_currentBrakes((double)inputs.get(key));
}else if(key.contentEquals("trajectory_length")) {
set_trajectory_length((int)inputs.get(key));
}else if(key.contentEquals("trajectory_x")) {
set_trajectory_x((double[])inputs.get(key));
}else if(key.contentEquals("trajectory_y")) {
set_trajectory_y((double[])inputs.get(key));
}
}
//execute model
execute();
//fill in outputs
HashMap<String, Serializable> outputs = new HashMap<String, Serializable>();
outputs.put("engine", get_engine());
outputs.put("steering", get_steering());
outputs.put("brakes", get_brakes());
return outputs;
}
}
......@@ -18,77 +18,71 @@
* License along with this project. If not, see <http://www.gnu.org/licenses/>.
* *******************************************************************************
*/
package rwth.rmi.model.server;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;
package simulator.integration;
import rwth.rmi.model.server.interfaces.RMIManager;
import rwth.rmi.model.server.interfaces.VehicleModel;
import simulator.integration.AutopilotAdapter;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.io.Serializable;
public class ModelManager implements RMIManager {
public class HardwareEmulatorInterface implements RMIManager {
public HardwareEmulatorInterface(String libraryPath) {
super();
String emu = System.getProperty("user.dir") + "/HardwareEmulator";
String OS = System.getProperty("os.name").toLowerCase();
if (OS.contains("win")){
System.load(emu+".dll");
} else if (OS.contains("nix")|| OS.contains("nux")|| OS.contains("aix")){
System.load(emu+".so");
} else {
System.out.println("Could not deduce Operating System for loading the HardwareEmulator.");
}
try {// Load AutopilotAdapter.dll from libraryPath
File b = new File(libraryPath);
String absolute = b.getCanonicalPath();
init("autopilots_folder=" + absolute);
} catch (IOException e) {
e.printStackTrace();
System.out.println("Could not initiate the Hardware Emulator");
init("");
}
private int lastModelId = 0;
private Map<Integer, VehicleModel> models;
}
//Served models
private VehicleModel[] supportedModels;
private native boolean init(String config);
@Override
public native int alloc_autopilot(String config);
@Override
public native void free_autopilot(int id);
@Override
public void update_bus(int id, HashMap<String, Serializable> inputs){
for (HashMap.Entry<String, Serializable> entry : inputs.entrySet()){
add_one_input(id, entry.getKey(), entry.getValue());
}
}
public ModelManager(String libraryPath) {
super();
this.models = new HashMap<Integer, VehicleModel>();
this.supportedModels = new VehicleModel[] {
new AutopilotAdapter(libraryPath)
};
}
@Override
/**
* Adds a VehicleModel to list of served models and returns the modelId, with which this model is accessible.
*
* @param model - the class name of the model, requested to be registered
* @return the model Id or -1 if incorrect model has been requested
* @throws RemoteException
* @throws AlreadyBoundException
*/
public Integer registerModel(String modelClass) throws RemoteException, AlreadyBoundException {
VehicleModel model = getCorrespondingModel(modelClass);
if(model == null) return -1;
this.models.put(++lastModelId, model);
System.out.println("Model [" + model.getClass().getName() + "] created with ID: " + this.lastModelId);
return this.lastModelId;
}
@Override
public native void start_tick(long time_delta);
@Override
public native void end_tick();
private VehicleModel getCorrespondingModel(String modelClass) {
for(VehicleModel model : this.supportedModels) {
if(model.getClass().getSimpleName().contentEquals(modelClass)) {
return model;
}
}
return null;
}
@Override
public HashMap<String, Serializable> get_outputs(int id) {
HashMap<String, Serializable> outputs = new HashMap<String, Serializable>();
querry_outputs(id, outputs);
return outputs;
}
@Override
public HashMap<String, Serializable> executeModel(Integer modelId, HashMap<String, Serializable> inputs) throws RemoteException {
VehicleModel model = this.models.get(modelId);
if(model == null) {
return new HashMap<String, Serializable>(); //fallback to empty map
}
return model.execute(inputs);
}
@Override
public void removeModel(Integer modelId) throws RemoteException {
System.out.println("Removed model: " + this.models.get(modelId).getClass().getName());
this.models.remove(modelId);
}
@Override
public native String querry(String msg);
@Override
public native String querry_autopilot(int id, String msg);
private native void add_one_input(int id, String key, Serializable value);
private native void querry_outputs(int id, HashMap<String, Serializable> opaque_hashmap);
private void add_one_output(HashMap<String, Serializable> opaque_hashmap, String key, Serializable value) {
opaque_hashmap.put(key, value);
}
}
/**
*
* ******************************************************************************
* MontiCAR Modeling Family, www.se-rwth.de
* Copyright (c) 2017, Software Engineering Group at RWTH Aachen,
* All rights reserved.
*
* This project is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this project. If not, see <http://www.gnu.org/licenses/>.
* *******************************************************************************
*/
package simulator.integration;
import org.junit.Test;
import org.junit.Assert;
import java.io.Serializable;
import java.util.HashMap;
public class HardwareEmulatorTest {
@Test
public void basic_test(){
System.out.println("Current test directory: " + System.getProperty("user.dir"));
HardwareEmulatorInterface manager = new HardwareEmulatorInterface("autopilots");
String querry = "get_available_autopilots\nget_available_threads";
String res = manager.querry(querry);
System.out.println("EmulatorManager querry response: " + res);
String lines[] = res.split("\n");
Assert.assertEquals("Querry result line count", 2, lines.length);
String line1[] = lines[0].split("=");
Assert.assertEquals("available_autopilots two values (=)", 2, line1.length);
Assert.assertEquals("available_autopilots command", new String("available_autopilots"), line1[0]);
String line2[] = lines[1].split("=");
Assert.assertEquals("available_threads two values (=)", 2, line2.length);
Assert.assertEquals("available_threads command", new String("available_threads"), line2[0]);
String config = "autopilot=AutopilotAdapter";
config += "\nos=windows";
int id = manager.alloc_autopilot(config);
if (id < 0){
String q = manager.querry( "get_error_msg" );
Assert.assertTrue("Could not allocate Emulator: " + q, id >= 0);
}
HashMap<String, Serializable> inputs = new HashMap<String, Serializable>();
inputs.put("timeIncrement", 1.0);
inputs.put("currentVelocity", 0.0);
inputs.put("x", 0.01);
inputs.put("y", 0.01);
inputs.put("compass", 0.0);
inputs.put("currentEngine", 0.0);
inputs.put("currentSteering", 0.0);
inputs.put("currentBrakes", 0.0);
inputs.put("trajectory_length", 5);
inputs.put("trajectory_x", new double[]{0.01, 0.02, 0.03, 0.04, 0.05, 0.06});
inputs.put("trajectory_y", new double[]{0.01, 0.01, 0.02, 0.02, 0.01, 0.01});
manager.update_bus(id, inputs);
manager.start_tick(1000000);
manager.end_tick();
String emu_querry = manager.querry_autopilot(id, "get_avg_runtime");
System.out.println("Emu querry: " + emu_querry);
HashMap<String, Serializable> outputs = manager.get_outputs(id);
Assert.assertEquals("output count", outputs.size(), 3);
for (HashMap.Entry<String, Serializable> entry : outputs.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
manager.free_autopilot(id);
}
}
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