Commit a9baf33b authored by Björn Richerzhagen's avatar Björn Richerzhagen
Browse files

Merge remote-tracking branch 'simonstrator/tm/vehicular-services'

parents 705984e5 f476dae3
...@@ -27,7 +27,7 @@ import java.io.IOException; ...@@ -27,7 +27,7 @@ import java.io.IOException;
/** /**
* Represents the header of a bitmap. * Represents the header of a bitmap.
* *
* @author Andr Mink, Sebastian Kaune * @author Andr Mink, Sebastian Kaune
*/ */
public class BitmapHeader { public class BitmapHeader {
public int nsize; // Size of file public int nsize; // Size of file
......
...@@ -32,7 +32,7 @@ import java.util.ArrayList; ...@@ -32,7 +32,7 @@ import java.util.ArrayList;
* colorTable of the bitmap. Currently, there are only 8bit bitmaps (256 colors) * colorTable of the bitmap. Currently, there are only 8bit bitmaps (256 colors)
* supported. * supported.
* *
* @author Andr Mink, Sebastian Kaune * @author Andr Mink, Sebastian Kaune
*/ */
public class BitmapLoader { public class BitmapLoader {
public int[][] cartesianSpace; public int[][] cartesianSpace;
......
...@@ -3584,7 +3584,7 @@ public class regionName { ...@@ -3584,7 +3584,7 @@ public class regionName {
if (country_code.equals("FI") == true) { if (country_code.equals("FI") == true) {
switch (region_code2) { switch (region_code2) {
case 1: case 1:
name = "land"; name = "land";
break; break;
case 6: case 6:
name = "Lapland"; name = "Lapland";
...@@ -6683,7 +6683,7 @@ public class regionName { ...@@ -6683,7 +6683,7 @@ public class regionName {
name = "Aqmola"; name = "Aqmola";
break; break;
case 4: case 4:
name = "Aqtbe"; name = "Aqtbe";
break; break;
case 5: case 5:
name = "Astana"; name = "Astana";
...@@ -7071,7 +7071,7 @@ public class regionName { ...@@ -7071,7 +7071,7 @@ public class regionName {
name = "Bauskas"; name = "Bauskas";
break; break;
case 5: case 5:
name = "Csu"; name = "Csu";
break; break;
case 6: case 6:
name = "Daugavpils"; name = "Daugavpils";
...@@ -7086,7 +7086,7 @@ public class regionName { ...@@ -7086,7 +7086,7 @@ public class regionName {
name = "Gulbenes"; name = "Gulbenes";
break; break;
case 10: case 10:
name = "Jkabpils"; name = "Jkabpils";
break; break;
case 11: case 11:
name = "Jelgava"; name = "Jelgava";
...@@ -7098,16 +7098,16 @@ public class regionName { ...@@ -7098,16 +7098,16 @@ public class regionName {
name = "Jurmala"; name = "Jurmala";
break; break;
case 14: case 14:
name = "Krslavas"; name = "Krslavas";
break; break;
case 15: case 15:
name = "Kuldigas"; name = "Kuldigas";
break; break;
case 16: case 16:
name = "Liepja"; name = "Liepja";
break; break;
case 17: case 17:
name = "Liepjas"; name = "Liepjas";
break; break;
case 18: case 18:
name = "Limbazu"; name = "Limbazu";
...@@ -7125,10 +7125,10 @@ public class regionName { ...@@ -7125,10 +7125,10 @@ public class regionName {
name = "Preilu"; name = "Preilu";
break; break;
case 23: case 23:
name = "Rzekne"; name = "Rzekne";
break; break;
case 24: case 24:
name = "Rzeknes"; name = "Rzeknes";
break; break;
case 25: case 25:
name = "Riga"; name = "Riga";
......
...@@ -662,7 +662,7 @@ public class DefaultConfigurator implements Configurator { ...@@ -662,7 +662,7 @@ public class DefaultConfigurator implements Configurator {
} }
public String parseValue(String value) { public String parseValue(String value) {
if (value.trim().startsWith(CONFIG_VARIABLE_PREFIX_TAG)) { if (value.trim().startsWith(CONFIG_VARIABLE_PREFIX_TAG) && !value.trim().startsWith(CONFIG_VARIABLE_PREFIX_TAG + "{")) {
int posDollar = value.indexOf(CONFIG_VARIABLE_PREFIX_TAG); int posDollar = value.indexOf(CONFIG_VARIABLE_PREFIX_TAG);
String varName = value.substring(posDollar + 1, value.length()); String varName = value.substring(posDollar + 1, value.length());
value = variables.get(varName); value = variables.get(varName);
......
...@@ -2,17 +2,17 @@ ...@@ -2,17 +2,17 @@
* Copyright (c) 2005-2011 KOM - Multimedia Communications Lab * Copyright (c) 2005-2011 KOM - Multimedia Communications Lab
* *
* This file is part of PeerfactSim.KOM. * This file is part of PeerfactSim.KOM.
* *
* PeerfactSim.KOM is free software: you can redistribute it and/or modify * PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* any later version. * any later version.
* *
* PeerfactSim.KOM is distributed in the hope that it will be useful, * PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>. * along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
* *
...@@ -40,11 +40,11 @@ import de.tudarmstadt.maki.simonstrator.api.component.core.TimeComponent; ...@@ -40,11 +40,11 @@ import de.tudarmstadt.maki.simonstrator.api.component.core.TimeComponent;
* generated events in order to provide valid experiments. The duration of each * generated events in order to provide valid experiments. The duration of each
* experiment is controlled by the scheduler and the parameters defined by the * experiment is controlled by the scheduler and the parameters defined by the
* Application. * Application.
* *
* @author Sebastian Kaune * @author Sebastian Kaune
*/ */
public class Scheduler implements EventHandler, public class Scheduler implements EventHandler,
SchedulerComponent, TimeComponent { SchedulerComponent, TimeComponent {
// Flag to allow the compiler to remove the unneeded debug code // Flag to allow the compiler to remove the unneeded debug code
private static final boolean DEBUG_CODE = false; private static final boolean DEBUG_CODE = false;
...@@ -96,7 +96,7 @@ public class Scheduler implements EventHandler, ...@@ -96,7 +96,7 @@ public class Scheduler implements EventHandler,
/** /**
* Constructs a new scheduler instance using a calendar queue. If desired, * Constructs a new scheduler instance using a calendar queue. If desired,
* status events about the progress of the simulation will be plotted. * status events about the progress of the simulation will be plotted.
* *
* @param statusEvent * @param statusEvent
* the flag which speficies if status events will be plotted * the flag which speficies if status events will be plotted
*/ */
...@@ -158,7 +158,7 @@ public class Scheduler implements EventHandler, ...@@ -158,7 +158,7 @@ public class Scheduler implements EventHandler,
/** /**
* Wake up thread safe and insert event immediately. * Wake up thread safe and insert event immediately.
* *
* @param content * @param content
* the content * the content
* @param handler * @param handler
...@@ -198,17 +198,17 @@ public class Scheduler implements EventHandler, ...@@ -198,17 +198,17 @@ public class Scheduler implements EventHandler,
} }
Monitor.log(Scheduler.class, Level.INFO, Monitor.log(Scheduler.class, Level.INFO,
"Simulated realtime: " + Time.getFormattedTime() "Simulated realtime: " + Time.getFormattedTime()
+ " - End of simulation.\n Scheduler processed in total " + " - End of simulation.\n Scheduler processed in total "
+ this.processedEventCounter + " events with " + this.processedEventCounter + " events with "
+ this.eventQueue.size() + this.eventQueue.size()
+ " unprocessed events still in queue"); + " unprocessed events still in queue");
} }
/** /**
* Sets the end time at which the simulation framework will finish at the * Sets the end time at which the simulation framework will finish at the
* latest the simulation , irrespective if there are still unprocessed * latest the simulation , irrespective if there are still unprocessed
* events in the event queue. * events in the event queue.
* *
* @param endTime * @param endTime
* point in time at which the simulator will finish at the latest * point in time at which the simulator will finish at the latest
*/ */
...@@ -223,7 +223,7 @@ public class Scheduler implements EventHandler, ...@@ -223,7 +223,7 @@ public class Scheduler implements EventHandler,
/** /**
* Process the next event from the event queue. * Process the next event from the event queue.
* *
* @return whether an event was processed * @return whether an event was processed
*/ */
synchronized private boolean processNextEvent() { synchronized private boolean processNextEvent() {
...@@ -252,9 +252,9 @@ public class Scheduler implements EventHandler, ...@@ -252,9 +252,9 @@ public class Scheduler implements EventHandler,
} }
assert (nextEvent.getSimulationTime() >= currentTime) : "Next event: " assert (nextEvent.getSimulationTime() >= currentTime) : "Next event: "
+ nextEvent.getSimulationTime() + nextEvent.getSimulationTime()
+ ", but current " + ", but current "
+ currentTime + "."; + currentTime + ".";
if (nextEvent.getSimulationTime() <= newRoundsCurrentTime) { if (nextEvent.getSimulationTime() <= newRoundsCurrentTime) {
...@@ -273,7 +273,7 @@ public class Scheduler implements EventHandler, ...@@ -273,7 +273,7 @@ public class Scheduler implements EventHandler,
if (realEvent.schedulerType == TYPE_END) if (realEvent.schedulerType == TYPE_END)
return false; return false;
synchronized (this.eventQueue) { synchronized (this.eventQueue) {
if (this.eventQueue.peek().getSimulationTime() < newRoundsCurrentTime) { if (this.eventQueue.peek().getSimulationTime() < newRoundsCurrentTime) {
unhandledRegularEventsInPast = true; unhandledRegularEventsInPast = true;
...@@ -310,9 +310,9 @@ public class Scheduler implements EventHandler, ...@@ -310,9 +310,9 @@ public class Scheduler implements EventHandler,
} }
assert (peekedEvent.getSimulationTime() >= currentTime) : "Next event: " assert (peekedEvent.getSimulationTime() >= currentTime) : "Next event: "
+ peekedEvent.getSimulationTime() + peekedEvent.getSimulationTime()
+ ", but current " + ", but current "
+ currentTime + "."; + currentTime + ".";
if (peekedEvent.getSimulationTime() > currentTime) { if (peekedEvent.getSimulationTime() > currentTime) {
...@@ -326,12 +326,12 @@ public class Scheduler implements EventHandler, ...@@ -326,12 +326,12 @@ public class Scheduler implements EventHandler,
/* /*
* ATTENTION: Magic happening here! * ATTENTION: Magic happening here!
* *
* Correct for uncertainties of going to real sleep. * Correct for uncertainties of going to real sleep.
*/ */
final long SLEEP_CORRECTION_FACTOR = 400; final long SLEEP_CORRECTION_FACTOR = 400;
final long realTime_errorMs = System.currentTimeMillis() final long realTime_errorMs = System.currentTimeMillis()
- 0 /* Starttime */ - 0 /* Starttime */
- (currentTime / Time.MILLISECOND); - (currentTime / Time.MILLISECOND);
final long realTime_correctedTimeToWaitMs = realTime_timeToWaitMs final long realTime_correctedTimeToWaitMs = realTime_timeToWaitMs
- (realTime_errorMs / SLEEP_CORRECTION_FACTOR); - (realTime_errorMs / SLEEP_CORRECTION_FACTOR);
...@@ -379,8 +379,8 @@ public class Scheduler implements EventHandler, ...@@ -379,8 +379,8 @@ public class Scheduler implements EventHandler,
final SchedulerEvent realEvent = this.eventQueue.remove(); final SchedulerEvent realEvent = this.eventQueue.remove();
assert (realEvent.getSimulationTime() >= currentTime) : "Next event: " assert (realEvent.getSimulationTime() >= currentTime) : "Next event: "
+ realEvent.getSimulationTime() + ", but current " + realEvent.getSimulationTime() + ", but current "
+ currentTime + "."; + currentTime + ".";
if (timeSkew > 0) { if (timeSkew > 0) {
/* /*
...@@ -392,7 +392,7 @@ public class Scheduler implements EventHandler, ...@@ -392,7 +392,7 @@ public class Scheduler implements EventHandler,
if (timeToWait > 0) { if (timeToWait > 0) {
Monitor.log(Scheduler.class, Level.DEBUG, Monitor.log(Scheduler.class, Level.DEBUG,
"Scheduler sleeping: " + timeToWait / 1000 "Scheduler sleeping: " + timeToWait / 1000
+ " milliseconds"); + " milliseconds");
try { try {
Thread.sleep((long) ((timeToWait / 1000) / timeSkew)); Thread.sleep((long) ((timeToWait / 1000) / timeSkew));
...@@ -437,7 +437,7 @@ public class Scheduler implements EventHandler, ...@@ -437,7 +437,7 @@ public class Scheduler implements EventHandler,
/** /**
* Return whether event queue is empty. * Return whether event queue is empty.
* *
* @return whether event queue is empty. * @return whether event queue is empty.
*/ */
public boolean isEmpty() { public boolean isEmpty() {
...@@ -446,16 +446,17 @@ public class Scheduler implements EventHandler, ...@@ -446,16 +446,17 @@ public class Scheduler implements EventHandler,
/** /**
* Returns the current time of the scheduler * Returns the current time of the scheduler
* *
* @return current scheduler time * @return current scheduler time
*/ */
@Override
public long getCurrentTime() { public long getCurrentTime() {
return currentTime; return currentTime;
} }
/** /**
* Returns the end time of the scheduler * Returns the end time of the scheduler
* *
* @return * @return
*/ */
public long getEndTime() { public long getEndTime() {
...@@ -475,7 +476,7 @@ public class Scheduler implements EventHandler, ...@@ -475,7 +476,7 @@ public class Scheduler implements EventHandler,
/** /**
* Method for JUnit tests in order to verify the correctness * Method for JUnit tests in order to verify the correctness
* *
* @return number of events in event queue. * @return number of events in event queue.
*/ */
public int getEventQueueSize() { public int getEventQueueSize() {
...@@ -483,7 +484,7 @@ public class Scheduler implements EventHandler, ...@@ -483,7 +484,7 @@ public class Scheduler implements EventHandler,
} }
protected static final class SchedulerEvent implements protected static final class SchedulerEvent implements
Comparable<SchedulerEvent> { Comparable<SchedulerEvent> {
protected final int schedulerType; protected final int schedulerType;
...@@ -494,9 +495,9 @@ public class Scheduler implements EventHandler, ...@@ -494,9 +495,9 @@ public class Scheduler implements EventHandler,
protected final Object data; protected final Object data;
protected long simTime; protected long simTime;
protected long globalOrderIdx; protected long globalOrderIdx;
protected static long globalOrderCounter = 0; protected static long globalOrderCounter = 0;
protected SchedulerEvent(Object data, long simTime, protected SchedulerEvent(Object data, long simTime,
...@@ -518,6 +519,7 @@ public class Scheduler implements EventHandler, ...@@ -518,6 +519,7 @@ public class Scheduler implements EventHandler,
return simTime; return simTime;
} }
@Override
public int compareTo(SchedulerEvent o) { public int compareTo(SchedulerEvent o) {
int comp = Double.compare(this.simTime, o.simTime); int comp = Double.compare(this.simTime, o.simTime);
return comp == 0 ? Double.compare(this.globalOrderIdx, o.globalOrderIdx) : comp; return comp == 0 ? Double.compare(this.globalOrderIdx, o.globalOrderIdx) : comp;
...@@ -530,7 +532,7 @@ public class Scheduler implements EventHandler, ...@@ -530,7 +532,7 @@ public class Scheduler implements EventHandler,
/** /**
* Returns wheather the scheduler is running in realTime mode or not. * Returns wheather the scheduler is running in realTime mode or not.
* *
* @return the real time * @return the real time
*/ */
public boolean getRealTime() { public boolean getRealTime() {
...@@ -540,7 +542,7 @@ public class Scheduler implements EventHandler, ...@@ -540,7 +542,7 @@ public class Scheduler implements EventHandler,
/** /**
* a flag for slowing down the simulation down to real time. This flag only * a flag for slowing down the simulation down to real time. This flag only
* makes sense for simulations which run faster than real time * makes sense for simulations which run faster than real time
* *
* @param realTime * @param realTime
* flag for switching the scheduler to real time mode * flag for switching the scheduler to real time mode
*/ */
...@@ -556,7 +558,7 @@ public class Scheduler implements EventHandler, ...@@ -556,7 +558,7 @@ public class Scheduler implements EventHandler,
/** /**
* method for setting the time skew. A time skew of 100 means, that the * method for setting the time skew. A time skew of 100 means, that the
* simulation runs 100 times faster than real time * simulation runs 100 times faster than real time
* *
* @param timeSkew * @param timeSkew
* the time skew * the time skew
*/ */
...@@ -567,10 +569,14 @@ public class Scheduler implements EventHandler, ...@@ -567,10 +569,14 @@ public class Scheduler implements EventHandler,
} }
} }
public double getTimeSkew() {
return timeSkew;
}
/** /**
* Sets the simulation speed lock, changes in setRealTime or setTimeSkew * Sets the simulation speed lock, changes in setRealTime or setTimeSkew
* will not apply while the lock is set. * will not apply while the lock is set.
* *
* @param locked * @param locked
* the new simulation speed locked * the new simulation speed locked
*/ */
...@@ -593,7 +599,7 @@ public class Scheduler implements EventHandler, ...@@ -593,7 +599,7 @@ public class Scheduler implements EventHandler,
/** /**
* The comparator * The comparator
* *
* @author Bjoern Richerzhagen * @author Bjoern Richerzhagen
* @version 1.0, 05.03.2012 * @version 1.0, 05.03.2012
*/ */
......
...@@ -2,17 +2,17 @@ ...@@ -2,17 +2,17 @@
* Copyright (c) 2005-2011 KOM - Multimedia Communications Lab * Copyright (c) 2005-2011 KOM - Multimedia Communications Lab
* *
* This file is part of PeerfactSim.KOM. * This file is part of PeerfactSim.KOM.
* *
* PeerfactSim.KOM is free software: you can redistribute it and/or modify * PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* any later version. * any later version.
* *
* PeerfactSim.KOM is distributed in the hope that it will be useful, * PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>. * along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
* *
...@@ -56,11 +56,11 @@ import de.tudarmstadt.maki.simonstrator.api.component.core.RandomGeneratorCompon ...@@ -56,11 +56,11 @@ import de.tudarmstadt.maki.simonstrator.api.component.core.RandomGeneratorCompon
/** /**
* Concrete implementation of a simulator which can be used to run a simulation * Concrete implementation of a simulator which can be used to run a simulation
* by calling the main method in the SimulatorRunner class. * by calling the main method in the SimulatorRunner class.
* *
* @author Sebastian Kaune * @author Sebastian Kaune
* @author Konstantin Pussep * @author Konstantin Pussep
* @version 3.0, 11/29/2007 * @version 3.0, 11/29/2007
* *
*/ */
public class Simulator implements RandomGeneratorComponent, GlobalComponent { public class Simulator implements RandomGeneratorComponent, GlobalComponent {
...@@ -68,7 +68,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent { ...@@ -68,7 +68,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
* These constant should be ALWAYS used for virtual time calculations. * These constant should be ALWAYS used for virtual time calculations.
*/ */
public final static double NANOSECOND_UNIT = 1E-3d; public final static double NANOSECOND_UNIT = 1E-3d;
/** /**
* These constant should be ALWAYS used for virtual time calculations. * These constant should be ALWAYS used for virtual time calculations.
*/ */
...@@ -130,7 +130,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent { ...@@ -130,7 +130,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
/** /**
* This class is singleton, so use getInstance() method to obtain a * This class is singleton, so use getInstance() method to obtain a
* reference to it. * reference to it.
* *
*/ */
private Simulator() { private Simulator() {
singleton = this; singleton = this;
...@@ -145,7 +145,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent { ...@@ -145,7 +145,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
/** /**
* Returns the single instance of the SimulationFramework * Returns the single instance of the SimulationFramework
* *
* @return the SimulationFramework * @return the SimulationFramework
*/ */
public static Simulator getInstance() { public static Simulator getInstance() {
...@@ -158,10 +158,10 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent { ...@@ -158,10 +158,10 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
scheduler.reset(); scheduler.reset();
} }
/** /**
* Set the scenario (protocol stack, network topology etc.) which will be * Set the scenario (protocol stack, network topology etc.) which will be
* used to run the simulation. * used to run the simulation.
* *
* @param scenario * @param scenario
* simulation scenario to be used * simulation scenario to be used
*/ */
...@@ -172,7 +172,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent { ...@@ -172,7 +172,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
/** /**
* Returns the scenario used to run the simulation. * Returns the scenario used to run the simulation.
* *
* @return * @return
*/ */
public Scenario getScenario() { public Scenario getScenario() {
...@@ -181,7 +181,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent { ...@@ -181,7 +181,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
/** /**
* Only for internal use * Only for internal use
* *
* @return * @return
*/ */
public static Scheduler getScheduler() { public static Scheduler getScheduler() {
...@@ -195,35 +195,35 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent { ...@@ -195,35 +195,35 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
/** /**
* This method will run the simulation using the previously set scenario * This method will run the simulation using the previously set scenario
* data. * data.
* *
*/ */
public void start(boolean throwExceptions) { public void start(boolean throwExceptions) {
checkRunning(); checkRunning();
Monitor.log(Simulator.class, Level.INFO, "Prepare Scenario ..."); Monitor.log(Simulator.class, Level.INFO, "Prepare Scenario ...");
this.scenario.prepare(); this.scenario.prepare();
Monitor.log(Simulator.class, Level.INFO, "Prepare Scenario ..." Monitor.log(Simulator.class, Level.INFO, "Prepare Scenario ..."
+ getSeed()); + getSeed());
/* Real World Starting Time: /* Real World Starting Time:
* Block till we're allowed to start. * Block till we're allowed to start.
*/ */
if( realWorldStartTime != null ) { if( realWorldStartTime != null ) {
try { try {
//final Date now = new Date(); //final Date now = new Date();
final Date now = NTPClient.getDate(); final Date now = NTPClient.getDate();
final long waitFor = realWorldStartTime.getTime() - now.getTime(); final long waitFor = realWorldStartTime.getTime() - now.getTime();
Thread.sleep(waitFor); Thread.sleep(waitFor);
} catch (InterruptedException e) { } catch (InterruptedException e) {
// //
} }
} }
startTime = System.currentTimeMillis(); startTime = System.currentTimeMillis();
Monitor.log(Simulator.class, Level.INFO, "Simulation started..."); Monitor.log(Simulator.class, Level.INFO, "Simulation started...");
this.running = true; this.running = true;
...@@ -282,53 +282,53 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent { ...@@ -282,53 +282,53 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
/** /**
* Configure simulation from an XML file. * Configure simulation from an XML file.
* *
* @param configFile * @param configFile
* XML file with the configuration data. * XML file with the configuration data.
* @param variables * @param variables
* the variables which are specified in the XML file with the * the variables which are specified in the XML file with the
* configuarion data. * configuarion data.
*/ */
public void configure(String configFile, Map<String, String> variables, Map<String, String> modifiedVariables, List<String> variations) { public void configure(String configFile, Map<String, String> variables, Map<String, String> modifiedVariables, List<String> variations) {
// TODO create a class, that contains general informations of the // TODO create a class, that contains general informations of the
// simulation, which can be accessed from every component during a // simulation, which can be accessed from every component during a
// simulation. This can be seen as an alternative to implementing the // simulation. This can be seen as an alternative to implementing the
// Composable interface // Composable interface
if (configFile.endsWith(".xml")) { if (configFile.endsWith(".xml")) {
this.defaultConfigurator = new DefaultConfigurator(configFile); this.defaultConfigurator = new DefaultConfigurator(configFile);
defaultConfigurator.setVariables(variables); defaultConfigurator.setVariables(variables);
} else { } else {
SimCfgConfigurator simCfgConfigurator = new SimCfgConfigurator(configFile); SimCfgConfigurator simCfgConfigurator = new SimCfgConfigurator(configFile);
simCfgConfigurator.applyVariations(variations); simCfgConfigurator.applyVariations(variations);
simCfgConfigurator.setVariables(modifiedVariables); simCfgConfigurator.setVariables(modifiedVariables);
this.defaultConfigurator = simCfgConfigurator; this.defaultConfigurator = simCfgConfigurator;
} }
this.defaultConfigurator.register(Configurator.CORE, this); this.defaultConfigurator.register(Configurator.CORE, this);
this.defaultConfigurator.configureAll(); this.defaultConfigurator.configureAll();
// The next steps are only required for the xml version. // The next steps are only required for the xml version.
// SimCfg will execute them in the configurator // SimCfg will execute them in the configurator
if (configFile.endsWith(".xml")) { if (configFile.endsWith(".xml")) {
ScenarioFactory scenarioBuilder = (ScenarioFactory) this.defaultConfigurator.getConfigurable(Configurator.SCENARIO_TAG); ScenarioFactory scenarioBuilder = (ScenarioFactory) this.defaultConfigurator.getConfigurable(Configurator.SCENARIO_TAG);
if (scenarioBuilder == null) if (scenarioBuilder == null)
throw new ConfigurationException( throw new ConfigurationException(
"No scenario builder specified in the configuration file. Nothing to do."); "No scenario builder specified in the configuration file. Nothing to do.");
Scenario scenario = scenarioBuilder.createScenario(); Scenario scenario = scenarioBuilder.createScenario();
setScenario(scenario); setScenario(scenario);
} }
} }
/** /**
* Returns the seed used within a simulation run. * Returns the seed used within a simulation run.
* *
* @return the predefined seed * @return the predefined seed
* *
*/ */
public static long getSeed() { public static long getSeed() {
return seed; return seed;
...@@ -337,7 +337,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent { ...@@ -337,7 +337,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
/** /**
* This method sets the seed of the global random generator which can be * This method sets the seed of the global random generator which can be
* obtained using the static getRandom()-method. * obtained using the static getRandom()-method.
* *
* @param seed * @param seed
* the seed to configure the global random generator * the seed to configure the global random generator
*/ */
...@@ -356,53 +356,53 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent { ...@@ -356,53 +356,53 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
throw new IllegalStateException("Simulator is already running."); throw new IllegalStateException("Simulator is already running.");
} }
/** /**
* This method provides a newly created random generator, configured * This method provides a newly created random generator, configured
* with the specified seed of the simulator. This method should be preferred * with the specified seed of the simulator. This method should be preferred
* over the deprecated @{link getRandom}. * over the deprecated @{link getRandom}.
* *
* <b>Notes:</b> * <b>Notes:</b>
* Doing so will prevent components from influencing each other, thus creating * Doing so will prevent components from influencing each other, thus creating
* reproducible results while allowing different compositions of components. * reproducible results while allowing different compositions of components.
* *
* The method allows the use of an object as source. This is to allow the use in * The method allows the use of an object as source. This is to allow the use in
* different situations: * different situations:
* 1. Random generators belonging to a single component should pass the class * 1. Random generators belonging to a single component should pass the class
* object of that component to this method. * object of that component to this method.
* 2. Components that are always loaded during a simulation can use the * 2. Components that are always loaded during a simulation can use the
* Simulator.class object for a system wide random generator like {@link #getRandom()} * Simulator.class object for a system wide random generator like {@link #getRandom()}
* provided. * provided.
* 3. Utility classes that are loaded by many different components should use * 3. Utility classes that are loaded by many different components should use
* a reference to themselves to avoid transitive dependencies on the same random * a reference to themselves to avoid transitive dependencies on the same random
* generator throughout different components. * generator throughout different components.
* This approach will provide way to to configure different seeds for specific class * This approach will provide way to to configure different seeds for specific class
* objects. This will allow component specific seeds and, e.g., the transfer of movement * objects. This will allow component specific seeds and, e.g., the transfer of movement
* behavior from one configured scenario to another. * behavior from one configured scenario to another.
* *
* @param source The source that requires the random generator (component class object is preferred) * @param source The source that requires the random generator (component class object is preferred)
* @param salt Added to the default seed, should be bound * @param salt Added to the default seed, should be bound
* @return The random generator for the given source * @return The random generator for the given source
*/ */
@Override @Override
public Random getRandom(Object source) { public Random getRandom(Object source) {
if (randomGenerators.containsKey(source)) { if (randomGenerators.containsKey(source)) {
return randomGenerators.get(source); return randomGenerators.get(source);
} else { } else {
long thisSeed = source.toString().hashCode() + 31 long thisSeed = source.toString().hashCode() + 31
* seed; * seed;
Monitor.log(Simulator.class, Level.INFO, Monitor.log(Simulator.class, Level.INFO,
"Created a new Random Source for %s with seed %d", source, "Created a new Random Source for %s with seed %d", source,
thisSeed); thisSeed);
Random randomGenerator = new Random(thisSeed); Random randomGenerator = new Random(thisSeed);
randomGenerators.put(source, randomGenerator); randomGenerators.put(source, randomGenerator);
return randomGenerator; return randomGenerator;
} }
} }
/** /**
* Returns the current simulation unit value. * Returns the current simulation unit value.
* *
* @return the current simulation unit value * @return the current simulation unit value
*/ */
public static long getCurrentTime() { public static long getCurrentTime() {
...@@ -411,17 +411,17 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent { ...@@ -411,17 +411,17 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
/** /**
* Returns the start time of the simulation. * Returns the start time of the simulation.
* *
* @return * @return
*/ */
public static long getStartTime() { public static long getStartTime() {
return singleton.startTime; return singleton.startTime;
} }
/** /**
* Returns the end time of the simulation. * Returns the end time of the simulation.
* *
* @return * @return
*/ */
public static long getEndTime() { public static long getEndTime() {
...@@ -432,7 +432,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent { ...@@ -432,7 +432,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
* Sets the end time at which the simulation framework will finish at the * Sets the end time at which the simulation framework will finish at the
* latest the simulation , irrespective if there are still unprocessed * latest the simulation , irrespective if there are still unprocessed
* events in the event queue. * events in the event queue.
* *
* @param endTime * @param endTime
* point in time at which the simular will finish at the latest * point in time at which the simular will finish at the latest
*/ */
...@@ -450,7 +450,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent { ...@@ -450,7 +450,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
* in turn will save the state in a static variable. Is this flag set * in turn will save the state in a static variable. Is this flag set
* to true the MeasurementDAO will return from every method before * to true the MeasurementDAO will return from every method before
* doing any work. * doing any work.
* *
* @param inactive * @param inactive
*/ */
public void setDatabaseInactive(boolean inactive) { public void setDatabaseInactive(boolean inactive) {
...@@ -463,25 +463,25 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent { ...@@ -463,25 +463,25 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
} }
} }
/** /**
* Overrides the database name provided in the persistence.xml. * Overrides the database name provided in the persistence.xml.
* *
* As the DAO class only provides static methods and is not a singleton it * As the DAO class only provides static methods and is not a singleton it
* cannot be accessed through the config file otherwise. * cannot be accessed through the config file otherwise.
* *
* @param database * @param database
* @deprecated use the MetricOutputDAO instead to do all relevant * @deprecated use the MetricOutputDAO instead to do all relevant
* configuration! * configuration!
*/ */
@Deprecated @Deprecated
public void setDatabase(String database) { public void setDatabase(String database) {
DAO.database = database; DAO.database = database;
} }
/** /**
* Can be used to format the absolute simulation time (current, past or * Can be used to format the absolute simulation time (current, past or
* future) into human-readable format: (h:m:s:ms). * future) into human-readable format: (h:m:s:ms).
* *
* @param time * @param time
* - absolute simulation time like the one obtained via * - absolute simulation time like the one obtained via
* getCurrentTime(); * getCurrentTime();
...@@ -494,7 +494,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent { ...@@ -494,7 +494,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
/** /**
* Specifies how often the scheduler will printout the current simulation * Specifies how often the scheduler will printout the current simulation
* time. * time.
* *
* @param time * @param time
*/ */
public void setStatusInterval(long time) { public void setStatusInterval(long time) {
...@@ -512,38 +512,38 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent { ...@@ -512,38 +512,38 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
public void setSimulationSpeedLocked(boolean locked) { public void setSimulationSpeedLocked(boolean locked) {
scheduler.setSimulationSpeedLocked(locked); scheduler.setSimulationSpeedLocked(locked);
} }
public static Configurator getConfigurator() { public static Configurator getConfigurator() {
return defaultConfigurator; return defaultConfigurator;
} }
/** /**
* Sets the real world start time. * Sets the real world start time.
* *
* @param realWorldStartTime the new real world start time * @param realWorldStartTime the new real world start time
*/ */
public void setRealWorldStartTime(String realWorldStartTime) { public void setRealWorldStartTime(String realWorldStartTime) {
final Date now = new Date(); final Date now = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss z dd.MM.yyyy", Locale.GERMANY); SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss z dd.MM.yyyy", Locale.GERMANY);
try { try {
final Date startTime = formatter.parse(realWorldStartTime); final Date startTime = formatter.parse(realWorldStartTime);
if( now.after(startTime) ) { if( now.after(startTime) ) {
throw new AssertionError( throw new AssertionError(
"Simulator was supposed to run in the past. Check config for realWorldStartTime."); "Simulator was supposed to run in the past. Check config for realWorldStartTime.");
} }
this.realWorldStartTime = startTime; this.realWorldStartTime = startTime;
} catch (ParseException e) { } catch (ParseException e) {
Monitor.log( Monitor.log(
Simulator.class, Simulator.class,
Level.WARN, Level.WARN,
"Could not parse realWorldStartTime. Please check configuration file. Starting *NOW*"); "Could not parse realWorldStartTime. Please check configuration file. Starting *NOW*");
} }
} }
public void addObserver(SimulatorObserver observer) { public void addObserver(SimulatorObserver observer) {
......
...@@ -2,17 +2,17 @@ ...@@ -2,17 +2,17 @@
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab * Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
* *
* This file is part of PeerfactSim.KOM. * This file is part of PeerfactSim.KOM.
* *
* PeerfactSim.KOM is free software: you can redistribute it and/or modify * PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* any later version. * any later version.
* *
* PeerfactSim.KOM is distributed in the hope that it will be useful, * PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>. * along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
* *
...@@ -67,7 +67,7 @@ import de.tudarmstadt.maki.simonstrator.api.component.transport.ConnectivityList ...@@ -67,7 +67,7 @@ import de.tudarmstadt.maki.simonstrator.api.component.transport.ConnectivityList
/** /**
* Default implementation of a {@link TopologyComponent}. * Default implementation of a {@link TopologyComponent}.
* *
* @author Bjoern Richerzhagen * @author Bjoern Richerzhagen
* @version 1.0, 29.02.2012 * @version 1.0, 29.02.2012
*/ */
...@@ -95,7 +95,7 @@ public class DefaultTopologyComponent implements TopologyComponent { ...@@ -95,7 +95,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
/** /**
* Create a TopologyComponent for the current host. * Create a TopologyComponent for the current host.
* *
* @param host * @param host
* @param topology * @param topology
* @param movementModel * @param movementModel
...@@ -139,10 +139,10 @@ public class DefaultTopologyComponent implements TopologyComponent { ...@@ -139,10 +139,10 @@ public class DefaultTopologyComponent implements TopologyComponent {
final SiSComponent sis = host.getComponent(SiSComponent.class); final SiSComponent sis = host.getComponent(SiSComponent.class);
sis.provide().nodeState(SiSTypes.PHY_LOCATION, sis.provide().nodeState(SiSTypes.PHY_LOCATION,
new SiSDataCallback<Location>() { new SiSDataCallback<Location>() {
Set<INodeID> localID = INodeID Set<INodeID> localID = INodeID
.getSingleIDSet(getHost().getId()); .getSingleIDSet(getHost().getId());
@Override @Override
public Location getValue(INodeID nodeID, public Location getValue(INodeID nodeID,
SiSProviderHandle providerHandle) SiSProviderHandle providerHandle)
...@@ -153,32 +153,61 @@ public class DefaultTopologyComponent implements TopologyComponent { ...@@ -153,32 +153,61 @@ public class DefaultTopologyComponent implements TopologyComponent {
throw new InformationNotAvailableException(); throw new InformationNotAvailableException();
} }
} }
@Override @Override
public Set<INodeID> getObservedNodes() { public Set<INodeID> getObservedNodes() {
return localID; return localID;
} }
@Override @Override
public SiSInfoProperties getInfoProperties() { public SiSInfoProperties getInfoProperties() {
return new SiSInfoProperties(); return new SiSInfoProperties();
} }
}); });
sis.provide().nodeState(SiSTypes.SPEED,
new SiSDataCallback<Double>() {
Set<INodeID> localID = INodeID
.getSingleIDSet(getHost().getId());
@Override
public Double getValue(INodeID nodeID,
SiSProviderHandle providerHandle)
throws InformationNotAvailableException {
if (nodeID.equals(getHost().getId())) {
return getMovementSpeed();
} else {
throw new InformationNotAvailableException();
}
}
@Override
public Set<INodeID> getObservedNodes() {
return localID;
}
@Override
public SiSInfoProperties getInfoProperties() {
return new SiSInfoProperties();
}
});
// Provide Underlay topology // Provide Underlay topology
Event.scheduleImmediately(new EventHandler() { Event.scheduleImmediately(new EventHandler() {
@Override @Override
public void eventOccurred(Object content, int type) { public void eventOccurred(Object content, int type) {
if (getHost().getLinkLayer().hasPhy(PhyType.WIFI)) { if (getHost().getLinkLayer().hasPhy(PhyType.WIFI)) {
new SiSTopologyProvider(sis, SiSTypes.NEIGHBORS_WIFI, new SiSTopologyProvider(sis,
SiSTypes.NEIGHBORS_WIFI,
DefaultTopologyComponent.this, DefaultTopologyComponent.this,
getTopologyID(NetInterfaceName.WIFI, true), getTopologyID(NetInterfaceName.WIFI, true),
DefaultTopologyComponent.class); DefaultTopologyComponent.class);
} }
} }
}, null, 0); }, null, 0);
} catch (ComponentNotAvailableException e) { } catch (ComponentNotAvailableException e) {
// OK // OK
} }
...@@ -206,7 +235,7 @@ public class DefaultTopologyComponent implements TopologyComponent { ...@@ -206,7 +235,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
public Topology getTopology() { public Topology getTopology() {
return topology; return topology;
} }
/** /**
* Access to the movement model * Access to the movement model
* @return * @return
...@@ -279,19 +308,19 @@ public class DefaultTopologyComponent implements TopologyComponent { ...@@ -279,19 +308,19 @@ public class DefaultTopologyComponent implements TopologyComponent {
locationListener.onLocationChanged(getHost(), getLastLocation()); locationListener.onLocationChanged(getHost(), getLastLocation());
} }
} }
@Override @Override
public void setTargetAttractionPoint(AttractionPoint targetAttractionPoint) public void setTargetAttractionPoint(AttractionPoint targetAttractionPoint)
throws UnsupportedOperationException { throws UnsupportedOperationException {
movementModel.changeTargetLocation(this, targetAttractionPoint); movementModel.changeTargetLocation(this, targetAttractionPoint);
// NodeDebugMonitor.update(this.getClass(), getHost().getId(), "Target Location", targetAttractionPoint); // NodeDebugMonitor.update(this.getClass(), getHost().getId(), "Target Location", targetAttractionPoint);
} }
@Override @Override
public AttractionPoint getCurrentTargetAttractionPoint() { public AttractionPoint getCurrentTargetAttractionPoint() {
return movementModel.getTargetLocation(this); return movementModel.getTargetLocation(this);
} }
@Override @Override
public Set<AttractionPoint> getAllAttractionPoints() { public Set<AttractionPoint> getAllAttractionPoints() {
return movementModel.getAllAttractionPoints(); return movementModel.getAllAttractionPoints();
...@@ -339,7 +368,7 @@ public class DefaultTopologyComponent implements TopologyComponent { ...@@ -339,7 +368,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
/** /**
* Update 15.03.16 added support for multiple listeners (however, frequency * Update 15.03.16 added support for multiple listeners (however, frequency
* etc. is immune after the first request is registered.) * etc. is immune after the first request is registered.)
* *
* @author Bjoern Richerzhagen * @author Bjoern Richerzhagen
* @version 1.0, Mar 15, 2016 * @version 1.0, Mar 15, 2016
*/ */
...@@ -354,7 +383,7 @@ public class DefaultTopologyComponent implements TopologyComponent { ...@@ -354,7 +383,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
private Location lastLocation = null; private Location lastLocation = null;
private List<LocationListener> listeners = new LinkedList<LocationListener>(); private List<LocationListener> listeners = new LinkedList<LocationListener>();
private int eventTypeSeq = 0; private int eventTypeSeq = 0;
public LocationRequestImpl() { public LocationRequestImpl() {
...@@ -402,9 +431,9 @@ public class DefaultTopologyComponent implements TopologyComponent { ...@@ -402,9 +431,9 @@ public class DefaultTopologyComponent implements TopologyComponent {
public void eventOccurred(Object content, int type) { public void eventOccurred(Object content, int type) {
if (eventTypeSeq != type) { if (eventTypeSeq != type) {
/* /*
* Discard invalid events caused when a client cancels updates * Discard invalid events caused when a client cancels updates
* but reactivates the request within the update frequency * but reactivates the request within the update frequency
* interval. In this case, the old events continue rescheduling * interval. In this case, the old events continue rescheduling
* themselves. * themselves.
*/ */
return; return;
...@@ -413,7 +442,7 @@ public class DefaultTopologyComponent implements TopologyComponent { ...@@ -413,7 +442,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
// Only reschedule, if at least one listener is ... listening // Only reschedule, if at least one listener is ... listening
Location newLoc = getLastLocation(); Location newLoc = getLastLocation();
listeners.forEach((LocationListener listener) -> listener listeners.forEach((LocationListener listener) -> listener
.onLocationChanged(getHost(), newLoc)); .onLocationChanged(getHost(), newLoc));
lastLocation = newLoc; lastLocation = newLoc;
Event.scheduleWithDelay(interval, this, null, eventTypeSeq); Event.scheduleWithDelay(interval, this, null, eventTypeSeq);
} }
...@@ -448,7 +477,7 @@ public class DefaultTopologyComponent implements TopologyComponent { ...@@ -448,7 +477,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
boolean onlyOnline, double range) { boolean onlyOnline, double range) {
TopologyID id = TopologyID.getIdentifier( TopologyID id = TopologyID.getIdentifier(
netName.toString() + (onlyOnline ? "-online" : "-all") netName.toString() + (onlyOnline ? "-online" : "-all")
+ String.valueOf(range), + String.valueOf(range),
DefaultTopologyComponent.class); DefaultTopologyComponent.class);
if (!this.graphViews.containsKey(id)) { if (!this.graphViews.containsKey(id)) {
this.graphViews.put(id, this.graphViews.put(id,
...@@ -483,12 +512,12 @@ public class DefaultTopologyComponent implements TopologyComponent { ...@@ -483,12 +512,12 @@ public class DefaultTopologyComponent implements TopologyComponent {
/** /**
* This is calculated based on global knowledge. It only registers as * This is calculated based on global knowledge. It only registers as
* {@link LocationListener}, if a range is specified by the Provider. * {@link LocationListener}, if a range is specified by the Provider.
* *
* @author Bjoern Richerzhagen * @author Bjoern Richerzhagen
* @version 1.0, May 13, 2015 * @version 1.0, May 13, 2015
*/ */
private class LocalGraphView private class LocalGraphView
implements LocationListener, ConnectivityListener { implements LocationListener, ConnectivityListener {
/** /**
* Marker: has there been any movement since the graph view was last * Marker: has there been any movement since the graph view was last
...@@ -550,8 +579,8 @@ public class DefaultTopologyComponent implements TopologyComponent { ...@@ -550,8 +579,8 @@ public class DefaultTopologyComponent implements TopologyComponent {
if (host.getNetworkComponent() if (host.getNetworkComponent()
.getByName(medium) != null) { .getByName(medium) != null) {
host.getNetworkComponent().getByName(medium) host.getNetworkComponent().getByName(medium)
.addConnectivityListener( .addConnectivityListener(
LocalGraphView.this); LocalGraphView.this);
} }
} }
} }
...@@ -636,7 +665,7 @@ public class DefaultTopologyComponent implements TopologyComponent { ...@@ -636,7 +665,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
IEdge edge = currentView.createEdge( IEdge edge = currentView.createEdge(
mac.getHost().getId(), mac.getHost().getId(),
topoView.getMac(neighborMac).getHost() topoView.getMac(neighborMac).getHost()
.getId()); .getId());
currentView.addElement(edge); currentView.addElement(edge);
edge.setProperty(SiSTypes.PHY_DISTANCE, edge.setProperty(SiSTypes.PHY_DISTANCE,
topoView.getDistance(mac.getMacAddress(), topoView.getDistance(mac.getMacAddress(),
...@@ -666,7 +695,7 @@ public class DefaultTopologyComponent implements TopologyComponent { ...@@ -666,7 +695,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
/** /**
* This is the global view, therefore we do not distinguish between * This is the global view, therefore we do not distinguish between
* hosts. * hosts.
* *
* @return * @return
*/ */
public Graph getLocalView() { public Graph getLocalView() {
......
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.movement;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import de.tud.kom.p2psim.api.network.SimNetInterface;
import de.tud.kom.p2psim.api.topology.movement.MovementModel;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.network.routed.RoutedNetLayer;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.traci.TraciSimulationController;
import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.xml.XMLSimulationController;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.common.graph.INodeID;
import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableException;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.api.SimulationSetupExtractor;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
public class RSUMovementModel implements MovementModel {
private final List<SimLocationActuator> components;
private final String sumoExe;
private final String sumoConfigFile;
private final String sumoIntersections;
private final int offsetX;
private final int offsetY;
private final int width;
private final int height;
private final long timestepConversion = Time.SECOND;
private boolean initialized = false;
private SimulationSetupExtractor _controller;
private List<Location> _intersections;
private int _currentIndex = 0;
private final Map<INodeID, Integer> hostIntersectionMatching = new HashMap<>();
@XMLConfigurableConstructor({ "sumoExe", "sumoConfigFile", "offsetX", "offsetY", "width", "height" })
public RSUMovementModel(String sumoExe, String sumoConfigFile, String offsetX, String offsetY, String width, String height) {
this.components = new LinkedList<>();
this.sumoExe = sumoExe;
this.sumoConfigFile = sumoConfigFile;
this.sumoIntersections = null;
this.offsetX = Integer.parseInt(offsetX);
this.offsetY = Integer.parseInt(offsetY);
this.width = Integer.parseInt(width);
this.height = Integer.parseInt(height);
}
@XMLConfigurableConstructor({ "sumoIntersections", "offsetX", "offsetY", "width", "height" })
public RSUMovementModel(String sumoIntersections, String offsetX, String offsetY, String width, String height) {
this.components = new LinkedList<>();
this.sumoIntersections = sumoIntersections;
this.sumoExe = null;
this.sumoConfigFile = null;
this.offsetX = Integer.parseInt(offsetX);
this.offsetY = Integer.parseInt(offsetY);
this.width = Integer.parseInt(width);
this.height = Integer.parseInt(height);
}
@Override
public final void addComponent(SimLocationActuator comp) {
components.add(comp);
}
@Override
public void setTimeBetweenMoveOperations(long time) {
//Do nothing, only used for placement of RSU
}
@Override
public synchronized void placeComponent(SimLocationActuator actuator) {
if (!initialized) {
initializeModel();
initialized = true;
}
if (_currentIndex < _intersections.size()) {
// Initial placement
Location intersection = _intersections.get(_currentIndex);
actuator.updateCurrentLocation(new PositionVector(intersection.getLongitude(), intersection.getLatitude()));
hostIntersectionMatching.put(actuator.getHost().getId(), _currentIndex);
_currentIndex++;
//Put interfaces online
try {
RoutedNetLayer routedNetLayer = actuator.getHost().getComponent(RoutedNetLayer.class);
for (SimNetInterface netInterface : routedNetLayer.getSimNetworkInterfaces()) {
if (netInterface.isOffline()) {
netInterface.goOnline();
}
}
} catch (ComponentNotAvailableException e) {
e.printStackTrace();
}
} else {
actuator.updateCurrentLocation(new PositionVector(Double.NaN, Double.NaN));
}
}
/**
* Initializes the movement model by executing BonnMotion and parsing the
* resulting movement trace.
*/
protected void initializeModel() {
if (this.sumoExe != null) {
_controller = TraciSimulationController.createSimulationController(sumoExe, sumoConfigFile);
_controller.init();
_controller.setObservedArea(offsetX, offsetY, offsetX + width, offsetY + height);
_intersections = _controller.getAllIntersections(true);
} else {
_controller = new XMLSimulationController(null, sumoIntersections);
_controller.init();
_controller.setObservedArea(offsetX, offsetY, offsetX + width, offsetY + height);
_intersections = _controller.getAllIntersections(true);
}
// System.out.println("Require " + _intersections.size() + " RSUs");
}
}
\ No newline at end of file
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.movement;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.stream.Stream;
import de.tud.kom.p2psim.api.topology.movement.MovementModel;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
public class SumoTraceMovementModel implements MovementModel, EventHandler {
private long timeBetweenMoveOperations;
private final List<SimLocationActuator> components;
private final Map<SimLocationActuator, Queue<Step>> movements;
private final String tracefile;
private final long timestepConversion = Time.SECOND;
private boolean initialized = false;
@XMLConfigurableConstructor({ "timeBetweenMoveOperations", "tracefile" })
public SumoTraceMovementModel(long timeBetweenMoveOperations, String tracefile) {
this.timeBetweenMoveOperations = timeBetweenMoveOperations;
this.components = new LinkedList<>();
this.movements = new LinkedHashMap<>();
this.tracefile = tracefile;
}
@Override
public final void addComponent(SimLocationActuator comp) {
components.add(comp);
}
public long getTimeBetweenMoveOperations() {
return timeBetweenMoveOperations;
}
@Override
public void setTimeBetweenMoveOperations(long time) {
this.timeBetweenMoveOperations = time;
}
@Override
public void placeComponent(SimLocationActuator actuator) {
if (!initialized) {
initializeModel();
initialized = true;
}
// Initial placement
actuator.updateCurrentLocation(new PositionVector(5, 5));
}
/**
* Initializes the movement model by executing BonnMotion and parsing the
* resulting movement trace.
*/
protected void initializeModel() {
// Schedule first step
Event.scheduleWithDelay(timeBetweenMoveOperations, this, null, 0);
// Read the if-file (.if)
try (Stream<String> lines = Files.lines(Paths.get(tracefile), Charset.defaultCharset())) {
lines.forEachOrdered(line -> process(line));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Initialization: done.");
}
/**
* Invoked for each line within the input file. A line consists of the
* following data, separated by a space:
*
* Node-ID Timestamp X-Coordinate Y-Coordinate
*
* @param line
*/
protected void process(String line) {
String[] step = line.split(" ");
int nodeId = Integer.valueOf(step[0]);
//assert nodeId < components.size();
long time = Long.valueOf(step[1]);
double x = Double.valueOf(step[2]);
double y = Double.valueOf(step[3]);
if (nodeId >= components.size()) {
return;
}
// TODO make SUMO trace offsets configurable.
time -= 21600;
x -= 10000;
y -= 10000;
x/=10;
y/=10;
SimLocationActuator comp = components.get(nodeId);
Queue<Step> steps = movements.get(comp);
if (steps == null) {
steps = new LinkedList<>();
movements.put(comp, steps);
}
steps.add(new Step(time, x, y));
}
@Override
public void eventOccurred(Object content, int type) {
/*
* One event for all nodes (synchronized movement), as this boosts
* simulation performance due to less recalculations in the network
* models.
*/
long currentTime = Time.getCurrentTime() / timestepConversion;
movements.forEach((component, steps) -> {
Step step = null;
Step nextStep = null;
do {
step = steps.peek();
nextStep = null;
// Valid step
if (step != null && step.timestamp <= currentTime) {
step = steps.poll();
// Look ahead, maybe we need to skip?
nextStep = steps.peek();
}
} while (step != null && nextStep != null && nextStep.timestamp < currentTime);
if (step != null) {
component.updateCurrentLocation(new PositionVector(step.x, step.y));
// System.out.println("Set component "+component.getHost().getId()+" location to "+step.x+","+step.y);
}
});
// Reschedule next step
Event.scheduleWithDelay(timeBetweenMoveOperations, this, null, 0);
}
/**
* A Step.
*
* @author Bjoern Richerzhagen
*
*/
private class Step {
public final double x;
public final double y;
public final long timestamp;
public Step(long timestamp, double x, double y) {
this.x = x;
this.y = y;
this.timestamp = timestamp;
}
}
}
\ No newline at end of file
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.movement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Random;
import de.tud.kom.p2psim.api.network.SimNetInterface;
import de.tud.kom.p2psim.api.topology.movement.MovementModel;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.network.routed.RoutedNetLayer;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.traci.TraciSimulationController;
import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.xml.XMLSimulationController;
import de.tud.kom.p2psim.impl.vehicular.DefaultVehicleInformationComponent;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Host;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.common.graph.INodeID;
import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableException;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.VehicleInformationComponent;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.api.SimulationSetupExtractor;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.api.VehicleController;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.roadnetwork.RoadNetwork;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
public class VehicleMovementModel implements MovementModel, EventHandler {
private Random _knownRoutesRandom = Randoms.getRandom(getClass());
private static final Location DEFAULT_LOCATION = new PositionVector(Double.NaN, Double.NaN);
private boolean _reuseComponents = false;
private static VehicleMovementModel MOVEMENT;
private long timeBetweenMoveOperations;
private final List<SimLocationActuator> components;
private final Queue<SimLocationActuator> freeComponents;
private final Map<String, SimLocationActuator> idComponentMatcher;
private final Map<INodeID, String> hostVehicleIDMatching = new HashMap<>();
private final int offsetX;
private final int offsetY;
private final int width;
private final int height;
private double scenarioWidth = 0;
private double scenarioHeight = 0;
private final String sumoExe;
private final String sumoConfigFile;
private final String sumoTrace;
private String sumoIntersections;
private final long timestepConversion = Time.SECOND;
private boolean initialized = false;
private VehicleController _controller;
private SimulationSetupExtractor _extractor;
private double _percentageOfKnownRoutes = 1;
/**
* Constructor for the movement model using the sumo TraCI API
* @param timeBetweenMoveOperations The time between two movement operations.
* @param sumoExe The path to the executable of sumo
* @param sumoConfigFile The path to the configuration file of the scenario
* @param offsetX The offset that should be used. If no offset is required, offset 0 shall be used.
* @param offsetY The offset that should be used. If no offset is required, offset 0 shall be used.
* @param width The width of the scenario.
* @param height The height of the scenario.
*/
@XMLConfigurableConstructor({ "timeBetweenMoveOperations", "sumoExe", "sumoConfigFile", "offsetX", "offsetY", "width", "height" })
public VehicleMovementModel(long timeBetweenMoveOperations, String sumoExe, String sumoConfigFile, String offsetX, String offsetY, String width, String height) {
MOVEMENT = this;
this.timeBetweenMoveOperations = timeBetweenMoveOperations;
this.components = new LinkedList<>();
this.freeComponents = new LinkedList<>();
this.idComponentMatcher = new HashMap<>();
this.sumoExe = sumoExe;
this.sumoConfigFile = sumoConfigFile;
this.sumoTrace = null;
this.offsetX = Integer.parseInt(offsetX);
this.offsetY = Integer.parseInt(offsetY);
this.width = Integer.parseInt(width);
this.height = Integer.parseInt(height);
}
/**
* Constructor for the movement model using the a generated sumo trace file
* @param timeBetweenMoveOperations The time between two movement operations.
* @param sumoTrace The path to the vehicle movement file (*.xml)
* @param sumoIntersections The path to the intersections file (*.csv)
* @param offsetX The offset that should be used. If no offset is required, offset 0 shall be used.
* @param offsetY The offset that should be used. If no offset is required, offset 0 shall be used.
* @param width The width of the scenario.
* @param height The height of the scenario.
*/
@XMLConfigurableConstructor({ "timeBetweenMoveOperations", "sumoTrace", "sumoIntersections", "offsetX", "offsetY", "width", "height" })
public VehicleMovementModel(long timeBetweenMoveOperations, String sumoTrace, String sumoIntersections, int offsetX, int offsetY, int width, int height) {
MOVEMENT = this;
this.timeBetweenMoveOperations = timeBetweenMoveOperations;
this.components = new LinkedList<>();
this.freeComponents = new LinkedList<>();
this.idComponentMatcher = new HashMap<>();
this.sumoExe = null;
this.sumoConfigFile = null;
this.sumoTrace = sumoTrace;
this.sumoIntersections = sumoIntersections;
this.offsetX = offsetX;
this.offsetY = offsetY;
this.width = width;
this.height = height;
}
/**
* @param pPercentageOfKnownRoutes the percentageOfKnownRoutes to set
*/
public void setPercentageOfKnownRoutes(double pPercentageOfKnownRoutes) {
_percentageOfKnownRoutes = pPercentageOfKnownRoutes;
}
public void setReuseComponents(boolean pReuseComponents) {
_reuseComponents = pReuseComponents;
if (_reuseComponents) {
System.err.println("WARNING: Enabling the reuse of components might cause strange behaviors of your simulation!");
}
}
/**
* Adding an additional component to be moved by this movement model
* @param comp The component to be added.
*/
@Override
public final void addComponent(SimLocationActuator comp) {
components.add(comp);
freeComponents.add(comp);
comp.updateCurrentLocation(DEFAULT_LOCATION);
}
/**
* Returns the time between movement operations
* @return time between movement operations
*/
public long getTimeBetweenMoveOperations() {
return timeBetweenMoveOperations;
}
/**
* Set the time between movement operations
* @param time the time between movement operations
*/
@Override
public void setTimeBetweenMoveOperations(long time) {
this.timeBetweenMoveOperations = time;
}
/**
* Place a component at the correct location
* @param actuator The component to be placed.
*/
@Override
public void placeComponent(SimLocationActuator actuator) {
if (!initialized) {
initializeModel();
VehicleMovementModel.getRoadNetwork();
initialized = true;
}
// Initial placement
actuator.updateCurrentLocation(DEFAULT_LOCATION);
}
/**
* Initializes the movement model by executing BonnMotion and parsing the
* resulting movement trace.
*/
protected void initializeModel() {
// Schedule first step
if (!initialized) {
Event.scheduleWithDelay(timeBetweenMoveOperations, this, null, 0);
if (sumoExe != null) {
TraciSimulationController simulationController = TraciSimulationController.createSimulationController(sumoExe, sumoConfigFile);
_controller = simulationController;
_controller.setObservedArea(offsetX, offsetY, offsetX + width, offsetY + height);
_controller.init();
_controller.nextStep();
_extractor = simulationController;
} else {
XMLSimulationController simulationController;
if (sumoIntersections == null || sumoIntersections.equals("")) {
simulationController = new XMLSimulationController(sumoTrace);
} else {
simulationController = new XMLSimulationController(sumoTrace, sumoIntersections);
}
_controller = simulationController;
_controller.setObservedArea(offsetX, offsetY, offsetX + width, offsetY + height);
_controller.init();
_controller.nextStep();
_extractor = simulationController;
}
scenarioWidth = _extractor.getScenarioWidth();
scenarioHeight = _extractor.getScenarioHeight();
System.out.println("Initialization: done.");
}
}
/**
* Used for the periodical updates of the vehicle positions
* @param content not used in this case, should be null
* @param type not used in this case, should be 0
*/
@Override
public void eventOccurred(Object content, int type) {
/*
* One event for all nodes (synchronized movement), as this boosts
* simulation performance due to less recalculations in the network
* models.
*/
long currentTime = Time.getCurrentTime() / timestepConversion;
while (_controller.getStep() - _controller.getStart() < currentTime) {
if (!_controller.nextStep()) {
return;
}
}
List<String> allVehicles = _controller.getAllVehicles();
for (int i = 0; i < allVehicles.size(); i++) {
String vehicle = allVehicles.get(i);
Location position = _controller.getVehiclePosition(vehicle);
if (position == null) {
allVehicles.remove(i--);
continue;
}
SimLocationActuator component = requestSimActuator(vehicle);
try {
RoutedNetLayer routedNetLayer = component.getHost().getComponent(RoutedNetLayer.class);
for (SimNetInterface netInterface : routedNetLayer.getSimNetworkInterfaces()) {
if (netInterface.isOffline()) {
netInterface.goOnline();
}
}
} catch (ComponentNotAvailableException e) {
e.printStackTrace();
}
component.updateCurrentLocation(new PositionVector(position.getLongitude(), position.getLatitude()));
component.setMovementSpeed(_controller.getVehicleSpeed(vehicle));
}
if (allVehicles.size() != idComponentMatcher.size()) {
ArrayList<String> registeredVehicles = new ArrayList<>(idComponentMatcher.keySet());
for (int i = 0; i < registeredVehicles.size(); i++) {
String vehicle = registeredVehicles.get(i);
if (!allVehicles.contains(vehicle)) {
addFreeHost(vehicle);
}
}
}
if (Time.getCurrentTime() < 5 * Time.SECOND) {
for (SimLocationActuator simLocationActuator : freeComponents) {
simLocationActuator.updateCurrentLocation(DEFAULT_LOCATION);
}
}
// Reschedule next step
Event.scheduleWithDelay(timeBetweenMoveOperations, this, null, 0);
}
/**
* Remove a vehicle from the set of moved components as the vehicle has stopped driving
* @param vehicleID The stopped vehicle
*/
private void addFreeHost(String vehicleID) {
if (idComponentMatcher.containsKey(vehicleID)) {
SimLocationActuator simLocationActuator = idComponentMatcher.remove(vehicleID);
if (simLocationActuator != null) {
try {
VehicleInformationComponent vehicularHostComponent = simLocationActuator.getHost().getComponent(VehicleInformationComponent.class);
vehicularHostComponent.resetVehicleID();
} catch (ComponentNotAvailableException e) {
// Nothing to do here
}
hostVehicleIDMatching.remove(simLocationActuator.getHost().getId());
try {
RoutedNetLayer routedNetLayer = simLocationActuator.getHost().getComponent(RoutedNetLayer.class);
for (SimNetInterface netInterface : routedNetLayer.getSimNetworkInterfaces()) {
if (netInterface.isOnline()) {
netInterface.goOffline();
}
}
} catch (ComponentNotAvailableException e) {
e.printStackTrace();
}
simLocationActuator.updateCurrentLocation(DEFAULT_LOCATION);
if (_reuseComponents) {
freeComponents.add(simLocationActuator);
}
}
}
}
/**
* Request a component for a vehicle. If no component has been assigned to the vehicle yet, a new component is assigned.
* @param vehicle The vehicle for which a component is requested.
* @throws RuntimeException If no component can be assigned.
* @return The component for the vehicle.
*/
private SimLocationActuator requestSimActuator(String vehicle) {
if (!idComponentMatcher.containsKey(vehicle)) {
SimLocationActuator simLocationActuator = freeComponents.poll();
if (simLocationActuator != null) {
VehicleInformationComponent vehicularHostComponent;
try {
vehicularHostComponent = simLocationActuator.getHost().getComponent(VehicleInformationComponent.class);
} catch (ComponentNotAvailableException e) {
Host host = simLocationActuator.getHost();
boolean routeKnown;
if (_knownRoutesRandom.nextDouble() < _percentageOfKnownRoutes) {
routeKnown = true;
} else {
routeKnown = false;
}
vehicularHostComponent = new DefaultVehicleInformationComponent(host, _controller, _extractor, routeKnown);
host.registerComponent(vehicularHostComponent);
}
vehicularHostComponent.setVehicleID(vehicle);
idComponentMatcher.put(vehicle, simLocationActuator);
hostVehicleIDMatching.put(simLocationActuator.getHost().getId(), vehicle);
} else {
throw new RuntimeException("Unable to assign new components. Please increase node amount" + (_reuseComponents?".":" or enable the reuse of components."));
}
}
return idComponentMatcher.get(vehicle);
}
public static RoadNetwork getRoadNetwork() {
return MOVEMENT._extractor.getRoadNetwork();
}
}
package de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller;
import java.io.FileInputStream;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.xml.CancelParsingSAXException;
import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.xml.SimulationSetupInformationHandler;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
public class SimulationSetupInformationProvider {
private static final SimulationSetupInformationProvider ONLY_INSTANCE = new SimulationSetupInformationProvider();
private SimulationSetupInformationHandler _handler = new SimulationSetupInformationHandler();
private SimulationSetupInformationProvider() {
}
public static SimulationSetupInformationProvider getOnlyInstance() {
return ONLY_INSTANCE;
}
public Location getUpperLeft() {
return _handler.getUpperLeft();
}
public Location getLowerRight() {
return _handler.getLowerRight();
}
public static void init(String pNetFileLocation) {
try {
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
parser.parse(new FileInputStream(pNetFileLocation), ONLY_INSTANCE._handler);
} catch (CancelParsingSAXException e) {
return;
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.roadnetwork.RoadNetworkRoute;
public class VehicleInformationContainer {
private Location _position;
private double _heading;
private double _speed;
private RoadNetworkRoute _route;
public VehicleInformationContainer(Location pPosition, double pHeading,
double pSpeed, RoadNetworkRoute pRoute) {
_position = pPosition;
_heading = pHeading;
_speed = pSpeed;
_route = pRoute;
}
public Location getPosition() {
return _position;
}
public double getHeading() {
return _heading;
}
public double getSpeed() {
return _speed;
}
public RoadNetworkRoute getRoute() {
return _route;
}
}
\ No newline at end of file
package de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.csv;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
public class RoadSideUnitInformationHandler {
private List<Location> _positions = new ArrayList<>();
private boolean _observedAreaSet = false;
private double _startX = -1;
private double _startY = -1;
private double _endX = -1;
private double _endY = -1;
public List<Location> getIntersections() {
if (!_observedAreaSet) {
return _positions;
} else {
List<Location> result = new ArrayList<>();
for (Location position : _positions) {
if (_startX <= position.getLongitude() && position.getLongitude() <= _endX && _startY <= position.getLatitude() && position.getLatitude() <= _endY) {
result.add(new PositionVector(position.getLongitude() - _startX, position.getLatitude() - _startY, 0));
}
}
return result;
}
}
public void parseIntersectionsFile(String pRoadSideUnitDataPath) {
File file = new File(pRoadSideUnitDataPath);
try {
FileInputStream inputStream = new FileInputStream(file);
Scanner scanner = new Scanner(inputStream);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.contains(";")) {
String[] split = line.split(";");
if (split.length == 2) {
double x = Double.parseDouble(split[0]);
double y = Double.parseDouble(split[1]);
_positions.add(new PositionVector(x, y, 0));
}
}
}
scanner.close();
} catch (FileNotFoundException e) {
System.err.println("Unable to read file " + e.getMessage());
}
}
public void setObservedArea(double pStartX, double pStartY, double pEndX, double pEndY) {
_startX = pStartX;
_startY = pStartY;
_endX = pEndX;
_endY = pEndY;
_observedAreaSet = true;
}
}
package de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.traci;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import de.tud.kom.p2psim.api.simengine.SimulatorObserver;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.VehicleInformationContainer;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.api.EdgeController;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.api.SimulationSetupExtractor;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.api.VehicleController;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.api.information.LocationUtils;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.roadnetwork.RoadNetwork;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.roadnetwork.RoadNetworkEdge;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.roadnetwork.RoadNetworkLane;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.roadnetwork.RoadNetworkRoute;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.roadnetwork.SerializableRoadNetwork;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.roadnetwork.exception.NoAdditionalRouteAvailableException;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.roadnetwork.exception.NoExitAvailableException;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.roadnetwork.routing.DijkstraAlgorithm;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.roadnetwork.routing.RoutingAlgorithm;
import de.tudresden.sumo.cmd.Edge;
import de.tudresden.sumo.cmd.Junction;
import de.tudresden.sumo.cmd.Lane;
import de.tudresden.sumo.cmd.Simulation;
import de.tudresden.sumo.cmd.Vehicle;
import de.tudresden.sumo.util.SumoCommand;
import de.tudresden.ws.container.SumoBoundingBox;
import de.tudresden.ws.container.SumoGeometry;
import de.tudresden.ws.container.SumoLink;
import de.tudresden.ws.container.SumoLinkList;
import de.tudresden.ws.container.SumoPosition2D;
import de.tudresden.ws.container.SumoStringList;
import edu.emory.mathcs.backport.java.util.Collections;
import it.polito.appeal.traci.SumoTraciConnection;
/**
*
* @author Tobias Meuser (tobias.meuser@kom.tu-darmstadt.de)
* @version 1.0 at 06.11.2017
*
*/
public class TraciSimulationController implements VehicleController, SimulationSetupExtractor, EdgeController, SimulatorObserver {
private static final File TEMP_FILE = new File(new File(System.getProperty("java.io.tmpdir")), "road_network.tmp");
private Random _random = Randoms.getRandom(getClass());
private static final Map<String, TraciSimulationController> CONTROLLER = new HashMap<>();
private static final double CLUSTERING_DISTANCE = 50;
private String _sumoExe;
private String _configFile;
private SumoTraciConnection _connection;
private double _start = -1;
private double _step = -1;
private double _startX;
private double _startY;
private double _endX;
private double _endY;
private Map<String, VehicleInformationContainer> _positons = new HashMap<>();
private boolean _initalized = false;
private boolean _observedAreaSet;
private Map<String, Double> _vehiclesOutOfRange = new HashMap<>();
private RoadNetwork _roadNetwork;
private RoutingAlgorithm _algorithm = new DijkstraAlgorithm();
public static synchronized TraciSimulationController createSimulationController(String pSumoExe, String pConfigFile) {
if (!CONTROLLER.containsKey(pConfigFile)) {
CONTROLLER.put(pConfigFile, new TraciSimulationController(pSumoExe, pConfigFile));
}
return CONTROLLER.get(pConfigFile);
}
private TraciSimulationController(String pSumoExe, String pConfigFile) {
_sumoExe = pSumoExe;
_configFile = pConfigFile;
}
public static VehicleController getSimulationController() {
return CONTROLLER.values().iterator().next();
}
@Override
public synchronized void init() {
if (!_initalized) {
Random random = Randoms.getRandom("SUMO");
// This will only work with the updated version of the TraaS API for sumo
// It is available for download at https://dev.kom.e-technik.tu-darmstadt.de/gitlab/tobiasm/TraaS.git
_connection = new SumoTraciConnection(_sumoExe, _configFile, random.nextInt());
/*
* prevent vehicles form teleporting (http://sumo.dlr.de/wiki/Simulation/Why_Vehicles_are_teleporting)
*/
_connection.addOption("time-to-teleport", Integer.toString(-1));
try {
_connection.runServer();
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
e.printStackTrace();
}
Simulator.getInstance().addObserver(this);
_initalized = true;
}
}
@Override
public void simulationFinished() {
/*
* This is called by the simulation scheduler once the simulation is
* finished - it should be used to terminate the connection to SUMO.
*/
if (_connection != null && !_connection.isClosed()) {
_connection.close();
}
}
@Override
public Location getVehiclePosition(String pVehicleID) {
return _positons.get(pVehicleID).getPosition();
}
@Override
public double getVehicleHeading(String pVehicleID) {
return _positons.get(pVehicleID).getHeading();
}
@Override
public Location getVehiclePosition(double pStep, String pVehicleID) {
if (pStep == _step) {
return getVehiclePosition(pVehicleID);
}
throw new UnsupportedOperationException("Future locations is not supported anymore!");
}
@Override
public List<Location> getAllIntersections(boolean pCluster) {
List<Location> result = new ArrayList<>();
SumoCommand intersectionCommand = Junction.getIDList();
Object intersectionObject = requestObject(intersectionCommand);
SumoStringList intersections = (SumoStringList) intersectionObject;
for (String intersection : intersections) {
SumoCommand positionCommand = Junction.getPosition(intersection);
Object positionObject = requestObject(positionCommand);
SumoPosition2D sumoPosition = (SumoPosition2D) positionObject;
if (_observedAreaSet) {
if (_startX <= sumoPosition.x && sumoPosition.x <= _endX && _startY <= sumoPosition.y && sumoPosition.y <= _endY) {
result.add(new PositionVector(sumoPosition.x - _startX, sumoPosition.y - _startY, 0));
}
} else {
result.add(new PositionVector(sumoPosition.x, sumoPosition.y, 0));
}
}
if (pCluster) {
List<Location> tempResult = new ArrayList<>();
outer:for (int i = 0; i < result.size(); i++) {
Location position = result.get(i);
for (int j = 0; j < tempResult.size(); j++) {
Location addedPosition = tempResult.get(j);
if (position != addedPosition && LocationUtils.calculateDistance(position, addedPosition) < CLUSTERING_DISTANCE / 1000.0) {
continue outer;
}
}
tempResult.add(position);
}
result = tempResult;
}
return result;
}
@Override
public boolean nextStep() {
if (Simulator.getEndTime() == Simulator.getCurrentTime()) {
return false;
}
try {
_connection.do_timestep();
try {
synchronized (_positons) {
_positons.clear();
int temp = (Integer) _connection.do_job_get(Simulation.getCurrentTime());
_step = temp / 1000.0;
if (_start == -1) {
_start = _step;
}
Map<String, VehicleInformationContainer> vehiclePositions = new HashMap<>();
List<String> allVehicles = requestAllVehicles();
for (String vehicle : allVehicles) {
Location position = requestVehiclePosition(vehicle);
if (position != null) {
double heading = requestVehicleHeading(vehicle);
double speed = requestVehicleSpeed(vehicle);
RoadNetworkRoute route = requestVehicleRoute(vehicle);
VehicleInformationContainer informationContainer = new VehicleInformationContainer(position, heading, speed, route);
vehiclePositions.put(vehicle, informationContainer);
}
}
_positons = vehiclePositions;
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
private Location requestVehiclePosition(String pVehicleID) {
if (_vehiclesOutOfRange.containsKey(pVehicleID)) {
if (_vehiclesOutOfRange.get(pVehicleID) < _step) {
return null;
} else {
_vehiclesOutOfRange.remove(pVehicleID);
}
}
SumoCommand positionCommand = Vehicle.getPosition(pVehicleID);
Object positionObject = requestObject(positionCommand);
SumoPosition2D sumoPosition = (SumoPosition2D) positionObject;
if (_observedAreaSet) {
if (_startX <= sumoPosition.x && sumoPosition.x <= _endX && _startY <= sumoPosition.y && sumoPosition.y <= _endY) {
return new PositionVector(sumoPosition.x - _startX, sumoPosition.y - _startY, 0);
} else {
double diffX = _startX - sumoPosition.x;
if (diffX < 0 || sumoPosition.x - _endX < diffX) {
diffX = sumoPosition.x - _endX;
}
if (diffX < 0) {
diffX = 0;
}
double diffY = _startY - sumoPosition.y;
if (diffY < 0 || sumoPosition.y - _endY < diffY) {
diffY = sumoPosition.y - _endY;
}
if (diffY < 0) {
diffY = 0;
}
double diff = Math.sqrt(Math.pow(diffX, 2) + Math.pow(diffY, 2));
double timeTillNextJoin = diff / 50;
// _vehiclesOutOfRange.put(pVehicleID, _step + timeTillNextJoin);
return null;
}
} else {
return new PositionVector(sumoPosition.x, sumoPosition.y, 0);
}
}
private double requestVehicleHeading(String pVehicleID) {
if (_vehiclesOutOfRange.containsKey(pVehicleID)) {
if (_vehiclesOutOfRange.get(pVehicleID) < _step) {
return -1;
} else {
_vehiclesOutOfRange.remove(pVehicleID);
}
}
SumoCommand angleCommand = Vehicle.getAngle(pVehicleID);
Object angleObject = requestObject(angleCommand);
if (angleObject != null) {
return (Double) angleObject;
}
return -1;
}
private double requestVehicleSpeed(String pVehicleID) {
if (_vehiclesOutOfRange.containsKey(pVehicleID)) {
if (_vehiclesOutOfRange.get(pVehicleID) < _step) {
return -1;
} else {
_vehiclesOutOfRange.remove(pVehicleID);
}
}
SumoCommand speedCommand = Vehicle.getSpeed(pVehicleID);
Object speedObject = requestObject(speedCommand);
if (speedObject != null) {
return (Double) speedObject;
}
return -1;
}
private List<String> requestAllVehicles() {
SumoCommand idList = Vehicle.getIDList();
Object object = requestObject(idList);
SumoStringList list = (SumoStringList)object;
List<String> result = new ArrayList<>();
for (String vehicle : list) {
result.add(vehicle);
}
return result;
}
@Override
public List<String> getAllVehicles() {
return getAllVehicles(_step);
}
@Override
public List<String> getAllVehicles(double pStep) {
if (pStep == _step) {
return new ArrayList<>(_positons.keySet());
}
throw new UnsupportedOperationException("Future locations is not supported anymore!");
}
public RoadNetworkEdge getCurrentEdge(String pVehicleID) {
obtainRoadNetwork();
SumoCommand roadIDCommand = Vehicle.getRoadID(pVehicleID);
String currentRoadID = (String) requestObject(roadIDCommand);
RoadNetworkEdge edge = _roadNetwork.getEdge(currentRoadID);
while (edge.isInternal()) {
if (edge.getAccessibleEdges().size() == 1) {
edge = edge.getAccessibleEdges().get(0);
} else {
break;
}
}
return edge;
}
public RoadNetworkRoute requestVehicleRoute(String pVehicleID) {
obtainRoadNetwork();
synchronized (_positons) {
List<RoadNetworkEdge> streets = new ArrayList<>();
SumoCommand routeCommand = Vehicle.getRoute(pVehicleID);
Object object = requestObject(routeCommand);
SumoStringList streetList = (SumoStringList) object;
RoadNetworkEdge currentEdge = getCurrentEdge(pVehicleID);
if (currentEdge == null) {
return null;
}
boolean add = false;
for (String street : streetList) {
if (street.equals(currentEdge.getEdgeID())) {
add = true;
}
if (add) {
streets.add(_roadNetwork.getEdge(street));
}
}
if (streets.size() == 0) {
return new RoadNetworkRoute(new ArrayList<>());
}
return new RoadNetworkRoute(streets);
}
}
@Override
public RoadNetworkRoute getCurrentRoute(String pVehicleID) {
if (_positons.containsKey(pVehicleID)) {
VehicleInformationContainer route = _positons.get(pVehicleID);
if (route != null) {
return route.getRoute();
}
}
return null;
}
public Object requestObject(SumoCommand routeCommand) {
Object object = null;
try {
object = _connection.do_job_get(routeCommand);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
e.printStackTrace();
}
return object;
}
public void execute(SumoCommand routeCommand) {
try {
_connection.do_job_set(routeCommand);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public double getStep() {
return _step;
}
@Override
public double getStart() {
return _start;
}
@Override
public double getMaximumAvailablePrediction() {
return getStep();
}
@Override
public void setObservedArea(double pStartX, double pStartY, double pEndX, double pEndY) {
_startX = pStartX;
_startY = pStartY;
_endX = pEndX;
_endY = pEndY;
_observedAreaSet = true;
}
@Override
public double getScenarioWidth() {
SumoCommand netBoundaryCommand = Simulation.getNetBoundary();
try {
SumoBoundingBox netBoundary = (SumoBoundingBox) _connection.do_job_get(netBoundaryCommand);
return Math.max(netBoundary.x_max - netBoundary.x_min, 10);
} catch (Exception e) {
//Nothing to do
}
return -1;
}
@Override
public double getScenarioHeight() {
SumoCommand netBoundaryCommand = Simulation.getNetBoundary();
try {
SumoBoundingBox netBoundary = (SumoBoundingBox) _connection.do_job_get(netBoundaryCommand);
return Math.max(netBoundary.y_max - netBoundary.y_min, 10);
} catch (Exception e) {
//Nothing to do
}
return -1;
}
public boolean providesRoadInformation() {
return true;
}
public RoadNetworkEdge getVehicleDestination(String pVehicleID) {
RoadNetworkRoute roadNetworkRoute = getCurrentRoute(pVehicleID);
return roadNetworkRoute.getDestination();
}
@Override
public RoadNetwork getRoadNetwork() {
obtainRoadNetwork();
return _roadNetwork;
}
@Override
public RoadNetworkRoute findNewRoute(String pVehicle) throws NoAdditionalRouteAvailableException {
List<RoadNetworkRoute> routes = new ArrayList<>();
RoadNetworkRoute route = getCurrentRoute(pVehicle);
if (route.getRoute().isEmpty()) {
return null;
}
routes.add(route);
RoadNetworkRoute findRoute = _algorithm.findRoute(_roadNetwork, route.getStart(), route.getDestination(), routes);
if (findRoute == null) {
throw new NoAdditionalRouteAvailableException(route.getStart(), route.getDestination(), routes);
}
return findRoute;
}
@Override
public RoadNetworkRoute findNewRoute(String pVehicle, List<RoadNetworkEdge> pEdgesToAvoid, boolean pKeepDestination) throws NoAdditionalRouteAvailableException, NoExitAvailableException {
if (pKeepDestination) {
List<RoadNetworkRoute> routes = new ArrayList<>();
RoadNetworkRoute route = getCurrentRoute(pVehicle);
if (route.getRoute().isEmpty()) {
return null;
}
routes.add(route);
RoadNetworkRoute findRoute = _algorithm.findRoute(_roadNetwork, route.getStart(), route.getDestination(), routes, pEdgesToAvoid);
if (findRoute == null) {
throw new NoAdditionalRouteAvailableException(route.getStart(), route.getDestination(), routes);
}
return findRoute;
} else {
RoadNetworkRoute route = getCurrentRoute(pVehicle);
if (route.getRoute().isEmpty()) {
return null;
}
List<RoadNetworkEdge> routeList = route.getRoute();
RoadNetworkEdge lastEdge = null;
boolean search = false;
outer:for (int i = routeList.size() - 1; i >= 0; i--) {
if (search) {
List<RoadNetworkEdge> accessibleEdges = routeList.get(i).getAccessibleEdges();
if (accessibleEdges.size() > 1) {
for (int j = 0; j < accessibleEdges.size(); j++) {
if (!accessibleEdges.get(j).equals(lastEdge)) {
List<RoadNetworkEdge> edges = new ArrayList<>();
for (int k = 0; k <= i; k++) {
edges.add(routeList.get(k));
}
edges.add(accessibleEdges.get(j));
List<RoadNetworkEdge> newPaths;
while ((newPaths = edges.get(edges.size() - 1).getAccessibleEdges()).size() > 0) {
edges.add(newPaths.get(_random.nextInt(newPaths.size())));
}
for (RoadNetworkEdge roadNetworkEdge : edges) {
if (pEdgesToAvoid.contains(roadNetworkEdge)) {
continue outer;
}
}
return new RoadNetworkRoute(edges);
}
}
}
}
search = true;
lastEdge = routeList.get(i);
}
throw new NoExitAvailableException(route.getStart(), route.getDestination());
}
}
@Override
public void rerouteVehicle(String pVehicle, RoadNetworkRoute pRoute) {
SumoStringList routeEdges = new SumoStringList();
for (RoadNetworkEdge edge : pRoute.getRoute()) {
routeEdges.add(edge.getEdgeID());
}
execute(Vehicle.setRoute(pVehicle, routeEdges));
}
@Override
public void stopVehicle(String pVehicle) {
SumoCommand stopCommand = Vehicle.setSpeed(pVehicle, 0);
execute(stopCommand);
}
public void obtainRoadNetwork() {
if (_roadNetwork == null) {
if (TEMP_FILE.exists()) {
try {
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(TEMP_FILE));
Object readObject = inputStream.readObject();
if (readObject instanceof SerializableRoadNetwork) {
SerializableRoadNetwork serializedRoadNetwork = (SerializableRoadNetwork) readObject;
_roadNetwork = new RoadNetwork(serializedRoadNetwork, this);
}
inputStream.close();
} catch (IOException | ClassNotFoundException | NullPointerException e) {
//Nothing to do
}
}
if (_roadNetwork != null) {
System.out.println("Got network from cache");
SumoCommand edgeIDCommand = Edge.getIDList();
SumoStringList edgeIDStringList = (SumoStringList) requestObject(edgeIDCommand);
if (_roadNetwork.getAvailableEdges().size() == edgeIDStringList.size()) {
boolean matching = true;
for (String edgeID : edgeIDStringList) {
if (_roadNetwork.getEdge(edgeID) == null) {
matching = false;
}
}
if (matching) {
return;
}
}
}
SumoCommand laneIDCommand = Lane.getIDList();
Map<String, RoadNetworkEdge> roadNetwork = new HashMap<>();
SumoStringList laneIDStringList = (SumoStringList) requestObject(laneIDCommand);
//Requesting all lanes from sumo.
for (String laneID : laneIDStringList) {
SumoCommand edgeIDCommand = Lane.getEdgeID(laneID);
SumoLinkList linkStringList = (SumoLinkList) requestObject(Lane.getLinks(laneID));
double angle = getLaneAngle(laneID);
double maxSpeed = getMaxSpeed(laneID);
if (linkStringList.size() > 0) {
String edgeID = (String) requestObject(edgeIDCommand);
if (!roadNetwork.containsKey(edgeID)) {
roadNetwork.put(edgeID, new RoadNetworkEdge(edgeID, angle, this));
}
RoadNetworkEdge edge = roadNetwork.get(edgeID);
edge.setOriginalMaxSpeed(maxSpeed);
edge.addLane(new RoadNetworkLane(laneID));
for (SumoLink link : linkStringList) {
String notInternalLane = link.notInternalLane;
String connectedEdge = (String) requestObject(Lane.getEdgeID(notInternalLane));
double linkAngle = getLaneAngle(laneID);
if (!roadNetwork.containsKey(connectedEdge)) {
RoadNetworkEdge roadNetworkEdge = new RoadNetworkEdge(connectedEdge, linkAngle, this);
roadNetwork.put(connectedEdge, roadNetworkEdge);
}
edge.addConnectedEdge(roadNetwork.get(connectedEdge));
}
}
}
_roadNetwork = new RoadNetwork(roadNetwork, this, true);
try {
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(TEMP_FILE));
outputStream.writeObject(new SerializableRoadNetwork(_roadNetwork));
outputStream.flush();
outputStream.close();
} catch (IOException e) {
//Nothing to do
e.printStackTrace();
}
}
RoadNetwork.CURRENT_ROAD_NETWORK = _roadNetwork;
}
public double getMaxSpeed(String laneID) {
SumoCommand maxSpeedCommand = Lane.getMaxSpeed(laneID);
double maxSpeed = (Double) requestObject(maxSpeedCommand);
return maxSpeed;
}
public double getLaneAngle(String laneID) {
SumoCommand shapeCommand = Lane.getShape(laneID);
SumoGeometry geometry = (SumoGeometry) requestObject(shapeCommand);
LinkedList<SumoPosition2D> coords = geometry.coords;
SumoPosition2D start = coords.getFirst();
SumoPosition2D end = coords.getLast();
double sin = (end.y - start.y) / Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2));
double angle = Math.asin(sin) * 180 / Math.PI;
if (end.x - start.x < 0) {
angle += 180;
}
return angle;
}
@Override
public List<Location> getLaneShape(String pLaneID) {
List<Location> positions = new ArrayList<>();
boolean set = true;
SumoCommand laneShapeCommand = Lane.getShape(pLaneID);
SumoGeometry geometry = (SumoGeometry)requestObject(laneShapeCommand);
for (SumoPosition2D location : geometry.coords) {
if (!isObservedAreaSet()) {
positions.add(new PositionVector(location.x, location.y));
} else {
if (_startX <= location.x && location.x <= _endX && _startY <= location.y && location.y <= _endY) {
positions.add(new PositionVector(location.x - _startX, location.y - _startY));
} else {
set = true;
}
}
}
if (set) {
return positions;
} else {
return Collections.emptyList();
}
}
@Override
public Location getEdgeMeanPosition(String pEdgeID) {
List<Location> positions = new ArrayList<>();
for (RoadNetworkLane lane : _roadNetwork.getEdge(pEdgeID).getLanes()) {
String laneID = lane.getLaneID();
positions.addAll(getLaneShape(laneID));
}
double x = 0;
double y = 0;
int count = 0;
for (Location position : positions) {
x += position.getLongitude();
y += position.getLatitude();
count++;
}
return new PositionVector(x / (count), y / (count));
}
@Override
public double getVehicleSpeed(String pVehicleID) {
SumoCommand speedCommand = Vehicle.getSpeed(pVehicleID);
Object object = requestObject(speedCommand);
return (Double)object;
}
@Override
public double getLastStepMeanSpeed(String pEdgeID) {
SumoCommand speedCommand = Edge.getLastStepMeanSpeed(pEdgeID);
Object object = requestObject(speedCommand);
return (Double)object;
}
@Override
public void setEdgeMaxSpeed(String pEdgeID, double pMaxSpeed) {
SumoCommand setMaxSpeedCommand = Edge.setMaxSpeed(pEdgeID, pMaxSpeed);
execute(setMaxSpeedCommand);
RoadNetworkEdge edge = getRoadNetwork().getEdge(pEdgeID);
edge.setMaxSpeed(pMaxSpeed);
}
@Override
public double getEdgeLength(String pEdgeID) {
double length = 0;
for (RoadNetworkLane lane : _roadNetwork.getEdge(pEdgeID).getLanes()) {
SumoCommand speedCommand = Lane.getLength(lane.getLaneID());
Object object = requestObject(speedCommand);
length += (double) object;
}
return length / (_roadNetwork.getEdge(pEdgeID).getLaneAmount());
}
@Override
public boolean isEdgeUsable(String pEdgeID) {
if (_observedAreaSet) {
List<RoadNetworkLane> lanes = _roadNetwork.getEdge(pEdgeID).getLanes();
if (lanes.size() > 0) {
List<Location> laneShape = getLaneShape(lanes.get(0).getLaneID());
if (laneShape.size() > 1) {
return true;
}
}
return false;
}
return true;
}
/**
* @return the startX
*/
@Override
public double getStartX() {
return _startX;
}
/**
* @return the startY
*/
@Override
public double getStartY() {
return _startY;
}
/**
* @return the endX
*/
@Override
public double getEndX() {
return _endX;
}
/**
* @return the endY
*/
@Override
public double getEndY() {
return _endY;
}
/**
* @return the observedAreaSet
*/
@Override
public boolean isObservedAreaSet() {
return _observedAreaSet;
}
}
package de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.xml;
import org.xml.sax.SAXException;
public class CancelParsingSAXException extends SAXException {
/**
*
*/
private static final long serialVersionUID = 1L;
}
package de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.xml;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
public class SimulationSetupInformationHandler extends DefaultHandler {
private Location _upperLeft;
private Location _lowerRight;
@Override
public void startElement(String pUri, String pLocalName, String pQName, Attributes pAttributes)
throws SAXException {
if (pQName.equals("location")) {
String meterBoundary = pAttributes.getValue("convBoundary");
if (meterBoundary != null) {
String[] edges = meterBoundary.split(",");
_upperLeft = new PositionVector(Double.valueOf(edges[0]), Double.valueOf(edges[1]), 0);
_lowerRight = new PositionVector(Double.valueOf(edges[2]), Double.valueOf(edges[3]), 0);
}
throw new CancelParsingSAXException();
}
}
public Location getLowerRight() {
return _lowerRight;
}
public Location getUpperLeft() {
return _upperLeft;
}
}
package de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.xml;
import java.util.HashMap;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.VehicleInformationContainer;
public class VehicleDataInformationHandler extends DefaultHandler {
private boolean _next = true;
private boolean _run = true;
private HashMap<String, VehicleInformationContainer> _vehiclePositions = new HashMap<>();
private double _currentStep = -1;
private boolean _observedAreaSet = false;
private double _startX = -1;
private double _startY = -1;
private double _endX = -1;
private double _endY = -1;
private HashMap<String, VehicleInformationContainer> _nextVehiclePositions = new HashMap<>();
private double _nextStep = -1;
private static final String doublePattern = "-?[0-9]*\\.?[0-9]+";
private boolean _terminated = false;
@Override
public void startElement(String pUri, String pLocalName, String pQName, Attributes pAttributes)
throws SAXException {
if (pQName.equals("timestep")) {
while (!_next) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
_next = false;
String value = pAttributes.getValue("time");
if (value.matches(doublePattern)) {
_nextStep = Double.valueOf(value);
}
} else if (pQName.equals("vehicle")) {
String id = pAttributes.getValue("id");
String lonString = pAttributes.getValue("x");
String latString = pAttributes.getValue("y");
String speedString = pAttributes.getValue("speed");
String headingString = pAttributes.getValue("angle");
if (lonString.matches(doublePattern) && latString.matches(doublePattern) && headingString.matches(doublePattern) && speedString.matches(doublePattern) ) {
double lon = Double.valueOf(lonString);
double lat = Double.valueOf(latString);
double heading = Double.valueOf(headingString);
double speed = Double.valueOf(speedString);
if (_observedAreaSet) {
if (_startX <= lon && lon <= _endX && _startY <= lat && lat <= _endY) {
_nextVehiclePositions.put(id, new VehicleInformationContainer(new PositionVector(lon - _startX, lat - _startY, 0), heading, speed, null));
}
} else {
_nextVehiclePositions.put(id, new VehicleInformationContainer(new PositionVector(lon, lat, 0), heading, speed, null));
}
}
}
}
@Override
public void endElement(String pUri, String pLocalName, String pQName) throws SAXException {
if (pQName.equals("timestep")) {
_run = false;
} else if (pQName.equals("fcd-export")) {
while (!_next) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
_next = false;
_run = false;
_terminated = true;
}
}
public void setObservedArea(double pStartX, double pStartY, double pEndX, double pEndY) {
_startX = pStartX;
_startY = pStartY;
_endX = pEndX;
_endY = pEndY;
_observedAreaSet = true;
}
public boolean isTerminated() {
return _terminated;
}
public HashMap<String, VehicleInformationContainer> getVehiclePositions() {
return _vehiclePositions;
}
public void readNext() {
while (_run) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
_vehiclePositions = _nextVehiclePositions;
_currentStep = _nextStep;
_nextStep = -1;
_nextVehiclePositions = new HashMap<>();
_run = true;
_next = true;
}
public boolean isRunning() {
return _run;
}
public double getStep() {
return _currentStep;
}
}
package de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.xml;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.VehicleInformationContainer;
import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.csv.RoadSideUnitInformationHandler;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.api.SimulationSetupExtractor;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.api.VehicleController;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.roadnetwork.RoadNetwork;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.roadnetwork.RoadNetworkEdge;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.roadnetwork.RoadNetworkRoute;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.roadnetwork.exception.NoAdditionalRouteAvailableException;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.roadnetwork.exception.NoExitAvailableException;
public class XMLSimulationController implements VehicleController, SimulationSetupExtractor, Runnable {
private String _vehicleDataPath;
private String _roadSideUnitDataPath;
private List<String> _vehicles;
private Map<Double, Map<String, VehicleInformationContainer>> _positonsByTimestamp = new HashMap<>();
private int _futureInformation = 0;
private boolean _initalized = false;
private VehicleDataInformationHandler _vehicleDataInformationHandler = new VehicleDataInformationHandler();
private RoadSideUnitInformationHandler _roadSideUnitInformationHandler = new RoadSideUnitInformationHandler();
private double _start = -1;
private double _step;
public XMLSimulationController(String pVehicleDataPath, String pRoadSideUnitDataPath) {
this(pVehicleDataPath);
_roadSideUnitDataPath = pRoadSideUnitDataPath;
}
public XMLSimulationController(String pVehicleDataPath) {
_vehicleDataPath = pVehicleDataPath;
}
@Override
public void init() {
if (!_initalized) {
if (_vehicleDataPath != null) {
Thread thread = new Thread(this);
thread.start();
for (int i = 0; i < _futureInformation; i++) {
nextStep();
}
}
if (_roadSideUnitDataPath != null) {
_roadSideUnitInformationHandler.parseIntersectionsFile(_roadSideUnitDataPath);
}
_initalized = true;
}
}
@Override
public Location getVehiclePosition(String pVehicleID) {
return getVehiclePosition(_step, pVehicleID);
}
public VehicleInformationContainer requestVehicleInformation(String pVehicleID) {
return _vehicleDataInformationHandler.getVehiclePositions().get(pVehicleID);
}
@Override
public boolean nextStep() {
_vehicleDataInformationHandler.readNext();
_step = _vehicleDataInformationHandler.getStep() - _futureInformation;
if (_start == -1) {
_start = _vehicleDataInformationHandler.getStep();
}
double newStep = _step + _futureInformation;
if (!_positonsByTimestamp.containsKey(newStep)) {
Map<String, VehicleInformationContainer> vehiclePositions = new HashMap<>();
_positonsByTimestamp.put(newStep, vehiclePositions);
List<String> allVehicles = new ArrayList<>(_vehicleDataInformationHandler.getVehiclePositions().keySet());
for (String vehicle : allVehicles) {
VehicleInformationContainer vehiclePosition = requestVehicleInformation(vehicle);
if (vehiclePosition != null) {
vehiclePositions.put(vehicle, vehiclePosition);
}
}
}
return !_vehicleDataInformationHandler.isTerminated();
}
@Override
public List<String> getAllVehicles() {
return getAllVehicles(_step);
}
@Override
public double getStep() {
return _step;
}
@Override
public double getStart() {
return _start;
}
@Override
public void run() {
try {
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
parser.parse(new FileInputStream(_vehicleDataPath), _vehicleDataInformationHandler);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void setObservedArea(double pStartX, double pStartY, double pEndX, double pEndY) {
_vehicleDataInformationHandler.setObservedArea(pStartX, pStartY, pEndX, pEndY);
_roadSideUnitInformationHandler.setObservedArea(pStartX, pStartY, pEndX, pEndY);
}
@Override
public Location getVehiclePosition(double pStep, String pVehicleID) {
Map<String, VehicleInformationContainer> map = _positonsByTimestamp.get(pStep);
return map.get(pVehicleID).getPosition();
}
@Override
public List<String> getAllVehicles(double pStep) {
Map<String, VehicleInformationContainer> map = _positonsByTimestamp.get(pStep);
return new ArrayList<>(map.keySet());
}
@Override
public double getMaximumAvailablePrediction() {
double max = Collections.max(_positonsByTimestamp.keySet());
return max;
}
@Override
public List<Location> getAllIntersections(boolean pCluster) {
return _roadSideUnitInformationHandler.getIntersections();
}
@Override
public double getScenarioWidth() {
return -1;
}
@Override
public double getScenarioHeight() {
return -1;
}
@Override
public RoadNetworkRoute getCurrentRoute(String pVehicleID) {
throw new UnsupportedOperationException("This method is not supported for " + getClass().getSimpleName());
}
@Override
public RoadNetwork getRoadNetwork() {
return null;
}
@Override
public void rerouteVehicle(String pVehicle, RoadNetworkRoute pRoute) {
throw new UnsupportedOperationException("This method is not supported for " + getClass().getSimpleName());
}
@Override
public RoadNetworkRoute findNewRoute(String pVehicle)
throws NoAdditionalRouteAvailableException {
throw new UnsupportedOperationException("This method is not supported for " + getClass().getSimpleName());
}
@Override
public RoadNetworkRoute findNewRoute(String pVehicle,
List<RoadNetworkEdge> pEdgesToAvoid, boolean pKeepDestination)
throws NoAdditionalRouteAvailableException,
NoExitAvailableException {
throw new UnsupportedOperationException("This method is not supported for " + getClass().getSimpleName());
}
@Override
public void stopVehicle(String pVehicle) {
throw new UnsupportedOperationException("This method is not supported for " + getClass().getSimpleName());
}
@Override
public double getVehicleSpeed(String pVehicleID) {
return _vehicleDataInformationHandler.getVehiclePositions().get(pVehicleID).getSpeed();
}
@Override
public double getVehicleHeading(String pVehicleID) {
return _vehicleDataInformationHandler.getVehiclePositions().get(pVehicleID).getHeading();
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.placement;
import java.util.List;
import de.tud.kom.p2psim.api.topology.TopologyComponent;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.traci.TraciSimulationController;
import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.xml.XMLSimulationController;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.api.SimulationSetupExtractor;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/**
*/
public class RSUPlacement implements PlacementModel {
private final String sumoExe;
private final String sumoConfigFile;
private final String sumoIntersections;
private final int offsetX;
private final int offsetY;
private final int width;
private final int height;
private SimulationSetupExtractor _controller;
private List<Location> _intersections;
private int _currentIndex = 0;
@XMLConfigurableConstructor({ "sumoExe", "sumoConfigFile", "offsetX", "offsetY", "width", "height" })
public RSUPlacement(String sumoExe, String sumoConfigFile, String offsetX, String offsetY, String width, String height) {
this.sumoExe = sumoExe;
this.sumoConfigFile = sumoConfigFile;
this.sumoIntersections = null;
this.offsetX = Integer.parseInt(offsetX);
this.offsetY = Integer.parseInt(offsetY);
this.width = Integer.parseInt(width);
this.height = Integer.parseInt(height);
initializeModel();
}
@XMLConfigurableConstructor({ "sumoIntersections", "offsetX", "offsetY", "width", "height" })
public RSUPlacement(String sumoIntersections, String offsetX, String offsetY, String width, String height) {
this.sumoIntersections = sumoIntersections;
this.sumoExe = null;
this.sumoConfigFile = null;
this.offsetX = Integer.parseInt(offsetX);
this.offsetY = Integer.parseInt(offsetY);
this.width = Integer.parseInt(width);
this.height = Integer.parseInt(height);
initializeModel();
}
/**
* Initializes the movement model by executing BonnMotion and parsing the
* resulting movement trace.
*/
protected void initializeModel() {
if (this.sumoExe != null) {
_controller = TraciSimulationController.createSimulationController(sumoExe, sumoConfigFile);
_controller.init();
_controller.setObservedArea(offsetX, offsetY, offsetX + width, offsetY + height);
_intersections = _controller.getAllIntersections(true);
} else {
_controller = new XMLSimulationController(null, sumoIntersections);
_controller.init();
_controller.setObservedArea(offsetX, offsetY, offsetX + width, offsetY + height);
_intersections = _controller.getAllIntersections(true);
}
}
@Override
public void addComponent(TopologyComponent comp) {
//
}
@Override
public PositionVector place(TopologyComponent comp) {
if (_currentIndex < _intersections.size()) {
Location intersection = _intersections.get(_currentIndex);
_currentIndex++;
return new PositionVector(intersection.getLongitude(), intersection.getLatitude());
} else {
return new PositionVector(Double.NaN, Double.NaN);
}
}
}
...@@ -43,6 +43,7 @@ import java.util.Collection; ...@@ -43,6 +43,7 @@ import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
...@@ -387,7 +388,7 @@ public class VisualizationTopologyView extends JFrame ...@@ -387,7 +388,7 @@ public class VisualizationTopologyView extends JFrame
*/ */
protected class WorldPanel extends JLayeredPane { protected class WorldPanel extends JLayeredPane {
protected HashMap<INodeID, VisNodeInformation> nodeInformation = new HashMap<INodeID, VisNodeInformation>(); protected ConcurrentHashMap<INodeID, VisNodeInformation> nodeInformation = new ConcurrentHashMap<INodeID, VisNodeInformation>();
protected final static int PADDING = 16; protected final static int PADDING = 16;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment