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) {
52 rollrate = conditions.getRollRate();
56 public Collection<FlightEvent> stepTaken(SimulationStatus status) {
58 if (status.time < START_TIME)
63 for (RocketComponent c: status.configuration) {
64 if ((c instanceof FinSet) && (c.getName().equals("CONTROL"))) {
70 throw new RuntimeException("CONTROL fin not found");
74 double error = SETPOINT - rollrate;
77 error = Math.signum(error) * error * error; //// pow2(error)
79 double p = KP * error;
80 intState += error * DELTA_T;
81 double i = KI * intState;
86 if (Math.abs(value) > MAX_ANGLE) {
87 System.err.printf("Attempting to set angle %.1f at t=%.3f, clamping.\n",
88 value*180/Math.PI, status.time);
89 value = MathUtil.clamp(value, -MAX_ANGLE, MAX_ANGLE);
93 if (finPosition < value) {
94 finPosition = Math.min(finPosition + TURNRATE*DELTA_T, value);
96 finPosition = Math.max(finPosition - TURNRATE*DELTA_T, value);
99 if (MathUtil.equals(status.time*10, Math.rint(status.time*10))) {
100 System.err.printf("t=%.3f angle=%.1f current=%.1f\n",status.time,
101 value*180/Math.PI, finPosition*180/Math.PI);
104 finset.setCantAngle(finPosition);