dead ETB console stuff

This commit is contained in:
rusefillc 2023-06-11 11:40:43 -04:00
parent 36e2ec7822
commit 30ac6de87a
11 changed files with 0 additions and 980 deletions

View File

@ -102,8 +102,6 @@ public class ConsoleUI {
}
if (!linkManager.isLogViewer()) {
tabbedPane.addTab("Bench Test", new BenchTestPane(uiContext, getConfig()).getContent());
if (tabbedPane.paneSettings.showEtbPane)
tabbedPane.addTab("ETB", new ETBPane(uiContext).getContent());
tabbedPane.addTab("Presets", new PresetsPane(uiContext).getContent());
}

View File

@ -1,33 +0,0 @@
package com.rusefi;
import com.rusefi.core.Sensor;
import com.rusefi.ui.GaugesGridElement;
import com.rusefi.ui.UIContext;
import com.rusefi.ui.etb.EtbCommandsPanel;
import javax.swing.*;
import java.awt.*;
/**
* Controls related to Electronic Throttle Body
*
* Andrey Belomutskiy, (c) 2013-2020
*/
public class ETBPane {
private final JPanel content = new JPanel(new BorderLayout());
public ETBPane(UIContext uiContext) {
JPanel centerPanel = new JPanel(new GridLayout(3, 1));
centerPanel.add(GaugesGridElement.create(uiContext, Sensor.PPS));
centerPanel.add(GaugesGridElement.create(uiContext, Sensor.ETB_CONTROL_QUALITY));
centerPanel.add(GaugesGridElement.create(uiContext, Sensor.TPS));
content.add(new EtbCommandsPanel(uiContext).getContent(), BorderLayout.WEST);
content.add(centerPanel, BorderLayout.CENTER);
}
public JPanel getContent() {
return content;
}
}

View File

@ -1,35 +0,0 @@
package com.rusefi.etb;
import com.rusefi.config.generated.Fields;
import com.rusefi.io.CommandQueue;
import com.rusefi.ui.UIContext;
public class EtbTarget extends TestSequenceStep {
private final UIContext uiContext;
/**
* 0-100 percent open
*/
private final double position;
private final Runnable onEachStep;
public EtbTarget(UIContext uiContext, long duration, double position, Runnable onEachStep, Condition condition) {
super(duration, condition);
this.uiContext = uiContext;
this.position = position;
this.onEachStep = onEachStep;
}
protected void doJob() {
uiContext.getCommandQueue().write("set " + Fields.MOCK_PPS_POSITION_COMMAND + " " + position);
if (onEachStep != null)
onEachStep.run();
}
@Override
public String toString() {
return "EtbTarget{" +
"nextStepDelay=" + nextStepDelay +
", position=" + position +
'}';
}
}

View File

