This commit is contained in:
thzero 2023-05-06 11:31:24 -05:00
parent 0bd3b1630e
commit 8aac8594d3
29 changed files with 2 additions and 4080 deletions

View File

@ -13,7 +13,7 @@ public abstract class Error extends Message {
* @return an Error with the specific text.
*/
public static Error fromString(String text) {
return new Error.Other(text);
return new Other(text);
}

View File

@ -18,7 +18,7 @@ public abstract class Warning extends Message {
* @return a Warning with the specific text.
*/
public static Warning fromString(String text) {
return new Warning.Other(text);
return new Other(text);
}

View File

@ -1,19 +0,0 @@
package net.sf.openrocket.file.rasaero;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class CustomBooleanAdapter extends XmlAdapter<String, Boolean> {
@Override
public Boolean unmarshal(String s) throws Exception {
return "true".equalsIgnoreCase(s);
}
@Override
public String marshal(Boolean b) throws Exception {
if (b) {
return "True";
}
return "False";
}
}

View File

@ -1,22 +0,0 @@
package net.sf.openrocket.file.rasaero;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
public class CustomDoubleAdapter extends XmlAdapter<String, Double> {
@Override
public Double unmarshal(String s) throws Exception {
return Double.parseDouble(s);
}
@Override
public String marshal(Double aDouble) throws Exception {
if (aDouble == null) {
return null;
}
DecimalFormat df = new DecimalFormat("#.####", new DecimalFormatSymbols(Locale.US)); // RASAero has 4 decimal precision
return df.format(aDouble);
}
}

View File

@ -1,517 +0,0 @@
package net.sf.openrocket.file.rasaero;
import net.sf.openrocket.file.motor.AbstractMotorLoader;
import net.sf.openrocket.logging.WarningSet;
import net.sf.openrocket.motor.Manufacturer;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.motor.ThrustCurveMotor;
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
import net.sf.openrocket.rocketcomponent.ExternalComponent;
import net.sf.openrocket.rocketcomponent.FinSet;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.util.Color;
import net.sf.openrocket.util.MathUtil;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* List of constants used in RASAero files + helper functions to read parameters from it.
*
* @author Sibo Van Gool <sibo.vangool@hotmail.com>
*/
public class RASAeroCommonConstants {
// File settings
public static final String FILE_EXTENSION = "CDX1";
// General settings
public static final String RASAERO_DOCUMENT = "RASAeroDocument";
public static final String FILE_VERSION = "FileVersion";
public static final String ROCKET_DESIGN = "RocketDesign";
// RASAeroDocument settings
public static final String MACH_ALT = "MachAlt";
// Base part settings
public static final String PART_TYPE = "PartType";
public static final String LENGTH = "Length";
public static final String DIAMETER = "Diameter";
public static final String LOCATION = "Location";
public static final String COLOR = "Color";
public static final String SURFACE_FINISH = "Surface";
public static final String COMMENTS = "Comments";
// Components
public static final String NOSE_CONE = "NoseCone";
public static final String BODY_TUBE = "BodyTube";
public static final String TRANSITION = "Transition";
public static final String FIN = "Fin";
public static final String BOOSTER = "Booster";
public static final String FIN_CAN = "FinCan";
public static final String BOATTAIL = "BoatTail";
// Body tube settings
public static final String OVERHANG = "Overhang";
// Nose cone settings
public static final String SHAPE = "Shape";
public static final String POWER_LAW = "PowerLaw";
public static final String BLUNT_RADIUS = "BluntRadius";
private static final Map<String, Transition.Shape> RASAeroNoseConeShapeMap = new HashMap<>();
//// Nose cone shapes
private static final String SHAPE_CONICAL = "Conical";
private static final String SHAPE_TANGENT_OGIVE = "Tangent Ogive";
private static final String SHAPE_VON_KARMAN_OGIVE = "Von Karman Ogive";
private static final String SHAPE_POWER_LAW = "Power Law";
private static final String SHAPE_LVHAACK = "LV-Haack";
private static final String SHAPE_PARABOLIC = "Parabolic";
private static final String SHAPE_ELLIPTICAL = "Elliptical";
// Transition settings
public static final String REAR_DIAMETER = "RearDiameter";
// Fin settings
public static final String FIN_COUNT = "Count";
public static final String FIN_CHORD = "Chord";
public static final String FIN_SPAN = "Span";
public static final String FIN_SWEEP_DISTANCE = "SweepDistance";
public static final String FIN_TIP_CHORD = "TipChord";
public static final String FIN_THICKNESS = "Thickness";
public static final String FIN_LE_RADIUS = "LERadius";
public static final String FIN_AIRFOIL_SECTION = "AirfoilSection";
public static final String FIN_FX1 = "FX1";
public static final String FIN_FX3 = "FX3";
public static final String AIRFOIL_SECTION = "AirfoilSection";
//// LERadius, FX1 and FX3 not used
public static final String CROSS_SECTION_SQUARE = "Square";
public static final String CROSS_SECTION_ROUNDED = "Rounded";
public static final String CROSS_SECTION_SUBSONIC_NACA = "Subsonic NACA";
// Launch lug settings
public static final String LAUNCH_LUG_DIAMETER = "LaunchLugDiameter";
public static final String LAUNCH_LUG_LENGTH = "LaunchLugLength";
// Rail guide settings
public static final String RAIL_GUIDE_DIAMETER = "RailGuideDiameter";
public static final String RAIL_GUIDE_HEIGHT = "RailGuideHeight";
// Launch shoe settings
public static final String LAUNCH_SHOE_AREA = "LaunchShoeArea";
// Fin can settings
public static final String INSIDE_DIAMETER = "InsideDiameter";
public static final String SHOULDER_LENGTH = "ShoulderLength";
// Surface finishes
public static final String FINISH_SMOOTH = "Smooth (Zero Roughness)";
public static final String FINISH_POLISHED = "Polished";
public static final String FINISH_SHEET_METAL = "Sheet Metal";
public static final String FINISH_SMOOTH_PAINT = "Smooth Paint";
public static final String FINISH_CAMOUFLAGE = "Camouflage Paint";
public static final String FINISH_ROUGH_CAMOUFLAGE = "Rough Camouflage Paint";
public static final String FINISH_GALVANIZED = "Galvanized Metal";
public static final String FINISH_CAST_IRON = "Cast Iron (Very Rough)";
// Booster settings
public static final String BOATTAIL_LENGTH = "BoattailLength";
public static final String BOATTAIL_REAR_DIAMETER = "BoattailRearDiameter";
public static final String BOATTAIL_OFFSET = "BoattailOffset";
public static final String NOZZLE_EXIT_DIAMETER = "NozzleExitDiameter";
// RocketDesign settings
public static final String CD = "CD";
public static final String MODIFIED_BARROWMAN = "ModifiedBarrowman";
public static final String TURBULENCE = "Turbulence";
public static final String SUSTAINER_NOZZLE = "SustainerNozzle";
public static final String BOOSTER1_NOZZLE = "Booster1Nozzle";
public static final String BOOSTER2_NOZZLE = "Booster2Nozzle";
public static final String USE_BOOSTER1 = "UseBooster1";
public static final String USE_BOOSTER2 = "UseBooster2";
// Launch site settings
public static final String LAUNCH_SITE = "LaunchSite";
public static final String LAUNCH_ALTITUDE = "Altitude";
public static final String LAUNCH_PRESSURE = "Pressure";
public static final String LAUNCH_ROD_ANGLE = "RodAngle";
public static final String LAUNCH_ROD_LENGTH = "RodLength";
public static final String LAUNCH_TEMPERATURE = "Temperature";
public static final String LAUNCH_WIND_SPEED = "WindSpeed";
// Recovery settings
public static final String RECOVERY = "Recovery";
public static final String RECOVERY_ALTITUDE = "Altitude";
public static final String RECOVERY_DEVICE_TYPE = "DeviceType";
public static final String RECOVERY_EVENT = "Event";
public static final String RECOVERY_SIZE = "Size";
public static final String RECOVERY_EVENT_TYPE = "EventType";
public static final String RECOVERY_CD = "CD";
// Deployment settings
public static final String DEPLOYMENT_NONE = "None";
public static final String DEPLOYMENT_APOGEE = "Apogee";
public static final String DEPLOYMENT_ALTITUDE = "Altitude";
// Simulation settings
public static final String SIMULATION_LIST = "SimulationList";
public static final String SIMULATION = "Simulation";
public static final String SUSTAINER_ENGINE = "SustainerEngine";
public static final String SUSTAINER_LAUNCH_WT = "SustainerLaunchWt";
public static final String SUSTAINER_NOZZLE_DIAMETER = "SustainerNozzleDiameter";
public static final String SUSTAINER_CG = "SustainerCG";
public static final String SUSTAINER_IGNITION_DELAY = "SustainerIgnitionDelay";
public static final String BOOSTER1_ENGINE = "Booster1Engine";
public static final String BOOSTER1_SEPARATION_DELAY = "Booster1SeparationDelay"; // Delay after booster burnout to separate
public static final String BOOSTER1_IGNITION_DELAY = "Booster1IgnitionDelay";
public static final String BOOSTER1_LAUNCH_WT = "Booster1LaunchWt";
public static final String BOOSTER1_NOZZLE_DIAMETER = "Booster1NozzleDiameter";
public static final String BOOSTER1_CG = "Booster1CG";
public static final String INCLUDE_BOOSTER1 = "IncludeBooster1";
public static final String BOOSTER2_ENGINE = "Booster2Engine";
public static final String BOOSTER2_SEPARATION_DELAY = "Booster2Delay"; // Delay after booster burnout to separate
public static final String BOOSTER2_LAUNCH_WT = "Booster2LaunchWt";
public static final String BOOSTER2_NOZZLE_DIAMETER = "Booster2NozzleDiameter";
public static final String BOOSTER2_CG = "Booster2CG";
public static final String INCLUDE_BOOSTER2 = "IncludeBooster2";
public static final String FLIGHT_TIME = "FlightTime";
public static final String TIME_TO_APOGEE = "TimetoApogee";
public static final String MAX_ALTITUDE = "MaxAltitude";
public static final String MAX_VELOCITY = "MaxVelocity";
public static final String OPTIMUM_WT = "OptimumWt";
public static final String OPTIMUM_MAX_ALT = "OptimumMaxAlt";
/**
* Length conversion from OpenRocket units to RASAero units. RASAero is in inches, OpenRocket in meters.
*/
public static final double OPENROCKET_TO_RASAERO_LENGTH = 39.37;
/**
* Altitude conversion from OpenRocket units to RASAero units. RASAero is in feet, OpenRocket in meters.
*/
public static final double OPENROCKET_TO_RASAERO_ALTITUDE = 3.28084;
/**
* Speed conversion from OpenRocket units to RASAero units. RASAero is in mph, OpenRocket in m/s.
*/
public static final double OPENROCKET_TO_RASAERO_SPEED = 2.23694;
/**
* Pressure conversion from OpenRocket units to RASAero units. RASAero is in in-hg, OpenRocket in Pa.
*/
public static final double OPENROCKET_TO_RASAERO_PRESSURE = 0.000295301;
/**
* Angle conversion from OpenRocket units to RASAero units. RASAero is in degrees, OpenRocket in rad.
*/
public static final double OPENROCKET_TO_RASAERO_ANGLE = 180 / Math.PI;
/**
* Weight conversion from OpenRocket units to RASAero units. RASAero is in pounds (lb), OpenRocket in kilograms (kg).
*/
public static final double OPENROCKET_TO_RASAERO_WEIGHT = 2.20462262;
/**
* Temperature conversion from OpenRocket units to RASAero units. RASAero is in Fahrenheit, OpenRocket in Kelvin.
*/
public static final double RASAERO_TO_OPENROCKET_TEMPERATURE(Double input) {
return (input + 459.67) * 5.0 / 9.0;
}
public static final double OPENROCKET_TO_RASAERO_TEMPERATURE(Double input) {
return input * 9.0 / 5.0 - 459.67;
}
static {
RASAeroNoseConeShapeMap.put(SHAPE_CONICAL, Transition.Shape.CONICAL);
RASAeroNoseConeShapeMap.put(SHAPE_TANGENT_OGIVE, Transition.Shape.OGIVE); // = Ogive with shape parameter = 1
RASAeroNoseConeShapeMap.put(SHAPE_VON_KARMAN_OGIVE, Transition.Shape.HAACK); // = Haack series with shape parameter = 0
RASAeroNoseConeShapeMap.put(SHAPE_POWER_LAW, Transition.Shape.POWER);
RASAeroNoseConeShapeMap.put(SHAPE_LVHAACK, Transition.Shape.HAACK); // = Haack series with shape parameter = 1/3
RASAeroNoseConeShapeMap.put(SHAPE_PARABOLIC, Transition.Shape.POWER); // = Power law with shape parameter = 1/2
RASAeroNoseConeShapeMap.put(SHAPE_ELLIPTICAL, Transition.Shape.ELLIPSOID);
}
private static final Logger log = LoggerFactory.getLogger(RASAeroCommonConstants.class);
/**
* Returns the OpenRocket nose cone shape from the RASAero shape string.
* @param shape The RASAero shape string.
* @return The OpenRocket nose cone shape.
*/
public static Transition.Shape RASAERO_TO_OPENROCKET_SHAPE(String shape) {
return RASAeroNoseConeShapeMap.get(shape);
}
/**
* Returns the OpenRocket nose cone shape from the RASAero shape string.
* @param shape The RASAero shape string.
* @return The OpenRocket nose cone shape object.
*/
public static NoseConeShapeSettings OPENROCKET_TO_RASAERO_SHAPE(Transition.Shape shape, double shapeParameter)
throws RASAeroExportException {
if (shape.equals(Transition.Shape.CONICAL)) {
return new NoseConeShapeSettings(SHAPE_CONICAL);
} else if (shape.equals(Transition.Shape.OGIVE) && MathUtil.equals(shapeParameter, 1)) {
return new NoseConeShapeSettings(SHAPE_TANGENT_OGIVE);
} else if (shape.equals(Transition.Shape.HAACK) && MathUtil.equals(shapeParameter, 0)) {
return new NoseConeShapeSettings(SHAPE_VON_KARMAN_OGIVE);
} else if (shape.equals(Transition.Shape.POWER) && MathUtil.equals(shapeParameter, 0.5, 0.01)) {
return new NoseConeShapeSettings(SHAPE_PARABOLIC);
} else if (shape.equals(Transition.Shape.POWER)) {
return new NoseConeShapeSettings(SHAPE_POWER_LAW, shapeParameter);
} else if (shape.equals(Transition.Shape.HAACK) && MathUtil.equals(shapeParameter, 0.33, 0.01)) {
return new NoseConeShapeSettings(SHAPE_LVHAACK);
} else if (shape.equals(Transition.Shape.ELLIPSOID)) {
return new NoseConeShapeSettings(SHAPE_ELLIPTICAL);
}
// Special cases
else if (shape.equals(Transition.Shape.OGIVE)) {
throw new RASAeroExportException(
String.format("RASAero only supports Ogive nose cones with shape parameter 1, not %.2f", shapeParameter));
} else if (shape.equals(Transition.Shape.HAACK)) {
throw new RASAeroExportException(
String.format("RASAero only supports Haack nose cones with shape parameter 0 or 0.33, not %.2f", shapeParameter));
} else if (shape.equals(Transition.Shape.PARABOLIC)) {
throw new RASAeroExportException("RASAero does not support Parabolic nose cones");
}
throw new RASAeroExportException(
String.format("Invalid shape and shape parameter combination: %s, %.2f", shape.getName(), shapeParameter));
}
/**
* RASAero has a slightly different way of specifying shapes compared to OpenRocket. For instance
* RASAero has an "LV-Haack" shape, which is the same as the OpenRocket "Haack" shape with a shape
* parameter of 1/3.
* This method returns the shape parameter for the RASAero shape to get the correct OpenRocket nose cone shape.
* @param shape The RASAero shape string.
* @return The shape parameter for the OpenRocket nose cone.
*/
public static double RASAERO_TO_OPENROCKET_SHAPE_PARAMETER(String shape) {
if (SHAPE_CONICAL.equals(shape)) {
return 0.0; // Not really needed, but just to be explicit
} else if (SHAPE_TANGENT_OGIVE.equals(shape)) {
return 1.0;
} else if (SHAPE_VON_KARMAN_OGIVE.equals(shape)) {
return 0.0;
} else if (SHAPE_POWER_LAW.equals(shape)) {
return 0.0; // Not really needed, but just to be explicit (will be overwritten later)
} else if (SHAPE_LVHAACK.equals(shape)) {
return 0.33;
} else if (SHAPE_PARABOLIC.equals(shape)) {
return 0.5;
} else if (SHAPE_ELLIPTICAL.equals(shape)) {
return 0.0; // Not really needed, but just to be explicit
} else {
return 0.0;
}
}
public static FinSet.CrossSection RASAERO_TO_OPENROCKET_FIN_CROSSSECTION(String crossSection, WarningSet warnings) {
if (CROSS_SECTION_SQUARE.equals(crossSection)) {
return FinSet.CrossSection.SQUARE;
} else if (CROSS_SECTION_ROUNDED.equals(crossSection)) {
return FinSet.CrossSection.ROUNDED;
} else if (CROSS_SECTION_SUBSONIC_NACA.equals(crossSection)) {
return FinSet.CrossSection.AIRFOIL;
} else {
String msg = "Unknown fin cross section: " + crossSection + ", defaulting to Airfoil.";
warnings.add(msg);
log.debug(msg);
return FinSet.CrossSection.AIRFOIL;
}
}
public static String OPENROCKET_TO_RASAERO_FIN_CROSSSECTION(FinSet.CrossSection crossSection, WarningSet warnings) {
if (FinSet.CrossSection.SQUARE.equals(crossSection)) {
return CROSS_SECTION_SQUARE;
} else if (FinSet.CrossSection.ROUNDED.equals(crossSection)) {
return CROSS_SECTION_ROUNDED;
} else if (FinSet.CrossSection.AIRFOIL.equals(crossSection)) {
return CROSS_SECTION_SUBSONIC_NACA;
} else {
String msg = "Unknown fin cross section: " + crossSection + ".";
warnings.add(msg);
log.warn(msg);
return null;
}
}
public static ExternalComponent.Finish RASAERO_TO_OPENROCKET_SURFACE(String surfaceFinish, WarningSet warnings) {
// NOTE: the RASAero surface finishes are not really the same as the OpenRocket surface finishes. There are some
// approximations here.
if (FINISH_SMOOTH.equals(surfaceFinish)) {
return ExternalComponent.Finish.MIRROR;
} else if (FINISH_POLISHED.equals(surfaceFinish)) {
return ExternalComponent.Finish.FINISHPOLISHED;
} else if (FINISH_SHEET_METAL.equals(surfaceFinish)) {
return ExternalComponent.Finish.OPTIMUM;
} else if (FINISH_SMOOTH_PAINT.equals(surfaceFinish)) {
return ExternalComponent.Finish.OPTIMUM;
} else if (FINISH_CAMOUFLAGE.equals(surfaceFinish)) {
return ExternalComponent.Finish.SMOOTH;
} else if (FINISH_ROUGH_CAMOUFLAGE.equals(surfaceFinish)) {
return ExternalComponent.Finish.NORMAL;
} else if (FINISH_GALVANIZED.equals(surfaceFinish)) {
return ExternalComponent.Finish.UNFINISHED;
} else if (FINISH_CAST_IRON.equals(surfaceFinish)) {
return ExternalComponent.Finish.ROUGHUNFINISHED;
} else {
String msg = "Unknown surface finish: " + surfaceFinish + ", defaulting to Regular Paint.";
warnings.add(msg);
log.debug(msg);
return ExternalComponent.Finish.NORMAL;
}
}
public static String OPENROCKET_TO_RASAERO_SURFACE(ExternalComponent.Finish finish, WarningSet warnings) {
if (finish.equals(ExternalComponent.Finish.MIRROR)) {
return FINISH_SMOOTH;
} else if (finish.equals(ExternalComponent.Finish.FINISHPOLISHED)) {
return FINISH_POLISHED;
} else if (finish.equals(ExternalComponent.Finish.OPTIMUM)) {
return FINISH_SHEET_METAL;
} else if (finish.equals(ExternalComponent.Finish.SMOOTH)) {
return FINISH_CAMOUFLAGE;
} else if (finish.equals(ExternalComponent.Finish.NORMAL)) {
return FINISH_ROUGH_CAMOUFLAGE;
} else if (finish.equals(ExternalComponent.Finish.UNFINISHED)) {
return FINISH_GALVANIZED;
} else if (finish.equals(ExternalComponent.Finish.ROUGHUNFINISHED)) {
return FINISH_CAST_IRON;
} else {
String msg = "Unknown surface finish: " + finish + ", defaulting to Smooth.";
warnings.add(msg);
log.debug(msg);
return FINISH_SMOOTH;
}
}
/**
* Format an OpenRocket motor as a RASAero motor.
* @param RASAeroMotors list of available RASAero motors
* @param ORMotor OpenRocket motor
* @return a RASAero String representation of a motor
*/
public static String OPENROCKET_TO_RASAERO_MOTOR(List<ThrustCurveMotor> RASAeroMotors, Motor ORMotor,
WarningSet warnings) {
if (!(ORMotor instanceof ThrustCurveMotor)) {
log.debug("RASAero motor not found: not a thrust curve motor");
return null;
}
for (ThrustCurveMotor RASAeroMotor : RASAeroMotors) {
String RASAeroDesignation = AbstractMotorLoader.removeDelay(RASAeroMotor.getDesignation());
if (ORMotor.getDesignation().equals(RASAeroDesignation) &&
((ThrustCurveMotor) ORMotor).getManufacturer().matches(RASAeroMotor.getManufacturer().getDisplayName())) {
String motorName = RASAeroMotor.getDesignation();
log.debug(String.format("RASAero RASAeroMotor found: %s", motorName));
return motorName + " (" + OPENROCKET_TO_RASAERO_MANUFACTURER(RASAeroMotor.getManufacturer()) + ")";
}
}
String msg = String.format("Could not find RASAero motor for '%s'", ORMotor.getDesignation());
warnings.add(msg);
log.debug(msg);
return null;
}
public static String OPENROCKET_TO_RASAERO_MANUFACTURER(Manufacturer manufacturer) {
if (manufacturer.matches("AeroTech")) {
return "AT";
} else if (manufacturer.matches("Estes")) {
return "ES";
} else if (manufacturer.matches("Apogee")) {
return "AP";
} else if (manufacturer.matches("Quest")) {
return "QU";
} else if (manufacturer.matches("Cesaroni")) {
return "CTI";
} else if (manufacturer.matches("NoThrust")) {
return "NoThrust";
} else if (manufacturer.matches("Ellis Mountain")) {
return "EM";
} else if (manufacturer.matches("Contrail")) {
return "Contrail";
} else if (manufacturer.matches("Rocketvision")) {
return "RV";
} else if (manufacturer.matches("Roadrunner Rocketry")) {
return "RR";
} else if (manufacturer.matches("Sky Ripper Systems")) {
return "SRS";
} else if (manufacturer.matches("Loki Research")) {
return "LR";
} else if (manufacturer.matches("Public Missiles, Ltd.")) {
return "PML";
} else if (manufacturer.matches("Kosdon by AeroTech")) {
return "KBA";
} else if (manufacturer.matches("Gorilla Rocket Motors")) {
return "GM";
} else if (manufacturer.matches("RATT Works")) {
return "RTW";
} else if (manufacturer.matches("HyperTEK")) {
return "HT";
} else if (manufacturer.matches("Animal Motor Works")) {
return "AMW";
} else if (manufacturer.matches("Loki")) {
return "CT";
} else if (manufacturer.matches("AMW ProX")) {
return "AMW/ProX";
} else if (manufacturer.matches("Loki Research EX")) {
return "LR-EX";
} else if (manufacturer.matches("Derek Deville DEAP EX")) {
return "DEAP-EX";
} else if (manufacturer.matches("Historical")) {
return "Hist";
}
return manufacturer.getSimpleName();
}
public static DeploymentConfiguration.DeployEvent RASAERO_TO_OPENROCKET_DEPLOY_EVENT(String deployEvent, WarningSet warnings) {
if (DEPLOYMENT_NONE.equals(deployEvent)) {
return DeploymentConfiguration.DeployEvent.NEVER;
} else if (DEPLOYMENT_APOGEE.equals(deployEvent)) {
return DeploymentConfiguration.DeployEvent.APOGEE;
} else if (DEPLOYMENT_ALTITUDE.equals(deployEvent)) {
return DeploymentConfiguration.DeployEvent.ALTITUDE;
}
warnings.add("Unknown deployment event: " + deployEvent + ", defaulting to apogee.");
return DeploymentConfiguration.DeployEvent.APOGEE;
}
public static String OPENROCKET_TO_RASAERO_COLOR(Color color) {
if (color != null) {
if (color.equals(Color.BLACK)) {
return "Black"; // Currently the only officially supported color by RASAero
}
}
return "Blue"; // But we can also apply our own color hehe
}
/**
* Class containing the RASAero nose cone shape and shape parameter settings
*/
public static class NoseConeShapeSettings {
private final String shape;
private final Double shapeParameter;
public NoseConeShapeSettings(String shape, double shapeParameter) {
this.shape = shape;
this.shapeParameter = shapeParameter;
}
public NoseConeShapeSettings(String shape) {
this.shape = shape;
this.shapeParameter = null;
}
public String getShape() {
return shape;
}
public Double getShapeParameter() {
return shapeParameter;
}
}
}

View File

@ -1,104 +0,0 @@
package net.sf.openrocket.file.rasaero;
import net.sf.openrocket.file.motor.GeneralMotorLoader;
import net.sf.openrocket.file.motor.RASPMotorLoader;
import net.sf.openrocket.logging.WarningSet;
import net.sf.openrocket.database.motor.ThrustCurveMotorSet;
import net.sf.openrocket.file.motor.AbstractMotorLoader;
import net.sf.openrocket.motor.ThrustCurveMotor;
import net.sf.openrocket.startup.Application;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public abstract class RASAeroMotorsLoader {
private static List<ThrustCurveMotor> allMotors = null;
/**
* Returns a RASAero motor from the motor string of its RASAero file.
* @param motorString The motor string of the RASAero file, e.g. "1/4A2 (AP)".
* @param warnings The warning set to add import warnings to.
* @return The motor, or null if not found.
*/
public static ThrustCurveMotor getMotorFromRASAero(String motorString, WarningSet warnings) {
if (motorString == null) {
return null;
}
if (allMotors == null) {
loadAllMotors(warnings);
}
/*
RASAero file motor strings are formatted as "<motorName> (<manufacturer>)"
*/
String[] split = motorString.split("\\s{2}");
if (split.length != 2) {
return null;
}
String motorName = AbstractMotorLoader.removeDelay(split[0]);
String manufacturer = split[1].replaceAll("^\\(|\\)$", ""); // Remove beginning and ending parenthesis
for (ThrustCurveMotor motor : allMotors) {
if (motorName.equals(motor.getDesignation()) && motor.getManufacturer().matches(manufacturer)) {
return motor;
}
}
warnings.add("Could not find motor '" + motorString + "' in the OpenRocket motors database. Please add it manually.");
return null;
}
/**
* Call this method when you don't need the RASAero motors anymore to free memory.
*/
public static void clearAllMotors() {
if (allMotors != null) {
allMotors.clear();
allMotors = null;
}
}
// Not currently used for importing, because it causes some compatibility issues when e.g. wanting to open the RASAero motor
// in the motor selection table (because it is not present there).
// It's probably also better to load OR-native motors.
// But I'll leave this in, in case it's needed in the future.
/**
* Loads all original RASAero motors.
* @param warnings The warning set to add import warnings to.
* @return the loaded motors
* @throws RuntimeException If the RASAero motors file could not be found.
*/
public static List<ThrustCurveMotor> loadAllRASAeroMotors(WarningSet warnings) throws RuntimeException {
List<ThrustCurveMotor> RASAeroMotors = new ArrayList<>();
RASPMotorLoader loader = new RASPMotorLoader();
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
String fileName = "RASAero_Motors.eng";
InputStream is = classloader.getResourceAsStream("datafiles/thrustcurves/RASAero/" + fileName);
if (is == null) {
throw new RuntimeException("Could not find " + fileName);
}
try {
List<ThrustCurveMotor.Builder> motors = loader.load(is, fileName, false);
for (ThrustCurveMotor.Builder builder : motors) {
RASAeroMotors.add(builder.build());
}
} catch (IOException e) {
warnings.add("Error during motor loading: " + e.getMessage());
}
return RASAeroMotors;
}
/**
* Loads the OpenRocket motors database.
*/
private static void loadAllMotors(WarningSet warnings) {
allMotors = new ArrayList<>();
List<ThrustCurveMotorSet> database = Application.getThrustCurveMotorSetDatabase().getMotorSets();
for (ThrustCurveMotorSet set : database) {
allMotors.addAll(set.getMotors());
}
//allMotors.addAll(loadAllRASAeroMotors(warnings));
}
}

View File

@ -1,148 +0,0 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.ErrorSet;
import net.sf.openrocket.logging.WarningSet;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.NoseCone;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.MathUtil;
/**
* The base class for most RASAero components.
*/
@XmlRootElement
@XmlType(name="RASAeroBasePartDTO")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlTransient
public class BasePartDTO {
@XmlElement(name = RASAeroCommonConstants.PART_TYPE)
private String partType;
@XmlElement(name = RASAeroCommonConstants.LENGTH)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double length;
@XmlElement(name = RASAeroCommonConstants.DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double diameter;
@XmlElement(name = RASAeroCommonConstants.LOCATION)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double location;
@XmlElement(name = RASAeroCommonConstants.COLOR)
private String color;
@XmlTransient
private final RocketComponent component;
@XmlTransient
private final WarningSet warnings;
@XmlTransient
private final ErrorSet errors;
@XmlTransient
private static final Translator trans = Application.getTranslator();
/**
* We need a default no-args constructor.
*/
public BasePartDTO() {
this.component = null;
this.warnings = null;
this.errors = null;
}
protected BasePartDTO(RocketComponent component, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
this.component = component;
this.warnings = warnings;
this.errors = errors;
if (component instanceof BodyTube) {
setPartType(RASAeroCommonConstants.BODY_TUBE);
setDiameter(((BodyTube) component).getOuterRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
} else if (component instanceof NoseCone) {
setPartType(RASAeroCommonConstants.NOSE_CONE);
NoseCone noseCone = (NoseCone) component;
if (noseCone.isFlipped()) {
throw new RASAeroExportException(trans.get("RASAeroExport.warning1"));
}
setDiameter(((NoseCone) component).getAftRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
} else if (component instanceof Transition) {
setPartType(RASAeroCommonConstants.TRANSITION);
// This is a bit strange: I would expect diameter to be the fore radius, since you also have a rearDiamter
// field for transitions, but okay
setDiameter(((Transition) component).getAftRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
} else if (component instanceof AxialStage) {
setPartType(RASAeroCommonConstants.BOOSTER);
AxialStage stage = (AxialStage) component;
if (stage.getChildCount() == 0 || !(stage.getChild(0) instanceof BodyTube)) {
throw new RASAeroExportException(trans.get("RASAeroExport.warning2"));
}
setDiameter(stage.getBoundingRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
} else {
throw new RASAeroExportException(String.format(trans.get("RASAeroExport.error1"), component.getComponentName()));
}
setLength(component.getLength() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setLocation(component.getAxialOffset(AxialMethod.ABSOLUTE) * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setColor(RASAeroCommonConstants.OPENROCKET_TO_RASAERO_COLOR(component.getColor()));
}
public String getPartType() {
return partType;
}
public void setPartType(String partType) {
this.partType = partType;
}
public Double getLength() {
return length;
}
public void setLength(Double length) throws RASAeroExportException {
if (MathUtil.equals(length, 0)) {
throw new RASAeroExportException(String.format(trans.get("RASAeroExport.error2"), component.getName()));
}
this.length = length;
}
public Double getDiameter() {
return diameter;
}
public void setDiameter(Double diameter) throws RASAeroExportException {
if (MathUtil.equals(diameter, 0)) {
throw new RASAeroExportException(String.format(trans.get("RASAeroExport.error3"), component.getName()));
}
this.diameter = diameter;
}
public Double getLocation() {
return location;
}
public void setLocation(Double location) {
this.location = location;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}

View File

@ -1,28 +0,0 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.logging.ErrorSet;
import net.sf.openrocket.logging.WarningSet;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = RASAeroCommonConstants.BOATTAIL)
@XmlAccessorType(XmlAccessType.FIELD)
public class BoattailDTO extends TransitionDTO {
/**
* We need a default no-args constructor.
*/
public BoattailDTO() {
super();
}
public BoattailDTO(Transition boattail, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
super(boattail, warnings, errors);
setPartType(RASAeroCommonConstants.BOATTAIL);
}
}

View File

@ -1,192 +0,0 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.ErrorSet;
import net.sf.openrocket.logging.WarningSet;
import net.sf.openrocket.rocketcomponent.BodyTube;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.MathUtil;
@XmlRootElement(name = RASAeroCommonConstants.BODY_TUBE)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = {
"partType",
"length",
"diameter",
"launchLugDiameter",
"launchLugLength",
"railGuideDiameter",
"railGuideHeight",
"launchShoeArea",
"location",
"color",
"boattailLength",
"boattailRearDiameter",
"boattailOffset",
"overhang",
"fin"
})
public class BodyTubeDTO extends BasePartDTO implements BodyTubeDTOAdapter {
@XmlElement(name = RASAeroCommonConstants.LAUNCH_LUG_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double launchLugDiameter = 0d;
@XmlElement(name = RASAeroCommonConstants.LAUNCH_LUG_LENGTH)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double launchLugLength = 0d;
@XmlElement(name = RASAeroCommonConstants.RAIL_GUIDE_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double railGuideDiameter = 0d;
@XmlElement(name = RASAeroCommonConstants.RAIL_GUIDE_HEIGHT)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double railGuideHeight = 0d;
@XmlElement(name = RASAeroCommonConstants.LAUNCH_SHOE_AREA)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double launchShoeArea = 0d; // Currently not available in OR
@XmlElement(name = RASAeroCommonConstants.BOATTAIL_LENGTH)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double boattailLength = 0d;
@XmlElement(name = RASAeroCommonConstants.BOATTAIL_REAR_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double boattailRearDiameter = 0d;
@XmlElement(name = RASAeroCommonConstants.BOATTAIL_OFFSET)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double boattailOffset = 0d;
@XmlElement(name = RASAeroCommonConstants.OVERHANG)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double overhang = 0d;
@XmlElementRef(name = RASAeroCommonConstants.FIN, type = FinDTO.class)
private FinDTO fin;
@XmlTransient
private final WarningSet warnings;
@XmlTransient
private final ErrorSet errors;
@XmlTransient
private static final Translator trans = Application.getTranslator();
/**
* We need a default no-args constructor.
*/
public BodyTubeDTO() {
this.warnings = null;
this.errors = null;
}
public BodyTubeDTO(BodyTube bodyTube, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
super(bodyTube, warnings, errors);
this.warnings = warnings;
this.errors = errors;
applyBodyTubeSettings(bodyTube, warnings, errors);
}
public Double getLaunchLugDiameter() {
return launchLugDiameter;
}
public void setLaunchLugDiameter(Double launchLugDiameter) throws RASAeroExportException {
if (MathUtil.equals(launchLugDiameter, 0)) {
throw new RASAeroExportException(trans.get("RASAeroExport.error4"));
}
this.launchLugDiameter = launchLugDiameter;
}
public Double getLaunchLugLength() {
return launchLugLength;
}
public void setLaunchLugLength(Double launchLugLength) throws RASAeroExportException {
if (MathUtil.equals(launchLugLength, 0)) {
throw new RASAeroExportException(trans.get("RASAeroExport.error5"));
}
this.launchLugLength = launchLugLength;
}
public Double getRailGuideDiameter() {
return railGuideDiameter;
}
public void setRailGuideDiameter(Double railGuideDiameter) throws RASAeroExportException {
if (MathUtil.equals(railGuideDiameter, 0)) {
throw new RASAeroExportException(trans.get("RASAeroExport.error6"));
}
this.railGuideDiameter = railGuideDiameter;
}
public Double getRailGuideHeight() {
return railGuideHeight;
}
public void setRailGuideHeight(Double railGuideHeight) throws RASAeroExportException {
if (MathUtil.equals(railGuideHeight, 0)) {
throw new RASAeroExportException(trans.get("RASAeroExport.error7"));
}
this.railGuideHeight = railGuideHeight;
}
public Double getLaunchShoeArea() {
return launchShoeArea;
}
public void setLaunchShoeArea(Double launchShoeArea) throws RASAeroExportException {
if (MathUtil.equals(launchShoeArea, 0)) {
throw new RASAeroExportException(trans.get("RASAeroExport.error8"));
}
this.launchShoeArea = launchShoeArea;
}
public Double getBoattailLength() {
return boattailLength;
}
public void setBoattailLength(Double boattailLength) {
this.boattailLength = boattailLength;
}
public Double getBoattailRearDiameter() {
return boattailRearDiameter;
}
public void setBoattailRearDiameter(Double boattailRearDiameter) {
this.boattailRearDiameter = boattailRearDiameter;
}
public Double getBoattailOffset() {
return boattailOffset;
}
public void setBoattailOffset(Double boattailOffset) {
this.boattailOffset = boattailOffset;
}
public Double getOverhang() {
return overhang;
}
public void setOverhang(Double overhang) {
this.overhang = overhang;
}
public FinDTO getFin() {
return fin;
}
public void setFin(FinDTO fin) {
this.fin = fin;
}
}

View File

@ -1,101 +0,0 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.ErrorSet;
import net.sf.openrocket.logging.WarningSet;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.LaunchLug;
import net.sf.openrocket.rocketcomponent.Parachute;
import net.sf.openrocket.rocketcomponent.RailButton;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
import javax.xml.bind.annotation.XmlTransient;
public interface BodyTubeDTOAdapter {
@XmlTransient
Translator trans = Application.getTranslator();
default void applyBodyTubeSettings(BodyTube bodyTube, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
for (RocketComponent child : bodyTube.getChildren()) {
if (child instanceof TrapezoidFinSet) {
setFin(new FinDTO((TrapezoidFinSet) child, warnings, errors));
} else if (child instanceof LaunchLug) {
if (!MathUtil.equals(getRailGuideDiameter(), 0) || !MathUtil.equals(getRailGuideHeight(), 0)) { // only one check on diameter or length should be sufficient, but just to be safe
warnings.add(String.format(trans.get("RASAeroExport.warning3"), child.getName()));
continue;
}
if (!MathUtil.equals(getLaunchShoeArea(), 0)) {
warnings.add(String.format(trans.get("RASAeroExport.warning4"), child.getName()));
continue;
}
LaunchLug lug = (LaunchLug) child;
setLaunchLugDiameter(lug.getOuterRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
if (lug.getInstanceCount() == 2) {
setLaunchLugLength(lug.getLength() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
} else {
warnings.add(String.format(trans.get("RASAeroExport.warning5"), lug.getName()));
setLaunchLugLength(lug.getLength() * lug.getInstanceCount() / 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
}
} else if (child instanceof RailButton) {
if (!MathUtil.equals(getLaunchLugDiameter(), 0) || !MathUtil.equals(getLaunchLugLength(), 0)) { // only one check on diameter or length should be sufficient, but just to be safe
warnings.add(String.format(trans.get("RASAeroExport.warning6"), child.getName()));
continue;
}
if (!MathUtil.equals(getLaunchShoeArea(), 0)) {
warnings.add(String.format(trans.get("RASAeroExport.warning7"), child.getName()));
continue;
}
RailButton button = (RailButton) child;
setRailGuideDiameter(button.getOuterDiameter() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setRailGuideHeight(button.getTotalHeight() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
if (button.getInstanceCount() != 2) {
warnings.add(String.format(trans.get("RASAeroExport.warning8"), button.getName(), button.getInstanceCount()));
}
} else if (child instanceof Parachute) {
// Do nothing, is handled by RecoveryDTO
} else {
warnings.add(String.format(trans.get("RASAeroExport.warning9"), child.getComponentName()));
}
}
}
Double getLaunchLugDiameter();
void setLaunchLugDiameter(Double launchLugDiameter) throws RASAeroExportException;
Double getLaunchLugLength();
void setLaunchLugLength(Double launchLugLength) throws RASAeroExportException;
Double getRailGuideDiameter();
void setRailGuideDiameter(Double railGuideDiameter) throws RASAeroExportException;
Double getRailGuideHeight();
void setRailGuideHeight(Double railGuideHeight) throws RASAeroExportException;
Double getLaunchShoeArea();
void setLaunchShoeArea(Double launchShoeArea) throws RASAeroExportException;
Double getBoattailLength();
void setBoattailLength(Double boattailLength) throws RASAeroExportException;
Double getBoattailRearDiameter();
void setBoattailRearDiameter(Double boattailRearDiameter) throws RASAeroExportException;
FinDTO getFin();
void setFin(FinDTO fin);
}

View File

@ -1,369 +0,0 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.ErrorSet;
import net.sf.openrocket.logging.WarningSet;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.NoseCone;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
import net.sf.openrocket.rocketcomponent.SymmetricComponent;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.MathUtil;
@XmlRootElement(name = RASAeroCommonConstants.BOOSTER)
@XmlAccessorType(XmlAccessType.FIELD)
public class BoosterDTO implements BodyTubeDTOAdapter {
@XmlElement(name = RASAeroCommonConstants.PART_TYPE)
private String partType;
@XmlElement(name = RASAeroCommonConstants.LENGTH)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double length;
@XmlElement(name = RASAeroCommonConstants.DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double diameter;
@XmlElement(name = RASAeroCommonConstants.INSIDE_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double insideDiameter;
@XmlElement(name = RASAeroCommonConstants.LAUNCH_LUG_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double launchLugDiameter = 0d;
@XmlElement(name = RASAeroCommonConstants.LAUNCH_LUG_LENGTH)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double launchLugLength = 0d;
@XmlElement(name = RASAeroCommonConstants.RAIL_GUIDE_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double railGuideDiameter = 0d;
@XmlElement(name = RASAeroCommonConstants.RAIL_GUIDE_HEIGHT)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double railGuideHeight = 0d;
@XmlElement(name = RASAeroCommonConstants.LAUNCH_SHOE_AREA)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double launchShoeArea = 0d; // Currently not available in OR
@XmlElement(name = RASAeroCommonConstants.LOCATION)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double location;
@XmlElement(name = RASAeroCommonConstants.COLOR)
private String color;
@XmlElement(name = RASAeroCommonConstants.SHOULDER_LENGTH)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double shoulderLength;
@XmlElement(name = RASAeroCommonConstants.NOZZLE_EXIT_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double nozzleExitDiameter = 0d;
@XmlElement(name = RASAeroCommonConstants.BOATTAIL_LENGTH)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double boattailLength;
@XmlElement(name = RASAeroCommonConstants.BOATTAIL_REAR_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double boattailRearDiameter;
@XmlElementRef(name = RASAeroCommonConstants.FIN, type = FinDTO.class)
private FinDTO fin;
@XmlTransient
private final RocketComponent component;
@XmlTransient
private final WarningSet warnings;
@XmlTransient
private final ErrorSet errors;
@XmlTransient
private static final Translator trans = Application.getTranslator();
/**
* We need a default, no-args constructor.
*/
public BoosterDTO() {
this.component = null;
this.warnings = null;
this.errors = null;
}
protected BoosterDTO(Rocket rocket, AxialStage stage, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
this.component = stage;
this.warnings = warnings;
this.errors = errors;
int stageNr = rocket.getChildPosition(stage); // Use this instead of stage.getStageNumber() in case there are parallel stages in the design
if (stageNr != 1 && stageNr != 2) {
throw new RASAeroExportException(String.format(trans.get("RASAeroExport.error9"), stageNr, stage.getName()));
}
if (stage.getChildCount() == 0) {
throw new RASAeroExportException(String.format(trans.get("RASAeroExport.error10"), stage.getName()));
}
RocketComponent firstChild = stage.getChild(0);
if (!(firstChild instanceof BodyTube) &&
!(firstChild instanceof Transition && !(firstChild instanceof NoseCone))) {
throw new RASAeroExportException(String.format(trans.get("RASAeroExport.error11"), stage.getName()));
}
final BodyTube firstTube;
if (firstChild instanceof Transition) {
if (stage.getChildCount() == 1 || !(stage.getChild(1) instanceof BodyTube)) {
throw new RASAeroExportException(
String.format(trans.get("RASAeroExport.error12"), stage.getName()));
}
Transition transition = (Transition) firstChild;
SymmetricComponent previousComponent = transition.getPreviousSymmetricComponent();
if (previousComponent == null) {
throw new RASAeroExportException(String.format(trans.get("RASAeroExport.error13"),
firstChild.getName(), stage.getName()));
}
if (!MathUtil.equals(transition.getForeRadius(), previousComponent.getAftRadius())) {
throw new RASAeroExportException(
String.format(trans.get("RASAeroExport.error14"),
transition.getName(), stage.getName(), previousComponent.getName()));
}
firstTube = (BodyTube) stage.getChild(1);
if (!MathUtil.equals(firstTube.getOuterRadius(), transition.getAftRadius())) {
throw new RASAeroExportException(
String.format(trans.get("RASAeroExport.error15"),
firstTube.getName(), stage.getName(), transition.getName()));
}
setShoulderLength(firstChild.getLength() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setDiameter(firstTube.getOuterRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setInsideDiameter(transition.getForeRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
} else {
firstTube = (BodyTube) stage.getChild(0);
}
TrapezoidFinSet finSet = getFinSetFromBodyTube(firstTube);
double tubeLength = firstTube.getLength();
double finLocationOffset = 0;
// Aggregate same-sized body tubes
for (int i = stage.getChildPosition(firstTube) + 1; i < stage.getChildCount(); i++) {
RocketComponent comp = stage.getChild(i);
if (comp instanceof BodyTube &&
MathUtil.equals(((BodyTube) comp).getOuterRadius(), firstTube.getOuterRadius())) {
// Aggregate the tubes by combining the lengths
tubeLength += comp.getLength();
// If no fin set in firstTube, add fin from new tube
if (finSet == null) {
finSet = getFinSetFromBodyTube((BodyTube) comp);
}
// We need an offset to the fin location, since the fin axial offset is referenced to its parent tube,
// which can be different from the bottom of the aggregate tubes
else {
finLocationOffset += comp.getLength();
}
} else {
// If this booster is the last stage, and the last component is a transition, it could be a boattail
boolean isBoattail = (comp instanceof Transition && !(comp instanceof NoseCone)) && i == stage.getChildCount() - 1;
if (stageNr == rocket.getChildCount() - 1 && isBoattail) {
Transition transition = (Transition) comp;
setBoattailLength(transition.getLength() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setBoattailRearDiameter(transition.getAftRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
break;
}
String msg = String.format(trans.get("RASAeroExport.error31"), stage.getName());
if (isBoattail) {
msg = "<html>" + msg + "<br>&nbsp;" + trans.get("RASAeroExport.error32") + "</html>";
}
errors.add(msg);
break;
}
}
applyBodyTubeSettings(firstTube, warnings, errors);
if (finSet == null) {
throw new RASAeroExportException(
String.format(trans.get("RASAeroExport.error16"),
firstTube.getName(), stage.getName()));
}
FinDTO finDTO = new FinDTO(finSet, warnings, errors);
double finLocation = finDTO.getLocation();
finDTO.setLocation(finLocation + finLocationOffset * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setFin(finDTO);
setPartType(RASAeroCommonConstants.BOOSTER);
setLength(tubeLength * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setDiameter(firstTube.getOuterRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setLocation(firstChild.getAxialOffset(AxialMethod.ABSOLUTE) * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setColor(RASAeroCommonConstants.OPENROCKET_TO_RASAERO_COLOR(firstTube.getColor()));
}
private TrapezoidFinSet getFinSetFromBodyTube(BodyTube bodyTube) {
for (RocketComponent child : bodyTube.getChildren()) {
if (child instanceof TrapezoidFinSet) {
return (TrapezoidFinSet) child;
}
}
return null;
}
public String getPartType() {
return partType;
}
public void setPartType(String partType) {
this.partType = partType;
}
public Double getLength() {
return length;
}
public void setLength(Double length) {
if (MathUtil.equals(length, 0)) {
errors.add(String.format(trans.get("RASAeroExport.error17"), component.getName()));
return;
}
this.length = length;
}
public Double getDiameter() {
return diameter;
}
public void setDiameter(Double diameter) throws RASAeroExportException {
if (MathUtil.equals(diameter, 0)) {
throw new RASAeroExportException(String.format(trans.get("RASAeroExport.error18"), component.getName()));
}
this.diameter = diameter;
}
public Double getInsideDiameter() {
return insideDiameter;
}
public void setInsideDiameter(Double insideDiameter) throws RASAeroExportException {
if (MathUtil.equals(insideDiameter, 0)) {
throw new RASAeroExportException(String.format(trans.get("RASAeroExport.error19"), component.getName()));
}
this.insideDiameter = insideDiameter;
}
public Double getLaunchLugDiameter() {
return launchLugDiameter;
}
public void setLaunchLugDiameter(Double launchLugDiameter) {
this.launchLugDiameter = launchLugDiameter;
}
public Double getLaunchLugLength() {
return launchLugLength;
}
public void setLaunchLugLength(Double launchLugLength) {
this.launchLugLength = launchLugLength;
}
public Double getRailGuideDiameter() {
return railGuideDiameter;
}
public void setRailGuideDiameter(Double railGuideDiameter) {
this.railGuideDiameter = railGuideDiameter;
}
public Double getRailGuideHeight() {
return railGuideHeight;
}
public void setRailGuideHeight(Double railGuideHeight) {
this.railGuideHeight = railGuideHeight;
}
public Double getLaunchShoeArea() {
return launchShoeArea;
}
public void setLaunchShoeArea(Double launchShoeArea) {
this.launchShoeArea = launchShoeArea;
}
public Double getLocation() {
return location;
}
public void setLocation(Double location) {
this.location = location;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Double getShoulderLength() {
return shoulderLength;
}
public void setShoulderLength(Double shoulderLength) {
this.shoulderLength = shoulderLength;
}
public Double getNozzleExitDiameter() {
return nozzleExitDiameter;
}
public void setNozzleExitDiameter(Double nozzleExitDiameter) {
this.nozzleExitDiameter = nozzleExitDiameter;
}
public Double getBoattailLength() {
return boattailLength;
}
public void setBoattailLength(Double boattailLength) throws RASAeroExportException {
if (boattailLength == 0) {
throw new RASAeroExportException(trans.get("RASAeroExport.error29"));
}
this.boattailLength = boattailLength;
}
public Double getBoattailRearDiameter() {
return boattailRearDiameter;
}
public void setBoattailRearDiameter(Double boattailRearDiameter) throws RASAeroExportException {
if (boattailRearDiameter == 0) {
throw new RASAeroExportException(trans.get("RASAeroExport.error30"));
}
this.boattailRearDiameter = boattailRearDiameter;
}
public FinDTO getFin() {
return fin;
}
public void setFin(FinDTO fin) {
this.fin = fin;
}
}

View File

@ -1,168 +0,0 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.ErrorSet;
import net.sf.openrocket.logging.WarningSet;
import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
import net.sf.openrocket.startup.Application;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement(name = RASAeroCommonConstants.FIN)
@XmlAccessorType(XmlAccessType.FIELD)
public class FinDTO {
@XmlElement(name = RASAeroCommonConstants.FIN_COUNT)
private int count;
@XmlElement(name = RASAeroCommonConstants.FIN_CHORD)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double chord;
@XmlElement(name = RASAeroCommonConstants.FIN_SPAN)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double span;
@XmlElement(name = RASAeroCommonConstants.FIN_SWEEP_DISTANCE)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double sweepDistance;
@XmlElement(name = RASAeroCommonConstants.FIN_TIP_CHORD)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double tipChord;
@XmlElement(name = RASAeroCommonConstants.FIN_THICKNESS)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double thickness;
@XmlElement(name = RASAeroCommonConstants.FIN_LE_RADIUS)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double LERadius = 0d; // Leading edge radius
@XmlElement(name = RASAeroCommonConstants.LOCATION)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double location;
@XmlElement(name = RASAeroCommonConstants.AIRFOIL_SECTION)
private String airfoilSection;
@XmlElement(name = RASAeroCommonConstants.FIN_FX1)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double FX1 = 0d;
@XmlElement(name = RASAeroCommonConstants.FIN_FX3)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double FX3 = 0d;
@XmlTransient
private static final Translator trans = Application.getTranslator();
/**
* We need a default no-args constructor.
*/
public FinDTO() {
}
public FinDTO(TrapezoidFinSet fin, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
int finCount = fin.getFinCount();
if (finCount < 3 || finCount > 8) {
throw new RASAeroExportException(
String.format(trans.get("RASAeroExport.error20"), fin.getName()));
}
setCount(fin.getFinCount());
setChord(fin.getRootChord() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setTipChord(fin.getTipChord() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setSpan(fin.getSpan() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setSweepDistance(fin.getSweep() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setThickness(fin.getThickness() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setAirfoilSection(RASAeroCommonConstants.OPENROCKET_TO_RASAERO_FIN_CROSSSECTION(fin.getCrossSection(), warnings));
setLocation((-fin.getAxialOffset(AxialMethod.BOTTOM) + fin.getLength()) * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public Double getChord() {
return chord;
}
public void setChord(Double chord) {
this.chord = chord;
}
public Double getSpan() {
return span;
}
public void setSpan(Double span) {
this.span = span;
}
public Double getSweepDistance() {
return sweepDistance;
}
public void setSweepDistance(Double sweepDistance) {
this.sweepDistance = sweepDistance;
}
public Double getTipChord() {
return tipChord;
}
public void setTipChord(Double tipChord) {
this.tipChord = tipChord;
}
public Double getThickness() {
return thickness;
}
public void setThickness(Double thickness) {
this.thickness = thickness;
}
public Double getLERadius() {
return LERadius;
}
public void setLERadius(Double LERadius) {
this.LERadius = LERadius;
}
public Double getLocation() {
return location;
}
public void setLocation(Double location) {
this.location = location;
}
public String getAirfoilSection() {
return airfoilSection;
}
public void setAirfoilSection(String airfoilSection) {
this.airfoilSection = airfoilSection;
}
public Double getFX1() {
return FX1;
}
public void setFX1(Double FX1) {
this.FX1 = FX1;
}
public Double getFX3() {
return FX3;
}
public void setFX3(Double FX3) {
this.FX3 = FX3;
}
}

View File

@ -1,121 +0,0 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.logging.ErrorSet;
import net.sf.openrocket.logging.WarningSet;
import net.sf.openrocket.simulation.SimulationOptions;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.startup.Preferences;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement(name = RASAeroCommonConstants.LAUNCH_SITE)
@XmlAccessorType(XmlAccessType.FIELD)
public class LaunchSiteDTO {
@XmlElement(name = RASAeroCommonConstants.LAUNCH_ALTITUDE)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double altitude = 0d;
@XmlElement(name = RASAeroCommonConstants.LAUNCH_PRESSURE)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double pressure = 0d;
@XmlElement(name = RASAeroCommonConstants.LAUNCH_ROD_ANGLE)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double rodAngle = 0d;
@XmlElement(name = RASAeroCommonConstants.LAUNCH_ROD_LENGTH)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double rodLength = 0d;
@XmlElement(name = RASAeroCommonConstants.LAUNCH_TEMPERATURE)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double temperature = 0d;
@XmlElement(name = RASAeroCommonConstants.LAUNCH_WIND_SPEED)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double windSpeed = 0d;
/**
* We need a default, no-args constructor.
*/
public LaunchSiteDTO() {
}
public LaunchSiteDTO(OpenRocketDocument document, WarningSet warnings, ErrorSet errors) {
for (Simulation sim : document.getSimulations()) {
SimulationOptions options = sim.getSimulatedConditions();
if (options == null) {
continue;
}
setAltitude(options.getLaunchAltitude() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_ALTITUDE);
setPressure(options.getLaunchPressure() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_PRESSURE);
setTemperature(RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TEMPERATURE(options.getLaunchTemperature()));
setRodAngle(options.getLaunchRodAngle() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_ANGLE);
setRodLength(options.getLaunchRodLength() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setWindSpeed(options.getWindSpeedAverage() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_SPEED);
return;
}
// If we can't get settings from the sims, use the launch site settings from the preferences
Preferences prefs = Application.getPreferences();
setAltitude(prefs.getLaunchAltitude() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_ALTITUDE);
setPressure(prefs.getLaunchPressure() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_PRESSURE);
setTemperature(RASAeroCommonConstants.OPENROCKET_TO_RASAERO_TEMPERATURE(prefs.getLaunchTemperature()));
setRodAngle(prefs.getLaunchRodAngle() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_ANGLE);
setRodLength(prefs.getLaunchRodLength() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
setWindSpeed(prefs.getWindSpeedAverage() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_SPEED);
}
public Double getAltitude() {
return altitude;
}
public void setAltitude(Double altitude) {
this.altitude = altitude;
}
public Double getPressure() {
return pressure;
}
public void setPressure(Double pressure) {
this.pressure = pressure;
}
public Double getRodAngle() {
return rodAngle;
}
public void setRodAngle(Double rodAngle) {
this.rodAngle = rodAngle;
}
public Double getRodLength() {
return rodLength;
}
public void setRodLength(Double rodLength) {
this.rodLength = rodLength;
}
public Double getTemperature() {
return temperature;
}
public void setTemperature(Double temperature) {
this.temperature = temperature;
}
public Double getWindSpeed() {
return windSpeed;
}
public void setWindSpeed(Double windSpeed) {
this.windSpeed = windSpeed;
}
}

View File

@ -1,84 +0,0 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.logging.ErrorSet;
import net.sf.openrocket.logging.WarningSet;
import net.sf.openrocket.rocketcomponent.NoseCone;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants.NoseConeShapeSettings;
@XmlRootElement(name = RASAeroCommonConstants.NOSE_CONE)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = {
"partType",
"length",
"diameter",
"shape",
"bluntRadius",
"location",
"color",
"powerLaw"
})
public class NoseConeDTO extends BasePartDTO {
@XmlElement(name = RASAeroCommonConstants.SHAPE)
private String shape;
@XmlElement(name = RASAeroCommonConstants.BLUNT_RADIUS)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double bluntRadius = 0d;
@XmlElement(name = RASAeroCommonConstants.POWER_LAW)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double powerLaw;
/**
* We need a default no-args constructor.
*/
public NoseConeDTO() {
}
public NoseConeDTO(NoseCone noseCone, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
super(noseCone, warnings, errors);
NoseConeShapeSettings shapeSettings =
RASAeroCommonConstants.OPENROCKET_TO_RASAERO_SHAPE(noseCone.getShapeType(), noseCone.getShapeParameter());
setShape(shapeSettings.getShape());
Double shapeParameter = shapeSettings.getShapeParameter();
if (shapeParameter != null) {
setPowerLaw(shapeParameter);
}
}
public String getShape() {
return shape;
}
public void setShape(String shape) {
this.shape = shape;
}
public Double getPowerLaw() {
return powerLaw;
}
public void setPowerLaw(Double powerLaw) {
this.powerLaw = powerLaw;
}
public double getBluntRadius() {
return bluntRadius;
}
public void setBluntRadius(double bluntRadius) {
this.bluntRadius = bluntRadius;
}
}

View File

@ -1,83 +0,0 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* The top level RASAero document.
*/
@XmlRootElement(name = RASAeroCommonConstants.RASAERO_DOCUMENT)
@XmlAccessorType(XmlAccessType.FIELD)
public class RASAeroDocumentDTO {
@XmlElement(name = RASAeroCommonConstants.FILE_VERSION)
private final String version = "2";
@XmlElement(name = RASAeroCommonConstants.ROCKET_DESIGN)
private RocketDesignDTO design;
@XmlElement(name = RASAeroCommonConstants.LAUNCH_SITE)
private LaunchSiteDTO launchSite;
@XmlElement(name = RASAeroCommonConstants.RECOVERY)
private RecoveryDTO recovery;
@XmlElement(name = RASAeroCommonConstants.MACH_ALT)
private String machAlt = ""; // Currently not implemented
@XmlElement(name = RASAeroCommonConstants.SIMULATION_LIST)
private SimulationListDTO simulationList = null;
/**
* Get the subordinate design DTO.
*
* @return the RocketDesignDTO
*/
public RocketDesignDTO getDesign() {
return design;
}
public void setDesign(RocketDesignDTO theDesign) {
this.design = theDesign;
}
public LaunchSiteDTO getLaunchSite() {
return launchSite;
}
public void setLaunchSite(LaunchSiteDTO launchSite) {
this.launchSite = launchSite;
}
public RecoveryDTO getRecovery() {
return recovery;
}
public void setRecovery(RecoveryDTO recovery) {
this.recovery = recovery;
}
public SimulationListDTO getSimulationList() {
return simulationList;
}
public void setSimulationList(SimulationListDTO simulationList) {
this.simulationList = simulationList;
}
public String getMachAlt() {
return this.machAlt;
}
public void setMachAlt(String machAlt) {
this.machAlt = machAlt;
}
public String getVersion() {
return version;
}
}

View File

@ -1,138 +0,0 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.StorageOptions;
import net.sf.openrocket.file.RocketSaver;
import net.sf.openrocket.logging.ErrorSet;
import net.sf.openrocket.logging.WarningSet;
import net.sf.openrocket.rocketcomponent.Rocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
/**
* This class is responsible for marshalling an OpenRocketDocument (OR design) to RASAero-compliant XML.
* Big thanks to hcraigmiller for testing and providing feedback.
*
* @author Sibo Van Gool <sibo.vangool@hotmail.com>
*/
public class RASAeroSaver extends RocketSaver {
/**
* The logger.
*/
private static final Logger log = LoggerFactory.getLogger(RASAeroSaver.class);
public static class RASAeroExportException extends Exception {
public RASAeroExportException(String errorMessage) {
super(errorMessage);
}
}
/**
* This method marshals an OpenRocketDocument (OR design) to RASAero-compliant XML.
*
* @param doc the OR design
* @return RASAero-compliant XML
*/
public String marshalToRASAero(OpenRocketDocument doc, WarningSet warnings, ErrorSet errors) {
try {
JAXBContext binder = JAXBContext.newInstance(RASAeroDocumentDTO.class);
Marshaller marshaller = binder.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
StringWriter sw = new StringWriter();
marshaller.marshal(toRASAeroDocumentDTO(doc, warnings, errors), sw);
return sw.toString();
} catch (RASAeroExportException e) {
errors.add(e.getMessage());
} catch (Exception e) {
log.error("Could not marshall a design to RASAero format. " + e.getMessage());
throw new RuntimeException("Could not marshall a design to RASAero format. " + e.getMessage());
}
throw new RuntimeException("Could not marshall a design to RASAero format.");
}
@Override
public void save(OutputStream dest, OpenRocketDocument doc, StorageOptions options, WarningSet warnings, ErrorSet errors) throws IOException {
log.info("Saving .CDX1 file");
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(dest, StandardCharsets.UTF_8));
writer.write(marshalToRASAero(doc, warnings, errors));
writer.flush();
}
@Override
public long estimateFileSize(OpenRocketDocument doc, StorageOptions options) {
return marshalToRASAero(doc, new WarningSet(), new ErrorSet()).length();
}
/**
* Root conversion method. It iterates over all subcomponents.
*
* @param doc the OR design
* @param warnings list to add export warnings to
* @param errors list to add export errors to
* @return a corresponding RASAero representation
*/
private RASAeroDocumentDTO toRASAeroDocumentDTO(OpenRocketDocument doc, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
RASAeroDocumentDTO rad = new RASAeroDocumentDTO();
rad.setDesign(toRocketDesignDTO(doc.getRocket(), warnings, errors));
rad.setLaunchSite(toLaunchSiteDTO(doc, warnings, errors));
rad.setRecovery(toRecoveryDTO(doc.getRocket(), warnings, errors));
rad.setSimulationList(toSimulationListDTO(doc, warnings, errors));
return rad;
}
/**
* Create the RASAero rocket design (containing all the actual rocket components).
* @param rocket the OR rocket to export the components from
* @return the RASAero rocket design
*/
private RocketDesignDTO toRocketDesignDTO(Rocket rocket, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
return new RocketDesignDTO(rocket, warnings, errors);
}
/**
* Create RASAero launch site settings.
* @param document document that contains simulations to take the launch site settings from
* @param warnings list to add export warnings to
* @param errors list to add export errors to
* @return the RASAero launch site settings
*/
private LaunchSiteDTO toLaunchSiteDTO(OpenRocketDocument document, WarningSet warnings, ErrorSet errors) {
return new LaunchSiteDTO(document, warnings, errors);
}
/**
* Create RASAero recovery settings.
* @param rocket rocket to fetch the recovery devices from
* @param warnings list to add export warnings to
* @param errors list to add export errors to
* @return the RASAero launch site settings
*/
private RecoveryDTO toRecoveryDTO(Rocket rocket, WarningSet warnings, ErrorSet errors) {
return new RecoveryDTO(rocket, warnings, errors);
}
/**
* Create a list of simulations.
* @param document document that contains simulations
* @param warnings list to add export warnings to
* @param errors list to add export errors to
* @return the RASAero simulation list
*/
private SimulationListDTO toSimulationListDTO(OpenRocketDocument document, WarningSet warnings, ErrorSet errors) {
return new SimulationListDTO(document, warnings, errors);
}
}

View File

@ -1,245 +0,0 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.CustomBooleanAdapter;
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.ErrorSet;
import net.sf.openrocket.logging.WarningSet;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
import net.sf.openrocket.rocketcomponent.Parachute;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.startup.Application;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.LinkedList;
import java.util.List;
@XmlRootElement(name = RASAeroCommonConstants.RECOVERY)
@XmlAccessorType(XmlAccessType.FIELD)
public class RecoveryDTO {
@XmlElement(name = RASAeroCommonConstants.RECOVERY_ALTITUDE + 1)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double altitude1 = 0d;
@XmlElement(name = RASAeroCommonConstants.RECOVERY_ALTITUDE + 2)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double altitude2 = 0d;
@XmlElement(name = RASAeroCommonConstants.RECOVERY_DEVICE_TYPE + 1)
private String deviceType1 = "None";
@XmlElement(name = RASAeroCommonConstants.RECOVERY_DEVICE_TYPE + 2)
private String deviceType2 = "None";
@XmlElement(name = RASAeroCommonConstants.RECOVERY_EVENT + 1)
@XmlJavaTypeAdapter(CustomBooleanAdapter.class)
private Boolean event1 = false;
@XmlElement(name = RASAeroCommonConstants.RECOVERY_EVENT + 2)
@XmlJavaTypeAdapter(CustomBooleanAdapter.class)
private Boolean event2 = false;
@XmlElement(name = RASAeroCommonConstants.RECOVERY_SIZE + 1)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double size1 = 0d;
@XmlElement(name = RASAeroCommonConstants.RECOVERY_SIZE + 2)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double size2 = 0d;
@XmlElement(name = RASAeroCommonConstants.RECOVERY_EVENT_TYPE + 1)
private String eventType1 = "None";
@XmlElement(name = RASAeroCommonConstants.RECOVERY_EVENT_TYPE + 2)
private String eventType2 = "None";
@XmlElement(name = RASAeroCommonConstants.RECOVERY_CD + 1)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double CD1 = 0d;
@XmlElement(name = RASAeroCommonConstants.RECOVERY_CD + 2)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double CD2 = 0d;
@XmlTransient
private static final Logger log = LoggerFactory.getLogger(RecoveryDTO.class);
@XmlTransient
private static final Translator trans = Application.getTranslator();
/**
* We need a default, no-args constructor.
*/
public RecoveryDTO() {
}
public RecoveryDTO(Rocket rocket, WarningSet warnings, ErrorSet errors) {
List<Parachute> parachutes = getParachutesFromRocket(rocket);
switch (parachutes.size()) {
case 0:
log.debug("No parachutes present");
break;
case 1:
configureRecoveryDevice1(parachutes.get(0), errors);
break;
case 2:
configureRecoveryDevice1(parachutes.get(0), errors);
configureRecoveryDevice2(parachutes.get(1), errors);
break;
}
}
private List<Parachute> getParachutesFromRocket(Rocket rocket) {
List<Parachute> parachutes = new LinkedList<>();
for (int i = 0; i < Math.min(rocket.getChildCount(), 3); i++) {
AxialStage stage = (AxialStage) rocket.getChild(i);
for (RocketComponent stageChild : stage.getChildren()) {
if (stageChild instanceof BodyTube) {
for (RocketComponent child : stageChild) {
if (child instanceof Parachute) {
parachutes.add((Parachute) child);
if (parachutes.size() == 2) {
return parachutes;
}
}
}
}
}
}
return parachutes;
}
private void configureRecoveryDevice1(Parachute device1, ErrorSet errors) {
setCD1(device1.getCD());
setDeviceType1("Parachute");
DeploymentConfiguration deployConfig = device1.getDeploymentConfigurations().getDefault();
setAltitude1(deployConfig.getDeployAltitude() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_ALTITUDE);
if (deployConfig.getDeployEvent() == DeploymentConfiguration.DeployEvent.APOGEE) {
setEventType1(RASAeroCommonConstants.DEPLOYMENT_APOGEE);
} else if (deployConfig.getDeployEvent() == DeploymentConfiguration.DeployEvent.ALTITUDE) {
setEventType1(RASAeroCommonConstants.RECOVERY_ALTITUDE);
} else {
errors.add(String.format(trans.get("RASAeroExport.error21"),
device1.getName(), deployConfig.getDeployEvent().toString()));
}
setEvent1(true);
setSize1(device1.getDiameter() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
}
private void configureRecoveryDevice2(Parachute device2, ErrorSet errors) {
setCD1(device2.getCD());
setDeviceType2("Parachute");
DeploymentConfiguration deployConfig = device2.getDeploymentConfigurations().getDefault();
setAltitude2(deployConfig.getDeployAltitude() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_ALTITUDE);
if (deployConfig.getDeployEvent() == DeploymentConfiguration.DeployEvent.APOGEE) {
setEventType2(RASAeroCommonConstants.DEPLOYMENT_APOGEE);
} else if (deployConfig.getDeployEvent() == DeploymentConfiguration.DeployEvent.ALTITUDE) {
setEventType2(RASAeroCommonConstants.RECOVERY_ALTITUDE);
} else {
errors.add(String.format(trans.get("RASAeroExport.error21"),
device2.getName(), deployConfig.getDeployEvent().toString()));
}
setEvent2(true);
setSize2(device2.getDiameter() * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
}
public Double getAltitude1() {
return altitude1;
}
public void setAltitude1(Double altitude1) {
this.altitude1 = altitude1;
}
public Double getAltitude2() {
return altitude2;
}
public void setAltitude2(Double altitude2) {
this.altitude2 = altitude2;
}
public String getDeviceType1() {
return deviceType1;
}
public void setDeviceType1(String deviceType1) {
this.deviceType1 = deviceType1;
}
public String getDeviceType2() {
return deviceType2;
}
public void setDeviceType2(String deviceType2) {
this.deviceType2 = deviceType2;
}
public Boolean getEvent1() {
return event1;
}
public void setEvent1(Boolean event1) {
this.event1 = event1;
}
public Boolean getEvent2() {
return event2;
}
public void setEvent2(Boolean event2) {
this.event2 = event2;
}
public Double getSize1() {
return size1;
}
public void setSize1(Double size1) {
this.size1 = size1;
}
public Double getSize2() {
return size2;
}
public void setSize2(Double size2) {
this.size2 = size2;
}
public String getEventType1() {
return eventType1;
}
public void setEventType1(String eventType1) {
this.eventType1 = eventType1;
}
public String getEventType2() {
return eventType2;
}
public void setEventType2(String eventType2) {
this.eventType2 = eventType2;
}
public Double getCD1() {
return CD1;
}
public void setCD1(Double CD1) {
this.CD1 = CD1;
}
public Double getCD2() {
return CD2;
}
public void setCD2(Double CD2) {
this.CD2 = CD2;
}
}

View File

@ -1,229 +0,0 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.CustomBooleanAdapter;
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.ErrorSet;
import net.sf.openrocket.logging.WarningSet;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.NoseCone;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.ArrayList;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementRefs;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.List;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
@XmlAccessorType(XmlAccessType.FIELD)
public class RocketDesignDTO {
@XmlElementRefs({
@XmlElementRef(name = RASAeroCommonConstants.BODY_TUBE, type = BodyTubeDTO.class),
@XmlElementRef(name = RASAeroCommonConstants.NOSE_CONE, type = NoseConeDTO.class),
@XmlElementRef(name = RASAeroCommonConstants.TRANSITION, type = TransitionDTO.class),
@XmlElementRef(name = RASAeroCommonConstants.BOOSTER, type = BoosterDTO.class)
})
private final List<BasePartDTO> externalPart = new ArrayList<>();
@XmlElementRefs({
@XmlElementRef(name = RASAeroCommonConstants.BOOSTER, type = BoosterDTO.class),
})
private final List<BoosterDTO> boosters = new ArrayList<>();
@XmlElement(name = RASAeroCommonConstants.SURFACE_FINISH)
private String surface = RASAeroCommonConstants.FINISH_SMOOTH;
@XmlElement(name = RASAeroCommonConstants.CD)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double CD = 0d;
@XmlElement(name = RASAeroCommonConstants.MODIFIED_BARROWMAN)
@XmlJavaTypeAdapter(CustomBooleanAdapter.class)
private Boolean modifiedBarrowman = false;
@XmlElement(name = RASAeroCommonConstants.TURBULENCE)
@XmlJavaTypeAdapter(CustomBooleanAdapter.class)
private Boolean turbulence = false;
@XmlElement(name = RASAeroCommonConstants.SUSTAINER_NOZZLE)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double sustainerNozzle = 0d;
@XmlElement(name = RASAeroCommonConstants.BOOSTER1_NOZZLE)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double booster1Nozzle = 0d;
@XmlElement(name = RASAeroCommonConstants.BOOSTER2_NOZZLE)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double booster2Nozzle = 0d;
@XmlElement(name = RASAeroCommonConstants.USE_BOOSTER1)
@XmlJavaTypeAdapter(CustomBooleanAdapter.class)
private Boolean useBooster1 = false;
@XmlElement(name = RASAeroCommonConstants.USE_BOOSTER2)
@XmlJavaTypeAdapter(CustomBooleanAdapter.class)
private Boolean useBooster2 = false;
@XmlElement(name = RASAeroCommonConstants.COMMENTS)
private String comments = "";
@XmlTransient
private static final Translator trans = Application.getTranslator();
public RocketDesignDTO(Rocket rocket, WarningSet warnings, ErrorSet errors) {
setComments(rocket.getComment());
if (rocket.getChildCount() > 3) {
warnings.add(trans.get("RASAeroExport.warning10"));
}
setUseBooster1(rocket.getChildCount() >= 2);
setUseBooster2(rocket.getChildCount() == 3);
AxialStage sustainer = rocket.getStage(0);
// Export components from sustainer
for (int i = 0; i < sustainer.getChildCount(); i++) {
try {
RocketComponent component = sustainer.getChild(i);
if (i == 0 && !(component instanceof NoseCone)) {
errors.add(trans.get("RASAeroExport.error22"));
return;
} else if (i == 1 && !(component instanceof BodyTube ||
(component instanceof Transition && !(component instanceof NoseCone) && (i == sustainer.getChildCount() - 1)))) {
errors.add(trans.get("RASAeroExport.error23"));
return;
}
if (component instanceof BodyTube) {
addExternalPart(new BodyTubeDTO((BodyTube) component, warnings, errors));
} else if (component instanceof NoseCone) {
if (i != 0) {
errors.add(trans.get("RASAeroExport.error24"));
return;
}
addExternalPart(new NoseConeDTO((NoseCone) component, warnings, errors));
// Set the global surface finish to that of the first nose cone
setSurface(RASAeroCommonConstants.OPENROCKET_TO_RASAERO_SURFACE(((NoseCone) component).getFinish(),
warnings));
} else if (component instanceof Transition) {
// If there is only a sustainer & this is the last child of the sustainer, it's a boattail
if (rocket.getChildCount() == 1 && (i == sustainer.getChildCount() - 1)) {
addExternalPart(new BoattailDTO((Transition) component, warnings, errors));
} else {
addExternalPart(new TransitionDTO((Transition) component, warnings, errors));
}
} else {
throw new RASAeroExportException(String.format(trans.get("RASAeroExport.error33"), component.getComponentName()));
}
} catch (RASAeroExportException e) {
errors.add(e.getMessage());
}
}
// Export components from other stages
for (int i = 1; i < Math.min(rocket.getChildCount(), 3); i++) {
try {
addBooster(new BoosterDTO(rocket, (AxialStage) rocket.getChild(i), warnings, errors));
} catch (RASAeroExportException e) {
errors.add(e.getMessage());
}
}
}
public String getSurface() {
return surface;
}
public void setSurface(String surface) {
this.surface = surface;
}
public double getCD() {
return CD;
}
public void setCD(double CD) {
this.CD = CD;
}
public boolean isModifiedBarrowman() {
return modifiedBarrowman;
}
public void setModifiedBarrowman(boolean modifiedBarrowman) {
this.modifiedBarrowman = modifiedBarrowman;
}
public Boolean isTurbulence() {
return turbulence;
}
public void setTurbulence(Boolean turbulence) {
this.turbulence = turbulence;
}
public Double getSustainerNozzle() {
return sustainerNozzle;
}
public void setSustainerNozzle(Double sustainerNozzle) {
this.sustainerNozzle = sustainerNozzle;
}
public Double getBooster1Nozzle() {
return booster1Nozzle;
}
public void setBooster1Nozzle(Double booster1Nozzle) {
this.booster1Nozzle = booster1Nozzle;
}
public Double getBooster2Nozzle() {
return booster2Nozzle;
}
public void setBooster2Nozzle(Double booster2Nozzle) {
this.booster2Nozzle = booster2Nozzle;
}
public Boolean isUseBooster1() {
return useBooster1;
}
public void setUseBooster1(Boolean useBooster1) {
this.useBooster1 = useBooster1;
}
public Boolean isUseBooster2() {
return useBooster2;
}
public void setUseBooster2(Boolean useBooster2) {
this.useBooster2 = useBooster2;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
public List<BasePartDTO> getExternalPart() {
return externalPart;
}
public void addExternalPart(BasePartDTO theExternalPartDTO) {
externalPart.add(theExternalPartDTO);
}
public List<BoosterDTO> getBoosters() {
return boosters;
}
public void addBooster(BoosterDTO boosterDTO) {
boosters.add(boosterDTO);
}
}

View File

@ -1,496 +0,0 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.file.rasaero.CustomBooleanAdapter;
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.ErrorSet;
import net.sf.openrocket.logging.WarningSet;
import net.sf.openrocket.masscalc.MassCalculator;
import net.sf.openrocket.masscalc.RigidBody;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.MotorConfiguration;
import net.sf.openrocket.motor.ThrustCurveMotor;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.FlightConfigurationId;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.StageSeparationConfiguration;
import net.sf.openrocket.startup.Application;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.List;
import java.util.Map;
@XmlRootElement(name = RASAeroCommonConstants.SIMULATION)
@XmlAccessorType(XmlAccessType.FIELD)
public class SimulationDTO {
@XmlElement(name = RASAeroCommonConstants.SUSTAINER_ENGINE)
private String sustainerEngine;
@XmlElement(name = RASAeroCommonConstants.SUSTAINER_LAUNCH_WT)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double sustainerLaunchWt = 0d;
@XmlElement(name = RASAeroCommonConstants.SUSTAINER_NOZZLE_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double sustainerNozzleDiameter = 0d;
@XmlElement(name = RASAeroCommonConstants.SUSTAINER_CG)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double sustainerCG = 0d;
@XmlElement(name = RASAeroCommonConstants.SUSTAINER_IGNITION_DELAY)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double sustainerIgnitionDelay = 0d;
@XmlElement(name = RASAeroCommonConstants.BOOSTER1_ENGINE)
private String booster1Engine;
@XmlElement(name = RASAeroCommonConstants.BOOSTER1_LAUNCH_WT)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double booster1LaunchWt = 0d;
@XmlElement(name = RASAeroCommonConstants.BOOSTER1_SEPARATION_DELAY)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double booster1SeparationDelay = 0d;
@XmlElement(name = RASAeroCommonConstants.BOOSTER1_IGNITION_DELAY)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double booster1IgnitionDelay = 0d;
@XmlElement(name = RASAeroCommonConstants.BOOSTER1_CG)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double booster1CG = 0d;
@XmlElement(name = RASAeroCommonConstants.BOOSTER1_NOZZLE_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double booster1NozzleDiameter = 0d;
@XmlElement(name = RASAeroCommonConstants.INCLUDE_BOOSTER1)
@XmlJavaTypeAdapter(CustomBooleanAdapter.class)
private Boolean includeBooster1 = false;
@XmlElement(name = RASAeroCommonConstants.BOOSTER2_ENGINE)
private String booster2Engine;
@XmlElement(name = RASAeroCommonConstants.BOOSTER2_LAUNCH_WT)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double booster2LaunchWt = 0d;
@XmlElement(name = RASAeroCommonConstants.BOOSTER2_SEPARATION_DELAY)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double booster2Delay = 0d;
@XmlElement(name = RASAeroCommonConstants.BOOSTER2_CG)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double booster2CG = 0d;
@XmlElement(name = RASAeroCommonConstants.BOOSTER2_NOZZLE_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double booster2NozzleDiameter = 0d;
@XmlElement(name = RASAeroCommonConstants.INCLUDE_BOOSTER2)
@XmlJavaTypeAdapter(CustomBooleanAdapter.class)
private Boolean includeBooster2 = false;
@XmlElement(name = RASAeroCommonConstants.FLIGHT_TIME)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double flightTime = 0d;
@XmlElement(name = RASAeroCommonConstants.TIME_TO_APOGEE)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double timetoApogee = 0d;
@XmlElement(name = RASAeroCommonConstants.MAX_ALTITUDE)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double maxAltitude = 0d;
@XmlElement(name = RASAeroCommonConstants.MAX_VELOCITY)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double maxVelocity = 0d;
@XmlElement(name = RASAeroCommonConstants.OPTIMUM_WT)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double optimumWt = 0d;
@XmlElement(name = RASAeroCommonConstants.OPTIMUM_MAX_ALT)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double optimumMaxAlt = 0d;
@XmlTransient
private static final Translator trans = Application.getTranslator();
/**
* We need a default, no-args constructor.
*/
public SimulationDTO() {
}
/**
* RASAero Simulation object.
* @param rocket the rocket
* @param simulation the simulation to convert
* @param mounts a map of stages and their corresponding motor mount (only 1 mount per stage allowed)
* if a motor mount is null, it means that stage does not have any motors, but mass/CG export should still take place
* @param motors a list of RASAero motors
* @param warnings a list to add export warnings to
* @param errors a list to add export errors to
*/
public SimulationDTO(Rocket rocket, Simulation simulation, Map<AxialStage, MotorMount> mounts, List<ThrustCurveMotor> motors,
WarningSet warnings, ErrorSet errors) {
String simulationName = simulation != null ? simulation.getName() : "DEFAULT";
FlightConfigurationId fcid = simulation != null ? simulation.getFlightConfigurationId() : null;
if (simulation != null && fcid == null) {
warnings.add(String.format(trans.get("RASAeroExport.warning11"), simulationName));
return;
}
if (mounts.isEmpty()) {
warnings.add(String.format(trans.get("RASAeroExport.warning12"), simulationName));
return;
}
// Get sustainer motor mass
MotorMount sustainerMount = mounts.get((AxialStage) rocket.getChild(0));
Motor sustainerMotor = null;
double sustainerMotorMass = 0;
if (sustainerMount != null) {
MotorConfiguration sustainerConfig = sustainerMount.getMotorConfig(fcid);
sustainerMotor = sustainerConfig.getMotor();
sustainerMotorMass = sustainerMotor != null ? sustainerMotor.getLaunchMass() : 0;
}
for (Map.Entry<AxialStage, MotorMount> mountSet : mounts.entrySet()) {
AxialStage stage = mountSet.getKey();
MotorMount mount = mountSet.getValue();
if (stage == null) {
continue;
}
// Get the motor info for this stage
MotorConfiguration motorConfig = mount != null ? mount.getMotorConfig(fcid) : null;
Motor motor = null;
StageSeparationConfiguration separationConfig = null;
double motorMass = 0;
if (motorConfig != null) {
motor = motorConfig.getMotor();
motorMass = motor != null ? motor.getLaunchMass() : 0;
separationConfig = stage.getSeparationConfigurations().get(fcid);
}
int stageNr = rocket.getChildPosition(stage);
// Add friendly reminder to user
if (motor == null) {
warnings.add(String.format(trans.get("RASAeroExport.warning13"), stage.getName()));
}
// Add the simulation info for each stage
FlightConfiguration CGCalcConfig = new FlightConfiguration(rocket);
RigidBody calc;
double ignitionDelay, totalCG, separationDelay;
switch (stageNr) {
// Sustainer
case 0:
setSustainerEngine(RASAeroCommonConstants.OPENROCKET_TO_RASAERO_MOTOR(motors, motor, warnings));
// Calculate mass & CG of sustainer
CGCalcConfig.setOnlyStage(0);
calc = MassCalculator.calculateStructure(CGCalcConfig);
// Set mass
double sustainerMass = calc.getMass() + motorMass;
setSustainerLaunchWt(sustainerMass * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_WEIGHT);
// Set CG
double sustainerCG = calc.getCM().x; // = sutainer CG with no motors
sustainerCG = addMotorCGToStageCG(sustainerCG, calc.getMass(), mount, motor, fcid);
setSustainerCG(sustainerCG * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
// Set ignition delay
ignitionDelay = motorConfig != null ? motorConfig.getIgnitionDelay() : 0;
setSustainerIgnitionDelay(ignitionDelay);
break;
// Booster 1
case 1:
setBooster1Engine(RASAeroCommonConstants.OPENROCKET_TO_RASAERO_MOTOR(motors, motor, warnings));
// Calculate mass & CG of sustainer + booster 1 combined
CGCalcConfig.setOnlyStage(0);
for (int i = 1; i <= stage.getStageNumber(); i++) {
CGCalcConfig._setStageActive(i, true);
}
calc = MassCalculator.calculateStructure(CGCalcConfig);
// Set mass
double booster1Mass = calc.getMass() + motorMass + sustainerMotorMass;
setBooster1LaunchWt(booster1Mass * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_WEIGHT);
// Set CG
totalCG = calc.getCM().x; // = sustainer + booster 1 CG with no sustainer & booster & motors
totalCG = addMotorCGToStageCG(totalCG, calc.getMass(), sustainerMount, sustainerMotor, fcid);
totalCG = addMotorCGToStageCG(totalCG, calc.getMass() + sustainerMotorMass, mount, motor, fcid);
setBooster1CG(totalCG * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
// Set ignition delay
ignitionDelay = motorConfig != null ? motorConfig.getIgnitionDelay() : 0;
setBooster1IgnitionDelay(ignitionDelay);
// Set separation delay
separationDelay = separationConfig != null ? separationConfig.getSeparationDelay() : 0;
setBooster1SeparationDelay(separationDelay); // TODO: this could be handled a bit better (look at separation delay, upper stage ignition event etc.)
setIncludeBooster1(mount != null && mount.isMotorMount());
break;
// Booster 2
case 2:
setBooster2Engine(RASAeroCommonConstants.OPENROCKET_TO_RASAERO_MOTOR(motors, motor, warnings));
// Calculate mass & CG of sustainer + booster 1 + booster 2 combined
CGCalcConfig.setOnlyStage(0);
for (int i = 1; i <= stage.getStageNumber(); i++) {
CGCalcConfig._setStageActive(i, true);
}
calc = MassCalculator.calculateStructure(CGCalcConfig);
// Get booster1 motor mass
double booster1MotorMass = 0;
MotorMount booster1Mount = mounts.get((AxialStage) rocket.getChild(1));
Motor booster1Motor = null;
if (booster1Mount != null) {
MotorConfiguration booster1Config = booster1Mount.getMotorConfig(fcid);
booster1Motor = booster1Config.getMotor();
booster1MotorMass = booster1Motor != null ? booster1Motor.getLaunchMass() : 0;
}
// Set mass
double booster2Mass = calc.getMass() + motorMass + sustainerMotorMass + booster1MotorMass;
setBooster2LaunchWt(booster2Mass * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_WEIGHT);
// Set CG
totalCG = calc.getCM().x; // CG of sustainer + booster 1 + booster 2 combined, with no sustainer, booster1 and booster2 motors!
totalCG = addMotorCGToStageCG(totalCG, calc.getMass(), sustainerMount, sustainerMotor, fcid);
totalCG = addMotorCGToStageCG(totalCG, calc.getMass() + sustainerMotorMass, booster1Mount, booster1Motor, fcid);
totalCG = addMotorCGToStageCG(totalCG, calc.getMass() + sustainerMotorMass + booster1MotorMass, mount, motor, fcid);
setBooster2CG(totalCG * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
// Set separation delay
separationDelay = separationConfig != null ? separationConfig.getSeparationDelay() : 0;
setBooster2Delay(separationDelay); // TODO: this could be handled a bit better (look at separation delay, upper stage ignition event etc.)
setIncludeBooster2(mount != null && mount.isMotorMount());
break;
// Invalid
default:
errors.add(String.format(trans.get("RASAeroExport.error25"), stageNr, simulationName));
}
}
}
/**
* Combines the stage CG with the CG of the motor in that stage.
* @param stageCG The CG of the stage
* @param mount The motor mount of the stage
* @param motor The motor in the stage
* @return The combined CG
*/
private double addMotorCGToStageCG(double stageCG, double stageMass, MotorMount mount, Motor motor, FlightConfigurationId fcid) {
if (mount == null || !(motor instanceof ThrustCurveMotor)) {
return stageCG;
}
// Calculate the motor CG
double motorPositionXRel = mount.getMotorPosition(fcid).x; // Motor position relative to the mount
double mountLocationX = mount.getLocations()[0].x;
double motorLocationX = mountLocationX + motorPositionXRel;
double motorCG = ((ThrustCurveMotor) motor).getCGPoints()[0].x + motorLocationX;
double motorMass = motor.getLaunchMass();
return (stageCG*stageMass + motorCG*motorMass) / (stageMass + motorMass);
}
public String getSustainerEngine() {
return sustainerEngine;
}
public void setSustainerEngine(String sustainerEngine) {
this.sustainerEngine = sustainerEngine;
}
public Double getSustainerLaunchWt() {
return sustainerLaunchWt;
}
public void setSustainerLaunchWt(Double sustainerLaunchWt) {
this.sustainerLaunchWt = sustainerLaunchWt;
}
public Double getSustainerNozzleDiameter() {
return sustainerNozzleDiameter;
}
public void setSustainerNozzleDiameter(Double sustainerNozzleDiameter) {
this.sustainerNozzleDiameter = sustainerNozzleDiameter;
}
public Double getSustainerCG() {
return sustainerCG;
}
public void setSustainerCG(Double sustainerCG) {
this.sustainerCG = sustainerCG;
}
public Double getSustainerIgnitionDelay() {
return sustainerIgnitionDelay;
}
public void setSustainerIgnitionDelay(Double sustainerIgnitionDelay) {
this.sustainerIgnitionDelay = sustainerIgnitionDelay;
}
public String getBooster1Engine() {
return booster1Engine;
}
public void setBooster1Engine(String booster1Engine) {
this.booster1Engine = booster1Engine;
}
public Double getBooster1LaunchWt() {
return booster1LaunchWt;
}
public void setBooster1LaunchWt(Double booster1LaunchWt) {
this.booster1LaunchWt = booster1LaunchWt;
}
public Double getBooster1SeparationDelay() {
return booster1SeparationDelay;
}
public void setBooster1SeparationDelay(Double booster1SeparationDelay) {
this.booster1SeparationDelay = booster1SeparationDelay;
}
public Double getBooster1IgnitionDelay() {
return booster1IgnitionDelay;
}
public void setBooster1IgnitionDelay(Double booster1IgnitionDelay) {
this.booster1IgnitionDelay = booster1IgnitionDelay;
}
public Double getBooster1CG() {
return booster1CG;
}
public void setBooster1CG(Double booster1CG) {
this.booster1CG = booster1CG;
}
public Double getBooster1NozzleDiameter() {
return booster1NozzleDiameter;
}
public void setBooster1NozzleDiameter(Double booster1NozzleDiameter) {
this.booster1NozzleDiameter = booster1NozzleDiameter;
}
public Boolean getIncludeBooster1() {
return includeBooster1;
}
public void setIncludeBooster1(Boolean includeBooster1) {
this.includeBooster1 = includeBooster1;
}
public String getBooster2Engine() {
return booster2Engine;
}
public void setBooster2Engine(String booster2Engine) {
this.booster2Engine = booster2Engine;
}
public Double getBooster2LaunchWt() {
return booster2LaunchWt;
}
public void setBooster2LaunchWt(Double booster2LaunchWt) {
this.booster2LaunchWt = booster2LaunchWt;
}
public Double getBooster2Delay() {
return booster2Delay;
}
public void setBooster2Delay(Double booster2Delay) {
this.booster2Delay = booster2Delay;
}
public Double getBooster2CG() {
return booster2CG;
}
public void setBooster2CG(Double booster2CG) {
this.booster2CG = booster2CG;
}
public Double getBooster2NozzleDiameter() {
return booster2NozzleDiameter;
}
public void setBooster2NozzleDiameter(Double booster2NozzleDiameter) {
this.booster2NozzleDiameter = booster2NozzleDiameter;
}
public Boolean getIncludeBooster2() {
return includeBooster2;
}
public void setIncludeBooster2(Boolean includeBooster2) {
this.includeBooster2 = includeBooster2;
}
public Double getFlightTime() {
return flightTime;
}
public void setFlightTime(Double flightTime) {
this.flightTime = flightTime;
}
public Double getTimetoApogee() {
return timetoApogee;
}
public void setTimetoApogee(Double timetoApogee) {
this.timetoApogee = timetoApogee;
}
public Double getMaxAltitude() {
return maxAltitude;
}
public void setMaxAltitude(Double maxAltitude) {
this.maxAltitude = maxAltitude;
}
public Double getMaxVelocity() {
return maxVelocity;
}
public void setMaxVelocity(Double maxVelocity) {
this.maxVelocity = maxVelocity;
}
public Double getOptimumWt() {
return optimumWt;
}
public void setOptimumWt(Double optimumWt) {
this.optimumWt = optimumWt;
}
public Double getOptimumMaxAlt() {
return optimumMaxAlt;
}
public void setOptimumMaxAlt(Double optimumMaxAlt) {
this.optimumMaxAlt = optimumMaxAlt;
}
}

View File

@ -1,102 +0,0 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.file.rasaero.RASAeroMotorsLoader;
import net.sf.openrocket.logging.ErrorSet;
import net.sf.openrocket.logging.WarningSet;
import net.sf.openrocket.motor.ThrustCurveMotor;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.BodyTube;
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@XmlRootElement(name = RASAeroCommonConstants.SIMULATION_LIST)
@XmlAccessorType(XmlAccessType.FIELD)
public class SimulationListDTO {
@XmlElement(name = RASAeroCommonConstants.SIMULATION)
private final List<SimulationDTO> simulations = new LinkedList<>();
/**
* We need a default, no-args constructor.
*/
public SimulationListDTO() {
}
public SimulationListDTO(OpenRocketDocument document, WarningSet warnings, ErrorSet errors) {
Map<AxialStage, MotorMount> mounts = new HashMap<>();
Rocket rocket = document.getRocket();
// Fetch all the motor mounts from the design
for (RocketComponent child : rocket.getChildren()) {
AxialStage stage = (AxialStage) child;
if (mounts.containsKey(stage)) {
continue;
}
for (RocketComponent stageChild : stage.getChildren()) {
if (stageChild instanceof BodyTube) {
// First check if the body tube itself has a motor
if (((BodyTube) stageChild).hasMotor()) {
mounts.put(stage, (BodyTube) stageChild);
break;
}
// Then check if it has an inner tube with a motor
else {
boolean addedMount = false;
for (RocketComponent tubeChild : stageChild.getChildren()) {
if (tubeChild instanceof MotorMount && ((MotorMount) tubeChild).hasMotor()) {
mounts.put(stage, (MotorMount) tubeChild);
addedMount = true;
break;
}
}
if (addedMount) {
break;
}
}
}
}
// If at this point, we still don't have a mount, there is probably a mount without a motor.
// In that case, add a null mount, so that mass/CG export happens.
if (!mounts.containsKey(stage)) {
mounts.put(stage, null);
}
}
// Load all RASAero motors
List<ThrustCurveMotor> motors = RASAeroMotorsLoader.loadAllRASAeroMotors(warnings);
// Add all the simulations
for (Simulation simulation : document.getSimulations()) {
addSimulation(new SimulationDTO(rocket, simulation, mounts, motors, warnings, errors));
}
// If there are no simulations, add a default simulation (to have the mass/CG export)
if (document.getSimulations().size() == 0) {
addSimulation(new SimulationDTO(rocket, null, mounts, motors, warnings, errors));
}
motors.clear();
}
public List<SimulationDTO> getSimulations() {
return simulations;
}
public void addSimulation(SimulationDTO simulation) {
simulations.add(simulation);
}
}

View File

@ -1,84 +0,0 @@
package net.sf.openrocket.file.rasaero.export;
import net.sf.openrocket.file.rasaero.CustomDoubleAdapter;
import net.sf.openrocket.file.rasaero.RASAeroCommonConstants;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.ErrorSet;
import net.sf.openrocket.logging.WarningSet;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import net.sf.openrocket.file.rasaero.export.RASAeroSaver.RASAeroExportException;
import net.sf.openrocket.rocketcomponent.SymmetricComponent;
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.MathUtil;
@XmlRootElement(name = RASAeroCommonConstants.TRANSITION)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = {
"partType",
"length",
"diameter",
"rearDiameter",
"location",
"color"
})
@XmlSeeAlso({BoattailDTO.class})
public class TransitionDTO extends BasePartDTO {
@XmlElement(name = RASAeroCommonConstants.REAR_DIAMETER)
@XmlJavaTypeAdapter(CustomDoubleAdapter.class)
private Double rearDiameter;
@XmlTransient
private static final Translator trans = Application.getTranslator();
@XmlTransient
private static Transition component = null;
/**
* We need a default no-args constructor.
*/
public TransitionDTO() {
}
public TransitionDTO(Transition transition, WarningSet warnings, ErrorSet errors) throws RASAeroExportException {
super(transition, warnings, errors);
component = transition;
if (!transition.getShapeType().equals(Transition.Shape.CONICAL)) {
throw new RASAeroExportException(trans.get("RASAeroExport.error26"));
}
SymmetricComponent previousComp = transition.getPreviousSymmetricComponent();
if (previousComp == null) {
throw new RASAeroExportException(String.format(trans.get("RASAeroExport.error27"), transition.getName()));
}
if (!MathUtil.equals(transition.getForeRadius(), previousComp.getAftRadius())) {
throw new RASAeroExportException(
String.format(trans.get("RASAeroExport.error28"),
transition.getName(), previousComp.getAftRadius(), transition.getForeRadius()));
}
setRearDiameter(transition.getAftRadius() * 2 * RASAeroCommonConstants.OPENROCKET_TO_RASAERO_LENGTH);
}
public Double getRearDiameter() {
return rearDiameter;
}
public void setRearDiameter(Double rearDiameter) throws RASAeroExportException {
if (rearDiameter < 0.0001) {
throw new RASAeroExportException(String.format("'%s' rear diameter must be greater than 0.0001 inch", component));
}
this.rearDiameter = rearDiameter;
}
}

View File

@ -1,59 +0,0 @@
package net.sf.openrocket.logging;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.startup.Application;
/**
* An error message wrapper.
*/
public abstract class Error extends Message {
private static final Translator trans = Application.getTranslator();
/**
* @return an Error with the specific text.
*/
public static Error fromString(String text) {
return new Error.Other(text);
}
///////////// Specific Error classes /////////////
/**
* An unspecified error type. This error type holds a <code>String</code>
* describing it. Two errors of this type are considered equal if the strings
* are identical.
*/
public static class Other extends Error {
private final String description;
public Other(String description) {
this.description = description;
}
@Override
public String toString() {
return description;
}
@Override
public boolean equals(Object other) {
if (!(other instanceof Other))
return false;
Other o = (Other) other;
return (o.description.equals(this.description));
}
@Override
public int hashCode() {
return description.hashCode();
}
@Override
public boolean replaceBy(Message other) {
return false;
}
}
}

View File

@ -1,32 +0,0 @@
package net.sf.openrocket.logging;
import net.sf.openrocket.util.BugException;
public class ErrorSet extends MessageSet<Error> {
/**
* Add an <code>Error</code> with the specified text to the set. The Error object
* is created using the {@link Error#fromString(String)} method. If an error of the
* same type exists in the set, the error that is left in the set is defined by the
* method {@link Error#replaceBy(Message)}.
*
* @param s the message text.
* @throws IllegalStateException if this message set has been made immutable.
*/
public boolean add(String s) {
mutable.check();
return add(Error.fromString(s));
}
@Override
public ErrorSet clone() {
try {
ErrorSet newSet = (ErrorSet) super.clone();
newSet.messages = this.messages.clone();
newSet.mutable = this.mutable.clone();
return newSet;
} catch (CloneNotSupportedException e) {
throw new BugException("CloneNotSupportedException occurred, report bug!", e);
}
}
}

View File

@ -1,43 +0,0 @@
package net.sf.openrocket.logging;
/**
* Baseclass for logging messages (warnings, errors...)
*/
public abstract class Message {
/**
* @return a Message with the specific text.
*/
public static Message fromString(String text) {
return new Warning.Other(text);
}
/**
* Return <code>true</code> if the <code>other</code> warning should replace
* this message. The method should return <code>true</code> if the other
* indicates a "worse" condition than the current warning.
*
* @param other the message to compare to
* @return whether this message should be replaced
*/
public abstract boolean replaceBy(Message other);
/**
* Two <code>Message</code>s are by default considered equal if they are of
* the same class. Therefore only one instance of a particular message type
* is stored in a {@link MessageSet}. Subclasses may override this method for
* more specific functionality.
*/
@Override
public boolean equals(Object o) {
return o != null && (o.getClass() == this.getClass());
}
/**
* A <code>hashCode</code> method compatible with the <code>equals</code> method.
*/
@Override
public int hashCode() {
return this.getClass().hashCode();
}
}

View File

@ -1,123 +0,0 @@
package net.sf.openrocket.logging;
import net.sf.openrocket.util.ArrayList;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Monitorable;
import net.sf.openrocket.util.Mutable;
import java.util.AbstractSet;
import java.util.Iterator;
/**
* A set that contains multiple <code>Message</code>s. When adding a
* {@link Message} to this set, the contents is checked for a message of the
* same type. If one is found, then the message left in the set is determined
* by the method {@link Message#replaceBy(Message)}.
* <p>
* A MessageSet can be made immutable by calling {@link #immute()}.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public abstract class MessageSet<E extends Message> extends AbstractSet<E> implements Cloneable, Monitorable {
/** the actual array of messages */
protected ArrayList<E> messages = new ArrayList<>();
protected Mutable mutable = new Mutable();
private int modID = 0;
/**
* Add a <code>Message</code> to the set. If a message of the same type
* exists in the set, the message that is left in the set is defined by the
* method {@link Message#replaceBy(Message)}.
*
* @throws IllegalStateException if this message set has been made immutable.
*/
@Override
public boolean add(E m) {
mutable.check();
modID++;
int index = messages.indexOf(m);
if (index < 0) {
messages.add(m);
return false;
}
E old = messages.get(index);
if (old.replaceBy(m)) {
messages.set(index, m);
}
return true;
}
/**
* Add a <code>Message</code> with the specified text to the set.
*
* @param s the message text.
* @throws IllegalStateException if this message set has been made immutable.
*/
public abstract boolean add(String s);
/**
* Add a <code>Message</code> of the specified type with the specified discriminator to the
* set.
* @param m the message
* @param d the extra discriminator
*
*/
public boolean add (E m, String d) {
return this.add(m.toString() + ": \"" + d + "\"");
}
@Override
public Iterator<E> iterator() {
final Iterator<E> iterator = messages.iterator();
return new Iterator<E>() {
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public E next() {
return iterator.next();
}
@Override
public void remove() {
mutable.check();
iterator.remove();
}
};
}
@Override
public int size() {
return messages.size();
}
public void immute() {
mutable.immute();
}
@Override
public String toString() {
StringBuilder s = new StringBuilder();
for (Message m : messages) {
if (s.length() > 0)
s.append(",");
s.append(m.toString());
}
return "Messages[" + s + "]";
}
@Override
public int getModID() {
return modID;
}
}

View File

@ -1,392 +0,0 @@
package net.sf.openrocket.logging;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.simulation.FlightEvent;
import net.sf.openrocket.unit.UnitGroup;
/**
* A warning message wrapper.
*/
public abstract class Warning extends Message {
/** support to multiple languages warning */
private static final Translator trans = Application.getTranslator();
/**
* @return a Warning with the specific text.
*/
public static Warning fromString(String text) {
return new Warning.Other(text);
}
///////////// Specific warning classes /////////////
/**
* A <code>Warning</code> indicating a large angle of attack was encountered.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public static class LargeAOA extends Warning {
private final double aoa;
/**
* Sole constructor. The argument is the AOA that caused this warning.
*
* @param aoa the angle of attack that caused this warning
*/
public LargeAOA(double aoa) {
this.aoa = aoa;
}
@Override
public String toString() {
if (Double.isNaN(aoa))
//// Large angle of attack encountered.
return trans.get("Warning.LargeAOA.str1");
//// Large angle of attack encountered (
return (trans.get("Warning.LargeAOA.str2") +
UnitGroup.UNITS_ANGLE.getDefaultUnit().toString(aoa) + ").");
}
@Override
public boolean replaceBy(Message other) {
if (!(other instanceof LargeAOA))
return false;
LargeAOA o = (LargeAOA) other;
if (Double.isNaN(this.aoa)) // If this has value NaN then replace
return true;
return (o.aoa > this.aoa);
}
}
/**
* A <code>Warning</code> indicating recovery device deployment at high speed was encountered.
*
* @author Craig Earls <enderw88@gmail.com>
*/
public static class HighSpeedDeployment extends Warning {
private final double recoverySpeed;
/**
* Sole constructor. The argument is the speed that caused this warning.
*
* @param speed the speed that caused this warning
*/
public HighSpeedDeployment(double speed) {
this.recoverySpeed = speed;
}
@Override
public String toString() {
if (Double.isNaN(recoverySpeed)) {
return trans.get("Warning.RECOVERY_HIGH_SPEED");
}
return trans.get("Warning.RECOVERY_HIGH_SPEED") + " (" + UnitGroup.UNITS_VELOCITY.toStringUnit(recoverySpeed) + ")";
}
@Override
public boolean replaceBy(Message other) {
return false;
}
}
/**
* A <code>Warning</code> indicating flight events occurred after ground hit
*
*/
public static class EventAfterLanding extends Warning {
private final FlightEvent event;
/**
* Sole constructor. The argument is an event which has occurred after landing
*
* @param _event the event that caused this warning
*/
public EventAfterLanding(FlightEvent _event) {
this.event = _event;
}
// I want a warning on every event that occurs after we land,
// so severity of problem is clear to the user
@Override
public boolean equals(Object o) {
return false;
}
@Override
public String toString() {
return trans.get("Warning.EVENT_AFTER_LANDING") + event.getType();
}
@Override
public boolean replaceBy(Message other) {
return false;
}
}
public static class MissingMotor extends Warning {
private Motor.Type type = null;
private String manufacturer = null;
private String designation = null;
private String digest = null;
private double diameter = Double.NaN;
private double length = Double.NaN;
private double delay = Double.NaN;
@Override
public String toString() {
String str = "No motor with designation '" + designation + "'";
if (manufacturer != null)
str += " for manufacturer '" + manufacturer + "'";
str += " found.";
return str;
}
public Motor.Type getType() {
return type;
}
public void setType(Motor.Type type) {
this.type = type;
}
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
public String getDigest() {
return digest;
}
public void setDigest(String digest) {
this.digest = digest;
}
public double getDiameter() {
return diameter;
}
public void setDiameter(double diameter) {
this.diameter = diameter;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public double getDelay() {
return delay;
}
public void setDelay(double delay) {
this.delay = delay;
}
@Override
public boolean replaceBy(Message other) {
return false;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
long temp;
temp = Double.doubleToLongBits(delay);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime * result
+ ((designation == null) ? 0 : designation.hashCode());
temp = Double.doubleToLongBits(diameter);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime * result
+ ((digest == null) ? 0 : digest.hashCode());
temp = Double.doubleToLongBits(length);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime * result
+ ((manufacturer == null) ? 0 : manufacturer.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
MissingMotor other = (MissingMotor) obj;
if (Double.doubleToLongBits(delay) != Double
.doubleToLongBits(other.delay))
return false;
if (designation == null) {
if (other.designation != null)
return false;
} else if (!designation.equals(other.designation))
return false;
if (Double.doubleToLongBits(diameter) != Double
.doubleToLongBits(other.diameter))
return false;
if (digest == null) {
if (other.digest != null)
return false;
} else if (!digest.equals(other.digest))
return false;
if (Double.doubleToLongBits(length) != Double
.doubleToLongBits(other.length))
return false;
if (manufacturer == null) {
if (other.manufacturer != null)
return false;
} else if (!manufacturer.equals(other.manufacturer))
return false;
if (type != other.type)
return false;
return true;
}
}
/**
* An unspecified warning type. This warning type holds a <code>String</code>
* describing it. Two warnings of this type are considered equal if the strings
* are identical.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public static class Other extends Warning {
private final String description;
public Other(String description) {
this.description = description;
}
@Override
public String toString() {
return description;
}
@Override
public boolean equals(Object other) {
if (!(other instanceof Other))
return false;
Other o = (Other) other;
return (o.description.equals(this.description));
}
@Override
public int hashCode() {
return description.hashCode();
}
@Override
public boolean replaceBy(Message other) {
return false;
}
}
/** A <code>Warning</code> that the body diameter is discontinuous. */
////Discontinuity in rocket body diameter.
public static final Warning DIAMETER_DISCONTINUITY = new Other(trans.get("Warning.DISCONTINUITY"));
/** A <code>Warning</code> that a ComponentAssembly has an open forward end */
public static final Warning OPEN_AIRFRAME_FORWARD = new Other(trans.get("Warning.OPEN_AIRFRAME_FORWARD"));
/** A <code>Warning</code> that there is a gap in the airframe */
public static final Warning AIRFRAME_GAP = new Other(trans.get("Warning.AIRFRAME_GAP"));
/** A <code>Warning</code> that there are overlapping airframe components */
public static final Warning AIRFRAME_OVERLAP = new Other(trans.get("Warning.AIRFRAME_OVERLAP"));
/** A <code>Warning</code> that an inline podset is completely forward of its parent component */
public static final Warning PODSET_FORWARD = new Other(trans.get("Warning.PODSET_FORWARD"));
/** A <code>Warning</code> that an inline podset overlaps its parent component */
public static final Warning PODSET_OVERLAP = new Other(trans.get("Warning.PODSET_OVERLAP"));
/** A <code>Warning</code> that the fins are thick compared to the rocket body. */
////Thick fins may not be modeled accurately.
public static final Warning THICK_FIN = new Other(trans.get("Warning.THICK_FIN"));
/** A <code>Warning</code> that the fins have jagged edges. */
////Jagged-edged fin predictions may be inaccurate.
public static final Warning JAGGED_EDGED_FIN = new Other(trans.get("Warning.JAGGED_EDGED_FIN"));
/** A <code>Warning</code> that the fins have a zero area. */
////Fins with no area will not affect aerodynamics
public static final Warning ZERO_AREA_FIN = new Other(trans.get("Warning.ZERO_AREA_FIN"));
/** A <code>Warning</code> that simulation listeners have affected the simulation */
////Listeners modified the flight simulation
public static final Warning LISTENERS_AFFECTED = new Other(trans.get("Warning.LISTENERS_AFFECTED"));
////Recovery device opened while motor still burning.
public static final Warning RECOVERY_DEPLOYMENT_WHILE_BURNING = new Other(trans.get("Warning.RECOVERY_DEPLOYMENT_WHILE_BURNING"));
////No recovery device for simulation
public static final Warning NO_RECOVERY_DEVICE = new Other(trans.get("Warning.NO_RECOVERY_DEVICE"));
//// Invalid parameter encountered, ignoring.
public static final Warning FILE_INVALID_PARAMETER = new Other(trans.get("Warning.FILE_INVALID_PARAMETER"));
public static final Warning PARALLEL_FINS = new Other(trans.get("Warning.PARALLEL_FINS"));
public static final Warning SUPERSONIC = new Other(trans.get("Warning.SUPERSONIC"));
public static final Warning RECOVERY_LAUNCH_ROD = new Other(trans.get("Warning.RECOVERY_LAUNCH_ROD"));
public static final Warning TUMBLE_UNDER_THRUST = new Other(trans.get("Warning.TUMBLE_UNDER_THRUST"));
public static final Warning EVENT_AFTER_LANDING = new Other(trans.get("Warning.EVENT_AFTER_LANDING"));
public static final Warning ZERO_VOLUME_BODY = new Other(trans.get("Warning.ZERO_VOLUME_BODY"));
public static final Warning TUBE_SEPARATION = new Other(trans.get("Warning.TUBE_SEPARATION"));
public static final Warning TUBE_OVERLAP = new Other(trans.get("Warning.TUBE_OVERLAP"));
public static final Warning SEPARATION_ORDER = new Other(trans.get("Warning.SEPARATION_ORDER"));
public static final Warning EMPTY_BRANCH = new Other(trans.get("Warning.EMPTY_BRANCH"));
}

View File

@ -1,48 +0,0 @@
package net.sf.openrocket.logging;
import java.util.AbstractSet;
import java.util.Iterator;
import net.sf.openrocket.util.ArrayList;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Monitorable;
import net.sf.openrocket.util.Mutable;
/**
* A set that contains multiple <code>Warning</code>s. When adding a
* {@link Warning} to this set, the contents is checked for a warning of the
* same type. If one is found, then the warning left in the set is determined
* by the method {@link Warning#replaceBy(Message)}.
* <p>
* A WarningSet can be made immutable by calling {@link #immute()}.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class WarningSet extends MessageSet<Warning> {
/**
* Add a <code>Warning</code> with the specified text to the set. The Warning object
* is created using the {@link Message#fromString(String)} method. If a warning of the
* same type exists in the set, the warning that is left in the set is defined by the
* method {@link Warning#replaceBy(Message)}.
*
* @param s the message text.
* @throws IllegalStateException if this message set has been made immutable.
*/
public boolean add(String s) {
mutable.check();
return add(Warning.fromString(s));
}
@Override
public WarningSet clone() {
try {
WarningSet newSet = (WarningSet) super.clone();
newSet.messages = this.messages.clone();
newSet.mutable = this.mutable.clone();
return newSet;
} catch (CloneNotSupportedException e) {
throw new BugException("CloneNotSupportedException occurred, report bug!", e);
}
}
}

View File

@ -1,95 +0,0 @@
package net.sf.openrocket.gui.dialogs;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.gui.util.BetterListCellRenderer;
import net.sf.openrocket.logging.Error;
import net.sf.openrocket.logging.ErrorSet;
import net.sf.openrocket.logging.Warning;
import net.sf.openrocket.logging.WarningSet;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.ListSelectionModel;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
/**
* A message dialog displaying errors and warnings.
*/
@SuppressWarnings("serial")
public abstract class ErrorWarningDialog {
public static void showErrorsAndWarnings(Component parent, Object message, String title, ErrorSet errors, WarningSet warnings) {
JPanel content = new JPanel(new MigLayout("ins 0, fillx"));
StyledLabel label = new StyledLabel("Errors");
label.setFontColor(net.sf.openrocket.util.Color.DARK_RED.toAWTColor());
content.add(label, "wrap, gaptop 15lp");
Error[] e = errors.toArray(new Error[0]);
final JList<Error> errorList = new JList<>(e);
errorList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
errorList.setCellRenderer(new ErrorListCellRenderer());
JScrollPane errorPane = new JScrollPane(errorList);
content.add(errorPane, "wrap, growx");
// Deselect items if clicked on blank region
errorList.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
int selectedIndex = errorList.locationToIndex(e.getPoint());
if (selectedIndex < 0 || !errorList.getCellBounds(0, errorList.getLastVisibleIndex()).contains(e.getPoint())) {
errorList.clearSelection();
}
}
});
content.add(new JSeparator(JSeparator.HORIZONTAL), "wrap");
content.add(new JLabel("Warnings:"), "wrap");
Warning[] w = warnings.toArray(new Warning[0]);
final JList<Warning> warningList = new JList<>(w);
warningList.setCellRenderer(new BetterListCellRenderer());
JScrollPane warningPane = new JScrollPane(warningList);
content.add(warningPane, "wrap, growx");
// Deselect items if clicked on blank region
warningList.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
int selectedIndex = warningList.locationToIndex(e.getPoint());
if (selectedIndex < 0 || !warningList.getCellBounds(0, warningList.getLastVisibleIndex()).contains(e.getPoint())) {
warningList.clearSelection();
}
}
});
JOptionPane.showMessageDialog(parent, new Object[] { message, content },
title, JOptionPane.WARNING_MESSAGE);
}
private static class ErrorListCellRenderer extends BetterListCellRenderer {
@Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
// Text color
if (isSelected) {
label.setForeground(Color.WHITE);
} else {
label.setForeground(net.sf.openrocket.util.Color.DARK_RED.toAWTColor());
}
return label;
}
}
}

View File

@ -1,36 +0,0 @@
package net.sf.openrocket.gui.util;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JLabel;
import javax.swing.JList;
import java.awt.Color;
import java.awt.Component;
/**
* An improved list cell renderer, with alternating row background colors.
*
* @author Sibo Van Gool <sibo.vangool@hotmail.com>
*/
public class BetterListCellRenderer extends DefaultListCellRenderer {
@Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
// Alternating row colors
if (!isSelected) {
if (index % 2 == 0) {
label.setBackground(Color.WHITE);
} else {
label.setBackground(new Color(245, 245, 245));
}
}
// Text color
if (isSelected) {
label.setForeground(Color.WHITE);
} else {
label.setForeground(Color.BLACK);
}
return label;
}
}