commit a0436b871aa2bdbc6a1105115a13f10714833802 Author: gobbo_a Date: Tue Jan 31 08:32:53 2023 +0100 Creation diff --git a/config/config.properties b/config/config.properties new file mode 100644 index 0000000..9dc9b80 --- /dev/null +++ b/config/config.properties @@ -0,0 +1,50 @@ +#Tue Jan 31 08:32:36 CET 2023 +autoSaveScanData=true +simulation=false +dataScanSaveOutput=false +userAuthenticator= +dataScanSaveScript=false +notifiedTasks= +parallelInitialization=false +fdaSerialization=false +dataTransferPath= +saveConsoleSessionFiles=false +hostName= +disableEmbeddedAttributes=false +serverPort=8080 +versionTrackingEnabled=true +dataPath={data}/{year}_{month}/{date}/{date}_{time}_{name} +serverEnabled=true +depthDimension=0 +logLevel=Info +dataLayout=default +disableDataFileLogs=false +sessionHandling=Off +terminalEnabled=false +notificationLevel=Off +terminalPort=3579 +dataTransferUser= +versionTrackingLogin={context}/svcusr-hlapp_robot +noBytecodeFiles=false +versionTrackingRemote=git@git.psi.ch\:pshell_config/saresb.git +dataScanLazyTableCreation=false +logDaysToLive=-1 +logLevelConsole=Off +filePermissionsConfig=Default +scanStreamerPort=-1 +dataScanSaveSetpoints=false +versionTrackingManual=false +dataTransferMode=Off +userManagement=false +instanceName= +dataServerPort=-1 +hideServerMessages=false +dataScanReleaseRecords=false +dataScanPreserveTypes=false +dataScanFlushRecords=false +filePermissionsLogs=Default +logPath={logs}/{date}_{time} +filePermissionsScripts=Default +filePermissionsData=Default +dataProvider=h5 +saveCommandStatistics=false diff --git a/config/devices.properties b/config/devices.properties new file mode 100644 index 0000000..b775dc4 --- /dev/null +++ b/config/devices.properties @@ -0,0 +1,3 @@ +$cam_n=ch.psi.pshell.imaging.MjpegSource|http://bernina-cam-n/axis-cgi/mjpg/video.cgi reopen||-200|false +$cam_s=ch.psi.pshell.imaging.MjpegSource|http://bernina-cam-s/axis-cgi/mjpg/video.cgi reopen||-200| +$cam_w=ch.psi.pshell.imaging.MjpegSource|http://bernina-cam-w/axis-cgi/mjpg/video.cgi reopen||-200| diff --git a/config/mail.properties b/config/mail.properties new file mode 100644 index 0000000..7ac38a6 --- /dev/null +++ b/config/mail.properties @@ -0,0 +1,9 @@ +#Tue Jan 24 14:39:51 CET 2023 +port=0 +usr= +auth=None +smsSuffix=@sms.switch.ch +host= +from= +to= +pwd= diff --git a/config/plugins.properties b/config/plugins.properties new file mode 100644 index 0000000..e6190fa --- /dev/null +++ b/config/plugins.properties @@ -0,0 +1,2 @@ +RobotBernina.java=enabled +RobotPanel.java=enabled diff --git a/config/preferences.json b/config/preferences.json new file mode 100644 index 0000000..4b92096 --- /dev/null +++ b/config/preferences.json @@ -0,0 +1,139 @@ +{ + "fontShellPanel" : { + "name" : "Monospaced", + "style" : 0, + "size" : 13 + }, + "fontShellCommand" : { + "name" : "SansSerif", + "style" : 0, + "size" : 13 + }, + "fontOutput" : { + "name" : "Monospaced", + "style" : 0, + "size" : 13 + }, + "fontEditor" : { + "name" : "Monospaced", + "style" : 0, + "size" : 13 + }, + "fontPlotLabel" : { + "name" : "SansSerif", + "style" : 0, + "size" : 11 + }, + "fontPlotTick" : { + "name" : "SansSerif", + "style" : 0, + "size" : 10 + }, + "fontPlotTitle" : { + "name" : "SansSerif", + "style" : 1, + "size" : 13 + }, + "fontTerminal" : { + "name" : "Menlo", + "style" : 0, + "size" : 14 + }, + "tabSize" : 4, + "contentWidth" : 0, + "editorBackground" : null, + "editorForeground" : null, + "simpleEditor" : false, + "hideEditorLineNumbers" : false, + "hideEditorContextMenu" : false, + "consoleLocation" : "Left", + "dataPanelLocation" : "Status", + "openDataFilesInDocTab" : false, + "noVariableEvaluationPropagation" : false, + "processingScripts" : [ ], + "asyncViewersUpdate" : false, + "asyncHistoryPlotsUpdate" : false, + "scanPlotDisabled" : false, + "scanTableDisabled" : false, + "cachedDataPanel" : false, + "dataExtensions" : "", + "dataSubFiles" : "", + "hideFileName" : false, + "showEmergencyStop" : false, + "showHomingButtons" : false, + "showJogButtons" : false, + "hideScanPanel" : false, + "hideOutputPanel" : false, + "showXScanFileBrowser" : false, + "showQueueBrowser" : false, + "backgroundRendering" : false, + "showImageStatusBar" : true, + "persistRendererWindows" : false, + "defaultRendererColormap" : "Grayscale", + "linePlot" : "ch.psi.pshell.plot.LinePlotJFree", + "matrixPlot" : "ch.psi.pshell.plot.MatrixPlotJFree", + "surfacePlot" : "null", + "timePlot" : "ch.psi.pshell.plot.TimePlotJFree", + "plotsDetached" : false, + "plotLayout" : "Vertical", + "quality" : "High", + "defaultPlotColormap" : "Temperature", + "markerSize" : 2, + "plotBackground" : null, + "gridColor" : null, + "outlineColor" : null, + "disableOffscreenBuffer" : false, + "defaultPanels" : [ { + "deviceClassName" : "ch.psi.pshell.epics.Scaler", + "panelClassName" : "ch.psi.pshell.swing.ScalerPanel" + }, { + "deviceClassName" : "ch.psi.pshell.epics.Scienta", + "panelClassName" : "ch.psi.pshell.swing.ScientaPanel" + }, { + "deviceClassName" : "ch.psi.pshell.device.Motor", + "panelClassName" : "ch.psi.pshell.swing.MotorPanel" + }, { + "deviceClassName" : "ch.psi.pshell.device.MasterPositioner", + "panelClassName" : "ch.psi.pshell.swing.MasterPositionerPanel" + }, { + "deviceClassName" : "ch.psi.pshell.device.ProcessVariable", + "panelClassName" : "ch.psi.pshell.swing.ProcessVariablePanel" + }, { + "deviceClassName" : "ch.psi.pshell.device.MotorGroup", + "panelClassName" : "ch.psi.pshell.swing.MotorGroupPanel" + }, { + "deviceClassName" : "ch.psi.pshell.device.DiscretePositioner", + "panelClassName" : "ch.psi.pshell.swing.DiscretePositionerPanel" + }, { + "deviceClassName" : "ch.psi.pshell.device.Camera", + "panelClassName" : "ch.psi.pshell.swing.CameraPanel" + }, { + "deviceClassName" : "ch.psi.pshell.device.Slit", + "panelClassName" : "ch.psi.pshell.swing.SlitPanel" + }, { + "deviceClassName" : "ch.psi.pshell.device.HistogramGenerator", + "panelClassName" : "ch.psi.pshell.swing.HistogramGeneratorPanel" + }, { + "deviceClassName" : "ch.psi.pshell.bs.Stream", + "panelClassName" : "ch.psi.pshell.swing.StreamPanel" + }, { + "deviceClassName" : "ch.psi.pshell.bs.StreamChannel", + "panelClassName" : "ch.psi.pshell.swing.StreamChannelPanel" + }, { + "deviceClassName" : "ch.psi.pshell.camserver.CamServerStream", + "panelClassName" : "ch.psi.pshell.swing.CamServerStreamPanel" + }, { + "deviceClassName" : "ch.psi.pshell.camserver.CamServerService", + "panelClassName" : "ch.psi.pshell.swing.CamServerServicePanel" + }, { + "deviceClassName" : "ch.psi.pshell.device.ReadonlyRegister$ReadonlyRegisterArray", + "panelClassName" : "ch.psi.pshell.swing.DeviceValueChart" + }, { + "deviceClassName" : "ch.psi.pshell.device.ReadonlyRegister$ReadonlyRegisterMatrix", + "panelClassName" : "ch.psi.pshell.swing.DeviceValueChart" + }, { + "deviceClassName" : "RobotTCP", + "panelClassName" : "RobotPanel" + } ], + "scriptPopupDialog" : "None" +} \ No newline at end of file diff --git a/config/setup.properties b/config/setup.properties new file mode 100644 index 0000000..f9f476c --- /dev/null +++ b/config/setup.properties @@ -0,0 +1,25 @@ +#Tue Jan 24 14:39:50 CET 2023 +scriptPath={home}/script +sessionsPath={outp}/sessions +configFileDevices={config}/devices.properties +xscanPath={script} +queuePath={script} +extensionsPath={home}/extensions +configPath={home}/config +configFileSessions={config}/sessions.properties +userSessionsPath={sessions}/user +dataPath={outp}/data +configFileVariables={config}/variables.properties +wwwPath={home}/www +logPath={outp}/log +configFile={config}/config.properties +configFileTasks={config}/tasks.properties +pluginsPath={home}/plugins +consoleSessionsPath={sessions}/console +libraryPath={script}; {script}/Lib +contextPath={outp}/context +configFilePlugins={config}/plugins.properties +devicesPath={home}/devices +configFileSettings={config}/settings.properties +imagesPath={outp}/images +scriptType=py diff --git a/devices/cam_n.properties b/devices/cam_n.properties new file mode 100644 index 0000000..558f98f --- /dev/null +++ b/devices/cam_n.properties @@ -0,0 +1,20 @@ +#Thu Jan 26 13:46:16 CET 2023 +spatialCalOffsetY=NaN +invert=false +spatialCalOffsetX=NaN +rotation=0.0 +rotationCrop=false +scale=1.0 +rescaleFactor=1.0 +grayscale=false +spatialCalUnits=mm +flipVertically=false +roiHeight=-1 +spatialCalScaleX=NaN +spatialCalScaleY=NaN +flipHorizontally=false +roiY=0 +roiX=0 +rescaleOffset=0.0 +transpose=false +roiWidth=-1 diff --git a/devices/cam_s.properties b/devices/cam_s.properties new file mode 100644 index 0000000..558f98f --- /dev/null +++ b/devices/cam_s.properties @@ -0,0 +1,20 @@ +#Thu Jan 26 13:46:16 CET 2023 +spatialCalOffsetY=NaN +invert=false +spatialCalOffsetX=NaN +rotation=0.0 +rotationCrop=false +scale=1.0 +rescaleFactor=1.0 +grayscale=false +spatialCalUnits=mm +flipVertically=false +roiHeight=-1 +spatialCalScaleX=NaN +spatialCalScaleY=NaN +flipHorizontally=false +roiY=0 +roiX=0 +rescaleOffset=0.0 +transpose=false +roiWidth=-1 diff --git a/devices/cam_w.properties b/devices/cam_w.properties new file mode 100644 index 0000000..558f98f --- /dev/null +++ b/devices/cam_w.properties @@ -0,0 +1,20 @@ +#Thu Jan 26 13:46:16 CET 2023 +spatialCalOffsetY=NaN +invert=false +spatialCalOffsetX=NaN +rotation=0.0 +rotationCrop=false +scale=1.0 +rescaleFactor=1.0 +grayscale=false +spatialCalUnits=mm +flipVertically=false +roiHeight=-1 +spatialCalScaleX=NaN +spatialCalScaleY=NaN +flipHorizontally=false +roiY=0 +roiX=0 +rescaleOffset=0.0 +transpose=false +roiWidth=-1 diff --git a/plugins/.DS_Store b/plugins/.DS_Store new file mode 100644 index 0000000..d8f31db Binary files /dev/null and b/plugins/.DS_Store differ diff --git a/plugins/RobotBernina.form b/plugins/RobotBernina.form new file mode 100644 index 0000000..8bacaa1 --- /dev/null +++ b/plugins/RobotBernina.form @@ -0,0 +1,1031 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/RobotBernina.java b/plugins/RobotBernina.java new file mode 100644 index 0000000..68888f4 --- /dev/null +++ b/plugins/RobotBernina.java @@ -0,0 +1,1196 @@ +import ch.psi.pshell.core.Context; +import ch.psi.pshell.device.Device; +import ch.psi.pshell.device.DeviceAdapter; +import ch.psi.pshell.device.DeviceListener; +import ch.psi.pshell.device.GenericDevice; +import ch.psi.pshell.imaging.MjpegSource; +import ch.psi.pshell.imaging.RendererMode; +import ch.psi.pshell.ui.App; +import ch.psi.pshell.ui.Panel; +import ch.psi.utils.State; +import ch.psi.utils.swing.SwingUtils; +import java.awt.Color; +import java.awt.Component; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.Map; +import javax.swing.DefaultComboBoxModel; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JSpinner; +import javax.swing.JTextField; + +/** + * + */ +public class RobotBernina extends Panel { + volatile boolean updatingRobotControls; + volatile boolean moving; + volatile String currentCamera; + + public RobotBernina() { + initComponents(); + ((JSpinner.DefaultEditor)spinnerSpeed.getEditor()).getTextField().setHorizontalAlignment(JTextField.CENTER); + renderer.setMode(RendererMode.Fit); + updateCameraControls(); + } + + //Overridable callbacks + @Override + public void onInitialize(int runCount) { + updateCameraControls(); + DefaultComboBoxModel model = new DefaultComboBoxModel(); + renderer.setDeviceName(null); + for (GenericDevice dev : Context.getInstance().getDevicePool().getAllDevices(MjpegSource.class)){ + MjpegSource camera =(MjpegSource) dev; + model.addElement(camera.getName()); + } + model.addElement(""); + model.setSelectedItem(null); + comboCameras.setModel(model); + currentCamera = null; + comboCameras.requestFocus(); + } + + @Override + public void onStateChange(State state, State former) { + if (state.isInitialized()){ + GenericDevice robot = getDevice("robot"); + if (robot!=null){ + robot.addListener(robotListener); + } + } + for (Component c:SwingUtils.getComponentsByType(panelCommands, Component.class)){ + c.setEnabled(state.isReady()); + } + } + + @Override + public void onExecutedFile(String fileName, Object result) { + } + + @Override + protected void onTimer() { + } + + @Override + protected void onLoaded() { + + } + + @Override + protected void onUnloaded() { + + } + + //Invoked by 'update()' to update components in the event thread + @Override + protected void doUpdate() { + } + + void updateCameraControls(){ + boolean isCameraSelected = (currentCamera!=null); + boolean enabled = isCameraSelected && getState().isNormal() && !moving; + for (Component button : SwingUtils.getComponentsByType(panelControls, JButton.class)){ + button.setEnabled(enabled); + } + } + + protected void evalCmd(String cmd){ + evalCmd(cmd, false); + } + + protected void evalCmd(String cmd, boolean background){ + try{ + this.evalAsync(cmd, background).handle((ret, ex) -> { + if (ex != null){ + showException((Exception)ex); + } + return ret; + }); + } catch (Exception ex) { + showException(ex); + } + } + + final DeviceListener robotListener = new DeviceAdapter() { + @Override + public void onStateChanged(Device device, State state, State former) { + boolean enabled = state.isNormal(); + spinnerSpeed.setEnabled(enabled); + buttonAbort.setEnabled(enabled); + if (!enabled){ + buttonEnable.setEnabled(enabled); + buttonDisable.setEnabled(enabled); + butonStop.setEnabled(enabled); + buttonPause.setEnabled(enabled); + buttonResume.setEnabled(enabled); + } + } + + @Override + public void onCacheChanged(Device device, Object value, Object former, long timestamp, boolean valueChange) { + updatingRobotControls = true; + try{ + Boolean powered = null; + Boolean empty = null; + Boolean settled = null; + Boolean moving = null; + Boolean open = null; + Integer speed = null; + String task = null; + String mode = null; + String position = null; + + if ((value != null) && (value instanceof Map)) { + Map status = (Map) value; + try { + powered = (Boolean) status.get("powered"); + } catch (Exception ex) { + } + try { + empty = (Boolean) status.get("empty"); + } catch (Exception ex) { + } + try { + settled = (Boolean) status.get("settled"); + } catch (Exception ex) { + } + try { + open = (Boolean) status.get("open"); + } catch (Exception ex) { + } + try { + speed = (Integer) status.get("speed"); + } catch (Exception ex) { + } + try { + position = (String) status.get("pos"); + if (position==null){ + position = ""; + } + } catch (Exception ex) { + } + try { + task = ((status.containsKey("task")) && (status.get("task") == null)) ? "" : ((String) status.get("task")).trim(); + } catch (Exception ex) { + System.out.println(ex); + ex.printStackTrace(); + } + try { + mode = ((String) status.get("mode")).trim(); + } catch (Exception ex) { + } + try { + moving = Boolean.FALSE.equals(settled) || Boolean.FALSE.equals(empty); + } catch (Exception ex) { + } + } + + boolean remote = mode.equals("remote"); + boolean enabled = Boolean.TRUE.equals(powered); + buttonEnable.setEnabled((powered != null) && (powered == false)); + buttonDisable.setEnabled(enabled); + + butonStop.setEnabled(remote && Boolean.TRUE.equals(moving)); + buttonPause.setEnabled(remote && enabled && Boolean.TRUE.equals(moving) && Boolean.FALSE.equals(settled)); + buttonResume.setEnabled(remote && enabled && Boolean.TRUE.equals(moving) && Boolean.TRUE.equals(settled)); + + + ledPowered.setColor((powered == null) ? Color.GRAY : (powered ? Color.YELLOW : Color.DARK_GRAY)); + ledEmpty.setColor((empty == null) ? Color.GRAY : (empty ? Color.GREEN : Color.YELLOW)); + ledSettled.setColor((settled == null) ? Color.GRAY : (settled ? Color.GREEN : Color.YELLOW)); + ledOpen.setColor((open == null) ? Color.GRAY : (open ? Color.GREEN : Color.DARK_GRAY)); + ledMoving.setColor((moving == null) ? Color.GRAY : (moving ? Color.YELLOW : Color.DARK_GRAY)); + textTask.setText((task == null) ? "" : task); + ledTask.setColor((task == null) ? Color.GRAY : (task.isEmpty() ? Color.DARK_GRAY : Color.YELLOW)); + textPosition.setText((position == null) ? "" : position); + ledPosition.setColor((position == null) ? Color.GRAY : (position.isEmpty() ? Color.DARK_GRAY : Color.GREEN)); + //buttonAbort.setEnabled(!textTask.getText().isEmpty()); + spinnerSpeed.setEnabled(speed != null); + if (speed == null) { + spinnerSpeed.setValue(0); + } else { + spinnerSpeed.setValue(speed); + } + ledMode.setColor((mode == null) ? Color.BLACK : (remote ? Color.GREEN : Color.YELLOW)); + textMode.setText((mode == null) ? "" : mode); + + } finally{ + updatingRobotControls = false; + } + } + }; + + + //Cameras + void selectCamera(String name){ + renderer.clear(); + currentCamera = ((name == null)||(name.isBlank()))? null : name; + renderer.setDeviceName(currentCamera); + updateCameraControls(); + } + + + void move(String direction){ + try { + moving = true; + updateCameraControls(); + String camera = comboCameras.getSelectedItem().toString(); + this.evalAsync("axis_move(" + camera + ", '" + direction + "')", true).handle((ret,ex)->{ + if (ex!=null){ + getLogger().log(Level.WARNING, null, ex); + } + moving = false; + updateCameraControls(); + return ret; + }); + } catch (Context.ContextStateException ex) { + getLogger().log(Level.SEVERE, null, ex); + moving = false; + updateCameraControls(); + + } + } + + void zoom(int steps){ + try { + moving = true; + updateCameraControls(); + String camera = comboCameras.getSelectedItem().toString(); + this.evalAsync("axis_rzoom(" + camera + ", " + steps + ")", true).handle((ret,ex)->{ + if (ex!=null){ + getLogger().log(Level.WARNING, null, ex); + } + moving = false; + updateCameraControls(); + return ret; + }); + } catch (Context.ContextStateException ex) { + getLogger().log(Level.SEVERE, null, ex); + moving = false; + updateCameraControls(); + + } + } + + ImageIcon getIcon(String name) { + ImageIcon ret = null; + try { + ret = new ImageIcon(ch.psi.pshell.ui.App.class.getResource("/ch/psi/pshell/ui/" + name + ".png")); + if (ch.psi.utils.swing.MainFrame.isDark()) { + try { + ret = new ImageIcon(ch.psi.pshell.ui.App.class.getResource("/ch/psi/pshell/ui/dark/" + name + ".png")); + } catch (Exception e) { + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + return ret; + } + + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + panelCommands = new javax.swing.JPanel(); + movePark = new javax.swing.JButton(); + moveHome = new javax.swing.JButton(); + buttonTweakX = new javax.swing.JButton(); + spinnerOffsetX = new javax.swing.JSpinner(); + panelRobot = new javax.swing.JPanel(); + deviceStatePanel1 = new ch.psi.pshell.swing.DeviceStatePanel(); + jPanel4 = new javax.swing.JPanel(); + jLabel3 = new javax.swing.JLabel(); + ledSettled = new ch.psi.pshell.swing.Led(); + jLabel4 = new javax.swing.JLabel(); + ledEmpty = new ch.psi.pshell.swing.Led(); + textTask = new javax.swing.JTextField(); + jLabel6 = new javax.swing.JLabel(); + textMode = new javax.swing.JTextField(); + buttonAbort = new javax.swing.JButton(); + jLabel8 = new javax.swing.JLabel(); + ledTask = new ch.psi.pshell.swing.Led(); + ledMode = new ch.psi.pshell.swing.Led(); + textPosition = new javax.swing.JTextField(); + ledPosition = new ch.psi.pshell.swing.Led(); + jLabel9 = new javax.swing.JLabel(); + jPanel5 = new javax.swing.JPanel(); + jLabel2 = new javax.swing.JLabel(); + spinnerSpeed = new ch.psi.utils.swing.HorizontalSpinner(); + jLabel7 = new javax.swing.JLabel(); + ledMoving = new ch.psi.pshell.swing.Led(); + panelMotionCtr = new javax.swing.JPanel(); + butonStop = new javax.swing.JButton(); + buttonResume = new javax.swing.JButton(); + buttonPause = new javax.swing.JButton(); + jPanel6 = new javax.swing.JPanel(); + ledPowered = new ch.psi.pshell.swing.Led(); + jLabel1 = new javax.swing.JLabel(); + panelPowerCtr = new javax.swing.JPanel(); + buttonDisable = new javax.swing.JButton(); + buttonEnable = new javax.swing.JButton(); + jPanel7 = new javax.swing.JPanel(); + ledOpen = new ch.psi.pshell.swing.Led(); + jLabel5 = new javax.swing.JLabel(); + panelPowerCtr1 = new javax.swing.JPanel(); + buttonClose = new javax.swing.JButton(); + buttonOpen = new javax.swing.JButton(); + panelCameras = new javax.swing.JPanel(); + renderer = new ch.psi.pshell.imaging.Renderer(); + panelControls = new javax.swing.JPanel(); + jPanel8 = new javax.swing.JPanel(); + buttonMoveLeft = new javax.swing.JButton(); + buttonMoveDLeft = new javax.swing.JButton(); + buttonMoveDRight = new javax.swing.JButton(); + buttonMoveRight = new javax.swing.JButton(); + buttonMoveUReight = new javax.swing.JButton(); + buttonMoveHome = new javax.swing.JButton(); + buttonMoveDown = new javax.swing.JButton(); + buttonMoveULeft = new javax.swing.JButton(); + buttonMoveUp = new javax.swing.JButton(); + jPanel9 = new javax.swing.JPanel(); + buttonZoomOut = new javax.swing.JButton(); + buttonZooHome = new javax.swing.JButton(); + buttonZoomIn = new javax.swing.JButton(); + jPanel10 = new javax.swing.JPanel(); + comboCameras = new javax.swing.JComboBox<>(); + + panelCommands.setBorder(javax.swing.BorderFactory.createTitledBorder("Commands")); + + movePark.setText("Move to Park"); + movePark.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + moveParkActionPerformed(evt); + } + }); + + moveHome.setText("Move to Home"); + moveHome.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + moveHomeActionPerformed(evt); + } + }); + + buttonTweakX.setText("Tweak X"); + buttonTweakX.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonTweakXActionPerformed(evt); + } + }); + + spinnerOffsetX.setModel(new javax.swing.SpinnerNumberModel(1.0d, -10.0d, 10.0d, 1.0d)); + + javax.swing.GroupLayout panelCommandsLayout = new javax.swing.GroupLayout(panelCommands); + panelCommands.setLayout(panelCommandsLayout); + panelCommandsLayout.setHorizontalGroup( + panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelCommandsLayout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(movePark, javax.swing.GroupLayout.PREFERRED_SIZE, 138, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(moveHome, javax.swing.GroupLayout.PREFERRED_SIZE, 138, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(panelCommandsLayout.createSequentialGroup() + .addComponent(buttonTweakX, javax.swing.GroupLayout.PREFERRED_SIZE, 138, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spinnerOffsetX, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + panelCommandsLayout.setVerticalGroup( + panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelCommandsLayout.createSequentialGroup() + .addContainerGap() + .addComponent(movePark) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(moveHome) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(panelCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonTweakX) + .addComponent(spinnerOffsetX, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + panelRobot.setBorder(javax.swing.BorderFactory.createTitledBorder("Robot")); + + deviceStatePanel1.setDeviceName("robot"); + + jPanel4.setBorder(javax.swing.BorderFactory.createTitledBorder("Status")); + + jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel3.setText("Settled:"); + + ledSettled.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel4.setText("Empty:"); + + ledEmpty.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + textTask.setEditable(false); + textTask.setHorizontalAlignment(javax.swing.JTextField.CENTER); + + jLabel6.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel6.setText("Mode:"); + + textMode.setEditable(false); + textMode.setHorizontalAlignment(javax.swing.JTextField.CENTER); + + buttonAbort.setText("Abort"); + buttonAbort.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonAbortActionPerformed(evt); + } + }); + + jLabel8.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel8.setText("Task:"); + + ledTask.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + ledMode.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + textPosition.setEditable(false); + textPosition.setHorizontalAlignment(javax.swing.JTextField.CENTER); + + ledPosition.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + jLabel9.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel9.setText("Position:"); + + javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); + jPanel4.setLayout(jPanel4Layout); + jPanel4Layout.setHorizontalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel3) + .addComponent(jLabel4) + .addComponent(jLabel6) + .addComponent(jLabel8) + .addComponent(jLabel9)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(ledTask, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(ledEmpty, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(ledSettled, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(ledPosition, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(textTask) + .addComponent(textPosition))) + .addGroup(jPanel4Layout.createSequentialGroup() + .addComponent(ledMode, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(textMode))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonAbort) + .addContainerGap()) + ); + + jPanel4Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel3, jLabel4, jLabel6, jLabel8, jLabel9}); + + jPanel4Layout.setVerticalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel4Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel3) + .addComponent(ledSettled, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel4) + .addComponent(ledEmpty, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(textMode, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(ledMode, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel6)) + .addGap(2, 2, 2) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(buttonAbort) + .addComponent(jLabel8) + .addComponent(ledTask, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(textTask, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel9) + .addComponent(ledPosition, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(textPosition, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2)) + ); + + jPanel5.setBorder(javax.swing.BorderFactory.createTitledBorder("Motion")); + + jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel2.setText("Speed:"); + + spinnerSpeed.setModel(new javax.swing.SpinnerNumberModel(10, null, 100, 1)); + spinnerSpeed.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerSpeedStateChanged(evt); + } + }); + + jLabel7.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel7.setText("Moving:"); + + ledMoving.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + butonStop.setIcon(new javax.swing.ImageIcon(App.class.getResource("/ch/psi/pshell/ui/Stop.png"))); + butonStop.setText(" "); + butonStop.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + butonStop.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + butonStopActionPerformed(evt); + } + }); + + buttonResume.setIcon(new javax.swing.ImageIcon(App.class.getResource("/ch/psi/pshell/ui/Play.png"))); + buttonResume.setText(" "); + buttonResume.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + buttonResume.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonResumeActionPerformed(evt); + } + }); + + buttonPause.setIcon(new javax.swing.ImageIcon(App.class.getResource("/ch/psi/pshell/ui/Pause.png"))); + buttonPause.setText(" "); + buttonPause.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + buttonPause.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonPauseActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelMotionCtrLayout = new javax.swing.GroupLayout(panelMotionCtr); + panelMotionCtr.setLayout(panelMotionCtrLayout); + panelMotionCtrLayout.setHorizontalGroup( + panelMotionCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelMotionCtrLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(butonStop, javax.swing.GroupLayout.DEFAULT_SIZE, 45, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonPause, javax.swing.GroupLayout.DEFAULT_SIZE, 46, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonResume, javax.swing.GroupLayout.DEFAULT_SIZE, 47, Short.MAX_VALUE) + .addGap(0, 0, 0)) + ); + panelMotionCtrLayout.setVerticalGroup( + panelMotionCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelMotionCtrLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(panelMotionCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(butonStop, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonPause, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonResume, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGap(0, 0, 0)) + ); + + javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5); + jPanel5.setLayout(jPanel5Layout); + jPanel5Layout.setHorizontalGroup( + jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel5Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel5Layout.createSequentialGroup() + .addComponent(jLabel7) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledMoving, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jLabel2)) + .addGap(14, 14, 14) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(panelMotionCtr, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(spinnerSpeed)) + .addContainerGap()) + ); + + jPanel5Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel2, jLabel7}); + + jPanel5Layout.setVerticalGroup( + jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel5Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel7) + .addComponent(ledMoving, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(panelMotionCtr, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel2) + .addComponent(spinnerSpeed, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2)) + ); + + jPanel6.setBorder(javax.swing.BorderFactory.createTitledBorder("Power")); + + ledPowered.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel1.setText("Powered:"); + + buttonDisable.setText("Disable"); + buttonDisable.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonDisableActionPerformed(evt); + } + }); + + buttonEnable.setText("Enable"); + buttonEnable.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonEnableActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelPowerCtrLayout = new javax.swing.GroupLayout(panelPowerCtr); + panelPowerCtr.setLayout(panelPowerCtrLayout); + panelPowerCtrLayout.setHorizontalGroup( + panelPowerCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelPowerCtrLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(buttonEnable) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18, Short.MAX_VALUE) + .addComponent(buttonDisable)) + ); + panelPowerCtrLayout.setVerticalGroup( + panelPowerCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelPowerCtrLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(panelPowerCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addComponent(buttonDisable, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonEnable)) + .addGap(0, 0, 0)) + ); + + javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6); + jPanel6.setLayout(jPanel6Layout); + jPanel6Layout.setHorizontalGroup( + jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel6Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledPowered, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelPowerCtr, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel6Layout.setVerticalGroup( + jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel6Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel1) + .addComponent(ledPowered, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(panelPowerCtr, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2)) + ); + + jPanel7.setBorder(javax.swing.BorderFactory.createTitledBorder("Tool")); + + ledOpen.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel5.setText("Open:"); + + buttonClose.setText(" Close "); + buttonClose.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonCloseActionPerformed(evt); + } + }); + + buttonOpen.setText(" Open "); + buttonOpen.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonOpenActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelPowerCtr1Layout = new javax.swing.GroupLayout(panelPowerCtr1); + panelPowerCtr1.setLayout(panelPowerCtr1Layout); + panelPowerCtr1Layout.setHorizontalGroup( + panelPowerCtr1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelPowerCtr1Layout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(buttonOpen) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18, Short.MAX_VALUE) + .addComponent(buttonClose)) + ); + panelPowerCtr1Layout.setVerticalGroup( + panelPowerCtr1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelPowerCtr1Layout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(panelPowerCtr1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addComponent(buttonClose, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonOpen)) + .addGap(0, 0, 0)) + ); + + javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7); + jPanel7.setLayout(jPanel7Layout); + jPanel7Layout.setHorizontalGroup( + jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel7Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel5, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledOpen, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelPowerCtr1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel7Layout.setVerticalGroup( + jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel7Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel5) + .addComponent(ledOpen, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(panelPowerCtr1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2)) + ); + + javax.swing.GroupLayout panelRobotLayout = new javax.swing.GroupLayout(panelRobot); + panelRobot.setLayout(panelRobotLayout); + panelRobotLayout.setHorizontalGroup( + panelRobotLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelRobotLayout.createSequentialGroup() + .addContainerGap() + .addGroup(panelRobotLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(deviceStatePanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel7, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) + ); + panelRobotLayout.setVerticalGroup( + panelRobotLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelRobotLayout.createSequentialGroup() + .addComponent(jPanel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel7, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(deviceStatePanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + + panelCameras.setBorder(javax.swing.BorderFactory.createTitledBorder("Camera")); + panelCameras.setLayout(new java.awt.BorderLayout()); + panelCameras.add(renderer, java.awt.BorderLayout.CENTER); + + jPanel8.setBorder(javax.swing.BorderFactory.createTitledBorder("Move")); + + buttonMoveLeft.setIcon(getIcon("arrows/Left")); + buttonMoveLeft.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveLeftActionPerformed(evt); + } + }); + + buttonMoveDLeft.setIcon(getIcon("arrows/DLeft")); + buttonMoveDLeft.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveDLeftActionPerformed(evt); + } + }); + + buttonMoveDRight.setIcon(getIcon("arrows/DRight")); + buttonMoveDRight.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveDRightActionPerformed(evt); + } + }); + + buttonMoveRight.setIcon(getIcon("arrows/Right")); + buttonMoveRight.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveRightActionPerformed(evt); + } + }); + + buttonMoveUReight.setIcon(getIcon("arrows/URight")); + buttonMoveUReight.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveUReightActionPerformed(evt); + } + }); + + buttonMoveHome.setIcon(getIcon("arrows/Center")); + buttonMoveHome.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveHomeActionPerformed(evt); + } + }); + + buttonMoveDown.setIcon(getIcon("arrows/Down")); + buttonMoveDown.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveDownActionPerformed(evt); + } + }); + + buttonMoveULeft.setIcon(getIcon("arrows/ULeft")); + buttonMoveULeft.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveULeftActionPerformed(evt); + } + }); + + buttonMoveUp.setIcon(getIcon("arrows/Up")); + buttonMoveUp.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveUpActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel8Layout = new javax.swing.GroupLayout(jPanel8); + jPanel8.setLayout(jPanel8Layout); + jPanel8Layout.setHorizontalGroup( + jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel8Layout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(buttonMoveULeft, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonMoveDLeft, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(buttonMoveLeft, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addComponent(buttonMoveDown, javax.swing.GroupLayout.DEFAULT_SIZE, 40, Short.MAX_VALUE) + .addComponent(buttonMoveHome, javax.swing.GroupLayout.DEFAULT_SIZE, 40, Short.MAX_VALUE) + .addComponent(buttonMoveUp, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 40, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(buttonMoveRight, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE) + .addComponent(buttonMoveUReight, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE) + .addComponent(buttonMoveDRight, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel8Layout.setVerticalGroup( + jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel8Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonMoveUp, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonMoveUReight, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonMoveULeft, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonMoveLeft, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonMoveRight, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonMoveHome, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel8Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonMoveDown, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonMoveDLeft, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonMoveDRight, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + + jPanel9.setBorder(javax.swing.BorderFactory.createTitledBorder("Zoom")); + + buttonZoomOut.setIcon(getIcon("arrows/Out")); + buttonZoomOut.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonZoomOutActionPerformed(evt); + } + }); + + buttonZooHome.setIcon(getIcon("arrows/Center")); + buttonZooHome.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonZooHomeActionPerformed(evt); + } + }); + + buttonZoomIn.setIcon(getIcon("arrows/In")); + buttonZoomIn.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonZoomInActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel9Layout = new javax.swing.GroupLayout(jPanel9); + jPanel9.setLayout(jPanel9Layout); + jPanel9Layout.setHorizontalGroup( + jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel9Layout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonZoomOut, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonZooHome, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonZoomIn, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel9Layout.setVerticalGroup( + jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel9Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel9Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonZoomOut, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonZoomIn, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonZooHome, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + + jPanel10.setBorder(javax.swing.BorderFactory.createTitledBorder("Selection")); + + comboCameras.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + comboCamerasActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel10Layout = new javax.swing.GroupLayout(jPanel10); + jPanel10.setLayout(jPanel10Layout); + jPanel10Layout.setHorizontalGroup( + jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel10Layout.createSequentialGroup() + .addContainerGap() + .addComponent(comboCameras, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addContainerGap()) + ); + jPanel10Layout.setVerticalGroup( + jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel10Layout.createSequentialGroup() + .addContainerGap() + .addComponent(comboCameras, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + + javax.swing.GroupLayout panelControlsLayout = new javax.swing.GroupLayout(panelControls); + panelControls.setLayout(panelControlsLayout); + panelControlsLayout.setHorizontalGroup( + panelControlsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelControlsLayout.createSequentialGroup() + .addContainerGap() + .addGroup(panelControlsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel9, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel8, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel10, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) + ); + panelControlsLayout.setVerticalGroup( + panelControlsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelControlsLayout.createSequentialGroup() + .addContainerGap() + .addComponent(jPanel10, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jPanel8, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jPanel9, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(200, Short.MAX_VALUE)) + ); + + panelCameras.add(panelControls, java.awt.BorderLayout.WEST); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(panelCommands, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelRobot, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(panelCameras, javax.swing.GroupLayout.PREFERRED_SIZE, 197, Short.MAX_VALUE) + .addGap(5, 5, 5)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(panelCommands, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(panelRobot, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(panelCameras, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + private void moveParkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveParkActionPerformed + evalCmd("robot.move_park()"); + }//GEN-LAST:event_moveParkActionPerformed + + private void moveHomeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveHomeActionPerformed + evalCmd("robot.move_home()"); + }//GEN-LAST:event_moveHomeActionPerformed + + private void buttonAbortActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonAbortActionPerformed + evalCmd("robot.stop_task()", true); + }//GEN-LAST:event_buttonAbortActionPerformed + + private void spinnerSpeedStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerSpeedStateChanged + if (!updatingRobotControls){ + evalCmd("robot.set_monitor_speed(" + spinnerSpeed.getValue() + ")"); + } + }//GEN-LAST:event_spinnerSpeedStateChanged + + private void butonStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_butonStopActionPerformed + evalCmd("robot.reset_motion()", true); + }//GEN-LAST:event_butonStopActionPerformed + + private void buttonResumeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonResumeActionPerformed + evalCmd("robot.resume()", true); + }//GEN-LAST:event_buttonResumeActionPerformed + + private void buttonPauseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonPauseActionPerformed + evalCmd("robot.stop()",true); + }//GEN-LAST:event_buttonPauseActionPerformed + + private void buttonDisableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonDisableActionPerformed + evalCmd("robot.disable()", true); + }//GEN-LAST:event_buttonDisableActionPerformed + + private void buttonEnableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonEnableActionPerformed + evalCmd("robot.enable()", true); + }//GEN-LAST:event_buttonEnableActionPerformed + + private void buttonCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCloseActionPerformed + evalCmd("robot.close_tool()"); + }//GEN-LAST:event_buttonCloseActionPerformed + + private void buttonOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonOpenActionPerformed + evalCmd("robot.open_tool()"); + }//GEN-LAST:event_buttonOpenActionPerformed + + private void buttonMoveLeftActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveLeftActionPerformed + move("left"); + }//GEN-LAST:event_buttonMoveLeftActionPerformed + + private void buttonMoveDLeftActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveDLeftActionPerformed + move("downleft"); + }//GEN-LAST:event_buttonMoveDLeftActionPerformed + + private void buttonMoveDRightActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveDRightActionPerformed + move("downright"); + }//GEN-LAST:event_buttonMoveDRightActionPerformed + + private void buttonMoveRightActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveRightActionPerformed + move("right"); + }//GEN-LAST:event_buttonMoveRightActionPerformed + + private void buttonMoveUReightActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveUReightActionPerformed + move("upright"); + }//GEN-LAST:event_buttonMoveUReightActionPerformed + + private void buttonMoveHomeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveHomeActionPerformed + move("home"); + }//GEN-LAST:event_buttonMoveHomeActionPerformed + + private void buttonMoveDownActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveDownActionPerformed + move("down"); + }//GEN-LAST:event_buttonMoveDownActionPerformed + + private void buttonMoveULeftActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveULeftActionPerformed + move("upleft"); + }//GEN-LAST:event_buttonMoveULeftActionPerformed + + private void buttonMoveUpActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveUpActionPerformed + move("up"); + }//GEN-LAST:event_buttonMoveUpActionPerformed + + private void buttonZoomOutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonZoomOutActionPerformed + zoom(-100); + }//GEN-LAST:event_buttonZoomOutActionPerformed + + private void buttonZooHomeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonZooHomeActionPerformed + move("home"); + }//GEN-LAST:event_buttonZooHomeActionPerformed + + private void buttonZoomInActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonZoomInActionPerformed + zoom(100); + }//GEN-LAST:event_buttonZoomInActionPerformed + + private void comboCamerasActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboCamerasActionPerformed + try{ + if (getState().isInitialized()){ + Object selection = comboCameras.getSelectedItem(); + selectCamera((selection==null) ? null :selection.toString()); + } + } catch(Exception ex){ + showException(ex); + } + }//GEN-LAST:event_comboCamerasActionPerformed + + private void buttonTweakXActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonTweakXActionPerformed + evalCmd("robot.tweak_x(" + spinnerOffsetX.getValue() + ")"); + }//GEN-LAST:event_buttonTweakXActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton butonStop; + private javax.swing.JButton buttonAbort; + private javax.swing.JButton buttonClose; + private javax.swing.JButton buttonDisable; + private javax.swing.JButton buttonEnable; + private javax.swing.JButton buttonMoveDLeft; + private javax.swing.JButton buttonMoveDRight; + private javax.swing.JButton buttonMoveDown; + private javax.swing.JButton buttonMoveHome; + private javax.swing.JButton buttonMoveLeft; + private javax.swing.JButton buttonMoveRight; + private javax.swing.JButton buttonMoveULeft; + private javax.swing.JButton buttonMoveUReight; + private javax.swing.JButton buttonMoveUp; + private javax.swing.JButton buttonOpen; + private javax.swing.JButton buttonPause; + private javax.swing.JButton buttonResume; + private javax.swing.JButton buttonTweakX; + private javax.swing.JButton buttonZooHome; + private javax.swing.JButton buttonZoomIn; + private javax.swing.JButton buttonZoomOut; + private javax.swing.JComboBox comboCameras; + private ch.psi.pshell.swing.DeviceStatePanel deviceStatePanel1; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel6; + private javax.swing.JLabel jLabel7; + private javax.swing.JLabel jLabel8; + private javax.swing.JLabel jLabel9; + private javax.swing.JPanel jPanel10; + private javax.swing.JPanel jPanel4; + private javax.swing.JPanel jPanel5; + private javax.swing.JPanel jPanel6; + private javax.swing.JPanel jPanel7; + private javax.swing.JPanel jPanel8; + private javax.swing.JPanel jPanel9; + private ch.psi.pshell.swing.Led ledEmpty; + private ch.psi.pshell.swing.Led ledMode; + private ch.psi.pshell.swing.Led ledMoving; + private ch.psi.pshell.swing.Led ledOpen; + private ch.psi.pshell.swing.Led ledPosition; + private ch.psi.pshell.swing.Led ledPowered; + private ch.psi.pshell.swing.Led ledSettled; + private ch.psi.pshell.swing.Led ledTask; + private javax.swing.JButton moveHome; + private javax.swing.JButton movePark; + private javax.swing.JPanel panelCameras; + private javax.swing.JPanel panelCommands; + private javax.swing.JPanel panelControls; + private javax.swing.JPanel panelMotionCtr; + private javax.swing.JPanel panelPowerCtr; + private javax.swing.JPanel panelPowerCtr1; + private javax.swing.JPanel panelRobot; + private ch.psi.pshell.imaging.Renderer renderer; + private javax.swing.JSpinner spinnerOffsetX; + private javax.swing.JSpinner spinnerSpeed; + private javax.swing.JTextField textMode; + private javax.swing.JTextField textPosition; + private javax.swing.JTextField textTask; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/RobotPanel.form b/plugins/RobotPanel.form new file mode 100644 index 0000000..bf9c0d6 --- /dev/null +++ b/plugins/RobotPanel.form @@ -0,0 +1,587 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/RobotPanel.java b/plugins/RobotPanel.java new file mode 100644 index 0000000..e841f57 --- /dev/null +++ b/plugins/RobotPanel.java @@ -0,0 +1,685 @@ + +import ch.psi.pshell.device.Device; +import ch.psi.pshell.ui.App; +import ch.psi.pshell.swing.DevicePanel; +import ch.psi.pshell.core.Context; +import ch.psi.utils.State; +import java.awt.Color; +import java.util.Map; +import javax.swing.JSpinner; +import javax.swing.JTextField; + +/** + * + */ +public class RobotPanel extends DevicePanel { + + /** + * Creates new form RobotPanel + */ + public RobotPanel() { + initComponents(); + ((JSpinner.DefaultEditor)spinnerSpeed.getEditor()).getTextField().setHorizontalAlignment(JTextField.CENTER); + } + + @Override + public void setDevice(Device device) { + super.setDevice(device); + if (device == null) { + + } + panelState.setDevice(device); + } + + @Override + protected void onDeviceStateChanged(State state, State former) { + boolean enabled = state.isNormal(); + spinnerSpeed.setEnabled(enabled); + buttonAbort.setEnabled(enabled); + if (!enabled){ + buttonEnable.setEnabled(enabled); + buttonDisable.setEnabled(enabled); + butonStop.setEnabled(enabled); + buttonPause.setEnabled(enabled); + buttonResume.setEnabled(enabled); + } + } + + boolean updating; + @Override + protected void onDeviceCacheChanged(Object value, Object former, long timestamp, boolean valueChange) { + updating = true; + try{ + Boolean powered = null; + Boolean empty = null; + Boolean settled = null; + Boolean moving = null; + Boolean open = null; + Integer speed = null; + String task = null; + String mode = null; + String position = null; + + if ((value != null) && (value instanceof Map)) { + Map status = (Map) value; + try { + powered = (Boolean) status.get("powered"); + } catch (Exception ex) { + } + try { + empty = (Boolean) status.get("empty"); + } catch (Exception ex) { + } + try { + settled = (Boolean) status.get("settled"); + } catch (Exception ex) { + } + try { + open = (Boolean) status.get("open"); + } catch (Exception ex) { + } + try { + speed = (Integer) status.get("speed"); + } catch (Exception ex) { + } + try { + position = (String) status.get("pos"); + if (position==null){ + position = ""; + } + } catch (Exception ex) { + } + try { + task = ((status.containsKey("task")) && (status.get("task") == null)) ? "" : ((String) status.get("task")).trim(); + } catch (Exception ex) { + System.out.println(ex); + ex.printStackTrace(); + } + try { + mode = ((String) status.get("mode")).trim(); + //mode = (String) Context.getInstance().evalLineBackground(getDevice().getName() + ".working_mode"); + } catch (Exception ex) { + } + try { + //if (status.get("status").equals("hold")){ + // moving = false; + //} else if (status.get("status").equals("move")){ + // moving = true; + //} + moving = Boolean.FALSE.equals(settled) || Boolean.FALSE.equals(empty); + } catch (Exception ex) { + } + } + + boolean remote = mode.equals("remote"); + boolean enabled = Boolean.TRUE.equals(powered); + buttonEnable.setEnabled((powered != null) && (powered == false)); + buttonDisable.setEnabled(enabled); + + butonStop.setEnabled(remote && Boolean.TRUE.equals(moving)); + buttonPause.setEnabled(remote && enabled && Boolean.TRUE.equals(moving) && Boolean.FALSE.equals(settled)); + buttonResume.setEnabled(remote && enabled && Boolean.TRUE.equals(moving) && Boolean.TRUE.equals(settled)); + + + ledPowered.setColor((powered == null) ? Color.GRAY : (powered ? Color.YELLOW : Color.DARK_GRAY)); + ledEmpty.setColor((empty == null) ? Color.GRAY : (empty ? Color.GREEN : Color.YELLOW)); + ledSettled.setColor((settled == null) ? Color.GRAY : (settled ? Color.GREEN : Color.YELLOW)); + ledOpen.setColor((open == null) ? Color.GRAY : (open ? Color.GREEN : Color.DARK_GRAY)); + ledMoving.setColor((moving == null) ? Color.GRAY : (moving ? Color.YELLOW : Color.DARK_GRAY)); + textTask.setText((task == null) ? "" : task); + ledTask.setColor((task == null) ? Color.GRAY : (task.isEmpty() ? Color.DARK_GRAY : Color.YELLOW)); + textPosition.setText((position == null) ? "" : position); + ledPosition.setColor((position == null) ? Color.GRAY : (position.isEmpty() ? Color.DARK_GRAY : Color.GREEN)); + //buttonAbort.setEnabled(!textTask.getText().isEmpty()); + spinnerSpeed.setEnabled(speed != null); + if (speed == null) { + spinnerSpeed.setValue(0); + } else { + spinnerSpeed.setValue(speed); + } + ledMode.setColor((mode == null) ? Color.BLACK : (remote ? Color.GREEN : Color.YELLOW)); + textMode.setText((mode == null) ? "" : mode); + + } finally{ + updating = false; + } + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jPanel1 = new javax.swing.JPanel(); + ledPowered = new ch.psi.pshell.swing.Led(); + jLabel1 = new javax.swing.JLabel(); + panelPowerCtr = new javax.swing.JPanel(); + buttonDisable = new javax.swing.JButton(); + buttonEnable = new javax.swing.JButton(); + jPanel2 = new javax.swing.JPanel(); + jLabel2 = new javax.swing.JLabel(); + spinnerSpeed = new ch.psi.utils.swing.HorizontalSpinner(); + jLabel7 = new javax.swing.JLabel(); + ledMoving = new ch.psi.pshell.swing.Led(); + panelMotionCtr = new javax.swing.JPanel(); + butonStop = new javax.swing.JButton(); + buttonResume = new javax.swing.JButton(); + buttonPause = new javax.swing.JButton(); + jPanel3 = new javax.swing.JPanel(); + jLabel3 = new javax.swing.JLabel(); + ledSettled = new ch.psi.pshell.swing.Led(); + jLabel4 = new javax.swing.JLabel(); + ledEmpty = new ch.psi.pshell.swing.Led(); + textTask = new javax.swing.JTextField(); + jLabel6 = new javax.swing.JLabel(); + textMode = new javax.swing.JTextField(); + buttonAbort = new javax.swing.JButton(); + jLabel8 = new javax.swing.JLabel(); + ledTask = new ch.psi.pshell.swing.Led(); + ledMode = new ch.psi.pshell.swing.Led(); + textPosition = new javax.swing.JTextField(); + ledPosition = new ch.psi.pshell.swing.Led(); + jLabel9 = new javax.swing.JLabel(); + panelState = new ch.psi.pshell.swing.DeviceStatePanel(); + jPanel4 = new javax.swing.JPanel(); + ledOpen = new ch.psi.pshell.swing.Led(); + jLabel5 = new javax.swing.JLabel(); + panelPowerCtr1 = new javax.swing.JPanel(); + buttonClose = new javax.swing.JButton(); + buttonOpen = new javax.swing.JButton(); + + jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Power")); + + ledPowered.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel1.setText("Powered:"); + + buttonDisable.setText("Disable"); + buttonDisable.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonDisableActionPerformed(evt); + } + }); + + buttonEnable.setText("Enable"); + buttonEnable.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonEnableActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelPowerCtrLayout = new javax.swing.GroupLayout(panelPowerCtr); + panelPowerCtr.setLayout(panelPowerCtrLayout); + panelPowerCtrLayout.setHorizontalGroup( + panelPowerCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelPowerCtrLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(buttonEnable) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18, Short.MAX_VALUE) + .addComponent(buttonDisable)) + ); + panelPowerCtrLayout.setVerticalGroup( + panelPowerCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelPowerCtrLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(panelPowerCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addComponent(buttonDisable, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonEnable)) + .addGap(0, 0, 0)) + ); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledPowered, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(panelPowerCtr, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel1) + .addComponent(ledPowered, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(panelPowerCtr, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2)) + ); + + jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Motion")); + + jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel2.setText("Speed:"); + + spinnerSpeed.setModel(new javax.swing.SpinnerNumberModel(10, null, 100, 1)); + spinnerSpeed.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerSpeedStateChanged(evt); + } + }); + + jLabel7.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel7.setText("Moving:"); + + ledMoving.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + butonStop.setIcon(new javax.swing.ImageIcon(App.class.getResource("/ch/psi/pshell/ui/Stop.png"))); + butonStop.setText(" "); + butonStop.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + butonStop.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + butonStopActionPerformed(evt); + } + }); + + buttonResume.setIcon(new javax.swing.ImageIcon(App.class.getResource("/ch/psi/pshell/ui/Play.png"))); + buttonResume.setText(" "); + buttonResume.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + buttonResume.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonResumeActionPerformed(evt); + } + }); + + buttonPause.setIcon(new javax.swing.ImageIcon(App.class.getResource("/ch/psi/pshell/ui/Pause.png"))); + buttonPause.setText(" "); + buttonPause.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + buttonPause.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonPauseActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelMotionCtrLayout = new javax.swing.GroupLayout(panelMotionCtr); + panelMotionCtr.setLayout(panelMotionCtrLayout); + panelMotionCtrLayout.setHorizontalGroup( + panelMotionCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelMotionCtrLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(butonStop, javax.swing.GroupLayout.DEFAULT_SIZE, 45, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonPause, javax.swing.GroupLayout.DEFAULT_SIZE, 46, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonResume, javax.swing.GroupLayout.DEFAULT_SIZE, 47, Short.MAX_VALUE) + .addGap(0, 0, 0)) + ); + panelMotionCtrLayout.setVerticalGroup( + panelMotionCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelMotionCtrLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(panelMotionCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(butonStop, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonPause, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonResume, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGap(0, 0, 0)) + ); + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addComponent(jLabel7, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledMoving, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(14, 14, 14) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(panelMotionCtr, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(spinnerSpeed)) + .addContainerGap()) + ); + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel7) + .addComponent(ledMoving, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(panelMotionCtr, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel2) + .addComponent(spinnerSpeed, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2)) + ); + + jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder("Status")); + + jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel3.setText("Settled:"); + + ledSettled.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel4.setText("Empty:"); + + ledEmpty.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + textTask.setEditable(false); + textTask.setHorizontalAlignment(javax.swing.JTextField.CENTER); + + jLabel6.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel6.setText("Mode:"); + + textMode.setEditable(false); + textMode.setHorizontalAlignment(javax.swing.JTextField.CENTER); + + buttonAbort.setText("Abort"); + buttonAbort.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonAbortActionPerformed(evt); + } + }); + + jLabel8.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel8.setText("Task:"); + + ledTask.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + ledMode.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + textPosition.setEditable(false); + textPosition.setHorizontalAlignment(javax.swing.JTextField.CENTER); + + ledPosition.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + jLabel9.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel9.setText("Position:"); + + javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); + jPanel3.setLayout(jPanel3Layout); + jPanel3Layout.setHorizontalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(jLabel8, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledTask, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledEmpty, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(jLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledSettled, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(jLabel9, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledPosition, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(textTask) + .addComponent(textPosition))) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(jLabel6, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledMode, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(textMode))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonAbort) + .addContainerGap()) + ); + + jPanel3Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel3, jLabel4, jLabel6, jLabel8, jLabel9}); + + jPanel3Layout.setVerticalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel3) + .addComponent(ledSettled, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel4) + .addComponent(ledEmpty, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(textMode, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(ledMode, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel6)) + .addGap(2, 2, 2) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(buttonAbort) + .addComponent(jLabel8) + .addComponent(ledTask, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(textTask, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel9) + .addComponent(ledPosition, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(textPosition, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2)) + ); + + jPanel4.setBorder(javax.swing.BorderFactory.createTitledBorder("Tool")); + + ledOpen.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel5.setText("Open:"); + + buttonClose.setText(" Close "); + buttonClose.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonCloseActionPerformed(evt); + } + }); + + buttonOpen.setText(" Open "); + buttonOpen.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonOpenActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelPowerCtr1Layout = new javax.swing.GroupLayout(panelPowerCtr1); + panelPowerCtr1.setLayout(panelPowerCtr1Layout); + panelPowerCtr1Layout.setHorizontalGroup( + panelPowerCtr1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelPowerCtr1Layout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(buttonOpen) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18, Short.MAX_VALUE) + .addComponent(buttonClose)) + ); + + panelPowerCtr1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonClose, buttonOpen}); + + panelPowerCtr1Layout.setVerticalGroup( + panelPowerCtr1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelPowerCtr1Layout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(panelPowerCtr1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addComponent(buttonClose, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonOpen)) + .addGap(0, 0, 0)) + ); + + javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); + jPanel4.setLayout(jPanel4Layout); + jPanel4Layout.setHorizontalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel5, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledOpen, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(panelPowerCtr1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel4Layout.setVerticalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel5) + .addComponent(ledOpen, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(panelPowerCtr1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2)) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelState, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(panelState, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + }// //GEN-END:initComponents + + private void buttonEnableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonEnableActionPerformed + try{ + Context.getInstance().evalLineBackground(getDevice().getName() + ".enable()"); + } catch (Exception ex){ + this.showException(ex); + } + }//GEN-LAST:event_buttonEnableActionPerformed + + private void buttonDisableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonDisableActionPerformed + try{ + Context.getInstance().evalLineBackground(getDevice().getName() + ".disable()"); + } catch (Exception ex){ + this.showException(ex); + } + }//GEN-LAST:event_buttonDisableActionPerformed + + private void spinnerSpeedStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerSpeedStateChanged + try{ + if (!updating){ + Context.getInstance().evalLineBackground(getDevice().getName() + ".set_monitor_speed(" + spinnerSpeed.getValue() + ")"); + } + } catch (Exception ex){ + this.showException(ex); + } + }//GEN-LAST:event_spinnerSpeedStateChanged + + private void butonStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_butonStopActionPerformed + try{ + Context.getInstance().evalLineBackground(getDevice().getName() + ".reset_motion()"); + } catch (Exception ex){ + this.showException(ex); + } + }//GEN-LAST:event_butonStopActionPerformed + + private void buttonPauseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonPauseActionPerformed + try{ + Context.getInstance().evalLineBackground(getDevice().getName() + ".stop()"); + } catch (Exception ex){ + this.showException(ex); + } + }//GEN-LAST:event_buttonPauseActionPerformed + + private void buttonResumeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonResumeActionPerformed + try{ + Context.getInstance().evalLineBackground(getDevice().getName() + ".resume()"); + } catch (Exception ex){ + this.showException(ex); + } + }//GEN-LAST:event_buttonResumeActionPerformed + + private void buttonAbortActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonAbortActionPerformed + try{ + Context.getInstance().evalLineBackground(getDevice().getName() + ".stop_task()"); + //Context.getInstance().evalLineBackground(getDevice().getName() + ".task_kill('" + textTask.getText() + "')"); + } catch (Exception ex){ + this.showException(ex); + } + }//GEN-LAST:event_buttonAbortActionPerformed + + private void buttonCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCloseActionPerformed + try{ + Context.getInstance().evalLineBackground(getDevice().getName() + ".close_tool()"); + } catch (Exception ex){ + this.showException(ex); + } + }//GEN-LAST:event_buttonCloseActionPerformed + + private void buttonOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonOpenActionPerformed + try{ + Context.getInstance().evalLineBackground(getDevice().getName() + ".open_tool()"); + } catch (Exception ex){ + this.showException(ex); + } + }//GEN-LAST:event_buttonOpenActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton butonStop; + private javax.swing.JButton buttonAbort; + private javax.swing.JButton buttonClose; + private javax.swing.JButton buttonDisable; + private javax.swing.JButton buttonEnable; + private javax.swing.JButton buttonOpen; + private javax.swing.JButton buttonPause; + private javax.swing.JButton buttonResume; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel6; + private javax.swing.JLabel jLabel7; + private javax.swing.JLabel jLabel8; + private javax.swing.JLabel jLabel9; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private javax.swing.JPanel jPanel3; + private javax.swing.JPanel jPanel4; + private ch.psi.pshell.swing.Led ledEmpty; + private ch.psi.pshell.swing.Led ledMode; + private ch.psi.pshell.swing.Led ledMoving; + private ch.psi.pshell.swing.Led ledOpen; + private ch.psi.pshell.swing.Led ledPosition; + private ch.psi.pshell.swing.Led ledPowered; + private ch.psi.pshell.swing.Led ledSettled; + private ch.psi.pshell.swing.Led ledTask; + private javax.swing.JPanel panelMotionCtr; + private javax.swing.JPanel panelPowerCtr; + private javax.swing.JPanel panelPowerCtr1; + private ch.psi.pshell.swing.DeviceStatePanel panelState; + private javax.swing.JSpinner spinnerSpeed; + private javax.swing.JTextField textMode; + private javax.swing.JTextField textPosition; + private javax.swing.JTextField textTask; + // End of variables declaration//GEN-END:variables +} diff --git a/script/.DS_Store b/script/.DS_Store new file mode 100644 index 0000000..3016cac Binary files /dev/null and b/script/.DS_Store differ diff --git a/script/client/.history b/script/client/.history new file mode 100644 index 0000000..e69de29 diff --git a/script/client/BerninaRobotClient.py b/script/client/BerninaRobotClient.py new file mode 100644 index 0000000..19b5c6d --- /dev/null +++ b/script/client/BerninaRobotClient.py @@ -0,0 +1,90 @@ +from PShellClient import PShellClient +import json +import time +import sys + + + +class BerninaRobotClient(PShellClient): + def __init__(self, url): + PShellClient.__init__(self, url) + self.start_sse_event_loop_task(["state", "shell"]) + self.state = self.get_state() + self.debug=False + + def on_event(self, name, value): + if name == "state": + self.state = value + print ("State: ", value) + elif name == "shell": + if self.debug: + print ("> ", value) + + def get_state(self): + self.state = PShellClient.get_state(self) + return self.state + + def wait_ready(self): + count = 0 + #Monitors event but polls every second just n case an event is missed + while (True): + if self.state != "Busy": + break + time.sleep(0.01) + count = count + 1 + if count>=100: + count=0 + self.get_state() + if self.state != "Ready": + raise Exception("Invalid state: " + str(self.state)) + + + def start_cmd(self, cmd, *argv): + cmd = cmd + "(" + for a in argv: + cmd = cmd + (("'" + a + "'") if type(a) is str else str(a) ) + ", " + cmd = cmd + ")" + ret = self.start_eval(cmd) + self.get_state() + return ret + + def wait_cmd(self, cmd): + self.wait_ready() + result = self.get_result(cmd) + #print (result) + if result["exception"] is not None: + raise Exception(result["exception"] ) + return result["return"] + + def abort_cmd(self): + self.abort() + self.eval("robot.stop_task()&") + + def get_robot_state(self): + return self.eval("robot.state&") + + + def get_robot_status(self): + status = self.eval("robot.take()&") + return status + + def print_info(self): + print ("State: " + str(self.get_state())) + print ("Robot state: " + str(self.get_robot_state())) + print ("Robot status: " + str(self.get_robot_status())) + print ("") + + + #High-level commands + def move_park(self, wait=True): + cmd = self.start_cmd("robot.move_park",) + return self.wait_cmd(cmd) if wait else cmd + + def move_home(self, wait=True): + cmd = self.start_cmd("robot.move_home") + return self.wait_cmd(cmd) if wait else cmd + + def tweak_x(self, offset, wait=True): + cmd = self.start_cmd("robot.tweak_x", offset) + return self.wait_cmd(cmd) if wait else cmd + diff --git a/script/client/PShellClient.py b/script/client/PShellClient.py new file mode 100644 index 0000000..30a3cc4 --- /dev/null +++ b/script/client/PShellClient.py @@ -0,0 +1,601 @@ +import threading +import time +import sys +import requests +import json + +try: + from urllib import quote # Python 2 +except ImportError: + from urllib.parse import quote # Python 3 + +try: + from sseclient import SSEClient +except: + SSEClient = None + + +class TimeoutException(Exception): + pass + +class PShellClient: + def __init__(self, url): + if not url.endswith('/'): + url=url+"/" + self.url = url + self.sse_event_loop_thread = None + self.subscribed_events = None + self.event_callback = None + self.plot_defaults={"format":"png", "width":600, "height":400} + self.debug = False + + def _get(self, url, stream=False): + url=self.url+url + if self.debug: + print ("GET " + url) + return requests.get(url=url, stream=stream) + + + def _put(self, url, json_data=None): + url=self.url+url + if self.debug: + print ("PUT " + url + " -> " + json.dumps(json_data)) + return requests.put(url=url, json=json_data) + + def _del(self, url): + url=self.url+url + if self.debug: + print ("DEL " + url) + return requests.delete(url=url) + + def _get_response(self, response, is_json=True): + if self.debug==True or self.debug=="rx": + print (" -> " + str(response.status_code) + ((" - " + response.text) if self.debug=="rx" else "")) + try: + response.raise_for_status() + except: + print (response.text) + raise + return json.loads(response.text) if is_json else response.text + + def _get_binary_response(self, response): + response.raise_for_status() + return response.raw.read() + + def get_plot_defaults(self): + """Return plot default properties. + + Args: + + Returns: + Dictionary + + """ + return self.plot_defaults.copy() + + def set_plot_defaults(self, defaults): + """Update plot default properties. + + Args: + Dictionary that will updated into the plot default properties. + Returns: + + """ + self.plot_defaults.update(defaults) + + def get_version(self): + """Return application version. + + Args: + + Returns: + String with application version. + + """ + return self._get_response(self._get("version"), False) + + def get_config(self): + """Return application configuration. + + Args: + + Returns: + Dictionary. + """ + return self._get_response(self._get("config")) + + def get_state(self): + """Return application state. + + Args: + + Returns: + String: Invalid, Initializing,Ready, Paused, Busy, Disabled, Closing, Fault, Offline + """ + return self._get_response(self._get("state")) + + def wait_state(self, state, timeout = -1): + """Wait application state equals. + + Args: + state (string or list of strings) + Returns: + """ + if type(state)==str: + state = [state] + start = time.time() + while self.get_state() not in state: + if (timeout>=0) and ((time.time()-start)>timeout): + raise TimeoutException() + time.sleep(0.1) + + def wait_state_not(self, state, timeout = -1): + """Wait application state different than. + + Args: + state (string or list of strings) + Returns: + """ + if type(state)==str: + state = [state] + start = time.time() + while self.get_state() in state: + if (timeout>=0) and ((time.time()-start)>timeout): + raise TimeoutException() + time.sleep(0.1) + + def get_logs(self): + """Return application logs. + + Args: + + Returns: + List of logs. + Format of each log: [date, time, origin, level, description] + + """ + return self._get_response(self._get("logs")) + + def get_history(self, index): + """Access console command history. + + Args: + index(int): Index of history entry (0 is the most recent) + + Returns: + History entry + + """ + return self._get_response(self._get("history/"+str(index)), False) + + def get_script(self, path): + """Return script. + + Args: + path(str): Script path (absolute or relative to script folder) + + Returns: + String with file contents. + + """ + return self._get_response(self._get("script/"+str(path)), False) + + def get_devices(self): + """Return global devices. + + Args: + + Returns: + List of devices. + Format of each device record: [name, type, state, value, age] + + """ + return self._get_response(self._get("devices")) + + def abort(self, command_id=None): + """Abort execution of command + + Args: + command_id(optional, int): id of the command to be aborted. + if None (default), aborts the foreground execution. + + Returns: + + """ + if command_id is None: + self._get("abort") + else: + return self._get("abort/"+str(command_id)) + + def pause(self): + """Pause execution of command + + Args: + + Returns: + + """ + self._get("pause") + + def resume(self): + """Resume execution of command + + Args: + + Returns: + + """ + self._get("resume") + + + def reinit(self): + """Reinitialize the software. + + Args: + + Returns: + + """ + self._get("reinit") + + def stop(self): + """Stop all devices implementing the 'Stoppable' interface. + + Args: + + Returns: + + """ + self._get("stop") + + def update(self): + """Update all global devices. + + Args: + + Returns: + + """ + self._get("update") + + def eval(self,statement): + """Evaluates a statement in the interpreter. + If the statement finishes by '&', it is executed in background. + Otherwise statement is executed in foreground (exclusive). + + Args: + statement(str): input statement + + Returns: + String containing the console return. + If an exception is produces in the interpretor, it is re-thrown here. + """ + statement = quote(statement) + return self._get_response(self._get("eval/"+statement), False) + + def run(self,script, pars=None, background=False): + """Executes script in the interpreter. + + Args: + script(str): name of the script (absolute or relative to the script base folder). Extension may be omitted. + pars(optional, list or dict): if a list is given, it sets sys.argv for the script. + If a dict is given, it sets global variable for the script. + background(optional, bool): if True script is executed in background. + + Returns: + Return value of the script. + If an exception is produces in the interpretor, it is re-thrown here. + """ + return self._get_response(self._put("run", {"script":script, "pars":pars, "background":background, "async":False })) + + def start_eval(self,statement): + """Starts evaluation of a statement in the interpreter. + If the statement finishes by '&', it is executed in background. + Otherwise statement is executed in foreground (exclusive). + + Args: + statement(str): input statement + + Returns: + Command id (int), which is used to retrieve command execution status/result (get_result). + """ + statement = quote(statement) + return int(self._get_response(self._get("evalAsync/"+statement), False)) + + def eval_json(self,statement): + """Evaluates a statement in the interpreter. + Args: + statement(str): input statement + + Returns: + Return object decoded from JSON string + """ + statement = quote(statement) + return self._get_response(self._get("eval-json/"+statement), True) + + def set_var(self,name, value): + """Sets interpreter variable. + Args: + name(str): variable name + value(obj): value - must be JSON compatible + + Returns: + + """ + data = {} + data["name"]=name + data["value"]=value + return self._get_response(self._put("set-var", data), False) + + def start_run(self,script, pars=None, background=False): + """Starts execution of a script in the interpreter. + + Args: + script(str): name of the script (absolute or relative to the script base folder). Extension may be omitted. + pars(optional, list or dict): if a list is given, it sets sys.argv for the script. + If a dict is given, it sets global variable for the script. + background(optional, bool): if True script is executed in background. + + Returns: + Command id (int), which is used to retrieve command execution status/result (get_result). + """ + return int(self._get_response(self._put("run", {"script":script, "pars":pars, "background":background, "async":True }))) + + def get_result(self, command_id=-1): + """Gets status/result of a command executed asynchronously (start_eval and start_run). + + Args: + command_id(optional, int): command id. If equals to -1 (default) return status/result of the foreground task. + + Returns: + Dictionary with the fields: 'id' (int): command id + 'status' (str): unlaunched, invalid, removed, running, aborted, failed or completed. + 'exception' (str): if status equals 'failed', holds exception string. + 'return' (obj): if status equals 'completed', holds return value of script (start_run) + or console return (start_eval) + """ + return self._get_response(self._get("result/"+str(command_id))) + + def help(self, input = ""): + """Returns help or auto-completion strings. + + Args: + input(optional, str): - ":" for control commands + - "" for builtin functions + - "devices" for device names + - builtin function name for function help + - else contains entry for auto-completion + + Returns: + List + + """ + return self._get_response(self._get("autocompletion/" + input)) + + def get_contents(self, path=None): + """Returns contents of data path. + + Args: + path(optional, str): Path to data relative to data home path. + - Folder + - File + - File (data root) | internal path + - internal path (on currently open data root) + + Returns: + List of contents + + """ + return self._get_response(self._get("contents" + ("" if path is None else ( "/"+path))), False) + + def get_data(self, path, type="txt"): + """Returns data on a given path. + + Args: + path(str): Path to data relative to data home path. + - File (data root) | internal path + - internal path (on currently open data root) + type(optional, str): txt, "json", "bin", "bs" + + Returns: + Data accordind to selected format/. + + """ + if type == "json": + return self._get_response(self._get("data-json/"+path), True) + elif type == "bin": + return self._get_binary_response(self._get("data-bin/"+path, stream=True)) + elif type == "bs": + from collections import OrderedDict + bs = self._get_binary_response(self._get("data-bs/"+path, stream=True)) + index=0 + msg = [] + for i in range(4): + size =int.from_bytes(bs[index:index+4], byteorder='big', signed=False) + index=index+4 + msg.append(bs[index:index+size]) + index=index+size + [main_header, data_header, data, timestamp] = msg + main_header = json.loads(main_header, object_pairs_hook=OrderedDict) + data_header = json.loads(data_header, object_pairs_hook=OrderedDict) + channel = data_header["channels"][0] + channel["encoding"] = "<" if channel.get("encoding", "little") else ">" + from bsread.data.helpers import get_channel_reader + channel_value_reader = get_channel_reader(channel) + return channel_value_reader(data) + + return self._get_response(self._get("data" + ("" if path is None else ( "/"+path))), False) + + def get_data_attrs(self, path): + return self._get_response(self._get("data-attr/"+path), True) + + def get_data_info(self, path): + return self._get_response(self._get("data-info/"+path), True) + + def get_scan_data(self, layout, path, group, device, type="txt"): + """Returns scan data of a device. + + Args: + layout(str): data layout + path(str): scan path + group(str): scan group + device(str): device name + type(optional, str): txt, "json", "bin" + + Returns: + Data accordind to selected format. + + """ + if layout is None or layout.strip()=="" or path is None: + raise Exception ("Invalid scan persistence path or layout") + path=path.replace("/", "
") + path=path.replace("|", "