@ -1,67 +0,0 @@
package com.rusefi.etb;
import com.rusefi.core.Sensor;
import com.rusefi.core.SensorCentral;
import com.rusefi.ui.UIContext;
import org.jetbrains.annotations.NotNull;
import static com.rusefi.Timeouts.SECOND;
import static com.rusefi.ui.etb.EtbTestSequence.PAST_DEPTH;
public class StandardTestSequence {
public final static ClosedLoopControlQualityMetric metric = createMetric();
@NotNull
protected static ClosedLoopControlQualityMetric createMetric() {
return new ClosedLoopControlQualityMetric(
SensorCentral.getInstance().getValueSource(Sensor.PPS),
SensorCentral.getInstance().getValueSource(Sensor.TPS),
Sensor.ETB_CONTROL_QUALITY,
PAST_DEPTH
);
}
public static TestSequenceStep addSequence(UIContext uiContext, TestSequenceStep first_step, Runnable onEachStep, TestSequenceStep.Condition condition) {
TestSequenceStep secondStep = new TestSequenceStep(SECOND, EtbTarget.Condition.YES) {
@Override
protected void doJob() {
metric.reset();
}
};
return first_step.addNext(secondStep)
.addNext(uiContext, 10 * SECOND, 4 /*position*/, onEachStep, condition)
.addNext(uiContext, 5 * SECOND, 6, /*position*/onEachStep, condition)
.addNext(uiContext, 5 * SECOND, 8, /*position*/onEachStep, condition)
.addNext(uiContext, 5 * SECOND, 6, /*position*/onEachStep, condition)
.addNext(uiContext, 5 * SECOND, 4, /*position*/onEachStep, condition)
.addNext(uiContext, 5 * SECOND, 2, /*position*/onEachStep, condition)
.addNext(uiContext, 5 * SECOND, 0, /*position*/onEachStep, condition)
.addNext(uiContext, 5 * SECOND, 10, /*position*/onEachStep, condition)
.addNext(uiContext, 3 * SECOND, 0, /*position*/onEachStep, condition)
.addNext(uiContext, 1 * SECOND, 6, /*position*/onEachStep, condition)
.addNext(uiContext, 1 * SECOND, 8, /*position*/onEachStep, condition)
.addNext(uiContext, 1 * SECOND, 6, /*position*/onEachStep, condition)
.addNext(uiContext, 1 * SECOND, 4, /*position*/onEachStep, condition)
.addNext(uiContext, 1 * SECOND, 2, /*position*/onEachStep, condition)
.addNext(uiContext, 1 * SECOND, 0, /*position*/onEachStep, condition)
.addNext(uiContext, 1 * SECOND, 10, /*position*/onEachStep, condition)
.addNext(uiContext, 3 * SECOND, 7, /*position*/onEachStep, condition)
.addNext(uiContext, 3 * SECOND, 6, /*position*/onEachStep, condition)
.addNext(uiContext, 3 * SECOND, 5, /*position*/onEachStep, condition)
.addNext(uiContext, 3 * SECOND, 4, /*position*/onEachStep, condition)
.addNext(uiContext, 3 * SECOND, 3, /*position*/onEachStep, condition)
.addNext(uiContext, 3 * SECOND, 2, /*position*/onEachStep, condition)
.addNext(uiContext, 3 * SECOND, 1, /*position*/onEachStep, condition)
.addNext(uiContext, 3 * SECOND, 0, /*position*/onEachStep, condition)
.addNext(uiContext, 10 * SECOND, 6, /*position*/onEachStep, condition)
.addNext(uiContext, 10 * SECOND, 30, /*position*/onEachStep, condition)
.addNext(uiContext, 10 * SECOND, 50, /*position*/onEachStep, condition)
.addNext(uiContext, 10 * SECOND, 70, /*position*/onEachStep, condition)
.addNext(uiContext, 10 * SECOND, 95, /*position*/onEachStep, condition)
.addNext(uiContext, 10 * SECOND, 50, /*position*/onEachStep, condition)
.addNext(uiContext, 10 * SECOND, 70, /*position*/onEachStep, condition)
.addNext(uiContext, 10 * SECOND, 4, /*position*/onEachStep, condition)
.addNext(uiContext, 10 * SECOND, 0, /*position*/onEachStep, condition)
;
}
}

View File

@ -1,67 +0,0 @@
package com.rusefi.etb;
import com.rusefi.FileLog;
import com.rusefi.core.MessagesCentral;
import com.rusefi.ui.UIContext;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public abstract class TestSequenceStep {
/**
* First we execute {{@link #doJob()}} then we schedule next step for after 'nextStepDelay' time passes.
*/
protected final long nextStepDelay;
private final EtbTarget.Condition condition;
private TestSequenceStep next;
public TestSequenceStep(long nextStepDelay, EtbTarget.Condition condition) {
this.nextStepDelay = nextStepDelay;
this.condition = condition;
}
public static int count(TestSequenceStep step) {
int result = 0;
while ((step = step.getNext()) != null)
result++;
return result;
}
public void execute(ScheduledExecutorService executor) {
boolean shouldRun = condition.shouldRunTask();
if (shouldRun)
doJob();
if (next != null) {
if (shouldRun) {
FileLog.MAIN.logLine("Scheduling " + next + " with " + nextStepDelay + "ms delay");
executor.schedule(() -> next.execute(executor), nextStepDelay, TimeUnit.MILLISECONDS);
} else {
// we've skipped current job and we skip the delay as well
next.execute(executor);
}
} else {
MessagesCentral.getInstance().postMessage(TestSequenceStep.class, "ETB test sequence done!");
}
}
protected abstract void doJob();
public TestSequenceStep addNext(UIContext uiContext, long duration, double position, Runnable onEachStep, Condition condition) {
return addNext(new EtbTarget(uiContext, duration, position, onEachStep, condition));
}
public TestSequenceStep addNext(TestSequenceStep step) {
next = step;
return next;
}
public TestSequenceStep getNext() {
return next;
}
public interface Condition {
boolean shouldRunTask();
Condition YES = () -> true;
}
}

View File

