vroious improvements

This commit is contained in:
Stephan Richter
2021-02-12 18:04:28 +01:00
parent 2973bd1432
commit c3242cddcb
10 changed files with 88 additions and 47 deletions

View File

@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>de.srsoftware</groupId>
<artifactId>web4rail</artifactId>
<version>1.3.41</version>
<version>1.3.42</version>
<name>Web4Rail</name>
<packaging>jar</packaging>
<description>Java Model Railway Control</description>

View File

@@ -32,8 +32,10 @@
<logger name="de.srsoftware.web4rail" level="INFO" />
<logger name="de.srsoftware.web4rail.Application" level="DEBUG" />
<logger name="de.srsoftware.web4rail.Route" level="DEBUG" />
<logger name="de.srsoftware.web4rail.actions.Action" level="DEBUG" />
<logger name="de.srsoftware.web4rail.actions.ActionList" level="DEBUG" />
<logger name="de.srsoftware.web4rail.moving.Train" level="DEBUG" />
<logger name="de.srsoftware.web4rail.tiles.Contact" level="DEBUG" />
<logger name="de.srsoftware.web4rail.tiles.Block" level="DEBUG" />
</configuration>

View File

@@ -89,7 +89,7 @@ public class Route extends BaseClass {
private String brakeId;
private long estimatedDistance; // Unit: s*km/h "km/h-Sekunden"
private int startSpeed,endSpeed;
private boolean aborted,modified;
private boolean aborted,modified,finished;
public BrakeProcessor(Route route, Train train) {
this.train = train;
@@ -97,14 +97,14 @@ public class Route extends BaseClass {
aborted = false;
modified = false;
estimatedDistance = 0;
finished = false;
brakeId = train.brakeId();
startSpeed = train.speed;
endSpeed = defaultEndSpeed;
timeStep = brakeTimes.get(brakeId);
if (isNull(timeStep)) timeStep = 100; // if no brake time is available for this train
if (isNull(timeStep)) timeStep = 256; // if no brake time is available for this train
Application.threadPool.execute(this);
}
@@ -123,58 +123,84 @@ public class Route extends BaseClass {
return dist;
}
private void checkNextRoute() {
Route nextRoute = train.nextRoute();
if (isSet(nextRoute) && nextRoute.state == Route.State.PREPARED) { // auf Startgeschwindigkeit der Nachfolgeroute bremsen
Integer nextRouteStartSpeed = nextRoute.startSpeed();
if (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;
while (calcDistance(newTimeStep) < estimatedDistance) newTimeStep += (1+newTimeStep/8); // zu schnell gebremst: pasue verlängern
while (calcDistance(newTimeStep) > estimatedDistance) newTimeStep -= 1+(newTimeStep/16); // zu langsam gebremst: pasue verkürzen
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 != timeStep) {
if (!newTimeStep.equals(timeStep)) {
route.brakeTimes.put(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 = timestamp();
estimatedDistance += train.speed * (tick-latestTick);
estimatedDistance += train.speed * (5+tick-latestTick);
latestTick = tick;
}
@Override
public void run() {
LOG.debug("started BrakeProcessor ({} → {}) for {} with timestep = {} ms.",train.speed,endSpeed,train,timeStep);
estimatedDistance = 0;
latestTick = timestamp();
while (train.speed > endSpeed) {
LOG.debug("BrakeProcessor({}) setting Speed of {}.",route,train);
if (finished) 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);
}
Route nextRoute = train.nextRoute();
if (!modified && isSet(nextRoute) && nextRoute.state == Route.State.PREPARED) { // auf Startgeschwindigkeit der Nachfolgeroute bremsen
Integer nrsp = nextRoute.startSpeed();
if (isSet(nrsp)) {
LOG.debug("updating target velocity from {} to {}!",endSpeed,nrsp);
endSpeed = nrsp;
modified = true;
}
}
}
if (endSpeed > train.speed) train.setSpeed(endSpeed);
while (!finished && !aborted && !modified) {
try {
sleep(1000);
} catch (InterruptedException e) {
LOG.warn("BrakeProcessor interrupted!", e);
}
checkNextRoute();
}
}
public void setEndSpeed(Integer newEndSpeed) {
@@ -511,11 +537,11 @@ public class Route extends BaseClass {
tile.unset(this);
} catch (IllegalArgumentException e) {}
Tile lastTile = path.lastElement();
/* Tile lastTile = path.lastElement();
if (lastTile instanceof Contact) {
lastTile.setTrain(null);
if (isSet(train)) train.removeChild(lastTile);
}
}*/
}
private String generateName() {
@@ -780,6 +806,7 @@ public class Route extends BaseClass {
private void moveTrainToEndBlock() {
if (isNull(train)) return;
LOG.debug("{}.moveTrainToEndBlock()",this);
train.set(endBlock);
train.heading(endDirection);
@@ -788,7 +815,9 @@ public class Route extends BaseClass {
train.destination(null); // unset old destination
String destTag = train.destinationTag();
if (isSet(destTag)) {
LOG.debug("destination tag: {}",destTag);
String[] parts = destTag.split(Train.DESTINATION_PREFIX);
for (int i=0; i<parts.length;i++) LOG.debug(" part {}: {}",i+1,parts[i]);
String destId = parts[1];
boolean turn = false;
@@ -1014,6 +1043,7 @@ public class Route extends BaseClass {
}
public Integer startSpeed() {
LOG.debug("{}.startSpeed()",this);
ActionList startActions = triggeredActions.get(ROUTE_START);
Context context = new Context(this);
return isSet(startActions) ? startActions.getSpeed(context) : null;

View File

@@ -81,12 +81,12 @@ public class ActionList extends Action implements Iterable<Action>{
}
public boolean fire(Context context) {
LOG.debug("{}.fire({})",this,context);
if (context.invalidated()) {
LOG.debug("Context has been invalidated, aborting {}",this);
return false;
}
if (!isEmpty()) LOG.debug(t("Firing {}"),actions);
if (!isEmpty()) LOG.debug("{}.fire({})",this,context);
for (Action action : actions) {
if (!action.fire(context)) return false;
}
@@ -94,12 +94,11 @@ public class ActionList extends Action implements Iterable<Action>{
}
public Integer getSpeed(Context context) {
LOG.debug("{}.getSpeed({})",this,context);
Integer speed = null;
for (Action action : this) {
if (action instanceof SetSpeed) {
speed = ((SetSpeed)action).getSpeed();
}
if (action instanceof ActionList) {
if (action instanceof SetSpeed) speed = ((SetSpeed)action).getSpeed();
if (isNull(speed) && action instanceof ActionList) {
Integer listSpeed = ((ActionList)action).getSpeed(context);
if (isSet(listSpeed)) speed = listSpeed;
}

View File

@@ -34,8 +34,9 @@ public class DelayedAction extends ActionList {
Application.threadPool.execute(new Thread() {
public void run() {
try {
Thread.sleep(min_delay + (min_delay < max_delay ? random.nextInt(max_delay - min_delay) : 0));
LOG.debug("{} ms passed by, firing actions:",min_delay);
int delay = min_delay + (min_delay < max_delay ? random.nextInt(max_delay - min_delay) : 0);
Thread.sleep(delay);
LOG.debug("{} ms passed by, firing actions:",delay);
} catch (InterruptedException e) {
LOG.warn("Interrupted Exception thrown while waiting:",e);
}

View File

@@ -4,6 +4,7 @@ import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.Range;
import de.srsoftware.web4rail.Route;
import de.srsoftware.web4rail.moving.Train;
import de.srsoftware.web4rail.tiles.Block;
public class PreserveRoute extends Action {
@@ -21,11 +22,12 @@ public class PreserveRoute extends Action {
// These are NOT errors:
if (!train.usesAutopilot()) return true; // do not reserve routes, when not in auto-mode
if (train.destination() == route.endBlock()) return true; // do not reserve routes, when destination has been reached
Block endBlock = route.endBlock();
if (train.destination() == endBlock) return true; // do not reserve routes, when destination has been reached
Range waitTime = route.endBlock().getWaitTime(train,route.endDirection);
Range waitTime = endBlock.getWaitTime(train,route.endDirection);
if (waitTime.max > 0) {
LOG.debug("Not preserving route, as train needs to stop in following block!");
LOG.debug("Not preserving route, as train needs to stop for {} ms at {}!",waitTime,endBlock);
return true; // train is expected to wait in next block.
}

View File

@@ -2,6 +2,7 @@ package de.srsoftware.web4rail.actions;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONObject;
@@ -41,7 +42,7 @@ public class TriggerContact extends Action {
@Override
protected Window properties(List<Fieldset> preForm, FormInput formInputs, List<Fieldset> postForm) {
formInputs.add(t("Select contact"),Contact.selector(contact));
formInputs.add(t("Select contact")+": "+(isNull(contact) ? t("unset") : contact),button(t("Select from plan"),Map.of(ACTION,ACTION_UPDATE,ASSIGN,CONTACT)));
return super.properties(preForm, formInputs, postForm);
}

View File

@@ -93,6 +93,7 @@ public class Train extends BaseClass implements Comparable<Train> {
private static final String SHUNTING = "shunting";
private boolean shunting = false;
private boolean reserving; // used to prevent recursive calls of reserveNext
private class Autopilot extends Thread{
boolean stop = false;
@@ -109,8 +110,8 @@ public class Train extends BaseClass implements Comparable<Train> {
if (stop) return;
if (isNull(route)) { // may have been set by start action in between
Object o = Train.this.start();
LOG.debug("{}.start called, route now is {}",Train.this,route);
if (isSet(route)) {
LOG.debug("{}.start called, route now is {}",Train.this,route);
if (o instanceof String) plan.stream((String)o);
//if (isSet(destination)) Thread.sleep(1000); // limit load on PathFinder
} else waitTime = 1000; // limit load on PathFinder
@@ -383,6 +384,7 @@ public class Train extends BaseClass implements Comparable<Train> {
if (isNull(destination)) {
String destTag = destinationTag();
if (isSet(destTag)) {
destTag = destTag.split(DESTINATION_PREFIX)[1];
for (int i=destTag.length()-1; i>0; i--) {
switch (destTag.charAt(i)) {
case FLAG_SEPARATOR:
@@ -409,10 +411,7 @@ public class Train extends BaseClass implements Comparable<Train> {
public String destinationTag() {
for (String tag : tags()) { // check, if endBlock is in train's destinations
if (tag.startsWith(DESTINATION_PREFIX)) {
String[] parts = tag.split(DESTINATION_PREFIX);
return parts[1];
}
if (tag.startsWith(DESTINATION_PREFIX)) return tag;
}
return null;
}
@@ -751,8 +750,8 @@ public class Train extends BaseClass implements Comparable<Train> {
return tags().iterator();
}
public void reserveNext() {
if (reserving) return;
LOG.debug("{}.reserveNext()",this);
Context context = new Context(this).route(route).block(route.endBlock()).direction(route.endDirection);
Route newRoute = PathFinder.chooseRoute(context);
@@ -760,6 +759,8 @@ public class Train extends BaseClass implements Comparable<Train> {
LOG.debug("{}.reserveNext() found no available route!",this);
return;
}
reserving = true;
LOG.debug("next route: {}",newRoute);
newRoute.set(context);
boolean error = !newRoute.lockIgnoring(route);
error = error || !newRoute.prepare();
@@ -772,6 +773,7 @@ public class Train extends BaseClass implements Comparable<Train> {
nextRoute = newRoute;
LOG.debug("prepared next route: {}",nextRoute);
}
reserving = false;
}
/**
@@ -808,8 +810,6 @@ public class Train extends BaseClass implements Comparable<Train> {
return this;
}
public static void saveAll(String filename) throws IOException {
BufferedWriter file = new BufferedWriter(new FileWriter(filename));
for (Train train:BaseClass.listElements(Train.class)) file.write(train.json()+"\n");

View File

@@ -12,6 +12,8 @@ import java.util.Vector;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.BaseClass;
@@ -33,6 +35,7 @@ import de.srsoftware.web4rail.tags.Window;
*
*/
public abstract class Block extends StretchableTile{
protected static Logger LOG = LoggerFactory.getLogger(Block.class);
private static final String ALLOW_TURN = "allowTurn";
private static final String NAME = "name";
private static final String NO_TAG = "[default]";
@@ -211,12 +214,15 @@ public abstract class Block extends StretchableTile{
}
public Range getWaitTime(Train train,Direction dir) {
LOG.debug("{}.getWaitTime({},{})",this,train,dir);
for (WaitTime wt : waitTimes) {
LOG.debug("examinig {}",wt);
if (train.tags().contains(wt.tag)) {
LOG.info(t("{} @ {} using rule for \"{}\".",train,this,wt.tag));
return wt.get(train.direction());
return wt.get(dir);
}
}
LOG.info(t("{} @ {} using rule for \"[default]\".",train,this));
return getWaitTime(NO_TAG).get(dir);
}

View File

@@ -371,7 +371,7 @@ public abstract class Tile extends BaseClass implements Comparable<Tile>{
}
public Tile setTrain(Train newTrain) {
Route.LOG.debug("{}.setTrain({})",this,newTrain);
LOG.debug("{}.setTrain({})",this,newTrain);
if (newTrain == train) return this; // nothing to update
this.train = newTrain;
return plan.place(this);