1 package net.sf.openrocket.simulation.listeners.haisu;
3 import java.util.Collection;
5 import net.sf.openrocket.aerodynamics.FlightConditions;
6 import net.sf.openrocket.rocketcomponent.FinSet;
7 import net.sf.openrocket.rocketcomponent.RocketComponent;
8 import net.sf.openrocket.simulation.FlightEvent;
9 import net.sf.openrocket.simulation.SimulationStatus;
10 import net.sf.openrocket.simulation.listeners.AbstractSimulationListener;
11 import net.sf.openrocket.util.MathUtil;
14 public class RollControlListener extends AbstractSimulationListener {
16 private static final double DELTA_T = 0.01;
17 private static final double START_TIME = 0.5;
19 private static final double MACH = 0.9;
21 private static final double SETPOINT = 0.0;
23 private static final double TURNRATE = 10 * Math.PI/180; // per second
27 * At M=0.3 KP oscillation threshold between 0.35 and 0.4. Good KI=3
28 * At M=0.6 KP oscillation threshold between 0.07 and 0.08 Good KI=2
29 * At M=0.9 KP oscillation threshold between 0.013 and 0.014 Good KI=0.5
31 private static final double KP = 0.007;
32 private static final double KI = 0.2;
35 private static final double MAX_ANGLE = 15 * Math.PI/180;
40 private double rollrate;
42 private double intState = 0;
44 private double finPosition = 0;
47 public RollControlListener() {
51 public void flightConditions(SimulationStatus status, FlightConditions conditions) {
54 // conditions.setAOA(0);
55 // conditions.setTheta(0);
56 // conditions.setMach(MACH);
57 // conditions.setPitchRate(0);
58 // conditions.setYawRate(0);
59 // status.position = new Coordinate(0,0,100);
60 // status.velocity = Coordinate.NUL;
63 rollrate = conditions.getRollRate();
67 public Collection<FlightEvent> stepTaken(SimulationStatus status) {
69 if (status.time < START_TIME)
74 for (RocketComponent c: status.configuration) {
75 if ((c instanceof FinSet) && (c.getName().equals("CONTROL"))) {
81 throw new RuntimeException("CONTROL fin not found");
85 double error = SETPOINT - rollrate;
88 error = Math.signum(error) * error * error; //// pow2(error)
90 double p = KP * error;
91 intState += error * DELTA_T;
92 double i = KI * intState;
97 if (Math.abs(value) > MAX_ANGLE) {
98 System.err.printf("Attempting to set angle %.1f at t=%.3f, clamping.\n",
99 value*180/Math.PI, status.time);
100 value = MathUtil.clamp(value, -MAX_ANGLE, MAX_ANGLE);
104 if (finPosition < value) {
105 finPosition = Math.min(finPosition + TURNRATE*DELTA_T, value);
107 finPosition = Math.max(finPosition - TURNRATE*DELTA_T, value);
110 if (MathUtil.equals(status.time*10, Math.rint(status.time*10))) {
111 System.err.printf("t=%.3f angle=%.1f current=%.1f\n",status.time,
112 value*180/Math.PI, finPosition*180/Math.PI);
115 finset.setCantAngle(finPosition);