@ -1,103 +0,0 @@
package com.rusefi.ui.etb;
import com.rusefi.config.generated.Fields;
import com.rusefi.io.CommandQueue;
import com.rusefi.ui.UIContext;
import org.putgemin.VerticalFlowLayout;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import static com.rusefi.config.generated.Fields.CMD_ETB_DUTY;
/**
* Little panel to drive ETB duty cycle directly
*
* Andrey Belomutskiy, (c) 2013-2020
* @see Fields#CMD_ETB_DUTY
*/
public class DirectDrivePanel {
public static final String CANCEL_DIRECT_DRIVE_COMMAND = CMD_ETB_DUTY + " NaN";
private final JPanel content = new JPanel(new BorderLayout());
private final JLabel currentOverride = new JLabel("NaN");
private final JTextArea increment = new JTextArea("0.5");
private final JButton reset = new JButton("Cancel Direct Drive");
private double directDriverValue;
public DirectDrivePanel(UIContext uiContext) {
content.setBorder(BorderFactory.createTitledBorder("Direct Drive"));
uiContext.getCommandQueue().addListener(command -> {
if (command.startsWith(CMD_ETB_DUTY + " ")) {
command = command.substring((CMD_ETB_DUTY + " ").length());
directDriverValue = parseDouble(command, Double.NaN);
SwingUtilities.invokeLater(() -> currentOverride.setText("PWM override " + directDriverValue));
reset.setEnabled(!Double.isNaN(directDriverValue));
}
});
JPanel upDownPanel = new JPanel(new GridLayout(2, 1));
JButton more = new JButton("More");
more.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
double newValue = getCurrent() + getIncrement();
uiContext.getCommandQueue().write(CMD_ETB_DUTY + " " + newValue);
}
});
upDownPanel.add(more);
JButton less = new JButton("Less");
upDownPanel.add(less);
less.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
double newValue = getCurrent() - getIncrement();
uiContext.getCommandQueue().write(CMD_ETB_DUTY + " " + newValue);
}
});
JPanel leftPanel = new JPanel(new VerticalFlowLayout());
reset.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
uiContext.getCommandQueue().write(CANCEL_DIRECT_DRIVE_COMMAND);
}
});
leftPanel.add(reset);
leftPanel.add(currentOverride);
leftPanel.add(new JLabel("Increment:"));
leftPanel.add(increment);
content.add(leftPanel, BorderLayout.CENTER);
content.add(upDownPanel, BorderLayout.EAST);
}
private double parseDouble(String text, double defaultValue) {
try {
return Double.parseDouble(text);
} catch (NumberFormatException e) {
return defaultValue;
}
}
private double getIncrement() {
try {
double value = Double.parseDouble(increment.getText());
return Double.isNaN(value) ? 0.5 : value;
} catch (NumberFormatException e) {
increment.setText("0.5");
return 0.5;
}
}
private double getCurrent() {
return Double.isNaN(directDriverValue) ? 0 : directDriverValue;
}
public JPanel getContent() {
return content;
}
}

View File

