Browse Source

implemented automatic brake time learning

lookup-tables
Stephan Richter 4 years ago
parent
commit
ba2be67f8f
  1. 2
      pom.xml
  2. 23
      resources/translations/Application.de.translation
  3. 91
      src/main/java/de/srsoftware/web4rail/Route.java
  4. 4
      src/main/java/de/srsoftware/web4rail/actions/Action.java
  5. 12
      src/main/java/de/srsoftware/web4rail/actions/BrakeCancel.java
  6. 13
      src/main/java/de/srsoftware/web4rail/actions/BrakeStart.java
  7. 12
      src/main/java/de/srsoftware/web4rail/actions/BrakeStop.java
  8. 77
      src/main/java/de/srsoftware/web4rail/actions/SetContextTrain.java
  9. 2
      src/main/java/de/srsoftware/web4rail/moving/Locomotive.java
  10. 5
      src/main/java/de/srsoftware/web4rail/moving/Train.java
  11. 2
      src/main/java/de/srsoftware/web4rail/tiles/Block.java

2
pom.xml

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

23
resources/translations/Application.de.translation

@ -26,23 +26,27 @@ Block {} is free : Block {} ist frei @@ -26,23 +26,27 @@ Block {} is free : Block {} ist frei
Block {} is occupied : Block {} ist belegt
Block properties : Block-Eigenschaften
{}bound : nach {}
BrakeCancel : Bremsvorgang abbrechen
BrakeStart : Bremsvorgang starten
BrakeStop : Zug anhalten
Car manager : Waggon-Verwaltung
Cars\: : Waggons:
Click on a name to edit the entry. : Klicke auf einen Namen, um einen Eintrag zu bearbeiten.
ConditionalAction : bedingte Aktion
Conditions : Bedingungen
Condition type\: : Bedingungs-Typ:
Control : Steuerung
Control unit : Zentrale
Current location\: : Aktueller Ort:
Click here to select train! : HIer klicken, um Zug auszuwählen!
[Click here to select block!] : [Hier klicken, um Block auszuwählen!]
[Click here to add condition] : [Hier klicken, um Bedingung hinzuzufügen]
[Click here to select display!] : [Hier klicken, um Anzeige auszuwählen!]
[Click here to select train!] : [Hier klicken, um Zug auszuwählen!]
click here to setup contact : Hier klicken, um Kontakt auszuwählen
click here to setup relay : Hier klicken, um Relais einzurichten
Click on a name to edit the entry. : Klicke auf einen Namen, um einen Eintrag zu bearbeiten.
Command to send to control unit\: : Kommando, welches zur Zentrale gesendet werden soll:
ConditionalAction : bedingte Aktion
Conditions : Bedingungen
Condition type\: : Bedingungs-Typ:
Control : Steuerung
Control unit : Zentrale
Create action : Aktion erzeugen
Current location\: : Aktueller Ort:
Current location : Aufenthaltsort
Current location\: {} : Aufenthaltsort: {}
Current velocity\: {} {} : Aktuelle Geschwindigkeit: {} {}
@ -64,6 +68,7 @@ Dropped destination of {}. : Ziel von {} verworfen. @@ -64,6 +68,7 @@ Dropped destination of {}. : Ziel von {} verworfen.
EAST : Osten
editable train properties : veränderliche Zug-Eigenschaften
Emergency : Notfall
Faster (10 {}) : 10 {} schneller
Firing {} : starte {}
FinishRoute : Route abschließen
Found {} routes. : {} Routen gefunden.
@ -101,6 +106,7 @@ No : keine @@ -101,6 +106,7 @@ No : keine
No free routes from {} : keine Route von {} frei
NORTH : Norden
{} now heading for {} : {} ist nun unterweg nach {}
{} now in auto-mode : {} ist nun im Automatikmodus
Occupied area\: : Belegte Abschnitte:
Off : Aus
On : An
@ -132,6 +138,8 @@ Select relay\: : Relais auswählen: @@ -132,6 +138,8 @@ Select relay\: : Relais auswählen:
Select train\: : Zug auswählen:
SendCommand : Kommando senden
Send command "{}" to control unit : Kommando „{}“ an Zentrale senden
Set {} as context : {} als Kontext setzen
SetContextTrain : Zug für Folgeaktionen festlegen
SetDisplayText : Anzeige-Text setzen
SetRelay : Relais schalten
SetSignal : Signal stellen
@ -146,6 +154,7 @@ Setup actions : Vorbereitung-Aktionen @@ -146,6 +154,7 @@ Setup actions : Vorbereitung-Aktionen
ShowText : Text anzeigen
Signals : Signale
Simulating movement of {}... : Simuliere Fahrt von {}...
Slower (10 {}) : 10 {} langsamer
SOUTH : Süden
Start actions : Start-Aktionen
Stock ID : Inventarnummer

