package net.sf.openrocket.simulation;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.unit.UnitGroup;
import net.sf.openrocket.util.StringUtil;
/**
* A class defining a storable simulation variable type. This class defined numerous ready
* types, and allows also creating new types with any name. When retrieving types based on
* a name, you should use {@link #getType(String, UnitGroup)} to return the default unit type,
* or a new type if the name does not currently exist.
* <p>
* Each type has a type name (description), a unit group and a priority. The type is identified
* purely by its name case-insensitively. The unit group provides the units for the type.
* The priority is used to order the types. The pre-existing types are defined specific priority
* numbers, and other types have a default priority number that is after all other types.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class FlightDataType implements Comparable<FlightDataType> {
private static final Translator trans = Application.getTranslator();
private static final Logger log = LoggerFactory.getLogger(FlightDataType.class);
/** Priority of custom-created variables */
private static final int DEFAULT_PRIORITY = 999;
/** List of existing types. MUST BE DEFINED BEFORE ANY TYPES!! */
/** NOTE: The String key here is now the symbol */
private static final Map<String, FlightDataType> EXISTING_TYPES = new HashMap<String, FlightDataType>();
//// Time
public static final FlightDataType TYPE_TIME = newType(trans.get("FlightDataType.TYPE_TIME"), "t", UnitGroup.UNITS_FLIGHT_TIME, 1);
//// Vertical position and motion
//// Altitude
public static final FlightDataType TYPE_ALTITUDE = newType(trans.get("FlightDataType.TYPE_ALTITUDE"), "h", UnitGroup.UNITS_DISTANCE, 10);
//// Vertical velocity
public static final FlightDataType TYPE_VELOCITY_Z = newType(trans.get("FlightDataType.TYPE_VELOCITY_Z"), "Vz", UnitGroup.UNITS_VELOCITY, 11);
//// Vertical acceleration
public static final FlightDataType TYPE_ACCELERATION_Z = newType(trans.get("FlightDataType.TYPE_ACCELERATION_Z"), "Az", UnitGroup.UNITS_ACCELERATION, 12);
//// Total motion
//// Total velocity
public static final FlightDataType TYPE_VELOCITY_TOTAL = newType(trans.get("FlightDataType.TYPE_VELOCITY_TOTAL"), "Vt", UnitGroup.UNITS_VELOCITY, 20);
//// Total acceleration
public static final FlightDataType TYPE_ACCELERATION_TOTAL = newType(trans.get("FlightDataType.TYPE_ACCELERATION_TOTAL"), "At", UnitGroup.UNITS_ACCELERATION, 21);
//// Lateral position and motion
//// Position upwind
public static final FlightDataType TYPE_POSITION_X = newType(trans.get("FlightDataType.TYPE_POSITION_X"), "Px", UnitGroup.UNITS_DISTANCE, 30);
//// Position parallel to wind
public static final FlightDataType TYPE_POSITION_Y = newType(trans.get("FlightDataType.TYPE_POSITION_Y"), "Py", UnitGroup.UNITS_DISTANCE, 31);
//// Lateral distance
public static final FlightDataType TYPE_POSITION_XY = newType(trans.get("FlightDataType.TYPE_POSITION_XY"), "Pl", UnitGroup.UNITS_DISTANCE, 32);
//// Lateral direction
public static final FlightDataType TYPE_POSITION_DIRECTION = newType(trans.get("FlightDataType.TYPE_POSITION_DIRECTION"), "\u03b8l", UnitGroup.UNITS_ANGLE, 33);
//// Lateral velocity
public static final FlightDataType TYPE_VELOCITY_XY = newType(trans.get("FlightDataType.TYPE_VELOCITY_XY"), "Vl", UnitGroup.UNITS_VELOCITY, 34);
//// Lateral acceleration
public static final FlightDataType TYPE_ACCELERATION_XY = newType(trans.get("FlightDataType.TYPE_ACCELERATION_XY"), "Al", UnitGroup.UNITS_ACCELERATION, 35);
//// Latitude
public static final FlightDataType TYPE_LATITUDE = newType(trans.get("FlightDataType.TYPE_LATITUDE"), "\u03c6", UnitGroup.UNITS_ANGLE, 36);
//// Longitude
public static final FlightDataType TYPE_LONGITUDE = newType(trans.get("FlightDataType.TYPE_LONGITUDE"), "\u03bb", UnitGroup.UNITS_ANGLE, 37);
//// Gravity
public static final FlightDataType TYPE_GRAVITY = newType(trans.get("FlightDataType.TYPE_GRAVITY"), "g", UnitGroup.UNITS_ACCELERATION, 38);
//// Angular motion
//// Angle of attack
public static final FlightDataType TYPE_AOA = newType(trans.get("FlightDataType.TYPE_AOA"), "\u03b1", UnitGroup.UNITS_ANGLE, 40);
//// Roll rate
public static final FlightDataType TYPE_ROLL_RATE = newType(trans.get("FlightDataType.TYPE_ROLL_RATE"), "d\u03a6", UnitGroup.UNITS_ROLL, 41);
//// Pitch rate
public static final FlightDataType TYPE_PITCH_RATE = newType(trans.get("FlightDataType.TYPE_PITCH_RATE"), "d\u03b8", UnitGroup.UNITS_ROLL, 42);
//// Yaw rate
public static final FlightDataType TYPE_YAW_RATE = newType(trans.get("FlightDataType.TYPE_YAW_RATE"), "d\u03a8", UnitGroup.UNITS_ROLL, 43);
//// Stability information
//// Mass
public static final FlightDataType TYPE_MASS = newType(trans.get("FlightDataType.TYPE_MASS"), "m", UnitGroup.UNITS_MASS, 50);
//// Propellant mass
public static final FlightDataType TYPE_PROPELLANT_MASS = newType(trans.get("FlightDataType.TYPE_PROPELLANT_MASS"), "mp", UnitGroup.UNITS_MASS, 51);
//// Longitudinal moment of inertia
public static final FlightDataType TYPE_LONGITUDINAL_INERTIA = newType(trans.get("FlightDataType.TYPE_LONGITUDINAL_INERTIA"), "Il", UnitGroup.UNITS_INERTIA, 52);
//// Rotational moment of inertia
public static final FlightDataType TYPE_ROTATIONAL_INERTIA = newType(trans.get("FlightDataType.TYPE_ROTATIONAL_INERTIA"), "Ir", UnitGroup.UNITS_INERTIA, 53);
//// CP location
public static final FlightDataType TYPE_CP_LOCATION = newType(trans.get("FlightDataType.TYPE_CP_LOCATION"), "Cp", UnitGroup.UNITS_LENGTH, 54);
//// CG location
public static final FlightDataType TYPE_CG_LOCATION = newType(trans.get("FlightDataType.TYPE_CG_LOCATION"), "Cg", UnitGroup.UNITS_LENGTH, 55);
//// Stability margin calibers
public static final FlightDataType TYPE_STABILITY = newType(trans.get("FlightDataType.TYPE_STABILITY"), "S", UnitGroup.UNITS_COEFFICIENT, 56);
//// Characteristic numbers
//// Mach number
public static final FlightDataType TYPE_MACH_NUMBER = newType(trans.get("FlightDataType.TYPE_MACH_NUMBER"), "M", UnitGroup.UNITS_COEFFICIENT, 60);
//// Reynolds number
public static final FlightDataType TYPE_REYNOLDS_NUMBER = newType(trans.get("FlightDataType.TYPE_REYNOLDS_NUMBER"), "R", UnitGroup.UNITS_COEFFICIENT, 61);
//// Thrust and drag
//// Thrust
public static final FlightDataType TYPE_THRUST_FORCE = newType(trans.get("FlightDataType.TYPE_THRUST_FORCE"), "Ft", UnitGroup.UNITS_FORCE, 70);
//// Drag force
public static final FlightDataType TYPE_DRAG_FORCE = newType(trans.get("FlightDataType.TYPE_DRAG_FORCE"), "Fd", UnitGroup.UNITS_FORCE, 71);
//// Drag coefficient
public static final FlightDataType TYPE_DRAG_COEFF = newType(trans.get("FlightDataType.TYPE_DRAG_COEFF"), "Cd", UnitGroup.UNITS_COEFFICIENT, 72);
//// Axial drag coefficient
public static final FlightDataType TYPE_AXIAL_DRAG_COEFF = newType(trans.get("FlightDataType.TYPE_AXIAL_DRAG_COEFF"), "Cda", UnitGroup.UNITS_COEFFICIENT, 73);
//// Component drag coefficients
//// Friction drag coefficient
public static final FlightDataType TYPE_FRICTION_DRAG_COEFF = newType(trans.get("FlightDataType.TYPE_FRICTION_DRAG_COEFF"), "Cdf", UnitGroup.UNITS_COEFFICIENT, 80);
//// Pressure drag coefficient
public static final FlightDataType TYPE_PRESSURE_DRAG_COEFF = newType(trans.get("FlightDataType.TYPE_PRESSURE_DRAG_COEFF"), "Cdp", UnitGroup.UNITS_COEFFICIENT, 81);
//// Base drag coefficient
public static final FlightDataType TYPE_BASE_DRAG_COEFF = newType(trans.get("FlightDataType.TYPE_BASE_DRAG_COEFF"), "Cdb", UnitGroup.UNITS_COEFFICIENT, 82);
//// Other coefficients
//// Normal force coefficient
public static final FlightDataType TYPE_NORMAL_FORCE_COEFF = newType(trans.get("FlightDataType.TYPE_NORMAL_FORCE_COEFF"), "Cn", UnitGroup.UNITS_COEFFICIENT, 90);
//// Pitch moment coefficient
public static final FlightDataType TYPE_PITCH_MOMENT_COEFF = newType(trans.get("FlightDataType.TYPE_PITCH_MOMENT_COEFF"), "C\u03b8", UnitGroup.UNITS_COEFFICIENT, 91);
//// Yaw moment coefficient
public static final FlightDataType TYPE_YAW_MOMENT_COEFF = newType(trans.get("FlightDataType.TYPE_YAW_MOMENT_COEFF"), "C\u03c4\u03a8", UnitGroup.UNITS_COEFFICIENT, 92);
//// Side force coefficient
public static final FlightDataType TYPE_SIDE_FORCE_COEFF = newType(trans.get("FlightDataType.TYPE_SIDE_FORCE_COEFF"), "C\u03c4s", UnitGroup.UNITS_COEFFICIENT, 93);
//// Roll moment coefficient
public static final FlightDataType TYPE_ROLL_MOMENT_COEFF = newType(trans.get("FlightDataType.TYPE_ROLL_MOMENT_COEFF"), "C\u03c4\u03a6", UnitGroup.UNITS_COEFFICIENT, 94);
//// Roll forcing coefficient
public static final FlightDataType TYPE_ROLL_FORCING_COEFF = newType(trans.get("FlightDataType.TYPE_ROLL_FORCING_COEFF"), "Cf\u03a6", UnitGroup.UNITS_COEFFICIENT, 95);
//// Roll damping coefficient
public static final FlightDataType TYPE_ROLL_DAMPING_COEFF = newType(trans.get("FlightDataType.TYPE_ROLL_DAMPING_COEFF"), "C\u03b6\u03a6", UnitGroup.UNITS_COEFFICIENT, 96);
//// Pitch damping coefficient
public static final FlightDataType TYPE_PITCH_DAMPING_MOMENT_COEFF = newType(trans.get("FlightDataType.TYPE_PITCH_DAMPING_MOMENT_COEFF"), "C\u03b6\u03b8", UnitGroup.UNITS_COEFFICIENT, 97);
//// Yaw damping coefficient
public static final FlightDataType TYPE_YAW_DAMPING_MOMENT_COEFF = newType(trans.get("FlightDataType.TYPE_YAW_DAMPING_MOMENT_COEFF"), "C\u03b6\u03a8", UnitGroup.UNITS_COEFFICIENT, 98);
//// Coriolis acceleration
public static final FlightDataType TYPE_CORIOLIS_ACCELERATION = newType(trans.get("FlightDataType.TYPE_CORIOLIS_ACCELERATION"), "Ac", UnitGroup.UNITS_ACCELERATION, 99);
//// Reference length + area
//// Reference length
public static final FlightDataType TYPE_REFERENCE_LENGTH = newType(trans.get("FlightDataType.TYPE_REFERENCE_LENGTH"), "Lr", UnitGroup.UNITS_LENGTH, 100);
//// Reference area
public static final FlightDataType TYPE_REFERENCE_AREA = newType(trans.get("FlightDataType.TYPE_REFERENCE_AREA"), "Ar", UnitGroup.UNITS_AREA, 101);
//// Orientation
//// Vertical orientation (zenith)
public static final FlightDataType TYPE_ORIENTATION_THETA = newType(trans.get("FlightDataType.TYPE_ORIENTATION_THETA"), "\u0398", UnitGroup.UNITS_ANGLE, 106);
//// Lateral orientation (azimuth)
public static final FlightDataType TYPE_ORIENTATION_PHI = newType(trans.get("FlightDataType.TYPE_ORIENTATION_PHI"), "\u03a6", UnitGroup.UNITS_ANGLE, 107);
//// Atmospheric conditions
//// Wind velocity
public static final FlightDataType TYPE_WIND_VELOCITY = newType(trans.get("FlightDataType.TYPE_WIND_VELOCITY"), "Vw", UnitGroup.UNITS_VELOCITY, 110);
//// Air temperature
public static final FlightDataType TYPE_AIR_TEMPERATURE = newType(trans.get("FlightDataType.TYPE_AIR_TEMPERATURE"), "T", UnitGroup.UNITS_TEMPERATURE, 111);
//// Air pressure
public static final FlightDataType TYPE_AIR_PRESSURE = newType(trans.get("FlightDataType.TYPE_AIR_PRESSURE"), "P", UnitGroup.UNITS_PRESSURE, 112);
//// Speed of sound
public static final FlightDataType TYPE_SPEED_OF_SOUND = newType(trans.get("FlightDataType.TYPE_SPEED_OF_SOUND"), "Vs", UnitGroup.UNITS_VELOCITY, 113);
//// Simulation information
//// Simulation time step
public static final FlightDataType TYPE_TIME_STEP = newType(trans.get("FlightDataType.TYPE_TIME_STEP"), "dt", UnitGroup.UNITS_TIME_STEP, 200);
//// Computation time
public static final FlightDataType TYPE_COMPUTATION_TIME = newType(trans.get("FlightDataType.TYPE_COMPUTATION_TIME"), "tc", UnitGroup.UNITS_SHORT_TIME, 201);
// An array of all the built in types
public static final FlightDataType[] ALL_TYPES = {
TYPE_TIME,
TYPE_ALTITUDE ,
TYPE_VELOCITY_Z ,
TYPE_ACCELERATION_Z,
TYPE_VELOCITY_TOTAL,
TYPE_ACCELERATION_TOTAL,
TYPE_POSITION_X,
TYPE_POSITION_Y,
TYPE_POSITION_XY,
TYPE_POSITION_DIRECTION,
TYPE_VELOCITY_XY,
TYPE_ACCELERATION_XY,
TYPE_LATITUDE,
TYPE_LONGITUDE,
TYPE_GRAVITY,
TYPE_AOA,
TYPE_ROLL_RATE,
TYPE_PITCH_RATE,
TYPE_YAW_RATE,
TYPE_MASS,
TYPE_PROPELLANT_MASS,
TYPE_LONGITUDINAL_INERTIA,
TYPE_ROTATIONAL_INERTIA,
TYPE_CP_LOCATION,
TYPE_CG_LOCATION,
TYPE_STABILITY,
TYPE_MACH_NUMBER,
TYPE_REYNOLDS_NUMBER,
TYPE_THRUST_FORCE,
TYPE_DRAG_FORCE,
TYPE_DRAG_COEFF,
TYPE_AXIAL_DRAG_COEFF,
TYPE_FRICTION_DRAG_COEFF,
TYPE_PRESSURE_DRAG_COEFF,
TYPE_BASE_DRAG_COEFF,
TYPE_NORMAL_FORCE_COEFF,
TYPE_PITCH_MOMENT_COEFF,
TYPE_YAW_MOMENT_COEFF,
TYPE_SIDE_FORCE_COEFF,
TYPE_ROLL_MOMENT_COEFF,
TYPE_ROLL_FORCING_COEFF,
TYPE_ROLL_DAMPING_COEFF,
TYPE_PITCH_DAMPING_MOMENT_COEFF,
TYPE_YAW_DAMPING_MOMENT_COEFF,
TYPE_CORIOLIS_ACCELERATION,
TYPE_REFERENCE_LENGTH,
TYPE_REFERENCE_AREA,
TYPE_ORIENTATION_THETA,
TYPE_ORIENTATION_PHI,
TYPE_WIND_VELOCITY,
TYPE_AIR_TEMPERATURE,
TYPE_AIR_PRESSURE,
TYPE_SPEED_OF_SOUND,
TYPE_TIME_STEP,
TYPE_COMPUTATION_TIME
};
/**
* Return a {@link FlightDataType} with a given string description, symbol and unitgroup.
* This returns an existing data type if the symbol matches that of an existing type.
*
* If the symbol matches but the unit and description information differ, then the old stored datatype
* is erased and the updated version based on the given parametes is returned.
* The only exception is if the description or unitgroup are undefined (null or empty string). In this case
* we just get these parameters from the existing type when making the new one.
*
* @param s the string description of the type.
* @param u the unit group the new type should belong to if a new group is created.
* @return a data type.
*/
public static synchronized FlightDataType getType(String s, String symbol, UnitGroup u) {
// if symbol is null : try finding by name
// if unit is null : don't do anything to the unit if found, just return datatype if found and generate an error and an empty unit otherwise
int oldPriority = DEFAULT_PRIORITY;
//FlightDataType type = findFromSymbol(symbol);
FlightDataType type = EXISTING_TYPES.get(symbol);
if (type != null) {
// found it from symbol
// if name was not given (empty string), can use the one we found
if ( s == null || StringUtil.isEmpty(s)){
s = type.getName();
}
if ( u == null ){
u = type.getUnitGroup();
}
// if something has changed, then we need to remove the old one
// otherwise, just return what we found
if ( !u.equals(type.getUnitGroup()) )
{
oldPriority = type.priority;
EXISTING_TYPES.remove(type);
log.info("Unitgroup of type "+type.getName() +
", has changed from "+type.getUnitGroup().toString() +
" to "+u.toString() +
". Removing old version.");
}
else if (!s.equals(type.getName())) {
oldPriority = type.priority;
EXISTING_TYPES.remove(type);
log.info("Name of type "+type.getName()+", has changed to "+s+". Removing old version.");
}
else{
return type;
}
}
if (u == null){
u = UnitGroup.UNITS_NONE;
log.error("Made a new flightdatatype, but did not know what units to use.");
}
// make a new one
type = newType(s, symbol, u, oldPriority);
return type;
}
/*
* Get the flightdatatype from existing types based on the symbol.
*/
/*
private static FlightDataType findFromSymbol(String symbol){
for (FlightDataType t : EXISTING_TYPES.values()){
if (t.getSymbol().equals(symbol)){
return t;
}
}
return null;
}
*/
/**
* Used while initializing the class.
*/
private static synchronized FlightDataType newType(String s, String symbol, UnitGroup u, int priority) {
FlightDataType type = new FlightDataType(s, symbol, u, priority);
//EXISTING_TYPES.put(s.toLowerCase(Locale.ENGLISH), type);
EXISTING_TYPES.put(symbol, type);
return type;
}
private final String name;
private final String symbol;
private final UnitGroup units;
private final int priority;
private final int hashCode;
private FlightDataType(String typeName, String symbol, UnitGroup units, int priority) {
if (typeName == null)
throw new IllegalArgumentException("typeName is null");
if (units == null)
throw new IllegalArgumentException("units is null");
this.name = typeName;
this.symbol = symbol;
this.units = units;
this.priority = priority;
this.hashCode = this.name.toLowerCase(Locale.ENGLISH).hashCode();
}
/*
public void setPriority(int p){
this.priority = p;
}
*/
public String getName() {
return name;
}
public String getSymbol(){
return symbol;
}
public UnitGroup getUnitGroup() {
return units;
}
@Override
public String toString() {
return name; //+" ("+symbol+") "+units.getDefaultUnit().toString();
}
@Override
public boolean equals(Object other) {
if (!(other instanceof FlightDataType))
return false;
return this.name.equalsIgnoreCase(((FlightDataType) other).name);
}
@Override
public int hashCode() {
return hashCode;
}
@Override
public int compareTo(FlightDataType o) {
if (this.priority != o.priority)
return this.priority - o.priority;
return this.name.compareToIgnoreCase(o.name);
}
}