@ -1,86 +0,0 @@
package com.rusefi.ui.etb;
import com.rusefi.config.generated.Fields;
import com.rusefi.core.Sensor;
import com.rusefi.ui.UIContext;
import com.rusefi.ui.config.BitConfigField;
import com.rusefi.ui.config.ConfigUiField;
import com.rusefi.ui.config.EnumConfigField;
import com.rusefi.core.preferences.storage.Node;
import com.rusefi.ui.util.UiUtils;
import com.rusefi.ui.widgets.AnyCommand;
import com.rusefi.ui.widgets.DetachedSensor;
import org.jetbrains.annotations.NotNull;
import org.putgemin.VerticalFlowLayout;
import javax.swing.*;
import static com.rusefi.config.generated.Fields.CMD_ETB_DUTY;
/**
* Panel for ETB bench testing & research.
*/
public class EtbCommandsPanel {
private final JPanel content = new JPanel(new VerticalFlowLayout());
private final UIContext uiContext;
public EtbCommandsPanel(UIContext uiContext) {
this.uiContext = uiContext;
content.add(new DirectDrivePanel(uiContext).getContent());
JPanel testParameters = new JPanel(new VerticalFlowLayout());
testParameters.setBorder(BorderFactory.createTitledBorder("Try PID settings"));
EtbTestSequence etbTestSequence = new EtbTestSequence(uiContext);
testParameters.add(etbTestSequence.getButton());
testParameters.add(UiUtils.wrap(etbTestSequence.getCancelButton()));
testParameters.add(etbTestSequence.getResult());
testParameters.add(new JLabel("To change setting use following commands:"));
testParameters.add(new JLabel("set etb_p X"));
testParameters.add(new JLabel("set etb_i X"));
testParameters.add(new JLabel("set etb_d X"));
testParameters.add(new JLabel("set etb_o X"));
testParameters.add(new JLabel("For example:"));
testParameters.add(new JLabel("set etb_p 1.1"));
testParameters.add(new BitConfigField(uiContext, Fields.PAUSEETBCONTROL, "Pause").getContent());
testParameters.add(new ConfigUiField(uiContext, Fields.ETB_PFACTOR, "pFactor").getContent());
testParameters.add(new ConfigUiField(uiContext, Fields.ETB_IFACTOR, "iFactor").getContent());
testParameters.add(new ConfigUiField(uiContext, Fields.ETB_DFACTOR, "dFactor").getContent());
content.setBorder(BorderFactory.createTitledBorder("Commands"));
content.add(testParameters);
content.add(AnyCommand.createArea(uiContext, new Node(), CMD_ETB_DUTY + " " + "10", false, false).getContent());
JPanel mockPpsPanel = new JPanel(new VerticalFlowLayout());
mockPpsPanel.setBorder(BorderFactory.createTitledBorder("Mock PPS"));
mockPpsPanel.add(DetachedSensor.createMockVoltageSlider(uiContext.getCommandQueue(), Sensor.PPS));
content.add(mockPpsPanel);
// todo: restore this functionality
// content.add(LiveDocPanel.createPanel("ETB", ElectronicThrottleMeta.CONTENT));
content.add(new EnumConfigField(uiContext, Fields.DEBUGMODE, "Debug Mode").getContent());
content.add(createMagicSpotsPanel());
content.add(UiUtils.wrap(new EtbMonteCarloSequence(uiContext).getButton()));
content.add(UiUtils.wrap(new EtbReturnToNeutral(uiContext).getContent()));
}
@NotNull
private JPanel createMagicSpotsPanel() {
JPanel spotsPane = new JPanel(new VerticalFlowLayout());
spotsPane.setBorder(BorderFactory.createTitledBorder("Magic Spots"));
MagicSpotsFinder magicSpotsFinder = new MagicSpotsFinder(uiContext);
spotsPane.add(UiUtils.wrap(magicSpotsFinder.getButton()));
spotsPane.add(magicSpotsFinder.getPoints());
return spotsPane;
}
public JComponent getContent() {
return new JScrollPane(content, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
}
}

View File

@ -1,138 +0,0 @@
package com.rusefi.ui.etb;
import com.rusefi.core.MessagesCentral;
import com.rusefi.core.Sensor;
import com.rusefi.core.SensorCentral;
import com.rusefi.etb.EtbTarget;
import com.rusefi.etb.StandardTestSequence;
import com.rusefi.etb.TestSequenceStep;
import com.rusefi.ui.UIContext;
import javax.swing.*;
import java.util.concurrent.atomic.AtomicInteger;
import static com.rusefi.Timeouts.SECOND;
import static com.rusefi.binaryprotocol.BinaryProtocol.sleep;
import static com.rusefi.config.generated.Fields.CMD_ETB_DUTY;
import static com.rusefi.etb.TestSequenceStep.count;
import static com.rusefi.ui.etb.DirectDrivePanel.CANCEL_DIRECT_DRIVE_COMMAND;
import static com.rusefi.ui.etb.EtbTestSequence.*;
/**
* 3/2/2019
* Andrey Belomutskiy, (c) 2013-2020
*/
public class EtbMonteCarloSequence {
private static final int TOTAL_CYCLES_COUNT = 15;
private static final double DEFAULT_POSITION = 7;
private static final int CLT_THRESHOLD = 75;
private final JButton button = new JButton("ETB I feel lucky!");
private final UIContext uiContext;
private int counter;
private double bestResultSoFar = 750;
public EtbMonteCarloSequence(UIContext uiContext) {
this.uiContext = uiContext;
button.addActionListener(e -> {
counter = 0;
executor.execute(new Runnable() {
@Override
public void run() {
uiContext.getCommandQueue().write(CANCEL_DIRECT_DRIVE_COMMAND);
sleep(3 * SECOND);
// 30000 data points at 100Hz should be 300 seconds worth of data
StandardTestSequence.metric.start(/* buffer size: */durationSeconds * frequencyHz, /*period, ms: */ 1000 / frequencyHz);
// start first cycle. At the end of the run it would decide if it wants to start from beginning again
executor.execute(() -> runRandomCycle());
}
});
});
}
private void runRandomCycle() {
final int offset = 0;//r.nextInt(100);
final double pFactor = 6 + counter * 2;// + (r.nextInt(300) / 100.0);
final double iFactor = 0;//r.nextInt(30) / 100.0;
final double dFactor = 0;//r.nextInt(30) / 100.0;
String stats = "mcstats:offset:" + offset +
":pFactor:" + pFactor +
":iFactor:" + iFactor +
":dFactor:" + dFactor;
MessagesCentral.getInstance().postMessage(EtbMonteCarloSequence.class, stats);
uiContext.getCommandQueue().write("etbreset");
uiContext.getCommandQueue().write("set etb_o " + offset);
uiContext.getCommandQueue().write("set etb_p " + pFactor);
uiContext.getCommandQueue().write("set etb_i " + iFactor);
uiContext.getCommandQueue().write("set etb_d " + dFactor);
MessagesCentral.getInstance().postMessage(EtbMonteCarloSequence.class,
uiContext.sensorLogger.getSecondsSinceFileStart() + " running " + stats);
TestSequenceStep firstStep = new EtbTarget(uiContext, 10 * SECOND, DEFAULT_POSITION, null, TestSequenceStep.Condition.YES);
TestSequenceStep.Condition condition = new TestSequenceStep.Condition() {
@Override
public boolean shouldRunTask() {
double currentValue = StandardTestSequence.metric.getStandardDeviation();
boolean shouldRun = currentValue < bestResultSoFar;
if (!shouldRun) {
MessagesCentral.getInstance().postMessage(EtbMonteCarloSequence.class,
"Too much error accumulated, aborting! " + currentValue + " > " + bestResultSoFar);
}
return shouldRun;
}
};
AtomicInteger stepCounter = new AtomicInteger();
AtomicInteger totalSteps = new AtomicInteger();
Runnable onEachStep = () -> SwingUtilities.invokeLater(() -> {
String state = stepCounter.incrementAndGet() + "/" + totalSteps.get();
double value = StandardTestSequence.metric.getStandardDeviation();
MessagesCentral.getInstance().postMessage(EtbMonteCarloSequence.class,"Running " + state + ", current=" + value);
});
TestSequenceStep last = StandardTestSequence.addSequence(uiContext, firstStep, onEachStep, condition);
last.addNext(new TestSequenceStep(5 * SECOND, EtbTarget.Condition.YES) {
@Override
protected void doJob() {
double clt = SensorCentral.getInstance().getValue(Sensor.CLT);
if (clt > CLT_THRESHOLD) {
stopETB();
sleep(10 * SECOND);
System.exit(-1);
}
double cycleResult = SensorCentral.getInstance().getValue(Sensor.ETB_CONTROL_QUALITY);
if (cycleResult < bestResultSoFar) {
bestResultSoFar = cycleResult;
MessagesCentral.getInstance().postMessage(EtbMonteCarloSequence.class,
uiContext.sensorLogger.getSecondsSinceFileStart() + ":" + stats + ":new_record:" + bestResultSoFar);
}
MessagesCentral.getInstance().postMessage(EtbMonteCarloSequence.class,
uiContext.sensorLogger.getSecondsSinceFileStart() + ":" + stats + ":result:" + cycleResult);
if (counter == TOTAL_CYCLES_COUNT) {
stopETB();
MessagesCentral.getInstance().postMessage(EtbTestSequence.class, "ETB MC sequence done!");
return;
}
counter++;
MessagesCentral.getInstance().postMessage(EtbTestSequence.class, "Starting " + counter + " of " + TOTAL_CYCLES_COUNT);
runRandomCycle();
}
});
totalSteps.set(count(firstStep));
firstStep.execute(executor);
}
public JButton getButton() {
return button;
}
private void stopETB() {
uiContext.getCommandQueue().write(CMD_ETB_DUTY + " " + 0);
}
}

View File

@ -1,101 +0,0 @@
package com.rusefi.ui.etb;
import com.rusefi.core.MessagesCentral;
import com.rusefi.core.Sensor;
import com.rusefi.core.SensorCentral;
import com.rusefi.ui.UIContext;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import static com.rusefi.Timeouts.SECOND;
import static com.rusefi.config.generated.Fields.CMD_ETB_DUTY;
/**
* Andrey Belomutskiy, (c) 2013-2020
*/
public class EtbReturnToNeutral {
private static final int ZERO_POSITION = 0;
private static final int NEUTRAL_POSITION = 7;
private static final int ACCEPTABLE_ERROR = 1;
private static final int CYCLES_COUNT = 10;
private static final String ZERO_DUTY_CYCLE_COMMAND = CMD_ETB_DUTY + " " + 0;
private final UIContext uiContext;
private JButton button = new JButton("ETB Spring Test");
private final static float SHUT_OPEN = 70;
private final static float SHUT_CLOSED = -70;
public EtbReturnToNeutral(UIContext uiContext) {
this.uiContext = uiContext;
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
testSequence();
} catch (InterruptedException e1) {
throw new IllegalStateException(e1);
}
}
};
new Thread(runnable).start();
}
});
}
private void testSequence() throws InterruptedException {
uiContext.getCommandQueue().write(ZERO_DUTY_CYCLE_COMMAND);
// longer pause in the beginning just in case
Thread.sleep(2 * SECOND);
assertPosition("First neutral position expected.", NEUTRAL_POSITION);
int errorCount = 0;
for (int i = 1; i <= CYCLES_COUNT; i++) {
uiContext.getCommandQueue().write(ZERO_DUTY_CYCLE_COMMAND);
Thread.sleep(SECOND);
boolean isError = assertPosition(i + ": Neutral position expected.", NEUTRAL_POSITION);
if (isError)
errorCount++;
uiContext.getCommandQueue().write(CMD_ETB_DUTY + " " + SHUT_OPEN);
Thread.sleep((long) (0.5 * SECOND));
uiContext.getCommandQueue().write(CMD_ETB_DUTY + " " + SHUT_CLOSED);
Thread.sleep(SECOND);
isError = assertPosition(i + ": Should be shot closed", 0);
if (isError)
errorCount++;
}
uiContext.getCommandQueue().write(ZERO_DUTY_CYCLE_COMMAND);
// CommandQueue.getInstance().write(DirectDrivePanel.CANCEL_DIRECT_DRIVE_COMMAND);
MessagesCentral.getInstance().postMessage(getClass(), "Cycles = " + CYCLES_COUNT + ", errors = " + errorCount);
}
/**
* @return true in case of error: TPS is too far from expected position
*/
private boolean assertPosition(String msg, float expectedPosition) {
double tps = SensorCentral.getInstance().getValue(Sensor.TPS);
MessagesCentral.getInstance().postMessage(getClass(), msg + " TPS=" + tps);
boolean isError = Math.abs(tps - expectedPosition) > ACCEPTABLE_ERROR;
if (isError)
MessagesCentral.getInstance().postMessage(getClass(), msg + " NOT GREAT " + tps + " while expected " + expectedPosition);
return isError;
}
public JComponent getContent() {
return button;
}
}

