diff --git a/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/AbstractHost.java b/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/AbstractHost.java index 0b0b0be1f..df6c6bbcc 100644 --- a/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/AbstractHost.java +++ b/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/AbstractHost.java @@ -2,26 +2,19 @@ import cz.cuni.mff.d3s.deeco.timer.CurrentTimeProvider; -@SuppressWarnings("rawtypes") public abstract class AbstractHost implements CurrentTimeProvider { - protected final String id; protected final CurrentTimeProvider timeProvider; - + protected AbstractHost(String id, CurrentTimeProvider timeProvider) { this.id = id; this.timeProvider = timeProvider; } - + public String getHostId() { return id; } - - public abstract DataSender getDataSender(); - - public abstract void addDataReceiver(DataReceiver dataReceiver); - public long getCurrentMilliseconds() { return timeProvider.getCurrentMilliseconds(); } @@ -50,6 +43,4 @@ public boolean equals(Object obj) { return false; return true; } - - } diff --git a/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/Host.java b/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/Host.java index eeeb40317..45c96c047 100644 --- a/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/Host.java +++ b/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/Host.java @@ -9,7 +9,6 @@ * @author Michal Kit * */ -@SuppressWarnings("rawtypes") public class Host extends AbstractHost implements NetworkInterface { private final PacketReceiver packetReceiver; @@ -28,19 +27,7 @@ protected Host(NetworkProvider networkProvider, CurrentTimeProvider timeProvider public Host(NetworkProvider networkProvider, CurrentTimeProvider timeProvider, String jDEECoAppModuleId) { this(networkProvider, timeProvider, jDEECoAppModuleId, true, true); } - /* (non-Javadoc) - * @see cz.cuni.mff.d3s.deeco.network.HostDataHandler#getDataSender() - */ - @Override - public DataSender getDataSender() { - return packetSender; - } - @Override - public void addDataReceiver(DataReceiver dataReceiver) { - packetReceiver.addDataReceiver(dataReceiver); - } - // Method used by the simulation public void packetReceived(byte[] packet, double rssi) { packetReceiver.packetReceived(packet, rssi); diff --git a/jdeeco-matsim-plugin/.gitignore b/jdeeco-matsim-plugin/.gitignore new file mode 100644 index 000000000..3466e3dfe --- /dev/null +++ b/jdeeco-matsim-plugin/.gitignore @@ -0,0 +1,4 @@ +/target/ +/.classpath +/logs/ +/matsim/ diff --git a/jdeeco-matsim-plugin/.project b/jdeeco-matsim-plugin/.project new file mode 100644 index 000000000..b9c415063 --- /dev/null +++ b/jdeeco-matsim-plugin/.project @@ -0,0 +1,23 @@ + + + cz.cuni.mff.d3s.jdeeco.matsim + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/jdeeco-matsim-plugin/input/config.xml b/jdeeco-matsim-plugin/input/config.xml new file mode 100644 index 000000000..8ba535a45 --- /dev/null +++ b/jdeeco-matsim-plugin/input/config.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/jdeeco-matsim-plugin/input/grid.xml b/jdeeco-matsim-plugin/input/grid.xml new file mode 100644 index 000000000..3ea8b6091 --- /dev/null +++ b/jdeeco-matsim-plugin/input/grid.xml @@ -0,0 +1,8709 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdeeco-matsim-plugin/input/trivial.xml b/jdeeco-matsim-plugin/input/trivial.xml new file mode 100644 index 000000000..6d97e31be --- /dev/null +++ b/jdeeco-matsim-plugin/input/trivial.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/jdeeco-matsim-plugin/pom.xml b/jdeeco-matsim-plugin/pom.xml new file mode 100644 index 000000000..6aed2fd6c --- /dev/null +++ b/jdeeco-matsim-plugin/pom.xml @@ -0,0 +1,102 @@ + + 4.0.0 + + + cz.cuni.mff.d3s.jdeeco + cz.cuni.mff.d3s.jdeeco + 3.0.0 + ../jdeeco-parent/pom.xml + + + cz.cuni.mff.d3s.jdeeco.matsim + + + UTF-8 + + + + src + test + + + src + + **/*.java + + + + src/.. + + OSGI-INF/*.* + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.2 + + 1.8 + 1.8 + + + + + + + + cz.cuni.mff.d3s.jdeeco + cz.cuni.mff.d3s.jdeeco.core + 3.0.0 + + + + + cz.cuni.mff.d3s.jdeeco + cz.cuni.mff.d3s.jdeeco.network + 3.0.0 + + + + org.matsim + matsim + 0.5.0 + + + junit + junit + 4.12 + test + + + org.mockito + mockito-all + 1.9.5 + test + + + com.github.stefanbirkner + system-rules + 1.6.0 + test + + + log4j + log4j + 1.2.17 + + + org.jfree + jfreechart + 1.0.19 + + + + + d3s + https://gitlab.d3s.mff.cuni.cz:8443/nexus/content/groups/public/ + + + diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/Actuator.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/Actuator.java new file mode 100644 index 000000000..8f4ec4ac7 --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/Actuator.java @@ -0,0 +1,6 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.dataaccess; + +public interface Actuator { + public void set(T value); + public ActuatorType getActuatorType(); +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/ActuatorProvider.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/ActuatorProvider.java new file mode 100644 index 000000000..3f83a308f --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/ActuatorProvider.java @@ -0,0 +1,9 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.dataaccess; + +import java.util.Map; + + +public interface ActuatorProvider { + public Actuator createActuator(ActuatorType type); + public Map> getActuators(); +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/ActuatorType.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/ActuatorType.java new file mode 100644 index 000000000..c487ac4ad --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/ActuatorType.java @@ -0,0 +1,6 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.dataaccess; + +public enum ActuatorType { + ROUTE, + SPEED; +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/MATSimDataProviderReceiver.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/MATSimDataProviderReceiver.java new file mode 100644 index 000000000..588bb629f --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/MATSimDataProviderReceiver.java @@ -0,0 +1,196 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.dataaccess; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.matsim.api.core.v01.Id; +import org.matsim.core.basic.v01.IdImpl; + +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.MATSimDataProvider; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.MATSimDataReceiver; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.MATSimInput; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.MATSimOutput; + +/** + * Input, output handling for MATSim simulation + * + * TODO: Handle parked cars in some more systematic way + */ +public class MATSimDataProviderReceiver implements MATSimDataReceiver, MATSimDataProvider { + // This is coming from MATSim (i.e. its output) = sensors + protected final Map outputs; + + // This is going to MATSim (i.e. its input) = actuators + protected final Map inputs; + + protected final Map> parked; + + public MATSimDataProviderReceiver(List linksToDisable) { + this.outputs = new HashMap(); + this.inputs = new HashMap(); + this.parked = new HashMap>(); + + List parkedVehicles; + Id parkedVehicle = new IdImpl(-1); + for (String linkToDisable : linksToDisable) { + parkedVehicles = new LinkedList(); + parkedVehicles.add(parkedVehicle); + parked.put(new IdImpl(linkToDisable), parkedVehicles); + } + } + + // Here we return next links ids for MATSim agents + @Override + public Map getMATSimData() { + Map result = new HashMap(); + for (Map.Entry entry : inputs.entrySet()) { + result.put(entry.getKey(), entry.getValue().clone()); + } + return result; + } + + // Here we update sensors + @Override + public void setMATSimData(Map map) { + outputs.clear(); + outputs.putAll(map); + } + + public ActuatorProvider getActuatorProvider(final Id ownerId) { + return new ActuatorProvider() { + + private final Map> actuators = new HashMap>(); + + public Actuator createActuator(ActuatorType type) { + @SuppressWarnings("unchecked") + Actuator actuator = (Actuator) getActuatorInternal(ownerId, type, this); + actuators.put(type, actuator); + return actuator; + } + + public Map> getActuators() { + return actuators; + } + }; + } + + public SensorProvider getSensorProvider(final Id ownerId) { + return new SensorProvider() { + + private final Map> sensors = new HashMap>(); + + public Sensor createSensor(SensorType type) { + @SuppressWarnings("unchecked") + Sensor sensor = (Sensor) getSensorInternal(ownerId, type); + sensors.put(type, sensor); + return sensor; + } + + public Map> getSensors() { + return sensors; + } + }; + } + + private Sensor getSensorInternal(final Id requesterId, SensorType sensorType) { + if (sensorType == SensorType.CURRENT_LINK) { + return new Sensor() { + + public SensorType getSensorType() { + return SensorType.CURRENT_LINK; + } + + public Id read() { + MATSimOutput out = outputs.get(requesterId); + return out != null ? out.currentLinkId : null; + } + }; + } else if (sensorType == SensorType.IS_PARKED) { + return new Sensor() { + + public SensorType getSensorType() { + return SensorType.IS_PARKED; + } + + public Boolean read() { + MATSimOutput mo = outputs.get(requesterId); + List parkedVehicles = parked.get(mo.currentLinkId); + if (parkedVehicles == null) { + return false; + } else { + return parked.get(mo.currentLinkId).contains(requesterId); + } + } + }; + } else if (sensorType == SensorType.CURRENT_LINK_FREE_PLACES) { + return new Sensor() { + + public SensorType getSensorType() { + return SensorType.CURRENT_LINK_FREE_PLACES; + } + + public Integer read() { + MATSimOutput mo = outputs.get(requesterId); + List parkedVehicles = parked.get(mo.currentLinkId); + if (parkedVehicles == null || parkedVehicles.size() == 0) { + return 1; + } else { + return 0; + } + } + }; + } + return null; + } + + private Actuator getActuatorInternal(final Id requesterId, ActuatorType actuatorType, + final ActuatorProvider provider) { + final MATSimInput mData; + if (inputs.containsKey(requesterId)) { + mData = inputs.get(requesterId); + } else { + mData = new MATSimInput(); + inputs.put(requesterId, mData); + } + if (actuatorType == ActuatorType.ROUTE) { + return new Actuator>() { + public void set(List value) { + mData.route = value; + if (value == null || value.isEmpty()) { + MATSimOutput mo = outputs.get(requesterId); + List parkedVehicles; + if (parked.containsKey(mo.currentLinkId)) { + parkedVehicles = parked.get(mo.currentLinkId); + } else { + parkedVehicles = new LinkedList(); + parked.put(mo.currentLinkId, parkedVehicles); + } + if (!parkedVehicles.contains(requesterId) && parkedVehicles.size() == 0) { + parkedVehicles.add(requesterId); + } + } + } + + public ActuatorType getActuatorType() { + return ActuatorType.ROUTE; + } + }; + } + if (actuatorType == ActuatorType.SPEED) { + return new Actuator() { + @Override + public void set(Double meterPerSecond) { + mData.speed = meterPerSecond; + } + + @Override + public ActuatorType getActuatorType() { + return ActuatorType.SPEED; + } + }; + } + return null; + } +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/Sensor.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/Sensor.java new file mode 100644 index 000000000..78f1908a4 --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/Sensor.java @@ -0,0 +1,7 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.dataaccess; + +public interface Sensor { + + SensorType getSensorType(); + T read(); +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/SensorProvider.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/SensorProvider.java new file mode 100644 index 000000000..af7d664b3 --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/SensorProvider.java @@ -0,0 +1,8 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.dataaccess; + +import java.util.Map; + +public interface SensorProvider { + public Sensor createSensor(SensorType type); + public Map> getSensors(); +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/SensorType.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/SensorType.java new file mode 100644 index 000000000..d32b4ff3a --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/SensorType.java @@ -0,0 +1,5 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.dataaccess; + +public enum SensorType { + CURRENT_LINK, IS_PARKED, ROUTE, CURRENT_LINK_FREE_PLACES +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/package-info.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/package-info.java new file mode 100644 index 000000000..6d249e169 --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/dataaccess/package-info.java @@ -0,0 +1,6 @@ +/** + * Classes responsible for sensors and actuators provided by MATSim + * + * Ported sources from jDEECo 2 + */ +package cz.cuni.mff.d3s.jdeeco.matsim.dataaccess; \ No newline at end of file diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/plugin/MATSimConfigGenerator.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/plugin/MATSimConfigGenerator.java new file mode 100644 index 000000000..6b3d41fff --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/plugin/MATSimConfigGenerator.java @@ -0,0 +1,83 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.plugin; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +/** + * Generates simple MATSim configuration using the supplied map file + * + * @author Vladimir Matena + * + */ +public class MATSimConfigGenerator { + /** + * Gets configuration content as string + * + * @param map + * Street map used by configuration + * @return String representing the created configuration + */ + public static String getContent(String map) { + StringBuilder content = new StringBuilder(); + + content.append(String.format("%n")); + content.append(String.format("%n")); + + content.append(String.format("%n")); + + // Network / map module + content.append(String.format("%n")); + content.append(String.format("%n", map)); + content.append(String.format("%n")); + + // Controller module + content.append(String.format("%n")); + content.append(String.format("%n")); + content.append(String.format("%n")); + content.append(String.format("%n")); + content.append(String.format("%n")); + content.append(String.format("%n")); + content.append(String.format("%n")); + content.append(String.format("%n")); + content.append(String.format("%n")); + + // QSim module + content.append(String.format("%n")); + content.append(String.format("%n")); + content.append(String.format("%n")); + content.append(String.format("%n")); + content.append(String.format("%n")); + content.append(String.format("%n")); + content.append(String.format("%n")); + content.append(String.format("%n")); + content.append(String.format("%n")); + content.append(String.format("%n")); + content.append(String.format("%n")); + content.append(String.format("%n")); + content.append(String.format("%n")); + + content.append(String.format("%n")); + + return content.toString(); + } + + /** + * Write configuration to temporary file + * + * @param map + * Street map used by configuration + * @return File representing the created configuration + * @throws IOException + */ + public static File writeToTemp(String map) throws IOException { + File temp = File.createTempFile("config", ".xml"); + temp.deleteOnExit(); + + FileWriter writer = new FileWriter(temp); + writer.write(getContent(map)); + writer.close(); + + return temp; + } +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/plugin/MATSimHost.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/plugin/MATSimHost.java new file mode 100644 index 000000000..efae52907 --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/plugin/MATSimHost.java @@ -0,0 +1,22 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.plugin; + +import cz.cuni.mff.d3s.deeco.network.AbstractHost; +import cz.cuni.mff.d3s.deeco.timer.CurrentTimeProvider; +import cz.cuni.mff.d3s.deeco.timer.TimerEventListener; + +/** + * DEECo node host representation used in MATSim simulation + * + * @author Vladimir Matena + */ +public class MATSimHost extends AbstractHost { + public TimerEventListener listener; + + public MATSimHost(String id, CurrentTimeProvider timeProvider) { + super(id, timeProvider); + } + + public void at(double absoluteTime) { + listener.at(getCurrentMilliseconds()); + } +} \ No newline at end of file diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/plugin/MATSimSimulation.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/plugin/MATSimSimulation.java new file mode 100644 index 000000000..7222f41ed --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/plugin/MATSimSimulation.java @@ -0,0 +1,300 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.plugin; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.core.basic.v01.IdImpl; +import org.matsim.core.controler.Controler; +import org.matsim.core.controler.events.StartupEvent; +import org.matsim.core.controler.listener.StartupListener; +import org.matsim.core.mobsim.framework.Mobsim; +import org.matsim.core.router.util.TravelTime; +import org.matsim.withinday.trafficmonitoring.TravelTimeCollector; +import org.matsim.withinday.trafficmonitoring.TravelTimeCollectorFactory; + +import cz.cuni.mff.d3s.deeco.logging.Log; +import cz.cuni.mff.d3s.deeco.runtime.DEECoContainer; +import cz.cuni.mff.d3s.deeco.runtime.DEECoPlugin; +import cz.cuni.mff.d3s.deeco.timer.SimulationTimer; +import cz.cuni.mff.d3s.deeco.timer.TimerEventListener; +import cz.cuni.mff.d3s.jdeeco.matsim.dataaccess.MATSimDataProviderReceiver; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.AdditionAwareAgentSource; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.DefaultMATSimExtractor; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.DefaultMATSimUpdater; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.JDEECoAgent; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.JDEECoAgentSource; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.JDEECoMobsimFactory; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.JDEECoWithinDayMobsimListener; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.MATSimDataProvider; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.MATSimDataReceiver; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.MATSimExtractor; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.MATSimPreloadingControler; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.MATSimRouter; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.MATSimSimulationStepListener; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.Simulation; + +/** + * Plug-in providing MATSim simulation + * + * Based on the code from the jDEECo 2 simulation project + * + * @author Vladimir Matena + * + */ +public class MATSimSimulation implements DEECoPlugin { + private final TimerProvider timer = new TimerProvider(); + private final JDEECoAgentSource agentSource = new JDEECoAgentSource(); + private final MATSimRouter router; + private final MATSimDataProviderReceiver matSimProviderReceiver = new MATSimDataProviderReceiver( + new LinkedList()); + private long currentMilliseconds; + private final long simulationStep; // in milliseconds + private final TravelTime travelTime; + private final Controler controler; + private final JDEECoWithinDayMobsimListener listener; + private final MATSimDataProvider matSimProvider; + private final MATSimDataReceiver matSimReceiver; + private final Map hosts = new HashMap<>();; + private final MATSimExtractor extractor; + // private final Exchanger exchanger = new Exchanger();; + + public MATSimSimulation(String configPath, AdditionAwareAgentSource... additionalAgenSources) throws IOException { + this(new File(configPath), additionalAgenSources); + } + + public MATSimSimulation(File config, AdditionAwareAgentSource... additionalAgentSources) throws IOException { + List agentSources = new LinkedList<>(); + agentSources.add(agentSource); + agentSources.addAll(Arrays.asList(additionalAgentSources)); + + // Setup MATSim controller + controler = new MATSimPreloadingControler(config.getAbsolutePath()); + controler.setOverwriteFiles(true); + controler.getConfig().getQSimConfigGroup().setSimStarttimeInterpretation("onlyUseStarttime"); + + // Get simulation times + final double end = this.controler.getConfig().getQSimConfigGroup().getEndTime(); + final double start = this.controler.getConfig().getQSimConfigGroup().getStartTime(); + final double step = this.controler.getConfig().getQSimConfigGroup().getTimeStepSize(); + Log.i("Starting simulation: matsimStartTime: " + start + " matsimEndTime: " + end); + + this.extractor = new DefaultMATSimExtractor(); + this.listener = new JDEECoWithinDayMobsimListener(timer, new DefaultMATSimUpdater(), extractor); + this.matSimProvider = (MATSimDataProvider) matSimProviderReceiver; + this.matSimReceiver = (MATSimDataReceiver) matSimProviderReceiver; + + Set analyzedModes = new HashSet(); + analyzedModes.add(TransportMode.car); + travelTime = new TravelTimeCollectorFactory().createTravelTimeCollector(controler.getScenario(), analyzedModes); + + controler.addControlerListener(new StartupListener() { + public void notifyStartup(StartupEvent event) { + controler.getEvents().addHandler((TravelTimeCollector) travelTime); + controler.getMobsimListeners().add((TravelTimeCollector) travelTime); + controler.setMobsimFactory(new JDEECoMobsimFactory(listener, agentSources)); + } + }); + + /** + * Bind MATSim listener with the agent source. It is necessary to let the listener know about the jDEECo agents + * that it needs to update with data coming from a jDEECo runtime. + */ + for (AdditionAwareAgentSource source : agentSources) { + if (source instanceof JDEECoAgentSource) { + listener.registerAgentProvider((JDEECoAgentSource) source); + } + } + + simulationStep = TimerProvider.secondsToMilliseconds(step); + currentMilliseconds = TimerProvider.secondsToMilliseconds(controler.getConfig().getQSimConfigGroup().getStartTime()); + + router = new MATSimRouter(controler, travelTime, 10 /* TODO: FAKE VALUE */); + } + + public SimulationTimer getTimer() { + return timer; + } + + public MATSimRouter getRouter() { + return router; + } + + public MATSimDataProviderReceiver getMATSimProviderReceiver() { + return matSimProviderReceiver; + } + + public void addVehicle(int vehicleId, Id startLink) { + agentSource.addAgent(new JDEECoAgent(new IdImpl(vehicleId), startLink)); + } + + @Override + public List> getDependencies() { + // No dependencies + return new LinkedList>(); + } + + @Override + public void init(DEECoContainer container) { + MATSimHost host = new MATSimHost(String.valueOf(container.getId()), getTimer()); + addHost(container.getId(), host); + } + + private void addHost(int id, cz.cuni.mff.d3s.jdeeco.matsim.plugin.MATSimHost host) { + hosts.put(id, host); + } + + private MATSimHost getHost(int id) { + return hosts.get(id); + } + + private void run(long duration) { + double startTime = controler.getConfig().getQSimConfigGroup().getStartTime(); + double endTime = startTime + (((double) (duration)) / 1000); + controler.getConfig().getQSimConfigGroup().setEndTime(endTime); + controler.run(); + } + + /** + * Class implementing timer for MATSim simulation + * + * @author Vladimir Matena + * + */ + class TimerProvider extends Simulation implements SimulationTimer, MATSimSimulationStepListener { + private final TreeSet callbacks = new TreeSet<>(); + private final Map hostIdToCallback = new HashMap<>(); + + @Override + public void notifyAt(long time, TimerEventListener listener, DEECoContainer node) { + callAt(time, node.getId()); + MATSimSimulation.this.getHost(node.getId()).listener = listener; + } + + @Override + public synchronized void callAt(long absoluteTime, int hostId) { + Callback callback = hostIdToCallback.remove(hostId); + if (callback != null) { + callbacks.remove(callback); + } + callback = new Callback(hostId, absoluteTime); + hostIdToCallback.put(hostId, callback); + callbacks.add(callback); + } + + @Override + public long getCurrentMilliseconds() { + return MATSimSimulation.this.currentMilliseconds; + } + + @Override + public void start(long duration) { + MATSimSimulation.this.run(duration); + } + + @Override + public void at(double seconds, Mobsim mobsim) { + // Exchange data with MATSim + long milliseconds = secondsToMilliseconds(seconds); + matSimReceiver.setMATSimData(extractor.extractFromMATSim(listener.getAllJDEECoAgents(), mobsim)); + listener.updateJDEECoAgents(matSimProvider.getMATSimData()); + // Add callback for the MATSim step + callAt(milliseconds + simulationStep, Callback.SIMULATION_CALLBACK_HOSTID); + MATSimHost host; + Callback callback; + // Iterate through all the call-backs until the MATSim callback. + while (!callbacks.isEmpty()) { + callback = callbacks.pollFirst(); + if (callback.isSimulationCallaback()) { + break; + } + currentMilliseconds = callback.getAbsoluteTime(); + // System.out.println("At: " + currentMilliseconds); + host = hosts.get(callback.hostId); + host.at(millisecondsToSeconds(currentMilliseconds)); + } + } + } + + private class Callback implements Comparable { + static final int SIMULATION_CALLBACK_HOSTID = -1; + + private final long milliseconds; + private final int hostId; + + public Callback(int hostId, long milliseconds) { + this.hostId = hostId; + this.milliseconds = milliseconds; + } + + public long getAbsoluteTime() { + return milliseconds; + } + + public int getHostId() { + return hostId; + } + + public boolean isSimulationCallaback() { + return getHostId() == SIMULATION_CALLBACK_HOSTID; + } + + @Override + public int compareTo(Callback c) { + if (c.getAbsoluteTime() < milliseconds) { + return 1; + } else if (c.getAbsoluteTime() > milliseconds) { + return -1; + } else if (this == c) { + return 0; + } else { + return this.hashCode() < c.hashCode() ? 1 : -1; + } + } + + public String toString() { + return hostId + " " + milliseconds; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + getOuterType().hashCode(); + result = prime * result + hostId; + result = prime * result + (int) (milliseconds ^ (milliseconds >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Callback other = (Callback) obj; + if (!getOuterType().equals(other.getOuterType())) + return false; + if (hostId != other.hostId) + return false; + if (milliseconds != other.milliseconds) + return false; + return true; + } + + private MATSimSimulation getOuterType() { + return MATSimSimulation.this; + } + } +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/plugin/MATSimVehicle.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/plugin/MATSimVehicle.java new file mode 100644 index 000000000..413bce565 --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/plugin/MATSimVehicle.java @@ -0,0 +1,117 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.plugin; + +import java.util.Arrays; +import java.util.List; + +import org.matsim.api.core.v01.Id; +import org.matsim.core.basic.v01.IdImpl; +import org.matsim.core.utils.geometry.CoordImpl; + +import cz.cuni.mff.d3s.deeco.runtime.DEECoContainer; +import cz.cuni.mff.d3s.deeco.runtime.DEECoPlugin; +import cz.cuni.mff.d3s.deeco.timer.CurrentTimeProvider; +import cz.cuni.mff.d3s.jdeeco.matsim.dataaccess.ActuatorProvider; +import cz.cuni.mff.d3s.jdeeco.matsim.dataaccess.SensorProvider; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.MATSimRouter; + +/** + * jDEECo plug-in that provides MATSim vehicle agent + * + * @author Vladimir Matena + * + */ +public class MATSimVehicle implements DEECoPlugin { + private MATSimSimulation simulation; + private DEECoContainer container; + + // Initial configuration, either link or coordinates can be provided + private Id startLink; + private CoordImpl startPosition; + + /** + * Creates vehicle + * + * Vehicle is initially located at specified coordinates + * + * @param x + * position coordinate + * @param y + * position coordinate + */ + public MATSimVehicle(double x, double y) { + startPosition = new CoordImpl(x, y); + } + + /** + * Create vehicle + * + * Vehicle is initially located on the specified link + * + * @param startLink + */ + public MATSimVehicle(Id startLink) { + this.startLink = startLink; + } + + /** + * Gets vehicle sensor provider + * + * Used to create sensors to obtain data from vehicle. + * + * @return Sensor provider + */ + public SensorProvider getSensorProvider() { + return simulation.getMATSimProviderReceiver().getSensorProvider(new IdImpl(container.getId())); + } + + /** + * Gets vehicle actuator provider + * + * Used to create actuator to control the vehicle. + * + * @return Actuator provider + */ + public ActuatorProvider getActuatorProvider() { + return simulation.getMATSimProviderReceiver().getActuatorProvider(new IdImpl(container.getId())); + } + + /** + * Gets simulation router + * + * Used to find routes in the simulated world. + * + * @return Simulation router + */ + public MATSimRouter getRouter() { + return simulation.getRouter(); + } + + /** + * Gets time provider + * + * Used to get current time in the simulated world. + * + * @return Time provider + */ + public CurrentTimeProvider getTimer() { + return simulation.getTimer(); + } + + @Override + public List> getDependencies() { + return Arrays.asList(MATSimSimulation.class); + } + + @Override + public void init(DEECoContainer container) { + this.container = container; + simulation = container.getPluginInstance(MATSimSimulation.class); + + if (startLink == null) { + startLink = simulation.getRouter().findNearestLink(startPosition).getId(); + } + + // Add vehicle to simulation + simulation.addVehicle(container.getId(), startLink); + } +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/plugin/package-info.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/plugin/package-info.java new file mode 100644 index 000000000..b8999fcd6 --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/plugin/package-info.java @@ -0,0 +1,8 @@ +/** + * MATSim simulation plug-in for JDEECo implementation + */ +/** + * @author Vladimir Matena + * + */ +package cz.cuni.mff.d3s.jdeeco.matsim.plugin; \ No newline at end of file diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/AdditionAwareAgentSource.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/AdditionAwareAgentSource.java new file mode 100644 index 000000000..c5f943ec9 --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/AdditionAwareAgentSource.java @@ -0,0 +1,17 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import org.matsim.core.mobsim.framework.AgentSource; +import org.matsim.core.mobsim.qsim.QSim; + +/** + * This interface has been introduced to allow creation/modification of the + * MATSim agent source before the simulation is started. When simulation is + * started then the QSim instance is created and as such it needs to be passed + * to the agent source before it is used. + * + * @author Michal Kit + * + */ +public interface AdditionAwareAgentSource extends AgentSource { + public void agentSourceAdded(QSim qSim); +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/CallbackProvider.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/CallbackProvider.java new file mode 100644 index 000000000..db604a75f --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/CallbackProvider.java @@ -0,0 +1,5 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +public interface CallbackProvider { + public void callAt(long absoluteTime, int hostId); +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/DefaultMATSimExtractor.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/DefaultMATSimExtractor.java new file mode 100644 index 000000000..69d224b18 --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/DefaultMATSimExtractor.java @@ -0,0 +1,25 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.matsim.api.core.v01.Id; +import org.matsim.core.mobsim.framework.Mobsim; + +public class DefaultMATSimExtractor implements MATSimExtractor { + + @Override + public Map extractFromMATSim(Collection agents, + Mobsim mobsim) { + Map map = new HashMap(); + MATSimOutput matSimOutput; + for (JDEECoAgent agent : agents) { + matSimOutput = new MATSimOutput(agent.getCurrentLinkId(), + agent.getState()); + map.put(agent.getId(), matSimOutput); + } + return map; + } + +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/DefaultMATSimUpdater.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/DefaultMATSimUpdater.java new file mode 100644 index 000000000..c76dedc2a --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/DefaultMATSimUpdater.java @@ -0,0 +1,22 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import java.util.Collection; +import java.util.Map; + +public class DefaultMATSimUpdater implements MATSimUpdater { + + @SuppressWarnings("unchecked") + @Override + public void updateJDEECoAgents(Object input, Collection agents) { + if (input != null && input instanceof Map) { + Map map = (Map) input; + for (JDEECoAgent agent: agents) { + if (map.containsKey(agent.getId())) { + agent.setRoute(((MATSimInput) map.get(agent.getId())).route); + agent.setSpeed(((MATSimInput) map.get(agent.getId())).speed); + } + } + } + } + +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/JDEECoAgent.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/JDEECoAgent.java new file mode 100644 index 000000000..5e4512a76 --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/JDEECoAgent.java @@ -0,0 +1,202 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import java.util.LinkedList; +import java.util.List; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.core.api.experimental.events.AgentArrivalEvent; +import org.matsim.core.basic.v01.IdImpl; +import org.matsim.core.mobsim.framework.MobsimDriverAgent; +import org.matsim.core.mobsim.qsim.QSim; +import org.matsim.core.mobsim.qsim.interfaces.MobsimVehicle; + +/** + * JDEECo agent implementation. The agent is used by the + * {@link JDEECoWithinDayMobsimListener} to steer the MATSim simulation, + * according to the state of the JDEECo component. + * + * @author Michal Kit + * + */ +public class JDEECoAgent implements MobsimDriverAgent { + + private MobsimVehicle vehicle; + private Id currentLinkId; + private Id id; + private State state = State.ACTIVITY; + private Id plannedVehicleId; + + private QSim simulation; + private List route; + + // We need this variable to prevent the stopping the car (i.e. setting the + // route to empty or null) when it is at the intersection (i.e. in the link + // buffer). + private boolean unreachedDestinationGiven = false; + + public JDEECoAgent(Id id, Id currentLinkId, List route) { + this.id = id; + this.currentLinkId = currentLinkId; + this.route = route; + } + + public JDEECoAgent(Id id, Id currentLinkId) { + this(id, currentLinkId, null); + } + + public void setSimulation(QSim simulation) { + this.simulation = simulation; + } + + public void abort(double now) { + this.state = State.ABORT; + } + + public void endActivityAndComputeNextState(double now) { + if (route == null || route.isEmpty()) + return; + this.simulation.getEventsManager().processEvent( + this.simulation + .getEventsManager() + .getFactory() + .createActivityEndEvent(now, this.getId(), + currentLinkId, new IdImpl(100), "activity")); + this.state = State.LEG; // want to move + } + + public void endLegAndComputeNextState(double now) { + this.simulation.getEventsManager().processEvent( + new AgentArrivalEvent(now, this.getId(), destination(), + getMode())); + this.state = State.ACTIVITY; + } + + public double getActivityEndTime() { + if (route == null || route.isEmpty()) { + double currentTime = this.simulation.getSimTimer().getTimeOfDay(); + return currentTime + + this.simulation.getSimTimer().getSimTimestepSize(); + } else { + return simulation.getSimTimer().getTimeOfDay(); + } + } + + public Double getExpectedTravelTime() { + return 0.; // what does this matter for? + } + + public String getMode() { + return TransportMode.car; // either car or nothing + } + + public State getState() { + return this.state; + } + + public void notifyArrivalOnLinkByNonNetworkMode(Id linkId) { + this.currentLinkId = linkId; + } + + public void setRoute(List route) { + int indexOfCurrentLink; + if (unreachedDestinationGiven && (route == null || route.isEmpty())) { + if (this.route != null && !this.route.isEmpty()) { + indexOfCurrentLink = this.route.lastIndexOf(currentLinkId); + if (indexOfCurrentLink < 0) { + this.route = new LinkedList<>(this.route.subList(0, 1)); + } else if (indexOfCurrentLink < this.route.size() - 1){ + this.route = new LinkedList<>(this.route.subList(indexOfCurrentLink + 1, indexOfCurrentLink + 2)); + } else { + this.route = new LinkedList<>(); + } + //System.out.println(id + " route: " + this.route.toString()); + return; + } + } + indexOfCurrentLink = route.lastIndexOf(currentLinkId); + if (indexOfCurrentLink < 0) { + this.route = route; + } else { + this.route = new LinkedList(route.subList(indexOfCurrentLink + 1, + route.size())); + } + //System.out.println(id + " route: " + this.route.toString()); + } + + public void setSpeed(Double meterPerSecond) { + getVehicle().getVehicle().getType().setMaximumVelocity(meterPerSecond); + } + + public Id getCurrentLinkId() { + //System.out.println(id + " current: " + currentLinkId.toString()); + return this.currentLinkId; + } + + public Id getDestinationLinkId() { + Id result = destination(); + // Here we mark the situation when the agent was asked for the + // destination and it replied with one which is not yet reached. From + // now on and until invoking the chooseNextLink method setting an empty + // route is not allowed. + unreachedDestinationGiven = !result.equals(currentLinkId); + //System.out.println(id + " destination: " + result); + return result; + } + + public Id getId() { + return this.id; + } + + public Id chooseNextLinkId() { + this.unreachedDestinationGiven = false; + Id result; + if (route == null || route.isEmpty()) { + result = null; + } else if (currentLinkId.equals(route.get(route.size()-1))) { + route.clear(); + result = null; + } else { + result = route.remove(0); + if (result.equals(currentLinkId)) { + if (route.isEmpty()) { + result = null; + } else { + result = route.remove(0); + } + } + } + //System.out.println(id + " nextLink: " + result); + return result; + } + + public Id getPlannedVehicleId() { + return this.plannedVehicleId; + } + + public void setPlannedVehicleId(Id plannedVehicleId) { + this.plannedVehicleId = plannedVehicleId; + } + + public MobsimVehicle getVehicle() { + return this.vehicle; + } + + public void notifyMoveOverNode(Id newLinkId) { + this.currentLinkId = newLinkId; + } + + public void setVehicle(MobsimVehicle veh) { + this.vehicle = veh; + } + + private Id destination() { + Id result; + if (route == null || route.isEmpty()) { + result = currentLinkId; + } else { + result = route.get(route.size() - 1); + } + return result; + } +} \ No newline at end of file diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/JDEECoAgentProvider.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/JDEECoAgentProvider.java new file mode 100644 index 000000000..a14acce6a --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/JDEECoAgentProvider.java @@ -0,0 +1,14 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import java.util.Collection; + +/** + * The interface is used by the {@link JDEECoWithinDayMobsimListener} instance + * to retrieve simulated jDEECo agents. + * + * @author Michal Kit + * + */ +public interface JDEECoAgentProvider { + public Collection getAgents(); +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/JDEECoAgentSource.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/JDEECoAgentSource.java new file mode 100644 index 000000000..d0c7a6a15 --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/JDEECoAgentSource.java @@ -0,0 +1,57 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import org.matsim.core.basic.v01.IdImpl; +import org.matsim.core.mobsim.qsim.QSim; +import org.matsim.core.mobsim.qsim.QSimUtils; +import org.matsim.core.mobsim.qsim.interfaces.MobsimVehicle; + +import cz.cuni.mff.d3s.deeco.logging.Log; + +/** + * JDEECo agent source, which is used by MATSim to retrieve agents that need to + * be simulated. + * + * @author Michal Kit + * + */ +public class JDEECoAgentSource implements AdditionAwareAgentSource, + JDEECoAgentProvider { + private QSim qSim; + private final List agents; + + public JDEECoAgentSource() { + this.agents = new LinkedList(); + } + + public void agentSourceAdded(QSim qSim) { + this.qSim = qSim; + } + + public void addAgent(JDEECoAgent agent) { + agents.add(agent); + } + + public void insertAgentsIntoMobsim() { + if (qSim == null) { + Log.e("jDEECoAgentSource not properly initialized!"); + return; + } + for (JDEECoAgent agent : agents) { + MobsimVehicle vehicle = QSimUtils.createDefaultVehicle(new IdImpl( + agent.getId().toString() + "-vehicle")); + agent.setSimulation(qSim); + agent.setPlannedVehicleId(vehicle.getId()); + agent.setVehicle(vehicle); + qSim.addParkedVehicle(vehicle, agent.getCurrentLinkId()); + qSim.insertAgentIntoMobsim(agent); + } + } + + public Collection getAgents() { + return agents; + } +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/JDEECoMobsimFactory.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/JDEECoMobsimFactory.java new file mode 100644 index 000000000..e189b6744 --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/JDEECoMobsimFactory.java @@ -0,0 +1,53 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import java.util.Collection; + +import org.matsim.api.core.v01.Scenario; +import org.matsim.core.api.experimental.events.EventsManager; +import org.matsim.core.mobsim.framework.Mobsim; +import org.matsim.core.mobsim.framework.MobsimFactory; +import org.matsim.core.mobsim.qsim.ActivityEngine; +import org.matsim.core.mobsim.qsim.QSim; +import org.matsim.core.mobsim.qsim.TeleportationEngine; +import org.matsim.core.mobsim.qsim.qnetsimengine.DefaultQSimEngineFactory; +import org.matsim.core.mobsim.qsim.qnetsimengine.QNetsimEngine; + +/** + * Mobisim engine factory. It is the configuration point for the MATSim + * simulation to let it know, which agent source, listeners etc... to use. + * + * @author Michal Kit + * + */ +public class JDEECoMobsimFactory implements MobsimFactory { + + private final JDEECoWithinDayMobsimListener listener; + private final Collection agentSources; + + public JDEECoMobsimFactory(JDEECoWithinDayMobsimListener listener, + Collection agentSources) { + this.listener = listener; + this.agentSources = agentSources; + } + + public Mobsim createMobsim(Scenario sc, EventsManager events) { + QSim qSim = new QSim(sc, events); + ActivityEngine activityEngine = new ActivityEngine(); + qSim.addMobsimEngine(activityEngine); + qSim.addActivityHandler(activityEngine); + QNetsimEngine simEngine = new DefaultQSimEngineFactory() + .createQSimEngine(qSim); + qSim.addMobsimEngine(simEngine); + qSim.addDepartureHandler(simEngine.getDepartureHandler()); + TeleportationEngine teleportationEngine = new TeleportationEngine(); + qSim.addMobsimEngine(teleportationEngine); + qSim.addQueueSimulationListeners(listener); + // Add agent sources to the simulation + for (AdditionAwareAgentSource aaas : agentSources) { + qSim.addAgentSource(aaas); + aaas.agentSourceAdded(qSim); + } + return qSim; + } + +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/JDEECoWithinDayMobsimListener.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/JDEECoWithinDayMobsimListener.java new file mode 100644 index 000000000..23a418b56 --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/JDEECoWithinDayMobsimListener.java @@ -0,0 +1,95 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.Exchanger; + +import org.matsim.core.mobsim.framework.events.MobsimBeforeSimStepEvent; +import org.matsim.core.mobsim.framework.listeners.MobsimBeforeSimStepListener; + +import cz.cuni.mff.d3s.deeco.logging.Log; + +/** + * + * This class represents the interface (on the MATSim side) between jDEECo and + * MATSim. It's notifyMobsimBeforeSimStep is executed before each simulation + * step and data exchange between MATSim and jDEECo happens via the exchanger + * instance. + * + * @author Michal Kit + * + */ +public class JDEECoWithinDayMobsimListener implements + MobsimBeforeSimStepListener { + + private final Exchanger exchanger; + private final List agentProviders; + private final MATSimSimulationStepListener stepListener; + private final MATSimUpdater updater; + private final MATSimExtractor extractor; + + private long remainingExchanges; + + protected JDEECoWithinDayMobsimListener(Exchanger exchanger, MATSimSimulationStepListener stepListener, MATSimUpdater updater, MATSimExtractor extractor, long remainingExchanges) { + this.exchanger = exchanger; + this.agentProviders = new LinkedList(); + this.stepListener = stepListener; + this.updater = updater; + this.extractor = extractor; + this.remainingExchanges = remainingExchanges; + } + + public JDEECoWithinDayMobsimListener(Exchanger exchanger, MATSimUpdater updater, MATSimExtractor extractor) { + this(exchanger, null, updater, extractor, -1); + } + + public JDEECoWithinDayMobsimListener(Exchanger exchanger, MATSimUpdater updater, MATSimExtractor extractor, long remainingExchanges) { + this(exchanger, null, updater, extractor, remainingExchanges); + } + + public JDEECoWithinDayMobsimListener(MATSimSimulationStepListener stepListener, MATSimUpdater updater, MATSimExtractor extractor) { + this(null, stepListener, updater, extractor, -1); + } + + public void registerAgentProvider(JDEECoAgentProvider agentProvider) { + if (!agentProviders.contains(agentProvider)) { + agentProviders.add(agentProvider); + } + } + + public void updateJDEECoAgents(Object input) { + updater.updateJDEECoAgents(input, getAllJDEECoAgents()); + } + + public Collection getAllJDEECoAgents() { + List agents = new LinkedList<>(); + for (JDEECoAgentProvider agentProvider : agentProviders) { + agents.addAll(agentProvider.getAgents()); + } + return agents; + } + + @SuppressWarnings("rawtypes") + public void notifyMobsimBeforeSimStep(MobsimBeforeSimStepEvent event) { + if (this.remainingExchanges == 0) { + return; + } + if (exchanger != null) { + try { + //System.out.println("MATSIM before: " + event.getSimulationTime()); + updateJDEECoAgents(exchanger.exchange(extractor.extractFromMATSim(getAllJDEECoAgents(), event.getQueueSimulation()))); + //System.out.println("MATSIM after: " + event.getSimulationTime()); + } catch (Exception e) { + Log.e("jDEECoWithinDayMobsimListener: ", e); + } + } + if (stepListener != null) { + stepListener.at(event.getSimulationTime(), event.getQueueSimulation()); + } + if (this.remainingExchanges > 0) { + this.remainingExchanges--; + } + } + +} \ No newline at end of file diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimDataProvider.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimDataProvider.java new file mode 100644 index 000000000..7882770db --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimDataProvider.java @@ -0,0 +1,15 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import java.util.Map; + +import org.matsim.api.core.v01.Id; + +/** + * Interface for MATSim data i.e. the data that is for the MATSim side. + * + * @author Michal Kit + * + */ +public interface MATSimDataProvider { + public Map getMATSimData(); +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimDataReceiver.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimDataReceiver.java new file mode 100644 index 000000000..443ef77df --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimDataReceiver.java @@ -0,0 +1,16 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import java.util.Map; + +import org.matsim.api.core.v01.Id; + + +/** + * Interface for MATSim data retrieval. This data comes from MATSim side. + * + * @author Michal Kit + * + */ +public interface MATSimDataReceiver { + public void setMATSimData(Map data); +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimExtractor.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimExtractor.java new file mode 100644 index 000000000..678291ec6 --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimExtractor.java @@ -0,0 +1,11 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import java.util.Collection; +import java.util.Map; + +import org.matsim.api.core.v01.Id; +import org.matsim.core.mobsim.framework.Mobsim; + +public interface MATSimExtractor { + public Map extractFromMATSim(Collection agents, Mobsim mobsim); +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimInput.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimInput.java new file mode 100644 index 000000000..260b9ee4a --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimInput.java @@ -0,0 +1,28 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import java.util.LinkedList; +import java.util.List; + +import org.matsim.api.core.v01.Id; + +/** + * Data that is needed by MATSim to execute the simulation. + * + * @author Michal Kit + * + */ +public class MATSimInput { + public List route = new LinkedList<>(); + public Double speed = Double.POSITIVE_INFINITY; + + public MATSimInput clone() { + MATSimInput result = new MATSimInput(); + if (route == null) { + result.route = null; + } else { + result.route = new LinkedList(route); + } + result.speed = speed; + return result; + } +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimOMNetCoordinatesTranslator.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimOMNetCoordinatesTranslator.java new file mode 100644 index 000000000..7b689d80c --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimOMNetCoordinatesTranslator.java @@ -0,0 +1,65 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.network.Network; +import org.matsim.api.core.v01.network.Node; +import org.matsim.core.utils.geometry.CoordImpl; + +/** + * Because the coordinates in MATSim are given in meters in large numbers, this + * class takes care to translate coordinates from MATSim to OMNet, which are + * much smaller. + * + * + * + * @author Michal Kit + * + */ +public class MATSimOMNetCoordinatesTranslator { + + private final double OMNetSizeX; + private final double OMNetSizeY; + private final Coord translationVector; + + public MATSimOMNetCoordinatesTranslator(Network network) { + double maxX = 0, maxY = 0, minX = Double.MAX_VALUE, minY = Double.MAX_VALUE; + double currentX, currentY; + for (Node node : network.getNodes().values()) { + currentX = node.getCoord().getX(); + currentY = node.getCoord().getY(); + if (currentX > maxX) { + maxX = currentX; + } else if (currentX < minX) { + minX = currentX; + } + if (currentY > maxY) { + maxY = currentY; + } else if (currentY < minY) { + minY = currentY; + } + } + // Let's give 50m boundary + minX -= 50.0; + minY -= 50.0; + maxX += 50.0; + maxY += 50.0; + // Calculate OMNet sizes + this.OMNetSizeX = maxX - minX; + this.OMNetSizeY = maxY - minY; + this.translationVector = new CoordImpl(-minX, -minY); + } + + public double getOMNetSizeX() { + return OMNetSizeX; + } + + public double getOMNetSizeY() { + return OMNetSizeY; + } + + public Coord fromMATSimToOMNet(Coord coord) { + return new CoordImpl(coord.getX() + translationVector.getX(), + coord.getY() + translationVector.getY()); + } + +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimOutput.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimOutput.java new file mode 100644 index 000000000..36cbdc953 --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimOutput.java @@ -0,0 +1,20 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import org.matsim.api.core.v01.Id; +import org.matsim.core.mobsim.framework.MobsimAgent.State; + +/** + * Data coming from MATSim. + * + * @author Michal Kit + * + */ +public class MATSimOutput { + public Id currentLinkId; + public State state; + + public MATSimOutput(Id currentLinkId, State state) { + this.currentLinkId = currentLinkId; + this.state = state; + } +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimPopulationAgentSource.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimPopulationAgentSource.java new file mode 100644 index 000000000..83a12d3ce --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimPopulationAgentSource.java @@ -0,0 +1,93 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.population.Activity; +import org.matsim.api.core.v01.population.Leg; +import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.Plan; +import org.matsim.api.core.v01.population.PlanElement; +import org.matsim.api.core.v01.population.Population; +import org.matsim.core.mobsim.framework.MobsimAgent; +import org.matsim.core.mobsim.qsim.QSim; +import org.matsim.core.mobsim.qsim.agents.AgentFactory; +import org.matsim.core.mobsim.qsim.agents.ExperimentalBasicWithindayAgentFactory; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; + +public class MATSimPopulationAgentSource implements + AdditionAwareAgentSource { + + private Population population; + private AgentFactory agentFactory; + private QSim qsim; + private Map modeVehicleTypes; + private Collection mainModes; + + public void insertAgentsIntoMobsim() { + if (qsim == null || population == null) { + throw new RuntimeException("The PopulationAgentSource is not initialized properly."); + } + for (Person p : population.getPersons().values()) { + MobsimAgent agent = this.agentFactory.createMobsimAgentFromPerson(p); + qsim.insertAgentIntoMobsim(agent); + Plan plan = p.getSelectedPlan(); + Set seenModes = new HashSet(); + for (PlanElement planElement : plan.getPlanElements()) { + if (planElement instanceof Leg) { + Leg leg = (Leg) planElement; + if (this.mainModes.contains(leg.getMode())) { // only simulated modes get vehicles + if (!seenModes.contains(leg.getMode())) { // create one vehicle per simulated mode, put it on the home location + Id vehicleLink = findVehicleLink(p); + qsim.createAndParkVehicleOnLink(VehicleUtils.getFactory().createVehicle(p.getId(), modeVehicleTypes.get(leg.getMode())), vehicleLink); + seenModes.add(leg.getMode()); + } + } + } + } + } + } + + private Id findVehicleLink(Person p) { + // A more careful way to decide where this agent should have its vehicles created + // than to ask agent.getCurrentLinkId() after creation. + for (PlanElement planElement : p.getSelectedPlan().getPlanElements()) { + if (planElement instanceof Activity) { + Activity activity = (Activity) planElement; + if (activity.getLinkId() != null) { + return activity.getLinkId(); + } + } else if (planElement instanceof Leg) { + Leg leg = (Leg) planElement; + if (leg.getRoute().getStartLinkId() != null) { + return leg.getRoute().getStartLinkId(); + } + } + } + throw new RuntimeException("Don't know where to put a vehicle for this agent."); + } + + public void setModeVehicleTypes(Map modeVehicleTypes) { + this.modeVehicleTypes = modeVehicleTypes; + } + + public void agentSourceAdded(QSim qSim) { + this.qsim = qSim; + this.agentFactory = new ExperimentalBasicWithindayAgentFactory(qSim); + this.modeVehicleTypes = new HashMap(); + this.mainModes = qsim.getScenario().getConfig().getQSimConfigGroup().getMainMode(); + for (String mode : mainModes) { + modeVehicleTypes.put(mode, VehicleUtils.getDefaultVehicleType()); + } + } + + public void setPopulation(Population population) { + this.population = population; + } + +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimPreloadingControler.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimPreloadingControler.java new file mode 100644 index 000000000..7f3816d64 --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimPreloadingControler.java @@ -0,0 +1,27 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import org.matsim.core.controler.Controler; +import org.matsim.core.scenario.ScenarioImpl; +import org.matsim.population.algorithms.XY2Links; + +/** + * This is an extension of the MATSim controller that allows for scenario data + * preloading. Normally the scenario is loaded when the simulation starts. As + * data such as population, map is necessary beforehand this class has been + * introduced. + * + * @author Michal Kit + * + */ +public class MATSimPreloadingControler extends Controler { + + public MATSimPreloadingControler(String configFileName) { + super(configFileName); + loadData(); + XY2Links xy2Links = new XY2Links(this.getNetwork(), + ((ScenarioImpl) this.getScenario()) + .getActivityFacilities()); + xy2Links.run(getPopulation()); + } + +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimRouter.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimRouter.java new file mode 100644 index 000000000..3209c5bbb --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimRouter.java @@ -0,0 +1,184 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Node; +import org.matsim.api.core.v01.population.Leg; +import org.matsim.api.core.v01.population.PlanElement; +import org.matsim.core.api.experimental.facilities.Facility; +import org.matsim.core.controler.Controler; +import org.matsim.core.network.NetworkImpl; +import org.matsim.core.population.routes.NetworkRoute; +import org.matsim.core.router.TripRouter; +import org.matsim.core.router.TripRouterFactory; +import org.matsim.core.router.TripRouterFactoryImpl; +import org.matsim.core.router.util.DijkstraFactory; +import org.matsim.core.router.util.TravelTime; + +/** + * MATSim router. The class reuses the functionality available already in + * MATSim. + * + * @author Michal Kit + * + */ +public class MATSimRouter { + + private final Controler controler; + private final TripRouterFactory tripRouterFactory; + private final int routeCalculationOffset; + + public MATSimRouter(Controler controler, TravelTime travelTime, int routeCalculationOffset) { + this.tripRouterFactory = new WithinDayTripRouterFactory(controler, + travelTime); + this.controler = controler; + this.routeCalculationOffset = routeCalculationOffset; + } + + public Link findLinkById(Id id) { + return controler.getNetwork().getLinks().get(id); + } + + public Link findNearestLink(Coord coord) { + return ((NetworkImpl)controler.getNetwork()).getNearestLink(coord); + } + + public Link findNearestLinkRight(Coord coord) { + return ((NetworkImpl)controler.getNetwork()).getNearestRightEntryLink(coord); + } + + public Link findNearestLinkExactly(Coord coord) { + return ((NetworkImpl)controler.getNetwork()).getNearestLinkExactly(coord); + } + + public Node findNearestNode(Coord coord) { + return ((NetworkImpl)controler.getNetwork()).getNearestNode(coord); + } + + public Collection getNearestNodes(Coord coord, double distance) { + return ((NetworkImpl)controler.getNetwork()).getNearestNodes(coord, distance); + } + + public List route(Id from, Id to) { + return route(from, to, null); + } + + public List route(Id from, Id to, List currentRoute) { + List routePrefix = null; + Id newFrom; + if (currentRoute == null || currentRoute.isEmpty()) { + newFrom = from; + } else { + List truncatedCurrentRoute = new LinkedList<>(currentRoute); + int fromIndex = truncatedCurrentRoute.indexOf(from); + if (fromIndex > -1) { + truncatedCurrentRoute = truncatedCurrentRoute.subList(fromIndex, truncatedCurrentRoute.size()); + } + if (routeCalculationOffset < truncatedCurrentRoute.size()) { + fromIndex = Math.max(0, routeCalculationOffset-1); + } else { + fromIndex = truncatedCurrentRoute.size()-1; + } + routePrefix = truncatedCurrentRoute.subList(0, fromIndex + 1); + newFrom = truncatedCurrentRoute.get(fromIndex); + //System.out.println("from: "+from.toString()+" newFrom: " + newFrom.toString() + " to: " + to.toString()); + } + Link fromLink = controler.getNetwork().getLinks().get(newFrom); + Link toLink = controler.getNetwork().getLinks().get(to); + List calculatedRoute = route(fromLink, toLink); + //System.out.println("calculatedRoute: " + calculatedRoute.toString() + " prefix: " + ((routePrefix == null) ? "null" : routePrefix.toString())); + if (routePrefix != null && !routePrefix.isEmpty()) { + calculatedRoute.addAll(0, routePrefix); + } + return calculatedRoute; + } + + private List route(Link linkFrom, Link linkTo) { + TripRouter tr = tripRouterFactory.createTripRouter(); + List legs = tr.calcRoute("car", new LinkWrapper( + linkFrom), new LinkWrapper(linkTo), 0.0, null); + if (legs.size() == 0) { + throw new RuntimeException("Route calculation failed: " + + linkFrom.getId().toString() + " - " + + linkTo.getId().toString()); + } + Leg leg = (Leg) legs.get(0); + List route = new LinkedList<>(((NetworkRoute) leg.getRoute()).getLinkIds()); + if (!route.contains(linkTo.getId()) && !linkTo.equals(linkFrom)) + route.add(linkTo.getId()); + return route; + } + + public Map getLinks() { + return controler.getNetwork().getLinks(); + } + + public Link getLink(Id linkId) { + return controler.getNetwork().getLinks().get(linkId); + } + + public List getAdjacentLinks(Id linkId) { + Link link = controler.getNetwork().getLinks().get(linkId); + if (link == null) + return null; + Set outLinks = link.getToNode().getOutLinks().keySet(); + Set inLinks = link.getFromNode().getInLinks().keySet(); + List links = new LinkedList(); + links.addAll(inLinks); + links.addAll(outLinks); + return links; + } + + private static class LinkWrapper implements Facility { + + private final Link link; + + public LinkWrapper(Link link) { + this.link = link; + } + + public Coord getCoord() { + return link.getCoord(); + } + + public Id getId() { + throw new UnsupportedOperationException(); + } + + public Map getCustomAttributes() { + return null; + } + + public Id getLinkId() { + return link.getId(); + } + + } + + private static class WithinDayTripRouterFactory implements + TripRouterFactory { + + private final Controler controler; + private final TravelTime travelTime; + + public WithinDayTripRouterFactory(Controler controler, + TravelTime travelTime) { + this.controler = controler; + this.travelTime = travelTime; + } + + public TripRouter createTripRouter() { + return new TripRouterFactoryImpl(controler.getScenario(), + controler.getTravelDisutilityFactory(), travelTime, + new DijkstraFactory(), null).createTripRouter(); + } + + } +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimSimulationStepListener.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimSimulationStepListener.java new file mode 100644 index 000000000..1d75cb97a --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimSimulationStepListener.java @@ -0,0 +1,8 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import org.matsim.core.mobsim.framework.Mobsim; + +public interface MATSimSimulationStepListener { + + public void at(double seconds, Mobsim mobsim); +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimUpdater.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimUpdater.java new file mode 100644 index 000000000..b509ed740 --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/MATSimUpdater.java @@ -0,0 +1,7 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import java.util.Collection; + +public interface MATSimUpdater { + public void updateJDEECoAgents(Object input, Collection agents); +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/Simulation.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/Simulation.java new file mode 100644 index 000000000..a76874bd8 --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/Simulation.java @@ -0,0 +1,17 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; + +import cz.cuni.mff.d3s.deeco.timer.CurrentTimeProvider; + +public abstract class Simulation implements CurrentTimeProvider, + CallbackProvider { + + protected static final int MILLIS_IN_SECOND = 1000; + + public static double millisecondsToSeconds(long time) { + return time * 1.0 / MILLIS_IN_SECOND; + } + + public static long secondsToMilliseconds(double time) { + return Math.round(time * MILLIS_IN_SECOND); + } +} diff --git a/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/package-info.java b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/package-info.java new file mode 100644 index 000000000..f97f21f1c --- /dev/null +++ b/jdeeco-matsim-plugin/src/cz/cuni/mff/d3s/jdeeco/matsim/simulation/package-info.java @@ -0,0 +1,4 @@ +/** + * Ported sources from jDEECo 2 + */ +package cz.cuni.mff.d3s.jdeeco.matsim.simulation; \ No newline at end of file diff --git a/jdeeco-matsim-plugin/test/cz/cuni/mff/d3s/jdeeco/matsim/demo/convoy/OtherVehicleEnsemble.java b/jdeeco-matsim-plugin/test/cz/cuni/mff/d3s/jdeeco/matsim/demo/convoy/OtherVehicleEnsemble.java new file mode 100644 index 000000000..318626e8a --- /dev/null +++ b/jdeeco-matsim-plugin/test/cz/cuni/mff/d3s/jdeeco/matsim/demo/convoy/OtherVehicleEnsemble.java @@ -0,0 +1,36 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.demo.convoy; + + +import org.matsim.api.core.v01.Id; + +import cz.cuni.mff.d3s.deeco.annotations.Ensemble; +import cz.cuni.mff.d3s.deeco.annotations.In; +import cz.cuni.mff.d3s.deeco.annotations.KnowledgeExchange; +import cz.cuni.mff.d3s.deeco.annotations.Membership; +import cz.cuni.mff.d3s.deeco.annotations.Out; +import cz.cuni.mff.d3s.deeco.annotations.PeriodicScheduling; +import cz.cuni.mff.d3s.deeco.task.ParamHolder; + + +@Ensemble +@PeriodicScheduling(period=500) +public class OtherVehicleEnsemble { + + @Membership + public static boolean membership( + @In("member.id") String memberId, + @In("coord.id") String coordId) { +// System.out.println("membership: "+ memberId + " " + coordId); + return !(memberId.equals(coordId)); + } + + @KnowledgeExchange + public static void map( + @In("member.currentLink") Id memberLink, + @Out("coord.otherVehicleLink") ParamHolder coordOtherLink, + @In("member.id") String memberId, + @In("coord.id") String coordId) { +// System.out.println("exchange: "+ memberId + " " + coordId); + coordOtherLink.value = memberLink; + } +} diff --git a/jdeeco-matsim-plugin/test/cz/cuni/mff/d3s/jdeeco/matsim/demo/convoy/Vehicle.java b/jdeeco-matsim-plugin/test/cz/cuni/mff/d3s/jdeeco/matsim/demo/convoy/Vehicle.java new file mode 100644 index 000000000..dc732b3fc --- /dev/null +++ b/jdeeco-matsim-plugin/test/cz/cuni/mff/d3s/jdeeco/matsim/demo/convoy/Vehicle.java @@ -0,0 +1,182 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.demo.convoy; + +import java.util.List; + +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.Id; + +import cz.cuni.mff.d3s.deeco.annotations.Component; +import cz.cuni.mff.d3s.deeco.annotations.In; +import cz.cuni.mff.d3s.deeco.annotations.InOut; +import cz.cuni.mff.d3s.deeco.annotations.Local; +import cz.cuni.mff.d3s.deeco.annotations.Out; +import cz.cuni.mff.d3s.deeco.annotations.PeriodicScheduling; +import cz.cuni.mff.d3s.deeco.annotations.Process; +import cz.cuni.mff.d3s.deeco.logging.Log; +import cz.cuni.mff.d3s.deeco.task.ParamHolder; +import cz.cuni.mff.d3s.deeco.timer.CurrentTimeProvider; +import cz.cuni.mff.d3s.jdeeco.matsim.dataaccess.Actuator; +import cz.cuni.mff.d3s.jdeeco.matsim.dataaccess.ActuatorType; +import cz.cuni.mff.d3s.jdeeco.matsim.dataaccess.Sensor; +import cz.cuni.mff.d3s.jdeeco.matsim.dataaccess.SensorType; +import cz.cuni.mff.d3s.jdeeco.matsim.plugin.MATSimVehicle; +import cz.cuni.mff.d3s.jdeeco.matsim.simulation.MATSimRouter; + +@Component +public class Vehicle { + /** + * Id of the vehicle component. + */ + public String id; + + /** + * Link where the vehicle is currently at. + */ + public Id currentLink; + + /** + * Vehicle speed + */ + public Double speed; + + /** + * Position of the current link. + */ + public Coord position; + + public Id otherVehicleLink; + + /** + * Position of the destination + */ + public Id dstLinkId; + + /** + * Contains a list of link ids that lead to the destination. It is given to + * the MATSim to guide the vehicle which way it should go. + */ + @Local + public List route; + + @Local + public Actuator > routeActuator; + + @Local + public Actuator speedActuator; + + @Local + public Sensor currentLinkSensor; + + @Local + public MATSimRouter router; + + @Local + public CurrentTimeProvider clock; + + public Long curTime; + + public Vehicle(String id, Coord dst, MATSimVehicle vehiclePlugin) { + this.id = id; + + this.router = vehiclePlugin.getRouter(); + this.routeActuator = vehiclePlugin.getActuatorProvider().createActuator(ActuatorType.ROUTE); + this.speedActuator = vehiclePlugin.getActuatorProvider().createActuator(ActuatorType.SPEED); + this.currentLinkSensor = vehiclePlugin.getSensorProvider().createSensor(SensorType.CURRENT_LINK); + this.clock = vehiclePlugin.getTimer(); + this.dstLinkId = router.findNearestLink(dst).getId(); + } + + /** + * Periodically prints out the values of sensors and important values of the + * knowledge. + * + * This is also responsible for execution of vehicle monitoring calls. The monitoring + * calls reproduce dot description of vehicles positions and their relations. + */ + @Process + @PeriodicScheduling(period = 5000, order = 10) + public static void reportStatus( + @In("id") String id, + @In("currentLink") Id currentLink, + @In("position") Coord position, + @In("dstLinkId") Id dstLinkId, + @In("route") List route, + @In("clock") CurrentTimeProvider clock, + @In("router") MATSimRouter router, + @In("speed") Double speed, + @In("otherVehicleLink") Id otherVehicleLink) { + Log.d("Entry [" + id + "]:reportStatus"); + + System.out.format("%s %s, pos: %s, dst: %s, speed: %.0f, otherPos: %s%n", + formatTime(clock.getCurrentMilliseconds()), + id, + printPos(currentLink, router), + dstLinkId.toString(), + speed, + printPos(otherVehicleLink, router)); + } + + private static String printPos(Id linkId, MATSimRouter router) { + if(linkId == null) { + return "UNKNOWN"; + } + Coord coord = router.findLinkById(linkId).getCoord(); + return String.format("%s (%.0f, %.0f)", linkId.toString(), coord.getX(), coord.getY()); + } + + /** + * Periodically updates knowledge based on sensor readings. These knowledge + * fields are updated: currentLink, position, curTime. + */ + @Process + @PeriodicScheduling(period = 200, order = 1) + public static void updateSensors( + @In("id") String id, + @Out("currentLink") ParamHolder currentLinkHolder, + @Out("position") ParamHolder position, + @In("currentLinkSensor") Sensor currentLinkSensor, + @In("router") MATSimRouter router, + @In("clock") CurrentTimeProvider clock, + @Out("curTime") ParamHolder curTime) { + Log.d("Entry [" + id + "]:updateCurrentLink"); + currentLinkHolder.value = currentLinkSensor.read(); + position.value = router.getLink(currentLinkHolder.value).getCoord(); + curTime.value = clock.getCurrentMilliseconds(); + } + + /** + * Plans the route to the destination. + * + * This can operate with the leader which is followed or without. When the leader is set by road train or + * just by leader-follower relation the route to leader is used. When the leader is not available then the + * route to destination is used. + */ + @Process + @PeriodicScheduling(period = 2000, order = 4) + public static void planRouteAndDrive( + @In("id") String id, + @In("currentLink") Id currentLink, + @In("dstLinkId") Id dstLinkId, + @InOut("route") ParamHolder > route, + @In("routeActuator") Actuator > routeActuator, + @In("speedActuator") Actuator speedActuator, + @In("router") MATSimRouter router, + @Out("speed") ParamHolder speed) throws Exception { + + route.value = router.route(currentLink, dstLinkId, route.value); + + routeActuator.set(route.value); + } + + private static String formatTime(long ts) { + int msec = (int) (ts % 1000); + ts = ts / 1000; + int sec = (int) (ts % 60); + ts = ts / 60; + int min = (int) (ts % 60); + ts = ts / 60; + int hour = (int) ts; + + return String.format("<%02d:%02d:%02d.%03d>", hour, min, sec, msec); + } +} diff --git a/jdeeco-matsim-plugin/test/cz/cuni/mff/d3s/jdeeco/matsim/demo/convoy/VehicleTravelTest.java b/jdeeco-matsim-plugin/test/cz/cuni/mff/d3s/jdeeco/matsim/demo/convoy/VehicleTravelTest.java new file mode 100644 index 000000000..49d910907 --- /dev/null +++ b/jdeeco-matsim-plugin/test/cz/cuni/mff/d3s/jdeeco/matsim/demo/convoy/VehicleTravelTest.java @@ -0,0 +1,77 @@ +package cz.cuni.mff.d3s.jdeeco.matsim.demo.convoy; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; + +import java.io.IOException; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.contrib.java.lang.system.StandardOutputStreamLog; +import org.matsim.core.utils.geometry.CoordImpl; + +import cz.cuni.mff.d3s.deeco.annotations.processor.AnnotationProcessorException; +import cz.cuni.mff.d3s.deeco.runners.DEECoSimulation; +import cz.cuni.mff.d3s.deeco.runtime.DEECoException; +import cz.cuni.mff.d3s.deeco.runtime.DEECoNode; +import cz.cuni.mff.d3s.jdeeco.matsim.plugin.MATSimSimulation; +import cz.cuni.mff.d3s.jdeeco.matsim.plugin.MATSimVehicle; +import cz.cuni.mff.d3s.jdeeco.network.Network; +import cz.cuni.mff.d3s.jdeeco.network.device.BroadcastLoopback; +import cz.cuni.mff.d3s.jdeeco.network.l2.strategy.KnowledgeInsertingStrategy; +import cz.cuni.mff.d3s.jdeeco.publishing.DefaultKnowledgePublisher; + +/** + * Example of vehicles traveling across the map + * + * @author Vladimir Matena + * + */ +public class VehicleTravelTest { + @Rule + public final StandardOutputStreamLog log = new StandardOutputStreamLog(); + + public static void main(String[] args) throws AnnotationProcessorException, InterruptedException, DEECoException, + InstantiationException, IllegalAccessException, IOException { + new VehicleTravelTest().testTravel(); + } + + @Test + public void testTravel() throws AnnotationProcessorException, InterruptedException, DEECoException, + InstantiationException, IllegalAccessException, IOException { + MATSimSimulation matSim = new MATSimSimulation("input/config.xml"); + + // Create main application container + DEECoSimulation realm = new DEECoSimulation(matSim.getTimer()); + + // Add MATSim plug-in for all nodes + realm.addPlugin(matSim); + + // Configure loop-back networking for all nodes + realm.addPlugin(new BroadcastLoopback()); + realm.addPlugin(Network.class); + realm.addPlugin(DefaultKnowledgePublisher.class); + realm.addPlugin(KnowledgeInsertingStrategy.class); + + // Node hosting vehicle A + MATSimVehicle agentA = new MATSimVehicle(0, 0); // MATSim agent with start position + DEECoNode nodeA = realm.createNode(42, agentA); // DEECO node with Id and agent as plug-in + Vehicle vehicleA = new Vehicle("Vehicle A", new CoordImpl(100000, 100000), agentA); // DEECO component controlling the vehicle + nodeA.deployComponent(vehicleA); + nodeA.deployEnsemble(OtherVehicleEnsemble.class); + + // Node hosting vehicle B + MATSimVehicle agentB = new MATSimVehicle(0, 100000); // MATSim agent with start position + DEECoNode nodeB = realm.createNode(45, agentB); // DEECO node with Id and agent as plug-in + Vehicle vehicleB = new Vehicle("Vehicle B", new CoordImpl(100000, 100000), agentB); // DEECO component controlling the vehicle + nodeB.deployComponent(vehicleB); + nodeB.deployEnsemble(OtherVehicleEnsemble.class); + + // Simulate for specified time + realm.start(7 * 60000); + + // Check both cars reached the destination and know about each other + assertThat(log.getLog(), containsString("Vehicle A, pos: 4410 (1995, 2000), dst: 4410, speed: , otherPos: 4410 (1995, 2000)")); + assertThat(log.getLog(), containsString("Vehicle B, pos: 4410 (1995, 2000), dst: 4410, speed: , otherPos: 4410 (1995, 2000)")); + } +} diff --git a/jdeeco-matsim-plugin/test/logging.properties b/jdeeco-matsim-plugin/test/logging.properties new file mode 100644 index 000000000..c942581d6 --- /dev/null +++ b/jdeeco-matsim-plugin/test/logging.properties @@ -0,0 +1,16 @@ +handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler +java.util.logging.ConsoleHandler.level=WARNING +java.util.logging.ConsoleHandler.formatter=cz.cuni.mff.d3s.deeco.logging.SimpleColorFormatter + +java.util.logging.FileHandler.level=INFO +java.util.logging.FileHandler.pattern=logs/jdeeco.log + +# Write 10MB before rotating this file +java.util.logging.FileHandler.limit=10000000 +java.util.logging.FileHandler.append=true + +# Number of rotating files to be used +java.util.logging.FileHandler.count=4 +java.util.logging.FileHandler.formatter=cz.cuni.mff.d3s.deeco.logging.SimpleFormatter + +.level=INFO \ No newline at end of file