1 package net.sf.openrocket.utils;
3 import java.io.FileInputStream;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.util.ArrayList;
9 import net.sf.openrocket.file.motor.GeneralMotorLoader;
10 import net.sf.openrocket.file.motor.MotorLoader;
11 import net.sf.openrocket.logging.LogLevel;
12 import net.sf.openrocket.models.atmosphere.AtmosphericConditions;
13 import net.sf.openrocket.motor.Motor;
14 import net.sf.openrocket.motor.MotorDigest;
15 import net.sf.openrocket.motor.MotorInstance;
16 import net.sf.openrocket.motor.ThrustCurveMotor;
17 import net.sf.openrocket.startup.Application;
18 import net.sf.openrocket.util.BugException;
19 import net.sf.openrocket.util.MathUtil;
21 public class MotorCorrelation {
24 * Return a measure of motor similarity. The measure is a value between 0.0 and 1.0.
25 * The larger the value, the more similar the motor thrust curves are, for value 1.0 they
28 * This method takes into account the thrust curve shape, average thrust, burn time and
29 * total impulse of the motor. The similarity is the minimum of all of these.
31 * @param motor1 the first motor
32 * @param motor2 the second motor
33 * @return the similarity of the two motors
35 public static double similarity(Motor motor1, Motor motor2) {
38 d = crossCorrelation(motor1, motor2);
39 d = Math.min(d, diff(motor1.getAverageThrustEstimate(), motor2.getAverageThrustEstimate()));
40 d = Math.min(d, 2 * diff(motor1.getBurnTimeEstimate(), motor2.getBurnTimeEstimate()));
41 d = Math.min(d, diff(motor1.getTotalImpulseEstimate(), motor2.getTotalImpulseEstimate()));
47 private static double diff(double a, double b) {
48 double min = Math.min(a, b);
49 double max = Math.max(a, b);
51 if (MathUtil.equals(max, 0))
58 * Compute the cross-correlation of the thrust curves of the two motors. The result is
59 * a double between 0 and 1 (inclusive). The closer the return value is to one the more
60 * similar the thrust curves are.
62 * @param motor1 the first motor.
63 * @param motor2 the second motor.
64 * @return the scaled cross-correlation of the two thrust curves.
66 public static double crossCorrelation(Motor motor1, Motor motor2) {
67 MotorInstance m1 = motor1.getInstance();
68 MotorInstance m2 = motor2.getInstance();
70 AtmosphericConditions cond = new AtmosphericConditions();
76 for (t = 0; t < 1000; t += 0.01) {
80 double t1 = m1.getThrust();
81 double t2 = m2.getThrust();
83 if (t1 < 0 || t2 < 0) {
84 throw new BugException("Negative thrust, t1=" + t1 + " t2=" + t2);
92 double auto = Math.max(auto1, auto2);
94 if (MathUtil.equals(auto, 0)) {
104 public static void main(String[] args) {
105 Application.setLogOutputLevel(LogLevel.WARN);
107 MotorLoader loader = new GeneralMotorLoader();
108 List<Motor> motors = new ArrayList<Motor>();
109 List<String> files = new ArrayList<String>();
112 for (String file : args) {
113 List<Motor> m = null;
115 InputStream stream = new FileInputStream(file);
116 m = loader.load(stream, file);
118 } catch (IOException e) {
124 for (int i = 0; i < m.size(); i++)
129 // Output motor digests
130 final int count = motors.size();
131 for (int i = 0; i < count; i++) {
132 System.out.println(files.get(i) + ": " + MotorDigest.digestMotor((ThrustCurveMotor) motors.get(i)));
135 // Cross-correlate every pair
136 for (int i = 0; i < count; i++) {
137 for (int j = i + 1; j < count; j++) {
138 System.out.println(files.get(i) + " " + files.get(j) + " : " +
139 crossCorrelation(motors.get(i), motors.get(j)));