View File

@ -1,117 +0,0 @@
package com.rusefi.ui.etb;
import com.rusefi.TimeBasedBuffer;
import com.rusefi.core.Sensor;
import com.rusefi.etb.EtbTarget;
import com.rusefi.etb.StandardTestSequence;
import com.rusefi.etb.TestSequenceStep;
import com.rusefi.ui.UIContext;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicInteger;
import static com.rusefi.Timeouts.SECOND;
/**
* Here we initiate a sequence of commands which would change target electronic throttle position so that we can
* see how far the result would be how soon.
* <p>
* Error standard deviation is posted to {@link Sensor#ETB_CONTROL_QUALITY}
* <p>
* https://github.com/rusefi/rusefi/issues/494
* <p>
* 11/16/2017
* Andrey Belomutskiy, (c) 2013-2020
*
* @see TimeBasedBuffer
*/
public class EtbTestSequence {
protected static final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
public static final int durationSeconds = 300;
public static final int frequencyHz = 100;
public static final int PAST_DEPTH = 200 / (1000 / frequencyHz);
private static final String BUTTON_TEXT = "Measure Control Quality";
private final JButton button = new JButton(BUTTON_TEXT);
private final JLabel result = new JLabel("Result: N/A");
private final JButton cancelButton = new JButton("Cancel");
private boolean isCancelled;
public EtbTestSequence(UIContext uiContext) {
cancelButton.setEnabled(false);
button.addActionListener(e -> {
isCancelled = false;
button.setEnabled(false);
cancelButton.setEnabled(true);
// 3000 data points at 10Hz should be 300 seconds worth of data
StandardTestSequence.metric.start(/* buffer size: */durationSeconds * frequencyHz,
/*period, ms: */ 1000 / frequencyHz);
AtomicInteger stepCounter = new AtomicInteger();
AtomicInteger totalSteps = new AtomicInteger();
TestSequenceStep lastStep = new TestSequenceStep(SECOND, EtbTarget.Condition.YES) {
@Override
protected void doJob() {
endTestSequence();
}
};
Runnable onEachStep = () -> SwingUtilities.invokeLater(() -> {
String state = stepCounter.incrementAndGet() + "/" + totalSteps.get();
button.setText("Running " + state);
double value = StandardTestSequence.metric.getStandardDeviation();
result.setText(String.format(state + " Result: %.3f", value));
});
TestSequenceStep firstStep = new EtbTarget(uiContext, 10 * SECOND, 4, /*position*/onEachStep, TestSequenceStep.Condition.YES);
TestSequenceStep result = StandardTestSequence.addSequence(uiContext, firstStep, onEachStep, new TestSequenceStep.Condition() {
@Override
public boolean shouldRunTask() {
if (isCancelled)
endTestSequence();
return !isCancelled;
}
});
result.addNext(lastStep);
totalSteps.set(TestSequenceStep.count(firstStep));
firstStep.execute(executor);
});
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
isCancelled = true;
cancelButton.setEnabled(false);
}
});
}
private void endTestSequence() {
button.setEnabled(true);
cancelButton.setEnabled(false);
button.setText(BUTTON_TEXT);
double finalValue = StandardTestSequence.metric.getStandardDeviation();
result.setText(String.format("Final Result: %.3f", finalValue));
}
public JButton getButton() {
return button;
}
public JLabel getResult() {
return result;
}
public JComponent getCancelButton() {
return cancelButton;
}
}

View File

@ -1,231 +0,0 @@
package com.rusefi.ui.etb;
import com.rusefi.core.MessagesCentral;
import com.rusefi.core.Sensor;
import com.rusefi.core.SensorCentral;
import com.rusefi.io.InvocationConfirmationListener;
import com.rusefi.ui.UIContext;
import org.putgemin.VerticalFlowLayout;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import static com.rusefi.Timeouts.SECOND;
import static com.rusefi.config.generated.Fields.CMD_ETB_DUTY;
/**
* This tool finds interesting ETB duty cycles like the value when in starts to open or the value
* when it's completely open
* <p>
* Andrey Belomutskiy, (c) 2013-2020
* 10/21/2018
*/
public class MagicSpotsFinder {
private static final long SLEEP = SECOND;
// how much do we want to change duty cycle on each iteration?
private static final double DUTY_CYCLE_STEP = 0.5;
private static final String MAGIC_SPOTS_FINDER = "Magic Spots Finder";
private static final int INITIAL_SLEEP = 10 * SECOND;
private final JButton button = new JButton(MAGIC_SPOTS_FINDER);
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
private final static double MEASURMENT_PRECISION = 0.5;
private final UIContext uiContext;
private double defaultTpsPosition;
// private boolean isStarted;
private State state;
private double currentDutyCycle;
/**
* here we record at which duty cycle ETB would start moving
*/
private double startedToOpenValue;
private double reached100Value;
private double startedToCloseValue;
private double backToZeroValue;
private final JPanel points = new JPanel(new VerticalFlowLayout());
private final JLabel startedToOpenValueLabel = new JLabel("n/a");
private final JLabel reached100ValueLabel = new JLabel("n/a");
private final JLabel startedToCloseValueLabel = new JLabel("n/a");
private final JLabel backToZeroValueLabel = new JLabel("n/a");
private final InvocationConfirmationListener goingDown = new InvocationConfirmationListener() {
@Override
public void onCommandConfirmation() {
state = State.GOING_DOWN;
executor.execute(new Runnable() {
@Override
public void run() {
sleep(SLEEP);
double tpsPosition = SensorCentral.getInstance().getValue(Sensor.TPS);
MessagesCentral.getInstance().postMessage(getClass(), "ETB duty " + currentDutyCycle + ": tps=" + tpsPosition);
if (tpsPosition >= 100 - MEASURMENT_PRECISION) {
currentDutyCycle -= DUTY_CYCLE_STEP;
uiContext.getCommandQueue().write(CMD_ETB_DUTY + " " + currentDutyCycle, goingDown);
} else if (tpsPosition > defaultTpsPosition + MEASURMENT_PRECISION) {
if (startedToCloseValue == 0) {
// if that's the first we've moved let's remember duty cycle value
startedToCloseValue = currentDutyCycle;
startedToCloseValueLabel.setText(String.format("Started Close %.1f", startedToCloseValue));
MessagesCentral.getInstance().postMessage(getClass(), "Started to close at " + startedToCloseValue);
}
currentDutyCycle -= DUTY_CYCLE_STEP;
uiContext.getCommandQueue().write(CMD_ETB_DUTY + " " + currentDutyCycle, goingDown);
} else {
backToZeroValue = currentDutyCycle;
backToZeroValueLabel.setText(String.format("Back Zero %.1f", backToZeroValue));
MessagesCentral.getInstance().postMessage(getClass(), "Back closed to close at " + backToZeroValue);
MessagesCentral.getInstance().postMessage(getClass(), "startedToOpenValue = " + startedToOpenValue + ", reached100Value = " + reached100Value);
MessagesCentral.getInstance().postMessage(getClass(), "startedToCloseValue = " + startedToCloseValue + ", backToZeroValue = " + backToZeroValue);
button.setEnabled(true);
button.setText(MAGIC_SPOTS_FINDER);
}
}
});
}
};
private final InvocationConfirmationListener goingUp = new InvocationConfirmationListener() {
@Override
public void onCommandConfirmation() {
state = State.GOING_UP;
executor.execute(new Runnable() {
@Override
public void run() {
sleep(SLEEP);
double tpsPosition = SensorCentral.getInstance().getValue(Sensor.TPS);
MessagesCentral.getInstance().postMessage(getClass(), "ETB duty " + currentDutyCycle + ": tps=" + tpsPosition);
if (tpsPosition < defaultTpsPosition + MEASURMENT_PRECISION) {
// ETB has not moved yet, keep going up
currentDutyCycle += DUTY_CYCLE_STEP;
uiContext.getCommandQueue().write(CMD_ETB_DUTY + " " + currentDutyCycle, goingUp);
} else if (tpsPosition < 100 - MEASURMENT_PRECISION) {
if (startedToOpenValue == 0) {
// if that's the first we've moved let's remember duty cycle value
startedToOpenValue = currentDutyCycle;
startedToOpenValueLabel.setText(String.format("Start to open: %.1f", startedToOpenValue));
MessagesCentral.getInstance().postMessage(getClass(), "Started to open at " + startedToOpenValue);
}
// ETB has not reached 100%, keep going up
currentDutyCycle += DUTY_CYCLE_STEP;
uiContext.getCommandQueue().write(CMD_ETB_DUTY + " " + currentDutyCycle, goingUp);
} else {
// looks like we have reached 100%, cool!
reached100Value = currentDutyCycle;
reached100ValueLabel.setText(String.format("Reached 100: %.1f", reached100Value));
MessagesCentral.getInstance().postMessage(getClass(), "startedToOpenValue = " + startedToOpenValue + ", reached100Value = " + reached100Value);
currentDutyCycle -= DUTY_CYCLE_STEP;
uiContext.getCommandQueue().write(CMD_ETB_DUTY + " " + currentDutyCycle, goingDown);
}
}
});
}
};
public JPanel getPoints() {
return points;
}
// settings are confirmed, let's start going up from zero
private InvocationConfirmationListener setDebugModeConfiguration = new InvocationConfirmationListener() {
@Override
public void onCommandConfirmation() {
executor.execute(new Runnable() {
@Override
public void run() {
state = State.START;
MessagesCentral.getInstance().postMessage(getClass(), "Start!");
resetValues();
uiContext.getCommandQueue().write(CMD_ETB_DUTY + " " + currentDutyCycle, goingUp);
sleep(INITIAL_SLEEP);
defaultTpsPosition = SensorCentral.getInstance().getValue(Sensor.TPS);
}
});
}
};
private void resetValues() {
currentDutyCycle = 0.5;
startedToOpenValue = 0;
reached100Value = 0;
startedToCloseValue = 0;
backToZeroValue = 0;
}
public MagicSpotsFinder(UIContext uiContext) {
this.uiContext = uiContext;
points.add(startedToOpenValueLabel);
points.add(reached100ValueLabel);
points.add(startedToCloseValueLabel);
points.add(backToZeroValueLabel);
button.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
button.setEnabled(false);
button.setText("Running...");
// if (!isStarted) {
//// metric.start();
// isStarted = true;
// }
executor.execute(new Runnable() {
@Override
public void run() {
// magic constant for DBG_ELECTRONIC_THROTTLE_EXTRA
state = State.DEBUG_MODE;
uiContext.getCommandQueue().write("set debug_mode " + 29, setDebugModeConfiguration);
}
});
}
});
}
public JComponent getButton() {
return button;
}
private void sleep(long millis) {
try {
MessagesCentral.getInstance().postMessage(getClass(), "Sleeping " + millis + "ms");
Thread.sleep(millis);
} catch (InterruptedException unexpected) {
unexpected.printStackTrace();
throw new IllegalStateException(unexpected);
}
}
private enum State {
/**
* To begin we need to adjust some settings
*/
DEBUG_MODE,
/**
* Once settings change is confirmed we are here
*/
START,
GOING_UP,
GOING_DOWN,
}
}