diff --git a/java_console/ui/src/com/rusefi/ETBPane.java b/java_console/ui/src/com/rusefi/ETBPane.java new file mode 100644 index 0000000000..a8bd8f4528 --- /dev/null +++ b/java_console/ui/src/com/rusefi/ETBPane.java @@ -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; + } + +} diff --git a/java_console/ui/src/com/rusefi/ui/widgets/ClosedLoopControlQualityMetric.java b/java_console/ui/src/com/rusefi/etb/ClosedLoopControlQualityMetric.java similarity index 96% rename from java_console/ui/src/com/rusefi/ui/widgets/ClosedLoopControlQualityMetric.java rename to java_console/ui/src/com/rusefi/etb/ClosedLoopControlQualityMetric.java index d1c316903a..9ccf8435dc 100644 --- a/java_console/ui/src/com/rusefi/ui/widgets/ClosedLoopControlQualityMetric.java +++ b/java_console/ui/src/com/rusefi/etb/ClosedLoopControlQualityMetric.java @@ -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()); } diff --git a/java_console/ui/src/com/rusefi/etb/EtbTarget.java b/java_console/ui/src/com/rusefi/etb/EtbTarget.java new file mode 100644 index 0000000000..e84c39dbfe --- /dev/null +++ b/java_console/ui/src/com/rusefi/etb/EtbTarget.java @@ -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 + + '}'; + } +} diff --git a/java_console/ui/src/com/rusefi/etb/StandardTestSequence.java b/java_console/ui/src/com/rusefi/etb/StandardTestSequence.java new file mode 100644 index 0000000000..9837743446 --- /dev/null +++ b/java_console/ui/src/com/rusefi/etb/StandardTestSequence.java @@ -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; + } +} diff --git a/java_console/ui/src/com/rusefi/etb/TestSequenceStep.java b/java_console/ui/src/com/rusefi/etb/TestSequenceStep.java new file mode 100644 index 0000000000..b0071f273d --- /dev/null +++ b/java_console/ui/src/com/rusefi/etb/TestSequenceStep.java @@ -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; + } +} diff --git a/java_console/ui/src/com/rusefi/ui/GaugesGridElement.java b/java_console/ui/src/com/rusefi/ui/GaugesGridElement.java index 8d9036d41f..7e031965dd 100644 --- a/java_console/ui/src/com/rusefi/ui/GaugesGridElement.java +++ b/java_console/ui/src/com/rusefi/ui/GaugesGridElement.java @@ -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); diff --git a/java_console/ui/src/com/rusefi/ui/etb/CalibrationPanel.java b/java_console/ui/src/com/rusefi/ui/etb/CalibrationPanel.java new file mode 100644 index 0000000000..d4a36f49ff --- /dev/null +++ b/java_console/ui/src/com/rusefi/ui/etb/CalibrationPanel.java @@ -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; + } +} diff --git a/java_console/ui/src/com/rusefi/ui/etb/CommandsPanel.java b/java_console/ui/src/com/rusefi/ui/etb/CommandsPanel.java new file mode 100644 index 0000000000..0fe00e0352 --- /dev/null +++ b/java_console/ui/src/com/rusefi/ui/etb/CommandsPanel.java @@ -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; + } +} diff --git a/java_console/ui/src/com/rusefi/ui/widgets/EtbMonteCarloSequence.java b/java_console/ui/src/com/rusefi/ui/etb/EtbMonteCarloSequence.java similarity index 83% rename from java_console/ui/src/com/rusefi/ui/widgets/EtbMonteCarloSequence.java rename to java_console/ui/src/com/rusefi/ui/etb/EtbMonteCarloSequence.java index b23b6dd2f9..ba906caf82 100644 --- a/java_console/ui/src/com/rusefi/ui/widgets/EtbMonteCarloSequence.java +++ b/java_console/ui/src/com/rusefi/ui/etb/EtbMonteCarloSequence.java @@ -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); diff --git a/java_console/ui/src/com/rusefi/ui/etb/EtbTestSequence.java b/java_console/ui/src/com/rusefi/ui/etb/EtbTestSequence.java new file mode 100644 index 0000000000..21d9c1cce2 --- /dev/null +++ b/java_console/ui/src/com/rusefi/ui/etb/EtbTestSequence.java @@ -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. + *

+ * Error standard deviation is posted to {@link Sensor#ETB_CONTROL_QUALITY} + *

+ * https://github.com/rusefi/rusefi/issues/494 + *

+ * 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; + } +} diff --git a/java_console/ui/src/com/rusefi/ui/widgets/EtbResearch.java b/java_console/ui/src/com/rusefi/ui/etb/MagicSpotsFinder.java similarity index 96% rename from java_console/ui/src/com/rusefi/ui/widgets/EtbResearch.java rename to java_console/ui/src/com/rusefi/ui/etb/MagicSpotsFinder.java index 440f798680..070f76ad54 100644 --- a/java_console/ui/src/com/rusefi/ui/widgets/EtbResearch.java +++ b/java_console/ui/src/com/rusefi/ui/etb/MagicSpotsFinder.java @@ -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 + *

* (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) { diff --git a/java_console/ui/src/com/rusefi/ui/widgets/EtbTestSequence.java b/java_console/ui/src/com/rusefi/ui/widgets/EtbTestSequence.java deleted file mode 100644 index d7055f83a6..0000000000 --- a/java_console/ui/src/com/rusefi/ui/widgets/EtbTestSequence.java +++ /dev/null @@ -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. - *

- * Error standard deviation is posted to {@link Sensor#ETB_CONTROL_QUALITY} - *

- * https://github.com/rusefi/rusefi/issues/494 - *

- * 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 + - '}'; - } - } -}