This commit is contained in:
parent
8e3d4490bd
commit
e4bf065222
|
@ -2,6 +2,7 @@ package com.rusefi;
|
||||||
|
|
||||||
import com.rusefi.ui.MessagesView;
|
import com.rusefi.ui.MessagesView;
|
||||||
import com.rusefi.ui.util.UiUtils;
|
import com.rusefi.ui.util.UiUtils;
|
||||||
|
import com.rusefi.ui.widgets.EtbMonteCarloSequence;
|
||||||
import com.rusefi.ui.widgets.EtbResearch;
|
import com.rusefi.ui.widgets.EtbResearch;
|
||||||
import com.rusefi.ui.widgets.EtbTestSequence;
|
import com.rusefi.ui.widgets.EtbTestSequence;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
@ -25,6 +26,7 @@ public class BenchTestPane {
|
||||||
content.add(createIdleTest());
|
content.add(createIdleTest());
|
||||||
content.add(createDizzyTest());
|
content.add(createDizzyTest());
|
||||||
content.add(UiUtils.wrap(new EtbTestSequence().getButton()));
|
content.add(UiUtils.wrap(new EtbTestSequence().getButton()));
|
||||||
|
content.add(UiUtils.wrap(new EtbMonteCarloSequence().getButton()));
|
||||||
content.add(UiUtils.wrap(new EtbResearch().getButton()));
|
content.add(UiUtils.wrap(new EtbResearch().getButton()));
|
||||||
content.add(new MessagesView().messagesScroll);
|
content.add(new MessagesView().messagesScroll);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@ import java.util.concurrent.TimeUnit;
|
||||||
/**
|
/**
|
||||||
* https://github.com/rusefi/rusefi/issues/494
|
* https://github.com/rusefi/rusefi/issues/494
|
||||||
* <p>
|
* <p>
|
||||||
|
* https://en.wikipedia.org/wiki/Standard_deviation of error posted to specified sensor
|
||||||
|
* <p>
|
||||||
* 11/16/2017
|
* 11/16/2017
|
||||||
* (c) Andrey Belomutskiy
|
* (c) Andrey Belomutskiy
|
||||||
*
|
*
|
||||||
|
@ -25,6 +27,7 @@ public class ClosedLoopControlQualityMetric {
|
||||||
private final ValueSource target;
|
private final ValueSource target;
|
||||||
private final ValueSource result;
|
private final ValueSource result;
|
||||||
private final Sensor destination;
|
private final Sensor destination;
|
||||||
|
private boolean isStarted;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buffer of recent error measurements
|
* Buffer of recent error measurements
|
||||||
|
@ -43,6 +46,10 @@ public class ClosedLoopControlQualityMetric {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start(int bufferSize, int periodMs) {
|
public void start(int bufferSize, int periodMs) {
|
||||||
|
if (isStarted)
|
||||||
|
return;
|
||||||
|
isStarted = true;
|
||||||
|
|
||||||
errorsBuffer = new CyclicBuffer(bufferSize);
|
errorsBuffer = new CyclicBuffer(bufferSize);
|
||||||
executor.scheduleAtFixedRate(() -> {
|
executor.scheduleAtFixedRate(() -> {
|
||||||
rememberCurrentError(target.getValue() - result.getValue());
|
rememberCurrentError(target.getValue() - result.getValue());
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
package com.rusefi.ui.widgets;
|
||||||
|
|
||||||
|
import com.rusefi.core.MessagesCentral;
|
||||||
|
import com.rusefi.core.Sensor;
|
||||||
|
import com.rusefi.core.SensorCentral;
|
||||||
|
import com.rusefi.io.CommandQueue;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import static com.rusefi.Timeouts.SECOND;
|
||||||
|
import static com.rusefi.ui.widgets.EtbTestSequence.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 3/2/2019
|
||||||
|
* (c) Andrey Belomutskiy
|
||||||
|
*/
|
||||||
|
public class EtbMonteCarloSequence {
|
||||||
|
public static final int LIMIT = 100;
|
||||||
|
private final JButton button = new JButton("ETB I feel lucky!");
|
||||||
|
private final static Random r = new Random();
|
||||||
|
private int counter;
|
||||||
|
|
||||||
|
public EtbMonteCarloSequence() {
|
||||||
|
button.addActionListener(e -> {
|
||||||
|
counter = 0;
|
||||||
|
|
||||||
|
// 3000 data points at 10Hz should be 300 seconds worth of data
|
||||||
|
metric.start(/* buffer size: */3000, /*period, ms: */ 100);
|
||||||
|
|
||||||
|
executor.execute(this::runRandomCycle);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runRandomCycle() {
|
||||||
|
final int offset = r.nextInt(100);
|
||||||
|
final double pFactor = 1 + (r.nextInt(300) / 100.0);
|
||||||
|
final double iFactor = r.nextInt(30) / 100.0;
|
||||||
|
final double dFactor = r.nextInt(30) / 100.0;
|
||||||
|
String stats = "mcstats:offset:" + offset +
|
||||||
|
":pFactor:" + pFactor +
|
||||||
|
":iFactor:" + iFactor +
|
||||||
|
":dFactor:" + dFactor;
|
||||||
|
MessagesCentral.getInstance().postMessage(EtbMonteCarloSequence.class, stats);
|
||||||
|
CommandQueue.getInstance().write("set etb_o " + offset);
|
||||||
|
CommandQueue.getInstance().write("set etb_p " + pFactor);
|
||||||
|
CommandQueue.getInstance().write("set etb_i " + iFactor);
|
||||||
|
CommandQueue.getInstance().write("set etb_d " + dFactor);
|
||||||
|
|
||||||
|
SequenceStep firstStep = new EtbTarget(10 * SECOND, 4 /*position*/);
|
||||||
|
SequenceStep last = addSequence(firstStep);
|
||||||
|
last.addNext(new SequenceStep(5 * SECOND) {
|
||||||
|
@Override
|
||||||
|
protected void doJob() {
|
||||||
|
double result = SensorCentral.getInstance().getValue(Sensor.ETB_CONTROL_QUALITY);
|
||||||
|
MessagesCentral.getInstance().postMessage(EtbMonteCarloSequence.class, stats + ":result:" + result);
|
||||||
|
if (counter == LIMIT) {
|
||||||
|
MessagesCentral.getInstance().postMessage(EtbTestSequence.class, "ETB MC sequence done!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
MessagesCentral.getInstance().postMessage(EtbTestSequence.class, "Starting " + counter + " of " + LIMIT);
|
||||||
|
runRandomCycle();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
firstStep.execute(executor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JButton getButton() {
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import com.rusefi.core.MessagesCentral;
|
||||||
import com.rusefi.core.Sensor;
|
import com.rusefi.core.Sensor;
|
||||||
import com.rusefi.core.SensorCentral;
|
import com.rusefi.core.SensorCentral;
|
||||||
import com.rusefi.io.CommandQueue;
|
import com.rusefi.io.CommandQueue;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
@ -26,14 +27,18 @@ import java.util.concurrent.TimeUnit;
|
||||||
* @see TimeBasedBuffer
|
* @see TimeBasedBuffer
|
||||||
*/
|
*/
|
||||||
public class EtbTestSequence {
|
public class EtbTestSequence {
|
||||||
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
protected static final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
||||||
private boolean isStarted;
|
|
||||||
|
|
||||||
protected final ClosedLoopControlQualityMetric metric = new ClosedLoopControlQualityMetric(
|
protected final static ClosedLoopControlQualityMetric metric = createMetric();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected static ClosedLoopControlQualityMetric createMetric() {
|
||||||
|
return new ClosedLoopControlQualityMetric(
|
||||||
SensorCentral.getInstance().getValueSource(Sensor.PPS),
|
SensorCentral.getInstance().getValueSource(Sensor.PPS),
|
||||||
SensorCentral.getInstance().getValueSource(Sensor.TPS),
|
SensorCentral.getInstance().getValueSource(Sensor.TPS),
|
||||||
Sensor.ETB_CONTROL_QUALITY
|
Sensor.ETB_CONTROL_QUALITY
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private final static long SECOND = 1000;
|
private final static long SECOND = 1000;
|
||||||
|
|
||||||
|
@ -42,7 +47,11 @@ public class EtbTestSequence {
|
||||||
private SequenceStep FIRST_STEP = new EtbTarget(10 * SECOND, 4 /*position*/);
|
private SequenceStep FIRST_STEP = new EtbTarget(10 * SECOND, 4 /*position*/);
|
||||||
|
|
||||||
{
|
{
|
||||||
FIRST_STEP.add(new SequenceStep(SECOND) {
|
addSequence(FIRST_STEP);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static SequenceStep addSequence(SequenceStep first_step) {
|
||||||
|
return first_step.addNext(new SequenceStep(SECOND) {
|
||||||
@Override
|
@Override
|
||||||
protected void doJob() {
|
protected void doJob() {
|
||||||
metric.reset();
|
metric.reset();
|
||||||
|
@ -56,24 +65,38 @@ public class EtbTestSequence {
|
||||||
.addNext(5 * SECOND, 2 /*position*/)
|
.addNext(5 * SECOND, 2 /*position*/)
|
||||||
.addNext(5 * SECOND, 0 /*position*/)
|
.addNext(5 * SECOND, 0 /*position*/)
|
||||||
.addNext(5 * SECOND, 10 /*position*/)
|
.addNext(5 * SECOND, 10 /*position*/)
|
||||||
.addNext(10 * SECOND, 6 /*position*/)
|
.addNext(3 * SECOND, 0 /*position*/)
|
||||||
.addNext(10 * SECOND, 30 /*position*/)
|
.addNext(1 * SECOND, 6 /*position*/)
|
||||||
.addNext(10 * SECOND, 50 /*position*/)
|
.addNext(1 * SECOND, 8 /*position*/)
|
||||||
.addNext(10 * SECOND, 70 /*position*/)
|
.addNext(1 * SECOND, 6 /*position*/)
|
||||||
.addNext(10 * SECOND, 100 /*position*/)
|
.addNext(1 * SECOND, 4 /*position*/)
|
||||||
.addNext(10 * SECOND, 50 /*position*/)
|
.addNext(1 * SECOND, 2 /*position*/)
|
||||||
.addNext(10 * SECOND, 70 /*position*/)
|
.addNext(1 * SECOND, 0 /*position*/)
|
||||||
.addNext(10 * SECOND, 4 /*position*/)
|
.addNext(1 * SECOND, 10 /*position*/)
|
||||||
.addNext(10 * SECOND, 0 /*position*/)
|
.addNext(3 * SECOND, 7 /*position*/)
|
||||||
|
.addNext(3 * SECOND, 6 /*position*/)
|
||||||
|
.addNext(3 * SECOND, 5 /*position*/)
|
||||||
|
.addNext(3 * SECOND, 4 /*position*/)
|
||||||
|
.addNext(3 * SECOND, 3 /*position*/)
|
||||||
|
.addNext(3 * SECOND, 2 /*position*/)
|
||||||
|
.addNext(3 * SECOND, 1 /*position*/)
|
||||||
|
.addNext(3 * SECOND, 0 /*position*/)
|
||||||
|
// .addNext(10 * SECOND, 6 /*position*/)
|
||||||
|
// .addNext(10 * SECOND, 30 /*position*/)
|
||||||
|
// .addNext(10 * SECOND, 50 /*position*/)
|
||||||
|
// .addNext(10 * SECOND, 70 /*position*/)
|
||||||
|
// .addNext(10 * SECOND, 100 /*position*/)
|
||||||
|
// .addNext(10 * SECOND, 50 /*position*/)
|
||||||
|
// .addNext(10 * SECOND, 70 /*position*/)
|
||||||
|
// .addNext(10 * SECOND, 4 /*position*/)
|
||||||
|
// .addNext(10 * SECOND, 0 /*position*/)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EtbTestSequence() {
|
public EtbTestSequence() {
|
||||||
button.addActionListener(e -> {
|
button.addActionListener(e -> {
|
||||||
if (!isStarted) {
|
// 3000 data points at 10Hz should be 300 seconds worth of data
|
||||||
metric.start(/* buffer size: */1000, /*period, ms: */ 100);
|
metric.start(/* buffer size: */3000, /*period, ms: */ 100);
|
||||||
isStarted = true;
|
|
||||||
}
|
|
||||||
FIRST_STEP.execute(executor);
|
FIRST_STEP.execute(executor);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -93,7 +116,7 @@ public class EtbTestSequence {
|
||||||
public void execute(ScheduledExecutorService executor) {
|
public void execute(ScheduledExecutorService executor) {
|
||||||
doJob();
|
doJob();
|
||||||
if (next != null) {
|
if (next != null) {
|
||||||
FileLog.MAIN.logLine("Scheduling " + next);
|
FileLog.MAIN.logLine("Scheduling " + next + " with " + duration + "ms delay");
|
||||||
executor.schedule(() -> next.execute(executor), duration, TimeUnit.MILLISECONDS);
|
executor.schedule(() -> next.execute(executor), duration, TimeUnit.MILLISECONDS);
|
||||||
} else {
|
} else {
|
||||||
MessagesCentral.getInstance().postMessage(EtbTestSequence.class, "ETB test sequence done!");
|
MessagesCentral.getInstance().postMessage(EtbTestSequence.class, "ETB test sequence done!");
|
||||||
|
@ -103,10 +126,10 @@ public class EtbTestSequence {
|
||||||
protected abstract void doJob();
|
protected abstract void doJob();
|
||||||
|
|
||||||
public SequenceStep addNext(long duration, double position) {
|
public SequenceStep addNext(long duration, double position) {
|
||||||
return add(new EtbTarget(duration, position));
|
return addNext(new EtbTarget(duration, position));
|
||||||
}
|
}
|
||||||
|
|
||||||
private SequenceStep add(SequenceStep step) {
|
public SequenceStep addNext(SequenceStep step) {
|
||||||
next = step;
|
next = step;
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue