X-Git-Url: https://git.gag.com/?a=blobdiff_plain;ds=sidebyside;f=src%2Fnet%2Fsf%2Fopenrocket%2Fsimulation%2FRK4Simulator.java;h=1a1905864b7fbd448b7a5ce2057a4e7d1259abc8;hb=e298a9509613f232227d16d28310611b33c3aa03;hp=dd5ec49932eb796f47823f9c7b5b24c818632990;hpb=c71eeba85a8a25e1bd43b27ad09cb2238139b737;p=debian%2Fopenrocket diff --git a/src/net/sf/openrocket/simulation/RK4Simulator.java b/src/net/sf/openrocket/simulation/RK4Simulator.java index dd5ec499..1a190586 100644 --- a/src/net/sf/openrocket/simulation/RK4Simulator.java +++ b/src/net/sf/openrocket/simulation/RK4Simulator.java @@ -1,6 +1,7 @@ package net.sf.openrocket.simulation; import java.util.Collection; +import java.util.Random; import net.sf.openrocket.aerodynamics.AerodynamicCalculator; import net.sf.openrocket.aerodynamics.AerodynamicForces; @@ -22,6 +23,8 @@ import net.sf.openrocket.util.Rotation2D; public class RK4Simulator extends FlightSimulator { + private static final boolean DEBUG = false; + /** * A recommended reasonably accurate time step. */ @@ -32,24 +35,30 @@ public class RK4Simulator extends FlightSimulator { */ public static final double RECOMMENDED_ANGLE_STEP = 3*Math.PI/180; + /** + * A random amount that is added to pitch and yaw coefficients, plus or minus. + */ + public static final double PITCH_YAW_RANDOM = 0.0005; + /** * Maximum roll step allowed. This is selected as an uneven division of the full * circle so that the simulation will sample the most wind directions */ - private static final double MAX_ROLL_STEP_ANGLE = 28.32 * Math.PI/180; + private static final double MAX_ROLL_STEP_ANGLE = 2*28.32 * Math.PI/180; // private static final double MAX_ROLL_STEP_ANGLE = 8.32 * Math.PI/180; private static final double MAX_ROLL_RATE_CHANGE = 2 * Math.PI/180; - private static final double MAX_PITCH_CHANGE = 2 * Math.PI/180; + private static final double MAX_PITCH_CHANGE = 4 * Math.PI/180; - private static final boolean DEBUG = false; - /* Single instance so it doesn't have to be created each semi-step. */ private final FlightConditions flightConditions = new FlightConditions(null); + private final Random random = new Random(); + + private Coordinate linearAcceleration; private Coordinate angularAcceleration; @@ -131,10 +140,19 @@ public class RK4Simulator extends FlightSimulator { Quaternion o = new Quaternion(); + + // Initialize to roll angle with least stability w.r.t. the wind + FlightConditions cond = new FlightConditions(configuration); + calculator.getWorstCP(cond, null); + double angle = -cond.getTheta() - simulation.getLaunchRodDirection(); + o.multiplyLeft(Quaternion.rotation(new Coordinate(0, 0, angle))); + + // Launch rod angle and direction o.multiplyLeft(Quaternion.rotation( new Coordinate(0, simulation.getLaunchRodAngle(), 0))); o.multiplyLeft(Quaternion.rotation( new Coordinate(0, 0, simulation.getLaunchRodDirection()))); + status.orientation = o; status.position = Coordinate.NUL; status.velocity = Coordinate.NUL; @@ -193,8 +211,8 @@ public class RK4Simulator extends FlightSimulator { * The last two are required since near the steady-state roll rate the roll rate * may oscillate significantly even between the sub-steps of the RK4 integration. * - * Additionally a low-pass filter is applied to the time step selectively - * if the new time step is longer than the previous time step. + * Additionally if the time step is longer than the previous time step, the + * increase is limited to 50% of the previous time step. */ double dt1 = simulation.getTimeStep(); double dt2 = simulation.getMaximumStepAngle() / lateralPitchRate; @@ -204,18 +222,25 @@ public class RK4Simulator extends FlightSimulator { timestep = MathUtil.min(dt1,dt2,dt3); timestep = MathUtil.min(timestep,dt4,dt5); - if (oldTimestep > 0 && oldTimestep < timestep) { - timestep = 0.3*timestep + 0.7*oldTimestep; + if (status.launchRod) { + // Use 1/5th time step while on launch rod + timestep = MathUtil.min(timestep, simulation.getTimeStep()/5); + } + + if (oldTimestep > 0.0001 && oldTimestep < timestep) { + timestep = Math.min(timestep, oldTimestep*1.5); } - if (timestep < 0.001) - timestep = 0.001; +// if (timestep < 0.001) +// timestep = 0.001; + if (timestep < simulation.getTimeStep() / 10) + timestep = simulation.getTimeStep() / 10; oldTimestep = timestep; - if (DEBUG) - System.out.printf("Time step: %.3f dt1=%.3f dt2=%.3f dt3=%.3f dt4=%.3f dt5=%.3f\n", - timestep,dt1,dt2,dt3,dt4,dt5); - + if (DEBUG) { + System.out.printf("Time step (t=%.3f): %.3f dt1=%.3f dt2=%.3f dt3=%.3f dt4=%.3f dt5=%.3f\n", + status.time, timestep,dt1,dt2,dt3,dt4,dt5); + } //// First position, k1 = f(t, y) @@ -351,6 +376,15 @@ public class RK4Simulator extends FlightSimulator { } + // Add very small randomization to yaw & pitch moments to prevent + // over-perfect flight + // TODO: HIGH: This should rather be performed as a listener + forces.Cm += PITCH_YAW_RANDOM * 2 * (random.nextDouble()-0.5); + forces.Cyaw += PITCH_YAW_RANDOM * 2 * (random.nextDouble()-0.5); + + + + // Allow listeners to modify the forces int mod = flightConditions.getModCount(); SimulationListener[] list = listeners.toArray(new SimulationListener[0]); @@ -362,6 +396,9 @@ public class RK4Simulator extends FlightSimulator { } + + + assert(!Double.isNaN(forces.CD)); assert(!Double.isNaN(forces.CN)); assert(!Double.isNaN(forces.Caxial)); @@ -476,6 +513,7 @@ public class RK4Simulator extends FlightSimulator { airSpeed = status.orientation.invRotate(airSpeed); + // Lateral direction: double len = MathUtil.hypot(airSpeed.x, airSpeed.y); if (len > 0.0001) {