/*
* Open-Source tuning tools
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.vgi.mafscaling;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.ResourceBundle;
import java.util.TreeMap;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.border.LineBorder;
import javax.swing.table.DefaultTableModel;
import org.apache.log4j.Logger;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYSeries;
public class OpenLoop extends AMafScaling {
private static final long serialVersionUID = 2988105467764335997L;
private static final Logger logger = Logger.getLogger(OpenLoop.class);
private static final String SaveDataFileHeader = "[open_loop run data]";
private static final String RunTableName = "Run ";
private static final String Y2AxisName = "AFR Error (%)";
private static final String rpmAxisName = "RPM";
private static final String runDataName = "AFR Error";
private static final int RunCount = 10;
private static final int RunRowsCount = 200;
private double minMafV = Config.getMafVMinimumValue();
private double afrErrPrct = Config.getWidebandAfrErrorPercentValue();
private double minWotEnrichment = Config.getWOTEnrichmentValue();
private int wotPoint = Config.getWOTStationaryPointValue();
private int afrRowOffset = Config.getWBO2RowOffset();
private int skipRowsOnTransition = Config.getOLCLTransitionSkipRows();
private int logThtlAngleColIdx = -1;
private int logAfLearningColIdx = -1;
private int logAfCorrectionColIdx = -1;
private int logMafvColIdx = -1;
private int logAfrColIdx = -1;
private int logRpmColIdx = -1;
private int logLoadColIdx = -1;
private int logMapColIdx = -1;
private int logCommandedAfrColIdx = -1;
private JCheckBox checkBoxMafRpmData = null;
private ArrayList<Double> afrArray = new ArrayList<Double>();
private ArrayList<JTable> runTables = new ArrayList<JTable>();
private ArrayList<JButton> removeButtons = new ArrayList<JButton>();
private GridBagLayout gbl_dataRunPanel = null;
private GridBagConstraints gbc_run = null;
JPanel dataRunPanel = null;
public OpenLoop(int tabPlacement, PrimaryOpenLoopFuelingTable table, MafCompare comparer) {
super(tabPlacement, table, comparer);
runData = new XYSeries(runDataName);
initialize();
}
//////////////////////////////////////////////////////////////////////////////////////
// DATA TAB
//////////////////////////////////////////////////////////////////////////////////////
protected void createRunPanel(JPanel dataPanel) {
JScrollPane dataScrollPane = new JScrollPane();
GridBagConstraints gbc_dataScrollPane = new GridBagConstraints();
gbc_dataScrollPane.weightx = 1.0;
gbc_dataScrollPane.weighty = 1.0;
gbc_dataScrollPane.fill = GridBagConstraints.BOTH;
gbc_dataScrollPane.gridx = 0;
gbc_dataScrollPane.gridy = 3;
dataPanel.add(dataScrollPane, gbc_dataScrollPane);
dataRunPanel = new JPanel();
dataScrollPane.setViewportView(dataRunPanel);
gbl_dataRunPanel = new GridBagLayout();
gbl_dataRunPanel.columnWidths = new int[RunCount];
gbl_dataRunPanel.rowHeights = new int[] {0};
gbl_dataRunPanel.columnWeights = new double[RunCount];
gbl_dataRunPanel.columnWeights[RunCount -1] = 1.0;
gbl_dataRunPanel.rowWeights = new double[]{0.0};
dataRunPanel.setLayout(gbl_dataRunPanel);
createRunTables(dataRunPanel);
}
private void createRunTables(JPanel dataRunPanel) {
gbc_run = new GridBagConstraints();
gbc_run.anchor = GridBagConstraints.PAGE_START;
gbc_run.insets = new Insets(0, 2, 0, 2);
gbc_run.fill = GridBagConstraints.HORIZONTAL;
for (int i = 0; i < RunCount; ++i)
addRunTable();
}
private void addRunTable() {
JTable table = new JTable();
runTables.add(table);
table.getTableHeader().setReorderingAllowed(false);
table.setModel(new DefaultTableModel(RunRowsCount, 3));
table.setColumnSelectionAllowed(true);
table.setCellSelectionEnabled(true);
table.setBorder(new LineBorder(new Color(0, 0, 0)));
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.putClientProperty("terminateEditOnFocusLost", true);
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.getColumnModel().getColumn(0).setHeaderValue("<html><center>Engine<br>Speed<br>(RPM)<br></center></html>");
table.getColumnModel().getColumn(1).setHeaderValue("<html><center>MAF<br>Sensor<br>Voltage<br></center></html>");
table.getColumnModel().getColumn(2).setHeaderValue("<html><center>AFR<br>Error<br>%<br></center></html>");
Utils.initializeTable(table, ColumnWidth);
excelAdapter.addTable(table, true, false);
gbl_dataRunPanel.columnWidths = new int[runTables.size() + 1];
gbl_dataRunPanel.columnWeights = new double[runTables.size() + 1];
gbl_dataRunPanel.columnWeights[runTables.size()] = 1.0;
gbc_run.gridx = runTables.size() - 1;
gbc_run.gridy = 0;
JButton jb = new JButton("remove");
jb.setActionCommand("trem");
jb.addActionListener(this);
jb.setPreferredSize(new Dimension(150,20));
removeButtons.add(jb);
dataRunPanel.add(jb, gbc_run);
gbc_run.gridy = 1;
dataRunPanel.add(table.getTableHeader(), gbc_run);
gbc_run.gridy = 2;
dataRunPanel.add(table, gbc_run);
repaint();
revalidate();
}
private void removeRunTable(int index) {
JButton jb = removeButtons.remove(index);
JTable table = runTables.remove(index);
excelAdapter.removeTable(table);
dataRunPanel.remove(jb);
dataRunPanel.remove(table.getTableHeader());
dataRunPanel.remove(table);
gbl_dataRunPanel.columnWidths = new int[runTables.size() + 1];
gbl_dataRunPanel.columnWeights = new double[runTables.size() + 1];
gbl_dataRunPanel.columnWeights[runTables.size()] = 1.0;
for (int i = 0; i < runTables.size(); ++i) {
jb = removeButtons.get(i);
table = runTables.get(i);
gbc_run.gridx = i;
gbc_run.gridy = 0;
dataRunPanel.add(jb, gbc_run);
gbc_run.gridy = 1;
dataRunPanel.add(table.getTableHeader(), gbc_run);
gbc_run.gridy = 2;
dataRunPanel.add(table, gbc_run);
}
repaint();
revalidate();
}
//////////////////////////////////////////////////////////////////////////////////////
// CREATE CHART TAB
//////////////////////////////////////////////////////////////////////////////////////
protected void createGraphTab() {
JPanel cntlPanel = new JPanel();
JPanel plotPanel = createGraphPlotPanel(cntlPanel);
add(plotPanel, "<html><div style='text-align: center;'>C<br>h<br>a<br>r<br>t</div></html>");
GridBagLayout gbl_cntlPanel = new GridBagLayout();
gbl_cntlPanel.columnWidths = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
gbl_cntlPanel.rowHeights = new int[]{0, 0};
gbl_cntlPanel.columnWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
gbl_cntlPanel.rowWeights = new double[]{0};
cntlPanel.setLayout(gbl_cntlPanel);
GridBagConstraints gbc_check = new GridBagConstraints();
gbc_check.insets = insets2;
gbc_check.gridx = 0;
gbc_check.gridy = 0;
checkBoxMafRpmData = new JCheckBox("MafV/RPM");
checkBoxMafRpmData.setActionCommand("mafrpm");
checkBoxMafRpmData.addActionListener(this);
cntlPanel.add(checkBoxMafRpmData, gbc_check);
gbc_check.gridx++;
checkBoxRunData = new JCheckBox("AFR Error");
checkBoxRunData.setActionCommand("rdata");
checkBoxRunData.addActionListener(this);
cntlPanel.add(checkBoxRunData, gbc_check);
gbc_check.gridx++;
createGraphCommonControls(cntlPanel, gbc_check.gridx);
createChart(plotPanel, Y2AxisName);
createMafSmoothingPanel(plotPanel);
}
//////////////////////////////////////////////////////////////////////////////////////
// COMMON ACTIONS RELATED FUNCTIONS
//////////////////////////////////////////////////////////////////////////////////////
@Override
public void actionPerformed(ActionEvent e) {
if (checkActionPerformed(e))
return;
if ("mafrpm".equals(e.getActionCommand())) {
JCheckBox checkBox = (JCheckBox)e.getSource();
if (checkBox.isSelected()) {
clearNotRunDataCheckboxes();
if (!plotMafVRpmData())
checkBox.setSelected(false);
}
else
runData.clear();
setRanges();
}
else if ("rdata".equals(e.getActionCommand())) {
JCheckBox checkBox = (JCheckBox)e.getSource();
if (checkBox.isSelected()) {
if (checkBoxMafRpmData.isSelected()) {
checkBoxMafRpmData.setSelected(false);
runData.clear();
}
if (!plotRunData())
checkBox.setSelected(false);
}
else
runData.clear();
setRanges();
}
else if ("current".equals(e.getActionCommand())) {
JCheckBox checkBox = (JCheckBox)e.getSource();
if (checkBox.isSelected()) {
if (checkBoxMafRpmData.isSelected()) {
checkBoxMafRpmData.setSelected(false);
runData.clear();
}
if (!plotCurrentMafData())
checkBox.setSelected(false);
}
else
currMafData.clear();
setRanges();
}
else if ("corrected".equals(e.getActionCommand())) {
JCheckBox checkBox = (JCheckBox)e.getSource();
if (checkBox.isSelected()) {
if (checkBoxMafRpmData.isSelected()) {
checkBoxMafRpmData.setSelected(false);
runData.clear();
}
if (!setCorrectedMafData())
checkBox.setSelected(false);
}
else
corrMafData.clear();
setRanges();
}
else if ("smoothed".equals(e.getActionCommand())) {
JCheckBox checkBox = (JCheckBox)e.getSource();
if (checkBox.isSelected()) {
if (checkBoxMafRpmData.isSelected()) {
checkBoxMafRpmData.setSelected(false);
runData.clear();
}
if (!setSmoothedMafData())
checkBox.setSelected(false);
}
else
smoothMafData.clear();
setRanges();
}
else if ("smoothing".equals(e.getActionCommand())) {
JCheckBox checkBox = (JCheckBox)e.getSource();
if (checkBox.isSelected())
enableSmoothingView(true);
else
enableSmoothingView(false);
setRanges();
}
else if ("trem".equals(e.getActionCommand())) {
JButton sjb = (JButton) e.getSource();
int idx = 0;
for (JButton jb : removeButtons) {
if (jb == sjb)
break;
idx += 1;
}
removeRunTable(idx);
}
}
protected void clearRunTables() {
setCursor(new Cursor(Cursor.WAIT_CURSOR));
try {
while (runTables.size() > RunCount)
removeRunTable(runTables.size() - 1);
for (int i = 0; i < runTables.size(); ++i) {
while (RunRowsCount < runTables.get(i).getRowCount())
Utils.removeRow(RunRowsCount, runTables.get(i));
Utils.clearTable(runTables.get(i));
}
}
finally {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
protected void clearData() {
super.clearData();
afrArray.clear();
}
protected void clearChartCheckBoxes() {
super.clearChartCheckBoxes();
checkBoxMafRpmData.setSelected(false);
}
protected void calculateMafScaling() {
setCursor(new Cursor(Cursor.WAIT_CURSOR));
try {
clearData();
clearChartData();
clearChartCheckBoxes();
TreeMap<Integer, ArrayList<Double>> result = new TreeMap<Integer, ArrayList<Double>>();
if (!getMafTableData(voltArray, gsArray))
return;
if (!sortRunData(result) || result.isEmpty())
return;
calculateCorrectedGS(result);
setCorrectedMafData();
smoothGsArray.addAll(gsCorrected);
checkBoxCorrectedMaf.setSelected(true);
setXYTable(mafSmoothingTable, voltArray, smoothGsArray);
setRanges();
setSelectedIndex(1);
}
catch (Exception e) {
e.printStackTrace();
logger.error(e);
JOptionPane.showMessageDialog(null, "Error: " + e, "Error", JOptionPane.ERROR_MESSAGE);
}
finally {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
private boolean sortRunData(TreeMap<Integer, ArrayList<Double>> result) {
int closestVoltIdx;
double rpm;
double voltage;
double error;
ArrayList<Double> closestVolatageArray;
for (int i = 0; i < runTables.size(); ++i) {
JTable table = runTables.get(i);
String tableName = RunTableName + (i + 1);
String rpmValue;
String mafvValue;
String afrValue;
for (int j = 0; j < table.getRowCount(); ++j) {
rpmValue = table.getValueAt(j, 0).toString();
mafvValue = table.getValueAt(j, 1).toString();
afrValue = table.getValueAt(j, 2).toString();
if (rpmValue.isEmpty() || mafvValue.isEmpty() || afrValue.isEmpty())
continue;
if (!Utils.validateDouble(rpmValue, j, 0, tableName) ||
!Utils.validateDouble(mafvValue, j, 1, tableName) ||
!Utils.validateDouble(afrValue, j, 2, tableName))
return false;
rpm = Double.parseDouble(rpmValue);
voltage = Double.parseDouble(mafvValue);
error = Double.parseDouble(afrValue);
rpmArray.add(rpm);
mafvArray.add(voltage);
afrArray.add(error);
closestVoltIdx = Utils.closestValueIndex(voltage, voltArray);
closestVolatageArray = result.get(closestVoltIdx);
if (closestVolatageArray == null) {
closestVolatageArray = new ArrayList<Double>();
result.put(closestVoltIdx, closestVolatageArray);
}
closestVolatageArray.add(error);
}
}
return true;
}
private void calculateCorrectedGS(TreeMap<Integer, ArrayList<Double>> result) {
ArrayList<Double> closestVolatageArray;
double gs = 0;
double avgError = 0;
int lastErrIndex = 0;
int i;
gsCorrected.addAll(gsArray);
for (i = 0; i < gsCorrected.size(); ++i) {
gs = gsCorrected.get(i);
avgError = 0;
closestVolatageArray = result.get(i);
if (closestVolatageArray != null) {
for (int j = 0; j < closestVolatageArray.size(); ++j)
avgError += closestVolatageArray.get(j);
avgError /= closestVolatageArray.size();
lastErrIndex = i;
}
gsCorrected.set(i, gs * (1 + avgError/100.0));
}
avgError = 0;
ArrayList<Double> sortedAfrArray = result.get(lastErrIndex);
Collections.sort(sortedAfrArray, Collections.reverseOrder());
for (i = 0; i < 10 && i < sortedAfrArray.size(); ++i)
avgError += sortedAfrArray.get(i);
if (i > 0)
avgError /= i;
for (i = lastErrIndex + 1; i < gsCorrected.size(); ++i) {
gs = gsCorrected.get(i);
gsCorrected.set(i, gs +(gs * 0.01 * avgError));
}
}
private boolean plotMafVRpmData() {
return setXYSeries(runData, rpmArray, mafvArray);
}
private boolean plotRunData() {
return setXYSeries(runData, mafvArray, afrArray);
}
private void setRanges() {
double paddingX;
double paddingY;
XYPlot plot = mafChartPanel.getChartPanel().getChart().getXYPlot();
plot.getDomainAxis(0).setLabel(XAxisName);
plot.getRangeAxis(1).setLabel(Y2AxisName);
plot.getRangeAxis(0).setVisible(true);
if (checkBoxMafRpmData.isSelected() && checkBoxMafRpmData.isEnabled()) {
paddingX = runData.getMaxX() * 0.05;
paddingY = runData.getMaxY() * 0.05;
plot.getDomainAxis(0).setRange(runData.getMinX() - paddingX, runData.getMaxX() + paddingX);
plot.getRangeAxis(1).setRange(runData.getMinY() - paddingY, runData.getMaxY() + paddingY);
plot.getRangeAxis(0).setVisible(false);
plot.getRangeAxis(1).setLabel(XAxisName);
plot.getDomainAxis(0).setLabel(rpmAxisName);
}
else if (checkBoxRunData.isSelected() && checkBoxRunData.isEnabled() &&
!checkBoxCurrentMaf.isSelected() && !checkBoxCorrectedMaf.isSelected() && !checkBoxSmoothedMaf.isSelected()) {
paddingX = runData.getMaxX() * 0.05;
paddingY = runData.getMaxY() * 0.05;
plot.getDomainAxis(0).setRange(runData.getMinX() - paddingX, runData.getMaxX() + paddingX);
plot.getRangeAxis(1).setRange(runData.getMinY() - paddingY, runData.getMaxY() + paddingY);
}
else if (checkBoxSmoothing.isSelected()) {
double maxY = Collections.max(Arrays.asList(new Double[] { currMafData.getMaxY(), smoothMafData.getMaxY(), corrMafData.getMaxY() }));
double minY = Collections.min(Arrays.asList(new Double[] { currMafData.getMinY(), smoothMafData.getMinY(), corrMafData.getMinY() }));
paddingX = smoothMafData.getMaxX() * 0.05;
paddingY = maxY * 0.05;
plot.getDomainAxis(0).setRange(smoothMafData.getMinX() - paddingX, smoothMafData.getMaxX() + paddingX);
plot.getRangeAxis(0).setRange(minY - paddingY, maxY + paddingY);
}
else if ((checkBoxCurrentMaf.isSelected() && checkBoxCurrentMaf.isEnabled()) ||
(checkBoxCorrectedMaf.isSelected() && checkBoxCorrectedMaf.isEnabled()) ||
(checkBoxSmoothedMaf.isSelected() && checkBoxSmoothedMaf.isEnabled())) {
paddingX = voltArray.get(voltArray.size() - 1) * 0.05;
paddingY = gsCorrected.get(gsCorrected.size() - 1) * 0.05;
plot.getDomainAxis(0).setRange(voltArray.get(0) - paddingX, voltArray.get(voltArray.size() - 1) + paddingX);
plot.getRangeAxis(0).setRange(gsCorrected.get(0) - paddingY, gsCorrected.get(gsCorrected.size() - 1) + paddingY);
if (checkBoxRunData.isSelected()) {
paddingX = runData.getMaxX() * 0.05;
paddingY = runData.getMaxY() * 0.05;
plot.getRangeAxis(1).setRange(runData.getMinY() - paddingY, runData.getMaxY() + paddingY);
}
}
else {
plot.getRangeAxis(0).setAutoRange(true);
plot.getDomainAxis(0).setAutoRange(true);
}
}
protected void onEnableSmoothingView(boolean flag) {
checkBoxMafRpmData.setEnabled(!flag);
if (flag == false) {
if (checkBoxMafRpmData.isSelected())
plotMafVRpmData();
if (checkBoxRunData.isSelected())
plotRunData();
if (checkBoxCurrentMaf.isSelected())
plotCurrentMafData();
if (checkBoxCorrectedMaf.isSelected())
setCorrectedMafData();
if (checkBoxSmoothedMaf.isSelected())
setSmoothedMafData();
}
}
protected void onSmoothReset() {
if (!checkBoxMafRpmData.isEnabled() || !checkBoxMafRpmData.isSelected())
setCorrectedMafData();
if (checkBoxSmoothing.isSelected())
plotSmoothingLineSlopes();
else if (checkBoxSmoothedMaf.isSelected())
setSmoothedMafData();
}
public void saveData() {
if (JFileChooser.APPROVE_OPTION != fileChooser.showSaveDialog(this))
return;
File file = fileChooser.getSelectedFile();
setCursor(new Cursor(Cursor.WAIT_CURSOR));
int i, j;
Writer out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), Config.getEncoding()));
// write string identifier
out.write(SaveDataFileHeader + "\n");
// write maf data
for (i = 0; i < mafTable.getRowCount(); ++i) {
for (j = 0; j < mafTable.getColumnCount(); ++j)
out.write(mafTable.getValueAt(i, j).toString() + ",");
out.write("\n");
}
// write run data
for (int t = 0; t < runTables.size(); ++t) {
JTable table = runTables.get(t);
for (i = 0; i < table.getColumnCount(); ++i) {
for (j = 0; j < table.getRowCount(); ++j)
out.write(table.getValueAt(j, i).toString() + ",");
out.write("\n");
}
}
}
catch (Exception e) {
logger.error(e);
}
finally {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
if (out != null) {
try {
out.close();
}
catch (IOException e) {
logger.error(e);
}
}
}
}
public void loadData() {
fileChooser.setMultiSelectionEnabled(false);
if (JFileChooser.APPROVE_OPTION != fileChooser.showOpenDialog(this))
return;
File file = fileChooser.getSelectedFile();
int i, j, k, l;
setCursor(new Cursor(Cursor.WAIT_CURSOR));
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream(file.getAbsoluteFile()), Config.getEncoding()));
String line = br.readLine();
if (line == null || !line.equals(SaveDataFileHeader)) {
JOptionPane.showMessageDialog(null, "Invalid saved data file!", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
line = br.readLine();
String[] elements;
JTable table = null;
i = k = l = 0;
while (line != null) {
elements = line.split(Utils.fileFieldSplitter, -1);
switch (i) {
case 0:
Utils.ensureColumnCount(elements.length - 1, mafTable);
for (j = 0; j < elements.length - 1; ++j)
mafTable.setValueAt(elements[j], i, j);
break;
case 1:
Utils.ensureColumnCount(elements.length - 1, mafTable);
for (j = 0; j < elements.length - 1; ++j)
mafTable.setValueAt(elements[j], i, j);
break;
default:
int offset = runTables.size() * 3 + mafTable.getRowCount();
if (i > 1 && i < offset) {
if (l == 0 )
table = runTables.get(k++);
Utils.ensureRowCount(elements.length - 1, table);
for (j = 0; j < elements.length - 1; ++j)
table.setValueAt(elements[j], j, l);
l += 1;
if (l == 3)
l = 0;
}
}
i += 1;
line = br.readLine();
}
}
catch (Exception e) {
e.printStackTrace();
logger.error(e);
}
finally {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
if (br != null) {
try {
br.close();
}
catch (IOException e) {
logger.error(e);
}
}
}
}
private boolean getColumnsFilters(String[] elements, boolean isPolfTableSet, boolean isPolfTableMap) {
boolean ret = true;
ArrayList<String> columns = new ArrayList<String>(Arrays.asList(elements));
String logThtlAngleColName = Config.getThrottleAngleColumnName();
String logAfLearningColName = Config.getAfLearningColumnName();
String logAfCorrectionColName = Config.getAfCorrectionColumnName();
String logMafvColName = Config.getMafVoltageColumnName();
String logAfrColName = Config.getWidebandAfrColumnName();
String logRpmColName = Config.getRpmColumnName();
String logLoadColName = Config.getLoadColumnName();
String logMapColName = Config.getMapColumnName();
String logCommandedAfrColName = Config.getCommandedAfrColumnName();
logThtlAngleColIdx = columns.indexOf(logThtlAngleColName);
logAfLearningColIdx = columns.indexOf(logAfLearningColName);
logAfCorrectionColIdx = columns.indexOf(logAfCorrectionColName);
logMafvColIdx = columns.indexOf(logMafvColName);
logAfrColIdx = columns.indexOf(logAfrColName);
logRpmColIdx = columns.indexOf(logRpmColName);
logLoadColIdx = columns.indexOf(logLoadColName);
logMapColIdx = columns.indexOf(logMapColName);
logCommandedAfrColIdx = columns.indexOf(logCommandedAfrColName);
if (logThtlAngleColIdx == -1) { Config.setThrottleAngleColumnName(Config.NO_NAME); ret = false; }
if (logAfLearningColIdx == -1) { Config.setAfLearningColumnName(Config.NO_NAME); ret = false; }
if (logAfCorrectionColIdx == -1) { Config.setAfCorrectionColumnName(Config.NO_NAME); ret = false; }
if (logMafvColIdx == -1) { Config.setMafVoltageColumnName(Config.NO_NAME); ret = false; }
if (logAfrColIdx == -1) { Config.setWidebandAfrColumnName(Config.NO_NAME); ret = false; }
if (logRpmColIdx == -1) { Config.setRpmColumnName(Config.NO_NAME); ret = false; }
if (logLoadColIdx == -1 && isPolfTableSet && !isPolfTableMap) { Config.setLoadColumnName(Config.NO_NAME); ret = false; }
if (logMapColIdx == -1 && isPolfTableMap) { Config.setMapColumnName(Config.NO_NAME); ret = false; }
if (logCommandedAfrColIdx == -1) {
if (isPolfTableSet) {
if (!logCommandedAfrColName.equals(Config.NO_NAME)) {
JOptionPane.showMessageDialog(null, "'Commanded AFR' column is specified but was not found in the log file.\nResetting 'Commanded AFR' column to blank", "Invalid column", JOptionPane.WARNING_MESSAGE);
Config.setCommandedAfrColumnName(Config.NO_NAME);
}
}
else {
Config.setCommandedAfrColumnName(Config.NO_NAME);
ret = false;
}
}
wotPoint = Config.getWOTStationaryPointValue();
minMafV = Config.getMafVMinimumValue();
afrErrPrct = Config.getWidebandAfrErrorPercentValue();
minWotEnrichment = Config.getWOTEnrichmentValue();
afrRowOffset = Config.getWBO2RowOffset();
skipRowsOnTransition = Config.getOLCLTransitionSkipRows();
return ret;
}
protected void loadLogFile() {
boolean displayDialog = true;
boolean isPolfSet = polfTable.isSet();
boolean isPolfMap = polfTable.isMap();
File[] files = fileChooser.getSelectedFiles();
for (File file : files) {
BufferedReader br = null;
ArrayDeque<String[]> buffer = new ArrayDeque<String[]>();
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream(file.getAbsoluteFile()), Config.getEncoding()));
String line = null;
String [] elements = null;
while ((line = br.readLine()) != null && (elements = line.split(Utils.fileFieldSplitter, -1)) != null && elements.length < 2)
continue;
getColumnsFilters(elements, isPolfSet, isPolfMap);
boolean resetColumns = false;
if (logThtlAngleColIdx >= 0 || logAfLearningColIdx >= 0 || logAfCorrectionColIdx >= 0 || logMafvColIdx >= 0 ||
logAfrColIdx >= 0 || logRpmColIdx >= 0 || logLoadColIdx >= 0 || logCommandedAfrColIdx >= 0 || logMapColIdx >= 0) {
if (displayDialog) {
int rc = JOptionPane.showOptionDialog(null, "Would you like to reset column names or filter values?", "Columns/Filters Reset", JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, optionButtons, optionButtons[0]);
if (rc == 0)
resetColumns = true;
else if (rc == 2)
displayDialog = false;
}
}
if (resetColumns || logThtlAngleColIdx < 0 || logAfLearningColIdx < 0 || logAfCorrectionColIdx < 0 ||
logMafvColIdx < 0 || logAfrColIdx < 0 || logRpmColIdx < 0 || (logLoadColIdx < 0 && !isPolfMap && isPolfSet) ||
(logMapColIdx < 0 && isPolfMap) || (logCommandedAfrColIdx < 0 && !isPolfSet)) {
ColumnsFiltersSelection selectionWindow = new OLColumnsFiltersSelection(isPolfSet, isPolfMap);
if (!selectionWindow.getUserSettings(elements) || !getColumnsFilters(elements, isPolfSet, isPolfMap))
return;
}
String[] flds;
String[] afrflds;
boolean wotFlag = true;
boolean foundWot = false;
double throttle;
double afr;
double rpm;
double mafv;
double cmdafr = 0;
double afrErr = 0;
double loadOrMap;
int skipRowCount = 0;
int row = 0;
int i = 0;
int j = 0;
for (; i < runTables.size(); ++i) {
if (runTables.get(i).getValueAt(0, 0).toString().isEmpty())
break;
}
if (i == runTables.size())
addRunTable();
JTable table = runTables.get(i);
setCursor(new Cursor(Cursor.WAIT_CURSOR));
for (int k = 0; k <= afrRowOffset && line != null; ++k) {
line = br.readLine();
if (line != null)
buffer.addFirst(line.split(Utils.fileFieldSplitter, -1));
}
while (line != null && buffer.size() > afrRowOffset) {
afrflds = buffer.getFirst();
flds = buffer.removeLast();
line = br.readLine();
if (line != null)
buffer.addFirst(line.split(Utils.fileFieldSplitter, -1));
try {
throttle = Double.valueOf(flds[logThtlAngleColIdx]);
if (row == 0 && throttle < 99)
wotFlag = false;
if (throttle < wotPoint) {
if (wotFlag == true) {
wotFlag = false;
skipRowCount = 0;
j -= 1;
while (j > 0 && skipRowCount < skipRowsOnTransition) {
table.setValueAt("", j, 0);
table.setValueAt("", j, 1);
table.setValueAt("", j, 2);
skipRowCount += 1;
j -= 1;
}
skipRowCount = 0;
}
}
else {
if (wotFlag == false) {
wotFlag = true;
skipRowCount = 0;
if (foundWot &&
!table.getValueAt(0, 0).equals("") &&
!table.getValueAt(1, 0).equals("") &&
!table.getValueAt(2, 0).equals("")) {
i += 1;
if (i == runTables.size())
addRunTable();
table = runTables.get(i);
}
if (row > 0)
j = 0;
}
if (skipRowCount >= skipRowsOnTransition) {
mafv = Double.valueOf(flds[logMafvColIdx]);
if (minMafV <= mafv) {
foundWot = true;
afr = Double.valueOf(afrflds[logAfrColIdx]);
rpm = Double.valueOf(flds[logRpmColIdx]);
afr = afr / ((100.0 - (Double.valueOf(flds[logAfLearningColIdx]) + Double.valueOf(flds[logAfCorrectionColIdx]))) / 100.0);
if (logCommandedAfrColIdx >= 0)
cmdafr = Double.valueOf(flds[logCommandedAfrColIdx]);
else {
loadOrMap = (isPolfMap ? Double.valueOf(flds[logMapColIdx]) : Double.valueOf(flds[logLoadColIdx]));
cmdafr = Utils.calculateCommandedAfr(rpm, loadOrMap, minWotEnrichment, polfTable);
}
afrErr = (afr - cmdafr) / cmdafr * 100.0;
if (Math.abs(afrErr) <= afrErrPrct) {
Utils.ensureRowCount(j + 1, table);
table.setValueAt(rpm, j, 0);
table.setValueAt(mafv, j, 1);
table.setValueAt(afrErr, j, 2);
j += 1;
}
}
}
skipRowCount += 1;
}
}
catch (NumberFormatException e) {
logger.error(e);
JOptionPane.showMessageDialog(null, "Error parsing number at " + file.getName() + " line " + (row + 1) + ": " + e, "Error processing file", JOptionPane.ERROR_MESSAGE);
return;
}
row += 1;
}
if (!foundWot) {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
JOptionPane.showMessageDialog(null, "Sorry, no WOT pulls were found in the log file", "No WOT data", JOptionPane.INFORMATION_MESSAGE);
}
}
catch (Exception e) {
logger.error(e);
JOptionPane.showMessageDialog(null, e, "Error opening file", JOptionPane.ERROR_MESSAGE);
}
finally {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
if (br != null) {
try {
br.close();
}
catch (IOException e) {
logger.error(e);
}
}
}
}
}
protected String usage() {
ResourceBundle bundle;
bundle = ResourceBundle.getBundle("com.vgi.mafscaling.openloop");
return bundle.getString("usage");
}
}