91
src/main/java/de/srsoftware/web4rail/Route.java

@ -5,6 +5,7 @@ import java.io.FileInputStream; @@ -5,6 +5,7 @@ import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -24,6 +25,8 @@ import de.srsoftware.web4rail.Plan.Direction; @@ -24,6 +25,8 @@ import de.srsoftware.web4rail.Plan.Direction;
import de.srsoftware.web4rail.actions.Action;
import de.srsoftware.web4rail.actions.Action.Context;
import de.srsoftware.web4rail.actions.ActionList;
import de.srsoftware.web4rail.actions.BrakeStart;
import de.srsoftware.web4rail.actions.BrakeStop;
import de.srsoftware.web4rail.actions.FinishRoute;
import de.srsoftware.web4rail.actions.PreserveRoute;
import de.srsoftware.web4rail.actions.SetSignal;
@ -54,6 +57,7 @@ public class Route extends BaseClass implements Comparable<Route>{ @@ -54,6 +57,7 @@ public class Route extends BaseClass implements Comparable<Route>{
private static final String ACTIONS = "actions";
private static final String ACTION_LISTS = "action_lists";
private static final String BRAKE_TIMES = "brake_times";
private static final String CONDITIONS = "conditions";
private static final String DROP_CONDITION = "drop_condition";
private static final String END_DIRECTION = "direction_end";
@ -69,6 +73,65 @@ public class Route extends BaseClass implements Comparable<Route>{ @@ -69,6 +73,65 @@ public class Route extends BaseClass implements Comparable<Route>{
private static HashMap<Integer, String> names = new HashMap<Integer, String>(); // maps id to name. needed to keep names during plan.analyze()
private class BrakeProcessor extends Thread {
private int startSpeed;
private long timestamp;
private int timeStep;
private Route route;
private Train train;
private boolean aborted = false;
private static final int ENDSPEED = 5;
public BrakeProcessor(Route route, Train train, Integer timestep) {
startSpeed = train.speed;
this.timeStep = isNull(timestep) ? 100 : timestep;
this.route = route;
this.train = train;
start();
}
public void abort() {
aborted = true;
train.setSpeed(startSpeed);
}
public void finish() {
long timestamp2 = new Date().getTime();
//int remainingSpeed = train.speed;
train.setSpeed(0);
if (aborted) return;
long runtime = timestamp2 - timestamp;
int newTimeStep = 5*(int) runtime/(startSpeed - ENDSPEED);
int diff = newTimeStep - timeStep;
int absDiff = diff < 0 ? -diff : diff;
if (absDiff > timeStep/4) absDiff=timeStep/4;
newTimeStep = diff < 0 ? timeStep - absDiff : timeStep + absDiff;
if (newTimeStep != timeStep) {
route.brakeTimes.put(train.brakeId(),newTimeStep);
LOG.debug("Corrected brake timestep for {} @ {} from {} to {} ms.",train,route,timeStep,newTimeStep);
}
}
@Override
public void run() {
timestamp = new Date().getTime();
if (train.speed == 0) aborted = true;
while (train.speed > ENDSPEED) {
if (aborted) break;
train.setSpeed(train.speed - 5);
try {
sleep(timeStep);
} catch (InterruptedException e) {
LOG.warn("BrakeProcessor interrupted!", e);
}
}
}
}
private BrakeProcessor brakeProcessor = null;
private HashMap<String,Integer> brakeTimes = new HashMap<String, Integer>();
private Vector<Condition> conditions = new Vector<Condition>();
private Vector<Contact> contacts;
private boolean disabled = false;
@ -248,6 +311,7 @@ public class Route extends BaseClass implements Comparable<Route>{ @@ -248,6 +311,7 @@ public class Route extends BaseClass implements Comparable<Route>{
newActionList.addActionsFrom(existingActionList);
}
}
brakeTimes = new HashMap<String, Integer>(existingRoute.brakeTimes);
}
void addSignal(Signal signal) {
@ -295,6 +359,20 @@ public class Route extends BaseClass implements Comparable<Route>{ @@ -295,6 +359,20 @@ public class Route extends BaseClass implements Comparable<Route>{
return this;
}
public void brakeCancel() {
if (isSet(brakeProcessor)) brakeProcessor.abort();
}
public void brakeStart() {
if (isNull(train)) return;
Integer brakeTime = brakeTimes.get(train.brakeId());
brakeProcessor = new BrakeProcessor(this,train,brakeTime);
}
public void brakeStop() {
if (isSet(brakeProcessor)) brakeProcessor.finish();
}
protected Route clone() {
Route clone = new Route();
clone.startBlock = startBlock;
@ -305,6 +383,7 @@ public class Route extends BaseClass implements Comparable<Route>{ @@ -305,6 +383,7 @@ public class Route extends BaseClass implements Comparable<Route>{
clone.signals = new Vector<Signal>(signals);
clone.turnouts = new HashMap<>(turnouts);
clone.path = new Vector<>(path);
clone.brakeTimes = new HashMap<String, Integer>(brakeTimes);
return clone;
}
@ -317,17 +396,17 @@ public class Route extends BaseClass implements Comparable<Route>{ @@ -317,17 +396,17 @@ public class Route extends BaseClass implements Comparable<Route>{
if (contacts.size()>1) { // mindestens 2 Kontakte: erster Kontakt aktiviert Block, vorletzter Kontakt leitet Bremsung ein
Contact nextToLastContact = contacts.get(contacts.size()-2);
String trigger = nextToLastContact.trigger();
add(trigger,new SetSpeed().to(50));
add(trigger,new BrakeStart());
add(trigger,new PreserveRoute());
for (Signal signal : signals) add(trigger,new SetSignal().set(signal).to(Signal.STOP));
}
if (!contacts.isEmpty()) {
Contact lastContact = contacts.lastElement();
add(lastContact.trigger(), new SetSpeed());
add(lastContact.trigger(), new BrakeStop());
add(lastContact.trigger(), new FinishRoute());
}
for (Signal signal : signals) setupActions.add(new SetSignal().set(signal).to(Signal.GO));
startActions.add(new SetSpeed().to(100));
startActions.add(new SetSpeed().to(999));
return this;
}
@ -456,6 +535,8 @@ public class Route extends BaseClass implements Comparable<Route>{ @@ -456,6 +535,8 @@ public class Route extends BaseClass implements Comparable<Route>{
json.put(START_DIRECTION, startDirection);
json.put(END_DIRECTION, endDirection);
json.put(BRAKE_TIMES, brakeTimes);
JSONArray jConditions = new JSONArray();
for (Condition condition : conditions) jConditions.put(condition.json());
if (!jConditions.isEmpty()) json.put(CONDITIONS, jConditions);
@ -521,6 +602,10 @@ public class Route extends BaseClass implements Comparable<Route>{ @@ -521,6 +602,10 @@ public class Route extends BaseClass implements Comparable<Route>{
if (json.has(SETUP_ACTIONS)) setupActions = ActionList.load(json.getJSONArray(SETUP_ACTIONS));
if (json.has(START_ACTIONS)) startActions = ActionList.load(json.getJSONArray(START_ACTIONS));
if (json.has(DISABLED)) disabled = json.getBoolean(DISABLED);
if (json.has(BRAKE_TIMES)) {
JSONObject dummy = json.getJSONObject(BRAKE_TIMES);
dummy.keySet().forEach(key -> brakeTimes.put(key, dummy.getInt(key)));
}
return plan.registerRoute(this);
}

4
src/main/java/de/srsoftware/web4rail/actions/Action.java

@ -134,12 +134,16 @@ public abstract class Action extends BaseClass { @@ -134,12 +134,16 @@ public abstract class Action extends BaseClass {
public static List<Class<? extends Action>> list() {
return List.of(
BrakeStart.class,
BrakeStop.class,
BrakeCancel.class,
ConditionalAction.class,
DelayedAction.class,
DetermineTrainInBlock.class,
FinishRoute.class,
PreserveRoute.class,
SendCommand.class,
SetContextTrain.class,
SetDisplayText.class,
SetPower.class,
SetRelay.class,

12
src/main/java/de/srsoftware/web4rail/actions/BrakeCancel.java

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
package de.srsoftware.web4rail.actions;
public class BrakeCancel extends Action {
@Override
public boolean fire(Context context) {
if (isNull(context.route)) return false;
context.route.brakeCancel();
return true;
}
}

13
src/main/java/de/srsoftware/web4rail/actions/BrakeStart.java

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
package de.srsoftware.web4rail.actions;
public class BrakeStart extends Action {
@Override
public boolean fire(Context context) {
if (isNull(context.route)) return false;
context.route.brakeStart();
LOG.debug("Started brake process...");
return true;
}
}

12
src/main/java/de/srsoftware/web4rail/actions/BrakeStop.java

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
package de.srsoftware.web4rail.actions;
public class BrakeStop extends Action {
@Override
public boolean fire(Context context) {
if (isNull(context.route)) return false;
context.route.brakeStop();
return true;
}
}

77
src/main/java/de/srsoftware/web4rail/actions/SetContextTrain.java

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
package de.srsoftware.web4rail.actions;
import java.util.HashMap;
import org.json.JSONObject;
import de.srsoftware.web4rail.Window;
import de.srsoftware.web4rail.moving.Train;
import de.srsoftware.web4rail.tags.Button;
import de.srsoftware.web4rail.tags.Form;
import de.srsoftware.web4rail.tags.Input;
import de.srsoftware.web4rail.tags.Label;
import de.srsoftware.web4rail.tags.Select;
public class SetContextTrain extends Action {
private Train train = null;
@Override
public boolean fire(Context context) {
context.train = train;
return true;
}
@Override
public JSONObject json() {
JSONObject json = super.json();
if (isSet(train)) json.put(REALM_TRAIN, train.id);
return json;
}
@Override
public Action load(JSONObject json) {
super.load(json);
if (json.has(REALM_TRAIN)) {
new Thread() { // load asynchronously, as referred tile may not be available,yet
public void run() {
try {
sleep(1000);
int trainId = json.getInt(REALM_TRAIN);
if (isSet(trainId)) train = Train.get(trainId);
} catch (InterruptedException e) {}
};
}.start();
}
return this;
}
@Override
public Window properties(HashMap<String, String> params) {
Window win = super.properties(params);
Form form = new Form("action-prop-form-"+id);
new Input(REALM,REALM_ACTIONS).hideIn(form);
new Input(ID,params.get(ID)).hideIn(form);
new Input(ACTION,ACTION_UPDATE).hideIn(form);
new Input(CONTEXT,params.get(CONTEXT)).hideIn(form);
Select select = Train.selector(train, null);
select.addTo(new Label(t("Select train:")+NBSP)).addTo(form);
new Button(t("Apply"),form).addTo(form).addTo(win);
return win;
}
public String toString() {
return isSet(train) ? t("Set {} as context",train) : "["+t("Click here to select train!")+"]";
};
@Override
protected Object update(HashMap<String, String> params) {
LOG.debug("update: {}",params);
String trainId = params.get(Train.class.getSimpleName());
if (isSet(trainId)) train = Train.get(Integer.parseInt(trainId));
return properties(params);
}
}

2
src/main/java/de/srsoftware/web4rail/moving/Locomotive.java

@ -101,7 +101,7 @@ public class Locomotive extends Car implements Constants,Device{ @@ -101,7 +101,7 @@ public class Locomotive extends Car implements Constants,Device{
new Tag("span").content(t("Current velocity: {} {}",speed,speedUnit)).addTo(fieldset);
Tag par = new Tag("p");
Map.of("Slower (10 steps)",ACTION_SLOWER10,"Faster (10 steps)",ACTION_FASTER10).entrySet().forEach(e -> {
Map.of(t("Slower (10 {})",speedUnit),ACTION_SLOWER10,t("Faster (10 {})",speedUnit),ACTION_FASTER10).entrySet().forEach(e -> {
params.put(ACTION, e.getValue());
new Button(t(e.getKey()),params).addTo(par);
});

5
src/main/java/de/srsoftware/web4rail/moving/Train.java

@ -214,7 +214,7 @@ public class Train extends BaseClass implements Comparable<Train> { @@ -214,7 +214,7 @@ public class Train extends BaseClass implements Comparable<Train> {
TreeSet<Integer> carIds = new TreeSet<Integer>();
locos.stream().map(loco -> loco.id()).forEach(carIds::add);
cars.stream().map(car -> car.id()).forEach(carIds::add);
brakeId = md5sum(carIds);
brakeId = md5sum(carIds+":"+direction);
LOG.debug("generated new brake id for {}: {}",brakeId,this);
}
return brakeId;
@ -598,6 +598,7 @@ public class Train extends BaseClass implements Comparable<Train> { @@ -598,6 +598,7 @@ public class Train extends BaseClass implements Comparable<Train> {
public void reserveNext() {
Context context = new Context(null, route, this, route.endBlock(), route.endDirection);
Route nextRoute = PathFinder.chooseRoute(context);
if (isNull(nextRoute)) return;
boolean error = !nextRoute.lockIgnoring(route);
error = error || !nextRoute.setTurnouts();
@ -608,6 +609,7 @@ public class Train extends BaseClass implements Comparable<Train> { @@ -608,6 +609,7 @@ public class Train extends BaseClass implements Comparable<Train> {
route.lock(); // corrects unlocked tiles of nextRoute
} else {
this.nextRoute = nextRoute;
this.route.brakeCancel();
}
}
@ -775,6 +777,7 @@ public class Train extends BaseClass implements Comparable<Train> { @@ -775,6 +777,7 @@ public class Train extends BaseClass implements Comparable<Train> {
}
if (isSet(route)) {
route.reset();
route.brakeCancel();
route = null;
}

2
src/main/java/de/srsoftware/web4rail/tiles/Block.java

@ -122,7 +122,7 @@ public abstract class Block extends StretchableTile implements Comparable<Block> @@ -122,7 +122,7 @@ public abstract class Block extends StretchableTile implements Comparable<Block>
@Override
public Object click() throws IOException {
if (isSet(train)) return train.properties();
if (isSet(train) && train.currentBlock() == this) return train.properties();
return super.click();
}

Loading…
Cancel
Save