All Downloads are FREE. Search and download functionalities are using the official Maven repository.

JSci.instruments.pi.Mercury Maven / Gradle / Ivy

Go to download

JSci is a set of open source Java packages. The aim is to encapsulate scientific methods/principles in the most natural way possible. As such they should greatly aid the development of scientific based software. It offers: abstract math interfaces, linear algebra (support for various matrix and vector types), statistics (including probability distributions), wavelets, newtonian mechanics, chart/graph components (AWT and Swing), MathML DOM implementation, ... Note: some packages, like javax.comm, for the astro and instruments package aren't listed as dependencies (not available).

The newest version!
package JSci.instruments.pi;

import JSci.instruments.*;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
import java.util.prefs.*;
import java.io.*;
import java.text.*;

/** 
 * A mechanical device attached to a Mercury PI board.
* Attention! The Mercury board forgets the position of the axes when it is reset or * is turned off. Do not turn off the Mercury while the motor is moving!
* There is a lot of final and protected methods, because * this should be not be simply sub-classed by motor-specific classes, but it should be * included in them. */ public abstract class Mercury extends PositionControlAdapter { private int port; private int axis; private double bias = 0.0; private String type = ""; private String version = ""; private static final int numAxis = 10 ; private static final int numPorts = 10; private static DataInput rfi = null; private static DataOutput rfo = null; private Preferences persPref = Preferences.userRoot().node("/it/unimi/pi/Mercury"); /* read byte without EOF */ private byte readByteWithoutEOF() throws IOException { boolean found=false; byte c=0; while (!found) { try { c=rfi.readByte(); found=true; } catch (EOFException e) { try { Thread.sleep(10); } catch (InterruptedException e2) {} } } return c; } private void writeByte(int b) throws IOException { // System.out.println("Command: <"+b+">"); rfo.writeByte(b); } private void writeBytes(String s) throws IOException { // System.err.println("Command: "+s); rfo.writeBytes(s); } /* read a line from Mercury */ private String readLine() { // System.err.println("Reading."); String s=""; char c; try { while ((c=(char)readByteWithoutEOF())!=13) s+=c; } catch (IOException e) { throw new RuntimeException("Cannot communicate with port "+port+"; exception "+e); } try { if (readByteWithoutEOF()==10) readByteWithoutEOF(); } catch (IOException e) { throw new RuntimeException("Cannot communicate with port "+port+"; exception "+e); } // System.err.println("Read: "+s); return s; } /** Remember this class is abstract! * @param p the ttyS port number at which the Mercury is attached * @param rfi the input file connected to the port; something like * new RandomAccessFile("/dev/ttyS0","rw") * @param rfo the output file connected to the port; something like * new RandomAccessFile("/dev/ttyS0","rw") * @param n the number of the axis */ protected Mercury(int p, DataInput rfi, DataOutput rfo, int n) { if (n<0) throw(new IllegalArgumentException(n+": axis number should be positive")); if (p<0) throw(new IllegalArgumentException(n+": ttyS port number should be positive")); port=p; axis=n; this.rfi = rfi; this.rfo = rfo; try { synchronized (rfo) { // version writeByte(1); writeBytes(""+axis); writeBytes("ve"); writeByte(13); try { rfi.readByte(); } catch (EOFException e) { // reset writeByte(1); writeBytes(""+axis); writeBytes("rt"); writeByte(13); } readLine(); // version writeByte(1); writeBytes(""+axis); writeBytes("ve"); writeByte(13); version=readLine(); // brake off writeByte(1); writeBytes(""+axis); writeBytes("bf"); writeByte(13); // motor on writeByte(1); writeBytes(""+axis); writeBytes("mn"); writeByte(13); } } catch (IOException e) { throw(new IllegalArgumentException("Error writing to /dev/ttyS"+port)); } bias=0.0; bias=persPref.getDouble("zero-"+port+"-"+axis,0.0)-doGetPosition(); } /** set the limit switch polarity. * @param b the switch signals are high when out-of-limit? */ protected final void setLimitSwitches(boolean b) { try { synchronized (rfo) { writeByte(1); writeBytes(""+axis); if (b) writeBytes("lh"); else writeBytes("ll"); writeByte(13); } } catch (IOException e) { throw new RuntimeException("Cannot communicate with ttyS"+port); } } /** move to the position between the two limit switches. */ protected void findCenter() { try { synchronized (rfo) { writeByte(1); writeBytes(""+axis); writeBytes("fe"); writeByte(13); } } catch (IOException e) { throw new RuntimeException("Cannot communicate with ttyS"+port); } } ///////////////////////////////////////////////////////////////////////////////////////////// // Position /** move the device to the given position. * Checking the limits must be done (if necessary) by the extending class (note this class is abstract!) * @param p the position that we want to reach, in counts. * It is rounded to its nearest integer position */ public void setPosition(double p) { if (p==currPos) return; currPos=p; doSetPosition(p); persPref.putDouble("zero-"+port+"-"+axis,p); fireStateChanged(); } /* actually set the position. */ private void doSetPosition(double p) { try { synchronized (rfo) { writeByte(1); writeBytes(""+axis); writeBytes("ma"+(long)(p-bias)); writeByte(13); } } catch (IOException e) { throw new RuntimeException("Cannot communicate with ttyS"+port); } } /** get the position. * @return the position in counts. * It is alwais an integer value */ public double getPosition() { if (Double.isNaN(currPos)) currPos=doGetPosition(); return Math.rint(currPos); } private double currPos = Double.NaN; /* actually get the position */ public double doGetPosition() { double p = 0.0; try { synchronized (rfo) { writeByte(1); writeBytes(""+axis); writeBytes("tt"); writeByte(13); p=Double.parseDouble(readLine().substring(2)); } } catch (IOException e) { throw new RuntimeException("Cannot communicate with ttyS"+port); } return p+bias; } /** get the actual position while the axis is moving. * @return the position in counts. * It is alwais an integer value */ public double getActualPosition() { double p = 0.0; try { synchronized (rfo) { writeByte(1); writeBytes(""+axis); writeBytes("tp"); writeByte(13); p=Double.parseDouble(readLine().substring(2)); } } catch (IOException e) { throw new RuntimeException("Cannot communicate with ttyS"+port); } return p+bias; } /** get the minimum value of position * @return the minimum position */ public double getMinimum() { return Math.rint(persPref.getDouble("min-"+port+"-"+axis,getPosition())); } /** get the maximum value of position * @return the maximum position */ public double getMaximum() { return Math.rint(persPref.getDouble("max-"+port+"-"+axis,getPosition())); } /** set the minimum value of position. Only root can do this. * @param m the minimum position */ public void setMinimum(double m) { persPref.putDouble("min-"+port+"-"+axis,m); } /** set the maximum value of position. Only root can do this. * @param m the maximum position */ public void setMaximum(double m) { persPref.putDouble("max-"+port+"-"+axis,m); } /** get the unit in which the position is expressed * @return the units */ public String getUnit() {return "counts";} /** get the minor step suggested for changing the position * @return the suggested minor step */ public double getMinorStep() {return 400.0;} /** get the major step suggested for changing the position * @return the suggested major step */ public double getMajorStep() {return 4000.0;} /** get the error on the actual position. * @return the error on the position in counts. * It is rounded to its nearest integer position. */ public double getPositionError() { return doGetPositionError(); } /* actually get the error on the actual position. * return the error on the position in counts. * It is rounded to its nearest integer position. */ public double doGetPositionError() { double p = 0.0; try { synchronized (rfo) { writeByte(1); writeBytes(""+axis); writeBytes("te"); writeByte(13); p=Double.parseDouble(readLine().substring(2)); } } catch (IOException e) { throw new RuntimeException("Cannot communicate with ttyS"+port); } return p; } ////////////////////////////////////////////////////////////////////////////////////////////////// // Velocity /** set the velocity the device will reach when moving. * Checking the limits must be done (if necessary) by the extending class (note this class is abstract!) * @param v the velocity in counts per cycle. It is rounded to its * nearest integer position. */ public void setVelocity(double v) { try { synchronized (rfo) { writeByte(1); writeBytes(""+axis); writeBytes("sv"+(long)v); writeByte(13); } } catch (IOException e) { throw new RuntimeException("Cannot communicate with ttyS"+port); } } /** get the velocity that should be reached when moving. * @return the velocity in counts per cycle. It is rounded to its * nearest integer position. */ public double getVelocity() { double p = 0.0; try { synchronized (rfo) { writeByte(1); writeBytes(""+axis); writeBytes("ty"); writeByte(13); p=Double.parseDouble(readLine().substring(2)); } } catch (IOException e) { throw new RuntimeException("Cannot communicate with ttyS"+port); } return p; } /** get the actual velocity while moving. * @return the velocity in counts per cycle. It is rounded to its * nearest integer position. */ public double getActualVelocity() { double p = 0.0; try { synchronized (rfo) { writeByte(1); writeBytes(""+axis); writeBytes("tv"); writeByte(13); p=Double.parseDouble(readLine().substring(2)); } } catch (IOException e) { throw new RuntimeException("Cannot communicate with ttyS"+port); } return p; } /** get the maximum value of velocity * @return the maximum velocity */ public double getMaxVelocity() { return Double.POSITIVE_INFINITY; } /** get the step suggested for changing the velocity * @return the suggested step */ public double getVelocityStep() {return 100000.0;} /** get the unit in which the velocity is expressed * @return the units */ public String getVelocityUnit() {return "counts/cycle";} ////////////////////////////////////////////////////////////////////////////////////////////////// // Motor controls /** Clear errors */ protected void clearErrors() {} /** switch the motor on or off. * @param b do you want to switch the motor on? */ protected void setMotorOn(boolean b) { try { synchronized (rfo) { writeByte(1); writeBytes(""+axis); if (b) writeBytes("mn"); else writeBytes("mf"); writeByte(13); } } catch (IOException e) { throw new RuntimeException("Cannot communicate with ttyS"+port); } motor_on=b; } private boolean motor_on = true; /** check if the motor is on or off. * @return the motor is on? */ protected boolean getMotorOn() { return motor_on; } /** switch the brake on or off. * @param b do you want to switch the brake on? */ protected void setBrake(boolean b) { try { synchronized (rfo) { writeByte(1); writeBytes(""+axis); if (b) writeBytes("bn"); else writeBytes("bf"); writeByte(13); } } catch (IOException e) { throw new RuntimeException("Cannot communicate with ttyS"+port); } brake_on=b; } private boolean brake_on; /** check if the brake is on or off. * @return the brake is on? */ protected boolean getBrake() { return brake_on; } /** get the status of event. CURRENTLY NOT IMPLEMENTED. * @return the properties of the event. */ protected Hashtable getEventStatus() { return null; } protected static final String EVENT_MOTION_COMPLETE = "Motion complete"; protected static final String EVENT_WRAP_AROUND = "Wrap around"; protected static final String EVENT_BREAKPOINT1 = "Breakpoint 1"; protected static final String EVENT_CAPTURE_RECEIVED = "Capture received"; protected static final String EVENT_MOTION_ERROR = "Motion error"; protected static final String EVENT_POS_LIMIT = "Positive limit"; protected static final String EVENT_NEG_LIMIT = "Negative limit"; protected static final String EVENT_INSTRUCTION_ERR = "Instruction error"; protected static final String EVENT_COMMUNICATION_ERR = "Communication error"; protected static final String EVENT_BREAKPOINT2 = "Breakpoint 2"; /** get the status of signal. CURRENTLY NOT IMPLEMENTED. * @return the properties of the signal. */ protected Hashtable getSignalStatus() { return null; } protected static final String SIGNAL_ENCODER_A = "Encoder A"; protected static final String SIGNAL_ENCODER_B = "Encoder B"; protected static final String SIGNAL_ENCODER_INDEX = "Encoder index"; protected static final String SIGNAL_ENCODER_HOME = "Encoder home"; protected static final String SIGNAL_POS_LIMIT = "Positive limit"; protected static final String SIGNAL_NEG_LIMIT = "Negative limit"; protected static final String SIGNAL_AXIS_IN = "Axis in"; protected static final String SIGNAL_HALL_A = "Hall A"; protected static final String SIGNAL_HALL_B = "Hall B"; protected static final String SIGNAL_HALL_C = "Hall C"; protected static final String SIGNAL_AXIS_OUT = "Axis out"; protected static final String SIGNAL_STEP_OUTPUT = "Step output"; protected static final String SIGNAL_MOTOR_OUTPUT = "Motor output"; /** get the status of activity. CURRENTLY NOT IMPLEMENTED. * @return the property of activity */ protected Hashtable getActivityStatus() { return null; } protected static final String ACTIVITY_PHASING_INITD = "Not for the PI boards!!!"; protected static final String ACTIVITY_MAX_VELOCITY = "Running at max velocity"; protected static final String ACTIVITY_TRACKING = "Tracking"; protected static final String ACTIVITY_PROFILE_MODE_0 = "Profile mode 0"; protected static final String ACTIVITY_PROFILE_MODE_1 = "Profile mode 1"; protected static final String ACTIVITY_PROFILE_MODE_2 = "Profile mode 2"; protected static final String ACTIVITY_RESERVED = "Reserved"; protected static final String ACTIVITY_AXIS_SETTLED = "Setteled"; protected static final String ACTIVITY_MOTOR_STATUS = "Motor status"; protected static final String ACTIVITY_POSITION_CAPTURE = "Position capture"; protected static final String ACTIVITY_IN_MOTION = "In motion"; protected static final String ACTIVITY_ACT_POS_LIMIT = "Actual positive limit"; protected static final String ACTIVITY_ACT_NEG_LIMIT = "Actual negative limit"; /** sleep until the axis has reached its position */ public void sleep() { do { try { Thread.sleep(200); } catch (InterruptedException e) {} } while (Math.abs(doGetPositionError())>19.5); } /////////////////////////////////////////////////////////////////////////////////////////////// // Visual Component /** Create a JPanel with the controls of the position * @param monitor monitor the actual position every 0.1 s. * @param vertical the direction of motion is vertical * @param inverted invert the direction of motion */ protected JPanel createPositionPanel(boolean monitor,boolean vertical, boolean inverted) { final JButton setLimits = new JButton("Limits"); final JSpinner spinner; JButton plus,minus; JPanel fastMovement = new JPanel(); JPanel r = new JPanel(); fastMovement.setLayout(new BorderLayout()); r.setLayout(new FlowLayout()); if (vertical) { plus = new JButton("^"); minus = new JButton("v"); fastMovement.add("North",plus); fastMovement.add("South",minus); } else { plus = new JButton(">"); minus = new JButton("<"); fastMovement.add("East",plus); fastMovement.add("West",minus); } spinner=new JSpinner(new SpinnerNumberModel(getPosition(),getMinimum(),getMaximum(),getMinorStep())); Dimension dim = spinner.getPreferredSize(); dim.setSize(100,dim.getHeight()); spinner.setPreferredSize(dim); r.add(spinner); r.add(new JLabel("("+getUnit()+")")); r.add(fastMovement); if (monitor) { final JSpinner actpos; actpos = new JSpinner(new SpinnerNumberModel(getPosition(),getMinimum(),getMaximum(),getMinorStep() )); dim = actpos.getPreferredSize(); dim.setSize(100,dim.getHeight()); actpos.setPreferredSize(dim); actpos.setEnabled(false); r.add(new JLabel("Actual: ")); r.add(actpos); r.add(new JLabel("("+getUnit()+")")); class ActposChangeListener implements ChangeListener,Runnable { private boolean running = false; public void run() { Thread t = new Thread(new Runnable() { public void run() { sleep(); running=false; } }); t.setDaemon(true); t.start(); do { actpos.setValue(new Double(getActualPosition())); try { Thread.sleep(100); } catch (InterruptedException e) {} } while (running); actpos.setValue(new Double(getActualPosition())); } public void stateChanged(ChangeEvent event) { if (running) return; Thread t = new Thread(this); t.setDaemon(true); running=true; t.start(); } } addChangeListener(new ActposChangeListener()); } if (!inverted) { minus.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { double p=getPosition()-getMajorStep(); if (p>=getMinimum()) spinner.setValue(new Double(p)); } }); plus.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { double p=getPosition()+getMajorStep(); if (p<=getMaximum()) spinner.setValue(new Double(p)); } }); } else { minus.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { double p=getPosition()+getMajorStep(); if (p<=getMaximum()) spinner.setValue(new Double(p)); } }); plus.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { double p=getPosition()-getMajorStep(); if (p>=getMinimum()) spinner.setValue(new Double(p)); } }); } spinner.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent event) { double p=((Double)spinner.getValue()).doubleValue(); setPosition(p); } }); addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent event) { spinner.setValue(new Double(getPosition())); } }); r.add(setLimits); setLimits.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (setLimitsDialog==null) setLimits(); if (!setLimitsDialog.isVisible()) setLimitsDialog.setVisible(true); setLimitsDialog.toFront(); } }); r.setBorder( BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(), "Position" ) ); return r; } /** Create a JPanel with the controls of the velocity * @param monitor monitor the actual velocity every 0.1 s. */ protected JPanel createVelocityPanel(boolean monitor) { final JSpinner vel; final JRadioButton inMotion; JPanel r = new JPanel(); r.setLayout(new FlowLayout()); vel = new JSpinner(new SpinnerNumberModel(getVelocity(),0.0,getMaxVelocity(),getVelocityStep())); inMotion = new JRadioButton("In motion"); inMotion.setSelected(false); inMotion.setEnabled(false); Dimension dim = vel.getPreferredSize(); dim.setSize(100,dim.getHeight()); vel.setPreferredSize(dim); r.add(vel); r.add(new JLabel("("+getVelocityUnit()+")")); if (monitor) { final JSpinner actvel; actvel = new JSpinner(new SpinnerNumberModel(getActualVelocity(),-getMaxVelocity(),getMaxVelocity(),getVelocityStep()) ); dim = actvel.getPreferredSize(); dim.setSize(100,dim.getHeight()); actvel.setPreferredSize(dim); actvel.setEnabled(false); r.add(new JLabel("Actual: ")); r.add(actvel); r.add(new JLabel("("+getVelocityUnit()+")")); class ActvelChangeListener implements ChangeListener,Runnable { private boolean running = false; public void run() { Thread t = new Thread(new Runnable() { public void run() { inMotion.setSelected(true); sleep(); running=false; inMotion.setSelected(false); } }); t.setDaemon(true); t.start(); do { actvel.setValue(new Double(getActualVelocity())); try { Thread.sleep(100); } catch (InterruptedException e) {} } while (running); actvel.setValue(new Double(getActualVelocity())); } public void stateChanged(ChangeEvent event) { if (running) return; Thread t = new Thread(this); t.setDaemon(true); running=true; t.start(); } } addChangeListener(new ActvelChangeListener()); } r.add(inMotion); vel.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent event) { double v=((Double)vel.getValue()).doubleValue(); setVelocity(v); } }); r.setBorder( BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(), "Velocity" ) ); return r; } /** Create a JPanel with buttons for controlling the motor.
* ATTENZIONE! NON E' COMPLETO!!! */ protected JPanel createButtonControlPanel() { JPanel r = new JPanel(); JButton bFindHome,bSetMotorOn, bSetBrake,bSetMotorMode,bSetOutputMode, bClearErrors; r.setLayout(new FlowLayout()); bFindHome = new JButton("Find home"); bSetMotorOn = new JButton("Motor ON"); bSetBrake = new JButton("Brake ON"); bSetMotorMode = new JButton("Motor mode 1"); bSetOutputMode = new JButton("DAC"); bClearErrors = new JButton("Clear error"); bFindHome.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { findCenter(); } }); bSetMotorOn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { setMotorOn(!getMotorOn()); } }); bSetBrake.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { setBrake(!getBrake()); } }); bClearErrors.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { clearErrors(); } }); r.add(bFindHome); r.add(bSetMotorOn); r.add(bSetBrake); r.add(bClearErrors); r.setBorder( BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(), "Motor controls" ) ); return r; } /** The motor can be controlled by a visual component, with buttons, * sliders and so on. Call this to get the Component (actually, a JPanel). * This component displays also many informations. */ public abstract Component getControlComponent(); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // createMotorDevice() /** The C-150.PD motor */ public static final String C150PD = "C-150.PD"; /** The C-136.10 motor */ public static final String C136 = "C-136.10"; /** The M-126.PD motor */ public static final String M126PD = "M-126.PD"; /** A generic motor driven by Mercury */ public static final String RAW = "Raw"; /** Call this to build a driver for a given motor, instead of calling the constructor. * @param t the type of motor connected to the board (see RAW,C150PD, C136, M126PD). * @param p the number of the ttyS port * @param rfi the input file connected to the port * @param rfo the output file connected to the port * @param n the number of the axis * @param gf if there's a mechanical device such as a gear, gf is the ratio final motion/motor motion. gf=1 for RAW. */ public static Mercury createMotorDevice(String t,int p, DataInput rfi, DataOutput rfo, int n, double gf) { if (gf==0.0) throw(new IllegalArgumentException("Gear factor = 0")); if (!( t.equals(RAW) || t.equals(C150PD) || t.equals(C136) || t.equals(M126PD) )) throw(new IllegalArgumentException("Motor type not supported")); if ( t.equals(RAW) && gf!=1.0 ) throw(new IllegalArgumentException("Gear factor must be 1.0 for Row motor type")); Mercury c = null; final JPanel ccomp = new JPanel(); final double rpc; final double vpc; final double maxv; final String propname = "vel-"+p+"-"+n+"-"+t; final String posUnit; final String velUnit; if (t.equals(RAW)) { rpc = 1.0; vpc = 1.0; maxv = Double.POSITIVE_INFINITY; posUnit = "counts"; velUnit = "counts/s"; } else if (t.equals(C150PD)) { rpc = gf/4000.0; vpc = gf/4000.0; maxv = 100.0 * Math.abs(gf); posUnit = "turns"; velUnit = "turns/s"; } else if (t.equals(C136)) { rpc = gf / 2000.0; vpc = gf / 2000.0; maxv = 3.3 * Math.abs(gf) ; posUnit = "turns"; velUnit = "turns/s"; } else { if (! t.equals(M126PD)) throw new IllegalArgumentException("Unknown motor type: "+t); rpc = 0.5/4000.0 * gf; vpc = 0.5/4000.0 * gf; maxv = 15.0 * Math.abs(gf); posUnit = "mm"; velUnit = "mm/s"; } c = new Mercury(p, rfi, rfo, n) { public void setPosition(double p) { if (p>=getMinimum() && p<=getMaximum()) super.setPosition(p/rpc); } public double getPosition() { return super.getPosition()*rpc; } public double getActualPosition() { return super.getActualPosition()*rpc; } public double getMinimum() { return rpc*((rpc>0.0)?super.getMinimum():super.getMaximum()); } public double getMaximum() { return rpc*((rpc>0.0)?super.getMaximum():super.getMinimum()); } public void setMinimum(double m) { if (rpc>0.0) super.setMinimum(m/rpc); else super.setMaximum(m/rpc); } public void setMaximum(double m) { if (rpc>0.0) super.setMaximum(m/rpc); else super.setMinimum(m/rpc); } public String getUnit() { return posUnit; } public double getMinorStep() { return super.getMinorStep()*Math.abs(rpc);} public double getMajorStep() { return super.getMajorStep()*Math.abs(rpc);} public double getPositionError() { return super.getPositionError()*rpc; } public void setVelocity(double v) { if (v>0.0 && v=c.getMinimum() && c.getPosition()<=c.getMaximum())) throw new IllegalArgumentException("( Minimum <= Position <= Maximum ) failed"); c.type=t; c.setVelocity(c.persPref.getDouble("vel-"+c.port+"-"+c.axis+"-"+c.type,0.1)); ccomp.setLayout(new BorderLayout()); if (t.equals(M126PD)) ccomp.add("North",c.createPositionPanel(true,true,false)); else ccomp.add("North",c.createPositionPanel(true,false,false)); ccomp.add("Center",c.createVelocityPanel(true)); //ccomp.add("South",c.createButtonControlPanel()); ccomp.setBorder( BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(), "ttyS"+p+" Axis "+n+" "+t ) ); return c; } /** Call this to build a driver for a given motor, instead of calling the constructor. * @param t the type of motor connected to the board (see RAW,C150PD, C136, M126PD). * @param p the number of the ttyS port * @param n the number of the axis * @param gf if there's a mechanical device such as a gear, gf is the ratio final motion/motor motion. gf=1 for RAW. */ public static Mercury createMotorDevice(String t, int p, int n, double gf) { RandomAccessFile raf = null; try { raf = new RandomAccessFile("/dev/ttyS"+p,"rw"); } catch (FileNotFoundException e) { throw new IllegalArgumentException("/dev/ttyS"+p+"does not exist"); } return createMotorDevice(t, p, raf, raf, n, gf); } /** Call this to build a driver for a given motor, instead of calling the constructor. * @param t the type of motor connected to the board (see RAW,C150PD, C136, M126PD). * @param p the number of the ttyS port * @param n the number of the axis */ public static Mercury createMotorDevice(String t,int p, int n) { RandomAccessFile raf = null; try { raf = new RandomAccessFile("/dev/ttyS"+p,"rw"); } catch (FileNotFoundException e) { throw new IllegalArgumentException("/dev/ttyS"+p+"does not exist"); } return createMotorDevice(t, p, raf, raf, n, 1.0); } /** Report port number, device number and version */ public String toString() { return getClass().getName()+ "[\nPort=ttyS"+port+",axis="+axis+",type="+type+",version="+version+"]"; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Main private static void printHelp() { System.out.println( "Useful controls for the Mercury board. Parameters can be supplied.\n"+ "Syntax:\n"+ "java it.unimi.pi.Mercury {options} {commands}\n"+ "The options can be:\n"+ "-h : print the help\n"+ "-m type : set the motor type (\"Raw\" by default)\n"+ "-p ttyS_number : set the ttyS port number (0 by default)\n"+ "-n axis_number : set the axis number (0 by default)\n"+ "-g gear_factor : set the gear factor (1 by default)\n"+ "The commands can be:\n"+ "setMinimum position : set the minimum of the position (only root can do this)\n"+ "setMaximum position : set the maximum of the position (only root can do this)\n"+ "setPosition position : move the motor to the given position\n"+ "setLimits : graphical interface for setting limits of the given motor (only root can do this)\n"+ "monitor : open a window with the control component for the desired motor.\n"+ "motors : print a list of known motor types. \"Raw\" is a generic motor, with the\n"+ "units used by the board.\n" ); System.exit(0); } /** Useful controls for the Mercury board. Parameters can be supplied.
* Syntax:
* java it.unimi.pi.Mercury {options} {commands}
* The options can be:
* -h : print the help
* -m type : set the motor type ("Raw" by default)
* -p ttyS_number : set the ttyS port number (0 by default)
* -n axis_number : set the axis number (0 by default)
* -g gear_factor : set the gear factor (1 by default)
* The commands can be:
* setMinimum position : set the minimum of the position (only root can do this)
* setMaximum position : set the maximum of the position (only root can do this)
* setPosition position : move the motor to the given position
* setLimits : graphical interface for setting limits of the given motor (only root can do this)
* monitor : open a window with the control component for the desired motor.
* motors : print a list of known motor types. "Raw" is a generic motor, with the * units used by the board.
*/ public static void main(String [] args) { String t="Raw"; int a=0; double gf=1.0; int p=0; int n=0; while (n=args.length) printHelp(); t=args[n]; } else if (args[n].equals("-p")) { n++; if (n>=args.length) printHelp(); p=Integer.parseInt(args[n]); } else if (args[n].equals("-n")) { n++; if (n>=args.length) printHelp(); a=Integer.parseInt(args[n]); } else if (args[n].equals("-g")) { n++; if (n>=args.length) printHelp(); gf=Double.parseDouble(args[n]); } else if (args[n].equals("-h")) printHelp(); else break; n++; } Mercury c = createMotorDevice(t,p,a,gf); while (n=args.length) printHelp(); c.setMinimum(Double.parseDouble(args[n])); } else if (args[n].equals("setMaximum")) { n++; if (n>=args.length) printHelp(); c.setMaximum(Double.parseDouble(args[n])); } else if (args[n].equals("setPosition")) { n++; if (n>=args.length) printHelp(); c.setPosition(Double.parseDouble(args[n])); } else if (args[n].equals("setLimits")) c.setLimits(); else if (args[n].equals("monitor")) { JFrame frm = new JFrame("Mercury"); frm.getContentPane().add(c.getControlComponent()); frm.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frm.pack(); frm.show(); } else if (args[n].equals("motors")) { System.out.println("Supported motor types:\nRaw\nC-150.PD\nC-136.10\nM-126.PD\n\n"); } else printHelp(); n++; } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Graphical configuration of the limits JFrame setLimitsDialog = null; /** runs a graphical configuration of the limits. Only root can do this. * This operation allows the movement of the device outside the current limits; this could * damage the device. */ public void setLimits() { setLimitsDialog = new JFrame("Axis "+axis+" "+type+" Set limits"); final JSpinner min = new JSpinner(new SpinnerNumberModel(getMinimum(),Double.NEGATIVE_INFINITY,getPosition(),getMinorStep())); final JSpinner pos = new JSpinner(new SpinnerNumberModel(getPosition(),getMinimum(),getMaximum(),getMinorStep())); final JSpinner max = new JSpinner(new SpinnerNumberModel(getMaximum(),getPosition(),Double.POSITIVE_INFINITY,getMinorStep())); final JRadioButton rbPos = new JRadioButton("None",true); final JRadioButton rbMin = new JRadioButton("Min",false); final JRadioButton rbMax = new JRadioButton("Max",false); JButton toMin = new JButton("Move to min"); JButton toMax = new JButton("Move to max"); ButtonGroup bg = new ButtonGroup(); bg.add(rbPos);bg.add(rbMin);bg.add(rbMax); min.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { double v = ((Double)min.getValue()).doubleValue(); setMinimum(v); if (rbPos.isSelected()) ((SpinnerNumberModel)pos.getModel()).setMinimum(new Double(getMinimum())); if (rbMin.isSelected()) { pos.setValue(new Double(getMinimum())); ((SpinnerNumberModel)pos.getModel()).setMinimum(new Double(getMinimum())); ((SpinnerNumberModel)pos.getModel()).setMaximum(new Double(getMinimum())); ((SpinnerNumberModel)max.getModel()).setMinimum(new Double(getMinimum())); } if (rbMax.isSelected()) ((SpinnerNumberModel)max.getModel()).setMinimum(new Double(getMinimum())); } }); pos.addChangeListener(new ChangeListener() { private double currPos = 0.0; public void stateChanged(ChangeEvent e) { if (currPos == 0.0) currPos = getPosition(); double v = ((Double)pos.getValue()).doubleValue(); if (v==currPos) return; currPos=v; setPosition(v); if (rbPos.isSelected()) { ((SpinnerNumberModel)min.getModel()).setMaximum(new Double(getPosition())); ((SpinnerNumberModel)max.getModel()).setMinimum(new Double(getPosition())); } } }); max.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { double v = ((Double)max.getValue()).doubleValue(); setMaximum(v); if (rbPos.isSelected()) ((SpinnerNumberModel)pos.getModel()).setMaximum(new Double(getMaximum())); if (rbMin.isSelected()) ((SpinnerNumberModel)min.getModel()).setMaximum(new Double(getMaximum())); if (rbMax.isSelected()) { pos.setValue(new Double(getMaximum())); ((SpinnerNumberModel)pos.getModel()).setMinimum(new Double(getMaximum())); ((SpinnerNumberModel)pos.getModel()).setMaximum(new Double(getMaximum())); ((SpinnerNumberModel)min.getModel()).setMaximum(new Double(getMaximum())); } } }); rbPos.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ((SpinnerNumberModel)min.getModel()).setMaximum(new Double(getPosition())); ((SpinnerNumberModel)max.getModel()).setMinimum(new Double(getPosition())); ((SpinnerNumberModel)pos.getModel()).setMinimum(new Double(getMinimum())); ((SpinnerNumberModel)pos.getModel()).setMaximum(new Double(getMaximum())); } }); rbMin.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { pos.setValue(new Double(getMinimum())); ((SpinnerNumberModel)min.getModel()).setMaximum(new Double(getMaximum())); ((SpinnerNumberModel)pos.getModel()).setMinimum(new Double(getMinimum())); ((SpinnerNumberModel)pos.getModel()).setMaximum(new Double(getMinimum())); ((SpinnerNumberModel)max.getModel()).setMinimum(new Double(getMinimum())); } }); rbMax.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { pos.setValue(new Double(getMaximum())); ((SpinnerNumberModel)max.getModel()).setMinimum(new Double(getMinimum())); ((SpinnerNumberModel)pos.getModel()).setMinimum(new Double(getMaximum())); ((SpinnerNumberModel)pos.getModel()).setMaximum(new Double(getMaximum())); ((SpinnerNumberModel)min.getModel()).setMaximum(new Double(getMaximum())); } }); toMin.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (rbPos.isSelected()) pos.setValue(new Double(getMinimum())); } }); toMax.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (rbPos.isSelected()) pos.setValue(new Double(getMaximum())); } }); Dimension dim = min.getPreferredSize(); dim = new Dimension(100,(int)dim.getHeight()); min.setPreferredSize(dim); dim = pos.getPreferredSize(); dim = new Dimension(100,(int)dim.getHeight()); pos.setPreferredSize(dim); dim = max.getPreferredSize(); dim = new Dimension(100,(int)dim.getHeight()); max.setPreferredSize(dim); setLimitsDialog.getContentPane().setLayout(new GridBagLayout()); GridBagConstraints constr = new GridBagConstraints(); constr.fill=GridBagConstraints.NONE; constr.anchor=GridBagConstraints.EAST; constr.weightx=0; constr.weighty=0; constr.gridx=0;constr.gridy=0;constr.gridwidth=1;constr.gridheight=1; setLimitsDialog.getContentPane().add(new JLabel("Maximum:"),constr); constr.gridx=1;constr.gridy=0;constr.gridwidth=1;constr.gridheight=1; setLimitsDialog.getContentPane().add(max,constr); constr.gridx=2;constr.gridy=0;constr.gridwidth=1;constr.gridheight=1; setLimitsDialog.getContentPane().add(new JLabel(getUnit()),constr); constr.gridx=0;constr.gridy=1;constr.gridwidth=1;constr.gridheight=1; setLimitsDialog.getContentPane().add(new JLabel("Position:"),constr); constr.gridx=1;constr.gridy=1;constr.gridwidth=1;constr.gridheight=1; setLimitsDialog.getContentPane().add(pos,constr); constr.gridx=2;constr.gridy=1;constr.gridwidth=1;constr.gridheight=1; setLimitsDialog.getContentPane().add(new JLabel(getUnit()),constr); constr.gridx=0;constr.gridy=2;constr.gridwidth=1;constr.gridheight=1; setLimitsDialog.getContentPane().add(new JLabel("Minimum:"),constr); constr.gridx=1;constr.gridy=2;constr.gridwidth=1;constr.gridheight=1; setLimitsDialog.getContentPane().add(min,constr); constr.gridx=2;constr.gridy=2;constr.gridwidth=1;constr.gridheight=1; setLimitsDialog.getContentPane().add(new JLabel(getUnit()),constr); constr.gridx=0;constr.gridy=3;constr.gridwidth=1;constr.gridheight=1; setLimitsDialog.getContentPane().add(new JLabel("Anchor to: "),constr); constr.anchor=GridBagConstraints.WEST; constr.gridx=1;constr.gridy=4;constr.gridwidth=1;constr.gridheight=1; setLimitsDialog.getContentPane().add(rbPos,constr); constr.gridx=1;constr.gridy=5;constr.gridwidth=1;constr.gridheight=1; setLimitsDialog.getContentPane().add(rbMin,constr); constr.gridx=1;constr.gridy=6;constr.gridwidth=1;constr.gridheight=1; setLimitsDialog.getContentPane().add(rbMax,constr); constr.anchor=GridBagConstraints.CENTER; constr.gridx=0;constr.gridy=7;constr.gridwidth=1;constr.gridheight=1; setLimitsDialog.getContentPane().add(toMin,constr); constr.gridx=1;constr.gridy=7;constr.gridwidth=1;constr.gridheight=1; setLimitsDialog.getContentPane().add(toMax,constr); setLimitsDialog.pack(); setLimitsDialog.setResizable(false); setLimitsDialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); setLimitsDialog.setVisible(true); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy