ONE有2个模式: GUI 和 TextUI。我们只讨论文本模式 TextUI。三者之间有继承关系。模式和参数指定 通过main函数参数指定。
类DTNSimUI 有成员: 类 World; Vector reports; 类SimScenario.
类SimScenario有成员: List hosts;
文本模式 从 DTNSimTextUI.start() 即 DTNSimUI.start() 启动;
文本有两大流程 (1)DTNSimUI.initModel(); (2) DTNSimUI.runSim(); 即 DTNSimTextUI.runSim();
首先,Settings.init() 通过读取配置文件,再由 Properties 实现(Java的Properties机制); 类Properties 的 Properties.load();
之后进行两大流程
*
- DTNSimUI.initModel(); 初始化过程
Init过程 的 总体流程如下:
1.1 new Settings(); 之前已经通过 Settings.init()设置好, 现在实例化Setting即可得到相应的配置
1.2 new SimScenario();
根据 Settings读取到的配置设定 仿真环境;
1.3 new Report 等类
1.4 由Settings得到warmupTime后, SimClock.setTime();
1.5 SimScenario.createHosts();
每个Group里的各个Host用同样的 MovementModel 和 MessageRouter
for each Groups; 对每个group 里的 Host 逐个进行new, 属性包括 transmitRange,transmitSpeed ,尤其是 MovementModel 和 MessageRouter
//在函数 SimScenario.createHosts();里面 for each Group;
MovementModel mmProto = (MovementModel)s.createIntializedObject(MM_PACKAGE +s.getSetting(MOVEMENT_MODEL_S));
MessageRouter mRouterProto = (MessageRouter)s.createIntializedObject(ROUTING_PACKAGE +s.getSetting(ROUTER_S));
//看作
//...等其他操作
DTNHost host = new DTNHost(this.connectionListeners,
this.messageListeners, this.movementListeners,
gid, transmitRange, transmitSpeed, mmProto,
mRouterProto);
配置文件 default_settings.txt 里相应的配置:
##默认配置
Group.movementModel = ShortestPathMapBasedMovement
##Group.router = PassiveRouter
Group.router = EpidemicRouter
##各个Group的个性配置, 如果没有个性配置,则按照默认配置
Group4.movementModel = MapRouteMovement
Group4.routeFile = data/tram3.wkt
Group4.routeType = 1
Group4.waitTime = 10, 30
Group4.speed = 7, 10
Group4.nrofHosts = 2
Group5.routeFile = data/tram4.wkt
Group5.routeType = 2
Group6.movementModel = MapRouteMovement
Group6.routeFile = data/tram10.wkt
Group6.routeType = 2
之后 SimScenario.hosts.add(host);
1.6 new World(this.scen); world.warmupMovementModel(warmupTime);
1.7 如果warmupTime>0; 即存在 warmup流程;
例如:若warmupTime=3000, 类SimClock的time起始被设置为-3000,一直执行moveHost,直到 类SimClock的time为0
//World.warmupMovementModel(warmupTime)
public void warmupMovementModel(double time) {
if (time <= 0) {
return;
}
while(SimClock.getTime() < -updateInterval) {
moveHosts(updateInterval);
simClock.advance(updateInterval);
}
double finalStep = -SimClock.getTime();
moveHosts(finalStep);
simClock.setTime(0);
}
*
-
DTNSimUI.runSim(); 即 DTNSimTextUI.runSim(); 执行流程
while (simTime < endTime && !simCancelled){ try { world.update(); //更新的过程中 已经增加 clockTime; } catch (AssertionError e) { e.printStackTrace(); done(); return; } simTime = SimClock.getTime(); //此处 只是获取 SimClock.clockTime; this.update(false); } done(); this.update(true); // force final UI update
2.1 World.update()是 主要的更新函数
/**
* Update (move, connect, disconnect etc.) all hosts in the world.
* Performs external events if there are any happening before next time
* value
*/
public void update () {
double timeIncrement = this.updateInterval; //每次事件步进的 长度
// is it time to process next external event
if (SimClock.getTime() >= this.nextExternalEventTime) { //若 外部事件 会在本次步进之前发生;
ExternalEvent ee = this.extEvents.nextEvent(); //获取外部事件并处理
ee.processEvent(this);
this.nextExternalEventTime = this.extEvents.nextEventsTime(); //更新下次外部事件发生的时间
}
else { // no external events left for this time step //若 外部事件 不发生
moveHosts(timeIncrement); //Host移动
if (simulateConnections) { //是否 simulateConnections, 若是 则尝试 connect
connectHosts(); // make connections
}
// update rest of the stuff //此处是排除 更新顺序导致的 干扰
if (this.updateOrder == null) { // randomizing is off
for (int i=0, n = hosts.size();i < n; i++) {
hosts.get(i).update(); //更新Host
}
}
else { // update order randomizing is on
assert this.updateOrder.size() == this.hosts.size() :
"Nrof hosts has changed unexpectedly";
Random rng = new Random(SimClock.getIntTime());
Collections.shuffle(this.updateOrder, rng);
for (int i=0, n = hosts.size();i < n; i++) {
this.updateOrder.get(i).update();
}
}
simClock.advance(timeIncrement); // advance the clock //SimClock前进
}
// inform all update listeners
for (UpdateListener ul : this.updateListeners) { //更新World上的Listeners
ul.updated(this.hosts);
}
}
2.2 关于外部事件: 包括 消息生成
外部事件 补充说明****
2.3 World.moveHosts(double timeIncrement)
//World.moveHosts(double timeIncrement)
private void moveHosts(double timeIncrement) {
for (int i=0,n = hosts.size(); i<n; i++) {
DTNHost host = hosts.get(i);
host.move(timeIncrement); //主要操作: 时间间隔timeIncrement内的DTNHost的移动
if (conGrid != null ){ //另外网格机制:把DTNHost在Map里的的移动做成网格;通过网格是否相邻的判断 减少对 所有DTNHost相邻的判断;起到加速作用而已
conGrid.updateLocation(host);
}
}
}
World.moveHosts(double timeIncrement) 实际上是经过了时间间隔timeIncrement,
for each各个DTNHost的位置都发生移动;通过DTNHost.move()实现。
//DTNHost.move()
public void move(double timeIncrement) {
if (!isActive() || SimClock.getTime() < this.nextTimeToMove) {
return;
}
double possibleMovement = timeIncrement * speed;
double distance = this.location.distance(this.destination);
//如果经过本次时间间隔timeIncrement, DTNHost的新位置已经覆盖到了之前指定的目的地DTNHost.destination,则需要设置下一个DTNHost.destination /speed /nextTimeToMove
while (possibleMovement >= distance) {
// node can move past its next destination
this.location.setLocation(this.destination); // snap to destination
possibleMovement -= distance;
if (!setNextWaypoint()) { // get a new waypoint
return; // no more waypoints left
}
distance = this.location.distance(this.destination);
}
// move towards the point for possibleMovement amount //两个相邻点的方向, 前进x和y的距离
double dx, dy;
dx = (possibleMovement/distance) * (this.destination.getX() -
this.location.getX());
dy = (possibleMovement/distance) * (this.destination.getY() -
this.location.getY());
this.location.translate(dx, dy);
}
DTNHost.move() 采用规则:设置一个目的地,移动过去(随时间);如果到了当前目的地,再设置下一个目的地/速度/出发时间。
这里涉及的参数包括: DTNHost.destination //下一个目的地的 ; DTNHost.speed //speed 速度; DTNHost.nextTimeToMove //下次启动时间;
这些参数通过DTNHost.setNextWaypoint()进行更新;
//DTNHost.setNextWaypoint(); //DTNHost的成员 private Path path; 和 private MovementModel movement;
//Sets the next destination and speed to correspond the next waypoint on the path.
private boolean setNextWaypoint() {
if (path == null) {
path = movement.getPath(); //初始化Path path
}
if (path == null || !path.hasNext()) {
this.nextTimeToMove = movement.nextPathAvailable();
this.path = null;
return false;
}
this.destination = path.getNextWaypoint();
this.speed = path.getSpeed();
if (this.movListeners != null) {
for (MovementListener l : this.movListeners) {
l.newDestination(this, this.destination, this.speed);
}
}
return true;
}
实际上, 下一个Dest 由类Path = MovementModel.getpath(); 决定了
类MovementModel 的 各个子类: 都实现了getPath();函数;
2.4 若 simulateConnections==true, 则执行World.connectHosts()
connectHost流程补充说明****
2.5 DTNHost.update() 流程补充说明 包括: NetworkLayer.update() 和 MessageRouter.update
//DTNHost.update()
public void update() {
if (!isActive()) {
return;
}
this.net.update();
this.router.update();
}
2.5.1 NetworkLayer.update()
/**
* Updates the state of current connections (ie tears down connections
* that are out of range).
*/
public void update() {
for (int i=0; i<this.connections.size(); ) {
Connection con = this.connections.get(i);
DTNHost anotherNode = con.getOtherNode(this.host);
// all connections should be up at this stage
assert con.isUp() : "Connection " + con + " was down!";
if (!isWithinRange(anotherNode)) {
con.setUpState(false);
notifyConnectionListeners(CON_DOWN, anotherNode);
// tear down bidirectional connection
if (!anotherNode.getConnections().remove(con)) {
throw new SimError("No connection " + con + " found in " +
anotherNode);
}
this.host.changedConnection(con);
anotherNode.changedConnection(con);
connections.remove(i);
}
else {
i++;
}
}
}
2.5.2 MessageRouter.update()
详见 另文档