From cfc4b3a0da699d68bafb7ee9874279e74760f28a Mon Sep 17 00:00:00 2001 From: gac-S_Changer Date: Thu, 11 Oct 2018 13:42:31 +0200 Subject: [PATCH] --- devices/smart_magnet.properties | 4 +- plugins/Commands.form | 645 ++++++++++++++++--------- plugins/Commands.java | 541 +++++++++++++-------- plugins/LaserUE.java | 3 + plugins/MXSC-1.10.0.jar | Bin 262082 -> 262215 bytes script/calibration/ScanX.py | 81 ++++ script/calibration/ScanY.py | 4 +- script/calibration/ToolCalibration3.py | 65 +++ script/data/samples.py | 19 +- script/devices/LaserDistance.py | 2 +- script/devices/RobotSC.py | 3 +- script/devices/Wago.py | 19 +- script/local.py | 24 +- script/motion/dry.py | 6 +- script/motion/mount.py | 2 +- script/motion/move_scanner.py | 18 +- script/motion/scan_pin.py | 86 ++-- script/motion/tools.py | 14 +- 18 files changed, 1025 insertions(+), 511 deletions(-) create mode 100644 script/calibration/ScanX.py create mode 100644 script/calibration/ToolCalibration3.py diff --git a/devices/smart_magnet.properties b/devices/smart_magnet.properties index f8c2f31..5484332 100644 --- a/devices/smart_magnet.properties +++ b/devices/smart_magnet.properties @@ -1,5 +1,5 @@ -#Fri Sep 21 16:29:05 CEST 2018 -holdingCurrent=30.0 +#Wed Oct 03 14:07:43 CEST 2018 +holdingCurrent=50.0 mountCurrent=10.0 remanenceCurrent=-10.0 restingCurrent=10.0 diff --git a/plugins/Commands.form b/plugins/Commands.form index ff1764c..c7911a6 100644 --- a/plugins/Commands.form +++ b/plugins/Commands.form @@ -16,24 +16,36 @@ - - - - + + + + + - + + + + + + + + + + + + - + - + @@ -41,50 +53,21 @@ - + - - - - - - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -92,46 +75,8 @@ - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - @@ -142,21 +87,105 @@ + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + - + @@ -170,46 +199,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -221,16 +210,16 @@ - - + + - + - - + + @@ -272,11 +261,13 @@ + + @@ -302,11 +293,13 @@ + + @@ -329,11 +322,13 @@ + + @@ -344,6 +339,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -352,108 +447,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -462,6 +455,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -480,5 +590,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/Commands.java b/plugins/Commands.java index e5ddfdb..8a73abc 100644 --- a/plugins/Commands.java +++ b/plugins/Commands.java @@ -50,7 +50,7 @@ public class Commands extends Panel { @Override public void onStateChange(State state, State former) { - for (Component c: SwingUtils.getComponentsByType(panelCommands, JComponent.class)){ + for (Component c: SwingUtils.getComponentsByType(this, JComponent.class)){ c.setEnabled(state == State.Ready); } buttonHomingHexiposi.setEnabled(state == State.Ready); @@ -113,13 +113,15 @@ public class Commands extends Panel { // //GEN-BEGIN:initComponents private void initComponents() { - panelCommands = new javax.swing.JPanel(); + pnDry = new javax.swing.JPanel(); + jLabel6 = new javax.swing.JLabel(); + spinnerDryTime = new ch.psi.utils.swing.HorizontalSpinner(); + buttonDry = new javax.swing.JButton(); + spinnerDrySpeed = new ch.psi.utils.swing.HorizontalSpinner(); + jLabel7 = new javax.swing.JLabel(); + ckeckParkOnDry = new javax.swing.JCheckBox(); + pnTransfer = new javax.swing.JPanel(); buttonMount = new javax.swing.JButton(); - buttonUnmount = new javax.swing.JButton(); - buttonGetDewar = new javax.swing.JButton(); - buttonPutDewar = new javax.swing.JButton(); - buttonGetGonio = new javax.swing.JButton(); - buttonPutGonio = new javax.swing.JButton(); jPanel5 = new javax.swing.JPanel(); jLabel4 = new javax.swing.JLabel(); checkForce = new javax.swing.JCheckBox(); @@ -131,25 +133,89 @@ public class Commands extends Panel { jLabel3 = new javax.swing.JLabel(); jLabel5 = new javax.swing.JLabel(); checkDatamatrix = new javax.swing.JCheckBox(); + buttonUnmount = new javax.swing.JButton(); + buttonScanPin = new javax.swing.JButton(); + buttonScanPin1 = new javax.swing.JButton(); + pnLowLevel = new javax.swing.JPanel(); buttonMovePark = new javax.swing.JButton(); - buttonHomingHexiposi = new javax.swing.JButton(); - buttonMoveHome = new javax.swing.JButton(); - buttonMoveGonio = new javax.swing.JButton(); - buttonMoveDewar = new javax.swing.JButton(); - buttonMoveScanner = new javax.swing.JButton(); - buttonMoveHeater = new javax.swing.JButton(); - buttonDry = new javax.swing.JButton(); - spinnerDryTime = new ch.psi.utils.swing.HorizontalSpinner(); - jLabel6 = new javax.swing.JLabel(); - jLabel7 = new javax.swing.JLabel(); - spinnerDrySpeed = new ch.psi.utils.swing.HorizontalSpinner(); - buttonRecover = new javax.swing.JButton(); - buttonEnableAll = new javax.swing.JButton(); buttonMoveCold = new javax.swing.JButton(); + buttonMoveGonio = new javax.swing.JButton(); + buttonMoveHeater = new javax.swing.JButton(); + buttonGetGonio = new javax.swing.JButton(); + buttonPutGonio = new javax.swing.JButton(); + buttonMoveDewar = new javax.swing.JButton(); + buttonMoveHome = new javax.swing.JButton(); + buttonMoveScanner = new javax.swing.JButton(); + buttonGetDewar = new javax.swing.JButton(); + buttonPutDewar = new javax.swing.JButton(); + buttonHomingHexiposi = new javax.swing.JButton(); + pnDatabase = new javax.swing.JPanel(); buttonClearSampleDb = new javax.swing.JButton(); buttonResetPuckIds = new javax.swing.JButton(); + pnMotion = new javax.swing.JPanel(); + buttonRecover = new javax.swing.JButton(); + buttonEnableAll = new javax.swing.JButton(); - panelCommands.setBorder(javax.swing.BorderFactory.createTitledBorder("Commands")); + pnDry.setBorder(javax.swing.BorderFactory.createTitledBorder("Drying")); + + jLabel6.setText("Heat time(s):"); + + spinnerDryTime.setModel(new javax.swing.SpinnerNumberModel(30.0d, 1.0d, 30.0d, 1.0d)); + + buttonDry.setText("Dry"); + buttonDry.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonDryActionPerformed(evt); + } + }); + + spinnerDrySpeed.setModel(new javax.swing.SpinnerNumberModel(0.5d, 0.1d, 10.0d, 1.0d)); + + jLabel7.setText("Speed(%):"); + + ckeckParkOnDry.setText("Park on finish"); + + javax.swing.GroupLayout pnDryLayout = new javax.swing.GroupLayout(pnDry); + pnDry.setLayout(pnDryLayout); + pnDryLayout.setHorizontalGroup( + pnDryLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnDryLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnDryLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(buttonDry, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(ckeckParkOnDry)) + .addGap(18, 18, Short.MAX_VALUE) + .addGroup(pnDryLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jLabel6) + .addComponent(jLabel7)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnDryLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(spinnerDrySpeed, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(spinnerDryTime, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + + pnDryLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonDry, spinnerDrySpeed, spinnerDryTime}); + + pnDryLayout.setVerticalGroup( + pnDryLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnDryLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnDryLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnDryLayout.createSequentialGroup() + .addGroup(pnDryLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(buttonDry) + .addComponent(spinnerDryTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnDryLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(spinnerDrySpeed, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel7) + .addComponent(ckeckParkOnDry))) + .addComponent(jLabel6)) + .addContainerGap()) + ); + + pnTransfer.setBorder(javax.swing.BorderFactory.createTitledBorder("Sample Transfer")); buttonMount.setText("Mount"); buttonMount.addActionListener(new java.awt.event.ActionListener() { @@ -158,57 +224,28 @@ public class Commands extends Panel { } }); - buttonUnmount.setText("Unmount"); - buttonUnmount.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - buttonUnmountActionPerformed(evt); - } - }); - - buttonGetDewar.setText("Get Dewar"); - buttonGetDewar.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - buttonGetDewarActionPerformed(evt); - } - }); - - buttonPutDewar.setText("Put Dewar"); - buttonPutDewar.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - buttonPutDewarActionPerformed(evt); - } - }); - - buttonGetGonio.setText("Get Gonio"); - buttonGetGonio.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - buttonGetGonioActionPerformed(evt); - } - }); - - buttonPutGonio.setText("Put Gonio"); - buttonPutGonio.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - buttonPutGonioActionPerformed(evt); - } - }); - + jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); jLabel4.setText("Force:"); + checkForce.setSelected(true); checkForce.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING); spinnerSample.setModel(new javax.swing.SpinnerNumberModel(1, 1, 16, 1)); spinnerPuck.setModel(new javax.swing.SpinnerNumberModel(1, 1, 5, 1)); + jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); jLabel1.setText("Segment:"); + jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); jLabel2.setText("Puck:"); spinnerSegment.setModel(new javax.swing.SpinnerListModel(new String[] {"A", "B", "C", "D", "E", "F"})); + jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); jLabel3.setText("Sample:"); + jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); jLabel5.setText("Read DM:"); checkDatamatrix.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING); @@ -227,15 +264,17 @@ public class Commands extends Panel { .addComponent(jLabel5)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(spinnerPuck) + .addComponent(spinnerPuck, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(checkForce) .addComponent(checkDatamatrix) - .addComponent(spinnerSample, javax.swing.GroupLayout.DEFAULT_SIZE, 97, Short.MAX_VALUE) - .addComponent(spinnerSegment)) + .addComponent(spinnerSample, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(spinnerSegment, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(0, 0, 0)) ); - jPanel5Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel1, jLabel2, jLabel3}); + jPanel5Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel1, jLabel2, jLabel3, jLabel4, jLabel5}); + + jPanel5Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {spinnerPuck, spinnerSample, spinnerSegment}); jPanel5Layout.setVerticalGroup( jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -263,6 +302,64 @@ public class Commands extends Panel { .addGap(0, 0, 0)) ); + buttonUnmount.setText("Unmount"); + buttonUnmount.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonUnmountActionPerformed(evt); + } + }); + + buttonScanPin.setText("Scan Pin"); + buttonScanPin.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonScanPinActionPerformed(evt); + } + }); + + buttonScanPin1.setText("Scan Puck"); + buttonScanPin1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonScanPin1ActionPerformed(evt); + } + }); + + javax.swing.GroupLayout pnTransferLayout = new javax.swing.GroupLayout(pnTransfer); + pnTransfer.setLayout(pnTransferLayout); + pnTransferLayout.setHorizontalGroup( + pnTransferLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnTransferLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnTransferLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(buttonMount, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonUnmount, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonScanPin, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonScanPin1, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(18, 31, Short.MAX_VALUE) + .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + + pnTransferLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonMount, buttonScanPin, buttonUnmount}); + + pnTransferLayout.setVerticalGroup( + pnTransferLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnTransferLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnTransferLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnTransferLayout.createSequentialGroup() + .addComponent(buttonMount) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(buttonUnmount) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(buttonScanPin) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(buttonScanPin1)) + .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + + pnLowLevel.setBorder(javax.swing.BorderFactory.createTitledBorder("Low-level Motion Commands")); + buttonMovePark.setText("Move Park"); buttonMovePark.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -270,17 +367,10 @@ public class Commands extends Panel { } }); - buttonHomingHexiposi.setText("Homing Hexiposi"); - buttonHomingHexiposi.addActionListener(new java.awt.event.ActionListener() { + buttonMoveCold.setText("Move Cold"); + buttonMoveCold.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { - buttonHomingHexiposiActionPerformed(evt); - } - }); - - buttonMoveHome.setText("Move Home"); - buttonMoveHome.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - buttonMoveHomeActionPerformed(evt); + buttonMoveColdActionPerformed(evt); } }); @@ -291,6 +381,27 @@ public class Commands extends Panel { } }); + buttonMoveHeater.setText("Move Heater"); + buttonMoveHeater.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveHeaterActionPerformed(evt); + } + }); + + buttonGetGonio.setText("Get Gonio"); + buttonGetGonio.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonGetGonioActionPerformed(evt); + } + }); + + buttonPutGonio.setText("Put Gonio"); + buttonPutGonio.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonPutGonioActionPerformed(evt); + } + }); + buttonMoveDewar.setText("Move Dewar"); buttonMoveDewar.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -298,6 +409,13 @@ public class Commands extends Panel { } }); + buttonMoveHome.setText("Move Home"); + buttonMoveHome.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveHomeActionPerformed(evt); + } + }); + buttonMoveScanner.setText("Move Scanner"); buttonMoveScanner.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -305,48 +423,84 @@ public class Commands extends Panel { } }); - buttonMoveHeater.setText("Move Heater"); - buttonMoveHeater.addActionListener(new java.awt.event.ActionListener() { + buttonGetDewar.setText("Get Dewar"); + buttonGetDewar.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { - buttonMoveHeaterActionPerformed(evt); + buttonGetDewarActionPerformed(evt); } }); - buttonDry.setText("Dry"); - buttonDry.addActionListener(new java.awt.event.ActionListener() { + buttonPutDewar.setText("Put Dewar"); + buttonPutDewar.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { - buttonDryActionPerformed(evt); + buttonPutDewarActionPerformed(evt); } }); - spinnerDryTime.setModel(new javax.swing.SpinnerNumberModel(30.0d, 1.0d, 30.0d, 1.0d)); - - jLabel6.setText("Heat time(s):"); - - jLabel7.setText("Speed(%):"); - - spinnerDrySpeed.setModel(new javax.swing.SpinnerNumberModel(0.5d, 0.1d, 10.0d, 1.0d)); - - buttonRecover.setText("Recover"); - buttonRecover.addActionListener(new java.awt.event.ActionListener() { + buttonHomingHexiposi.setText("Homing Hexiposi"); + buttonHomingHexiposi.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { - buttonRecoverActionPerformed(evt); + buttonHomingHexiposiActionPerformed(evt); } }); - buttonEnableAll.setText("Enable Motion"); - buttonEnableAll.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - buttonEnableAllActionPerformed(evt); - } - }); + javax.swing.GroupLayout pnLowLevelLayout = new javax.swing.GroupLayout(pnLowLevel); + pnLowLevel.setLayout(pnLowLevelLayout); + pnLowLevelLayout.setHorizontalGroup( + pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnLowLevelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(buttonMovePark, javax.swing.GroupLayout.PREFERRED_SIZE, 114, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonHomingHexiposi) + .addComponent(buttonMoveCold, javax.swing.GroupLayout.PREFERRED_SIZE, 114, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonMoveHeater) + .addComponent(buttonGetGonio) + .addComponent(buttonGetDewar, javax.swing.GroupLayout.PREFERRED_SIZE, 114, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(buttonPutDewar, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonPutGonio, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonMoveGonio, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonMoveHome, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonMoveDewar, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonMoveScanner)) + .addContainerGap()) + ); - buttonMoveCold.setText("Move Cold"); - buttonMoveCold.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - buttonMoveColdActionPerformed(evt); - } - }); + pnLowLevelLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonGetDewar, buttonGetGonio, buttonHomingHexiposi, buttonMoveCold, buttonMoveDewar, buttonMoveGonio, buttonMoveHeater, buttonMoveHome, buttonMovePark, buttonMoveScanner, buttonPutDewar, buttonPutGonio}); + + pnLowLevelLayout.setVerticalGroup( + pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnLowLevelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonGetDewar) + .addComponent(buttonPutDewar)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonGetGonio) + .addComponent(buttonPutGonio)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonMoveGonio) + .addComponent(buttonHomingHexiposi)) + .addGap(18, 18, 18) + .addGroup(pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonMovePark) + .addComponent(buttonMoveHome)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonMoveDewar) + .addComponent(buttonMoveCold)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonMoveHeater) + .addComponent(buttonMoveScanner)) + .addContainerGap()) + ); + + pnDatabase.setBorder(javax.swing.BorderFactory.createTitledBorder("Database")); buttonClearSampleDb.setText("Clear Sample Db"); buttonClearSampleDb.addActionListener(new java.awt.event.ActionListener() { @@ -362,119 +516,93 @@ public class Commands extends Panel { } }); - javax.swing.GroupLayout panelCommandsLayout = new javax.swing.GroupLayout(panelCommands); - panelCommands.setLayout(panelCommandsLayout); - panelCommandsLayout.setHorizontalGroup( - panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelCommandsLayout.createSequentialGroup() + javax.swing.GroupLayout pnDatabaseLayout = new javax.swing.GroupLayout(pnDatabase); + pnDatabase.setLayout(pnDatabaseLayout); + pnDatabaseLayout.setHorizontalGroup( + pnDatabaseLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnDatabaseLayout.createSequentialGroup() .addContainerGap() - .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(buttonMoveHeater, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE) - .addComponent(buttonClearSampleDb, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(buttonGetDewar, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE) - .addComponent(buttonDry, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(buttonPutDewar, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE) - .addComponent(buttonGetGonio, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE) - .addComponent(buttonPutGonio, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE) - .addComponent(buttonMovePark, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE) - .addComponent(buttonRecover, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(buttonMoveCold, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(buttonMount, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE) - .addComponent(buttonUnmount, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE)) + .addComponent(buttonClearSampleDb) .addGap(18, 18, Short.MAX_VALUE) - .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelCommandsLayout.createSequentialGroup() - .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(buttonMoveScanner, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE) - .addComponent(buttonMoveHome, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE) - .addComponent(buttonMoveDewar, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE) - .addComponent(buttonHomingHexiposi, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE)) - .addGap(1, 1, 1)) - .addComponent(jPanel5, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(buttonEnableAll, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGroup(panelCommandsLayout.createSequentialGroup() - .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(jLabel6) - .addComponent(jLabel7)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(spinnerDrySpeed, javax.swing.GroupLayout.DEFAULT_SIZE, 92, Short.MAX_VALUE) - .addComponent(spinnerDryTime)))) - .addComponent(buttonMoveGonio, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 140, Short.MAX_VALUE) - .addComponent(buttonResetPuckIds, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(buttonResetPuckIds) .addContainerGap()) ); - panelCommandsLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonClearSampleDb, buttonDry, buttonEnableAll, buttonGetDewar, buttonGetGonio, buttonHomingHexiposi, buttonMount, buttonMoveCold, buttonMoveDewar, buttonMoveGonio, buttonMoveHeater, buttonMoveHome, buttonMovePark, buttonMoveScanner, buttonPutDewar, buttonPutGonio, buttonRecover, buttonResetPuckIds, buttonUnmount}); + pnDatabaseLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonClearSampleDb, buttonResetPuckIds}); - panelCommandsLayout.setVerticalGroup( - panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelCommandsLayout.createSequentialGroup() - .addGap(18, 18, 18) - .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addGroup(panelCommandsLayout.createSequentialGroup() - .addComponent(buttonMount) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(buttonUnmount) - .addGap(18, 18, 18) - .addComponent(buttonGetDewar) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(buttonPutDewar)) - .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addGap(18, 18, 18) - .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(buttonGetGonio) - .addComponent(buttonHomingHexiposi)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(buttonPutGonio) - .addComponent(buttonMoveGonio)) - .addGap(18, 18, 18) - .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(buttonMovePark) - .addComponent(buttonMoveHome)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(buttonMoveDewar) - .addComponent(buttonMoveCold)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(buttonMoveHeater) - .addComponent(buttonMoveScanner)) - .addGap(18, 18, 18) - .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(panelCommandsLayout.createSequentialGroup() - .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(buttonDry) - .addComponent(spinnerDryTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(spinnerDrySpeed, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jLabel7))) - .addComponent(jLabel6)) - .addGap(18, 18, 18) - .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + pnDatabaseLayout.setVerticalGroup( + pnDatabaseLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnDatabaseLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnDatabaseLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(buttonClearSampleDb) .addComponent(buttonResetPuckIds)) - .addGap(18, 18, 18) - .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addContainerGap()) + ); + + pnMotion.setBorder(javax.swing.BorderFactory.createTitledBorder("Motion")); + + buttonRecover.setText("Dewar Recovery"); + buttonRecover.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonRecoverActionPerformed(evt); + } + }); + + buttonEnableAll.setText("Enable Motion"); + buttonEnableAll.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonEnableAllActionPerformed(evt); + } + }); + + javax.swing.GroupLayout pnMotionLayout = new javax.swing.GroupLayout(pnMotion); + pnMotion.setLayout(pnMotionLayout); + pnMotionLayout.setHorizontalGroup( + pnMotionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnMotionLayout.createSequentialGroup() + .addContainerGap() + .addComponent(buttonRecover) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonEnableAll) + .addContainerGap()) + ); + + pnMotionLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonEnableAll, buttonRecover}); + + pnMotionLayout.setVerticalGroup( + pnMotionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnMotionLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnMotionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(buttonRecover) .addComponent(buttonEnableAll)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) ); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(panelCommands, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(pnDry, javax.swing.GroupLayout.PREFERRED_SIZE, 314, Short.MAX_VALUE) + .addComponent(pnMotion, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pnDatabase, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pnLowLevel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pnTransfer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(panelCommands, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(layout.createSequentialGroup() + .addComponent(pnDry, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(pnTransfer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(pnLowLevel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(pnDatabase, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(pnMotion, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); }// //GEN-END:initComponents @@ -557,8 +685,9 @@ public class Commands extends Panel { private void buttonDryActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonDryActionPerformed double dryTime = (Double) spinnerDryTime.getValue(); double streamTime = (Double) spinnerDrySpeed.getValue(); + boolean park = ckeckParkOnDry.isSelected(); - execute("dry(" + dryTime + ", " + streamTime + ")"); + execute("dry(" + dryTime + ", " + streamTime + (park ? ", wait_cold=-1": "") + ")"); }//GEN-LAST:event_buttonDryActionPerformed private void buttonRecoverActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonRecoverActionPerformed @@ -577,6 +706,21 @@ public class Commands extends Panel { execute("reset_puck_datamatrix()", true); }//GEN-LAST:event_buttonResetPuckIdsActionPerformed + private void buttonScanPinActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonScanPinActionPerformed + String segment = (String) spinnerSegment.getValue(); + int puck = (Integer) spinnerPuck.getValue(); + int sample = (Integer) spinnerSample.getValue(); + String force = checkForce.isSelected() ? "True" : "False"; + execute("scan_pin('" + segment + "'," + puck + "," + sample + ", force=" + force + ")", false, true); + }//GEN-LAST:event_buttonScanPinActionPerformed + + private void buttonScanPin1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonScanPin1ActionPerformed + String segment = (String) spinnerSegment.getValue(); + int puck = (Integer) spinnerPuck.getValue(); + String force = checkForce.isSelected() ? "True" : "False"; + execute("scan_puck('" + segment + "'," + puck + ", force=" + force + ")", false, true); + }//GEN-LAST:event_buttonScanPin1ActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton buttonClearSampleDb; private javax.swing.JButton buttonDry; @@ -596,9 +740,12 @@ public class Commands extends Panel { private javax.swing.JButton buttonPutGonio; private javax.swing.JButton buttonRecover; private javax.swing.JButton buttonResetPuckIds; + private javax.swing.JButton buttonScanPin; + private javax.swing.JButton buttonScanPin1; private javax.swing.JButton buttonUnmount; private javax.swing.JCheckBox checkDatamatrix; private javax.swing.JCheckBox checkForce; + private javax.swing.JCheckBox ckeckParkOnDry; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; @@ -607,7 +754,11 @@ public class Commands extends Panel { private javax.swing.JLabel jLabel6; private javax.swing.JLabel jLabel7; private javax.swing.JPanel jPanel5; - private javax.swing.JPanel panelCommands; + private javax.swing.JPanel pnDatabase; + private javax.swing.JPanel pnDry; + private javax.swing.JPanel pnLowLevel; + private javax.swing.JPanel pnMotion; + private javax.swing.JPanel pnTransfer; private javax.swing.JSpinner spinnerDrySpeed; private javax.swing.JSpinner spinnerDryTime; private javax.swing.JSpinner spinnerPuck; diff --git a/plugins/LaserUE.java b/plugins/LaserUE.java index ad0c03e..37dd6ee 100644 --- a/plugins/LaserUE.java +++ b/plugins/LaserUE.java @@ -3,6 +3,7 @@ import ch.psi.pshell.device.Readable; import ch.psi.pshell.serial.SerialPortDevice; import ch.psi.pshell.serial.SerialPortDeviceConfig; import static ch.psi.utils.BitMask.*; +import ch.psi.utils.State; import java.io.IOException; /* @@ -35,6 +36,8 @@ public class LaserUE extends SerialPortDevice{ protected void doInitialize() throws IOException, InterruptedException{ super.doInitialize(); //TODO: Start DAQ in ILD1320: http://www.micro-epsilon.com/download/manuals/man--optoNCDT-1320--en.pdf + setState(State.Ready); + write("OUTPUT RS422\n\r"); } public Readable getReadable(){ diff --git a/plugins/MXSC-1.10.0.jar b/plugins/MXSC-1.10.0.jar index d19a2d94bc1ed8265001cb72505cffa28b089cc4..28a93b89eba0fbafff8a104946a95ce3ee4fa8b7 100644 GIT binary patch delta 22849 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
    B)x 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 delta 22728 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: + raise Exception ("Should be near the laser position to perform the scan") + +RANGE = [-2.0, 2.0] #[-1.5, 1.5] +STEP = 0.02 +Z_OFFSET = 0 #-1.0 +LATENCY = 0.025 +BORDER_SIZE = 0.15 + +robot.enable() +robot.set_motors_enabled(True) +current_positon = robot_x.getPosition() +robot_z.moveRel(Z_OFFSET) + +robot.setPolling(25) +try: + ret = lscan(robot_x, ue.readable, RANGE[0], RANGE[1], STEP, latency = LATENCY, relative = True) +finally: + robot.setPolling(DEFAULT_ROBOT_POLLING) + +d = ret.getReadable(0) + +first_index = -1 +last_index = -1 +for i in range(len(d)): + if not math.isnan(d[i]): + if first_index<0: + first_index = i + last_index = i + +if first_index == -1 or last_index < first_index: + raise Exception("Invalid range") + + +remove = int(max(BORDER_SIZE, STEP) / STEP) + +_range = [first_index+remove, last_index-remove] +if _range[1] <= _range[0]: + raise Exception("Invalid range: " + str(_range)) + + +center_index = int((_range[0] + _range[1])/2) +center_positon = ret.getPositions(0)[center_index] + + + + +y = ret.getReadable(0)[_range[0] : _range[1]] +x = ret.getPositions(0)[_range[0]: _range[1]] +#x = enforce_monotonic(x) +#(normalization, mean_val, sigma) = fit_gaussian([-v for v in y], x) + + +closest_x = x[y.indexOf(min(y))] +closest_y = y[y.indexOf(min(y))] + + + +if closest_x is None or closest_x <= ret.getPositions(0)[first_index] or closest_x >= ret.getPositions(0)[last_index]: + raise Exception("Invalid Fit") + + + +center_offset = center_positon-closest_y +#center_offset = current_positon-closest_y + + + +p=get_plots()[0] +p.addMarker(closest_y, p.AxisId.X, str(closest_y), Color.GREEN) + +robot.set_motors_enabled(True) +robot_x.move(closest_x) diff --git a/script/calibration/ScanY.py b/script/calibration/ScanY.py index 8793019..17252f1 100644 --- a/script/calibration/ScanY.py +++ b/script/calibration/ScanY.py @@ -37,14 +37,14 @@ for i in range(len(d)): last_index = i if first_index == -1 or last_index < first_index: - raise Exception("Invalid X detection") + raise Exception("Invalid range") remove = int(max(BORDER_SIZE, STEP) / STEP) _range = [first_index+remove, last_index-remove] if _range[1] <= _range[0]: - raise Exception("invalid range: " + str(_range)) + raise Exception("Invalid range: " + str(_range)) center_index = int((_range[0] + _range[1])/2) diff --git a/script/calibration/ToolCalibration3.py b/script/calibration/ToolCalibration3.py new file mode 100644 index 0000000..e1ee185 --- /dev/null +++ b/script/calibration/ToolCalibration3.py @@ -0,0 +1,65 @@ +import plotutils +from mathutils import fit_gaussian, Gaussian + +cal_tool = TOOL_CALIBRATION + +robot.set_tool(cal_tool) +robot.enable() +move_to_laser() + + +robot.set_motors_enabled(True) +robot.set_joint_motors_enabled(True) +initial_pos = robot.get_cartesian_pos() + +#robot.align() + +run("calibration/ScanX") + +pos1 = robot.get_cartesian_pos() +x1, l1 = closest_x, closest_y + +print "Closest 1: ", [x1, l1] +print "Position 1: ", pos1 + + +pj6 = robot_j6.position +if pj6>0: + robot_j6.move(pj6 - 180.0) +else: + robot_j6.move(pj6 + 180.0) + + +run("calibration/ScanX") + + +x2, l2 = closest_x, closest_y +pos2 = robot.get_cartesian_pos() + +print "Closest 2: ", [x2, l2] +print "Position 2: ", pos2 + + +#Updates the tool +t=robot.get_tool_trsf(TOOL_DEFAULT) + +xoff = (x1-x2)/2 +yoff = (l2 - l1)/2 +xrot = math.degrees(math.atan(yoff/t[2])) +yrot = math.degrees(math.atan(xoff/t[2])) + +print "Former tool: " + str(t) +t[0]=xoff +t[1]=-yoff +print "Offset: ", [t[0], t[1]] + +print "CALIBRATED tool: " + str(t) +#robot.set_tool_trsf(t, TOOL_DEFAULT) + +robot.set_tool(TOOL_DEFAULT) +d = robot.get_distance_to_pnt("pLaser") +if d5: - raise Exception("Invlid pin offset: " + str(val)) + raise Exception("Invalid pin offset: " + str(val)) try: set_setting("pin_offset",float(val)) except: @@ -250,12 +251,31 @@ def get_pin_offset(): try: ret = float(get_setting("pin_offset")) if abs(ret) >5: - raise Exception("Invlid configured pin offset: " + str(ret)) + raise Exception("Invalid configured pin offset: " + str(ret)) return ret except: log("Error getting pin offset: " + str(sys.exc_info()[1]), False) return 0.0 + +def set_pin_angle_offset(val): + if (abs(val) > 180.0) or (abs(val) < -180.0): + raise Exception("Invalid pin angle offset: " + str(val)) + try: + set_setting("pin_angle_offset",float(val)) + except: + log("Error setting pin angle offset: " + str(sys.exc_info()[1]), False) + +def get_pin_angle_offset(): + try: + ret = float(get_setting("pin_angle_offset")) + if (abs(ret) > 180.0) or (abs(ret) < -180.0): + raise Exception("Invalid configured pin angle offset: " + str(ret)) + return ret + except: + log("Error getting pin angle offset: " + str(sys.exc_info()[1]), False) + return 0.0 + def is_force_dry(): try: dry_mount_counter = int(get_setting("dry_mount_counter")) diff --git a/script/motion/dry.py b/script/motion/dry.py index edaae41..1f606ee 100644 --- a/script/motion/dry.py +++ b/script/motion/dry.py @@ -1,6 +1,6 @@ -def dry(heat_time=30.0, speed=0.5, wait_cold = 30.0): +def dry(heat_time=30.0, speed=0.4, wait_cold = 30.0): """ heat_time (float): in seconds speed (float): % of nominal speed @@ -9,7 +9,7 @@ def dry(heat_time=30.0, speed=0.5, wait_cold = 30.0): """ print "dry" - #Initial checks + #Initial chec robot.assert_no_task() robot.reset_motion() robot.wait_ready() @@ -40,4 +40,4 @@ def dry(heat_time=30.0, speed=0.5, wait_cold = 30.0): robot.move_cold() time.sleep(wait_cold) else: - robot.move_dewar() \ No newline at end of file + robot.move_park() \ No newline at end of file diff --git a/script/motion/mount.py b/script/motion/mount.py index ec460db..ca4fbb0 100644 --- a/script/motion/mount.py +++ b/script/motion/mount.py @@ -56,7 +56,7 @@ def mount(segment, puck, sample, force=False, read_dm=False): if read_dm: barcode_reader.start_read(10.0) robot.move_scanner() - time.sleep(1.0) + #time.sleep(1.0) robot.move_gonio() diff --git a/script/motion/move_scanner.py b/script/motion/move_scanner.py index 791e634..b8fe41f 100644 --- a/script/motion/move_scanner.py +++ b/script/motion/move_scanner.py @@ -1,3 +1,4 @@ + def move_scanner(): """ """ @@ -13,14 +14,17 @@ def move_scanner(): #Enabling enable_motion() - #barcode_reader.start_read(20.0) - + barcode_reader.start_read(10.0) if not robot.is_scanner(): robot.move_scanner() - #robot.do_scan() - #dm = barcode_reader.get_readout() - dm = barcode_reader.read(0.5) + time.sleep(0.25) + dm = barcode_reader.get_readout() + if dm is None: + detected = is_pin_detected_in_scanner() + else: + detected = True - print "Datamatrix: " , dm - #print "Datamatrix: " , barcode_reader.wait_readout() \ No newline at end of file + print ("Detected: " + str( detected) + " - Datamatrix: " + str(dm)) + + return (detected, dm) diff --git a/script/motion/scan_pin.py b/script/motion/scan_pin.py index 9824652..7e35def 100644 --- a/script/motion/scan_pin.py +++ b/script/motion/scan_pin.py @@ -1,48 +1,42 @@ -segment, puck, sample, force = "B",1,1, True -pin_name = get_sample_name(segment, puck, sample) +def scan_pin(segment, puck, sample, force=False): + pin_name = get_sample_name(segment, puck, sample) + + print "scan pin", pin_name + #Initial checks + assert_valid_address(segment, puck, sample) + assert_puck_detected(segment, puck) + + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + + #Enabling + + set_status("Scanning pin: " + str(pin_name)) + + enable_motion() + set_hexiposi(segment) + if not force: + visual_check_hexiposi(segment) + + if not robot.is_dewar(): + robot.move_dewar() + + robot.get_dewar(segment, puck, sample) + + (detected, dm) = move_scanner() + update_samples_info_sample_scan(get_puck_name(segment, puck), sample, detected, dm) + + robot.move_dewar() + robot.put_dewar(segment, puck, sample) + return (detected, dm) -print "scan pin", pin_name -#Initial checks -robot.assert_no_task() -robot.reset_motion() -robot.wait_ready() -robot.assert_cleared() -#robot.assert_in_known_point() - -#Enabling - -set_status("Scanning pin: " + str(pin_name)) - -enable_motion() -set_hexiposi(segment) -if not force: - visual_check_hexiposi(segment) - - -robot.move_park() - -gripper_cam.update() -background_img = gripper_cam.getImage() - - -if not robot.is_dewar(): - robot.move_dewar() - -robot.get_dewar(segment, puck, sample) - -robot.move_park() -gripper_cam.update() -sample_img = gripper_cam.getImage() - -barcode_reader.start_read(10.0) -robot.move_scanner() -time.sleep(1.0) - -mount_sample_id = barcode_reader.get_readout() -print "Datamatrix: " , mount_sample_id - -robot.move_dewar() -robot.put_dewar(segment, puck, sample) - - \ No newline at end of file + +def scan_puck(segment, puck, force=False): + ret = [] + for i in range(16): + ret.append(scan_pin (segment, puck, i+1, force)) + return ret diff --git a/script/motion/tools.py b/script/motion/tools.py index b2aefb2..40e141e 100644 --- a/script/motion/tools.py +++ b/script/motion/tools.py @@ -155,4 +155,16 @@ def get_sample_name(segment, puck, sample): puck_name = get_puck_name(segment, puck) return None if (puck_name is None) else puck_name + str(sample) - \ No newline at end of file + +def is_pin_detected_in_scanner(): + samples = [] + for i in range(10): + samples.append(laser_distance.read()) + time.sleep(0.05) + av = mean(samples) + for s in samples: + if s<=1: + return False + if abs(s-av) > 0.1: + return False + return True \ No newline at end of file