package net.sf.openrocket.simulation.listeners.example;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.Iterator;
import net.sf.openrocket.rocketcomponent.FinSet;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.simulation.FlightDataType;
import net.sf.openrocket.simulation.FlightEvent;
import net.sf.openrocket.simulation.SimulationStatus;
import net.sf.openrocket.simulation.exception.SimulationException;
import net.sf.openrocket.simulation.listeners.AbstractSimulationListener;
public class CSVSaveListener extends AbstractSimulationListener {
private static enum Types {
TIME {
@Override
public double getValue(SimulationStatus status) {
return status.getSimulationTime();
}
},
POSITION_X {
@Override
public double getValue(SimulationStatus status) {
return status.getRocketPosition().x;
}
},
POSITION_Y {
@Override
public double getValue(SimulationStatus status) {
return status.getRocketPosition().y;
}
},
ALTITUDE {
@Override
public double getValue(SimulationStatus status) {
return status.getRocketPosition().z;
}
},
VELOCITY_X {
@Override
public double getValue(SimulationStatus status) {
return status.getRocketVelocity().x;
}
},
VELOCITY_Y {
@Override
public double getValue(SimulationStatus status) {
return status.getRocketVelocity().y;
}
},
VELOCITY_Z {
@Override
public double getValue(SimulationStatus status) {
return status.getRocketVelocity().z;
}
},
THETA {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_ORIENTATION_THETA);
}
},
PHI {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_ORIENTATION_PHI);
}
},
AOA {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_AOA);
}
},
ROLLRATE {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_ROLL_RATE);
}
},
PITCHRATE {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_PITCH_RATE);
}
},
PITCHMOMENT {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_PITCH_MOMENT_COEFF);
}
},
YAWMOMENT {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_YAW_MOMENT_COEFF);
}
},
ROLLMOMENT {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_ROLL_MOMENT_COEFF);
}
},
NORMALFORCE {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_NORMAL_FORCE_COEFF);
}
},
SIDEFORCE {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_SIDE_FORCE_COEFF);
}
},
AXIALFORCE {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_DRAG_FORCE);
}
},
WINDSPEED {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_WIND_VELOCITY);
}
},
PITCHDAMPING {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_PITCH_DAMPING_MOMENT_COEFF);
}
},
CA {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_AXIAL_DRAG_COEFF);
}
},
CD {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_DRAG_COEFF);
}
},
CDpressure {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_PRESSURE_DRAG_COEFF);
}
},
CDfriction {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_FRICTION_DRAG_COEFF);
}
},
CDbase {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_BASE_DRAG_COEFF);
}
},
MACH {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_MACH_NUMBER);
}
},
RE {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_REYNOLDS_NUMBER);
}
},
CONTROL_ANGLE {
@Override
public double getValue(SimulationStatus status) {
Iterator<RocketComponent> iterator =
status.getConfiguration().getRocket().iterator();
FinSet fin = null;
while (iterator.hasNext()) {
RocketComponent c = iterator.next();
if (c instanceof FinSet && c.getName().equals("CONTROL")) {
fin = (FinSet) c;
break;
}
}
if (fin == null)
return 0;
return fin.getCantAngle();
}
},
MASS {
@Override
public double getValue(SimulationStatus status) {
return status.getFlightData().getLast(FlightDataType.TYPE_MASS);
}
}
;
public abstract double getValue(SimulationStatus status);
}
public static final String FILENAME_FORMAT = "simulation-%03d.csv";
private File file;
private PrintStream output = null;
@Override
public boolean handleFlightEvent(SimulationStatus status, FlightEvent event) throws SimulationException {
if (event.getType() == FlightEvent.Type.LAUNCH) {
int n = 1;
if (output != null) {
System.err.println("WARNING: Ending simulation logging to CSV file " +
"(SIMULATION_END not encountered).");
output.close();
output = null;
}
do {
file = new File(String.format(FILENAME_FORMAT, n));
n++;
} while (file.exists());
System.err.println("Opening file " + file + " for CSV output.");
try {
output = new PrintStream(file);
} catch (FileNotFoundException e) {
System.err.println("ERROR OPENING FILE: " + e);
}
final Types[] types = Types.values();
StringBuilder s = new StringBuilder("# " + types[0].toString());
for (int i = 1; i < types.length; i++) {
s.append("," + types[i].toString());
}
output.println(s);
} else if (event.getType() == FlightEvent.Type.SIMULATION_END && output != null) {
System.err.println("Ending simulation logging to CSV file: " + file);
output.close();
output = null;
} else if (event.getType() != FlightEvent.Type.ALTITUDE) {
if (output != null) {
output.println("# Event " + event);
} else {
System.err.println("WARNING: Event " + event + " encountered without open file");
}
}
return true;
}
@Override
public void postStep(SimulationStatus status) throws SimulationException {
final Types[] types = Types.values();
StringBuilder s;
if (output != null) {
s = new StringBuilder("" + types[0].getValue(status));
for (int i = 1; i < types.length; i++) {
s.append("," + types[i].getValue(status));
}
output.println(s);
} else {
System.err.println("WARNING: stepTaken called with no open file " +
"(t=" + status.getSimulationTime() + ")");
}
}
}