Merge pull request #2236 from SiboVG/issue-2225
[#2225] Copy simulation data from sustainer to other stages for CSV exporting
This commit is contained in:
commit
d2bb552807
@ -92,9 +92,11 @@ public class CSVExport {
|
|||||||
private static void writeData(PrintWriter writer, FlightDataBranch branch,
|
private static void writeData(PrintWriter writer, FlightDataBranch branch,
|
||||||
FlightDataType[] fields, Unit[] units, String fieldSeparator, int decimalPlaces, boolean isExponentialNotation,
|
FlightDataType[] fields, Unit[] units, String fieldSeparator, int decimalPlaces, boolean isExponentialNotation,
|
||||||
boolean eventComments, String commentStarter) {
|
boolean eventComments, String commentStarter) {
|
||||||
|
// Time variable
|
||||||
|
List<Double> time = branch.get(FlightDataType.TYPE_TIME);
|
||||||
|
|
||||||
// Number of data points
|
// Number of data points
|
||||||
int n = branch.getLength();
|
int n = time != null ? time.size() : branch.getLength();
|
||||||
|
|
||||||
// Flight events in occurrence order
|
// Flight events in occurrence order
|
||||||
List<FlightEvent> events = branch.getEvents();
|
List<FlightEvent> events = branch.getEvents();
|
||||||
@ -102,15 +104,14 @@ public class CSVExport {
|
|||||||
int eventPosition = 0;
|
int eventPosition = 0;
|
||||||
|
|
||||||
// List of field values
|
// List of field values
|
||||||
List<List<Double>> fieldValues = new ArrayList<List<Double>>();
|
List<List<Double>> fieldValues = new ArrayList<>();
|
||||||
for (FlightDataType t : fields) {
|
for (FlightDataType t : fields) {
|
||||||
fieldValues.add(branch.get(t));
|
List<Double> values = branch.get(t);
|
||||||
|
fieldValues.add(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time variable
|
// If time information is not available, print events at beginning of file
|
||||||
List<Double> time = branch.get(FlightDataType.TYPE_TIME);
|
|
||||||
if (eventComments && time == null) {
|
if (eventComments && time == null) {
|
||||||
// If time information is not available, print events at beginning of file
|
|
||||||
for (FlightEvent e : events) {
|
for (FlightEvent e : events) {
|
||||||
printEvent(writer, e, commentStarter);
|
printEvent(writer, e, commentStarter);
|
||||||
}
|
}
|
||||||
|
@ -216,21 +216,22 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
/*
|
/*
|
||||||
* NOTE: Remember to update the supported versions in DocumentConfig as well!
|
* NOTE: Remember to update the supported versions in DocumentConfig as well!
|
||||||
*
|
*
|
||||||
* File version 1.8 is required for:
|
* File version 1.9 is required for:
|
||||||
* - new-style positioning
|
* - new-style positioning
|
||||||
* - external/parallel booster stages
|
* - external/parallel booster stages
|
||||||
* - external pods
|
* - external pods
|
||||||
* - Rail Buttons
|
* - Rail Buttons
|
||||||
|
* - Flight event source saving
|
||||||
*
|
*
|
||||||
* Otherwise use version 1.8.
|
* Otherwise use version 1.9.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/////////////////
|
/////////////////
|
||||||
// Version 1.8 //
|
// Version 1.9 //
|
||||||
/////////////////
|
/////////////////
|
||||||
// for any new-style positioning: 'axialoffset', 'angleoffset', 'radiusoffset' tags
|
// for any new-style positioning: 'axialoffset', 'angleoffset', 'radiusoffset' tags
|
||||||
// these tags are used for any RocketComponent child classes positioning... so... ALL the classes.
|
// these tags are used for any RocketComponent child classes positioning... so... ALL the classes.
|
||||||
return FILE_VERSION_DIVISOR + 8;
|
return FILE_VERSION_DIVISOR + 9;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,8 +532,13 @@ public class OpenRocketSaver extends RocketSaver {
|
|||||||
|
|
||||||
// Write events
|
// Write events
|
||||||
for (FlightEvent event : branch.getEvents()) {
|
for (FlightEvent event : branch.getEvents()) {
|
||||||
writeln("<event time=\"" + TextUtil.doubleToString(event.getTime())
|
String eventStr = "<event time=\"" + TextUtil.doubleToString(event.getTime())
|
||||||
+ "\" type=\"" + enumToXMLName(event.getType()) + "\"/>");
|
+ "\" type=\"" + enumToXMLName(event.getType());
|
||||||
|
if (event.getSource() != null) {
|
||||||
|
eventStr += "\" source=\"" + TextUtil.escapeXML(event.getSource().getID());
|
||||||
|
}
|
||||||
|
eventStr += "\"/>";
|
||||||
|
writeln(eventStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the data
|
// Write the data
|
||||||
|
@ -52,7 +52,7 @@ import net.sf.openrocket.util.Reflection;
|
|||||||
class DocumentConfig {
|
class DocumentConfig {
|
||||||
|
|
||||||
/* Remember to update OpenRocketSaver as well! */
|
/* Remember to update OpenRocketSaver as well! */
|
||||||
public static final String[] SUPPORTED_VERSIONS = { "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8" };
|
public static final String[] SUPPORTED_VERSIONS = { "1.0", "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7", "1.8", "1.9" };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Divisor used in converting an integer version to the point-represented version.
|
* Divisor used in converting an integer version to the point-represented version.
|
||||||
@ -113,6 +113,8 @@ class DocumentConfig {
|
|||||||
// RocketComponent
|
// RocketComponent
|
||||||
setters.put("RocketComponent:name", new StringSetter(
|
setters.put("RocketComponent:name", new StringSetter(
|
||||||
Reflection.findMethod(RocketComponent.class, "setName", String.class)));
|
Reflection.findMethod(RocketComponent.class, "setName", String.class)));
|
||||||
|
setters.put("RocketComponent:id", new StringSetter(
|
||||||
|
Reflection.findMethod(RocketComponent.class, "setID", String.class)));
|
||||||
setters.put("RocketComponent:color", new ColorSetter(
|
setters.put("RocketComponent:color", new ColorSetter(
|
||||||
Reflection.findMethod(RocketComponent.class, "setColor", Color.class)));
|
Reflection.findMethod(RocketComponent.class, "setColor", Color.class)));
|
||||||
setters.put("RocketComponent:linestyle", new EnumSetter<LineStyle>(
|
setters.put("RocketComponent:linestyle", new EnumSetter<LineStyle>(
|
||||||
|
@ -8,6 +8,8 @@ import net.sf.openrocket.file.simplesax.AbstractElementHandler;
|
|||||||
import net.sf.openrocket.file.simplesax.ElementHandler;
|
import net.sf.openrocket.file.simplesax.ElementHandler;
|
||||||
import net.sf.openrocket.file.simplesax.PlainTextHandler;
|
import net.sf.openrocket.file.simplesax.PlainTextHandler;
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
|
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||||
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.simulation.FlightDataBranch;
|
import net.sf.openrocket.simulation.FlightDataBranch;
|
||||||
import net.sf.openrocket.simulation.FlightDataType;
|
import net.sf.openrocket.simulation.FlightDataType;
|
||||||
import net.sf.openrocket.simulation.FlightEvent;
|
import net.sf.openrocket.simulation.FlightEvent;
|
||||||
@ -126,6 +128,8 @@ class FlightDataBranchHandler extends AbstractElementHandler {
|
|||||||
if (element.equals("event")) {
|
if (element.equals("event")) {
|
||||||
double time;
|
double time;
|
||||||
FlightEvent.Type type;
|
FlightEvent.Type type;
|
||||||
|
String sourceID;
|
||||||
|
RocketComponent source = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
time = DocumentConfig.stringToDouble(attributes.get("time"));
|
time = DocumentConfig.stringToDouble(attributes.get("time"));
|
||||||
@ -139,8 +143,15 @@ class FlightDataBranchHandler extends AbstractElementHandler {
|
|||||||
warnings.add("Illegal event specification, ignoring.");
|
warnings.add("Illegal event specification, ignoring.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the event source
|
||||||
|
Rocket rocket = context.getOpenRocketDocument().getRocket();
|
||||||
|
sourceID = attributes.get("source");
|
||||||
|
if (sourceID != null) {
|
||||||
|
source = rocket.findComponent(sourceID);
|
||||||
|
}
|
||||||
|
|
||||||
branch.addEvent(new FlightEvent(type, time));
|
branch.addEvent(new FlightEvent(type, time, source));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ public class RocketComponentSaver {
|
|||||||
|
|
||||||
protected void addParams(net.sf.openrocket.rocketcomponent.RocketComponent c, List<String> elements) {
|
protected void addParams(net.sf.openrocket.rocketcomponent.RocketComponent c, List<String> elements) {
|
||||||
elements.add("<name>" + TextUtil.escapeXML(c.getName()) + "</name>");
|
elements.add("<name>" + TextUtil.escapeXML(c.getName()) + "</name>");
|
||||||
|
elements.add("<id>" + TextUtil.escapeXML(c.getID()) + "</id>");
|
||||||
|
|
||||||
ComponentPreset preset = c.getPresetComponent();
|
ComponentPreset preset = c.getPresetComponent();
|
||||||
if (preset != null) {
|
if (preset != null) {
|
||||||
|
@ -1282,8 +1282,16 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
mutex.verify();
|
mutex.verify();
|
||||||
this.id = UniqueID.uuid();
|
this.id = UniqueID.uuid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the ID for this component.
|
||||||
|
* Generally not recommended to directly set the ID, this is done automatically. Only use this in case you have to.
|
||||||
|
* @param newID new ID
|
||||||
|
*/
|
||||||
|
public void setID(String newID) {
|
||||||
|
mutex.verify();
|
||||||
|
this.id = newID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2047,6 +2055,16 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
}
|
}
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this component contains <component> as one of its (sub-)children.
|
||||||
|
* @param component component to check
|
||||||
|
* @return true if component is a (sub-)child of this component
|
||||||
|
*/
|
||||||
|
public final boolean containsChild(RocketComponent component) {
|
||||||
|
List<RocketComponent> allChildren = getAllChildren();
|
||||||
|
return allChildren.contains(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -489,7 +489,7 @@ public class BasicEventSimulationEngine implements SimulationEngine {
|
|||||||
SimulationStatus boosterStatus = new SimulationStatus(currentStatus);
|
SimulationStatus boosterStatus = new SimulationStatus(currentStatus);
|
||||||
|
|
||||||
// Prepare the new simulation branch
|
// Prepare the new simulation branch
|
||||||
boosterStatus.setFlightData(new FlightDataBranch(boosterStage.getName(), currentStatus.getFlightData()));
|
boosterStatus.setFlightData(new FlightDataBranch(boosterStage.getName(), boosterStage, currentStatus.getFlightData()));
|
||||||
boosterStatus.getFlightData().addEvent(event);
|
boosterStatus.getFlightData().addEvent(event);
|
||||||
|
|
||||||
// Mark the current status as having dropped the current stage and all stages below it
|
// Mark the current status as having dropped the current stage and all stages below it
|
||||||
|
@ -134,8 +134,12 @@ public class FlightData {
|
|||||||
return branches.size();
|
return branches.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public FlightDataBranch getBranch(int n) {
|
public FlightDataBranch getBranch(int stageNr) {
|
||||||
return branches.get(n);
|
return branches.get(stageNr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStageNr(FlightDataBranch branch) {
|
||||||
|
return branches.indexOf(branch);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FlightDataBranch> getBranches() {
|
public List<FlightDataBranch> getBranches() {
|
||||||
|
@ -6,6 +6,9 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.sf.openrocket.rocketcomponent.AxialStage;
|
||||||
|
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||||
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.util.ArrayList;
|
import net.sf.openrocket.util.ArrayList;
|
||||||
import net.sf.openrocket.util.Monitorable;
|
import net.sf.openrocket.util.Monitorable;
|
||||||
import net.sf.openrocket.util.Mutable;
|
import net.sf.openrocket.util.Mutable;
|
||||||
@ -30,11 +33,10 @@ public class FlightDataBranch implements Monitorable {
|
|||||||
/** The name of this flight data branch. */
|
/** The name of this flight data branch. */
|
||||||
private final String branchName;
|
private final String branchName;
|
||||||
|
|
||||||
private final Map<FlightDataType, ArrayList<Double>> values =
|
private final Map<FlightDataType, ArrayList<Double>> values = new LinkedHashMap<>();
|
||||||
new LinkedHashMap<FlightDataType, ArrayList<Double>>();
|
|
||||||
|
|
||||||
private final Map<FlightDataType, Double> maxValues = new HashMap<FlightDataType, Double>();
|
private final Map<FlightDataType, Double> maxValues = new HashMap<>();
|
||||||
private final Map<FlightDataType, Double> minValues = new HashMap<FlightDataType, Double>();
|
private final Map<FlightDataType, Double> minValues = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* time for the rocket to reach apogee if the flight had been no recovery deployment
|
* time for the rocket to reach apogee if the flight had been no recovery deployment
|
||||||
@ -77,23 +79,19 @@ public class FlightDataBranch implements Monitorable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a flight data branch with one data point copied from its parent. Intended for use
|
* Make a flight data branch with all data points copied from its parent. Intended for use
|
||||||
* when creating a new branch upon stage separation, so the data at separation is present
|
* when creating a new branch upon stage separation, so the data at separation is present
|
||||||
* in both branches (and if the new branch has an immediate exception, it can be plotted)
|
* in both branches (and if the new branch has an immediate exception, it can be plotted)
|
||||||
|
*
|
||||||
|
* @param branchName the name of the new branch.
|
||||||
|
* @param srcComponent the component that is the source of the new branch.
|
||||||
|
* @param parent the parent branch to copy data from.
|
||||||
*/
|
*/
|
||||||
public FlightDataBranch(String branchName, FlightDataBranch parent) {
|
public FlightDataBranch(String branchName, RocketComponent srcComponent, FlightDataBranch parent) {
|
||||||
this.branchName = branchName;
|
this.branchName = branchName;
|
||||||
|
|
||||||
// need to have at least one type to set up values
|
// Copy all the values from the parent
|
||||||
values.put(FlightDataType.TYPE_TIME, new ArrayList<Double>());
|
copyValuesFromBranch(parent, srcComponent);
|
||||||
minValues.put(FlightDataType.TYPE_TIME, Double.NaN);
|
|
||||||
maxValues.put(FlightDataType.TYPE_TIME, Double.NaN);
|
|
||||||
|
|
||||||
// copy all values into new FlightDataBranch
|
|
||||||
this.addPoint();
|
|
||||||
for (FlightDataType t : parent.getTypes()) {
|
|
||||||
this.setValue(t, parent.getLast(t));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -115,12 +113,27 @@ public class FlightDataBranch implements Monitorable {
|
|||||||
public void addPoint() {
|
public void addPoint() {
|
||||||
mutable.check();
|
mutable.check();
|
||||||
|
|
||||||
for (FlightDataType t : values.keySet()) {
|
for (FlightDataType type : values.keySet()) {
|
||||||
values.get(t).add(Double.NaN);
|
sanityCheckValues(type, Double.NaN);
|
||||||
|
values.get(type).add(Double.NaN);
|
||||||
}
|
}
|
||||||
modID++;
|
modID++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sanityCheckValues(FlightDataType type, Double value) {
|
||||||
|
ArrayList<Double> list = values.get(type);
|
||||||
|
|
||||||
|
if (list == null) {
|
||||||
|
list = new ArrayList<>();
|
||||||
|
int n = getLength();
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
list.add(Double.NaN);
|
||||||
|
}
|
||||||
|
values.put(type, list);
|
||||||
|
minValues.put(type, value);
|
||||||
|
maxValues.put(type, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the value for a specific data type at the latest point. New variable types can be
|
* Set the value for a specific data type at the latest point. New variable types can be
|
||||||
@ -132,20 +145,10 @@ public class FlightDataBranch implements Monitorable {
|
|||||||
*/
|
*/
|
||||||
public void setValue(FlightDataType type, double value) {
|
public void setValue(FlightDataType type, double value) {
|
||||||
mutable.check();
|
mutable.check();
|
||||||
|
|
||||||
|
sanityCheckValues(type, value);
|
||||||
ArrayList<Double> list = values.get(type);
|
ArrayList<Double> list = values.get(type);
|
||||||
|
|
||||||
if (list == null) {
|
|
||||||
list = new ArrayList<Double>();
|
|
||||||
int n = getLength();
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
list.add(Double.NaN);
|
|
||||||
}
|
|
||||||
values.put(type, list);
|
|
||||||
minValues.put(type, value);
|
|
||||||
maxValues.put(type, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (list.size() > 0) {
|
if (list.size() > 0) {
|
||||||
list.set(list.size() - 1, value);
|
list.set(list.size() - 1, value);
|
||||||
}
|
}
|
||||||
@ -161,7 +164,68 @@ public class FlightDataBranch implements Monitorable {
|
|||||||
}
|
}
|
||||||
modID++;
|
modID++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears all the current values in the branch and copies the values from the given branch.
|
||||||
|
* @param srcBranch the branch to copy values from
|
||||||
|
* @param srcComponent the component that is the source of this branch (used for copying events)
|
||||||
|
*/
|
||||||
|
private void copyValuesFromBranch(FlightDataBranch srcBranch, RocketComponent srcComponent) {
|
||||||
|
this.values.clear();
|
||||||
|
|
||||||
|
// Need to have at least one type to set up values
|
||||||
|
values.put(FlightDataType.TYPE_TIME, new ArrayList<>());
|
||||||
|
minValues.put(FlightDataType.TYPE_TIME, Double.NaN);
|
||||||
|
maxValues.put(FlightDataType.TYPE_TIME, Double.NaN);
|
||||||
|
|
||||||
|
if (srcBranch == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy flight data
|
||||||
|
for (int i = 0; i < srcBranch.getLength(); i++) {
|
||||||
|
this.addPoint();
|
||||||
|
for (FlightDataType type : srcBranch.getTypes()) {
|
||||||
|
this.setValue(type, srcBranch.getByIndex(type, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy flight events belonging to this branch
|
||||||
|
List<FlightEvent> sustainerEvents = srcBranch.getEvents();
|
||||||
|
for (FlightEvent event : sustainerEvents) {
|
||||||
|
// Stage separation is already added elsewhere, so don't copy it over (otherwise you have a duplicate)
|
||||||
|
if (event.getType() == FlightEvent.Type.STAGE_SEPARATION) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
RocketComponent srcEventComponent = event.getSource();
|
||||||
|
// Ignore null events
|
||||||
|
if (srcComponent == null || srcEventComponent == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Ignore events from other stages. Important for when the current stage has a booster stage; we don't want to copy over the booster events.
|
||||||
|
if (getStageForComponent(srcComponent) != getStageForComponent(srcEventComponent)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (srcComponent == srcEventComponent || srcComponent.containsChild(srcEventComponent)) {
|
||||||
|
events.add(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A safer method for checking the stage of a component (that shouldn't throw exceptions when calling on stages/rockets)
|
||||||
|
* @param component the component to get the stage of
|
||||||
|
* @return the stage of the component, or null if the component is a rocket
|
||||||
|
*/
|
||||||
|
private AxialStage getStageForComponent(RocketComponent component) {
|
||||||
|
if (component instanceof AxialStage) {
|
||||||
|
return (AxialStage) component;
|
||||||
|
} else if (component instanceof Rocket) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return component.getStage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the branch name.
|
* Return the branch name.
|
||||||
@ -203,6 +267,23 @@ public class FlightDataBranch implements Monitorable {
|
|||||||
return null;
|
return null;
|
||||||
return list.clone();
|
return list.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the value of the specified type at the specified index.
|
||||||
|
* @param type the variable type
|
||||||
|
* @param index the data index of the value
|
||||||
|
* @return the value at the specified index
|
||||||
|
*/
|
||||||
|
public Double getByIndex(FlightDataType type, int index) {
|
||||||
|
if (index < 0 || index >= getLength()) {
|
||||||
|
throw new IllegalArgumentException("Index out of bounds");
|
||||||
|
}
|
||||||
|
ArrayList<Double> list = values.get(type);
|
||||||
|
if (list == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return list.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the last value of the specified type in the branch, or NaN if the type is
|
* Return the last value of the specified type in the branch, or NaN if the type is
|
||||||
|
@ -331,9 +331,9 @@ public class OpenRocketSaverTest {
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFileVersion108_withSimulationExtension() {
|
public void testFileVersion109_withSimulationExtension() {
|
||||||
OpenRocketDocument rocketDoc = TestRockets.makeTestRocket_v107_withSimulationExtension(SIMULATION_EXTENSION_SCRIPT);
|
OpenRocketDocument rocketDoc = TestRockets.makeTestRocket_v107_withSimulationExtension(SIMULATION_EXTENSION_SCRIPT);
|
||||||
assertEquals(108, getCalculatedFileVersion(rocketDoc));
|
assertEquals(109, getCalculatedFileVersion(rocketDoc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,8 +108,8 @@ public class FlightEventsTest extends BaseTestCase {
|
|||||||
// events whose time is too variable to check are given a time of 1200
|
// events whose time is too variable to check are given a time of 1200
|
||||||
for (int b = 0; b < 3; b++) {
|
for (int b = 0; b < 3; b++) {
|
||||||
FlightEvent[] expectedEvents;
|
FlightEvent[] expectedEvents;
|
||||||
final RocketComponent[] expectedSources;
|
|
||||||
switch (b) {
|
switch (b) {
|
||||||
|
// Sustainer (payload fairing stage)
|
||||||
case 0:
|
case 0:
|
||||||
expectedEvents = new FlightEvent[] {
|
expectedEvents = new FlightEvent[] {
|
||||||
new FlightEvent(FlightEvent.Type.LAUNCH, 0.0, rocket),
|
new FlightEvent(FlightEvent.Type.LAUNCH, 0.0, rocket),
|
||||||
@ -129,15 +129,23 @@ public class FlightEventsTest extends BaseTestCase {
|
|||||||
new FlightEvent(FlightEvent.Type.SIMULATION_END, 1200, null)
|
new FlightEvent(FlightEvent.Type.SIMULATION_END, 1200, null)
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
// Core stage
|
||||||
case 1:
|
case 1:
|
||||||
expectedEvents = new FlightEvent[] {
|
expectedEvents = new FlightEvent[] {
|
||||||
|
new FlightEvent(FlightEvent.Type.IGNITION, 0.0, coreBody),
|
||||||
|
new FlightEvent(FlightEvent.Type.BURNOUT, 2.0, coreBody),
|
||||||
|
new FlightEvent(FlightEvent.Type.EJECTION_CHARGE, 2.0, coreStage),
|
||||||
new FlightEvent(FlightEvent.Type.STAGE_SEPARATION, 2.0, coreStage),
|
new FlightEvent(FlightEvent.Type.STAGE_SEPARATION, 2.0, coreStage),
|
||||||
new FlightEvent(FlightEvent.Type.GROUND_HIT, 1200, null),
|
new FlightEvent(FlightEvent.Type.GROUND_HIT, 1200, null),
|
||||||
new FlightEvent(FlightEvent.Type.SIMULATION_END, 1200, null)
|
new FlightEvent(FlightEvent.Type.SIMULATION_END, 1200, null)
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
// Booster stage
|
||||||
case 2:
|
case 2:
|
||||||
expectedEvents = new FlightEvent[] {
|
expectedEvents = new FlightEvent[] {
|
||||||
|
new FlightEvent(FlightEvent.Type.IGNITION, 0.0, boosterMotorTubes),
|
||||||
|
new FlightEvent(FlightEvent.Type.BURNOUT, 2.0, boosterMotorTubes),
|
||||||
|
new FlightEvent(FlightEvent.Type.EJECTION_CHARGE, 2.0, boosterStage),
|
||||||
new FlightEvent(FlightEvent.Type.STAGE_SEPARATION, 2.0, boosterStage),
|
new FlightEvent(FlightEvent.Type.STAGE_SEPARATION, 2.0, boosterStage),
|
||||||
new FlightEvent(FlightEvent.Type.TUMBLE, 3.551, null),
|
new FlightEvent(FlightEvent.Type.TUMBLE, 3.551, null),
|
||||||
new FlightEvent(FlightEvent.Type.GROUND_HIT, 1200, null),
|
new FlightEvent(FlightEvent.Type.GROUND_HIT, 1200, null),
|
||||||
@ -150,10 +158,7 @@ public class FlightEventsTest extends BaseTestCase {
|
|||||||
|
|
||||||
// Test event count
|
// Test event count
|
||||||
final FlightDataBranch branch = sim.getSimulatedData().getBranch(b);
|
final FlightDataBranch branch = sim.getSimulatedData().getBranch(b);
|
||||||
final FlightEvent[] events = (FlightEvent[]) branch.getEvents().toArray(new FlightEvent[0]);
|
final FlightEvent[] events = branch.getEvents().toArray(new FlightEvent[0]);
|
||||||
for (int i = 0; i < events.length; i++) {
|
|
||||||
System.out.println("branch " + b + " index " + i + " event " + events[i]);
|
|
||||||
}
|
|
||||||
assertEquals(" Multi-stage simulation, branch " + b + " invalid number of events ", expectedEvents.length, events.length);
|
assertEquals(" Multi-stage simulation, branch " + b + " invalid number of events ", expectedEvents.length, events.length);
|
||||||
|
|
||||||
// Test that all expected events are present, in the right order, at the right time, from the right sources
|
// Test that all expected events are present, in the right order, at the right time, from the right sources
|
||||||
|
@ -63,3 +63,6 @@ The following file format versions exist:
|
|||||||
Rename <fincount> to <instancecount> (<fincount> remains for backward compatibility)
|
Rename <fincount> to <instancecount> (<fincount> remains for backward compatibility)
|
||||||
Rename <position> to <axialoffset> (<position> remains for backward compatibility)
|
Rename <position> to <axialoffset> (<position> remains for backward compatibility)
|
||||||
Rename <rotation> to <angleoffset> (<rotation> remains for backward compatibility)
|
Rename <rotation> to <angleoffset> (<rotation> remains for backward compatibility)
|
||||||
|
|
||||||
|
1.9: Introduced with OpenRocket 23.xx.
|
||||||
|
Added ID for each rocket component, to in turn add this ID as a source for flight events.
|
@ -192,9 +192,8 @@ public class SimulationPlot {
|
|||||||
}
|
}
|
||||||
data[axis].addSeries(series);
|
data[axis].addSeries(series);
|
||||||
}
|
}
|
||||||
// For each of the secondary branches, we use data from branch 0 for the earlier times
|
// Secondary branches
|
||||||
for (int branchIndex = 1; branchIndex < branchCount; branchIndex++) {
|
for (int branchIndex = 1; branchIndex < branchCount; branchIndex++) {
|
||||||
FlightDataBranch primaryBranch = simulation.getSimulatedData().getBranch(0);
|
|
||||||
FlightDataBranch thisBranch = simulation.getSimulatedData().getBranch(branchIndex);
|
FlightDataBranch thisBranch = simulation.getSimulatedData().getBranch(branchIndex);
|
||||||
|
|
||||||
// Ignore empty branches
|
// Ignore empty branches
|
||||||
@ -206,25 +205,10 @@ public class SimulationPlot {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get first time index used in secondary branch;
|
|
||||||
double firstSampleTime = thisBranch.get(FlightDataType.TYPE_TIME).get(0);
|
|
||||||
|
|
||||||
XYSeries series = new XYSeries(seriesCount++, false, true);
|
XYSeries series = new XYSeries(seriesCount++, false, true);
|
||||||
series.setDescription(thisBranch.getBranchName() + ": " + name);
|
series.setDescription(thisBranch.getBranchName() + ": " + name);
|
||||||
|
|
||||||
// Copy the first points from the primaryBranch.
|
// Copy all the data from the secondary branch
|
||||||
List<Double> primaryT = primaryBranch.get(FlightDataType.TYPE_TIME);
|
|
||||||
List<Double> primaryx = primaryBranch.get(domainType);
|
|
||||||
List<Double> primaryy = primaryBranch.get(type);
|
|
||||||
|
|
||||||
for (int j = 0; j < primaryT.size(); j++) {
|
|
||||||
if (primaryT.get(j) >= firstSampleTime) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
series.add(domainUnit.toUnit(primaryx.get(j)), unit.toUnit(primaryy.get(j)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now copy all the data from the secondary branch
|
|
||||||
List<Double> plotx = thisBranch.get(domainType);
|
List<Double> plotx = thisBranch.get(domainType);
|
||||||
List<Double> ploty = thisBranch.get(type);
|
List<Double> ploty = thisBranch.get(type);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user