mirror of https://github.com/rusefi/RomRaider.git
added alpha version of maf scaler
git-svn-id: http://svn.3splooges.com/romraider-arch/trunk@777 d2e2e1cd-ba16-0410-be16-b7c4453c7c2d
This commit is contained in:
parent
063177f401
commit
f49e30d36d
18
logger.xml
18
logger.xml
|
@ -647,10 +647,10 @@
|
|||
|
||||
<parameter id="P200" name="Engine Load (Calculated)" desc="Engine load as calculated from MAF and RPM.">
|
||||
<depends>
|
||||
<ref parameter="P8"/>
|
||||
<!-- Engine Speed -->
|
||||
<ref parameter="P12"/>
|
||||
<ref parameter="P8"/>
|
||||
<!-- MAF -->
|
||||
<ref parameter="P12"/>
|
||||
</depends>
|
||||
<conversions>
|
||||
<conversion units="g/rev" expr="(P12*60)/P8" format="0.00"/>
|
||||
|
@ -661,10 +661,10 @@
|
|||
|
||||
<parameter id="P201" name="Injector Duty Cycle" desc="">
|
||||
<depends>
|
||||
<ref parameter="P8"/>
|
||||
<!-- Engine Speed -->
|
||||
<ref parameter="P21"/>
|
||||
<ref parameter="P8"/>
|
||||
<!-- Fuel Inj. #1 Pulse Width -->
|
||||
<ref parameter="P21"/>
|
||||
</depends>
|
||||
<conversions>
|
||||
<conversion units="%" expr="(P8*P21)/1200" format="0.00"/>
|
||||
|
@ -674,10 +674,10 @@
|
|||
<parameter id="P202" name="Manifold Rel. Pressure (Corrected)"
|
||||
desc="Difference between Manifold Absolute Pressure and Atmospheric Pressure.">
|
||||
<depends>
|
||||
<ref parameter="P7"/>
|
||||
<!-- MAP -->
|
||||
<ref parameter="P24"/>
|
||||
<ref parameter="P7"/>
|
||||
<!-- Atmos. Pressure -->
|
||||
<ref parameter="P24"/>
|
||||
</depends>
|
||||
<conversions>
|
||||
<conversion units="psi" expr="[P7:psi]-[P24:psi]" format="0.00"/>
|
||||
|
@ -688,12 +688,12 @@
|
|||
<parameter id="P203" name="Fuel Consumption (Est.)"
|
||||
desc="Estimated fuel consumption based on MAF, AFR and vehicle speed.">
|
||||
<depends>
|
||||
<ref parameter="P9"/>
|
||||
<!-- Vehicle Speed -->
|
||||
<ref parameter="P12"/>
|
||||
<ref parameter="P9"/>
|
||||
<!-- MAF-->
|
||||
<ref parameter="P58"/>
|
||||
<ref parameter="P12"/>
|
||||
<!-- AFR-->
|
||||
<ref parameter="P58"/>
|
||||
</depends>
|
||||
<conversions>
|
||||
<conversion units="mpg (US)" expr="([P9:mph]/3600)/((P12/[P58:AFR])/2880)" format="0.00"/>
|
||||
|
|
|
@ -21,6 +21,59 @@
|
|||
|
||||
package enginuity.logger.ecu;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import static java.awt.BorderLayout.CENTER;
|
||||
import static java.awt.BorderLayout.EAST;
|
||||
import static java.awt.BorderLayout.NORTH;
|
||||
import static java.awt.BorderLayout.SOUTH;
|
||||
import static java.awt.BorderLayout.WEST;
|
||||
import static java.awt.Color.BLACK;
|
||||
import static java.awt.Color.RED;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import static java.util.Collections.sort;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Vector;
|
||||
import static javax.swing.BorderFactory.createLoweredBevelBorder;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import static javax.swing.JComponent.WHEN_IN_FOCUSED_WINDOW;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import static javax.swing.JLabel.RIGHT;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import static javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED;
|
||||
import static javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER;
|
||||
import static javax.swing.JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED;
|
||||
import javax.swing.JSeparator;
|
||||
import static javax.swing.JSeparator.VERTICAL;
|
||||
import javax.swing.JSplitPane;
|
||||
import static javax.swing.JSplitPane.HORIZONTAL_SPLIT;
|
||||
import static javax.swing.JSplitPane.VERTICAL_SPLIT;
|
||||
import javax.swing.JTabbedPane;
|
||||
import static javax.swing.JTabbedPane.BOTTOM;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JToggleButton;
|
||||
import static javax.swing.KeyStroke.getKeyStroke;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.table.TableColumn;
|
||||
import enginuity.ECUEditor;
|
||||
import enginuity.Settings;
|
||||
import enginuity.io.port.SerialPortRefresher;
|
||||
import enginuity.logger.ecu.comms.controller.LoggerController;
|
||||
|
@ -62,6 +115,7 @@ import enginuity.logger.ecu.ui.handler.file.FileUpdateHandlerImpl;
|
|||
import enginuity.logger.ecu.ui.handler.graph.GraphUpdateHandler;
|
||||
import enginuity.logger.ecu.ui.handler.livedata.LiveDataTableModel;
|
||||
import enginuity.logger.ecu.ui.handler.livedata.LiveDataUpdateHandler;
|
||||
import enginuity.logger.ecu.ui.handler.maf.MafUpdateHandler;
|
||||
import enginuity.logger.ecu.ui.handler.table.TableUpdateHandler;
|
||||
import enginuity.logger.ecu.ui.paramlist.ParameterListTable;
|
||||
import enginuity.logger.ecu.ui.paramlist.ParameterListTableModel;
|
||||
|
@ -75,59 +129,6 @@ import static enginuity.util.ThreadUtil.runAsDaemon;
|
|||
import static enginuity.util.ThreadUtil.sleep;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import static javax.swing.BorderFactory.createLoweredBevelBorder;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import static javax.swing.JComponent.WHEN_IN_FOCUSED_WINDOW;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import static javax.swing.JLabel.RIGHT;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import static javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED;
|
||||
import static javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER;
|
||||
import static javax.swing.JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED;
|
||||
import javax.swing.JSeparator;
|
||||
import static javax.swing.JSeparator.VERTICAL;
|
||||
import javax.swing.JSplitPane;
|
||||
import static javax.swing.JSplitPane.HORIZONTAL_SPLIT;
|
||||
import static javax.swing.JSplitPane.VERTICAL_SPLIT;
|
||||
import javax.swing.JTabbedPane;
|
||||
import static javax.swing.JTabbedPane.BOTTOM;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JToggleButton;
|
||||
import static javax.swing.KeyStroke.getKeyStroke;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.table.TableColumn;
|
||||
import java.awt.BorderLayout;
|
||||
import static java.awt.BorderLayout.CENTER;
|
||||
import static java.awt.BorderLayout.EAST;
|
||||
import static java.awt.BorderLayout.NORTH;
|
||||
import static java.awt.BorderLayout.SOUTH;
|
||||
import static java.awt.BorderLayout.WEST;
|
||||
import static java.awt.Color.BLACK;
|
||||
import static java.awt.Color.RED;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import static java.util.Collections.sort;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Vector;
|
||||
|
||||
/*
|
||||
TODO: add better debug logging, preferably to a file and switchable (on/off)
|
||||
TODO: Clean up this class!
|
||||
|
@ -147,6 +148,7 @@ public final class EcuLogger extends JFrame implements WindowListener, PropertyC
|
|||
private static final String HEADING_EXTERNAL = "External";
|
||||
private static final String CAL_ID_LABEL = "CAL ID";
|
||||
private static final String ECU_ID_LABEL = "ECU ID";
|
||||
private ECUEditor ecuEditor;
|
||||
private Settings settings;
|
||||
private LoggerController controller;
|
||||
private ResetManager resetManager;
|
||||
|
@ -178,12 +180,24 @@ public final class EcuLogger extends JFrame implements WindowListener, PropertyC
|
|||
private GraphUpdateHandler graphUpdateHandler;
|
||||
private JPanel dashboardPanel;
|
||||
private DashboardUpdateHandler dashboardUpdateHandler;
|
||||
private JPanel mafPanel;
|
||||
private MafUpdateHandler mafUpdateHandler;
|
||||
private EcuInit ecuInit;
|
||||
private JToggleButton logToFileButton;
|
||||
private List<ExternalDataSource> externalDataSources;
|
||||
|
||||
public EcuLogger(Settings settings) {
|
||||
super(ENGINUITY_ECU_LOGGER_TITLE);
|
||||
construct(settings);
|
||||
}
|
||||
|
||||
public EcuLogger(ECUEditor ecuEditor) {
|
||||
super(ENGINUITY_ECU_LOGGER_TITLE);
|
||||
this.ecuEditor = ecuEditor;
|
||||
construct(ecuEditor.getSettings());
|
||||
}
|
||||
|
||||
private void construct(Settings settings) {
|
||||
bootstrap(settings);
|
||||
loadEcuDefs();
|
||||
loadLoggerPlugins();
|
||||
|
@ -229,8 +243,10 @@ public final class EcuLogger extends JFrame implements WindowListener, PropertyC
|
|||
graphUpdateHandler = new GraphUpdateHandler(graphPanel);
|
||||
dashboardPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 3, 3));
|
||||
dashboardUpdateHandler = new DashboardUpdateHandler(dashboardPanel);
|
||||
mafPanel = new JPanel(new BorderLayout(2, 2));
|
||||
mafUpdateHandler = new MafUpdateHandler(mafPanel, ecuEditor);
|
||||
controller = new LoggerControllerImpl(settings, ecuInitCallback, this, liveDataUpdateHandler,
|
||||
graphUpdateHandler, dashboardUpdateHandler, fileUpdateHandler, TableUpdateHandler.getInstance());
|
||||
graphUpdateHandler, dashboardUpdateHandler, mafUpdateHandler, fileUpdateHandler, TableUpdateHandler.getInstance());
|
||||
resetManager = new ResetManagerImpl(settings, this);
|
||||
messageLabel = new JLabel(ENGINUITY_ECU_LOGGER_TITLE);
|
||||
calIdLabel = new JLabel(buildEcuInfoLabelText(CAL_ID_LABEL, null));
|
||||
|
@ -565,6 +581,7 @@ public final class EcuLogger extends JFrame implements WindowListener, PropertyC
|
|||
tabbedPane.add("Data", buildSplitPane(buildParamListPane(dataTabParamListTableModel, dataTabSwitchListTableModel, dataTabExternalListTableModel), buildDataTab()));
|
||||
tabbedPane.add("Graph", buildSplitPane(buildParamListPane(graphTabParamListTableModel, graphTabSwitchListTableModel, graphTabExternalListTableModel), buildGraphTab()));
|
||||
tabbedPane.add("Dashboard", buildSplitPane(buildParamListPane(dashboardTabParamListTableModel, dashboardTabSwitchListTableModel, dashboardTabExternalListTableModel), buildDashboardTab()));
|
||||
tabbedPane.add("MAF", mafPanel);
|
||||
return tabbedPane;
|
||||
}
|
||||
|
||||
|
@ -948,23 +965,36 @@ public final class EcuLogger extends JFrame implements WindowListener, PropertyC
|
|||
//**********************************************************************
|
||||
|
||||
|
||||
public static void startLogger(final int defaultCloseOperation, final Settings settings) {
|
||||
public static void startLogger(int defaultCloseOperation, ECUEditor ecuEditor) {
|
||||
// instantiate the controlling class.
|
||||
final EcuLogger ecuLogger = new EcuLogger(ecuEditor);
|
||||
createAndShowGui(defaultCloseOperation, ecuLogger);
|
||||
}
|
||||
|
||||
public static void startLogger(int defaultCloseOperation, Settings settings) {
|
||||
// instantiate the controlling class.
|
||||
final EcuLogger ecuLogger = new EcuLogger(settings);
|
||||
createAndShowGui(defaultCloseOperation, ecuLogger);
|
||||
}
|
||||
|
||||
private static void createAndShowGui(final int defaultCloseOperation, final EcuLogger ecuLogger) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
createAndShowGUI(defaultCloseOperation, settings);
|
||||
doCreateAndShowGui(defaultCloseOperation, ecuLogger);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void createAndShowGUI(int defaultCloseOperation, Settings settings) {
|
||||
// instantiate the controlling class.
|
||||
EcuLogger ecuLogger = new EcuLogger(settings);
|
||||
private static void doCreateAndShowGui(int defaultCloseOperation, EcuLogger ecuLogger) {
|
||||
Settings settings = ecuLogger.getSettings();
|
||||
|
||||
// set default close operation
|
||||
ecuLogger.setDefaultCloseOperation(defaultCloseOperation);
|
||||
|
||||
// set remaining window properties
|
||||
ecuLogger.pack();
|
||||
ecuLogger.setSize(settings.getLoggerWindowSize());
|
||||
ecuLogger.setIconImage(new ImageIcon("./graphics/enginuity-ico.gif").getImage());
|
||||
ecuLogger.setDefaultCloseOperation(defaultCloseOperation);
|
||||
ecuLogger.addWindowListener(ecuLogger);
|
||||
|
||||
// display the window
|
||||
|
@ -974,5 +1004,4 @@ public final class EcuLogger extends JFrame implements WindowListener, PropertyC
|
|||
}
|
||||
ecuLogger.setVisible(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
package enginuity.logger.ecu.ui.handler.maf;
|
||||
|
||||
import static java.awt.BorderLayout.CENTER;
|
||||
import static java.awt.BorderLayout.WEST;
|
||||
import java.util.Set;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import enginuity.ECUEditor;
|
||||
import enginuity.logger.ecu.comms.query.Response;
|
||||
import enginuity.logger.ecu.definition.LoggerData;
|
||||
import enginuity.logger.ecu.ui.handler.DataUpdateHandler;
|
||||
import enginuity.logger.ecu.ui.tab.maf.MafChartPanel;
|
||||
import enginuity.logger.ecu.ui.tab.maf.MafControlPanel;
|
||||
import org.jfree.data.xy.XYSeries;
|
||||
|
||||
public final class MafUpdateHandler implements DataUpdateHandler {
|
||||
private static final String MAFV = "P18";
|
||||
private static final String AF_LEARNING_1 = "P4";
|
||||
private static final String AF_CORRECTION_1 = "P3";
|
||||
private final XYSeries series = new XYSeries("MAF Analysis");
|
||||
private final XYTrendline trendline = new XYTrendline();
|
||||
private final JPanel mafPanel;
|
||||
private final ECUEditor ecuEditor;
|
||||
private final MafControlPanel controlPanel;
|
||||
|
||||
public MafUpdateHandler(JPanel mafPanel, ECUEditor ecuEditor) {
|
||||
this.mafPanel = mafPanel;
|
||||
this.ecuEditor = ecuEditor;
|
||||
controlPanel = buildControlPanel();
|
||||
mafPanel.add(controlPanel, WEST);
|
||||
mafPanel.add(buildGraphPanel(), CENTER);
|
||||
}
|
||||
|
||||
private MafControlPanel buildControlPanel() {
|
||||
return new MafControlPanel(mafPanel, trendline, series, ecuEditor);
|
||||
}
|
||||
|
||||
private MafChartPanel buildGraphPanel() {
|
||||
return new MafChartPanel(trendline, series);
|
||||
}
|
||||
|
||||
public synchronized void registerData(LoggerData loggerData) {
|
||||
}
|
||||
|
||||
public synchronized void handleDataUpdate(Response response) {
|
||||
if (controlPanel.isRecordData() && containsData(response, MAFV, AF_LEARNING_1, AF_CORRECTION_1)) {
|
||||
boolean valid = true;
|
||||
|
||||
// cl/ol check
|
||||
// if (valid && (containsData(response, "E3") || containsData(response, "E27"))) {
|
||||
// double clOl = -1;
|
||||
// if (containsData(response, "E3")) {
|
||||
// clOl = (int) findValue(response, "E3");
|
||||
// }
|
||||
// if (containsData(response, "E27")) {
|
||||
// clOl = (int) findValue(response, "E27");
|
||||
// }
|
||||
// valid = clOl == 8;
|
||||
// }
|
||||
|
||||
// afr check
|
||||
if (valid && containsData(response, "P58")) {
|
||||
double afr = findValue(response, "P58");
|
||||
valid = controlPanel.isValidAfr(afr);
|
||||
}
|
||||
|
||||
// rpm check
|
||||
if (valid && containsData(response, "P8")) {
|
||||
double rpm = findValue(response, "P8");
|
||||
valid = controlPanel.isValidRpm(rpm);
|
||||
}
|
||||
|
||||
// maf check
|
||||
if (valid && containsData(response, "P12")) {
|
||||
double maf = findValue(response, "P12");
|
||||
valid = controlPanel.isValidMaf(maf);
|
||||
}
|
||||
|
||||
// coolant temp check
|
||||
if (valid && containsData(response, "P2")) {
|
||||
double temp = findValue(response, "P2");
|
||||
valid = controlPanel.isValidCoolantTemp(temp);
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
final double mafv = findValue(response, MAFV);
|
||||
final double learning = findValue(response, AF_LEARNING_1);
|
||||
final double correction = findValue(response, AF_CORRECTION_1);
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
series.add(mafv, learning + correction);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean containsData(Response response, String... ids) {
|
||||
Set<LoggerData> datas = response.getData();
|
||||
for (String id : ids) {
|
||||
boolean found = false;
|
||||
for (LoggerData data : datas) {
|
||||
if (data.getId().equals(id)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private double findValue(Response response, String id) {
|
||||
for (final LoggerData loggerData : response.getData()) {
|
||||
if (id.equals(loggerData.getId())) {
|
||||
return response.getDataValue(loggerData);
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("Expected data item " + id + " not in response.");
|
||||
}
|
||||
|
||||
public synchronized void deregisterData(LoggerData loggerData) {
|
||||
}
|
||||
|
||||
public synchronized void cleanUp() {
|
||||
}
|
||||
|
||||
public synchronized void reset() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package enginuity.logger.ecu.ui.handler.maf;
|
||||
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import jamlab.Polyfit;
|
||||
import jamlab.Polyval;
|
||||
import org.jfree.data.xy.AbstractXYDataset;
|
||||
import org.jfree.data.xy.XYDataItem;
|
||||
import org.jfree.data.xy.XYSeries;
|
||||
|
||||
public final class XYTrendline extends AbstractXYDataset {
|
||||
private List<XYDataItem> items = new ArrayList<XYDataItem>();
|
||||
private double[] xVals = new double[0];
|
||||
private double[] yPoly = new double[0];
|
||||
private Polyfit polyfit;
|
||||
|
||||
public int getSeriesCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public Comparable getSeriesKey(int seriesIndex) {
|
||||
return "foo";
|
||||
}
|
||||
|
||||
public synchronized int getItemCount(int seriesIndex) {
|
||||
return yPoly.length;
|
||||
}
|
||||
|
||||
public synchronized Number getY(int seriesIndex, int item) {
|
||||
return yPoly[item];
|
||||
}
|
||||
|
||||
public synchronized Number getX(int seriesIndex, int item) {
|
||||
return xVals[item];
|
||||
}
|
||||
|
||||
public synchronized void update(XYSeries series, int order) {
|
||||
if (series.getItemCount() <= order) return;
|
||||
items = new ArrayList<XYDataItem>(series.getItems());
|
||||
xVals = new double[items.size()];
|
||||
double[] yVals = new double[items.size()];
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
XYDataItem dataItem = items.get(i);
|
||||
xVals[i] = dataItem.getX().doubleValue();
|
||||
yVals[i] = dataItem.getY().doubleValue();
|
||||
}
|
||||
try {
|
||||
polyfit = new Polyfit(xVals, yVals, order);
|
||||
yPoly = calculate(xVals);
|
||||
} catch (Exception e) {
|
||||
throw new UndeclaredThrowableException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized double[] calculate(double[] x) {
|
||||
Polyval polyval = new Polyval(x, polyfit);
|
||||
return polyval.getYout();
|
||||
}
|
||||
|
||||
public synchronized void clear() {
|
||||
items.clear();
|
||||
xVals = new double[0];
|
||||
yPoly = new double[0];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package enginuity.logger.ecu.ui.tab.maf;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SpringLayout;
|
||||
import enginuity.logger.ecu.ui.handler.graph.SpringUtilities;
|
||||
import enginuity.logger.ecu.ui.handler.maf.XYTrendline;
|
||||
import static enginuity.util.ParamChecker.checkNotNull;
|
||||
import org.jfree.chart.ChartFactory;
|
||||
import org.jfree.chart.ChartPanel;
|
||||
import org.jfree.chart.JFreeChart;
|
||||
import static org.jfree.chart.plot.PlotOrientation.VERTICAL;
|
||||
import org.jfree.chart.plot.XYPlot;
|
||||
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
|
||||
import org.jfree.chart.renderer.xy.XYDotRenderer;
|
||||
import org.jfree.data.xy.XYDataset;
|
||||
import org.jfree.data.xy.XYSeries;
|
||||
import org.jfree.data.xy.XYSeriesCollection;
|
||||
|
||||
public final class MafChartPanel extends JPanel {
|
||||
private static final Color DARK_GREY = new Color(80, 80, 80);
|
||||
private static final Color LIGHT_GREY = new Color(110, 110, 110);
|
||||
private final XYTrendline trendline;
|
||||
private final XYSeries series;
|
||||
|
||||
public MafChartPanel(XYTrendline trendline, XYSeries series) {
|
||||
super(new SpringLayout());
|
||||
checkNotNull(trendline, series);
|
||||
this.trendline = trendline;
|
||||
this.series = series;
|
||||
addChart();
|
||||
}
|
||||
|
||||
private void addChart() {
|
||||
ChartPanel chartPanel = new ChartPanel(createChart(), false, true, true, true, true);
|
||||
chartPanel.setMinimumSize(new Dimension(500, 400));
|
||||
chartPanel.setPreferredSize(new Dimension(500, 400));
|
||||
add(chartPanel);
|
||||
SpringUtilities.makeCompactGrid(this, 1, 1, 2, 2, 2, 2);
|
||||
}
|
||||
|
||||
private JFreeChart createChart() {
|
||||
XYDataset dataset = buildDataset();
|
||||
return buildChart(dataset);
|
||||
}
|
||||
|
||||
private XYSeriesCollection buildDataset() {
|
||||
return new XYSeriesCollection(series);
|
||||
}
|
||||
|
||||
private JFreeChart buildChart(XYDataset dataset) {
|
||||
JFreeChart chart = ChartFactory.createScatterPlot(null, "MAF (v)", "Total Correction (%)", dataset, VERTICAL, false, true, false);
|
||||
chart.setBackgroundPaint(Color.BLACK);
|
||||
configurePlot(chart);
|
||||
addTrendLine(chart);
|
||||
return chart;
|
||||
}
|
||||
|
||||
private void configurePlot(JFreeChart chart) {
|
||||
XYPlot plot = chart.getXYPlot();
|
||||
plot.setBackgroundPaint(Color.BLACK);
|
||||
plot.getDomainAxis().setLabelPaint(Color.WHITE);
|
||||
plot.getRangeAxis().setLabelPaint(Color.WHITE);
|
||||
plot.getDomainAxis().setTickLabelPaint(LIGHT_GREY);
|
||||
plot.getRangeAxis().setTickLabelPaint(LIGHT_GREY);
|
||||
plot.setDomainGridlinePaint(DARK_GREY);
|
||||
plot.setRangeGridlinePaint(DARK_GREY);
|
||||
plot.setOutlinePaint(DARK_GREY);
|
||||
plot.setRenderer(buildScatterRenderer());
|
||||
}
|
||||
|
||||
private XYDotRenderer buildScatterRenderer() {
|
||||
XYDotRenderer renderer = new XYDotRenderer();
|
||||
renderer.setDotHeight(2);
|
||||
renderer.setDotWidth(2);
|
||||
return renderer;
|
||||
}
|
||||
|
||||
private void addTrendLine(JFreeChart chart) {
|
||||
XYPlot plot = chart.getXYPlot();
|
||||
plot.setDataset(1, trendline);
|
||||
plot.setRenderer(1, buildTrendLineRenderer());
|
||||
}
|
||||
|
||||
private StandardXYItemRenderer buildTrendLineRenderer() {
|
||||
return new StandardXYItemRenderer();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,315 @@
|
|||
package enginuity.logger.ecu.ui.tab.maf;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.GridBagConstraints;
|
||||
import static java.awt.GridBagConstraints.CENTER;
|
||||
import static java.awt.GridBagConstraints.HORIZONTAL;
|
||||
import static java.awt.GridBagConstraints.NONE;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import static javax.swing.JOptionPane.ERROR_MESSAGE;
|
||||
import static javax.swing.JOptionPane.OK_OPTION;
|
||||
import static javax.swing.JOptionPane.WARNING_MESSAGE;
|
||||
import static javax.swing.JOptionPane.YES_NO_OPTION;
|
||||
import static javax.swing.JOptionPane.showConfirmDialog;
|
||||
import static javax.swing.JOptionPane.showMessageDialog;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.border.TitledBorder;
|
||||
import enginuity.ECUEditor;
|
||||
import enginuity.logger.ecu.ui.handler.maf.XYTrendline;
|
||||
import enginuity.maps.DataCell;
|
||||
import enginuity.maps.Rom;
|
||||
import enginuity.maps.Table2D;
|
||||
import static enginuity.util.ParamChecker.checkNotNull;
|
||||
import org.jfree.data.xy.XYSeries;
|
||||
|
||||
public final class MafControlPanel extends JPanel {
|
||||
private final JToggleButton recordDataButton = new JToggleButton("Record Data");
|
||||
private final JTextField mafvMin = new JTextField("1.20", 3);
|
||||
private final JTextField mafvMax = new JTextField("2.60", 3);
|
||||
private final JTextField afrMin = new JTextField("14.0", 3);
|
||||
private final JTextField afrMax = new JTextField("16.0", 3);
|
||||
private final JTextField rpmMin = new JTextField("0", 3);
|
||||
private final JTextField rpmMax = new JTextField("4500", 3);
|
||||
private final JTextField mafMin = new JTextField("0", 3);
|
||||
private final JTextField mafMax = new JTextField("100", 3);
|
||||
private final JTextField coolantMin = new JTextField("80", 3);
|
||||
private final Component parent;
|
||||
private final XYTrendline trendline;
|
||||
private final XYSeries series;
|
||||
private final ECUEditor ecuEditor;
|
||||
|
||||
public MafControlPanel(Component parent, XYTrendline trendline, XYSeries series, ECUEditor ecuEditor) {
|
||||
checkNotNull(parent, trendline, series);
|
||||
this.parent = parent;
|
||||
this.trendline = trendline;
|
||||
this.series = series;
|
||||
this.ecuEditor = ecuEditor;
|
||||
addControls();
|
||||
}
|
||||
|
||||
public boolean isRecordData() {
|
||||
return recordDataButton.isSelected();
|
||||
}
|
||||
|
||||
public boolean isValidAfr(double value) {
|
||||
return checkInRange("AFR", afrMin, afrMax, value);
|
||||
}
|
||||
|
||||
public boolean isValidRpm(double value) {
|
||||
return checkInRange("RPM", rpmMin, rpmMax, value);
|
||||
}
|
||||
|
||||
public boolean isValidMaf(double value) {
|
||||
return checkInRange("MAF", mafMin, mafMax, value);
|
||||
}
|
||||
|
||||
public boolean isValidMafv(double value) {
|
||||
return checkInRange("MAFv", mafvMin, mafvMax, value);
|
||||
}
|
||||
|
||||
public boolean isValidCoolantTemp(double value) {
|
||||
return checkGreaterThan("Coolant Temp.", coolantMin, value);
|
||||
}
|
||||
|
||||
private boolean checkInRange(String name, JTextField min, JTextField max, double value) {
|
||||
if (isValidRange(min, max)) {
|
||||
return inRange(value, min, max);
|
||||
} else {
|
||||
showMessageDialog(parent, "Invalid " + name + " range specified.", "Error", ERROR_MESSAGE);
|
||||
recordDataButton.setSelected(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkGreaterThan(String name, JTextField min, double value) {
|
||||
if (isNumber(min)) {
|
||||
return value >= parseDouble(min);
|
||||
} else {
|
||||
showMessageDialog(parent, "Invalid " + name + " specified.", "Error", ERROR_MESSAGE);
|
||||
recordDataButton.setSelected(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void addControls() {
|
||||
JPanel panel = new JPanel();
|
||||
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
panel.setLayout(gridBagLayout);
|
||||
|
||||
add(panel, gridBagLayout, buildFilterPanel(), 0, 0, 1, HORIZONTAL);
|
||||
add(panel, gridBagLayout, buildInterpolatePanel(), 0, 1, 1, HORIZONTAL);
|
||||
add(panel, gridBagLayout, buildUpdateMafPanel(), 0, 2, 1, HORIZONTAL);
|
||||
add(panel, gridBagLayout, buildResetPanel(), 0, 3, 1, HORIZONTAL);
|
||||
|
||||
add(panel);
|
||||
}
|
||||
|
||||
private void add(JPanel panel, GridBagLayout gridBagLayout, JComponent component, int x, int y, int spanX, int fillType) {
|
||||
GridBagConstraints constraints = buildBaseConstraints();
|
||||
updateConstraints(constraints, x, y, spanX, 1, 1, 1, fillType);
|
||||
gridBagLayout.setConstraints(component, constraints);
|
||||
panel.add(component);
|
||||
}
|
||||
|
||||
private JPanel buildResetPanel() {
|
||||
JPanel panel = new JPanel();
|
||||
panel.setBorder(new TitledBorder("Reset"));
|
||||
panel.add(buildResetButton());
|
||||
return panel;
|
||||
}
|
||||
|
||||
private JPanel buildUpdateMafPanel() {
|
||||
JPanel panel = new JPanel();
|
||||
panel.setBorder(new TitledBorder("Update MAF"));
|
||||
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
panel.setLayout(gridBagLayout);
|
||||
|
||||
addMinMaxFilter(panel, gridBagLayout, "MAFv Range", mafvMin, mafvMax, 0);
|
||||
addComponent(panel, gridBagLayout, buildUpdateMafButton(), 3);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private JPanel buildInterpolatePanel() {
|
||||
JPanel panel = new JPanel();
|
||||
panel.setBorder(new TitledBorder("Interpolate"));
|
||||
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
panel.setLayout(gridBagLayout);
|
||||
|
||||
JComboBox orderComboBox = buildPolyOrderComboBox();
|
||||
addLabeledComponent(panel, gridBagLayout, "Poly. order", orderComboBox, 0);
|
||||
addComponent(panel, gridBagLayout, buildInterpolateButton(orderComboBox), 2);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void addLabeledComponent(JPanel panel, GridBagLayout gridBagLayout, String name, JComponent component, int y) {
|
||||
add(panel, gridBagLayout, new JLabel(name), 0, y, 3, HORIZONTAL);
|
||||
add(panel, gridBagLayout, component, 0, y + 1, 3, NONE);
|
||||
}
|
||||
|
||||
private JPanel buildFilterPanel() {
|
||||
JPanel panel = new JPanel();
|
||||
panel.setBorder(new TitledBorder("Filter Data"));
|
||||
|
||||
GridBagLayout gridBagLayout = new GridBagLayout();
|
||||
panel.setLayout(gridBagLayout);
|
||||
|
||||
addMinMaxFilter(panel, gridBagLayout, "AFR Range", afrMin, afrMax, 0);
|
||||
addMinMaxFilter(panel, gridBagLayout, "RPM Range", rpmMin, rpmMax, 3);
|
||||
addMinMaxFilter(panel, gridBagLayout, "MAF Range (g/s)", mafMin, mafMax, 6);
|
||||
addLabeledComponent(panel, gridBagLayout, "Min. Coolant Temp.", coolantMin, 9);
|
||||
addComponent(panel, gridBagLayout, recordDataButton, 12);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void addComponent(JPanel panel, GridBagLayout gridBagLayout, JComponent component, int y) {
|
||||
add(panel, gridBagLayout, component, 0, y, 3, HORIZONTAL);
|
||||
}
|
||||
|
||||
private void addMinMaxFilter(JPanel panel, GridBagLayout gridBagLayout, String name, JTextField min, JTextField max, int y) {
|
||||
add(panel, gridBagLayout, new JLabel(name), 0, y, 3, HORIZONTAL);
|
||||
y += 1;
|
||||
add(panel, gridBagLayout, min, 0, y, 1, NONE);
|
||||
add(panel, gridBagLayout, new JLabel(" - "), 1, y, 1, NONE);
|
||||
add(panel, gridBagLayout, max, 2, y, 1, NONE);
|
||||
}
|
||||
|
||||
private GridBagConstraints buildBaseConstraints() {
|
||||
GridBagConstraints constraints = new GridBagConstraints();
|
||||
constraints.anchor = CENTER;
|
||||
constraints.fill = NONE;
|
||||
return constraints;
|
||||
}
|
||||
|
||||
private void updateConstraints(GridBagConstraints constraints, int gridx, int gridy, int gridwidth, int gridheight, int weightx, int weighty, int fill) {
|
||||
constraints.gridx = gridx;
|
||||
constraints.gridy = gridy;
|
||||
constraints.gridwidth = gridwidth;
|
||||
constraints.gridheight = gridheight;
|
||||
constraints.weightx = weightx;
|
||||
constraints.weighty = weighty;
|
||||
constraints.fill = fill;
|
||||
}
|
||||
|
||||
private JButton buildResetButton() {
|
||||
JButton resetButton = new JButton("Reset Data");
|
||||
resetButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
trendline.clear();
|
||||
series.clear();
|
||||
parent.repaint();
|
||||
}
|
||||
});
|
||||
return resetButton;
|
||||
}
|
||||
|
||||
private JButton buildInterpolateButton(final JComboBox orderComboBox) {
|
||||
JButton interpolateButton = new JButton("Interpolate");
|
||||
interpolateButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
trendline.update(series, (Integer) orderComboBox.getSelectedItem());
|
||||
parent.repaint();
|
||||
}
|
||||
});
|
||||
return interpolateButton;
|
||||
}
|
||||
|
||||
private JComboBox buildPolyOrderComboBox() {
|
||||
final JComboBox orderComboBox = new JComboBox(new Object[]{3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20});
|
||||
orderComboBox.setSelectedItem(10);
|
||||
return orderComboBox;
|
||||
}
|
||||
|
||||
private JButton buildUpdateMafButton() {
|
||||
final JButton updateMafButton = new JButton("Update MAF");
|
||||
updateMafButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
Table2D table = getMafTable(ecuEditor);
|
||||
if (table != null) {
|
||||
if (showUpdateMafConfirmation() == OK_OPTION) {
|
||||
if (isValidRange(mafvMin, mafvMax)) {
|
||||
DataCell[] axisCells = table.getAxis().getData();
|
||||
double[] x = new double[axisCells.length];
|
||||
for (int i = 0; i < axisCells.length; i++) {
|
||||
DataCell cell = axisCells[i];
|
||||
x[i] = cell.getValue();
|
||||
}
|
||||
double[] percentChange = trendline.calculate(x);
|
||||
DataCell[] dataCells = table.getData();
|
||||
for (int i = 0; i < dataCells.length; i++) {
|
||||
if (inRange(axisCells[i].getValue(), mafvMin, mafvMax)) {
|
||||
DataCell cell = dataCells[i];
|
||||
double value = cell.getValue();
|
||||
cell.setRealValue(String.valueOf(value * (1.0 + percentChange[i] / 100.0)));
|
||||
}
|
||||
}
|
||||
table.colorize();
|
||||
} else {
|
||||
showMessageDialog(parent, "Invalid MAFv range specified.", "Error", ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return updateMafButton;
|
||||
}
|
||||
|
||||
private boolean areNumbers(JTextField... textFields) {
|
||||
for (JTextField field : textFields) {
|
||||
if (!isNumber(field)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isValidRange(JTextField min, JTextField max) {
|
||||
return areNumbers(min, max) && parseDouble(min) < parseDouble(max);
|
||||
}
|
||||
|
||||
private boolean isNumber(JTextField textField) {
|
||||
try {
|
||||
parseDouble(textField);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean inRange(double val, double min, double max) {
|
||||
return val >= min && val <= max;
|
||||
}
|
||||
|
||||
private boolean inRange(double value, JTextField min, JTextField max) {
|
||||
return inRange(value, parseDouble(min), parseDouble(max));
|
||||
}
|
||||
|
||||
private double parseDouble(JTextField field) {
|
||||
return Double.parseDouble(field.getText().trim());
|
||||
}
|
||||
|
||||
private int showUpdateMafConfirmation() {
|
||||
return showConfirmDialog(parent, "Update MAF Sensor Scaling table?", "Confirm Update", YES_NO_OPTION, WARNING_MESSAGE);
|
||||
}
|
||||
|
||||
private Table2D getMafTable(ECUEditor ecuEditor) {
|
||||
try {
|
||||
Rom rom = ecuEditor.getLastSelectedRom();
|
||||
return (Table2D) rom.getTable("MAF Sensor Scaling");
|
||||
} catch (Exception e) {
|
||||
showMessageDialog(parent, "MAF Sensor Scaling table not found.", "Error", ERROR_MESSAGE);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,13 +21,10 @@
|
|||
|
||||
package enginuity.swing;
|
||||
|
||||
import com.centerkey.utils.BareBonesBrowserLaunch;
|
||||
import enginuity.ECUEditor;
|
||||
import enginuity.logger.ecu.EcuLogger;
|
||||
import enginuity.logger.utec.gui.JutecGUI;
|
||||
import enginuity.maps.Rom;
|
||||
import enginuity.ramtune.test.RamTuneTestApp;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JFileChooser;
|
||||
import static javax.swing.JFrame.DISPOSE_ON_CLOSE;
|
||||
|
@ -41,10 +38,12 @@ import static javax.swing.JOptionPane.showConfirmDialog;
|
|||
import static javax.swing.JOptionPane.showMessageDialog;
|
||||
import javax.swing.JRadioButtonMenuItem;
|
||||
import javax.swing.JSeparator;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import com.centerkey.utils.BareBonesBrowserLaunch;
|
||||
import enginuity.ECUEditor;
|
||||
import enginuity.logger.ecu.EcuLogger;
|
||||
import enginuity.logger.utec.gui.JutecGUI;
|
||||
import enginuity.maps.Rom;
|
||||
import enginuity.ramtune.test.RamTuneTestApp;
|
||||
|
||||
public class ECUEditorMenuBar extends JMenuBar implements ActionListener {
|
||||
|
||||
|
@ -289,7 +288,7 @@ public class ECUEditorMenuBar extends JMenuBar implements ActionListener {
|
|||
parent.setUserLevel(5);
|
||||
|
||||
} else if (e.getSource() == openLogger) {
|
||||
EcuLogger.startLogger(DISPOSE_ON_CLOSE, parent.getSettings());
|
||||
EcuLogger.startLogger(DISPOSE_ON_CLOSE, parent);
|
||||
|
||||
} else if (e.getSource() == utecLogger) {
|
||||
JutecGUI.startLogger(DISPOSE_ON_CLOSE, parent.getSettings());
|
||||
|
|
Loading…
Reference in New Issue