working on new autopilot code

This commit is contained in:
Stephan Richter
2021-03-11 11:20:48 +01:00
parent 830c1863ad
commit c6aa5e45da
8 changed files with 144 additions and 19 deletions

View File

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

View File

@@ -36,6 +36,7 @@ import de.srsoftware.web4rail.tags.Input;
import de.srsoftware.web4rail.tags.Label; import de.srsoftware.web4rail.tags.Label;
import de.srsoftware.web4rail.tags.Table; import de.srsoftware.web4rail.tags.Table;
import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.BrakeProcessor;
import de.srsoftware.web4rail.threads.ControlUnit; import de.srsoftware.web4rail.threads.ControlUnit;
import de.srsoftware.web4rail.tiles.Block; import de.srsoftware.web4rail.tiles.Block;
import de.srsoftware.web4rail.tiles.BlockContact; import de.srsoftware.web4rail.tiles.BlockContact;
@@ -152,7 +153,7 @@ public class Plan extends BaseClass{
private static final String SPEED_UNIT = "speed_unit"; private static final String SPEED_UNIT = "speed_unit";
private static final String LENGTH_UNIT = "length_unit"; private static final String LENGTH_UNIT = "length_unit";
private static final String CONFIRM = "confirm"; private static final String CONFIRM = "confirm";
// private static final String FINAL_SPEED = "final_speed"; // TODO private static final String FINAL_SPEED = "final_speed";
private static final String FREE_BEHIND_TRAIN = "free_behind_train"; private static final String FREE_BEHIND_TRAIN = "free_behind_train";
private static final String RENAME = "rename"; private static final String RENAME = "rename";
private String name = DEFAULT_NAME; private String name = DEFAULT_NAME;
@@ -356,7 +357,7 @@ public class Plan extends BaseClass{
new Input(ACTION,ACTION_UPDATE).hideIn(form); new Input(ACTION,ACTION_UPDATE).hideIn(form);
new Input(LENGTH_UNIT, lengthUnit).addTo(new Label(t("Length unit")+COL)).addTo(form); new Input(LENGTH_UNIT, lengthUnit).addTo(new Label(t("Length unit")+COL)).addTo(form);
new Input(SPEED_UNIT, speedUnit).addTo(new Label(t("Speed unit")+COL)).addTo(form); new Input(SPEED_UNIT, speedUnit).addTo(new Label(t("Speed unit")+COL)).addTo(form);
//new Input(FINAL_SPEED, BrakeProcessor.defaultEndSpeed).addTo(new Label(t("Lower speed limit")+COL)).attr("title", t("Final speed after breaking, before halting")).addTo(form); // TODO new Input(FINAL_SPEED, BrakeProcessor.defaultEndSpeed).addTo(new Label(t("Lower speed limit")+COL)).attr("title", t("Final speed after breaking, before halting")).addTo(form); // TODO
new Checkbox(FREE_BEHIND_TRAIN, t("Free tiles behind train"), Route.freeBehindTrain).attr("title", t("If checked, tiles behind the train are freed according to the length of the train and the tiles. If it is unchecked, tiles will not get free before route is finished.")).addTo(form); new Checkbox(FREE_BEHIND_TRAIN, t("Free tiles behind train"), Route.freeBehindTrain).attr("title", t("If checked, tiles behind the train are freed according to the length of the train and the tiles. If it is unchecked, tiles will not get free before route is finished.")).addTo(form);
new Button(t("Save"), form).addTo(form); new Button(t("Save"), form).addTo(form);
form.addTo(fieldset); form.addTo(fieldset);
@@ -490,7 +491,7 @@ public class Plan extends BaseClass{
.forEach(jTiles::put); .forEach(jTiles::put);
return new JSONObject() return new JSONObject()
// .put(FINAL_SPEED, BrakeProcessor.defaultEndSpeed) // TODO .put(FINAL_SPEED, BrakeProcessor.defaultEndSpeed)
.put(FREE_BEHIND_TRAIN, Route.freeBehindTrain) .put(FREE_BEHIND_TRAIN, Route.freeBehindTrain)
.put(LENGTH_UNIT, lengthUnit) .put(LENGTH_UNIT, lengthUnit)
.put(SPEED_UNIT, speedUnit) .put(SPEED_UNIT, speedUnit)
@@ -524,7 +525,7 @@ public class Plan extends BaseClass{
if (json.has(TILE)) json.getJSONArray(TILE).forEach(object -> Tile.load(object, plan)); if (json.has(TILE)) json.getJSONArray(TILE).forEach(object -> Tile.load(object, plan));
if (json.has(LENGTH_UNIT)) lengthUnit = json.getString(LENGTH_UNIT); if (json.has(LENGTH_UNIT)) lengthUnit = json.getString(LENGTH_UNIT);
if (json.has(SPEED_UNIT)) speedUnit = json.getString(SPEED_UNIT); if (json.has(SPEED_UNIT)) speedUnit = json.getString(SPEED_UNIT);
// if (json.has(FINAL_SPEED)) BrakeProcessor.defaultEndSpeed = json.getInt(FINAL_SPEED); // TODOO if (json.has(FINAL_SPEED)) BrakeProcessor.defaultEndSpeed = json.getInt(FINAL_SPEED);
if (json.has(FREE_BEHIND_TRAIN)) Route.freeBehindTrain = json.getBoolean(FREE_BEHIND_TRAIN); if (json.has(FREE_BEHIND_TRAIN)) Route.freeBehindTrain = json.getBoolean(FREE_BEHIND_TRAIN);
try { try {
@@ -983,7 +984,7 @@ public class Plan extends BaseClass{
if (params.containsKey(LENGTH_UNIT)) lengthUnit = params.get(LENGTH_UNIT); if (params.containsKey(LENGTH_UNIT)) lengthUnit = params.get(LENGTH_UNIT);
if (params.containsKey(SPEED_UNIT)) speedUnit = params.get(SPEED_UNIT); if (params.containsKey(SPEED_UNIT)) speedUnit = params.get(SPEED_UNIT);
// if (params.containsKey(FINAL_SPEED)) BrakeProcessor.defaultEndSpeed = Integer.parseInt(params.get(FINAL_SPEED)); // TODO if (params.containsKey(FINAL_SPEED)) BrakeProcessor.defaultEndSpeed = Integer.parseInt(params.get(FINAL_SPEED));
Route.freeBehindTrain = "on".equalsIgnoreCase(params.get(FREE_BEHIND_TRAIN)); Route.freeBehindTrain = "on".equalsIgnoreCase(params.get(FREE_BEHIND_TRAIN));
return t("Plan updated."); return t("Plan updated.");

View File

@@ -266,11 +266,6 @@ public class Route extends BaseClass {
return this; return this;
} }
public void brakeStart() {
if (isNull(train)) return;
// brakeProcessor = new BrakeProcessor(this,train);
}
protected Route clone() { protected Route clone() {
Route clone = new Route(); Route clone = new Route();
clone.startBlock = startBlock; clone.startBlock = startBlock;
@@ -331,7 +326,7 @@ public class Route extends BaseClass {
ActionList actions = triggeredActions.get(contact.trigger()); ActionList actions = triggeredActions.get(contact.trigger());
LOG.debug("Contact has id {} / trigger {} and is assigned with {}",contact.id(),contact.trigger(),isNull(actions)?t("nothing"):actions); LOG.debug("Contact has id {} / trigger {} and is assigned with {}",contact.id(),contact.trigger(),isNull(actions)?t("nothing"):actions);
if (isNull(actions)) return; if (isNull(actions)) return;
Context context = new Context(this).train(train); Context context = new Context(this).train(train).contact(contact);
actions.fire(context,"Route.Contact("+contact.addr()+")"); actions.fire(context,"Route.Contact("+contact.addr()+")");
} }
@@ -382,11 +377,19 @@ public class Route extends BaseClass {
public void finish() { public void finish() {
LOG.debug("{}.finish()",this); LOG.debug("{}.finish()",this);
train.endRoute();
// TODO: train = null;
free();
} }
private void free() {
for (Tile tile : path) {
if (train.onTrace(tile)) {
tile.setState(Status.OCCUPIED, train);
} else tile.free();
}
}
private String generateName() { private String generateName() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (int i=0; i<path.size();i++) { for (int i=0; i<path.size();i++) {

View File

@@ -10,8 +10,8 @@ public class BrakeStart extends Action {
@Override @Override
public boolean fire(Context context,Object cause) { public boolean fire(Context context,Object cause) {
if (isNull(context.route())) return false; if (isNull(context.train())) return false;
context.route().brakeStart(); context.train().startBrake();
LOG.debug("Started brake process..."); LOG.debug("Started brake process...");
return true; return true;
} }

View File

@@ -36,6 +36,7 @@ import de.srsoftware.web4rail.tags.Label;
import de.srsoftware.web4rail.tags.Select; import de.srsoftware.web4rail.tags.Select;
import de.srsoftware.web4rail.tags.Table; import de.srsoftware.web4rail.tags.Table;
import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.BrakeProcessor;
import de.srsoftware.web4rail.threads.PathFinder; import de.srsoftware.web4rail.threads.PathFinder;
import de.srsoftware.web4rail.tiles.Block; import de.srsoftware.web4rail.tiles.Block;
import de.srsoftware.web4rail.tiles.Contact; import de.srsoftware.web4rail.tiles.Contact;
@@ -101,6 +102,8 @@ public class Train extends BaseClass implements Comparable<Train> {
private HashSet<Listener> listeners = new HashSet<Train.Listener>(); private HashSet<Listener> listeners = new HashSet<Train.Listener>();
private BrakeProcessor brakeProcessor;
public static Object action(HashMap<String, String> params, Plan plan) throws IOException { public static Object action(HashMap<String, String> params, Plan plan) throws IOException {
String action = params.get(ACTION); String action = params.get(ACTION);
if (isNull(action)) return t("No action passed to Train.action!"); if (isNull(action)) return t("No action passed to Train.action!");
@@ -409,6 +412,14 @@ public class Train extends BaseClass implements Comparable<Train> {
while (!trace.isEmpty()) trace.removeFirst().free(); while (!trace.isEmpty()) trace.removeFirst().free();
} }
public void endRoute() {
setSpeed(0);
if (isSet(brakeProcessor)) brakeProcessor.end();
brakeProcessor = null;
route = null;
}
private Tag faster(int steps) { private Tag faster(int steps) {
setSpeed(speed+steps); setSpeed(speed+steps);
return properties(); return properties();
@@ -901,6 +912,18 @@ public class Train extends BaseClass implements Comparable<Train> {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return null; return null;
} }
public void startBrake() {
if (isNull(route)) {
LOG.warn("{}.startBrake() called, but train ist not on a route!",this);
return;
}
if (isSet(brakeProcessor)) {
LOG.debug("{} already is braking.");
return;
}
brakeProcessor = new BrakeProcessor(this).start();
}
public Object stopNow() { public Object stopNow() {
setSpeed(0); setSpeed(0);

View File

@@ -0,0 +1,99 @@
package de.srsoftware.web4rail.threads;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.Route;
import de.srsoftware.web4rail.moving.Train;
/**
* @author Stephan Richter, SRSoftware
*
*/
public class BrakeProcessor extends BaseClass implements Runnable {
private enum State {
IDLE, BRAKING, ABORTED, ENDED;
}
private static final Logger LOG = LoggerFactory.getLogger(BrakeProcessor.class);
public static int defaultEndSpeed;
private Train train;
private State state = State.IDLE;
private long measuredDistance;
private long lastTime;
private Integer brakeTime;
private int startSpeed;
public BrakeProcessor(Train train) {
this.train = train;
}
public void end() {
state = State.ENDED;
measuredDistance += train.speed * (BaseClass.timestamp() - lastTime);
LOG.debug("old brake time: {}, measured distance: {}",brakeTime,measuredDistance);
int step = brakeTime;
for (int i=0; i<10; i++) {
long calculatedDistance = calculate(brakeTime,startSpeed);
step/=2;
if (step<1) step = 1;
LOG.debug("new brake time: {}, calculated distance: {}",brakeTime,calculatedDistance);
if (measuredDistance < calculatedDistance) {
brakeTime -= step;
}
if (measuredDistance > calculatedDistance) {
brakeTime += step;
}
}
LOG.debug("new brake time: {}, calculated distance: {}",brakeTime,"");
}
private static long calculate(int brakeTime, int speed) {
long dist = 0;
while (speed > defaultEndSpeed) {
dist += speed*brakeTime;
speed -= 10;
}
return dist;
}
@Override
public void run() {
LOG.debug("run()");
Route route = train.route();
if (isNull(route)) return;
brakeTime = route.brakeTime(train.brakeId());
if (isNull(brakeTime)) brakeTime = 250;
state = State.BRAKING;
measuredDistance = 0;
lastTime = BaseClass.timestamp();
startSpeed = train.speed;
int targetSpeed = defaultEndSpeed;
while (state == State.BRAKING) {
sleep(brakeTime);
long newTime = BaseClass.timestamp();
if (isNull(train.route())) state = State.ABORTED;
if (state != State.BRAKING) break;
measuredDistance += train.speed * (newTime - lastTime);
int newSpeed = train.speed - 10;
if (newSpeed < targetSpeed) {
train.setSpeed(targetSpeed);
break;
}
train.setSpeed(newSpeed);
lastTime = newTime;
}
LOG.debug("{} reached final speed.", train);
}
public BrakeProcessor start() {
Thread thread = new Thread(this);
thread.setName(getClass().getSimpleName());
thread.start();
return this;
}
}

View File

@@ -321,9 +321,7 @@ public class ControlUnit extends Thread implements Constants{
Thread thread = new Thread() { Thread thread = new Thread() {
@Override @Override
public void run() { public void run() {
set(false);
plan.sensor(addr,active); plan.sensor(addr,active);
set(true);
} }
}; };
thread.setName(Application.threadName("CU.FeedBack("+addr+")")); thread.setName(Application.threadName("CU.FeedBack("+addr+")"));

View File

@@ -139,6 +139,7 @@ public abstract class Tile extends BaseClass implements Comparable<Tile>{
public void free() { public void free() {
train = null; train = null;
status = Status.FREE; status = Status.FREE;
plan.place(this);
} }
public int height() { public int height() {