") + group=group.replace("/", "
") + layout=layout.replace(".", "
") + url=layout+"/"+path+"/"+group+"/"+device + if type == "json": + url= "scandata-json/"+url + return self._get_response(self._get(url), True) + elif type == "bin": + url= "scandata-bin/"+url + return self._get_binary_response(self._get(url, stream=True)) + url= "scandata/"+url + return self._get_response(self._get(url), False) + + def get_plot_contexts(self): + """Return list of plot contexts + + Args: + + Returns: + List of names + + """ + return self._get_response(self._get("plots")) + + + def delete_plot_context(self, title): + """ + Delete a plotting context. + + Args: + title(str): name of the plotting context + + Returns: + + """ + return self._get_response(self._del("plots/"+title), False) + + def get_num_plots(self, title=None): + """Return number of plots in a given plotting context. + + Args: + title(str): name of the plotting context + + Returns: + Number of plots + + """ + if title is None: + title="null" + return int(self._get_response(self._get("plots/"+title))) + + def get_plot(self, title=None, index=0, format="png", width=None, height=None): + """Return a plot as a given image type. + + Args: + title(str): name of the plotting context + index(int): plot index (0-based) + format(str): plot format ("jpg", "png", "gif", "tif") + width(int): plot width (if 0 gets plot staddard size) + height(int): plot height (if 0 gets plot staddard size) + Returns: + Image file byte array + + """ + if title is None: + title="null" + if format is None: + format=self.plot_defaults["format"] + if width is None: + width=self.plot_defaults["width"] + if height is None: + height=self.plot_defaults["height"] + + url = "plot/"+title+"/"+str(index)+"/"+format+"/"+str(width)+"/"+str(height) + return self._get_binary_response(self._get(url, stream=True)) + + def print_logs(self): + for l in self.get_logs(): + print ("%s %s %-20s %-8s %s" % tuple(l)) + + def print_devices(self): + for l in self.get_devices(): + print ("%-16s %-32s %-10s %-32s %s" % tuple(l)) + + def print_help(self, input = ""): + for l in self.help(input): + print (l) + + #Events + def _sse_event_loop_task(self): + try: + while True: + try: + messages = SSEClient(self.url+"events") + for msg in messages: + if (self.subscribed_events is None) or (msg.event in self.subscribed_events): + try: + value = json.loads(msg.data) + except: + value = str(msg.data) + self.event_callback(msg.event, value) + except IOError as e: + #print(e) + pass + except: + print("Error:", sys.exc_info()[1]) + #raise + finally: + print ("Exit SSE loop task") + self.sse_event_loop_thread = None + + + def start_sse_event_loop_task(self, subscribed_events = None, event_callback = None): + """ + Initializes server event loop task. + Args: + subscribed_events: list of event names to subscribe to. If None subscribes to all. + event_callback: callback function. If None, self.on_event is called instead. + + Usage example: + def on_event(name, value): + if name == "state": + print ("State changed: ", value) + elif name == "record": + print ("Received scan record: ", value) + + pc.start_sse_event_loop_task(["state", "record"], on_event) + + """ + self.event_callback = event_callback if event_callback is not None else self.on_event + self.subscribed_events = subscribed_events + if SSEClient is not None: + if self.sse_event_loop_thread is None: + self.sse_event_loop_thread = threading.Thread(target=self._sse_event_loop_task, \ + args = (), \ + kwargs={}) + self.sse_event_loop_thread.daemon = True + self.sse_event_loop_thread.start() + else: + raise Exception ("sseclient library is not instlled: server events are not available") + + def on_event(self, name, value): + pass + + +if __name__ == "__main__": + import socket + ps = PShellClient( "http://" + socket.gethostname() + ":8080") + print (ps.get_state()) + diff --git a/script/client/sseclient.py b/script/client/sseclient.py new file mode 100644 index 0000000..3c42858 --- /dev/null +++ b/script/client/sseclient.py @@ -0,0 +1,163 @@ +import codecs +import re +import time +import warnings + +import six + +import requests + + +# Technically, we should support streams that mix line endings. This regex, +# however, assumes that a system will provide consistent line endings. +end_of_field = re.compile(r'\r\n\r\n|\r\r|\n\n') + +class SSEClient(object): + def __init__(self, url, last_id=None, retry=3000, session=None, chunk_size=1024, **kwargs): + self.url = url + self.last_id = last_id + self.retry = retry + self.chunk_size = chunk_size + + # Optional support for passing in a requests.Session() + self.session = session + + # Any extra kwargs will be fed into the requests.get call later. + self.requests_kwargs = kwargs + + # The SSE spec requires making requests with Cache-Control: nocache + if 'headers' not in self.requests_kwargs: + self.requests_kwargs['headers'] = {} + self.requests_kwargs['headers']['Cache-Control'] = 'no-cache' + + # The 'Accept' header is not required, but explicit > implicit + self.requests_kwargs['headers']['Accept'] = 'text/event-stream' + + # Keep data here as it streams in + self.buf = u'' + + self._connect() + + def _connect(self): + if self.last_id: + self.requests_kwargs['headers']['Last-Event-ID'] = self.last_id + + # Use session if set. Otherwise fall back to requests module. + requester = self.session or requests + self.resp = requester.get(self.url, stream=True, **self.requests_kwargs) + self.resp_iterator = self.resp.iter_content(chunk_size=self.chunk_size) + + # TODO: Ensure we're handling redirects. Might also stick the 'origin' + # attribute on Events like the Javascript spec requires. + self.resp.raise_for_status() + + def _event_complete(self): + return re.search(end_of_field, self.buf) is not None + + def __iter__(self): + return self + + def __next__(self): + decoder = codecs.getincrementaldecoder( + self.resp.encoding)(errors='replace') + while not self._event_complete(): + try: + next_chunk = next(self.resp_iterator) + if not next_chunk: + raise EOFError() + self.buf += decoder.decode(next_chunk) + + except (StopIteration, requests.RequestException, EOFError) as e: + time.sleep(self.retry / 1000.0) + self._connect() + + # The SSE spec only supports resuming from a whole message, so + # if we have half a message we should throw it out. + head, sep, tail = self.buf.rpartition('\n') + self.buf = head + sep + continue + + # Split the complete event (up to the end_of_field) into event_string, + # and retain anything after the current complete event in self.buf + # for next time. + (event_string, self.buf) = re.split(end_of_field, self.buf, maxsplit=1) + msg = Event.parse(event_string) + + # If the server requests a specific retry delay, we need to honor it. + if msg.retry: + self.retry = msg.retry + + # last_id should only be set if included in the message. It's not + # forgotten if a message omits it. + if msg.id: + self.last_id = msg.id + + return msg + + if six.PY2: + next = __next__ + + +class Event(object): + + sse_line_pattern = re.compile('(?P[^:]*):?( ?(?P.*))?') + + def __init__(self, data='', event='message', id=None, retry=None): + self.data = data + self.event = event + self.id = id + self.retry = retry + + def dump(self): + lines = [] + if self.id: + lines.append('id: %s' % self.id) + + # Only include an event line if it's not the default already. + if self.event != 'message': + lines.append('event: %s' % self.event) + + if self.retry: + lines.append('retry: %s' % self.retry) + + lines.extend('data: %s' % d for d in self.data.split('\n')) + return '\n'.join(lines) + '\n\n' + + @classmethod + def parse(cls, raw): + """ + Given a possibly-multiline string representing an SSE message, parse it + and return a Event object. + """ + msg = cls() + for line in raw.splitlines(): + m = cls.sse_line_pattern.match(line) + if m is None: + # Malformed line. Discard but warn. + warnings.warn('Invalid SSE line: "%s"' % line, SyntaxWarning) + continue + + name = m.group('name') + if name == '': + # line began with a ":", so is a comment. Ignore + continue + value = m.group('value') + + if name == 'data': + # If we already have some data, then join to it with a newline. + # Else this is it. + if msg.data: + msg.data = '%s\n%s' % (msg.data, value) + else: + msg.data = value + elif name == 'event': + msg.event = value + elif name == 'id': + msg.id = value + elif name == 'retry': + msg.retry = int(value) + + return msg + + def __str__(self): + return self.data diff --git a/script/client/test.py b/script/client/test.py new file mode 100644 index 0000000..8c4ac60 --- /dev/null +++ b/script/client/test.py @@ -0,0 +1,13 @@ +from BerninaRobotClient import BerninaRobotClient + +brc = BerninaRobotClient("http://saresb-cons-01.psi.ch:8080") + + +brc.print_info() +print brc.move_park() +print brc.move_home() +print brc.tweak_x(5) + +print brc.move_park(wait=False) +brc.abort_cmd() +print brc.move_home() diff --git a/script/devices/Axis.py b/script/devices/Axis.py new file mode 100644 index 0000000..d5f6fd6 --- /dev/null +++ b/script/devices/Axis.py @@ -0,0 +1,27 @@ +import requests + +def axis_exec(camera, cmd): + if is_string(camera): + camera = get_device(camera) + url = camera.url + s="axis-cgi/" + ctrl_url = url[0:url.find(s) + len(s)] + "com/ptz.cgi?" + cmd_url=ctrl_url+cmd + response = requests.get(url=cmd_url) + if 200<=response.status_code<300: + return response.text.strip() + raise Exception(response.text) + + +def axis_move(camera, direction): + direction=str(direction) + if direction not in ("home", "up", "down", "left", "right", "upleft", "upright", "downleft", "downright", "stop"): + raise Exception("Invalid direction: " + direction) + return axis_exec(camera, "move="+direction) + +def axis_rzoom(camera, steps): + steps= int(steps) + if steps<-9999 or steps>9999: + raise Exception("Invalid relative zoom steps: " + str(steps)) + return axis_exec(camera, "rzoom="+str(steps)) + diff --git a/script/devices/RobotBernina.py b/script/devices/RobotBernina.py new file mode 100644 index 0000000..eb6db20 --- /dev/null +++ b/script/devices/RobotBernina.py @@ -0,0 +1,120 @@ +KNOWN_POINTS = P_PARK, P_HOME = "park", "home" +TASKS = MOVE_PARK, MOVE_HOME, TWEAK_X = "movePark", "moveHome", "tweakX" + +DESCS = DESC_FAST,DESC_SLOW, = "mFast", "mSlow" +DESC_DEFAULT = DESCS[0] + +TOOLS = TOOL_DET = "tDet" +TOOL_DEFAULT = TOOLS[0] + +DEFAULT_ROBOT_POLLING = 500 +TASK_WAIT_ROBOT_POLLING = 50 +DEFAULT_SPEED=20 + +run("devices/RobotTCP") + + +simulation = False + + +class RobotSC(RobotTCP): + def __init__(self, name, server, timeout = 1000, retries = 1): + RobotTCP.__init__(self, name, server, timeout, retries) + self.set_tasks(TASKS) + self.set_known_points(KNOWN_POINTS) + self.setPolling(DEFAULT_ROBOT_POLLING) + self.last_command_timestamp = None + self.last_command_position = None + self.setSimulated() + + + def move_home(self): + if not self.is_in_point(P_HOME): + self.start_task(MOVE_HOME) + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + self.assert_home() + + def move_park(self): + if not self.is_in_point(P_PARK): + self.start_task(MOVE_PARK) + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + self.assert_park() + + def tweak_x(self, offset): + self.start_task(TWEAK_X, offset) + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + + def on_event(self,ev): + #print "EVT: " + ev + pass + + def on_change_working_mode(self, working_mode): + pass + + def on_task_finished(self, task, ret): + if self.isSimulated(): + if ret is not None and ret <0: + if task==MOVE_HOME: self.simulated_point=P_HOME + elif task==MOVE_PARK: self.simulated_point=P_PARK + else: self.simulated_point=None + + def doUpdate(self): + #start = time.time() + RobotTCP.doUpdate(self) + + def start_task(self, program, *args, **kwargs): + #TODO: Check safe position + self.task_name = program + self.task_args = args + self.task_kwargs = kwargs + ret = RobotTCP.start_task(self, program, *args, **kwargs) + + + def stop_task(self): + RobotTCP.stop_task(self) + #TODO: Restore safe position + + + def set_remote_mode(self): + self.set_profile("remote") + + def set_local(self): + self.set_profile("default") + + def is_park(self): + return self.is_in_point(P_PARK) + + def is_home(self): + return self.is_in_point(P_HOME) + + def is_cleared(self): + return self.get_current_point() is not None + + def assert_park(self): + self.assert_in_point(P_PARK) + + def assert_home(self): + self.assert_in_point(P_HOME) + + def assert_cleared(self): + if not self.is_cleared(): + raise Exception("Robot not in cleared position") + + def wait_ready(self): + robot.waitState(State.Ready, 1000) #robot.state.assertReady() + +if simulation: + add_device(RobotSC("robot","localhost:1000"),force = True) +else: + add_device(RobotSC("robot", "TellRobot6S:1000"), force = True) + + +#robot.latency = 0.005 +robot.set_default_desc(DESC_DEFAULT) +robot.default_speed = DEFAULT_SPEED +robot.set_frame(FRAME_DEFAULT) +robot.set_tool(TOOL_DEFAULT) +robot.setPolling(DEFAULT_ROBOT_POLLING) +robot.get_current_point() #TODO: REMOVE WHEN CURRENT POINT REPORTED BY POLLING MESSAGE + +#show_panel(robot) diff --git a/script/devices/RobotMotors.py b/script/devices/RobotMotors.py new file mode 100644 index 0000000..07ba862 --- /dev/null +++ b/script/devices/RobotMotors.py @@ -0,0 +1,62 @@ + +import ch.psi.pshell.device.PositionerConfig as PositionerConfig + + + +ROBOT_MOTORS = ["x" , "y", "z", "rx", "ry", "rz"] + + +class RobotCartesianMotor (PositionerBase): + def __init__(self, robot, index): + PositionerBase.__init__(self, robot.name + "_" + ROBOT_MOTORS[index], PositionerConfig()) + self.index = index + self.robot = robot + + #ATTENTION: Always initialize cartesian motors before scanning (or call robot.set_motors_enabled(True)) + def doInitialize(self): + self.setCache(self.doRead(), None) + + def doRead(self): + return float("nan") if self.robot.cartesian_destination is None else float(self.robot.cartesian_destination[self.index]) + + def doWrite(self, value): + if self.robot.cartesian_destination is not None: + #print "Move " + ROBOT_MOTORS[self.index] + " to " + str(value) + self.robot.cartesian_destination[self.index] = float(value) + self.robot.set_pnt(robot.cartesian_destination , "tcp_p") + self.robot.movel("tcp_p", self.robot.tool , DESC_SCAN) + + def doReadReadback(self): + return float("nan") if self.robot.cartesian_pos is None else float(self.robot.cartesian_pos[self.index]) + + + + +ROBOT_JOINT_MOTORS = ["j1" , "j2", "j3", "j4", "j5", "j6"] + + +class RobotJointMotor (PositionerBase): + def __init__(self, robot, index): + PositionerBase.__init__(self, robot.name + "_" + ROBOT_JOINT_MOTORS[index], PositionerConfig()) + self.index = index + self.robot = robot + + def doInitialize(self): + self.setpoint = self.doReadReadback() + self.setCache(self.doRead(), None) + + def doRead(self): + return self.setpoint + + def doWrite(self, value): + #print "Move " + ROBOT_JOINT_MOTORS[self.index] + " to " + str(value) + self.setpoint = value + joint = self.robot.herej() + joint[self.index] = value + self.robot.set_jnt(joint, name="tcp_j") + self.robot.movej("tcp_j", self.robot.tool , DESC_SCAN) + + def doReadReadback(self): + return self.robot.herej()[self.index] if self.robot.joint_pos is None else float(self.robot.joint_pos[self.index]) + + \ No newline at end of file diff --git a/script/devices/RobotTCP.py b/script/devices/RobotTCP.py new file mode 100644 index 0000000..fba7ecb --- /dev/null +++ b/script/devices/RobotTCP.py @@ -0,0 +1,959 @@ +import threading + +FRAME_DEFAULT = "world" +FLANGE = "flange" + +MAX_NUMBER_PARAMETERS = 20 + +run("devices/RobotMotors") + +class RobotTCP(TcpDevice, Stoppable): + def __init__(self, name, server, timeout = 1000, retries = 1): + TcpDevice.__init__(self, name, server) + self.timeout = timeout + self.retries = retries + self.header = None + self.trailer = "\n" + self.array_separator = '|' + self.cmd_separator = ' ' + self.msg_id = 0 + self.working_mode = "invalid" + self.status = "invalid" + self.powered = None + self.settled = None + self.empty = None + self.working_mode = None + self.status = None + self.lock = threading.Lock() + self.joint_forces = None + self.current_task = None + self.current_task_ret = None + self.high_level_tasks = [] + self.known_points = [] + self.current_points = [] + self.cartesian_destination = None + #self.flange_pos = [None] * 6 + self.cartesian_pos = [None] * 6 + self.joint_pos = [None] * 6 + self.cartesian_motors_enabled = False + self.cartesian_motors = [] + self.joint_motors_enabled = False + self.joint_motors = [] + self.tool = None + self.default_desc = None + self.tool_open = None + #self.tool_trsf = [0.0] * 6 + self.frame = FRAME_DEFAULT + self.polling_interval = 0.01 + self.reset = True + self.default_tolerance = 5 + self.default_speed = 100 + self.latency = 0 + self.last_msg_timestamp = 0 + + self.task_start_retries = 3 + self.exception_on_task_start_failure = True #Tasks may start and be finished when checked + self.simulated_point = "" + + def doInitialize(self): + super(RobotTCP, self).doInitialize() + self.reset = True + + def set_tool(self, tool): + self.tool = tool + #self.tool_trsf = self.get_tool_trsf() + self.evaluate("tcp_curtool=" + tool) + if self.cartesian_motors_enabled: + self.update() + self.set_motors_enabled(True) + self.is_tool_open() + + def get_tool(self): + return self.tool + + def set_frame(self, frame): + self.frame = frame + self.evaluate("tcp_curframe=" + frame) + if self.cartesian_motors_enabled: + self.update() + self.set_motors_enabled(True) + self.waitCacheChange(5000) + + def get_frame(self): + return self.frame + + def set_default_frame(self): + self.set_frame(FRAME_DEFAULT) + + def assert_tool(self, tool=None): + if tool is None: + if self.tool is None: + raise Exception("Tool is undefined") + elif self.tool != tool: + raise Exception("Invalid tool: " + self.tool) + + def set_default_desc(self,default_desc): + self.default_desc=default_desc + + def get_default_desc(self): + return self.default_desc + + def set_tasks(self,tasks): + self.high_level_tasks=tasks + + def get_tasks(self): + return self.high_level_tasks + + def set_known_points(self, points): + self.known_points=points + + def get_known_points(self): + return self.known_points + + def get_current_points(self, tolerance = None): + ret = self.is_in_points(*self.known_points, tolerance = tolerance) + current_points = [] + for i in range(len(ret)): + if ret[i] == True: + current_points.append(self.known_points[i]) + return current_points + + def get_current_point(self, tolerance = None): + current_points = self.get_current_points(tolerance) + if (current_points is not None) and ( len(current_points) >0): + return current_points[0] + return None + + def get_current_points_cached(self): + return self.current_points + + def get_current_point_cached(self): + if (self.current_points is not None) and (len (self.current_points) >0): + return self.current_points[0] + return None + + def assert_in_known_point(self, tolerance = None): + if self.get_current_point(tolerance) is None: + raise Exception ("Robot not in known point") + + def _sendReceive(self, msg_id, msg = "", timeout = None): + if self.latency >0: + timespan = time.time() - self.last_msg_timestamp + if timespan150): + raise Exception("Exceeded maximum message size") + self.getLogger().finer("TX = '" + str(tx)+ "'") + if (self.trailer != None): tx = tx + self.trailer + if self.isSimulated(): + return "" + rx = self.sendReceive(tx, msg_id, self.trailer , 0, self.timeout if timeout is None else timeout, self.retries) + self.last_msg_timestamp = time.time() + rx=rx[:-1] #Remove 0A + self.getLogger().finer("RX = '" + str(rx) + "'") + if rx[:3] != msg_id: + if (time.time()-start) >= timeout: + raise Exception("Received invalid message id: " + str(rx[:3]) + " - expecting:" + msg_id ) + if len(rx)<4: + raise Exception("Invalid message size: " + str(len(rx)) ) + if rx[3] == "*": + raise Exception(rx[4:]) + return rx[4:] + + def call(self, msg, timeout = None): + self.lock.acquire() + try: + id = "%03d" % self.msg_id + self.msg_id = (self.msg_id+1)%1000 + return self._sendReceive(id, msg, timeout) + finally: + self.lock.release() + + def execute(self, command, *args, **kwargs): + timeout = None if (kwargs is None) or (not kwargs.has_key("timeout")) else kwargs["timeout"] + msg = str(command) + if len(args)>MAX_NUMBER_PARAMETERS: + raise Exception("Exceeded maximum number of parameters") + for i in range(len(args)): + msg += (self.cmd_separator if (i==0) else self.array_separator) + str(args[i]) + rx = self.call(msg, timeout) + if rx.count(self.array_separator)>0: + return rx.split(self.array_separator) + return rx + + def evaluate(self, cmd, timeout=None): + ret = self.execute('eval', cmd, timeout=timeout) + if is_string(ret): + if ret.strip() != "": raise Exception(ret) + + def get_var(self, name): + return self.execute('get_var', name) + + #Makes app crash + #def get_str(self, name='s'): + # return self.execute('get_str', name) + + def get_arr(self, name, size): + return self.execute('get_arr', name, size) + + def get_bool(self, name = "tcp_b"): + return True if (self.execute('get_bool', name).strip() == '1') else False + + def get_int(self, name ="tcp_n"): + return int(self.get_var(name)) + + def get_float(self, name ="tcp_n"): + return float(self.get_var(name)) + + def get_int_arr(self, size, name="tcp_a"): + # not working. A Jython bug in PyUnicaode? + #return [int(x) for x in self.get_arr("tcp_a", size)] + ret = [] + a=self.get_arr(name, size) + for i in range(size): + ret.append(int(a[i])) + return ret + + def get_float_arr(self, size, name="tcp_a"): + #return [float(x) for x in self.get_arr("tcp_a", size)] + a=self.get_arr(name, size) + ret = []; + for i in range(size): ret.append(float(a[i])); + return ret + + def get_trsf(self, name="tcp_t"): + a = self.execute('get_trf', name) + ret = [] + for i in range(6): ret.append(float(a[i])) + return ret + + def set_trsf(self, l, name="tcp_t"): + self.evaluate(name + "={" + str(l[0]) + ","+ str(l[1]) + ","+ str(l[2]) + ","+ str(l[3]) + ","+ str(l[4]) + ","+ str(l[5]) + "}") + + def get_jnt(self, name="tcp_j"): + a = self.execute('get_jnt', name) + ret = [] + for i in range(6): ret.append(float(a[i])) + return ret + + def set_jnt(self, l, name="tcp_j"): + self.evaluate(name + "={" + str(l[0]) + ","+ str(l[1]) + ","+ str(l[2]) + ","+ str(l[3]) + ","+ str(l[4]) + ","+ str(l[5]) + "}") + + def get_pnt(self, name="tcp_p"): + #a = self.execute('get_pnt', name) + #ret = [] + #for i in range(6): ret.append(float(a[i])) + #return ret + return self.get_trsf(name+".trsf") + + #trsf = (x,y,z,rx,ry,rz) + #TODO: config = (shoulder, elbow, wrist) + def set_pnt(self, trsf, name="tcp_p", config=None): + self.set_trsf(trsf, name+".trsf") + + def get_tool_trsf(self, name=None): + if name is None: + self.assert_tool() + name = self.tool + return self.get_trsf(name+".trsf") + + def set_tool_trsf(self, trsf, name=None): + if name is None: + self.assert_tool() + name = self.tool + self.set_trsf(trsf, name+".trsf") + + def eval_int(self, cmd): + if self.isSimulated(): + return 0 + self.evaluate("tcp_n=" + cmd) + return self.get_int() + + def eval_float(self, cmd): + if self.isSimulated(): + return 0.0 + self.evaluate("tcp_n=" + cmd) + return self.get_float() + + def eval_bool(self, cmd): + if self.isSimulated(): + return False + self.evaluate("tcp_b=" + cmd) + return self.get_bool() + + #def eval_str(self, cmd): + # self.evaluate("s=" + cmd) + # return self.get_str() + + def eval_jnt(self, cmd): + self.evaluate("tcp_j=" + cmd) + return self.get_jnt() + + def eval_trf(self, cmd): + self.evaluate("tcp_t=" + cmd) + return self.get_trsf() + + def eval_pnt(self, cmd): + self.evaluate("tcp_p=" + cmd) + return self.get_pnt() + + + #Robot control + def is_powered(self): + self.powered = self.eval_bool("isPowered()") + return self.powered + + def enable(self): + if not self.is_powered(): + self.evaluate("enablePower()") + time.sleep(1.0) + if not self.is_powered(): + raise Exception("Cannot enable power") + + #waits for power to be actually cut off + def disable(self): + self.evaluate("disablePower()", timeout=5000) + + def get_monitor_speed(self): + self.speed = self.eval_int("getMonitorSpeed()") + return self.speed + + def set_monitor_speed(self, speed): + ret = self.eval_int("setMonitorSpeed(" + str(speed) + ")") + if (ret==-1): raise Exception("The robot is not in remote working mode") + if (ret==-2): raise Exception("The monitor speed is under the control of the operator") + if (ret==-3): raise Exception("The specified speed is not supported") + + def set_default_speed(self): + set_monitor_speed(self.default_speed) + + def is_calibrated(self): + return self.eval_bool("isCalibrated()") + + def save_program(self): + ret = self.execute('save', timeout=5000) + if str(ret) != "0": raise Exception("Error saving program: " + str(ret)) + + def _update_working_mode(self, mode, status): + cur_mode = self.working_mode + if mode==1: + self.working_mode = "manual" + self.status = "hold" if status==6 else "move" + elif mode==2: + self.working_mode = "test" + self.status = "hold" if status==3 else "move" + elif mode==3: + self.working_mode = "local" + self.status = "hold" if status==2 else "move" + elif mode==4: + self.working_mode = "remote" + self.status = "hold" if status==2 else "move" + else: + self.working_mode = "invalid" + self.status = "invalid" + if self.working_mode != cur_mode: + try: + self.on_change_working_mode(self.working_mode) + except: + pass + + def read_working_mode(self): + try: + mode = self.eval_int("workingMode(tcp_a)") + status = int(self.get_var("tcp_a[0]")) + self._update_working_mode(mode, status) + self._update_state() + except: + self.working_mode = "invalid" + self.status = "invalid" + return self.working_mode + + def get_emergency_stop_sts(self): + st = self.eval_int("esStatus()") + if (st== 1): return "active" + if (st== 2): return "activated" + return "off" + + def get_safety_fault_signal(self): + fault = self.eval_bool("safetyFault(s)") + #if (fault): + # return get_str() + return fault + + #Motion control + def stop(self): + self.evaluate("stopMove()") + + def resume(self): + self.evaluate("restartMove()") + + def reset_motion(self, joint=None, timeout=None): + #TODO: in new robot robot.resetMotion() is freezing controller + #self.evaluate("resetMotion()" if (joint is None) else ("resetMotion(" + joint + ")")) + if joint is None: + self.execute('reset', timeout=timeout) + else: + self.execute('reset', str(joint), timeout=timeout) + + def is_empty(self): + self.empty = self.eval_bool("isEmpty()") + self._update_state() + return self.empty + + def is_settled(self): + self.settled = self.eval_bool("isSettled()") + self._update_state() + return self.settled + + def get_move_id(self): + return self.eval_int("getMoveId()") + + def set_move_id(self, id): + return self.evaluate("setMoveId(" + str(id) + " )") + + def get_joint_forces(self): + try: + self.evaluate("getJointForce(tcp_a)") + self.joint_forces = self.get_float_arr(6) + return self.joint_forces + except: + self.joint_forces = None + raise + + def movej(self, joint_or_point, tool=None, desc=None, sync=False): + if self.isSimulated(): + self.simulated_point = "" + if desc is None: desc = self.default_desc + if tool is None: tool = self.tool + #If joint_or_point is a list assumes ir is a point + if not is_string(joint_or_point): + robot.set_pnt(joint_or_point , "tcp_p") + joint_or_point = "tcp_p" + + #TODO: in new robot movel and movej is freezing controller + #ret = self.eval_int("movej(" + joint_or_point + ", " + tool + ", " + desc +")") + ret = int(self.execute('movej',joint_or_point, tool, desc)) + + if sync: + self.wait_end_of_move() + if self.isSimulated(): + self.simulated_point = joint_or_point + return ret + + def movel(self, point, tool=None, desc=None, sync=False): + if self.isSimulated(): + self.simulated_point = "" + if desc is None: desc = self.default_desc + if tool is None: tool = self.tool + if not is_string(point): + robot.set_pnt(point , "tcp_p") + point = "tcp_p" + #TODO: in new robot movel and movej is freezing controller + #ret = self.eval_int("movel(" + point + ", " + tool + ", " + desc +")") + ret = int(self.execute('movel',point, tool, desc)) + + if sync: + self.wait_end_of_move() + if self.isSimulated(): + self.simulated_point = point + return ret + + def movec(self, point_interm, point_target, tool=None, desc=None, sync=False): + if self.isSimulated(): + self.simulated_point = "" + if desc is None: desc = self.default_desc + if tool is None: tool = self.tool + + #TODO: in new robot movel and movej is freezing controller + #ret = self.eval_int("movec(" + point_interm + ", " + point_target + ", " + tool + ", " + desc +")") + ret = int(self.execute('movec', point_interm, point_target, tool, desc)) + + if sync: + self.wait_end_of_move() + if self.isSimulated(): + self.simulated_point = point_target + return ret + + def wait_end_of_move(self): + time.sleep(0.05) + self.update() + #time.sleep(0.01) + #self.waitCacheChange(-1) + self.waitReady(-1) + #self.waitState(State.Ready, -1) + + + #Tool - synchronized as can freeze communication + """ + def open_tool(self, tool=None, timeout=3000): + #This function can timeout since it synchronizes move. Checking state before otherwise it can freeze the communication. + self.waitState(State.Ready, -1) + if tool is None: tool = self.tool + return self.evaluate("open(" + tool + " )", timeout=timeout) + + def close_tool(self, tool=None, timeout=3000): + #This function can timeout since it synchronizes move. Checking state before otherwise it can freeze the communication. + self.waitState(State.Ready, -1) + if tool is None: tool = self.tool + return self.evaluate("close(" + tool + " )", timeout=timeout) + """ + #Tool - Not synchronized calls: atention to open/close only when state is Ready + def open_tool(self, tool=None): + if tool is None: tool = self.tool + self.evaluate(tool + ".gripper=true") + self.tool_open = True + + def close_tool(self, tool=None): + if tool is None: tool = self.tool + self.evaluate(tool + ".gripper=false") + self.tool_open = False + + def is_tool_open(self, tool=None): + if tool is None: tool = self.tool + self.tool_open = robot.eval_bool(tool + ".gripper") + return self.tool_open + + + #Arm position + def herej(self): + return self.eval_jnt("herej()") + + def distance_t(self, trsf1, trsf2): + return self.eval_float("distance(" + trsf1 + ", " + trsf2 + ")") + + def distance_p(self, pnt1, pnt2): + return self.eval_float("distance(" + pnt1 + ", " + pnt2 + ")") + + def compose(self, pnt, frame = None, trsf = "tcp_t"): + if frame is None: frame = self.frame + return self.eval_pnt("compose(" + pnt + ", " + frame + ", " + trsf + ")") + + def here(self, tool=None, frame=None): + if tool is None: tool = self.tool + if frame is None: frame = self.frame + return self.eval_pnt("here(" + tool + ", " + frame + ")") + + def joint_to_point(self, tool=None, frame=None, joint="tcp_j"): + if tool is None: tool = self.tool + if frame is None: frame = self.frame + return self.eval_pnt("jointToPoint(" + tool + ", " + frame + ", " + joint +")") + + def point_to_joint(self, tool=None, initial_joint="tcp_j", point="tcp_p"): + if tool is None: tool = self.tool + if self.eval_bool("pointToJoint(" + tool + ", " + initial_joint + ", " + point +", j)"): + return self.get_jnt() + + def position(self, point, frame=None): + if frame is None: frame = self.frame + return self.eval_trf("position(" + point + ", " + frame + ")") + + #Profile + def get_profile(self): + return self.execute('get_profile', timeout=2000) + + def set_profile(self, name, pwd = ""): + self.execute('set_profile', str(name), str(pwd), timeout=5000) + + + #Task control + def task_create(self, program, *args, **kwargs): + program = str(program) + priority = 10 if (kwargs is None) or (not kwargs.has_key("priority")) or (kwargs["priority"] is None) else kwargs["priority"] + name = str(program if (kwargs is None) or (not kwargs.has_key("name")) else kwargs["name"]) + + if self.get_task_status(name)[0] != -1: + raise Exception("Task already exists: " + name) + + if priority<1 or priority > 100: + raise Exception("Invalid priority: " + str(priority)) + + cmd = program + '(' + for i in range(len(args)): + val = args[i] + if type(val) == bool: + if val == True: val = "true" + elif val == False: val = "false" + cmd += str(val) + (',' if (i<(len(args)-1)) else '') + cmd+=')' + + #TODO: in new robot exec taskCreate is freezing controller + #REMOVE if bug is fixed + self.execute('task_create',name, str(priority), program, *args) + #self.evaluate('taskCreate "' + name + '", ' + str(priority) + ', ' + cmd) + if self.isSimulated(): + self.simulated_point = "" + + + def task_suspend(self, name): + self.evaluate('taskSuspend("' + str(name)+ '")') + + #waits until the task is ready for restart + def task_resume(self, name): + self.evaluate('taskResume("' + str(name)+ '",0)', timeout = 2000) + + #waits for the task to be actually killed + def task_kill(self, name): + #self.evaluate('taskKill("' + str(name)+ '")', timeout = 5000) + self.execute('kill', str(name), timeout=5000) + + def get_task_status(self, name): + if self.isSimulated(): + return (-1,"Stopped") + code = self.eval_int('taskStatus("' + str(name)+ '")') + #TODO: String assignments in $exec causes application to freeze + #status = self + if code== -1: status = "Stopped" + elif code== 0: status = "Paused" + elif code== 1: status = "Running" + #else: status = self.execute('get_help', code) + else: status = "Error" + return (code,status) + + def get_tasks_status(self, *pars): + ret = self.execute("task_sts", *pars) + ret = ret[0:len(pars)] + for i in range(len(ret)): + try: + ret[i] = int(ret[i]) + except: + ret[i] = None + return ret + + def _update_state(self): + #self.setState(State.Busy if self.status=="move" else State.Ready) + if self.state==State.Offline: + print "Communication resumed" + if self.reset or (self.state==State.Offline): + self.check_task() + if self.current_task is not None: + print "Ongoing task: " + self.current_task + if (not self.settled) or (self.current_task is not None): self.setState(State.Busy) + elif not self.empty: self.setState(State.Paused) + else: self.setState(State.Ready) + + def doUpdate(self): + try: + start = time.time() + cur_task = self.current_task #Can change in background so cache it + if self.isSimulated(): + sts = [1, 1,"1", 100, "1", "1", 0, 0, \ + 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, \ + ] + else: + sts = self.execute("get_status", cur_task) + self._update_working_mode(int(sts[0]), int(sts[1])) + self.powered = sts[2] == "1" + self.speed = int(sts[3]) + self.empty = sts[4] == "1" + self.settled = sts[5] == "1" + + #TODO: add tool open + if cur_task is not None: + if self.isSimulated(): + if time.time() - self.current_task_timestamp > 3.0: + log("Task "+ str(cur_task) + " finished with code: -1", False) + ret = -1 if self.current_task_timestamp>0 else None + self.on_task_finished(self.current_task, ret) + self.current_task, self.current_task_ret = None, ret + + else: + if int(sts[6]) < 0: + try: + ret = int(sts[7]) + except: + ret = None + log("Task "+ str(cur_task) + " finished with code: " + str(ret), False) + self.on_task_finished(cur_task, ret) + self.current_task, self.current_task_ret = None, ret + + + + for i in range(6): + self.joint_pos[i] = float(sts[8 + i]) + for i in range(6): + self.cartesian_pos[i] = float(sts[14 + i]) + + ev_index = 20 #7 + ev = sts[ev_index] if len(sts)>ev_index else "" + if len(ev.strip()) >0: + self.getLogger().info(ev) + self.on_event(ev) + + self._update_state() + self.reset = False + self.setCache({"powered": self.powered, + "speed": self.speed, + "empty": self.empty, + "settled": self.settled, + "task": cur_task, + "mode": self.working_mode, + "status": self.status, + "open": self.tool_open, + "pos": self.get_current_point_cached() if self.state==State.Ready else None #TODO: make it calculated in robot by polling funtion + }, None) + + if self.cartesian_motors_enabled: + for m in self.cartesian_motors: + m.readback.update() + + if self.joint_motors_enabled: + for m in self.joint_motors: + m.readback.update() + + except: + if self.state != State.Offline: + print >> sys.stderr, "Update error: " + str(sys.exc_info()[1]) + self.setState(State.Offline) + + #Cartesian space + """ + def get_cartesian_pos(self): + self.assert_tool() + return self.eval_pnt("jointToPoint(" + self.tool + ", " + self.frame + ", herej())") + #self.set_jnt(self.herej()) + #return self.joint_to_point(tool, frame) + """ + + + #TODO: in new robot robot.evaluate("tcp_p=jointToPoint(tSuna, world, herej())") is freezing controller (cannot call herej directly) + #We can consider atomic because tcp_j is only accessed in comTcp + def get_cartesian_pos(self, tool=None, frame=None): + if tool is None: + self.assert_tool() + tool = self.tool + if frame is None: + frame = self.frame + #Do not work + #self.evaluate("tcp_j=herej(); tcp_p=jointToPoint(" + tool + ", " + frame + ", tcp_j)") + #return self.get_pnt() + a = self.execute('get_pos', tool, frame) + ret = [] + for i in range(6): ret.append(float(a[i])) + return ret + + + def get_flange_pos(self, frame=None): + return get_cartesian_pos(FLANGE, frame) + + + def get_cartesian_destination(self, tool=None, frame=None): + if tool is None: + self.assert_tool() + tool = self.tool + if frame is None: + frame = self.frame + return self.here(tool, frame) + + def get_distance_to_pnt(self, name): + if self.isSimulated(): + if name and (name==self.simulated_point): + return 0 + else: + return 10000 + #self.here(self.tool, self.frame) #??? + self.set_pnt(self.get_cartesian_pos() ) + return self.distance_p("tcp_p", name) + + def is_in_point(self, p, tolerance = None): #Tolerance in mm + if (tolerance is None) and p in self.known_points: + #If checking a known point with default tolerance, updates the position cache + return p in self.get_current_points() + tolerance = self.default_tolerance if tolerance == None else tolerance + d = self.get_distance_to_pnt(p) + if d<0: + raise Exception ("Error calculating distance to " + p + " : " + str(d)) + return d=0: + # raise Exception("Ongoing high-level task: " + task) + ts = self.get_tasks_status(*tasks) + for i in range(len(ts)): + if ts[i] > 0: + raise Exception("Ongoing high-level task: " + tasks[i]) + + self.clear_task_ret() + + for i in range(self.task_start_retries): + self.task_create(program, *args, **kwargs) + (code, status) = self.get_task_status(program) + if code>=0: break + + if self.isSimulated(): + break + if i < self.task_start_retries-1: + ret = self.get_task_ret(False) + if ret == 0: #Did't start + log("Retrying starting : " + str(program) + str(args) + " - status: " + str(status) + " (" + str(code) + ")", False) + print "Retrying starting : " + str(program) + str(args) + " - status: " + str(status) + " (" + str(code) + ")" + else : + print "Retrying aborted : " + str(program) + str(args) + " - ret: " + str(ret) + " - status: " + str(status) + " (" + str(code) + ")" + break + else: + log("Failed starting : " + str(program) + str(args), False) + print "Failed starting : " + str(program) + str(args) + if self.exception_on_task_start_failure: + raise Exception("Cannot start task: " + program + str(args)) + + log("Task started: " + str(program) + str(args) + " - status: " + str(status) + " (" + str(code) + ")", False) + self.current_task, self.current_task_ret, self.current_task_timestamp = program, None, time.time() + self.update() + #self._update_state() + + #TODO: remove + if self.current_task is None: + log("Task finished in first polling : " + str(program) , False) + print "Task finished in first polling : " + str(program) + + return code + + def stop_task(self): + tasks = [t for t in self.high_level_tasks] + if (self.current_task is not None) and (not self.current_task in tasks): + tasks.append(self.current_task) + for task in tasks: + #if self.get_task_status(task)[0]>=0: + self.task_kill(task) + if self.isSimulated(): + self.current_task_timestamp=-1 + self.reset_motion() + + def get_task_ret(self, cached = True): + return self.current_task_ret if cached else self.eval_int("tcp_ret") + + def clear_task_ret(self): + return self.evaluate("tcp_ret=0") + + def get_task(self): + return self.current_task + + def check_task(self): + if self.current_task is None: + for task in self.high_level_tasks: + if self.get_task_status(task)[0]>=0: + self.current_task, self.current_task_ret = task, None + log("Task detected: " + str(self.current_task), False) + return self.current_task + + def wait_task_finished (self, polling = None): + cur_polling = self.polling + if polling is not None: + self.polling = polling + try: + while self.get_task() != None: + time.sleep(self.polling_interval) + finally: + if polling is not None: + self.polling = cur_polling + ret = self.get_task_ret() + return ret + + def assert_no_task(self): + task = self.check_task() + if task != None: + raise Exception("Ongoing task: " + task) + + def on_event(self,ev): + pass + + def on_change_working_mode(self, working_mode): + pass + + def on_task_finished(self, task, ret): + pass \ No newline at end of file diff --git a/script/local.groovy b/script/local.groovy new file mode 100644 index 0000000..eef7106 --- /dev/null +++ b/script/local.groovy @@ -0,0 +1,3 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Deployment specific global definitions - executed after startup.groovy +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/script/local.js b/script/local.js new file mode 100644 index 0000000..e2eeaad --- /dev/null +++ b/script/local.js @@ -0,0 +1,4 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Deployment specific global definitions - executed after startup.js +/////////////////////////////////////////////////////////////////////////////////////////////////// + diff --git a/script/local.py b/script/local.py new file mode 100644 index 0000000..bb1d0eb --- /dev/null +++ b/script/local.py @@ -0,0 +1,6 @@ +################################################################################################### +# Deployment specific global definitions - executed after startup.py +################################################################################################### + +run("devices/RobotBernina") +run("devices/Axis") \ No newline at end of file