ETB quality instrumentation #494
This commit is contained in:
parent
7e7261d2cc
commit
d9c31bd6bd
|
@ -0,0 +1,34 @@
|
|||
package com.rusefi;
|
||||
|
||||
import com.rusefi.core.Sensor;
|
||||
import com.rusefi.ui.GaugesGridElement;
|
||||
import com.rusefi.ui.etb.CalibrationPanel;
|
||||
import com.rusefi.ui.etb.CommandsPanel;
|
||||
import com.rusefi.ui.util.UiUtils;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* Controls related to Electronic Throttle Body
|
||||
*
|
||||
* (c) Andrey Belomutskiy 2013-2019
|
||||
*/
|
||||
public class ETBPane {
|
||||
private final JPanel content = new JPanel(new BorderLayout());
|
||||
|
||||
public ETBPane() {
|
||||
JPanel centerPanel = new JPanel(new GridLayout(2, 1));
|
||||
centerPanel.add(GaugesGridElement.create(Sensor.PPS));
|
||||
centerPanel.add(GaugesGridElement.create(Sensor.TPS));
|
||||
|
||||
content.add(new CommandsPanel().getContent(), BorderLayout.WEST);
|
||||
content.add(centerPanel, BorderLayout.CENTER);
|
||||
content.add(new CalibrationPanel().getContent(), BorderLayout.EAST);
|
||||
}
|
||||
|
||||
public JPanel getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.rusefi.ui.widgets;
|
||||
package com.rusefi.etb;
|
||||
|
||||
import com.rusefi.CyclicBuffer;
|
||||
import com.rusefi.DataBuffer;
|
||||
|
@ -63,7 +63,7 @@ public class ClosedLoopControlQualityMetric {
|
|||
errorsBuffer.clear();
|
||||
}
|
||||
|
||||
private synchronized double getStandardDeviation() {
|
||||
public synchronized double getStandardDeviation() {
|
||||
return DataBuffer.getStandardDeviation(errorsBuffer.getValues());
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package com.rusefi.etb;
|
||||
|
||||
import com.rusefi.io.CommandQueue;
|
||||
|
||||
public class EtbTarget extends TestSequenceStep {
|
||||
/**
|
||||
* 0-100 percent open
|
||||
*/
|
||||
private final double position;
|
||||
private final Runnable onEachStep;
|
||||
|
||||
public EtbTarget(long duration, double position, Runnable onEachStep) {
|
||||
super(duration);
|
||||
this.position = position;
|
||||
this.onEachStep = onEachStep;
|
||||
}
|
||||
|
||||
protected void doJob() {
|
||||
CommandQueue.getInstance().write("set mock_pedal_position " + position);
|
||||
if (onEachStep != null)
|
||||
onEachStep.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EtbTarget{" +
|
||||
"duration=" + duration +
|
||||
", position=" + position +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package com.rusefi.etb;
|
||||
|
||||
import com.rusefi.core.Sensor;
|
||||
import com.rusefi.core.SensorCentral;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.rusefi.Timeouts.SECOND;
|
||||
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
public static TestSequenceStep addSequence(TestSequenceStep first_step, Runnable onEachStep) {
|
||||
TestSequenceStep secondStep = new TestSequenceStep(SECOND) {
|
||||
@Override
|
||||
protected void doJob() {
|
||||
metric.reset();
|
||||
}
|
||||
};
|
||||
TestSequenceStep result = first_step.addNext(secondStep)
|
||||
.addNext(10 * SECOND, 4 /*position*/, onEachStep)
|
||||
.addNext(5 * SECOND, 6, /*position*/onEachStep)
|
||||
.addNext(5 * SECOND, 8, /*position*/onEachStep)
|
||||
.addNext(5 * SECOND, 6, /*position*/onEachStep)
|
||||
.addNext(5 * SECOND, 4, /*position*/onEachStep)
|
||||
.addNext(5 * SECOND, 2, /*position*/onEachStep)
|
||||
.addNext(5 * SECOND, 0, /*position*/onEachStep)
|
||||
.addNext(5 * SECOND, 10, /*position*/onEachStep)
|
||||
.addNext(3 * SECOND, 0, /*position*/onEachStep)
|
||||
.addNext(1 * SECOND, 6, /*position*/onEachStep)
|
||||
.addNext(1 * SECOND, 8, /*position*/onEachStep)
|
||||
.addNext(1 * SECOND, 6, /*position*/onEachStep)
|
||||
.addNext(1 * SECOND, 4, /*position*/onEachStep)
|
||||
.addNext(1 * SECOND, 2, /*position*/onEachStep)
|
||||
.addNext(1 * SECOND, 0, /*position*/onEachStep)
|
||||
.addNext(1 * SECOND, 10, /*position*/onEachStep)
|
||||
.addNext(3 * SECOND, 7, /*position*/onEachStep)
|
||||
.addNext(3 * SECOND, 6, /*position*/onEachStep)
|
||||
.addNext(3 * SECOND, 5, /*position*/onEachStep)
|
||||
.addNext(3 * SECOND, 4, /*position*/onEachStep)
|
||||
.addNext(3 * SECOND, 3, /*position*/onEachStep)
|
||||
.addNext(3 * SECOND, 2, /*position*/onEachStep)
|
||||
.addNext(3 * SECOND, 1, /*position*/onEachStep)
|
||||
.addNext(3 * SECOND, 0, /*position*/onEachStep)
|
||||
.addNext(10 * SECOND, 6, /*position*/onEachStep)
|
||||
.addNext(10 * SECOND, 30, /*position*/onEachStep)
|
||||
.addNext(10 * SECOND, 50, /*position*/onEachStep)
|
||||
.addNext(10 * SECOND, 70, /*position*/onEachStep)
|
||||
.addNext(10 * SECOND, 95, /*position*/onEachStep)
|
||||
.addNext(10 * SECOND, 50, /*position*/onEachStep)
|
||||
.addNext(10 * SECOND, 70, /*position*/onEachStep)
|
||||
.addNext(10 * SECOND, 4, /*position*/onEachStep)
|
||||
.addNext(10 * SECOND, 0, /*position*/onEachStep)
|
||||
;
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package com.rusefi.etb;
|
||||
|
||||
import com.rusefi.FileLog;
|
||||
import com.rusefi.core.MessagesCentral;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public abstract class TestSequenceStep {
|
||||
protected final long duration;
|
||||
private TestSequenceStep next;
|
||||
|
||||
public TestSequenceStep(long duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public void execute(ScheduledExecutorService executor) {
|
||||
doJob();
|
||||
if (next != null) {
|
||||
FileLog.MAIN.logLine("Scheduling " + next + " with " + duration + "ms delay");
|
||||
executor.schedule(() -> next.execute(executor), duration, TimeUnit.MILLISECONDS);
|
||||
} else {
|
||||
MessagesCentral.getInstance().postMessage(TestSequenceStep.class, "ETB test sequence done!");
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void doJob();
|
||||
|
||||
public TestSequenceStep addNext(long duration, double position, Runnable onEachStep) {
|
||||
return addNext(new EtbTarget(duration, position, onEachStep));
|
||||
}
|
||||
|
||||
public TestSequenceStep addNext(TestSequenceStep step) {
|
||||
next = step;
|
||||
return next;
|
||||
}
|
||||
}
|
|
@ -27,11 +27,11 @@ public class GaugesGridElement {
|
|||
this.config = config;
|
||||
}
|
||||
|
||||
public GaugesGridElement create(Sensor sensor) {
|
||||
return new GaugesGridElement(new Node()).create(sensor);
|
||||
public static JComponent create(Sensor sensor) {
|
||||
return new GaugesGridElement(new Node()).createGauge(sensor);
|
||||
}
|
||||
|
||||
private Component createLiveBarElement(final Sensor defaultSensor) {
|
||||
private JComponent createLiveBarElement(final Sensor defaultSensor) {
|
||||
wrapper.setLayout(new GridLayout(2, 1));
|
||||
|
||||
JMenuItem switchToGauge = new JMenuItem("Switch to Gauge Mode");
|
||||
|
@ -50,7 +50,7 @@ public class GaugesGridElement {
|
|||
return wrapper;
|
||||
}
|
||||
|
||||
private Component createGauge(final Sensor sensor) {
|
||||
private JComponent createGauge(final Sensor sensor) {
|
||||
SensorGauge.GaugeChangeListener gaugeChangeListener = new SensorGauge.GaugeChangeListener() {
|
||||
@Override
|
||||
public void onSensorChange(Sensor sensor) {
|
||||
|
@ -75,7 +75,7 @@ public class GaugesGridElement {
|
|||
return wrapper;
|
||||
}
|
||||
|
||||
public static Component read(final Node config, Sensor defaultSensor) {
|
||||
public static JComponent read(final Node config, Sensor defaultSensor) {
|
||||
|
||||
if (config.getBoolProperty(IS_LIVE_GRAPH)) {
|
||||
return new GaugesGridElement(config).createLiveBarElement(defaultSensor);
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package com.rusefi.ui.etb;
|
||||
|
||||
import org.putgemin.VerticalFlowLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class CalibrationPanel {
|
||||
private final JPanel content = new JPanel(new VerticalFlowLayout());
|
||||
|
||||
public CalibrationPanel() {
|
||||
content.setBorder(BorderFactory.createTitledBorder("Calibration"));
|
||||
content.add(new JButton("Grab TPS#1 fully closed"));
|
||||
content.add(new JButton("Grab TPS#1 Wide Open"));
|
||||
|
||||
content.add(new JButton("Grab Pedal Up"));
|
||||
content.add(new JButton("Grab Pedal Down"));
|
||||
}
|
||||
|
||||
public JPanel getContent() {
|
||||
return content;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.rusefi.ui.etb;
|
||||
|
||||
import com.rusefi.ui.util.UiUtils;
|
||||
import org.putgemin.VerticalFlowLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class CommandsPanel {
|
||||
private final JPanel content = new JPanel(new VerticalFlowLayout());
|
||||
|
||||
public CommandsPanel() {
|
||||
|
||||
|
||||
JPanel testParameters = new JPanel(new VerticalFlowLayout());
|
||||
testParameters.setBorder(BorderFactory.createTitledBorder("Try PID settings"));
|
||||
EtbTestSequence etbTestSequence = new EtbTestSequence();
|
||||
testParameters.add(UiUtils.wrap(etbTestSequence.getButton()));
|
||||
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"));
|
||||
|
||||
|
||||
|
||||
content.setBorder(BorderFactory.createTitledBorder("Commands"));
|
||||
|
||||
content.add(testParameters);
|
||||
content.add(UiUtils.wrap(new EtbMonteCarloSequence().getButton()));
|
||||
content.add(UiUtils.wrap(new MagicSpotsFinder().getButton()));
|
||||
}
|
||||
|
||||
public JPanel getContent() {
|
||||
return content;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
package com.rusefi.ui.widgets;
|
||||
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.io.CommandQueue;
|
||||
|
||||
import javax.swing.*;
|
||||
|
@ -11,7 +14,7 @@ import java.util.Random;
|
|||
|
||||
import static com.rusefi.SensorLogger.getSecondsSinceFileStart;
|
||||
import static com.rusefi.Timeouts.SECOND;
|
||||
import static com.rusefi.ui.widgets.EtbTestSequence.*;
|
||||
import static com.rusefi.ui.etb.EtbTestSequence.*;
|
||||
|
||||
/**
|
||||
* 3/2/2019
|
||||
|
@ -28,7 +31,7 @@ public class EtbMonteCarloSequence {
|
|||
counter = 0;
|
||||
|
||||
// 3000 data points at 10Hz should be 300 seconds worth of data
|
||||
metric.start(/* buffer size: */3000, /*period, ms: */ 100);
|
||||
StandardTestSequence.metric.start(/* buffer size: */3000, /*period, ms: */ 100);
|
||||
|
||||
executor.execute(this::runRandomCycle);
|
||||
});
|
||||
|
@ -50,9 +53,9 @@ public class EtbMonteCarloSequence {
|
|||
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) {
|
||||
TestSequenceStep firstStep = new EtbTarget(10 * SECOND, 4, null);
|
||||
TestSequenceStep last = StandardTestSequence.addSequence(firstStep, null);
|
||||
last.addNext(new TestSequenceStep(5 * SECOND) {
|
||||
@Override
|
||||
protected void doJob() {
|
||||
double result = SensorCentral.getInstance().getValue(Sensor.ETB_CONTROL_QUALITY);
|
|
@ -0,0 +1,76 @@
|
|||
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 javax.swing.*;
|
||||
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
|
||||
* (c) Andrey Belomutskiy
|
||||
*
|
||||
* @see TimeBasedBuffer
|
||||
*/
|
||||
public class EtbTestSequence {
|
||||
protected static final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
||||
|
||||
private static final String BUTTON_TEXT = "Measure Quality Control";
|
||||
|
||||
private final JButton button = new JButton(BUTTON_TEXT);
|
||||
private final JLabel result = new JLabel("Result: N/A");
|
||||
|
||||
public EtbTestSequence() {
|
||||
button.addActionListener(e -> {
|
||||
button.setEnabled(false);
|
||||
// 3000 data points at 10Hz should be 300 seconds worth of data
|
||||
StandardTestSequence.metric.start(/* buffer size: */3000, /*period, ms: */ 100);
|
||||
|
||||
AtomicInteger stepCounter = new AtomicInteger();
|
||||
|
||||
TestSequenceStep lastStep = new TestSequenceStep(SECOND) {
|
||||
@Override
|
||||
protected void doJob() {
|
||||
button.setEnabled(true);
|
||||
button.setText(BUTTON_TEXT);
|
||||
double value = StandardTestSequence.metric.getStandardDeviation();
|
||||
result.setText(String.format("Result: %.3f", value));
|
||||
}
|
||||
};
|
||||
|
||||
Runnable onEachStep = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
SwingUtilities.invokeLater(() -> button.setText("Running " + stepCounter.incrementAndGet()));
|
||||
}
|
||||
};
|
||||
|
||||
TestSequenceStep firstStep = new EtbTarget(10 * SECOND, 4, /*position*/onEachStep);
|
||||
TestSequenceStep result = StandardTestSequence.addSequence(firstStep, onEachStep);
|
||||
result.addNext(lastStep);
|
||||
firstStep.execute(executor);
|
||||
});
|
||||
}
|
||||
|
||||
public JButton getButton() {
|
||||
return button;
|
||||
}
|
||||
|
||||
public JLabel getResult() {
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.rusefi.ui.widgets;
|
||||
package com.rusefi.ui.etb;
|
||||
|
||||
import com.rusefi.core.MessagesCentral;
|
||||
import com.rusefi.core.Sensor;
|
||||
|
@ -11,12 +11,16 @@ import java.awt.event.ActionEvent;
|
|||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import static com.rusefi.Timeouts.SECOND;
|
||||
|
||||
/**
|
||||
* This tool finds interesting ETB duty cycles like the value when in starts to open or the value
|
||||
* when it's completely open
|
||||
* <p>
|
||||
* (c) Andrey Belomutskiy
|
||||
* 10/21/2018
|
||||
*/
|
||||
public class EtbResearch {
|
||||
private static final int SECOND = 1000;
|
||||
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;
|
||||
|
@ -27,7 +31,7 @@ public class EtbResearch {
|
|||
// private boolean isStarted;
|
||||
|
||||
|
||||
State state;
|
||||
private State state;
|
||||
private double currentValue;
|
||||
/**
|
||||
* here we record at which duty cycle ETB would start moving
|
||||
|
@ -149,7 +153,7 @@ public class EtbResearch {
|
|||
backToZeroValue = 0;
|
||||
}
|
||||
|
||||
public EtbResearch() {
|
||||
public MagicSpotsFinder() {
|
||||
button.addActionListener(new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
|
@ -1,159 +0,0 @@
|
|||
package com.rusefi.ui.widgets;
|
||||
|
||||
import com.rusefi.FileLog;
|
||||
import com.rusefi.TimeBasedBuffer;
|
||||
import com.rusefi.core.MessagesCentral;
|
||||
import com.rusefi.core.Sensor;
|
||||
import com.rusefi.core.SensorCentral;
|
||||
import com.rusefi.io.CommandQueue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* (c) Andrey Belomutskiy
|
||||
*
|
||||
* @see TimeBasedBuffer
|
||||
*/
|
||||
public class EtbTestSequence {
|
||||
protected static final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
||||
|
||||
protected 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
|
||||
);
|
||||
}
|
||||
|
||||
private final static long SECOND = 1000;
|
||||
|
||||
private final JButton button = new JButton("ETB Test");
|
||||
|
||||
|
||||
protected static SequenceStep addSequence(SequenceStep first_step) {
|
||||
return first_step.addNext(new SequenceStep(SECOND) {
|
||||
@Override
|
||||
protected void doJob() {
|
||||
metric.reset();
|
||||
}
|
||||
})
|
||||
.addNext(10 * SECOND, 4 /*position*/)
|
||||
.addNext(5 * SECOND, 6 /*position*/)
|
||||
.addNext(5 * SECOND, 8 /*position*/)
|
||||
.addNext(5 * SECOND, 6 /*position*/)
|
||||
.addNext(5 * SECOND, 4 /*position*/)
|
||||
.addNext(5 * SECOND, 2 /*position*/)
|
||||
.addNext(5 * SECOND, 0 /*position*/)
|
||||
.addNext(5 * SECOND, 10 /*position*/)
|
||||
.addNext(3 * SECOND, 0 /*position*/)
|
||||
.addNext(1 * SECOND, 6 /*position*/)
|
||||
.addNext(1 * SECOND, 8 /*position*/)
|
||||
.addNext(1 * SECOND, 6 /*position*/)
|
||||
.addNext(1 * SECOND, 4 /*position*/)
|
||||
.addNext(1 * SECOND, 2 /*position*/)
|
||||
.addNext(1 * SECOND, 0 /*position*/)
|
||||
.addNext(1 * SECOND, 10 /*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, 95 /*position*/)
|
||||
.addNext(10 * SECOND, 50 /*position*/)
|
||||
.addNext(10 * SECOND, 70 /*position*/)
|
||||
.addNext(10 * SECOND, 4 /*position*/)
|
||||
.addNext(10 * SECOND, 0 /*position*/)
|
||||
;
|
||||
}
|
||||
|
||||
public EtbTestSequence() {
|
||||
button.addActionListener(e -> {
|
||||
// 3000 data points at 10Hz should be 300 seconds worth of data
|
||||
metric.start(/* buffer size: */3000, /*period, ms: */ 100);
|
||||
|
||||
SequenceStep firstStep = new EtbTarget(10 * SECOND, 4 /*position*/);
|
||||
addSequence(firstStep);
|
||||
firstStep.execute(executor);
|
||||
});
|
||||
}
|
||||
|
||||
public JButton getButton() {
|
||||
return button;
|
||||
}
|
||||
|
||||
static abstract class SequenceStep {
|
||||
final long duration;
|
||||
SequenceStep next;
|
||||
|
||||
public SequenceStep(long duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public void execute(ScheduledExecutorService executor) {
|
||||
doJob();
|
||||
if (next != null) {
|
||||
FileLog.MAIN.logLine("Scheduling " + next + " with " + duration + "ms delay");
|
||||
executor.schedule(() -> next.execute(executor), duration, TimeUnit.MILLISECONDS);
|
||||
} else {
|
||||
MessagesCentral.getInstance().postMessage(EtbTestSequence.class, "ETB test sequence done!");
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void doJob();
|
||||
|
||||
public SequenceStep addNext(long duration, double position) {
|
||||
return addNext(new EtbTarget(duration, position));
|
||||
}
|
||||
|
||||
public SequenceStep addNext(SequenceStep step) {
|
||||
next = step;
|
||||
return next;
|
||||
}
|
||||
}
|
||||
|
||||
static class EtbTarget extends SequenceStep {
|
||||
/**
|
||||
* 0-100 percent open
|
||||
*/
|
||||
final double position;
|
||||
|
||||
public EtbTarget(long duration, double position) {
|
||||
super(duration);
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
protected void doJob() {
|
||||
CommandQueue.getInstance().write("set mock_pedal_position " + position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EtbTarget{" +
|
||||
"duration=" + duration +
|
||||
", position=" + position +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue