dead ETB console stuff
This commit is contained in:
parent
36e2ec7822
commit
30ac6de87a
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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 +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue