KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > JSci > instruments > pi > Mercury


1 package JSci.instruments.pi;
2
3 import JSci.instruments.*;
4
5 import java.awt.*;
6 import java.awt.event.*;
7 import javax.swing.*;
8 import javax.swing.event.*;
9 import java.util.*;
10 import java.util.prefs.*;
11 import java.io.*;
12 import java.text.*;
13
14 /**
15  * A mechanical device attached to a Mercury PI board.<br>
16  * Attention! The Mercury board forgets the position of the axes when it is reset or
17  * is turned off. Do not turn off the Mercury while the motor is moving!<br>
18  * There is a lot of <code>final</code> and <code>protected</code> methods, because
19  * this should be not be simply sub-classed by motor-specific classes, but it should be
20  * included in them.
21  */

22 public abstract class Mercury extends PositionControlAdapter {
23   
24     private int port;
25     private int axis;
26     private double bias = 0.0;
27     private String JavaDoc type = "";
28     private String JavaDoc version = "";
29     private static final int numAxis = 10 ;
30     private static final int numPorts = 10;
31     private static RandomAccessFile rf[] = new RandomAccessFile[] {null, null, null, null, null, null}; // enough rs232 ports?
32
private Preferences persPref = Preferences.userRoot().node("/it/unimi/pi/Mercury");
33
34     /* read a line from Mercury */
35     private String JavaDoc readLine() {
36     String JavaDoc s="";
37     char c;
38     try {
39         while ((c=(char)rf[port].readByte())!=13) s+=c;
40         rf[port].readByte();
41         rf[port].readByte();
42     }
43     catch (IOException e) { throw new RuntimeException JavaDoc("Cannot communicate with ttyS"+port); }
44     return s;
45     }
46     
47     /** Remember this class is abstract!
48      * @param p the ttyS port number at which the Mercury is attached
49      * @param n the number of the axis
50      */

51     protected Mercury(int p,int n) {
52     if (n<0) throw(new IllegalArgumentException JavaDoc(n+": axis number should be positive"));
53     if (p<0) throw(new IllegalArgumentException JavaDoc(n+": ttyS port number should be positive"));
54     port=p;
55     axis=n;
56     try {
57         if (rf[port]==null) rf[port]=new RandomAccessFile("/dev/ttyS"+port,"rw");
58         synchronized (rf[port]) {
59         // reset
60
rf[port].writeByte(1);
61         rf[port].writeBytes(""+axis);
62         rf[port].writeBytes("rt");
63         rf[port].writeByte(13);
64         // version
65
rf[port].writeByte(1);
66         rf[port].writeBytes(""+axis);
67         rf[port].writeBytes("ve");
68         rf[port].writeByte(13);
69         version=readLine();
70         }
71     }
72     catch (FileNotFoundException e) { throw new IllegalArgumentException JavaDoc("/dev/ttyS"+port+"does not exist"); }
73     catch (IOException e) { throw(new IllegalArgumentException JavaDoc("Error writing to /dev/ttyS"+port)); }
74     bias=persPref.getDouble("zero-"+port+"-"+axis,0.0);
75     }
76
77
78     /** set the limit switch polarity.
79      * @param b the switch signals are high when out-of-limit?
80      */

81     protected final void setLimitSwitches(boolean b) {
82     try {
83         synchronized (rf[port]) {
84         rf[port].writeByte(1);
85         rf[port].writeBytes(""+axis);
86         if (b) rf[port].writeBytes("lh");
87         else rf[port].writeBytes("ll");
88         rf[port].writeByte(13);
89         }
90     }
91     catch (IOException e) { throw new RuntimeException JavaDoc("Cannot communicate with ttyS"+port); }
92     }
93
94     /** move to the position between the two limit switches.
95      */

96     protected void findCenter() {
97     try {
98         synchronized (rf[port]) {
99         rf[port].writeByte(1);
100         rf[port].writeBytes(""+axis);
101         rf[port].writeBytes("fe");
102         rf[port].writeByte(13);
103         }
104     }
105     catch (IOException e) { throw new RuntimeException JavaDoc("Cannot communicate with ttyS"+port); }
106     }
107   
108     /////////////////////////////////////////////////////////////////////////////////////////////
109
// Position
110

111     /** move the device to the given position.
112      * Checking the limits must be done (if necessary) by the extending class (note this class is abstract!)
113      * @param p the position that we want to reach, in counts.
114      * It is rounded to its nearest integer position
115      */

116     public void setPosition(double p) {
117     if (p==currPos) return;
118     currPos=p;
119     doSetPosition(p);
120     persPref.putDouble("zero-"+port+"-"+axis,p);
121     fireStateChanged();
122     }
123
124     /* actually set the position. */
125     private void doSetPosition(double p) {
126     try {
127         synchronized (rf[port]) {
128         rf[port].writeByte(1);
129         rf[port].writeBytes(""+axis);
130         rf[port].writeBytes("ma"+(long)(p-bias));
131         rf[port].writeByte(13);
132         }
133     } catch (IOException e) { throw new RuntimeException JavaDoc("Cannot communicate with ttyS"+port); }
134     }
135     
136     /** get the position.
137      * @return the position in counts.
138      * It is alwais an integer value
139      */

140     public double getPosition() {
141     if (Double.isNaN(currPos)) currPos=doGetPosition();
142     return Math.rint(currPos);
143     }
144     private double currPos = Double.NaN;
145     /* actually get the position */
146     public double doGetPosition() {
147     double p = 0.0;
148     try {
149         synchronized (rf[port]) {
150         rf[port].writeByte(1);
151         rf[port].writeBytes(""+axis);
152         rf[port].writeBytes("tt");
153         rf[port].writeByte(13);
154         p=Double.parseDouble(readLine().substring(2));
155         }
156     } catch (IOException e) { throw new RuntimeException JavaDoc("Cannot communicate with ttyS"+port); }
157     return p+bias;
158     }
159
160     /** get the actual position while the axis is moving.
161      * @return the position in counts.
162      * It is alwais an integer value
163      */

164     public double getActualPosition() {
165     double p = 0.0;
166     try {
167         synchronized (rf[port]) {
168         rf[port].writeByte(1);
169         rf[port].writeBytes(""+axis);
170         rf[port].writeBytes("tp");
171         rf[port].writeByte(13);
172         p=Double.parseDouble(readLine().substring(2));
173         }
174     } catch (IOException e) { throw new RuntimeException JavaDoc("Cannot communicate with ttyS"+port); }
175     return p+bias;
176     }
177
178     /** get the minimum value of position
179      * @return the minimum position
180      */

181     public double getMinimum() { return Math.rint(persPref.getDouble("min-"+port+"-"+axis,getPosition())); }
182
183     /** get the maximum value of position
184      * @return the maximum position
185      */

186     public double getMaximum() { return Math.rint(persPref.getDouble("max-"+port+"-"+axis,getPosition())); }
187
188     /** set the minimum value of position. Only root can do this.
189      * @param m the minimum position
190      */

191     public void setMinimum(double m) { persPref.putDouble("min-"+port+"-"+axis,m); }
192
193     /** set the maximum value of position. Only root can do this.
194      * @param m the maximum position
195      */

196     public void setMaximum(double m) { persPref.putDouble("max-"+port+"-"+axis,m); }
197
198     /** get the unit in which the position is expressed
199      * @return the units
200      */

201     public String JavaDoc getUnit() {return "counts";}
202
203     /** get the minor step suggested for changing the position
204      * @return the suggested minor step
205      */

206     public double getMinorStep() {return 400.0;}
207
208     /** get the major step suggested for changing the position
209      * @return the suggested major step
210      */

211     public double getMajorStep() {return 4000.0;}
212
213     /** get the error on the actual position.
214      * @return the error on the position in counts.
215      * It is rounded to its nearest integer position.
216      */

217     public double getPositionError() { return doGetPositionError(); }
218
219     /* actually get the error on the actual position.
220      * return the error on the position in counts.
221      * It is rounded to its nearest integer position.
222      */

223     public double doGetPositionError() {
224     double p = 0.0;
225     try {
226         synchronized (rf[port]) {
227         rf[port].writeByte(1);
228         rf[port].writeBytes(""+axis);
229         rf[port].writeBytes("te");
230         rf[port].writeByte(13);
231         p=Double.parseDouble(readLine().substring(2));
232         }
233     } catch (IOException e) { throw new RuntimeException JavaDoc("Cannot communicate with ttyS"+port); }
234     return p;
235     }
236
237     //////////////////////////////////////////////////////////////////////////////////////////////////
238
// Velocity
239

240     /** set the velocity the device will reach when moving.
241      * Checking the limits must be done (if necessary) by the extending class (note this class is abstract!)
242      * @param v the velocity in counts per cycle. It is rounded to its
243      * nearest integer position.
244      */

245     public void setVelocity(double v) {
246     try {
247         synchronized (rf[port]) {
248         rf[port].writeByte(1);
249         rf[port].writeBytes(""+axis);
250         rf[port].writeBytes("sv"+(long)v);
251         rf[port].writeByte(13);
252         }
253     } catch (IOException e) { throw new RuntimeException JavaDoc("Cannot communicate with ttyS"+port); }
254     }
255
256     /** get the velocity that should be reached when moving.
257      * @return the velocity in counts per cycle. It is rounded to its
258      * nearest integer position.
259      */

260     public double getVelocity() {
261     double p = 0.0;
262     try {
263         synchronized (rf[port]) {
264         rf[port].writeByte(1);
265         rf[port].writeBytes(""+axis);
266         rf[port].writeBytes("ty");
267         rf[port].writeByte(13);
268         p=Double.parseDouble(readLine().substring(2));
269         }
270     } catch (IOException e) { throw new RuntimeException JavaDoc("Cannot communicate with ttyS"+port); }
271     return p;
272     }
273
274     /** get the actual velocity while moving.
275      * @return the velocity in counts per cycle. It is rounded to its
276      * nearest integer position.
277      */

278     public double getActualVelocity() {
279     double p = 0.0;
280     try {
281         synchronized (rf[port]) {
282         rf[port].writeByte(1);
283         rf[port].writeBytes(""+axis);
284         rf[port].writeBytes("tv");
285         rf[port].writeByte(13);
286         p=Double.parseDouble(readLine().substring(2));
287         }
288     } catch (IOException e) { throw new RuntimeException JavaDoc("Cannot communicate with ttyS"+port); }
289     return p;
290     }
291
292     /** get the maximum value of velocity
293      * @return the maximum velocity
294      */

295     public double getMaxVelocity() { return Double.POSITIVE_INFINITY; }
296
297     /** get the step suggested for changing the velocity
298      * @return the suggested step
299      */

300     public double getVelocityStep() {return 100000.0;}
301
302     /** get the unit in which the velocity is expressed
303      * @return the units
304      */

305     public String JavaDoc getVelocityUnit() {return "counts/cycle";}
306
307     //////////////////////////////////////////////////////////////////////////////////////////////////
308
// Motor controls
309

310     /** Clear errors
311      */

312     protected void clearErrors() {}
313
314     /** switch the motor on or off.
315      * @param b do you want to switch the motor on?
316      */

317     protected void setMotorOn(boolean b) {
318     try {
319         synchronized (rf[port]) {
320         rf[port].writeByte(1);
321         rf[port].writeBytes(""+axis);
322         if (b) rf[port].writeBytes("mn");
323         else rf[port].writeBytes("mf");
324         rf[port].writeByte(13);
325         }
326     } catch (IOException e) { throw new RuntimeException JavaDoc("Cannot communicate with ttyS"+port); }
327     motor_on=b;
328     }
329     private boolean motor_on = true;
330
331     /** check if the motor is on or off.
332      * @return the motor is on?
333      */

334     protected boolean getMotorOn() { return motor_on; }
335
336     /** switch the brake on or off.
337      * @param b do you want to switch the brake on?
338      */

339     protected void setBrake(boolean b) {
340     try {
341         synchronized (rf[port]) {
342         rf[port].writeByte(1);
343         rf[port].writeBytes(""+axis);
344         if (b) rf[port].writeBytes("bn");
345         else rf[port].writeBytes("bf");
346         rf[port].writeByte(13);
347         }
348     } catch (IOException e) { throw new RuntimeException JavaDoc("Cannot communicate with ttyS"+port); }
349     brake_on=b;
350     }
351     private boolean brake_on;
352
353     /** check if the brake is on or off.
354      * @return the brake is on?
355      */

356     protected boolean getBrake() { return brake_on; }
357
358
359
360     /** get the status of event. CURRENTLY NOT IMPLEMENTED.
361      * @return the properties of the event.
362      */

363     protected Hashtable getEventStatus() { return null; }
364     protected static final String JavaDoc EVENT_MOTION_COMPLETE = "Motion complete";
365     protected static final String JavaDoc EVENT_WRAP_AROUND = "Wrap around";
366     protected static final String JavaDoc EVENT_BREAKPOINT1 = "Breakpoint 1";
367     protected static final String JavaDoc EVENT_CAPTURE_RECEIVED = "Capture received";
368     protected static final String JavaDoc EVENT_MOTION_ERROR = "Motion error";
369     protected static final String JavaDoc EVENT_POS_LIMIT = "Positive limit";
370     protected static final String JavaDoc EVENT_NEG_LIMIT = "Negative limit";
371     protected static final String JavaDoc EVENT_INSTRUCTION_ERR = "Instruction error";
372     protected static final String JavaDoc EVENT_COMMUNICATION_ERR = "Communication error";
373     protected static final String JavaDoc EVENT_BREAKPOINT2 = "Breakpoint 2";
374
375     /** get the status of signal. CURRENTLY NOT IMPLEMENTED.
376      * @return the properties of the signal.
377      */

378     protected Hashtable getSignalStatus() { return null; }
379     protected static final String JavaDoc SIGNAL_ENCODER_A = "Encoder A";
380     protected static final String JavaDoc SIGNAL_ENCODER_B = "Encoder B";
381     protected static final String JavaDoc SIGNAL_ENCODER_INDEX = "Encoder index";
382     protected static final String JavaDoc SIGNAL_ENCODER_HOME = "Encoder home";
383     protected static final String JavaDoc SIGNAL_POS_LIMIT = "Positive limit";
384     protected static final String JavaDoc SIGNAL_NEG_LIMIT = "Negative limit";
385     protected static final String JavaDoc SIGNAL_AXIS_IN = "Axis in";
386     protected static final String JavaDoc SIGNAL_HALL_A = "Hall A";
387     protected static final String JavaDoc SIGNAL_HALL_B = "Hall B";
388     protected static final String JavaDoc SIGNAL_HALL_C = "Hall C";
389     protected static final String JavaDoc SIGNAL_AXIS_OUT = "Axis out";
390     protected static final String JavaDoc SIGNAL_STEP_OUTPUT = "Step output";
391     protected static final String JavaDoc SIGNAL_MOTOR_OUTPUT = "Motor output";
392
393
394     /** get the status of activity. CURRENTLY NOT IMPLEMENTED.
395      * @return the property of activity
396      */

397     protected Hashtable getActivityStatus() { return null; }
398     protected static final String JavaDoc ACTIVITY_PHASING_INITD = "Not for the PI boards!!!";
399     protected static final String JavaDoc ACTIVITY_MAX_VELOCITY = "Running at max velocity";
400     protected static final String JavaDoc ACTIVITY_TRACKING = "Tracking";
401     protected static final String JavaDoc ACTIVITY_PROFILE_MODE_0 = "Profile mode 0";
402     protected static final String JavaDoc ACTIVITY_PROFILE_MODE_1 = "Profile mode 1";
403     protected static final String JavaDoc ACTIVITY_PROFILE_MODE_2 = "Profile mode 2";
404     protected static final String JavaDoc ACTIVITY_RESERVED = "Reserved";
405     protected static final String JavaDoc ACTIVITY_AXIS_SETTLED = "Setteled";
406     protected static final String JavaDoc ACTIVITY_MOTOR_STATUS = "Motor status";
407     protected static final String JavaDoc ACTIVITY_POSITION_CAPTURE = "Position capture";
408     protected static final String JavaDoc ACTIVITY_IN_MOTION = "In motion";
409     protected static final String JavaDoc ACTIVITY_ACT_POS_LIMIT = "Actual positive limit";
410     protected static final String JavaDoc ACTIVITY_ACT_NEG_LIMIT = "Actual negative limit";
411
412
413     /** sleep until the axis has reached its position */
414     public void sleep() {
415     do {
416         try {
417         Thread.sleep(200);
418         }
419         catch (InterruptedException JavaDoc e) {}
420     } while (Math.abs(doGetPositionError())>19.5);
421     }
422
423     ///////////////////////////////////////////////////////////////////////////////////////////////
424
// Visual Component
425

426
427     /** Create a JPanel with the controls of the position
428      * @param monitor monitor the actual position every 0.1 s.
429      * @param vertical the direction of motion is vertical
430      * @param inverted invert the direction of motion
431      */

432     protected JPanel createPositionPanel(boolean monitor,boolean vertical, boolean inverted) {
433     final JButton setLimits = new JButton("Limits");
434     final JSpinner spinner;
435     JButton plus,minus;
436     JPanel fastMovement = new JPanel();
437     JPanel r = new JPanel();
438     fastMovement.setLayout(new BorderLayout());
439     r.setLayout(new FlowLayout());
440     if (vertical) {
441         plus = new JButton("^");
442         minus = new JButton("v");
443         fastMovement.add("North",plus);
444         fastMovement.add("South",minus);
445     }
446     else {
447         plus = new JButton(">");
448         minus = new JButton("<");
449         fastMovement.add("East",plus);
450         fastMovement.add("West",minus);
451     }
452     spinner=new JSpinner(new SpinnerNumberModel(getPosition(),getMinimum(),getMaximum(),getMinorStep()));
453
454     Dimension dim = spinner.getPreferredSize();
455     dim.setSize(100,dim.getHeight());
456     spinner.setPreferredSize(dim);
457
458     r.add(spinner);
459     r.add(new JLabel("("+getUnit()+")"));
460     r.add(fastMovement);
461
462     if (monitor) {
463         final JSpinner actpos;
464         actpos = new JSpinner(new SpinnerNumberModel(getPosition(),getMinimum(),getMaximum(),getMinorStep() ));
465         dim = actpos.getPreferredSize();
466         dim.setSize(100,dim.getHeight());
467         actpos.setPreferredSize(dim);
468         actpos.setEnabled(false);
469         r.add(new JLabel("Actual: "));
470         r.add(actpos);
471         r.add(new JLabel("("+getUnit()+")"));
472         class ActposChangeListener implements ChangeListener,Runnable JavaDoc {
473         private boolean running = false;
474         public void run() {
475             Thread JavaDoc t = new Thread JavaDoc(new Runnable JavaDoc() {
476                 public void run() { sleep(); running=false; }
477             });
478             t.setDaemon(true);
479             t.start();
480             do {
481             actpos.setValue(new Double JavaDoc(getActualPosition()));
482             try { Thread.sleep(100); } catch (InterruptedException JavaDoc e) {}
483             } while (running);
484             actpos.setValue(new Double JavaDoc(getActualPosition()));
485         }
486         public void stateChanged(ChangeEvent event) {
487             if (running) return;
488             Thread JavaDoc t = new Thread JavaDoc(this);
489             t.setDaemon(true);
490             running=true;
491             t.start();
492         }
493         }
494         addChangeListener(new ActposChangeListener());
495     }
496
497     if (!inverted) {
498         minus.addActionListener(new ActionListener() {
499             public void actionPerformed(ActionEvent e) {
500             double p=getPosition()-getMajorStep();
501             if (p>=getMinimum()) spinner.setValue(new Double JavaDoc(p));
502             }
503         });
504         plus.addActionListener(new ActionListener() {
505             public void actionPerformed(ActionEvent e) {
506             double p=getPosition()+getMajorStep();
507             if (p<=getMaximum()) spinner.setValue(new Double JavaDoc(p));
508             }
509         });
510     }
511     else {
512         minus.addActionListener(new ActionListener() {
513             public void actionPerformed(ActionEvent e) {
514             double p=getPosition()+getMajorStep();
515             if (p<=getMaximum()) spinner.setValue(new Double JavaDoc(p));
516             }
517         });
518         plus.addActionListener(new ActionListener() {
519             public void actionPerformed(ActionEvent e) {
520             double p=getPosition()-getMajorStep();
521             if (p>=getMinimum()) spinner.setValue(new Double JavaDoc(p));
522             }
523         });
524     }
525     spinner.addChangeListener(new ChangeListener() {
526         public void stateChanged(ChangeEvent event) {
527             double p=((Double JavaDoc)spinner.getValue()).doubleValue();
528             setPosition(p);
529         }
530         });
531     addChangeListener(new ChangeListener() {
532         public void stateChanged(ChangeEvent event) {
533             spinner.setValue(new Double JavaDoc(getPosition()));
534         }
535         });
536
537     r.add(setLimits);
538     setLimits.addActionListener(new ActionListener() {
539         public void actionPerformed(ActionEvent e) {
540             if (setLimitsDialog==null) setLimits();
541             if (!setLimitsDialog.isVisible()) setLimitsDialog.setVisible(true);
542             setLimitsDialog.toFront();
543         }
544         });
545
546     r.setBorder(
547             BorderFactory.createTitledBorder(
548                              BorderFactory.createEtchedBorder(),
549                              "Position"
550                              )
551             );
552     return r;
553     }
554
555     /** Create a JPanel with the controls of the velocity
556      * @param monitor monitor the actual velocity every 0.1 s.
557      */

558     protected JPanel createVelocityPanel(boolean monitor) {
559     final JSpinner vel;
560     final JRadioButton inMotion;
561     JPanel r = new JPanel();
562     r.setLayout(new FlowLayout());
563     vel = new JSpinner(new SpinnerNumberModel(getVelocity(),0.0,getMaxVelocity(),getVelocityStep()));
564     inMotion = new JRadioButton("In motion");
565     inMotion.setSelected(false);
566     inMotion.setEnabled(false);
567
568     Dimension dim = vel.getPreferredSize();
569     dim.setSize(100,dim.getHeight());
570     vel.setPreferredSize(dim);
571
572     r.add(vel);
573     r.add(new JLabel("("+getVelocityUnit()+")"));
574
575     if (monitor) {
576         final JSpinner actvel;
577         actvel = new JSpinner(new SpinnerNumberModel(getActualVelocity(),-getMaxVelocity(),getMaxVelocity(),getVelocityStep()) );
578
579         dim = actvel.getPreferredSize();
580         dim.setSize(100,dim.getHeight());
581         actvel.setPreferredSize(dim);
582         actvel.setEnabled(false);
583         r.add(new JLabel("Actual: "));
584         r.add(actvel);
585         r.add(new JLabel("("+getVelocityUnit()+")"));
586         class ActvelChangeListener implements ChangeListener,Runnable JavaDoc {
587         private boolean running = false;
588         public void run() {
589             Thread JavaDoc t = new Thread JavaDoc(new Runnable JavaDoc() {
590                 public void run() {
591                 inMotion.setSelected(true);
592                 sleep();
593                 running=false;
594                 inMotion.setSelected(false);
595                 }
596             });
597             t.setDaemon(true);
598             t.start();
599             do {
600             actvel.setValue(new Double JavaDoc(getActualVelocity()));
601             try { Thread.sleep(100); } catch (InterruptedException JavaDoc e) {}
602             } while (running);
603             actvel.setValue(new Double JavaDoc(getActualVelocity()));
604         }
605         public void stateChanged(ChangeEvent event) {
606             if (running) return;
607             Thread JavaDoc t = new Thread JavaDoc(this);
608             t.setDaemon(true);
609             running=true;
610             t.start();
611         }
612         }
613         addChangeListener(new ActvelChangeListener());
614     }
615
616     r.add(inMotion);
617
618     vel.addChangeListener(new ChangeListener() {
619         public void stateChanged(ChangeEvent event) {
620             double v=((Double JavaDoc)vel.getValue()).doubleValue();
621             setVelocity(v);
622         }
623         });
624
625     r.setBorder(
626             BorderFactory.createTitledBorder(
627                              BorderFactory.createEtchedBorder(),
628                              "Velocity"
629                              )
630             );
631     return r;
632     }
633
634     /** Create a JPanel with buttons for controlling the motor.<br>
635      * ATTENZIONE! NON E' COMPLETO!!!
636      */

637     protected JPanel createButtonControlPanel() {
638     JPanel r = new JPanel();
639     JButton
640         bFindHome,bSetMotorOn,
641         bSetBrake,bSetMotorMode,bSetOutputMode,
642         bClearErrors;
643     r.setLayout(new FlowLayout());
644         
645     bFindHome = new JButton("Find home");
646     bSetMotorOn = new JButton("Motor ON");
647     bSetBrake = new JButton("Brake ON");
648     bSetMotorMode = new JButton("Motor mode 1");
649     bSetOutputMode = new JButton("DAC");
650     bClearErrors = new JButton("Clear error");
651
652     bFindHome.addActionListener(new ActionListener() {
653         public void actionPerformed(ActionEvent e) {
654             findCenter();
655         }
656         });
657     bSetMotorOn.addActionListener(new ActionListener() {
658         public void actionPerformed(ActionEvent e) {
659             setMotorOn(!getMotorOn());
660         }
661         });
662     bSetBrake.addActionListener(new ActionListener() {
663         public void actionPerformed(ActionEvent e) {
664             setBrake(!getBrake());
665         }
666         });
667     bClearErrors.addActionListener(new ActionListener() {
668         public void actionPerformed(ActionEvent e) {
669             clearErrors();
670         }
671         });
672     
673     r.add(bFindHome);
674     r.add(bSetMotorOn);
675     r.add(bSetBrake);
676     r.add(bClearErrors);
677
678     r.setBorder(
679             BorderFactory.createTitledBorder(
680                              BorderFactory.createEtchedBorder(),
681                              "Motor controls"
682                              )
683             );
684     return r;
685     }
686
687
688     /** The motor can be controlled by a visual component, with buttons,
689      * sliders and so on. Call this to get the Component (actually, a JPanel).
690      * This component displays also many informations.
691      */

692     public abstract Component getControlComponent();
693
694
695     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
696
// createMotorDevice()
697

698     /** The C-150.PD motor */
699     public static final String JavaDoc C150PD = "C-150.PD";
700     /** The C-136.10 motor */
701     public static final String JavaDoc C136 = "C-136.10";
702     /** The M-126.PD motor */
703     public static final String JavaDoc M126PD = "M-126.PD";
704     /** A generic motor driven by Mercury */
705     public static final String JavaDoc RAW = "Raw";
706
707     /** Call this to build a driver for a given motor, instead of calling the constructor.
708      * @param t the type of motor connected to the board (see RAW,C150PD, C136, M126PD).
709      * @param p the number of the ttyS port
710      * @param n the number of the axis
711      * @param gf if there's a mechanical device such as a gear, gf is the ratio final motion/motor motion. gf=1 for RAW.
712      */

713     public static Mercury createMotorDevice(String JavaDoc t,int p,int n, double gf) {
714     if (gf==0.0) throw(new IllegalArgumentException JavaDoc("Gear factor = 0"));
715     if (!( t.equals(RAW) || t.equals(C150PD) || t.equals(C136) || t.equals(M126PD) ))
716         throw(new IllegalArgumentException JavaDoc("Motor type not supported"));
717     if ( t.equals(RAW) && gf!=1.0 ) throw(new IllegalArgumentException JavaDoc("Gear factor must be 1.0 for Row motor type"));
718     Mercury c = null;
719     final JPanel ccomp = new JPanel();
720     final double rpc;
721     final double vpc;
722     final double maxv;
723     final String JavaDoc propname = "vel-"+p+"-"+n+"-"+t;
724     final String JavaDoc posUnit;
725     final String JavaDoc velUnit;
726     if (t.equals(RAW)) {
727         rpc = 1.0;
728         vpc = 1.0;
729         maxv = Double.POSITIVE_INFINITY;
730         posUnit = "counts";
731         velUnit = "counts/s";
732     }
733     else if (t.equals(C150PD)) {
734         rpc = gf/4000.0;
735         vpc = gf/4000.0;
736         maxv = 100.0 * Math.abs(gf);
737         posUnit = "turns";
738         velUnit = "turns/s";
739     }
740     else if (t.equals(C136)) {
741         rpc = gf / 2000.0;
742         vpc = gf / 2000.0;
743         maxv = 3.3 * Math.abs(gf) ;
744         posUnit = "turns";
745         velUnit = "turns/s";
746     }
747     else {
748         if (! t.equals(M126PD)) throw new IllegalArgumentException JavaDoc("Unknown motor type: "+t);
749         rpc = 0.5/4000.0 * gf;
750         vpc = 0.5/4000.0 * gf;
751         maxv = 15.0 * Math.abs(gf);
752         posUnit = "mm";
753         velUnit = "mm/s";
754     }
755     
756     c = new Mercury(p,n) {
757         public void setPosition(double p) { if (p>=getMinimum() && p<=getMaximum()) super.setPosition(p/rpc); }
758         public double getPosition() { return super.getPosition()*rpc; }
759         public double getActualPosition() { return super.getActualPosition()*rpc; }
760         public double getMinimum() { return rpc*((rpc>0.0)?super.getMinimum():super.getMaximum()); }
761         public double getMaximum() { return rpc*((rpc>0.0)?super.getMaximum():super.getMinimum()); }
762         public void setMinimum(double m) { if (rpc>0.0) super.setMinimum(m/rpc); else super.setMaximum(m/rpc); }
763         public void setMaximum(double m) { if (rpc>0.0) super.setMaximum(m/rpc); else super.setMinimum(m/rpc); }
764         public String JavaDoc getUnit() { return posUnit; }
765         public double getMinorStep() { return super.getMinorStep()*Math.abs(rpc);}
766         public double getMajorStep() { return super.getMajorStep()*Math.abs(rpc);}
767         public double getPositionError() { return super.getPositionError()*rpc; }
768         public void setVelocity(double v) {
769             if (v>0.0 && v<getMaxVelocity()) {
770             super.setVelocity(v/Math.abs(vpc));
771             super.persPref.putDouble(propname,v);
772             }
773         }
774         public double getVelocity() { return super.getVelocity()*Math.abs(vpc); }
775         public double getActualVelocity() { return super.getActualVelocity()*vpc; }
776         public double getMaxVelocity() { return maxv; }
777         public double getVelocityStep() { return super.getVelocityStep()*Math.abs(vpc); }
778         public String JavaDoc getVelocityUnit() { return velUnit; }
779         public Component getControlComponent() { return ccomp; }
780         };
781     if (t.equals(M126PD)) c.setLimitSwitches(true);
782     if ( ! t.equals(RAW)) c.setMotorOn(true);
783
784     if (!(c.getPosition()>=c.getMinimum() && c.getPosition()<=c.getMaximum())) throw new IllegalArgumentException JavaDoc("( Minimum <= Position <= Maximum ) failed");
785
786     c.type=t;
787     c.setVelocity(c.persPref.getDouble("vel-"+c.port+"-"+c.axis+"-"+c.type,0.1));
788
789     ccomp.setLayout(new BorderLayout());
790     if (t.equals(M126PD)) ccomp.add("North",c.createPositionPanel(true,true,false));
791     else ccomp.add("North",c.createPositionPanel(true,false,false));
792     ccomp.add("Center",c.createVelocityPanel(true));
793     //ccomp.add("South",c.createButtonControlPanel());
794

795     ccomp.setBorder(
796             BorderFactory.createTitledBorder(
797                              BorderFactory.createEtchedBorder(),
798                              "ttyS"+p+" Axis "+n+" "+t
799                              )
800             );
801     return c;
802     }
803     
804     /** Call this to build a driver for a given motor, instead of calling the constructor.
805      * @param t the type of motor connected to the board (see RAW,C150PD, C136, M126PD).
806      * @param n the number of the axis
807      */

808     public static Mercury createMotorDevice(String JavaDoc t,int p,int n) {
809     return createMotorDevice(t,p,n,1.0);
810     }
811
812
813
814     /** Report port number, device number and version */
815     public String JavaDoc toString() {
816     return getClass().getName()+
817             "[\nPort=ttyS"+port+",axis="+axis+",type="+type+",version="+version+"]";
818     }
819
820     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
821
// Main
822

823  
824     private static void printHelp() {
825     System.out.println(
826                "Useful controls for the Mercury board. Parameters can be supplied.\n"+
827                "Syntax:\n"+
828                "java it.unimi.pi.Mercury {options} {commands}\n"+
829                "The options can be:\n"+
830                "-h : print the help\n"+
831                "-m type : set the motor type (\"Raw\" by default)\n"+
832                "-p ttyS_number : set the ttyS port number (0 by default)\n"+
833                "-n axis_number : set the axis number (0 by default)\n"+
834                "-g gear_factor : set the gear factor (1 by default)\n"+
835                "The commands can be:\n"+
836                "setMinimum position : set the minimum of the position (only root can do this)\n"+
837                "setMaximum position : set the maximum of the position (only root can do this)\n"+
838                "setPosition position : move the motor to the given position\n"+
839                "setLimits : graphical interface for setting limits of the given motor (only root can do this)\n"+
840                "monitor : open a window with the control component for the desired motor.\n"+
841                "motors : print a list of known motor types. \"Raw\" is a generic motor, with the\n"+
842                "units used by the board.\n"
843                );
844     System.exit(0);
845     }
846
847     /** Useful controls for the Mercury board. Parameters can be supplied.<br>
848      * Syntax:<br>
849      * <code>java it.unimi.pi.Mercury {options} {commands}</code><br>
850      * The options can be:<br>
851      * -h : print the help<br>
852      * -m type : set the motor type ("Raw" by default)<br>
853      * -p ttyS_number : set the ttyS port number (0 by default)<br>
854      * -n axis_number : set the axis number (0 by default)<br>
855      * -g gear_factor : set the gear factor (1 by default)<br>
856      * The commands can be:<br>
857      * setMinimum position : set the minimum of the position (only root can do this)<br>
858      * setMaximum position : set the maximum of the position (only root can do this)<br>
859      * setPosition position : move the motor to the given position<br>
860      * setLimits : graphical interface for setting limits of the given motor (only root can do this)<br>
861      * monitor : open a window with the control component for the desired motor.<br>
862      * motors : print a list of known motor types. "Raw" is a generic motor, with the
863      * units used by the board.<br>
864      */

865     public static void main(String JavaDoc [] args) {
866     String JavaDoc t="Raw";
867     int a=0;
868     double gf=1.0;
869     int p=0;
870     int n=0;
871     while (n<args.length) {
872         if (args[n].equals("-m")) {
873         n++;
874         if (n>=args.length) printHelp();
875         t=args[n];
876         } else
877         if (args[n].equals("-p")) {
878             n++;
879             if (n>=args.length) printHelp();
880             p=Integer.parseInt(args[n]);
881         } else
882             if (args[n].equals("-n")) {
883             n++;
884             if (n>=args.length) printHelp();
885             a=Integer.parseInt(args[n]);
886             } else
887             if (args[n].equals("-g")) {
888                 n++;
889                 if (n>=args.length) printHelp();
890                 gf=Double.parseDouble(args[n]);
891             } else
892                 if (args[n].equals("-h")) printHelp();
893                 else break;
894         n++;
895     }
896
897     Mercury c = createMotorDevice(t,p,a,gf);
898
899     while (n<args.length) {
900         if (args[n].equals("setMinimum")) {
901         n++;
902         if (n>=args.length) printHelp();
903         c.setMinimum(Double.parseDouble(args[n]));
904         } else
905         if (args[n].equals("setMaximum")) {
906             n++;
907             if (n>=args.length) printHelp();
908             c.setMaximum(Double.parseDouble(args[n]));
909         } else
910             if (args[n].equals("setPosition")) {
911             n++;
912             if (n>=args.length) printHelp();
913             c.setPosition(Double.parseDouble(args[n]));
914             } else
915             if (args[n].equals("setLimits"))
916                 c.setLimits();
917             else
918                 if (args[n].equals("monitor")) {
919                 JFrame frm = new JFrame("Mercury");
920                 frm.getContentPane().add(c.getControlComponent());
921                 frm.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
922                 frm.pack();
923                 frm.show();
924                 } else
925                 if (args[n].equals("motors")) {
926                     System.out.println("Supported motor types:\nRaw\nC-150.PD\nC-136.10\nM-126.PD\n\n");
927                 } else printHelp();
928         n++;
929     }
930     }
931     
932
933     /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
934
// Graphical configuration of the limits
935

936     JFrame setLimitsDialog = null;
937     /** runs a graphical configuration of the limits. Only root can do this.
938      * This operation allows the movement of the device outside the current limits; this could
939      * damage the device.
940      */

941     public void setLimits() {
942     setLimitsDialog = new JFrame("Axis "+axis+" "+type+" Set limits");
943     final JSpinner min = new JSpinner(new SpinnerNumberModel(getMinimum(),Double.NEGATIVE_INFINITY,getPosition(),getMinorStep()));
944     final JSpinner pos = new JSpinner(new SpinnerNumberModel(getPosition(),getMinimum(),getMaximum(),getMinorStep()));
945     final JSpinner max = new JSpinner(new SpinnerNumberModel(getMaximum(),getPosition(),Double.POSITIVE_INFINITY,getMinorStep()));
946     final JRadioButton rbPos = new JRadioButton("None",true);
947     final JRadioButton rbMin = new JRadioButton("Min",false);
948     final JRadioButton rbMax = new JRadioButton("Max",false);
949     JButton toMin = new JButton("Move to min");
950     JButton toMax = new JButton("Move to max");
951     ButtonGroup bg = new ButtonGroup();
952     bg.add(rbPos);bg.add(rbMin);bg.add(rbMax);
953
954     min.addChangeListener(new ChangeListener() {
955         public void stateChanged(ChangeEvent e) {
956             double v = ((Double JavaDoc)min.getValue()).doubleValue();
957             setMinimum(v);
958             if (rbPos.isSelected())
959             ((SpinnerNumberModel)pos.getModel()).setMinimum(new Double JavaDoc(getMinimum()));
960             if (rbMin.isSelected()) {
961             pos.setValue(new Double JavaDoc(getMinimum()));
962             ((SpinnerNumberModel)pos.getModel()).setMinimum(new Double JavaDoc(getMinimum()));
963             ((SpinnerNumberModel)pos.getModel()).setMaximum(new Double JavaDoc(getMinimum()));
964             ((SpinnerNumberModel)max.getModel()).setMinimum(new Double JavaDoc(getMinimum()));
965             }
966             if (rbMax.isSelected())
967             ((SpinnerNumberModel)max.getModel()).setMinimum(new Double JavaDoc(getMinimum()));
968         }
969         });
970     pos.addChangeListener(new ChangeListener() {
971         private double currPos = 0.0;
972         public void stateChanged(ChangeEvent e) {
973             if (currPos == 0.0) currPos = getPosition();
974             double v = ((Double JavaDoc)pos.getValue()).doubleValue();
975             if (v==currPos) return;
976             currPos=v;
977             setPosition(v);
978             if (rbPos.isSelected()) {
979             ((SpinnerNumberModel)min.getModel()).setMaximum(new Double JavaDoc(getPosition()));
980             ((SpinnerNumberModel)max.getModel()).setMinimum(new Double JavaDoc(getPosition()));
981             }
982         }
983         });
984     max.addChangeListener(new ChangeListener() {
985         public void stateChanged(ChangeEvent e) {
986             double v = ((Double JavaDoc)max.getValue()).doubleValue();
987             setMaximum(v);
988             if (rbPos.isSelected())
989             ((SpinnerNumberModel)pos.getModel()).setMaximum(new Double JavaDoc(getMaximum()));
990             if (rbMin.isSelected())
991             ((SpinnerNumberModel)min.getModel()).setMaximum(new Double JavaDoc(getMaximum()));
992             if (rbMax.isSelected()) {
993             pos.setValue(new Double JavaDoc(getMaximum()));
994             ((SpinnerNumberModel)pos.getModel()).setMinimum(new Double JavaDoc(getMaximum()));
995             ((SpinnerNumberModel)pos.getModel()).setMaximum(new Double JavaDoc(getMaximum()));
996             ((SpinnerNumberModel)min.getModel()).setMaximum(new Double JavaDoc(getMaximum()));
997             }
998         }
999         });
1000
1001    rbPos.addActionListener(new ActionListener() {
1002        public void actionPerformed(ActionEvent e) {
1003            ((SpinnerNumberModel)min.getModel()).setMaximum(new Double JavaDoc(getPosition()));
1004            ((SpinnerNumberModel)max.getModel()).setMinimum(new Double JavaDoc(getPosition()));
1005            ((SpinnerNumberModel)pos.getModel()).setMinimum(new Double JavaDoc(getMinimum()));
1006            ((SpinnerNumberModel)pos.getModel()).setMaximum(new Double JavaDoc(getMaximum()));
1007        }
1008        });
1009    rbMin.addActionListener(new ActionListener() {
1010        public void actionPerformed(ActionEvent e) {
1011            pos.setValue(new Double JavaDoc(getMinimum()));
1012            ((SpinnerNumberModel)min.getModel()).setMaximum(new Double JavaDoc(getMaximum()));
1013            ((SpinnerNumberModel)pos.getModel()).setMinimum(new Double JavaDoc(getMinimum()));
1014            ((SpinnerNumberModel)pos.getModel()).setMaximum(new Double JavaDoc(getMinimum()));
1015            ((SpinnerNumberModel)max.getModel()).setMinimum(new Double JavaDoc(getMinimum()));
1016        }
1017        });
1018    rbMax.addActionListener(new ActionListener() {
1019        public void actionPerformed(ActionEvent e) {
1020            pos.setValue(new Double JavaDoc(getMaximum()));
1021            ((SpinnerNumberModel)max.getModel()).setMinimum(new Double JavaDoc(getMinimum()));
1022            ((SpinnerNumberModel)pos.getModel()).setMinimum(new Double JavaDoc(getMaximum()));
1023            ((SpinnerNumberModel)pos.getModel()).setMaximum(new Double JavaDoc(getMaximum()));
1024            ((SpinnerNumberModel)min.getModel()).setMaximum(new Double JavaDoc(getMaximum()));
1025        }
1026        });
1027
1028    toMin.addActionListener(new ActionListener() {
1029        public void actionPerformed(ActionEvent e) {
1030            if (rbPos.isSelected())
1031            pos.setValue(new Double JavaDoc(getMinimum()));
1032        }
1033        });
1034    toMax.addActionListener(new ActionListener() {
1035        public void actionPerformed(ActionEvent e) {
1036            if (rbPos.isSelected())
1037            pos.setValue(new Double JavaDoc(getMaximum()));
1038        }
1039        });
1040
1041    Dimension dim = min.getPreferredSize();
1042    dim = new Dimension(100,(int)dim.getHeight());
1043    min.setPreferredSize(dim);
1044    dim = pos.getPreferredSize();
1045    dim = new Dimension(100,(int)dim.getHeight());
1046    pos.setPreferredSize(dim);
1047    dim = max.getPreferredSize();
1048    dim = new Dimension(100,(int)dim.getHeight());
1049    max.setPreferredSize(dim);
1050
1051    setLimitsDialog.getContentPane().setLayout(new GridBagLayout());
1052    GridBagConstraints constr = new GridBagConstraints();
1053    constr.fill=GridBagConstraints.NONE;
1054    constr.anchor=GridBagConstraints.EAST;
1055    constr.weightx=0;
1056    constr.weighty=0;
1057
1058    constr.gridx=0;constr.gridy=0;constr.gridwidth=1;constr.gridheight=1;
1059    setLimitsDialog.getContentPane().add(new JLabel("Maximum:"),constr);
1060    constr.gridx=1;constr.gridy=0;constr.gridwidth=1;constr.gridheight=1;
1061    setLimitsDialog.getContentPane().add(max,constr);
1062    constr.gridx=2;constr.gridy=0;constr.gridwidth=1;constr.gridheight=1;
1063    setLimitsDialog.getContentPane().add(new JLabel(getUnit()),constr);
1064    constr.gridx=0;constr.gridy=1;constr.gridwidth=1;constr.gridheight=1;
1065    setLimitsDialog.getContentPane().add(new JLabel("Position:"),constr);
1066    constr.gridx=1;constr.gridy=1;constr.gridwidth=1;constr.gridheight=1;
1067    setLimitsDialog.getContentPane().add(pos,constr);
1068    constr.gridx=2;constr.gridy=1;constr.gridwidth=1;constr.gridheight=1;
1069    setLimitsDialog.getContentPane().add(new JLabel(getUnit()),constr);
1070    constr.gridx=0;constr.gridy=2;constr.gridwidth=1;constr.gridheight=1;
1071    setLimitsDialog.getContentPane().add(new JLabel("Minimum:"),constr);
1072    constr.gridx=1;constr.gridy=2;constr.gridwidth=1;constr.gridheight=1;
1073    setLimitsDialog.getContentPane().add(min,constr);
1074    constr.gridx=2;constr.gridy=2;constr.gridwidth=1;constr.gridheight=1;
1075    setLimitsDialog.getContentPane().add(new JLabel(getUnit()),constr);
1076    constr.gridx=0;constr.gridy=3;constr.gridwidth=1;constr.gridheight=1;
1077    setLimitsDialog.getContentPane().add(new JLabel("Anchor to: "),constr);
1078    constr.anchor=GridBagConstraints.WEST;
1079    constr.gridx=1;constr.gridy=4;constr.gridwidth=1;constr.gridheight=1;
1080    setLimitsDialog.getContentPane().add(rbPos,constr);
1081    constr.gridx=1;constr.gridy=5;constr.gridwidth=1;constr.gridheight=1;
1082    setLimitsDialog.getContentPane().add(rbMin,constr);
1083    constr.gridx=1;constr.gridy=6;constr.gridwidth=1;constr.gridheight=1;
1084    setLimitsDialog.getContentPane().add(rbMax,constr);
1085    constr.anchor=GridBagConstraints.CENTER;
1086    constr.gridx=0;constr.gridy=7;constr.gridwidth=1;constr.gridheight=1;
1087    setLimitsDialog.getContentPane().add(toMin,constr);
1088    constr.gridx=1;constr.gridy=7;constr.gridwidth=1;constr.gridheight=1;
1089    setLimitsDialog.getContentPane().add(toMax,constr);
1090
1091    setLimitsDialog.pack();
1092    setLimitsDialog.setResizable(false);
1093    setLimitsDialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
1094    setLimitsDialog.setVisible(true);
1095    }
1096
1097
1098
1099}
1100
1101
Popular Tags