26 changed files with 260 additions and 229 deletions
@ -0,0 +1,68 @@
@@ -0,0 +1,68 @@
|
||||
package de.srsoftware.web4rail.threads; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
import de.srsoftware.web4rail.Application; |
||||
import de.srsoftware.web4rail.BaseClass; |
||||
import de.srsoftware.web4rail.Range; |
||||
import de.srsoftware.web4rail.moving.Train; |
||||
|
||||
public class Autopilot extends Thread{ |
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Autopilot.class); |
||||
|
||||
boolean stop = false; |
||||
private Train train; |
||||
int waitTime = 100; |
||||
|
||||
public Autopilot(Train train) { |
||||
this.train = train; |
||||
setName(Application.threadName("Autopilot("+train+")")); |
||||
start(); |
||||
} |
||||
|
||||
public void doStop() { |
||||
stop = true; |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
try { |
||||
stop = false; |
||||
while (true) { |
||||
if (BaseClass.isNull(train.route())) { |
||||
Thread.sleep(waitTime); |
||||
if (waitTime > 100) waitTime /=2; |
||||
if (stop) break; |
||||
if (BaseClass.isNull(train.route())) { // may have been set by start action in between
|
||||
String message = train.start(); |
||||
if (BaseClass.isSet(train.route())) { |
||||
LOG.debug("{}.start called, route now is {}",train,train.route()); |
||||
BaseClass.plan.stream(message); |
||||
//if (isSet(destination)) Thread.sleep(1000); // limit load on PathFinder
|
||||
} else { |
||||
LOG.debug(message); |
||||
waitTime = 1000; // limit load on PathFinder
|
||||
} |
||||
} |
||||
} else { |
||||
if (stop) break; |
||||
Thread.sleep(250); |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
train.autopilot = null; |
||||
if (BaseClass.isSet(train.currentBlock())) BaseClass.plan.place(train.currentBlock()); |
||||
} |
||||
|
||||
public void waitTime(Range wt) { |
||||
this.waitTime = wt.random(); |
||||
String msg = BaseClass.t("{} waiting {} secs...",this,waitTime/1000d); |
||||
LOG.debug(msg); |
||||
BaseClass.plan.stream(msg); |
||||
|
||||
} |
||||
} |
@ -0,0 +1,145 @@
@@ -0,0 +1,145 @@
|
||||
package de.srsoftware.web4rail.threads; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
import de.srsoftware.web4rail.Application; |
||||
import de.srsoftware.web4rail.BaseClass; |
||||
import de.srsoftware.web4rail.Route; |
||||
import de.srsoftware.web4rail.moving.Train; |
||||
|
||||
public class BrakeProcessor extends Thread { |
||||
public static final Logger LOG = LoggerFactory.getLogger(BrakeProcessor.class); |
||||
|
||||
|
||||
private long latestTick; |
||||
private static final int SPEED_STEP = 5; |
||||
private Integer timeStep; |
||||
private Route route; |
||||
private Train train; |
||||
private String brakeId; |
||||
private long estimatedDistance; // Unit: s*km/h "km/h-Sekunden"
|
||||
private int startSpeed,endSpeed; |
||||
private boolean aborted,modified,finished; |
||||
public static int defaultEndSpeed = 10; |
||||
|
||||
public BrakeProcessor(Route route, Train train) { |
||||
this.train = train; |
||||
this.route = route; |
||||
|
||||
aborted = false; |
||||
modified = false; |
||||
finished = false; |
||||
brakeId = train.brakeId(); |
||||
startSpeed = train.speed; |
||||
endSpeed = defaultEndSpeed; |
||||
|
||||
timeStep = route.brakeTime(brakeId); |
||||
|
||||
if (BaseClass.isNull(timeStep) || timeStep>1000000) timeStep = 256; // if no brake time is available for this train
|
||||
setName(Application.threadName("BrakeProcessor("+train+")")); |
||||
start(); |
||||
} |
||||
|
||||
public void abort() { |
||||
aborted = true; |
||||
} |
||||
|
||||
private long calcDistance(Integer ts) { |
||||
long dist = 0; |
||||
int s = startSpeed; |
||||
while (s > defaultEndSpeed) { |
||||
s -= SPEED_STEP; |
||||
dist += s*ts; |
||||
} |
||||
LOG.debug("Estimated distamce with {} ms timestep: {}",ts,dist); |
||||
return dist; |
||||
} |
||||
|
||||
private void checkNextRoute() { |
||||
Route nextRoute = train.nextRoute(); |
||||
if (BaseClass.isSet(nextRoute) && nextRoute.state() == Route.State.PREPARED) { // auf Startgeschwindigkeit der Nachfolgeroute bremsen
|
||||
Integer nextRouteStartSpeed = nextRoute.startSpeed(); |
||||
if (BaseClass.isSet(nextRouteStartSpeed)) { |
||||
LOG.debug("updating target velocity from {} to {}!",endSpeed,nextRouteStartSpeed); |
||||
endSpeed = nextRouteStartSpeed; |
||||
modified = true; |
||||
if (endSpeed > train.speed) train.setSpeed(endSpeed); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* This is called from route.finish when train came to stop |
||||
*/ |
||||
public void finish() { |
||||
LOG.debug("BrakeProcessor.finish()"); |
||||
finished = true; |
||||
if (aborted || modified) return; |
||||
increaseDistance(); |
||||
train.setSpeed(0); |
||||
LOG.debug("Estimated distance: {}",estimatedDistance); |
||||
|
||||
if (startSpeed <= endSpeed) return; |
||||
if (timeStep<0) timeStep = 100; |
||||
Integer newTimeStep = timeStep; |
||||
long calculated; |
||||
int step = 32*newTimeStep; |
||||
for (int i=0; i<20; i++) { |
||||
step = step/2; |
||||
if (step<1) step = 1; |
||||
calculated = calcDistance(newTimeStep); |
||||
LOG.debug("Calculated distance for step = {} ms: {}",newTimeStep,calculated); |
||||
LOG.debug("Update step: {}",step); |
||||
newTimeStep = newTimeStep + (calculated > estimatedDistance ? -step : step); |
||||
} |
||||
|
||||
if (!newTimeStep.equals(timeStep)) { |
||||
route.brakeTime(brakeId,newTimeStep); |
||||
calculated = calcDistance(newTimeStep); |
||||
LOG.debug("Corrected brake timestep for {} @ {} from {} to {} ms.",train,route,timeStep,newTimeStep); |
||||
LOG.debug("Differemce from estimated distance: {} ({}%)",estimatedDistance-calculated,100*(estimatedDistance-calculated)/(float)estimatedDistance); |
||||
} |
||||
} |
||||
|
||||
private void increaseDistance(){ |
||||
long tick = BaseClass.timestamp(); |
||||
estimatedDistance += train.speed * (3+tick-latestTick); |
||||
latestTick = tick; |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
setName(Application.threadName("BreakeProcessor("+train+")")); |
||||
LOG.debug("started BrakeProcessor ({} → {}) for {} with timestep = {} ms.",train.speed,endSpeed,train,timeStep); |
||||
estimatedDistance = 0; |
||||
latestTick = BaseClass.timestamp(); |
||||
while (train.speed > endSpeed) { |
||||
if (finished || aborted) return; |
||||
increaseDistance(); |
||||
LOG.debug("BrakeProcessor({}) setting Speed of {}.",route,train); |
||||
train.setSpeed(Math.max(train.speed - SPEED_STEP,endSpeed)); |
||||
if (!modified) checkNextRoute(); |
||||
try { |
||||
sleep(timeStep); |
||||
} catch (InterruptedException e) { |
||||
LOG.warn("BrakeProcessor interrupted!", e); |
||||
} |
||||
} |
||||
|
||||
while (!finished && !aborted && !modified) { |
||||
try { |
||||
sleep(1000); |
||||
} catch (InterruptedException e) { |
||||
LOG.warn("BrakeProcessor interrupted!", e); |
||||
} |
||||
checkNextRoute(); |
||||
} |
||||
} |
||||
|
||||
public void setEndSpeed(Integer newEndSpeed) { |
||||
if (BaseClass.isNull(newEndSpeed)) return; |
||||
endSpeed = newEndSpeed; |
||||
modified = true; |
||||
} |
||||
} |
@ -1,4 +1,6 @@
@@ -1,4 +1,6 @@
|
||||
package de.srsoftware.web4rail; |
||||
package de.srsoftware.web4rail.threads; |
||||
|
||||
import de.srsoftware.web4rail.Application; |
||||
|
||||
public abstract class DelayedExecution extends Thread { |
||||
private int delay; |
Loading…
Reference in new issue