/** * Sigmoid Function Generator * @author Robert John Morton Email * @version 15 December 1997 This program exercises and demonstrates the 4 cases for the sigmoidal height profile of a waypoint encounter, which are: 1) The aircraft is outbound FROM the current waypoint, which is LOWer than the NEXT waypoint en route. [Applies at take-off] 2) The aircraft is outbound FROM the current waypoint, which is HIGHer than the NEXT waypoint en route. 3) The aircraft is inbound TO the current waypoint, which is LOWer than the PREVious waypoint en route. [Applied when landing] 3) The aircraft is inbound TO the current waypoint, which is HIGHer than the PREVious waypoint en route. Need to work out which variables need to be obtained and from where and which need to be preserved across iterations when this process is installed in aircraft.java. */ import java.awt.*; import javax.swing.*; import java.awt.image.BufferedImage; public class sigmoid extends JPanel implements Runnable { private static boolean sign[] = {true,false,false,true}; // sign of the increment private static int U = 400, // pixels per unit real (scaling factor) X = 200, // width of graph (pixels) Y = 200, // height of graph (pixels) H = 0, // horizontal window co-ordinate of graphical origin V = X - 1; // vertical window co-ordinate of graphical origin private static long δt = 50; // total Time Frame for T update cycle /* TRUTH TABLE FOR THE 4 HEIGHT PROFILE FUNCTIONS The THIS column says whether the current waypoint is higher or lower than the next or previous waypoint in the route. THIS X Y X-BIAS y-BIAS from low += 0.0 --> 0.5 seed --> 0.5 +0.0 +0.0 from high -= 0.0 --> 0.5 1-seed --> 0.5 +0.0 +0.0 to low -= 0.5 --> 1.0 0.5 --> 0.0 -0.5 +0.0 to high += 0.5 --> 1.0 0.5 --> 1.0 -0.5 -0.5 */ private static double k = 0.071978, // non-linearity constant δx = k / 10.22, // T (or look-up table) increment xI[] = { +0.0, +0.0, +0.5, +0.5 }, xF[] = { +0.5, +0.5, +1.0, +1.0 }, yI[] = { δx, 1-δx, +0.5, +0.5 }, yF[] = { +0.5, +0.5, +0.0, +1.0 }, xB[] = { +0.0, +0.0, -0.5, -0.5 }, // x_bias yB[] = { +0.0, -0.5, +0.0, -0.5 }; // y_bias private static String // annotations for the 4 cases AN[] = {"FROM / LOW ","FROM / HIGH"," TO / LOW "," TO / HIGH"}; private static Color bg = new Color(0,0,0), // background colour tr = new Color(0,255,128); // trace colour private static Font font=new Font("Dialog",Font.PLAIN,12); private static BufferedImage I = null; // ref for a Graph image object private static Graphics2D i; // graphics reference for off-screen image private boolean finished = false, // indicates when the curve has been completed firstpass = true, // first pass flag From = false, // to/from flag for waypoint approach/recede Low = false; // this waypoint is higher or lower than prev/next wp private int ph = 0, // horiz and vert pixel positions of previous pass pv = 0, // horiz and vert pixel positions of previous pass j; // index for the following arrays private double x = 0, // input value y = 0, // output value xf, // final value of x si, // sign of increment/decrement x_bias, y_bias; private long t; // time at which next new cycle is due to begin private volatile Thread T; // thread reference variable sigmoid(boolean From, boolean Low) { setBackground(bg); // set applet's background colour if(From) if(Low) j = 0; else j = 1; else if(Low) j = 2; else j = 3; x = xI[j]; xf = xF[j]; y = yI[j]; x_bias = xB[j]; y_bias = yB[j]; // Create image object on which to draw graph axes I = new BufferedImage(X,Y,BufferedImage.TYPE_INT_RGB); i = I.createGraphics(); // get its graphics context // Set end time for first update time frame t = System.currentTimeMillis() + δt; T = new Thread(this); // create the run thread T.start(); // start the run thread } // Set up the graphics and (re)draw from the off-screen image I public void paint(Graphics g) { g.drawImage(I,14,15,null); } public void newplot() { // PLOT THE SIGMOID GRAPH if(x > xf) { // if plot has reached edge of graph finished = true; j++; if(j > 3) j = 0; x = xI[j]; xf = xF[j]; y = yI[j]; x_bias = xB[j]; y_bias = yB[j]; firstpass = true; } else { // else [not yet finished T graph] // Convert the horizontal and vertical plots to pixels. int h = (int)(U * (x + x_bias)); v = V - (int)(U * (y + y_bias)); /* If this is the first time through, set the previous horizontal and vertical pixel positions equal to the current ones. */ if(firstpass) { i.setColor(bg); // set background colour of off-screen image i.fillRect(0,0,X,Y); // paint background of off-screen image i.setColor(Color.white); i.drawString(AN[j],55,100); i.setColor(tr); // set colour to paint the trace on image ph = h; pv = v; firstpass = false; } /* Do the next plot on the off-screen image then save the pixel positions ready for next pass. */ i.drawLine(ph,pv,h,v); ph = h; pv = v; /* Advance sigmoid function's difference equation ready for next pass. The height 'y' must be incremented or decremented as appro- priate for the TO/FROM LOW/HIGH case currently being traced. */ x += δx; // double δy = k * y * (1 - y); if(sign[j]) y += δy; else y -= δy; y = 2 * (1 + Math.exp(-k * x)) - 1; } } public void run(){ // run the T thread while(T != null){ // loop while thread is alive // Time left in the current time-frame. long s = t - System.currentTimeMillis(); newplot(); // If not yet finished, do the next plot. if(!finished) repaint(); else { s = 5000; finished = false; } if(s < 5) s = 5; /* Sleep for the remainder of the time-frame, while allowing external events to interrupt the thread. */ try{T.sleep(s);} catch (InterruptedException e){} // Set the finishing pass of the next time frame. t = System.currentTimeMillis() + δt; } } public void stop() {T = null;} // kill the program thread }