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;
/**
* Represents the header of a bitmap.
*
* @author Andr Mink, Sebastian Kaune
* @author Andr Mink, Sebastian Kaune
*/
public class BitmapHeader {
public int nsize; // Size of file
......
......@@ -32,7 +32,7 @@ import java.util.ArrayList;
* colorTable of the bitmap. Currently, there are only 8bit bitmaps (256 colors)
* supported.
*
* @author Andr Mink, Sebastian Kaune
* @author Andr Mink, Sebastian Kaune
*/
public class BitmapLoader {
public int[][] cartesianSpace;
......
......@@ -3584,7 +3584,7 @@ public class regionName {
if (country_code.equals("FI") == true) {
switch (region_code2) {
case 1:
name = "land";
name = "land";
break;
case 6:
name = "Lapland";
......@@ -6683,7 +6683,7 @@ public class regionName {
name = "Aqmola";
break;
case 4:
name = "Aqtbe";
name = "Aqtbe";
break;
case 5:
name = "Astana";
......@@ -7071,7 +7071,7 @@ public class regionName {
name = "Bauskas";
break;
case 5:
name = "Csu";
name = "Csu";
break;
case 6:
name = "Daugavpils";
......@@ -7086,7 +7086,7 @@ public class regionName {
name = "Gulbenes";
break;
case 10:
name = "Jkabpils";
name = "Jkabpils";
break;
case 11:
name = "Jelgava";
......@@ -7098,16 +7098,16 @@ public class regionName {
name = "Jurmala";
break;
case 14:
name = "Krslavas";
name = "Krslavas";
break;
case 15:
name = "Kuldigas";
break;
case 16:
name = "Liepja";
name = "Liepja";
break;
case 17:
name = "Liepjas";
name = "Liepjas";
break;
case 18:
name = "Limbazu";
......@@ -7125,10 +7125,10 @@ public class regionName {
name = "Preilu";
break;
case 23:
name = "Rzekne";
name = "Rzekne";
break;
case 24:
name = "Rzeknes";
name = "Rzeknes";
break;
case 25:
name = "Riga";
......
......@@ -662,7 +662,7 @@ public class DefaultConfigurator implements Configurator {
}
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);
String varName = value.substring(posDollar + 1, value.length());
value = variables.get(varName);
......
......@@ -2,17 +2,17 @@
* Copyright (c) 2005-2011 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/>.
*
......@@ -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
* experiment is controlled by the scheduler and the parameters defined by the
* Application.
*
*
* @author Sebastian Kaune
*/
public class Scheduler implements EventHandler,
SchedulerComponent, TimeComponent {
SchedulerComponent, TimeComponent {
// Flag to allow the compiler to remove the unneeded debug code
private static final boolean DEBUG_CODE = false;
......@@ -96,7 +96,7 @@ public class Scheduler implements EventHandler,
/**
* Constructs a new scheduler instance using a calendar queue. If desired,
* status events about the progress of the simulation will be plotted.
*
*
* @param statusEvent
* the flag which speficies if status events will be plotted
*/
......@@ -158,7 +158,7 @@ public class Scheduler implements EventHandler,
/**
* Wake up thread safe and insert event immediately.
*
*
* @param content
* the content
* @param handler
......@@ -198,17 +198,17 @@ public class Scheduler implements EventHandler,
}
Monitor.log(Scheduler.class, Level.INFO,
"Simulated realtime: " + Time.getFormattedTime()
+ " - End of simulation.\n Scheduler processed in total "
+ this.processedEventCounter + " events with "
+ this.eventQueue.size()
+ " unprocessed events still in queue");
+ " - End of simulation.\n Scheduler processed in total "
+ this.processedEventCounter + " events with "
+ this.eventQueue.size()
+ " unprocessed events still in queue");
}
/**
* Sets the end time at which the simulation framework will finish at the
* latest the simulation , irrespective if there are still unprocessed
* events in the event queue.
*
*
* @param endTime
* point in time at which the simulator will finish at the latest
*/
......@@ -223,7 +223,7 @@ public class Scheduler implements EventHandler,
/**
* Process the next event from the event queue.
*
*
* @return whether an event was processed
*/
synchronized private boolean processNextEvent() {
......@@ -252,9 +252,9 @@ public class Scheduler implements EventHandler,
}
assert (nextEvent.getSimulationTime() >= currentTime) : "Next event: "
+ nextEvent.getSimulationTime()
+ ", but current "
+ currentTime + ".";
+ nextEvent.getSimulationTime()
+ ", but current "
+ currentTime + ".";
if (nextEvent.getSimulationTime() <= newRoundsCurrentTime) {
......@@ -273,7 +273,7 @@ public class Scheduler implements EventHandler,
if (realEvent.schedulerType == TYPE_END)
return false;
synchronized (this.eventQueue) {
if (this.eventQueue.peek().getSimulationTime() < newRoundsCurrentTime) {
unhandledRegularEventsInPast = true;
......@@ -310,9 +310,9 @@ public class Scheduler implements EventHandler,
}
assert (peekedEvent.getSimulationTime() >= currentTime) : "Next event: "
+ peekedEvent.getSimulationTime()
+ ", but current "
+ currentTime + ".";
+ peekedEvent.getSimulationTime()
+ ", but current "
+ currentTime + ".";
if (peekedEvent.getSimulationTime() > currentTime) {
......@@ -326,12 +326,12 @@ public class Scheduler implements EventHandler,
/*
* ATTENTION: Magic happening here!
*
*
* Correct for uncertainties of going to real sleep.
*/
final long SLEEP_CORRECTION_FACTOR = 400;
final long realTime_errorMs = System.currentTimeMillis()
- 0 /* Starttime */
- 0 /* Starttime */
- (currentTime / Time.MILLISECOND);
final long realTime_correctedTimeToWaitMs = realTime_timeToWaitMs
- (realTime_errorMs / SLEEP_CORRECTION_FACTOR);
......@@ -379,8 +379,8 @@ public class Scheduler implements EventHandler,
final SchedulerEvent realEvent = this.eventQueue.remove();
assert (realEvent.getSimulationTime() >= currentTime) : "Next event: "
+ realEvent.getSimulationTime() + ", but current "
+ currentTime + ".";
+ realEvent.getSimulationTime() + ", but current "
+ currentTime + ".";
if (timeSkew > 0) {
/*
......@@ -392,7 +392,7 @@ public class Scheduler implements EventHandler,
if (timeToWait > 0) {
Monitor.log(Scheduler.class, Level.DEBUG,
"Scheduler sleeping: " + timeToWait / 1000
+ " milliseconds");
+ " milliseconds");
try {
Thread.sleep((long) ((timeToWait / 1000) / timeSkew));
......@@ -437,7 +437,7 @@ public class Scheduler implements EventHandler,
/**
* Return whether event queue is empty.
*
*
* @return whether event queue is empty.
*/
public boolean isEmpty() {
......@@ -446,16 +446,17 @@ public class Scheduler implements EventHandler,
/**
* Returns the current time of the scheduler
*
*
* @return current scheduler time
*/
@Override
public long getCurrentTime() {
return currentTime;
}
/**
* Returns the end time of the scheduler
*
*
* @return
*/
public long getEndTime() {
......@@ -475,7 +476,7 @@ public class Scheduler implements EventHandler,
/**
* Method for JUnit tests in order to verify the correctness
*
*
* @return number of events in event queue.
*/
public int getEventQueueSize() {
......@@ -483,7 +484,7 @@ public class Scheduler implements EventHandler,
}
protected static final class SchedulerEvent implements
Comparable<SchedulerEvent> {
Comparable<SchedulerEvent> {
protected final int schedulerType;
......@@ -494,9 +495,9 @@ public class Scheduler implements EventHandler,
protected final Object data;
protected long simTime;
protected long globalOrderIdx;
protected static long globalOrderCounter = 0;
protected SchedulerEvent(Object data, long simTime,
......@@ -518,6 +519,7 @@ public class Scheduler implements EventHandler,
return simTime;
}
@Override
public int compareTo(SchedulerEvent o) {
int comp = Double.compare(this.simTime, o.simTime);
return comp == 0 ? Double.compare(this.globalOrderIdx, o.globalOrderIdx) : comp;
......@@ -530,7 +532,7 @@ public class Scheduler implements EventHandler,
/**
* Returns wheather the scheduler is running in realTime mode or not.
*
*
* @return the real time
*/
public boolean getRealTime() {
......@@ -540,7 +542,7 @@ public class Scheduler implements EventHandler,
/**
* a flag for slowing down the simulation down to real time. This flag only
* makes sense for simulations which run faster than real time
*
*
* @param realTime
* flag for switching the scheduler to real time mode
*/
......@@ -556,7 +558,7 @@ public class Scheduler implements EventHandler,
/**
* method for setting the time skew. A time skew of 100 means, that the
* simulation runs 100 times faster than real time
*
*
* @param timeSkew
* the time skew
*/
......@@ -567,10 +569,14 @@ public class Scheduler implements EventHandler,
}
}
public double getTimeSkew() {
return timeSkew;
}
/**
* Sets the simulation speed lock, changes in setRealTime or setTimeSkew
* will not apply while the lock is set.
*
*
* @param locked
* the new simulation speed locked
*/
......@@ -593,7 +599,7 @@ public class Scheduler implements EventHandler,
/**
* The comparator
*
*
* @author Bjoern Richerzhagen
* @version 1.0, 05.03.2012
*/
......
......@@ -2,17 +2,17 @@
* Copyright (c) 2005-2011 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/>.
*
......@@ -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
* by calling the main method in the SimulatorRunner class.
*
*
* @author Sebastian Kaune
* @author Konstantin Pussep
* @version 3.0, 11/29/2007
*
*
*/
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.
*/
public final static double NANOSECOND_UNIT = 1E-3d;
/**
* These constant should be ALWAYS used for virtual time calculations.
*/
......@@ -130,7 +130,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
/**
* This class is singleton, so use getInstance() method to obtain a
* reference to it.
*
*
*/
private Simulator() {
singleton = this;
......@@ -145,7 +145,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
/**
* Returns the single instance of the SimulationFramework
*
*
* @return the SimulationFramework
*/
public static Simulator getInstance() {
......@@ -158,10 +158,10 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
scheduler.reset();
}
/**
/**
* Set the scenario (protocol stack, network topology etc.) which will be
* used to run the simulation.
*
*
* @param scenario
* simulation scenario to be used
*/
......@@ -172,7 +172,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
/**
* Returns the scenario used to run the simulation.
*
*
* @return
*/
public Scenario getScenario() {
......@@ -181,7 +181,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
/**
* Only for internal use
*
*
* @return
*/
public static Scheduler getScheduler() {
......@@ -195,35 +195,35 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
/**
* This method will run the simulation using the previously set scenario
* data.
*
*
*/
public void start(boolean throwExceptions) {
checkRunning();
Monitor.log(Simulator.class, Level.INFO, "Prepare Scenario ...");
this.scenario.prepare();
Monitor.log(Simulator.class, Level.INFO, "Prepare Scenario ..."
+ getSeed());
/* Real World Starting Time:
* Block till we're allowed to start.
* Block till we're allowed to start.
*/
if( realWorldStartTime != null ) {
try {
//final Date now = new Date();
final Date now = NTPClient.getDate();
final long waitFor = realWorldStartTime.getTime() - now.getTime();
Thread.sleep(waitFor);
} catch (InterruptedException e) {
//
}
}
startTime = System.currentTimeMillis();
Monitor.log(Simulator.class, Level.INFO, "Simulation started...");
this.running = true;
......@@ -282,53 +282,53 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
/**
* Configure simulation from an XML file.
*
*
* @param configFile
* XML file with the configuration data.
* @param variables
* the variables which are specified in the XML file with the
* configuarion data.
*/
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
// simulation, which can be accessed from every component during a
// simulation. This can be seen as an alternative to implementing the
// Composable interface
if (configFile.endsWith(".xml")) {
this.defaultConfigurator = new DefaultConfigurator(configFile);
defaultConfigurator.setVariables(variables);
} else {
SimCfgConfigurator simCfgConfigurator = new SimCfgConfigurator(configFile);
simCfgConfigurator.applyVariations(variations);
simCfgConfigurator.setVariables(modifiedVariables);
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
// simulation, which can be accessed from every component during a
// simulation. This can be seen as an alternative to implementing the
// Composable interface
if (configFile.endsWith(".xml")) {
this.defaultConfigurator = new DefaultConfigurator(configFile);
defaultConfigurator.setVariables(variables);
} else {
SimCfgConfigurator simCfgConfigurator = new SimCfgConfigurator(configFile);
simCfgConfigurator.applyVariations(variations);
simCfgConfigurator.setVariables(modifiedVariables);
this.defaultConfigurator = simCfgConfigurator;
}
this.defaultConfigurator = simCfgConfigurator;
}
this.defaultConfigurator.register(Configurator.CORE, this);
this.defaultConfigurator.register(Configurator.CORE, this);
this.defaultConfigurator.configureAll();
// The next steps are only required for the xml version.
// SimCfg will execute them in the configurator
if (configFile.endsWith(".xml")) {
ScenarioFactory scenarioBuilder = (ScenarioFactory) this.defaultConfigurator.getConfigurable(Configurator.SCENARIO_TAG);
// The next steps are only required for the xml version.
// SimCfg will execute them in the configurator
if (configFile.endsWith(".xml")) {
ScenarioFactory scenarioBuilder = (ScenarioFactory) this.defaultConfigurator.getConfigurable(Configurator.SCENARIO_TAG);
if (scenarioBuilder == null)
throw new ConfigurationException(
"No scenario builder specified in the configuration file. Nothing to do.");
if (scenarioBuilder == null)
throw new ConfigurationException(
"No scenario builder specified in the configuration file. Nothing to do.");
Scenario scenario = scenarioBuilder.createScenario();
setScenario(scenario);
}
Scenario scenario = scenarioBuilder.createScenario();
setScenario(scenario);
}
}
/**
* Returns the seed used within a simulation run.
*
*
* @return the predefined seed
*
*
*/
public static long getSeed() {
return seed;
......@@ -337,7 +337,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
/**
* This method sets the seed of the global random generator which can be
* obtained using the static getRandom()-method.
*
*
* @param seed
* the seed to configure the global random generator
*/
......@@ -356,53 +356,53 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
throw new IllegalStateException("Simulator is already running.");
}
/**
* This method provides a newly created random generator, configured
* with the specified seed of the simulator. This method should be preferred
* over the deprecated @{link getRandom}.
*
* <b>Notes:</b>
* Doing so will prevent components from influencing each other, thus creating
* 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
* different situations:
* 1. Random generators belonging to a single component should pass the class
* object of that component to this method.
* 2. Components that are always loaded during a simulation can use the
* Simulator.class object for a system wide random generator like {@link #getRandom()}
* provided.
* 3. Utility classes that are loaded by many different components should use
* a reference to themselves to avoid transitive dependencies on the same random
* generator throughout different components.
* 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
* behavior from one configured scenario to another.
*
* @param source The source that requires the random generator (component class object is preferred)
* @param salt Added to the default seed, should be bound
* @return The random generator for the given source
*/
/**
* This method provides a newly created random generator, configured
* with the specified seed of the simulator. This method should be preferred
* over the deprecated @{link getRandom}.
*
* <b>Notes:</b>
* Doing so will prevent components from influencing each other, thus creating
* 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
* different situations:
* 1. Random generators belonging to a single component should pass the class
* object of that component to this method.
* 2. Components that are always loaded during a simulation can use the
* Simulator.class object for a system wide random generator like {@link #getRandom()}
* provided.
* 3. Utility classes that are loaded by many different components should use
* a reference to themselves to avoid transitive dependencies on the same random
* generator throughout different components.
* 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
* behavior from one configured scenario to another.
*
* @param source The source that requires the random generator (component class object is preferred)
* @param salt Added to the default seed, should be bound
* @return The random generator for the given source
*/
@Override
public Random getRandom(Object source) {
if (randomGenerators.containsKey(source)) {
return randomGenerators.get(source);
} else {
if (randomGenerators.containsKey(source)) {
return randomGenerators.get(source);
} else {
long thisSeed = source.toString().hashCode() + 31
* seed;
Monitor.log(Simulator.class, Level.INFO,
"Created a new Random Source for %s with seed %d", source,
thisSeed);
Random randomGenerator = new Random(thisSeed);
randomGenerators.put(source, randomGenerator);
return randomGenerator;
}
}
randomGenerators.put(source, randomGenerator);
return randomGenerator;
}
}
/**
* Returns the current simulation unit value.
*
*
* @return the current simulation unit value
*/
public static long getCurrentTime() {
......@@ -411,17 +411,17 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
/**
* Returns the start time of the simulation.
*
*
* @return
*/
public static long getStartTime() {
return singleton.startTime;
}
/**
* Returns the end time of the simulation.
*
*
* @return
*/
public static long getEndTime() {
......@@ -432,7 +432,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
* Sets the end time at which the simulation framework will finish at the
* latest the simulation , irrespective if there are still unprocessed
* events in the event queue.
*
*
* @param endTime
* point in time at which the simular will finish at the latest
*/
......@@ -450,7 +450,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
* in turn will save the state in a static variable. Is this flag set
* to true the MeasurementDAO will return from every method before
* doing any work.
*
*
* @param inactive
*/
public void setDatabaseInactive(boolean inactive) {
......@@ -463,25 +463,25 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
}
}
/**
/**
* Overrides the database name provided in the persistence.xml.
*
*
* As the DAO class only provides static methods and is not a singleton it
* cannot be accessed through the config file otherwise.
*
*
* @param database
* @deprecated use the MetricOutputDAO instead to do all relevant
* configuration!
*/
@Deprecated
public void setDatabase(String database) {
DAO.database = database;
}
public void setDatabase(String database) {
DAO.database = database;
}
/**
* Can be used to format the absolute simulation time (current, past or
* future) into human-readable format: (h:m:s:ms).
*
*
* @param time
* - absolute simulation time like the one obtained via
* getCurrentTime();
......@@ -494,7 +494,7 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
/**
* Specifies how often the scheduler will printout the current simulation
* time.
*
*
* @param time
*/
public void setStatusInterval(long time) {
......@@ -512,38 +512,38 @@ public class Simulator implements RandomGeneratorComponent, GlobalComponent {
public void setSimulationSpeedLocked(boolean locked) {
scheduler.setSimulationSpeedLocked(locked);
}
public static Configurator getConfigurator() {
return defaultConfigurator;
}
/**
* Sets the real world start time.
*
* @param realWorldStartTime the new real world start time
*/
public void setRealWorldStartTime(String realWorldStartTime) {
final Date now = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss z dd.MM.yyyy", Locale.GERMANY);
try {
final Date startTime = formatter.parse(realWorldStartTime);
if( now.after(startTime) ) {
throw new AssertionError(
"Simulator was supposed to run in the past. Check config for realWorldStartTime.");
}
}
this.realWorldStartTime = startTime;
} catch (ParseException e) {
Monitor.log(
Simulator.class,
Level.WARN,
"Could not parse realWorldStartTime. Please check configuration file. Starting *NOW*");
}
}
public void addObserver(SimulatorObserver observer) {
......
......@@ -2,17 +2,17 @@
* 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/>.
*
......@@ -67,7 +67,7 @@ import de.tudarmstadt.maki.simonstrator.api.component.transport.ConnectivityList
/**
* Default implementation of a {@link TopologyComponent}.
*
*
* @author Bjoern Richerzhagen
* @version 1.0, 29.02.2012
*/
......@@ -95,7 +95,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
/**
* Create a TopologyComponent for the current host.
*
*
* @param host
* @param topology
* @param movementModel
......@@ -139,10 +139,10 @@ public class DefaultTopologyComponent implements TopologyComponent {
final SiSComponent sis = host.getComponent(SiSComponent.class);
sis.provide().nodeState(SiSTypes.PHY_LOCATION,
new SiSDataCallback<Location>() {
Set<INodeID> localID = INodeID
.getSingleIDSet(getHost().getId());
@Override
public Location getValue(INodeID nodeID,
SiSProviderHandle providerHandle)
......@@ -153,32 +153,61 @@ public class DefaultTopologyComponent implements TopologyComponent {
throw new InformationNotAvailableException();
}
}
@Override
public Set<INodeID> getObservedNodes() {
return localID;
}
@Override
public SiSInfoProperties getInfoProperties() {
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
Event.scheduleImmediately(new EventHandler() {
@Override
public void eventOccurred(Object content, int type) {
if (getHost().getLinkLayer().hasPhy(PhyType.WIFI)) {
new SiSTopologyProvider(sis, SiSTypes.NEIGHBORS_WIFI,
new SiSTopologyProvider(sis,
SiSTypes.NEIGHBORS_WIFI,
DefaultTopologyComponent.this,
getTopologyID(NetInterfaceName.WIFI, true),
DefaultTopologyComponent.class);
}
}
}, null, 0);
} catch (ComponentNotAvailableException e) {
// OK
}
......@@ -206,7 +235,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
public Topology getTopology() {
return topology;
}
/**
* Access to the movement model
* @return
......@@ -279,19 +308,19 @@ public class DefaultTopologyComponent implements TopologyComponent {
locationListener.onLocationChanged(getHost(), getLastLocation());
}
}
@Override
public void setTargetAttractionPoint(AttractionPoint targetAttractionPoint)
throws UnsupportedOperationException {
movementModel.changeTargetLocation(this, targetAttractionPoint);
// NodeDebugMonitor.update(this.getClass(), getHost().getId(), "Target Location", targetAttractionPoint);
}
@Override
public AttractionPoint getCurrentTargetAttractionPoint() {
return movementModel.getTargetLocation(this);
}
@Override
public Set<AttractionPoint> getAllAttractionPoints() {
return movementModel.getAllAttractionPoints();
......@@ -339,7 +368,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
/**
* Update 15.03.16 added support for multiple listeners (however, frequency
* etc. is immune after the first request is registered.)
*
*
* @author Bjoern Richerzhagen
* @version 1.0, Mar 15, 2016
*/
......@@ -354,7 +383,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
private Location lastLocation = null;
private List<LocationListener> listeners = new LinkedList<LocationListener>();
private int eventTypeSeq = 0;
public LocationRequestImpl() {
......@@ -402,9 +431,9 @@ public class DefaultTopologyComponent implements TopologyComponent {
public void eventOccurred(Object content, int type) {
if (eventTypeSeq != type) {
/*
* Discard invalid events caused when a client cancels updates
* but reactivates the request within the update frequency
* interval. In this case, the old events continue rescheduling
* Discard invalid events caused when a client cancels updates
* but reactivates the request within the update frequency
* interval. In this case, the old events continue rescheduling
* themselves.
*/
return;
......@@ -413,7 +442,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
// Only reschedule, if at least one listener is ... listening
Location newLoc = getLastLocation();
listeners.forEach((LocationListener listener) -> listener
.onLocationChanged(getHost(), newLoc));
.onLocationChanged(getHost(), newLoc));
lastLocation = newLoc;
Event.scheduleWithDelay(interval, this, null, eventTypeSeq);
}
......@@ -448,7 +477,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
boolean onlyOnline, double range) {
TopologyID id = TopologyID.getIdentifier(
netName.toString() + (onlyOnline ? "-online" : "-all")
+ String.valueOf(range),
+ String.valueOf(range),
DefaultTopologyComponent.class);
if (!this.graphViews.containsKey(id)) {
this.graphViews.put(id,
......@@ -483,12 +512,12 @@ public class DefaultTopologyComponent implements TopologyComponent {
/**
* This is calculated based on global knowledge. It only registers as
* {@link LocationListener}, if a range is specified by the Provider.
*
*
* @author Bjoern Richerzhagen
* @version 1.0, May 13, 2015
*/
private class LocalGraphView
implements LocationListener, ConnectivityListener {
implements LocationListener, ConnectivityListener {
/**
* Marker: has there been any movement since the graph view was last
......@@ -550,8 +579,8 @@ public class DefaultTopologyComponent implements TopologyComponent {
if (host.getNetworkComponent()
.getByName(medium) != null) {
host.getNetworkComponent().getByName(medium)
.addConnectivityListener(
LocalGraphView.this);
.addConnectivityListener(
LocalGraphView.this);
}
}
}
......@@ -636,7 +665,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
IEdge edge = currentView.createEdge(
mac.getHost().getId(),
topoView.getMac(neighborMac).getHost()
.getId());
.getId());
currentView.addElement(edge);
edge.setProperty(SiSTypes.PHY_DISTANCE,
topoView.getDistance(mac.getMacAddress(),
......@@ -666,7 +695,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
/**
* This is the global view, therefore we do not distinguish between
* hosts.
*
*
* @return
*/
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.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;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArrayList;
......@@ -387,7 +388,7 @@ public class VisualizationTopologyView extends JFrame
*/
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;
......
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