import java.awt.*; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.imageio.*; import java.io.*; import java.awt.image.*; import java.net.*; public class Controller extends Equipment{ public Controller (Point _position, Tank _t){ t = _t; I_t=0; h_ref = Tank.H/2; k_I = 0.85F; k_P = 0.85F; position=_position; try { // File sourceimage = new File("controller.png"); // As applicatios, this is OK. URL url = getClass().getResource("controller.png"); //it works for applications and applets. controller = ImageIO.read(url); } catch (IOException e) { } gui=new Box(BoxLayout.X_AXIS); JLabel label= new JLabel(" H_ref "); gui.add(label); SpinnerNumberModel levelSpinner= new SpinnerNumberModel(h_ref, 0.0, (float)Tank.H, 1); levelSpinner.addChangeListener(new ChangeListener(){ public void stateChanged(ChangeEvent e){ SpinnerNumberModel sn=(SpinnerNumberModel)e.getSource(); h_ref=sn.getNumber().floatValue(); } }); JSpinner spinner = new JSpinner(levelSpinner); label.setLabelFor(spinner); gui.add(spinner); label= new JLabel(" K Prop. "); gui.add(label); levelSpinner= new SpinnerNumberModel(k_P, 0.0, 3.0, 0.05); levelSpinner.addChangeListener(new ChangeListener(){ public void stateChanged(ChangeEvent e){ SpinnerNumberModel sn=(SpinnerNumberModel)e.getSource(); k_P=sn.getNumber().floatValue(); } }); spinner = new JSpinner(levelSpinner); gui.add(spinner); label= new JLabel(" K Integ. "); gui.add(label); levelSpinner= new SpinnerNumberModel(k_I, 0.0, 3.0, 0.05); levelSpinner.addChangeListener(new ChangeListener(){ public void stateChanged(ChangeEvent e){ SpinnerNumberModel sn=(SpinnerNumberModel)e.getSource(); k_I=sn.getNumber().floatValue(); } }); spinner = new JSpinner(levelSpinner); gui.add(spinner); } public void timeTick(float dt){ float x, e_t, I_prev=I_t; e_t = h_ref-t.getLevel(); I_t += k_I * e_t * dt; x = k_P * e_t + I_t; x*=(-1); x += 0.5; if (x>1) { x=1; I_t = I_prev; // do not integrate more when actuation is maximum. } // In control, this is referred to as without wind-up. if (x<0){ x=0; I_t = I_prev; // do not integrate more when actuation is maximum. } // In control, this is referred to as without wind-up. t.setOutValve(x); } public void paint(Graphics2D g2d){ g2d.drawImage(controller, null, position.x, position.y); } public Box getGUI(){ return gui; } private Tank t; private BufferedImage controller; private Point position; private float k_I, k_P, h_ref, I_t; private Box gui; }