Commit 00e946ee authored by Jean Meurice's avatar Jean Meurice
Browse files

Merge branch 'simple_network' into 'master'

Simple network + EESystem simplification

See merge request !37
parents 71822ab1 6c2ed3d1
Pipeline #381088 passed with stage
in 1 minute and 9 seconds
......@@ -6,17 +6,17 @@ import java.time.Instant;
import java.util.*;
import de.rwth.montisim.commons.dynamicinterface.BasicType;
import de.rwth.montisim.commons.dynamicinterface.PortInformation;
import de.rwth.montisim.commons.simulation.Inspectable;
import de.rwth.montisim.commons.utils.Geometry;
import de.rwth.montisim.commons.utils.IPM;
import de.rwth.montisim.commons.utils.Time;
import de.rwth.montisim.commons.utils.Vec2;
import de.rwth.montisim.simulation.eesimulator.actuator.Actuator;
import de.rwth.montisim.simulation.eesimulator.components.EEComponent;
import de.rwth.montisim.simulation.eesimulator.EEComponent;
import de.rwth.montisim.simulation.eesimulator.EESystem;
import de.rwth.montisim.simulation.eesimulator.events.MessageReceiveEvent;
import de.rwth.montisim.simulation.eesimulator.exceptions.EEMessageTypeException;
import de.rwth.montisim.simulation.eesimulator.message.Message;
import de.rwth.montisim.simulation.eesimulator.message.MessageInformation;
import de.rwth.montisim.simulation.vehicle.navigation.Navigation;
import de.rwth.montisim.simulation.vehicle.physicalvalues.TrueCompass;
import de.rwth.montisim.simulation.vehicle.physicalvalues.TruePosition;
......@@ -30,17 +30,17 @@ public class JavaAutopilot extends EEComponent implements Inspectable {
public static final double ORTHO_DIST = MAX_DEVIATION / (Math.sqrt(2) - 1); // max allowed deviation from the
// trajectory "corners" (in meters)
transient MessageInformation velocityMsg;
transient MessageInformation positionMsg;
transient MessageInformation compassMsg;
transient int velocityMsg;
transient int positionMsg;
transient int compassMsg;
transient MessageInformation trajLengthMsg;
transient MessageInformation trajXMsg;
transient MessageInformation trajYMsg;
transient int trajLengthMsg;
transient int trajXMsg;
transient int trajYMsg;
transient MessageInformation steeringMsg;
transient MessageInformation accelMsg;
transient MessageInformation brakeMsg;
transient int steeringMsg;
transient int accelMsg;
transient int brakeMsg;
public double currentVelocity = 0;
public Vec2 currentPosition = null;
......@@ -60,27 +60,24 @@ public class JavaAutopilot extends EEComponent implements Inspectable {
transient final PID speedPid;
transient final PID turnPid;
public JavaAutopilot(JavaAutopilotProperties properties) {
super(properties);
public JavaAutopilot(JavaAutopilotProperties properties, EESystem eeSystem) {
super(properties, eeSystem);
this.properties = properties;
this.speedPid = new PID(1, 0, 0.2);
this.turnPid = new PID(1, 0, 0.2);
}
@Override
protected void init() throws EEMessageTypeException {
this.velocityMsg = addInput(TrueVelocity.VALUE_NAME, TrueVelocity.TYPE);
this.positionMsg = addInput(TruePosition.VALUE_NAME, TruePosition.TYPE);
this.compassMsg = addInput(TrueCompass.VALUE_NAME, TrueCompass.TYPE);
this.trajLengthMsg = addInput(Navigation.TRAJECTORY_LENGTH_MSG, BasicType.N);
this.trajXMsg = addInput(Navigation.TRAJECTORY_X_MSG, Navigation.TRAJECTORY_X_TYPE);
this.trajYMsg = addInput(Navigation.TRAJECTORY_Y_MSG, Navigation.TRAJECTORY_Y_TYPE);
this.steeringMsg = addOutput(Actuator.SETTER_PREFIX + PowerTrainProperties.STEERING_VALUE_NAME,
BasicType.DOUBLE);
this.accelMsg = addOutput(Actuator.SETTER_PREFIX + PowerTrainProperties.GAS_VALUE_NAME, BasicType.DOUBLE);
this.brakeMsg = addOutput(Actuator.SETTER_PREFIX + PowerTrainProperties.BRAKING_VALUE_NAME, BasicType.DOUBLE);
this.velocityMsg = addPort(PortInformation.newRequiredInputDataPort(TrueVelocity.VALUE_NAME, TrueVelocity.TYPE, false));
this.positionMsg = addPort(PortInformation.newRequiredInputDataPort(TruePosition.VALUE_NAME, TruePosition.TYPE, false));
this.compassMsg = addPort(PortInformation.newRequiredInputDataPort(TrueCompass.VALUE_NAME, TrueCompass.TYPE, false));
this.trajLengthMsg = addPort(PortInformation.newRequiredInputDataPort(Navigation.TRAJECTORY_LENGTH_MSG, BasicType.N, false));
this.trajXMsg = addPort(PortInformation.newRequiredInputDataPort(Navigation.TRAJECTORY_X_MSG, Navigation.TRAJECTORY_X_TYPE, false));
this.trajYMsg = addPort(PortInformation.newRequiredInputDataPort(Navigation.TRAJECTORY_Y_MSG, Navigation.TRAJECTORY_Y_TYPE, false));
this.steeringMsg = addPort(PortInformation.newRequiredOutputDataPort(Actuator.SETTER_PREFIX + PowerTrainProperties.STEERING_VALUE_NAME,
BasicType.DOUBLE));
this.accelMsg = addPort(PortInformation.newRequiredOutputDataPort(Actuator.SETTER_PREFIX + PowerTrainProperties.GAS_VALUE_NAME, BasicType.DOUBLE));
this.brakeMsg = addPort(PortInformation.newRequiredOutputDataPort(Actuator.SETTER_PREFIX + PowerTrainProperties.BRAKING_VALUE_NAME, BasicType.DOUBLE));
}
@Override
......@@ -370,12 +367,12 @@ public class JavaAutopilot extends EEComponent implements Inspectable {
return "autopilot";
}
void addEntry(List<String> entries, boolean output, MessageInformation msgInf, Object val) {
void addEntry(List<String> entries, boolean output, PortInformation portInf, Object val) {
String res = output ? "output: " : "input: ";
res += msgInf.name + ": ";
res += portInf.name + ": ";
if (val == null) entries.add(res + "null");
else {
List<String> toStr = msgInf.type.toString(val);
List<String> toStr = portInf.data_type.toString(val);
if (toStr.size() == 0) entries.add(res + "No toString()");
if (toStr.size() == 1) entries.add(res + toStr.get(0));
else {
......@@ -390,15 +387,15 @@ public class JavaAutopilot extends EEComponent implements Inspectable {
@Override
public List<String> getEntries() {
List<String> entries = new ArrayList<>();
addEntry(entries, false, velocityMsg, currentVelocity);
addEntry(entries, false, compassMsg, currentCompass);
addEntry(entries, false, positionMsg, currentPosition);
addEntry(entries, false, trajLengthMsg, trajLength);
addEntry(entries, false, trajXMsg, trajX);
addEntry(entries, false, trajYMsg, trajY);
addEntry(entries, true, accelMsg, currentGas);
addEntry(entries, true, steeringMsg, currentSteering);
addEntry(entries, true, brakeMsg, currentBrakes);
addEntry(entries, false, ports.elementAt(0), currentVelocity);
addEntry(entries, false, ports.elementAt(1), currentPosition);
addEntry(entries, false, ports.elementAt(2), currentCompass);
addEntry(entries, false, ports.elementAt(3), trajLength);
addEntry(entries, false, ports.elementAt(4), trajX);
addEntry(entries, false, ports.elementAt(5), trajY);
addEntry(entries, true, ports.elementAt(6), currentSteering);
addEntry(entries, true, ports.elementAt(7), currentGas);
addEntry(entries, true, ports.elementAt(8), currentBrakes);
return entries;
}
......
......@@ -3,15 +3,15 @@ package de.rwth.montisim.simulation.eecomponents.autopilots;
import java.time.Duration;
import de.rwth.montisim.commons.utils.BuildContext;
import de.rwth.montisim.commons.utils.json.Typed;
import de.rwth.montisim.simulation.eesimulator.components.BusUserProperties;
import de.rwth.montisim.simulation.eesimulator.components.EEComponentType;
import de.rwth.montisim.simulation.eesimulator.components.EEEventProcessor;
import de.rwth.montisim.simulation.eesimulator.*;
import de.rwth.montisim.simulation.eesimulator.exceptions.EEMessageTypeException;
@Typed(JavaAutopilotProperties.TYPE)
public class JavaAutopilotProperties extends BusUserProperties {
public class JavaAutopilotProperties extends EEComponentProperties {
public static final String TYPE = "java_autopilot";
public Duration compute_time = Duration.ZERO;
public double maxVehicleAccel; // TODO get from properties system
......@@ -44,8 +44,8 @@ public class JavaAutopilotProperties extends BusUserProperties {
}
@Override
public EEEventProcessor build(ComponentBuildContext context) {
return new JavaAutopilot(this);
public EEComponent build(EESystem eesystem, BuildContext context) throws EEMessageTypeException {
return new JavaAutopilot(this, eesystem);
}
}
\ No newline at end of file
......@@ -4,9 +4,10 @@ package de.rwth.montisim.simulation.eecomponents.autopilots;
import java.time.*;
import de.rwth.montisim.commons.dynamicinterface.BasicType;
import de.rwth.montisim.commons.dynamicinterface.PortInformation;
import de.rwth.montisim.commons.utils.Time;
import de.rwth.montisim.simulation.eesimulator.actuator.Actuator;
import de.rwth.montisim.simulation.eesimulator.components.*;
import de.rwth.montisim.simulation.eesimulator.*;
import de.rwth.montisim.simulation.eesimulator.events.MessageReceiveEvent;
import de.rwth.montisim.simulation.eesimulator.exceptions.EEMessageTypeException;
import de.rwth.montisim.simulation.eesimulator.message.*;
......@@ -17,10 +18,10 @@ import de.rwth.montisim.simulation.vehicle.powertrain.PowerTrainProperties;
public class TestAutopilot extends EEComponent {
transient final TestAutopilotProperties properties;
transient MessageInformation velocityMsg;
transient MessageInformation steeringMsg;
transient MessageInformation accelMsg;
transient MessageInformation brakeMsg;
transient int velocityMsg;
transient int steeringMsg;
transient int accelMsg;
transient int brakeMsg;
double currentVelocity = 0;
double previous_error = 0;
......@@ -32,21 +33,19 @@ public class TestAutopilot extends EEComponent {
transient final PID pid;
public TestAutopilot(TestAutopilotProperties properties) {
super(properties);
public TestAutopilot(TestAutopilotProperties properties, EESystem eeSystem) {
super(properties, eeSystem);
this.properties = properties;
this.pid = new PID(1, 0, 0.2);
}
@Override
protected void init() throws EEMessageTypeException {
this.velocityMsg = addInput(TrueVelocity.VALUE_NAME, TrueVelocity.TYPE);
this.steeringMsg = addOutput(Actuator.SETTER_PREFIX + PowerTrainProperties.STEERING_VALUE_NAME,
BasicType.DOUBLE);
this.accelMsg = addOutput(Actuator.SETTER_PREFIX + PowerTrainProperties.GAS_VALUE_NAME, BasicType.DOUBLE);
this.brakeMsg = addOutput(Actuator.SETTER_PREFIX + PowerTrainProperties.BRAKING_VALUE_NAME, BasicType.DOUBLE);
this.velocityMsg = addPort(PortInformation.newRequiredInputDataPort(TrueVelocity.VALUE_NAME, TrueVelocity.TYPE, false));
this.steeringMsg = addPort(PortInformation.newRequiredOutputDataPort(Actuator.SETTER_PREFIX + PowerTrainProperties.STEERING_VALUE_NAME,
BasicType.DOUBLE));
this.accelMsg = addPort(PortInformation.newRequiredOutputDataPort(Actuator.SETTER_PREFIX + PowerTrainProperties.GAS_VALUE_NAME, BasicType.DOUBLE));
this.brakeMsg = addPort(PortInformation.newRequiredOutputDataPort(Actuator.SETTER_PREFIX + PowerTrainProperties.BRAKING_VALUE_NAME, BasicType.DOUBLE));
}
@Override
protected void receive(MessageReceiveEvent msgRecvEvent) {
Message msg = msgRecvEvent.getMessage();
......
......@@ -3,20 +3,22 @@ package de.rwth.montisim.simulation.eecomponents.autopilots;
import java.time.Duration;
import de.rwth.montisim.commons.utils.BuildContext;
import de.rwth.montisim.commons.utils.json.JsonEntry;
import de.rwth.montisim.commons.utils.json.Typed;
import de.rwth.montisim.simulation.eesimulator.components.BusUserProperties;
import de.rwth.montisim.simulation.eesimulator.components.EEComponentType;
import de.rwth.montisim.simulation.eesimulator.components.EEEventProcessor;
import de.rwth.montisim.simulation.eesimulator.EEComponentProperties;
import de.rwth.montisim.simulation.eesimulator.EEComponentType;
import de.rwth.montisim.simulation.eesimulator.EESystem;
import de.rwth.montisim.simulation.eesimulator.exceptions.EEMessageTypeException;
import de.rwth.montisim.simulation.eesimulator.EEComponent;
@Typed(TestAutopilotProperties.TYPE)
public class TestAutopilotProperties extends BusUserProperties {
public class TestAutopilotProperties extends EEComponentProperties {
public static final String TYPE = "test_autopilot";
public static enum Mode {
@JsonEntry("circle")
CIRCLE,
@JsonEntry("start_stop")
CIRCLE, @JsonEntry("start_stop")
START_STOP
}
......@@ -64,8 +66,8 @@ public class TestAutopilotProperties extends BusUserProperties {
}
@Override
public EEEventProcessor build(ComponentBuildContext context) {
return new TestAutopilot(this);
public EEComponent build(EESystem eesystem, BuildContext context) throws EEMessageTypeException {
return new TestAutopilot(this, eesystem);
}
}
\ No newline at end of file
package de.rwth.montisim.simulation.eecomponents.simple_network;
public class IPV6Address {
public static final IPV6Address BROADCAST_ADDR = new IPV6Address("ff02::1");
public String addr;
public IPV6Address(String addr) {
this.addr = addr;
}
}
package de.rwth.montisim.simulation.eecomponents.simple_network;
import de.rwth.montisim.commons.utils.BuildContext;
public interface ModuleProperties {
String getName();
SimulatorModule build(BuildContext context);
}
package de.rwth.montisim.simulation.eecomponents.simple_network;
import java.time.Duration;
import de.rwth.montisim.commons.utils.BuildContext;
import de.rwth.montisim.commons.utils.json.Typed;
import de.rwth.montisim.simulation.eesimulator.EEComponentProperties;
import de.rwth.montisim.simulation.eesimulator.EEComponentType;
import de.rwth.montisim.simulation.eesimulator.EESystem;
import de.rwth.montisim.simulation.eesimulator.exceptions.EEMessageTypeException;
import de.rwth.montisim.simulation.vehicle.Vehicle;
import de.rwth.montisim.simulation.eesimulator.EEComponent;
@Typed(SCGProperties.TYPE)
public class SCGProperties extends EEComponentProperties {
public static final String TYPE = "simple_communication_gateway";
public static final String COMPONENT_NAME = "SimpleCommunicationGateway";
public Duration processing_time = Duration.ofMillis(1);
public SCGProperties() {
this.name = COMPONENT_NAME;
}
@Override
public EEComponentType getGeneralType() {
return EEComponentType.COMPUTER;
}
@Override
public String getType() {
return TYPE;
}
@Override
public EEComponent build(EESystem eesystem, BuildContext context) throws EEMessageTypeException {
SimpleNetwork network = context.getObject(SimpleNetwork.CONTEXT_KEY);
Vehicle vehicle = context.getObject(Vehicle.CONTEXT_KEY);
return new SimpleCommunicationGateway(this, eesystem, network, vehicle);
}
}
package de.rwth.montisim.simulation.eecomponents.simple_network;
import java.util.HashSet;
import java.util.Set;
import de.rwth.montisim.commons.dynamicinterface.PortInformation;
import de.rwth.montisim.commons.dynamicinterface.SimplePacketType;
import de.rwth.montisim.commons.dynamicinterface.PortInformation.PortType;
import de.rwth.montisim.commons.eventsimulation.DiscreteEvent;
import de.rwth.montisim.commons.eventsimulation.exceptions.UnexpectedEventException;
import de.rwth.montisim.simulation.eecomponents.simple_network.events.SimpleNetworkRecvEvent;
import de.rwth.montisim.simulation.eesimulator.EEComponent;
import de.rwth.montisim.simulation.eesimulator.EESystem;
import de.rwth.montisim.simulation.eesimulator.events.MessageReceiveEvent;
import de.rwth.montisim.simulation.eesimulator.events.MessageSendEvent;
import de.rwth.montisim.simulation.eesimulator.message.Message;
import de.rwth.montisim.simulation.eesimulator.message.MessageInformation;
import de.rwth.montisim.simulation.eesimulator.message.PortTagUser;
import de.rwth.montisim.simulation.vehicle.Vehicle;
public class SimpleCommunicationGateway extends EEComponent implements PortTagUser {
public static final String NETWORK_TAG = "network";
public static final Set<String> tagSet = new HashSet<>();
static {
tagSet.add(NETWORK_TAG);
}
transient public final SCGProperties properties;
transient final SimpleNetwork network;
public transient final IPV6Address address;
transient final Vehicle vehicle;
public SimpleCommunicationGateway(SCGProperties properties, EESystem eeSystem, SimpleNetwork network, Vehicle vehicle) {
super(properties, eeSystem);
this.properties = properties;
this.network = network;
this.vehicle = vehicle;
this.address = network.registerNode(vehicle.properties.vehicleName + "_COMM_GATEWAY", vehicle.physicalObject, this);
}
@Override
public void process(DiscreteEvent event) {
int type = event.getType();
if (type == MessageSendEvent.type){
dispatchMessage((MessageSendEvent) event);
} else if (type == MessageReceiveEvent.type){
receive((MessageReceiveEvent) event);
} else if (type == SimpleNetworkRecvEvent.type){
receive((SimpleNetworkRecvEvent) event);
} else throw new UnexpectedEventException(this.toString(), event);
}
// Receiving a message from a vehicle component -> Send to the Network
@Override
protected void receive(MessageReceiveEvent msgRecvEvent) {
Message msg = msgRecvEvent.getMessage();
Object packet[] = (Object[]) msg.message;
SimpleNetworkMessage netMsg = new SimpleNetworkMessage(new IPV6Address((String) packet[0]), msg.msgInfo, packet[1], msg.msgLen);
netMsg.sender = address;
eesystem.simulator.addEvent(new SimpleNetworkRecvEvent(network, msgRecvEvent.getEventTime().plus(properties.processing_time), netMsg));
}
// Receiving a message from the Network
private void receive(SimpleNetworkRecvEvent event) {
MessageInformation msgInfo = getMsgInfo(event.msg.msgInfo.name);
if (msgInfo == null) return; // The vehicle does not use this message
// Resolve local MessageInformation
Object newData[] = new Object[2];
newData[0] = event.msg.sender.addr;
newData[1] = event.msg.message;
Message newMsg = new Message(msgInfo, newData, event.msg.msgLen);
eesystem.simulator.addEvent(new MessageSendEvent(this, event.getEventTime().plus(properties.processing_time), newMsg));
}
@Override
public Set<String> getUsedTags() {
return tagSet;
}
@Override
public void processTag(String tag, PortInformation portInfo) {
// TODO handle multiple components with same port
// Add the found ports as own ports
if (portInfo.port_type != PortType.SOCKET) throw new IllegalArgumentException("Port " + portInfo.name + " has 'network' tag but is not of type 'SOCKET'.");
if (!(portInfo.data_type instanceof SimplePacketType)) throw new IllegalArgumentException("Port "+portInfo.name + " has 'network' tag but its DataType is not 'SimplePacketType'.");
addPort(PortInformation.newSocketPort(portInfo.name, portInfo.data_type, portInfo.isOutput(), portInfo.isInput()));
// Register msg types at the Network for type checking
network.registerMessage(address, portInfo.name, portInfo.data_type);
}
}
package de.rwth.montisim.simulation.eecomponents.simple_network;
import java.util.HashMap;
import java.util.Vector;
import java.util.stream.Stream;
import de.rwth.montisim.commons.dynamicinterface.DataType;
import de.rwth.montisim.commons.eventsimulation.DiscreteEvent;
import de.rwth.montisim.commons.eventsimulation.DiscreteEventSimulator;
import de.rwth.montisim.commons.eventsimulation.EventTarget;
import de.rwth.montisim.commons.eventsimulation.exceptions.UnexpectedEventException;
import de.rwth.montisim.commons.simulation.StaticObject;
import de.rwth.montisim.commons.utils.Pair;
import de.rwth.montisim.simulation.eecomponents.simple_network.events.*;
public class SimpleNetwork implements EventTarget, SimulatorModule {
public static final String CONTEXT_KEY = "simple_network";
public final SimpleNetworkProperties properties;
final DiscreteEventSimulator simulator;
Vector<SimpleNetworkNodeInfo> nodes = new Vector<>();
HashMap<String, SimpleNetworkNodeInfo> ipToNode = new HashMap<>();
int addrCounter = 1;
HashMap<String, Pair<DataType, IPV6Address>> msgTypes = new HashMap<>();
public SimpleNetwork(SimpleNetworkProperties properties, DiscreteEventSimulator simulator) {
this.properties = properties;
this.simulator = simulator;
}
public IPV6Address registerNode(String nodeName, StaticObject physicalObject, SimpleCommunicationGateway component) {
String addrStr = "1::"+Integer.toHexString(addrCounter);
IPV6Address addr = new IPV6Address(addrStr);
SimpleNetworkNodeInfo nodeInfo = new SimpleNetworkNodeInfo(nodeName, addr, physicalObject, component);
nodes.add(nodeInfo);
ipToNode.put(addr.addr, nodeInfo);
addrCounter++;
return addr;
}
public void registerMessage(IPV6Address addr, String msgName, DataType msgType) {
Pair<DataType, IPV6Address> prev = msgTypes.get(msgName);
if (prev == null) {
msgTypes.put(msgName, new Pair<>(msgType, addr));
} else {
if (!prev.getKey().equals(msgType)) {
SimpleNetworkNodeInfo prevNode = ipToNode.get(prev.getValue().addr);
SimpleNetworkNodeInfo newNode = ipToNode.get(addr.addr);
throw new IllegalArgumentException(
"Network Msg type error: Node "+newNode.nodeName + " registered msg '"+msgName+"' with type '"+msgType
+" which was already registered with type '"+prev.getKey()+"' by node "+prevNode.nodeName);
}
}
}
@Override
public void process(DiscreteEvent event) {
int type = event.getType();
if (type == SimpleNetworkRecvEvent.type){
simulator.addEvent(new SimpleNetworkSendEvent(this, event.getEventTime().plus(properties.transmission_time), ((SimpleNetworkRecvEvent)event).msg));
} else if (type == SimpleNetworkSendEvent.type){
dispatch((SimpleNetworkSendEvent) event);
} else throw new UnexpectedEventException(this.toString(), event);
}
private void dispatch(SimpleNetworkSendEvent event) {
SimpleNetworkNodeInfo sender = ipToNode.get(event.msg.sender.addr);
SimpleNetworkRecvEvent recvEvent = new SimpleNetworkRecvEvent(null, event.getEventTime(), event.msg);
if (event.msg.target.addr.equals(IPV6Address.BROADCAST_ADDR.addr)) {
nodesInRange(sender).forEach(v -> {
if (v != sender)
v.component.process(recvEvent);
});
} else {
SimpleNetworkNodeInfo target = ipToNode.get(event.msg.target.addr);
if (inRange(target, sender)) {
target.component.process(recvEvent);
}
}
}
private Stream<SimpleNetworkNodeInfo> nodesInRange(SimpleNetworkNodeInfo target) {
return nodes.stream().filter(v -> inRange(target, v));
}