From b4b83995ed86fe3b4113eba43e630ab6de6cf481 Mon Sep 17 00:00:00 2001 From: Shekar V Date: Fri, 5 Apr 2024 23:19:59 -0400 Subject: [PATCH 1/5] Added iced pin check --- embl_robot.py | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/embl_robot.py b/embl_robot.py index 072b0994..4d9066cb 100644 --- a/embl_robot.py +++ b/embl_robot.py @@ -296,10 +296,13 @@ def mount(self, gov_robot, puckPos,pinPos,sampID,**kwargs): logger.error(e) e_s = str(e) if (e_s.find("Fatal") != -1): - daq_macros.robotOff() - daq_macros.disableMount() - daq_lib.gui_message(e_s + ". FATAL ROBOT ERROR - CALL STAFF! robotOff() executed.") - return MOUNT_FAILURE + if self.checkIcedPin(e_s): + return MOUNT_STEP_SUCCESSFUL + else: + daq_macros.robotOff() + daq_macros.disableMount() + daq_lib.gui_message(e_s + ". FATAL ROBOT ERROR - CALL STAFF! robotOff() executed.") + return MOUNT_FAILURE if (e_s.find("tilted") != -1 or e_s.find("Load Sample Failed") != -1 or e_s.find("Fail to calculate Pin Position") != -1): if (getBlConfig("queueCollect") == 0): daq_lib.gui_message(e_s + ". Try mounting again") @@ -324,6 +327,25 @@ def mount(self, gov_robot, puckPos,pinPos,sampID,**kwargs): return MOUNT_FAILURE return MOUNT_STEP_SUCCESSFUL + def checkIcedPin(self, error_string, max_wait_time=60): + """Sometimes after mount, the pin is not detected on the gonio because + there is a buildup of ice between the pin and gonio + This function checks for that error, and if it is detected will check for + the pin every second for max_wait_time seconds. + If after that time it still does not detect the sample it will throw an error + """ + + if (error_string.find("Pin lost during mount transaction") != -1): + logger.info(f"Pin probably has ice, waiting for {max_wait_time} seconds") + wait_time = 0 + while wait_time < max_wait_time: + wait_time += 1 + time.sleep(1) + if getPvDesc("sampleDetected") == 0: + # Sample is detected + return True + return False + def postMount(self, gov_robot, puck, pinPos, sampID): sampYadjust = float(getBlConfig('sampYAdjust')) if getBlConfig('robot_online'): From 62cdacbcc688a882171e28100a5c682093e870ba Mon Sep 17 00:00:00 2001 From: Shekar V Date: Tue, 16 Apr 2024 10:37:05 -0400 Subject: [PATCH 2/5] Changed checkIcedPin to isSampleDetected --- embl_robot.py | 829 +++++++++++++++++++++++++++----------------------- 1 file changed, 455 insertions(+), 374 deletions(-) diff --git a/embl_robot.py b/embl_robot.py index 4d9066cb..3903eaa6 100644 --- a/embl_robot.py +++ b/embl_robot.py @@ -1,448 +1,529 @@ -import RobotControlLib -import daq_utils -import db_lib -from daq_utils import getBlConfig, setBlConfig -import daq_lib -import beamline_lib -import time -import daq_macros -import beamline_support -from beamline_support import getPvValFromDescriptor as getPvDesc, setPvValFromDescriptor as setPvDesc +import _thread +import logging import os import sys +import time import traceback -import _thread from threading import Thread -import logging + import epics.ca -import top_view -from config_params import TOP_VIEW_CHECK, DETECTOR_SAFE_DISTANCE, MOUNT_SUCCESSFUL, MOUNT_FAILURE,\ - MOUNT_UNRECOVERABLE_ERROR, MOUNT_STEP_SUCCESSFUL, UNMOUNT_SUCCESSFUL,\ - UNMOUNT_FAILURE, UNMOUNT_STEP_SUCCESSFUL, PINS_PER_PUCK, EMBL_SERVER_PV_BASE +import RobotControlLib + +import beamline_lib +import beamline_support +import daq_lib +import daq_macros +import daq_utils +import db_lib import gov_lib -#from start_bs import gov_human, gov_robot +import top_view +from beamline_support import getPvValFromDescriptor as getPvDesc +from beamline_support import setPvValFromDescriptor as setPvDesc +from config_params import ( + DETECTOR_SAFE_DISTANCE, + EMBL_SERVER_PV_BASE, + MOUNT_FAILURE, + MOUNT_STEP_SUCCESSFUL, + MOUNT_SUCCESSFUL, + MOUNT_UNRECOVERABLE_ERROR, + PINS_PER_PUCK, + TOP_VIEW_CHECK, + UNMOUNT_FAILURE, + UNMOUNT_STEP_SUCCESSFUL, + UNMOUNT_SUCCESSFUL, +) +from daq_utils import getBlConfig, setBlConfig + +# from start_bs import gov_human, gov_robot logger = logging.getLogger(__name__) global retryMountCount retryMountCount = 0 -setBlConfig('sampYAdjust', 0) +setBlConfig("sampYAdjust", 0) -def setWorkposThread(init,junk): - logger.info("setting work pos in thread") - setPvDesc("robotGovActive",1) - setPvDesc("robotXWorkPos",getPvDesc("robotXMountPos")) - setPvDesc("robotYWorkPos",getPvDesc("robotYMountPos")) - setPvDesc("robotZWorkPos",getPvDesc("robotZMountPos")) - setPvDesc("robotOmegaWorkPos",90.0) - if (init): - time.sleep(20) - setPvDesc("robotGovActive",0) -class EMBLRobot: +def setWorkposThread(init, junk): + logger.info("setting work pos in thread") + setPvDesc("robotGovActive", 1) + setPvDesc("robotXWorkPos", getPvDesc("robotXMountPos")) + setPvDesc("robotYWorkPos", getPvDesc("robotYMountPos")) + setPvDesc("robotZWorkPos", getPvDesc("robotZMountPos")) + setPvDesc("robotOmegaWorkPos", 90.0) + if init: + time.sleep(20) + setPvDesc("robotGovActive", 0) +class EMBLRobot: + def __init__(self): self.workposThread = None - def control_type(self): return "DIRECT" def finish(self): - if (getBlConfig('robot_online')): - try: - RobotControlLib.runCmd("finish") - return MOUNT_SUCCESSFUL - except Exception as e: - e_s = str(e) - message = "ROBOT Finish ERROR: " + e_s - daq_lib.gui_message(message) - logger.error(message) - return MOUNT_FAILURE - - def warmupGripperRecoverThread(self, savedThreshold,junk): - time.sleep(120.0) - setPvDesc("warmupThreshold",savedThreshold) + if getBlConfig("robot_online"): + try: + RobotControlLib.runCmd("finish") + return MOUNT_SUCCESSFUL + except Exception as e: + e_s = str(e) + message = "ROBOT Finish ERROR: " + e_s + daq_lib.gui_message(message) + logger.error(message) + return MOUNT_FAILURE + def warmupGripperRecoverThread(self, savedThreshold, junk): + time.sleep(120.0) + setPvDesc("warmupThreshold", savedThreshold) def recoverRobot(self): - try: - self.rebootEMBL() - time.sleep(8.0) - _,bLoaded,_ = RobotControlLib.recover() - if bLoaded: - daq_macros.robotOff() - daq_macros.disableMount() - daq_lib.gui_message("Found a sample in the gripper - CALL STAFF! disableMount() executed.") - else: - RobotControlLib.runCmd("goHome") - except Exception as e: - e_s = str(e) - daq_lib.gui_message("ROBOT Recover failed! " + e_s) - + try: + self.rebootEMBL() + time.sleep(8.0) + _, bLoaded, _ = RobotControlLib.recover() + if bLoaded: + daq_macros.robotOff() + daq_macros.disableMount() + daq_lib.gui_message( + "Found a sample in the gripper - CALL STAFF! disableMount() executed." + ) + else: + RobotControlLib.runCmd("goHome") + except Exception as e: + e_s = str(e) + daq_lib.gui_message("ROBOT Recover failed! " + e_s) def dryGripper(self): - try: - saveThreshold = getPvDesc("warmupThresholdRBV") - setPvDesc("warmupThreshold",50) - _thread.start_new_thread(self.warmupGripperRecoverThread,(saveThreshold,0)) - self.warmupGripperForDry() - except Exception as e: - e_s = str(e) - daq_lib.gui_message("Dry gripper failed! " + e_s) - setPvDesc("warmupThreshold",saveThreshold) + try: + saveThreshold = getPvDesc("warmupThresholdRBV") + setPvDesc("warmupThreshold", 50) + _thread.start_new_thread( + self.warmupGripperRecoverThread, (saveThreshold, 0) + ) + self.warmupGripperForDry() + except Exception as e: + e_s = str(e) + daq_lib.gui_message("Dry gripper failed! " + e_s) + setPvDesc("warmupThreshold", saveThreshold) def DewarAutoFillOn(self): - RobotControlLib.runCmd("turnOnAutoFill") + RobotControlLib.runCmd("turnOnAutoFill") def DewarAutoFillOff(self): - RobotControlLib.runCmd("turnOffAutoFill") + RobotControlLib.runCmd("turnOffAutoFill") def DewarHeaterOn(self): - RobotControlLib.runCmd("dewarHeaterOn") + RobotControlLib.runCmd("dewarHeaterOn") def DewarHeaterOff(self): - RobotControlLib.runCmd("dewarHeaterOff") + RobotControlLib.runCmd("dewarHeaterOff") - def warmupGripper(self): - try: - RobotControlLib.runCmd("warmupGripper") - daq_lib.mountCounter = 0 - except: - daq_lib.gui_message("ROBOT warmup failed!") + try: + RobotControlLib.runCmd("warmupGripper") + daq_lib.mountCounter = 0 + except: + daq_lib.gui_message("ROBOT warmup failed!") def warmupGripperForDry(self): RobotControlLib.runCmd("warmupGripper") daq_lib.mountCounter = 0 - - def enableDewarTscreen(self): - RobotControlLib.runCmd("enableTScreen") + RobotControlLib.runCmd("enableTScreen") def openPort(self, portNo): - RobotControlLib.openPort(int(portNo)) + RobotControlLib.openPort(int(portNo)) def closePorts(self): - RobotControlLib.runCmd("closePorts") + RobotControlLib.runCmd("closePorts") def rebootEMBL(self): - try: - RobotControlLib.rebootEMBL() - except Exception as e: - exc_type, exc_value, exc_tb = sys.exc_info() - if exc_type == epics.ca.ChannelAccessGetFailure and str(exc_value) == "Get failed; status code: 192": - logger.info('channel access failure detected but error 192 is expected, so continuing') - else: - # channel access exception with error 192 seems "normal". only raise for other exceptions - logger.error('rebootEMBL exception: %s' % traceback.format_exception(exc_type, exc_value, exc_tb)) - raise(e) - + try: + RobotControlLib.rebootEMBL() + except Exception as e: + exc_type, exc_value, exc_tb = sys.exc_info() + if ( + exc_type == epics.ca.ChannelAccessGetFailure + and str(exc_value) == "Get failed; status code: 192" + ): + logger.info( + "channel access failure detected but error 192 is expected, so continuing" + ) + else: + # channel access exception with error 192 seems "normal". only raise for other exceptions + logger.error( + "rebootEMBL exception: %s" + % traceback.format_exception(exc_type, exc_value, exc_tb) + ) + raise (e) def cooldownGripper(self): - try: - RobotControlLib.runCmd("cooldownGripper") - except: - daq_lib.gui_message("ROBOT cooldown failed!") - + try: + RobotControlLib.runCmd("cooldownGripper") + except: + daq_lib.gui_message("ROBOT cooldown failed!") def parkGripper(self): - try: - RobotControlLib.runCmd("park") - except Exception as e: - e_s = str(e) - message = "Park gripper Failed!: " + e_s - daq_lib.gui_message(message) - logger.error(message) - + try: + RobotControlLib.runCmd("park") + except Exception as e: + e_s = str(e) + message = "Park gripper Failed!: " + e_s + daq_lib.gui_message(message) + logger.error(message) def testRobot(self): - try: - RobotControlLib.testRobot() - logger.info("Test Robot passed!") - daq_lib.gui_message("Test Robot passed!") - except Exception as e: - e_s = str(e) - message = "Test Robot failed!: " + e_s - daq_lib.gui_message(message) - logger.error(message) - + try: + RobotControlLib.testRobot() + logger.info("Test Robot passed!") + daq_lib.gui_message("Test Robot passed!") + except Exception as e: + e_s = str(e) + message = "Test Robot failed!: " + e_s + daq_lib.gui_message(message) + logger.error(message) def multiSampleGripper(self): - return False + return False def openGripper(self): - RobotControlLib.openGripper() - + RobotControlLib.openGripper() def closeGripper(self): - RobotControlLib.closeGripper() - + RobotControlLib.closeGripper() # pin alignment, then dewar alignment done here def preMount(self, gov_robot, puckPos, pinPos, sampID, **kwargs): - init = kwargs.get("init", 0) - if (getBlConfig('robot_online')): - desired_gov_state = 'SE' - if kwargs.get('govStatus', None): - gov_lib.waitGov(kwargs['govStatus']) - if not kwargs.get('govStatus', None) or not kwargs['govStatus'].success: # TODO check that we are at desired_gov_state - gov_return = gov_lib.setGovRobot(gov_robot, desired_gov_state) - if not gov_return.success: - logger.error(f'Did not reach {desired_gov_state}') - return MOUNT_FAILURE, kwargs - if (getBlConfig(TOP_VIEW_CHECK) == 1): - try: - if (daq_utils.beamline == "fmx"): - self.workposThread = Thread(target=setWorkposThread,args=(init,0)) - self.workposThread.start() - - sample = db_lib.getSampleByID(sampID) - sampName = sample['name'] - reqCount = sample['request_count'] - prefix1 = sampName + "_" + str(puckPos) + "_" + str(pinPos) + "_" + str(reqCount) + "_PA_0" - prefix90 = sampName + "_" + str(puckPos) + "_" + str(pinPos) + "_" + str(reqCount) + "_PA_90" - kwargs['prefix1'] = prefix1 - kwargs['prefix90'] = prefix90 - top_view.topViewSnap(prefix1,getBlConfig("visitDirectory")+"/pinAlign",1,acquire=0) - except Exception as e: - e_s = str(e) - message = "TopView check ERROR, will continue: " + e_s - daq_lib.gui_message(message) - logger.error(message) - logger.info("mounting " + str(puckPos) + " " + str(pinPos) + " " + str(sampID)) - platePos = int(puckPos/3) - rotMotTarget = daq_utils.dewarPlateMap[platePos][0] - rotCP = beamline_lib.motorPosFromDescriptor("dewarRot") - logger.info("dewar target,CP") - logger.info("%s %s" % (rotMotTarget,rotCP)) - if (abs(rotMotTarget-rotCP)>0.01): - logger.info("rot dewar") - try: - if (init == 0): - RobotControlLib.runCmd("park") - except Exception as e: - e_s = str(e) - message = "ROBOT Park ERROR: " + e_s - daq_lib.gui_message(message) - logger.error(message) - return MOUNT_FAILURE, kwargs - beamline_lib.mvaDescriptor("dewarRot",rotMotTarget) - return MOUNT_STEP_SUCCESSFUL, kwargs - + init = kwargs.get("init", 0) + if getBlConfig("robot_online"): + desired_gov_state = "SE" + if kwargs.get("govStatus", None): + gov_lib.waitGov(kwargs["govStatus"]) + if ( + not kwargs.get("govStatus", None) or not kwargs["govStatus"].success + ): # TODO check that we are at desired_gov_state + gov_return = gov_lib.setGovRobot(gov_robot, desired_gov_state) + if not gov_return.success: + logger.error(f"Did not reach {desired_gov_state}") + return MOUNT_FAILURE, kwargs + if getBlConfig(TOP_VIEW_CHECK) == 1: + try: + if daq_utils.beamline == "fmx": + self.workposThread = Thread( + target=setWorkposThread, args=(init, 0) + ) + self.workposThread.start() + + sample = db_lib.getSampleByID(sampID) + sampName = sample["name"] + reqCount = sample["request_count"] + prefix1 = ( + sampName + + "_" + + str(puckPos) + + "_" + + str(pinPos) + + "_" + + str(reqCount) + + "_PA_0" + ) + prefix90 = ( + sampName + + "_" + + str(puckPos) + + "_" + + str(pinPos) + + "_" + + str(reqCount) + + "_PA_90" + ) + kwargs["prefix1"] = prefix1 + kwargs["prefix90"] = prefix90 + top_view.topViewSnap( + prefix1, + getBlConfig("visitDirectory") + "/pinAlign", + 1, + acquire=0, + ) + except Exception as e: + e_s = str(e) + message = "TopView check ERROR, will continue: " + e_s + daq_lib.gui_message(message) + logger.error(message) + logger.info( + "mounting " + str(puckPos) + " " + str(pinPos) + " " + str(sampID) + ) + platePos = int(puckPos / 3) + rotMotTarget = daq_utils.dewarPlateMap[platePos][0] + rotCP = beamline_lib.motorPosFromDescriptor("dewarRot") + logger.info("dewar target,CP") + logger.info("%s %s" % (rotMotTarget, rotCP)) + if abs(rotMotTarget - rotCP) > 0.01: + logger.info("rot dewar") + try: + if init == 0: + RobotControlLib.runCmd("park") + except Exception as e: + e_s = str(e) + message = "ROBOT Park ERROR: " + e_s + daq_lib.gui_message(message) + logger.error(message) + return MOUNT_FAILURE, kwargs + beamline_lib.mvaDescriptor("dewarRot", rotMotTarget) + return MOUNT_STEP_SUCCESSFUL, kwargs def callAlignPinThread(self, gov_robot, **kwargs): - if (getBlConfig(TOP_VIEW_CHECK) == 1): - prefix1 = kwargs['prefix1'] - prefix90 = kwargs['prefix90'] - omegaCP = beamline_lib.motorPosFromDescriptor("omega") - if (omegaCP > 89.5 and omegaCP < 90.5): - beamline_lib.mvrDescriptor("omega", 85.0) - logger.info("calling thread") - _thread.start_new_thread(top_view.wait90TopviewThread,(gov_robot, prefix1,prefix90)) - logger.info("called thread") - - - def mount(self, gov_robot, puckPos,pinPos,sampID,**kwargs): - global retryMountCount - init = kwargs.get("init", 0) - warmup = kwargs.get("warmup", 0) - - absPos = (PINS_PER_PUCK*(puckPos%3))+pinPos+1 - logger.info("absPos = " + str(absPos)) - if getBlConfig('robot_online'): - try: - if (init): - setPvDesc("boostSelect",0) - if (getPvDesc("sampleDetected") == 0): #reverse logic, 0 = true - setPvDesc("boostSelect",1) - else: - robotStatus = beamline_support.get_any_epics_pv(f"{EMBL_SERVER_PV_BASE.get(daq_utils.beamline, 'SW')}:RobotState","VAL") - if (robotStatus != "Ready"): - gov_status = gov_lib.setGovRobot(gov_robot, 'SE') - if not gov_status.success: - return MOUNT_FAILURE - self.callAlignPinThread(gov_robot, **kwargs) - setPvDesc("boostSelect",0) - if (getPvDesc("gripTemp")>-170): - try: - RobotControlLib.mount(absPos) - except Exception as e: + if getBlConfig(TOP_VIEW_CHECK) == 1: + prefix1 = kwargs["prefix1"] + prefix90 = kwargs["prefix90"] + omegaCP = beamline_lib.motorPosFromDescriptor("omega") + if omegaCP > 89.5 and omegaCP < 90.5: + beamline_lib.mvrDescriptor("omega", 85.0) + logger.info("calling thread") + _thread.start_new_thread( + top_view.wait90TopviewThread, (gov_robot, prefix1, prefix90) + ) + logger.info("called thread") + + def mount(self, gov_robot, puckPos, pinPos, sampID, **kwargs): + global retryMountCount + init = kwargs.get("init", 0) + warmup = kwargs.get("warmup", 0) + + absPos = (PINS_PER_PUCK * (puckPos % 3)) + pinPos + 1 + logger.info("absPos = " + str(absPos)) + if getBlConfig("robot_online"): + try: + if init: + setPvDesc("boostSelect", 0) + if getPvDesc("sampleDetected") == 0: # reverse logic, 0 = true + setPvDesc("boostSelect", 1) + else: + robotStatus = beamline_support.get_any_epics_pv( + f"{EMBL_SERVER_PV_BASE.get(daq_utils.beamline, 'SW')}:RobotState", + "VAL", + ) + if robotStatus != "Ready": + gov_status = gov_lib.setGovRobot(gov_robot, "SE") + if not gov_status.success: + return MOUNT_FAILURE + self.callAlignPinThread(gov_robot, **kwargs) + setPvDesc("boostSelect", 0) + if getPvDesc("gripTemp") > -170: + try: + RobotControlLib.mount(absPos) + except Exception as e: + e_s = str(e) + message = "ROBOT mount ERROR: " + e_s + daq_lib.gui_message(message) + logger.error(message) + return MOUNT_FAILURE + else: + time.sleep(0.5) + if getPvDesc("sampleDetected") == 0: + logger.info("full mount") + RobotControlLib.mount(absPos) + else: + RobotControlLib.initialize() + RobotControlLib._mount(absPos) + setPvDesc("boostSelect", 1) + else: + self.callAlignPinThread(gov_robot, **kwargs) + if warmup: + RobotControlLib._mount(absPos, warmup=True) + else: + RobotControlLib._mount(absPos) + except Exception as e: + # the following errors in the exception are from RobotControlMerge + logger.error(e) e_s = str(e) - message = "ROBOT mount ERROR: " + e_s - daq_lib.gui_message(message) - logger.error(message) + if e_s.find("Fatal") != -1: + if self.isSampleDetected(e_s): + return MOUNT_STEP_SUCCESSFUL + else: + daq_macros.robotOff() + daq_macros.disableMount() + daq_lib.gui_message( + e_s + + ". FATAL ROBOT ERROR - CALL STAFF! robotOff() executed." + ) + return MOUNT_FAILURE + if ( + e_s.find("tilted") != -1 + or e_s.find("Load Sample Failed") != -1 + or e_s.find("Fail to calculate Pin Position") != -1 + ): + if getBlConfig("queueCollect") == 0: + daq_lib.gui_message(e_s + ". Try mounting again") + return MOUNT_FAILURE + else: + if retryMountCount == 0: + retryMountCount += 1 + if e_s.find("Fail to calculate Pin Position") != -1: + # This error happens when the dewar has not rotated to the correct position + # If it happens, try running the premount again + logger.info("Trying premount") + self.preMount( + gov_robot, puckPos, pinPos, sampID, init=1 + ) + mountStat = self.mount( + gov_robot, puckPos, pinPos, sampID, **kwargs + ) + if mountStat == MOUNT_STEP_SUCCESSFUL: + retryMountCount = 0 + return mountStat + else: + retryMountCount = 0 + daq_lib.gui_message("ROBOT: Could not recover from " + e_s) + return MOUNT_UNRECOVERABLE_ERROR + daq_lib.gui_message("ROBOT mount ERROR: " + e_s) return MOUNT_FAILURE - else: - time.sleep(0.5) - if (getPvDesc("sampleDetected") == 0): - logger.info("full mount") - RobotControlLib.mount(absPos) - else: - RobotControlLib.initialize() - RobotControlLib._mount(absPos) - setPvDesc("boostSelect",1) - else: - self.callAlignPinThread(gov_robot, **kwargs) - if (warmup): - RobotControlLib._mount(absPos,warmup=True) - else: - RobotControlLib._mount(absPos) - except Exception as e: - # the following errors in the exception are from RobotControlMerge - logger.error(e) - e_s = str(e) - if (e_s.find("Fatal") != -1): - if self.checkIcedPin(e_s): - return MOUNT_STEP_SUCCESSFUL - else: - daq_macros.robotOff() - daq_macros.disableMount() - daq_lib.gui_message(e_s + ". FATAL ROBOT ERROR - CALL STAFF! robotOff() executed.") - return MOUNT_FAILURE - if (e_s.find("tilted") != -1 or e_s.find("Load Sample Failed") != -1 or e_s.find("Fail to calculate Pin Position") != -1): - if (getBlConfig("queueCollect") == 0): - daq_lib.gui_message(e_s + ". Try mounting again") - return MOUNT_FAILURE - else: - if (retryMountCount == 0): - retryMountCount+=1 - if e_s.find("Fail to calculate Pin Position") != -1: - # This error happens when the dewar has not rotated to the correct position - # If it happens, try running the premount again - logger.info('Trying premount') - self.preMount(gov_robot, puckPos, pinPos, sampID, init=1) - mountStat = self.mount(gov_robot, puckPos,pinPos,sampID, **kwargs) - if (mountStat == MOUNT_STEP_SUCCESSFUL): - retryMountCount = 0 - return mountStat - else: - retryMountCount = 0 - daq_lib.gui_message("ROBOT: Could not recover from " + e_s) - return MOUNT_UNRECOVERABLE_ERROR - daq_lib.gui_message("ROBOT mount ERROR: " + e_s) - return MOUNT_FAILURE - return MOUNT_STEP_SUCCESSFUL - - def checkIcedPin(self, error_string, max_wait_time=60): - """Sometimes after mount, the pin is not detected on the gonio because - there is a buildup of ice between the pin and gonio - This function checks for that error, and if it is detected will check for - the pin every second for max_wait_time seconds. - If after that time it still does not detect the sample it will throw an error - """ - - if (error_string.find("Pin lost during mount transaction") != -1): - logger.info(f"Pin probably has ice, waiting for {max_wait_time} seconds") - wait_time = 0 - while wait_time < max_wait_time: - wait_time += 1 - time.sleep(1) - if getPvDesc("sampleDetected") == 0: - # Sample is detected - return True - return False - + return MOUNT_STEP_SUCCESSFUL + + def isSampleDetected(self, error_string, max_wait_time=60): + """Sometimes after mount, the pin is not detected on the gonio because + there is a buildup of ice between the pin and gonio + This function checks for that error, and if it is detected will check for + the pin every second for max_wait_time seconds. + If after that time it still does not detect the sample it will throw an error + """ + + if error_string.find("Pin lost during mount transaction") != -1: + logger.info(f"Pin probably has ice, waiting for {max_wait_time} seconds") + wait_time = 0 + while wait_time < max_wait_time: + wait_time += 1 + time.sleep(1) + if getPvDesc("sampleDetected") == 0: + # Sample is detected + return True + return False + def postMount(self, gov_robot, puck, pinPos, sampID): - sampYadjust = float(getBlConfig('sampYAdjust')) - if getBlConfig('robot_online'): - if (getBlConfig(TOP_VIEW_CHECK) == 1): - if daq_utils.beamline == "fmx": - try: #make sure workposThread is finished before proceeding to robotGovActive check - timeout = 20 - start_time = time.time() - while self.workposThread.isAlive(): - time.sleep(0.5) - if time.time() - start_time > timeout: - raise Exception(f'setWorkposThread failed to finish before {timeout}s timeout') - logger.info(f'Time waiting for workposThread: {time.time() - start_time}s') + sampYadjust = float(getBlConfig("sampYAdjust")) + if getBlConfig("robot_online"): + if getBlConfig(TOP_VIEW_CHECK) == 1: + if daq_utils.beamline == "fmx": + try: # make sure workposThread is finished before proceeding to robotGovActive check + timeout = 20 + start_time = time.time() + while self.workposThread.isAlive(): + time.sleep(0.5) + if time.time() - start_time > timeout: + raise Exception( + f"setWorkposThread failed to finish before {timeout}s timeout" + ) + logger.info( + f"Time waiting for workposThread: {time.time() - start_time}s" + ) + except Exception as e: + daq_lib.gui_message(e) + logger.error(e) + return MOUNT_FAILURE + if ( + getPvDesc("robotGovActive") == 0 + ): # HACK, if FMX and top view, if stuck in robot inactive + # (due to setWorkposThread), + logger.info( + "FMX, top view active, and robot stuck in inactive - restoring to active" + ) + setPvDesc("robotGovActive", 1) # set it active + else: + logger.info("not changing anything as governor is active") + if sampYadjust == 0: + logger.info("Cannot align pin - Mount next sample.") + gov_status = gov_lib.setGovRobot(gov_robot, "SA") + if not gov_status.success: + logger.error("Failure during governor change to SA") + return MOUNT_SUCCESSFUL + + def preUnmount( + self, gov_robot, puckPos, pinPos, sampID + ): # will somehow know where it came from + absPos = (PINS_PER_PUCK * (puckPos % 3)) + pinPos + 1 + robotOnline = getBlConfig("robot_online") + logger.info("robot online = " + str(robotOnline)) + if robotOnline: + detDist = beamline_lib.motorPosFromDescriptor("detectorDist") + if detDist < DETECTOR_SAFE_DISTANCE[daq_utils.beamline]: + gov_lib.set_detz_out( + gov_robot, DETECTOR_SAFE_DISTANCE[daq_utils.beamline] + ) + if daq_utils.beamline == "fmx": + beamline_lib.mvaDescriptor("omega", 0) + daq_lib.setRobotGovState("SE") + logger.info( + "unmounting " + str(puckPos) + " " + str(pinPos) + " " + str(sampID) + ) + logger.info("absPos = " + str(absPos)) + platePos = int(puckPos / 3) + rotMotTarget = daq_utils.dewarPlateMap[platePos][0] + rotCP = beamline_lib.motorPosFromDescriptor("dewarRot") + logger.info("dewar target,CP") + logger.info("%s %s" % (rotMotTarget, rotCP)) + if abs(rotMotTarget - rotCP) > 1: + logger.info("rot dewar") + try: + RobotControlLib.runCmd("park") + except Exception as e: + e_s = str(e) + message = "ROBOT park ERROR: " + e_s + daq_lib.gui_message(message) + logger.error(message) + return UNMOUNT_FAILURE + beamline_lib.mvaDescriptor("dewarRot", rotMotTarget) + try: + par_init = ( + beamline_support.get_any_epics_pv("SW:RobotState", "VAL") != "Ready" + ) + par_cool = getPvDesc("gripTemp") > -170 + RobotControlLib.unmount1(init=par_init, cooldown=par_cool) except Exception as e: - daq_lib.gui_message(e) - logger.error(e) - return MOUNT_FAILURE - if getPvDesc('robotGovActive') == 0: #HACK, if FMX and top view, if stuck in robot inactive - #(due to setWorkposThread), - logger.info('FMX, top view active, and robot stuck in inactive - restoring to active') - setPvDesc('robotGovActive', 1) #set it active - else: - logger.info('not changing anything as governor is active') - if (sampYadjust == 0): - logger.info("Cannot align pin - Mount next sample.") - gov_status = gov_lib.setGovRobot(gov_robot, 'SA') - if not gov_status.success: - logger.error('Failure during governor change to SA') - return MOUNT_SUCCESSFUL - - - def preUnmount(self, gov_robot, puckPos,pinPos,sampID): #will somehow know where it came from - absPos = (PINS_PER_PUCK*(puckPos%3))+pinPos+1 - robotOnline = getBlConfig('robot_online') - logger.info("robot online = " + str(robotOnline)) - if (robotOnline): - detDist = beamline_lib.motorPosFromDescriptor("detectorDist") - if (detDist1): - logger.info("rot dewar") - try: - RobotControlLib.runCmd("park") - except Exception as e: - e_s = str(e) - message = "ROBOT park ERROR: " + e_s - daq_lib.gui_message(message) - logger.error(message) - return UNMOUNT_FAILURE - beamline_lib.mvaDescriptor("dewarRot",rotMotTarget) - try: - par_init=(beamline_support.get_any_epics_pv("SW:RobotState","VAL")!="Ready") - par_cool=(getPvDesc("gripTemp")>-170) - RobotControlLib.unmount1(init=par_init,cooldown=par_cool) - except Exception as e: - e_s = str(e) - message = "ROBOT unmount ERROR: " + e_s - daq_lib.gui_message(message) - logger.error(message) - return UNMOUNT_FAILURE - detDist = beamline_lib.motorPosFromDescriptor("detectorDist") - if (detDist Date: Tue, 16 Apr 2024 10:38:14 -0400 Subject: [PATCH 3/5] Fixed log message for max_wait_time --- embl_robot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embl_robot.py b/embl_robot.py index 3903eaa6..e469982f 100644 --- a/embl_robot.py +++ b/embl_robot.py @@ -394,7 +394,7 @@ def isSampleDetected(self, error_string, max_wait_time=60): """ if error_string.find("Pin lost during mount transaction") != -1: - logger.info(f"Pin probably has ice, waiting for {max_wait_time} seconds") + logger.info(f"Pin probably has ice, waiting for {max_wait_time+1} seconds") wait_time = 0 while wait_time < max_wait_time: wait_time += 1 From eaec9032c30d764bf94eec781742c1440c11473e Mon Sep 17 00:00:00 2001 From: Shekar V Date: Tue, 16 Apr 2024 13:56:46 -0400 Subject: [PATCH 4/5] Undid formatting --- embl_robot.py | 825 +++++++++++++++++++++++--------------------------- 1 file changed, 372 insertions(+), 453 deletions(-) diff --git a/embl_robot.py b/embl_robot.py index e469982f..78486af7 100644 --- a/embl_robot.py +++ b/embl_robot.py @@ -1,529 +1,448 @@ -import _thread -import logging +import RobotControlLib +import daq_utils +import db_lib +from daq_utils import getBlConfig, setBlConfig +import daq_lib +import beamline_lib +import time +import daq_macros +import beamline_support +from beamline_support import getPvValFromDescriptor as getPvDesc, setPvValFromDescriptor as setPvDesc import os import sys -import time import traceback +import _thread from threading import Thread - +import logging import epics.ca -import RobotControlLib - -import beamline_lib -import beamline_support -import daq_lib -import daq_macros -import daq_utils -import db_lib -import gov_lib import top_view -from beamline_support import getPvValFromDescriptor as getPvDesc -from beamline_support import setPvValFromDescriptor as setPvDesc -from config_params import ( - DETECTOR_SAFE_DISTANCE, - EMBL_SERVER_PV_BASE, - MOUNT_FAILURE, - MOUNT_STEP_SUCCESSFUL, - MOUNT_SUCCESSFUL, - MOUNT_UNRECOVERABLE_ERROR, - PINS_PER_PUCK, - TOP_VIEW_CHECK, - UNMOUNT_FAILURE, - UNMOUNT_STEP_SUCCESSFUL, - UNMOUNT_SUCCESSFUL, -) -from daq_utils import getBlConfig, setBlConfig - -# from start_bs import gov_human, gov_robot +from config_params import TOP_VIEW_CHECK, DETECTOR_SAFE_DISTANCE, MOUNT_SUCCESSFUL, MOUNT_FAILURE,\ + MOUNT_UNRECOVERABLE_ERROR, MOUNT_STEP_SUCCESSFUL, UNMOUNT_SUCCESSFUL,\ + UNMOUNT_FAILURE, UNMOUNT_STEP_SUCCESSFUL, PINS_PER_PUCK, EMBL_SERVER_PV_BASE +import gov_lib +#from start_bs import gov_human, gov_robot logger = logging.getLogger(__name__) global retryMountCount retryMountCount = 0 -setBlConfig("sampYAdjust", 0) - - -def setWorkposThread(init, junk): - logger.info("setting work pos in thread") - setPvDesc("robotGovActive", 1) - setPvDesc("robotXWorkPos", getPvDesc("robotXMountPos")) - setPvDesc("robotYWorkPos", getPvDesc("robotYMountPos")) - setPvDesc("robotZWorkPos", getPvDesc("robotZMountPos")) - setPvDesc("robotOmegaWorkPos", 90.0) - if init: - time.sleep(20) - setPvDesc("robotGovActive", 0) +setBlConfig('sampYAdjust', 0) +def setWorkposThread(init,junk): + logger.info("setting work pos in thread") + setPvDesc("robotGovActive",1) + setPvDesc("robotXWorkPos",getPvDesc("robotXMountPos")) + setPvDesc("robotYWorkPos",getPvDesc("robotYMountPos")) + setPvDesc("robotZWorkPos",getPvDesc("robotZMountPos")) + setPvDesc("robotOmegaWorkPos",90.0) + if (init): + time.sleep(20) + setPvDesc("robotGovActive",0) class EMBLRobot: + def __init__(self): self.workposThread = None + def control_type(self): return "DIRECT" def finish(self): - if getBlConfig("robot_online"): - try: - RobotControlLib.runCmd("finish") - return MOUNT_SUCCESSFUL - except Exception as e: - e_s = str(e) - message = "ROBOT Finish ERROR: " + e_s - daq_lib.gui_message(message) - logger.error(message) - return MOUNT_FAILURE + if (getBlConfig('robot_online')): + try: + RobotControlLib.runCmd("finish") + return MOUNT_SUCCESSFUL + except Exception as e: + e_s = str(e) + message = "ROBOT Finish ERROR: " + e_s + daq_lib.gui_message(message) + logger.error(message) + return MOUNT_FAILURE + + def warmupGripperRecoverThread(self, savedThreshold,junk): + time.sleep(120.0) + setPvDesc("warmupThreshold",savedThreshold) - def warmupGripperRecoverThread(self, savedThreshold, junk): - time.sleep(120.0) - setPvDesc("warmupThreshold", savedThreshold) def recoverRobot(self): - try: - self.rebootEMBL() - time.sleep(8.0) - _, bLoaded, _ = RobotControlLib.recover() - if bLoaded: - daq_macros.robotOff() - daq_macros.disableMount() - daq_lib.gui_message( - "Found a sample in the gripper - CALL STAFF! disableMount() executed." - ) - else: - RobotControlLib.runCmd("goHome") - except Exception as e: - e_s = str(e) - daq_lib.gui_message("ROBOT Recover failed! " + e_s) + try: + self.rebootEMBL() + time.sleep(8.0) + _,bLoaded,_ = RobotControlLib.recover() + if bLoaded: + daq_macros.robotOff() + daq_macros.disableMount() + daq_lib.gui_message("Found a sample in the gripper - CALL STAFF! disableMount() executed.") + else: + RobotControlLib.runCmd("goHome") + except Exception as e: + e_s = str(e) + daq_lib.gui_message("ROBOT Recover failed! " + e_s) + def dryGripper(self): - try: - saveThreshold = getPvDesc("warmupThresholdRBV") - setPvDesc("warmupThreshold", 50) - _thread.start_new_thread( - self.warmupGripperRecoverThread, (saveThreshold, 0) - ) - self.warmupGripperForDry() - except Exception as e: - e_s = str(e) - daq_lib.gui_message("Dry gripper failed! " + e_s) - setPvDesc("warmupThreshold", saveThreshold) + try: + saveThreshold = getPvDesc("warmupThresholdRBV") + setPvDesc("warmupThreshold",50) + _thread.start_new_thread(self.warmupGripperRecoverThread,(saveThreshold,0)) + self.warmupGripperForDry() + except Exception as e: + e_s = str(e) + daq_lib.gui_message("Dry gripper failed! " + e_s) + setPvDesc("warmupThreshold",saveThreshold) def DewarAutoFillOn(self): - RobotControlLib.runCmd("turnOnAutoFill") + RobotControlLib.runCmd("turnOnAutoFill") def DewarAutoFillOff(self): - RobotControlLib.runCmd("turnOffAutoFill") + RobotControlLib.runCmd("turnOffAutoFill") def DewarHeaterOn(self): - RobotControlLib.runCmd("dewarHeaterOn") + RobotControlLib.runCmd("dewarHeaterOn") def DewarHeaterOff(self): - RobotControlLib.runCmd("dewarHeaterOff") + RobotControlLib.runCmd("dewarHeaterOff") + def warmupGripper(self): - try: - RobotControlLib.runCmd("warmupGripper") - daq_lib.mountCounter = 0 - except: - daq_lib.gui_message("ROBOT warmup failed!") + try: + RobotControlLib.runCmd("warmupGripper") + daq_lib.mountCounter = 0 + except: + daq_lib.gui_message("ROBOT warmup failed!") def warmupGripperForDry(self): RobotControlLib.runCmd("warmupGripper") daq_lib.mountCounter = 0 + + def enableDewarTscreen(self): - RobotControlLib.runCmd("enableTScreen") + RobotControlLib.runCmd("enableTScreen") def openPort(self, portNo): - RobotControlLib.openPort(int(portNo)) + RobotControlLib.openPort(int(portNo)) def closePorts(self): - RobotControlLib.runCmd("closePorts") + RobotControlLib.runCmd("closePorts") def rebootEMBL(self): - try: - RobotControlLib.rebootEMBL() - except Exception as e: - exc_type, exc_value, exc_tb = sys.exc_info() - if ( - exc_type == epics.ca.ChannelAccessGetFailure - and str(exc_value) == "Get failed; status code: 192" - ): - logger.info( - "channel access failure detected but error 192 is expected, so continuing" - ) - else: - # channel access exception with error 192 seems "normal". only raise for other exceptions - logger.error( - "rebootEMBL exception: %s" - % traceback.format_exception(exc_type, exc_value, exc_tb) - ) - raise (e) + try: + RobotControlLib.rebootEMBL() + except Exception as e: + exc_type, exc_value, exc_tb = sys.exc_info() + if exc_type == epics.ca.ChannelAccessGetFailure and str(exc_value) == "Get failed; status code: 192": + logger.info('channel access failure detected but error 192 is expected, so continuing') + else: + # channel access exception with error 192 seems "normal". only raise for other exceptions + logger.error('rebootEMBL exception: %s' % traceback.format_exception(exc_type, exc_value, exc_tb)) + raise(e) + def cooldownGripper(self): - try: - RobotControlLib.runCmd("cooldownGripper") - except: - daq_lib.gui_message("ROBOT cooldown failed!") + try: + RobotControlLib.runCmd("cooldownGripper") + except: + daq_lib.gui_message("ROBOT cooldown failed!") + def parkGripper(self): - try: - RobotControlLib.runCmd("park") - except Exception as e: - e_s = str(e) - message = "Park gripper Failed!: " + e_s - daq_lib.gui_message(message) - logger.error(message) + try: + RobotControlLib.runCmd("park") + except Exception as e: + e_s = str(e) + message = "Park gripper Failed!: " + e_s + daq_lib.gui_message(message) + logger.error(message) + def testRobot(self): - try: - RobotControlLib.testRobot() - logger.info("Test Robot passed!") - daq_lib.gui_message("Test Robot passed!") - except Exception as e: - e_s = str(e) - message = "Test Robot failed!: " + e_s - daq_lib.gui_message(message) - logger.error(message) + try: + RobotControlLib.testRobot() + logger.info("Test Robot passed!") + daq_lib.gui_message("Test Robot passed!") + except Exception as e: + e_s = str(e) + message = "Test Robot failed!: " + e_s + daq_lib.gui_message(message) + logger.error(message) + def multiSampleGripper(self): - return False + return False def openGripper(self): - RobotControlLib.openGripper() + RobotControlLib.openGripper() + def closeGripper(self): - RobotControlLib.closeGripper() + RobotControlLib.closeGripper() + # pin alignment, then dewar alignment done here def preMount(self, gov_robot, puckPos, pinPos, sampID, **kwargs): - init = kwargs.get("init", 0) - if getBlConfig("robot_online"): - desired_gov_state = "SE" - if kwargs.get("govStatus", None): - gov_lib.waitGov(kwargs["govStatus"]) - if ( - not kwargs.get("govStatus", None) or not kwargs["govStatus"].success - ): # TODO check that we are at desired_gov_state - gov_return = gov_lib.setGovRobot(gov_robot, desired_gov_state) - if not gov_return.success: - logger.error(f"Did not reach {desired_gov_state}") - return MOUNT_FAILURE, kwargs - if getBlConfig(TOP_VIEW_CHECK) == 1: - try: - if daq_utils.beamline == "fmx": - self.workposThread = Thread( - target=setWorkposThread, args=(init, 0) - ) - self.workposThread.start() - - sample = db_lib.getSampleByID(sampID) - sampName = sample["name"] - reqCount = sample["request_count"] - prefix1 = ( - sampName - + "_" - + str(puckPos) - + "_" - + str(pinPos) - + "_" - + str(reqCount) - + "_PA_0" - ) - prefix90 = ( - sampName - + "_" - + str(puckPos) - + "_" - + str(pinPos) - + "_" - + str(reqCount) - + "_PA_90" - ) - kwargs["prefix1"] = prefix1 - kwargs["prefix90"] = prefix90 - top_view.topViewSnap( - prefix1, - getBlConfig("visitDirectory") + "/pinAlign", - 1, - acquire=0, - ) - except Exception as e: - e_s = str(e) - message = "TopView check ERROR, will continue: " + e_s - daq_lib.gui_message(message) - logger.error(message) - logger.info( - "mounting " + str(puckPos) + " " + str(pinPos) + " " + str(sampID) - ) - platePos = int(puckPos / 3) - rotMotTarget = daq_utils.dewarPlateMap[platePos][0] - rotCP = beamline_lib.motorPosFromDescriptor("dewarRot") - logger.info("dewar target,CP") - logger.info("%s %s" % (rotMotTarget, rotCP)) - if abs(rotMotTarget - rotCP) > 0.01: - logger.info("rot dewar") - try: - if init == 0: - RobotControlLib.runCmd("park") - except Exception as e: - e_s = str(e) - message = "ROBOT Park ERROR: " + e_s - daq_lib.gui_message(message) - logger.error(message) - return MOUNT_FAILURE, kwargs - beamline_lib.mvaDescriptor("dewarRot", rotMotTarget) - return MOUNT_STEP_SUCCESSFUL, kwargs + init = kwargs.get("init", 0) + if (getBlConfig('robot_online')): + desired_gov_state = 'SE' + if kwargs.get('govStatus', None): + gov_lib.waitGov(kwargs['govStatus']) + if not kwargs.get('govStatus', None) or not kwargs['govStatus'].success: # TODO check that we are at desired_gov_state + gov_return = gov_lib.setGovRobot(gov_robot, desired_gov_state) + if not gov_return.success: + logger.error(f'Did not reach {desired_gov_state}') + return MOUNT_FAILURE, kwargs + if (getBlConfig(TOP_VIEW_CHECK) == 1): + try: + if (daq_utils.beamline == "fmx"): + self.workposThread = Thread(target=setWorkposThread,args=(init,0)) + self.workposThread.start() + + sample = db_lib.getSampleByID(sampID) + sampName = sample['name'] + reqCount = sample['request_count'] + prefix1 = sampName + "_" + str(puckPos) + "_" + str(pinPos) + "_" + str(reqCount) + "_PA_0" + prefix90 = sampName + "_" + str(puckPos) + "_" + str(pinPos) + "_" + str(reqCount) + "_PA_90" + kwargs['prefix1'] = prefix1 + kwargs['prefix90'] = prefix90 + top_view.topViewSnap(prefix1,getBlConfig("visitDirectory")+"/pinAlign",1,acquire=0) + except Exception as e: + e_s = str(e) + message = "TopView check ERROR, will continue: " + e_s + daq_lib.gui_message(message) + logger.error(message) + logger.info("mounting " + str(puckPos) + " " + str(pinPos) + " " + str(sampID)) + platePos = int(puckPos/3) + rotMotTarget = daq_utils.dewarPlateMap[platePos][0] + rotCP = beamline_lib.motorPosFromDescriptor("dewarRot") + logger.info("dewar target,CP") + logger.info("%s %s" % (rotMotTarget,rotCP)) + if (abs(rotMotTarget-rotCP)>0.01): + logger.info("rot dewar") + try: + if (init == 0): + RobotControlLib.runCmd("park") + except Exception as e: + e_s = str(e) + message = "ROBOT Park ERROR: " + e_s + daq_lib.gui_message(message) + logger.error(message) + return MOUNT_FAILURE, kwargs + beamline_lib.mvaDescriptor("dewarRot",rotMotTarget) + return MOUNT_STEP_SUCCESSFUL, kwargs + def callAlignPinThread(self, gov_robot, **kwargs): - if getBlConfig(TOP_VIEW_CHECK) == 1: - prefix1 = kwargs["prefix1"] - prefix90 = kwargs["prefix90"] - omegaCP = beamline_lib.motorPosFromDescriptor("omega") - if omegaCP > 89.5 and omegaCP < 90.5: - beamline_lib.mvrDescriptor("omega", 85.0) - logger.info("calling thread") - _thread.start_new_thread( - top_view.wait90TopviewThread, (gov_robot, prefix1, prefix90) - ) - logger.info("called thread") - - def mount(self, gov_robot, puckPos, pinPos, sampID, **kwargs): - global retryMountCount - init = kwargs.get("init", 0) - warmup = kwargs.get("warmup", 0) - - absPos = (PINS_PER_PUCK * (puckPos % 3)) + pinPos + 1 - logger.info("absPos = " + str(absPos)) - if getBlConfig("robot_online"): - try: - if init: - setPvDesc("boostSelect", 0) - if getPvDesc("sampleDetected") == 0: # reverse logic, 0 = true - setPvDesc("boostSelect", 1) - else: - robotStatus = beamline_support.get_any_epics_pv( - f"{EMBL_SERVER_PV_BASE.get(daq_utils.beamline, 'SW')}:RobotState", - "VAL", - ) - if robotStatus != "Ready": - gov_status = gov_lib.setGovRobot(gov_robot, "SE") - if not gov_status.success: - return MOUNT_FAILURE - self.callAlignPinThread(gov_robot, **kwargs) - setPvDesc("boostSelect", 0) - if getPvDesc("gripTemp") > -170: - try: - RobotControlLib.mount(absPos) - except Exception as e: - e_s = str(e) - message = "ROBOT mount ERROR: " + e_s - daq_lib.gui_message(message) - logger.error(message) - return MOUNT_FAILURE - else: - time.sleep(0.5) - if getPvDesc("sampleDetected") == 0: - logger.info("full mount") - RobotControlLib.mount(absPos) - else: - RobotControlLib.initialize() - RobotControlLib._mount(absPos) - setPvDesc("boostSelect", 1) - else: - self.callAlignPinThread(gov_robot, **kwargs) - if warmup: - RobotControlLib._mount(absPos, warmup=True) - else: - RobotControlLib._mount(absPos) - except Exception as e: - # the following errors in the exception are from RobotControlMerge - logger.error(e) + if (getBlConfig(TOP_VIEW_CHECK) == 1): + prefix1 = kwargs['prefix1'] + prefix90 = kwargs['prefix90'] + omegaCP = beamline_lib.motorPosFromDescriptor("omega") + if (omegaCP > 89.5 and omegaCP < 90.5): + beamline_lib.mvrDescriptor("omega", 85.0) + logger.info("calling thread") + _thread.start_new_thread(top_view.wait90TopviewThread,(gov_robot, prefix1,prefix90)) + logger.info("called thread") + + + def mount(self, gov_robot, puckPos,pinPos,sampID,**kwargs): + global retryMountCount + init = kwargs.get("init", 0) + warmup = kwargs.get("warmup", 0) + + absPos = (PINS_PER_PUCK*(puckPos%3))+pinPos+1 + logger.info("absPos = " + str(absPos)) + if getBlConfig('robot_online'): + try: + if (init): + setPvDesc("boostSelect",0) + if (getPvDesc("sampleDetected") == 0): #reverse logic, 0 = true + setPvDesc("boostSelect",1) + else: + robotStatus = beamline_support.get_any_epics_pv(f"{EMBL_SERVER_PV_BASE.get(daq_utils.beamline, 'SW')}:RobotState","VAL") + if (robotStatus != "Ready"): + gov_status = gov_lib.setGovRobot(gov_robot, 'SE') + if not gov_status.success: + return MOUNT_FAILURE + self.callAlignPinThread(gov_robot, **kwargs) + setPvDesc("boostSelect",0) + if (getPvDesc("gripTemp")>-170): + try: + RobotControlLib.mount(absPos) + except Exception as e: e_s = str(e) - if e_s.find("Fatal") != -1: - if self.isSampleDetected(e_s): - return MOUNT_STEP_SUCCESSFUL - else: - daq_macros.robotOff() - daq_macros.disableMount() - daq_lib.gui_message( - e_s - + ". FATAL ROBOT ERROR - CALL STAFF! robotOff() executed." - ) - return MOUNT_FAILURE - if ( - e_s.find("tilted") != -1 - or e_s.find("Load Sample Failed") != -1 - or e_s.find("Fail to calculate Pin Position") != -1 - ): - if getBlConfig("queueCollect") == 0: - daq_lib.gui_message(e_s + ". Try mounting again") - return MOUNT_FAILURE - else: - if retryMountCount == 0: - retryMountCount += 1 - if e_s.find("Fail to calculate Pin Position") != -1: - # This error happens when the dewar has not rotated to the correct position - # If it happens, try running the premount again - logger.info("Trying premount") - self.preMount( - gov_robot, puckPos, pinPos, sampID, init=1 - ) - mountStat = self.mount( - gov_robot, puckPos, pinPos, sampID, **kwargs - ) - if mountStat == MOUNT_STEP_SUCCESSFUL: - retryMountCount = 0 - return mountStat - else: - retryMountCount = 0 - daq_lib.gui_message("ROBOT: Could not recover from " + e_s) - return MOUNT_UNRECOVERABLE_ERROR - daq_lib.gui_message("ROBOT mount ERROR: " + e_s) + message = "ROBOT mount ERROR: " + e_s + daq_lib.gui_message(message) + logger.error(message) return MOUNT_FAILURE - return MOUNT_STEP_SUCCESSFUL + else: + time.sleep(0.5) + if (getPvDesc("sampleDetected") == 0): + logger.info("full mount") + RobotControlLib.mount(absPos) + else: + RobotControlLib.initialize() + RobotControlLib._mount(absPos) + setPvDesc("boostSelect",1) + else: + self.callAlignPinThread(gov_robot, **kwargs) + if (warmup): + RobotControlLib._mount(absPos,warmup=True) + else: + RobotControlLib._mount(absPos) + except Exception as e: + # the following errors in the exception are from RobotControlMerge + logger.error(e) + e_s = str(e) + if (e_s.find("Fatal") != -1): + if self.isSampleDetected(e_s): + return MOUNT_STEP_SUCCESSFUL + else: + daq_macros.robotOff() + daq_macros.disableMount() + daq_lib.gui_message(e_s + ". FATAL ROBOT ERROR - CALL STAFF! robotOff() executed.") + return MOUNT_FAILURE + if (e_s.find("tilted") != -1 or e_s.find("Load Sample Failed") != -1 or e_s.find("Fail to calculate Pin Position") != -1): + if (getBlConfig("queueCollect") == 0): + daq_lib.gui_message(e_s + ". Try mounting again") + return MOUNT_FAILURE + else: + if (retryMountCount == 0): + retryMountCount+=1 + if e_s.find("Fail to calculate Pin Position") != -1: + # This error happens when the dewar has not rotated to the correct position + # If it happens, try running the premount again + logger.info('Trying premount') + self.preMount(gov_robot, puckPos, pinPos, sampID, init=1) + mountStat = self.mount(gov_robot, puckPos,pinPos,sampID, **kwargs) + if (mountStat == MOUNT_STEP_SUCCESSFUL): + retryMountCount = 0 + return mountStat + else: + retryMountCount = 0 + daq_lib.gui_message("ROBOT: Could not recover from " + e_s) + return MOUNT_UNRECOVERABLE_ERROR + daq_lib.gui_message("ROBOT mount ERROR: " + e_s) + return MOUNT_FAILURE + return MOUNT_STEP_SUCCESSFUL def isSampleDetected(self, error_string, max_wait_time=60): - """Sometimes after mount, the pin is not detected on the gonio because - there is a buildup of ice between the pin and gonio - This function checks for that error, and if it is detected will check for - the pin every second for max_wait_time seconds. - If after that time it still does not detect the sample it will throw an error - """ - - if error_string.find("Pin lost during mount transaction") != -1: - logger.info(f"Pin probably has ice, waiting for {max_wait_time+1} seconds") - wait_time = 0 - while wait_time < max_wait_time: - wait_time += 1 - time.sleep(1) - if getPvDesc("sampleDetected") == 0: - # Sample is detected - return True - return False - + """Sometimes after mount, the pin is not detected on the gonio because + there is a buildup of ice between the pin and gonio + This function checks for that error, and if it is detected will check for + the pin every second for max_wait_time seconds. + If after that time it still does not detect the sample it will throw an error + """ + + if (error_string.find("Pin lost during mount transaction") != -1): + logger.info(f"Pin probably has ice, waiting for {max_wait_time + 1} seconds") + wait_time = 0 + while wait_time < max_wait_time: + wait_time += 1 + time.sleep(1) + if getPvDesc("sampleDetected") == 0: + # Sample is detected + return True + return False + def postMount(self, gov_robot, puck, pinPos, sampID): - sampYadjust = float(getBlConfig("sampYAdjust")) - if getBlConfig("robot_online"): - if getBlConfig(TOP_VIEW_CHECK) == 1: - if daq_utils.beamline == "fmx": - try: # make sure workposThread is finished before proceeding to robotGovActive check - timeout = 20 - start_time = time.time() - while self.workposThread.isAlive(): - time.sleep(0.5) - if time.time() - start_time > timeout: - raise Exception( - f"setWorkposThread failed to finish before {timeout}s timeout" - ) - logger.info( - f"Time waiting for workposThread: {time.time() - start_time}s" - ) - except Exception as e: - daq_lib.gui_message(e) - logger.error(e) - return MOUNT_FAILURE - if ( - getPvDesc("robotGovActive") == 0 - ): # HACK, if FMX and top view, if stuck in robot inactive - # (due to setWorkposThread), - logger.info( - "FMX, top view active, and robot stuck in inactive - restoring to active" - ) - setPvDesc("robotGovActive", 1) # set it active - else: - logger.info("not changing anything as governor is active") - if sampYadjust == 0: - logger.info("Cannot align pin - Mount next sample.") - gov_status = gov_lib.setGovRobot(gov_robot, "SA") - if not gov_status.success: - logger.error("Failure during governor change to SA") - return MOUNT_SUCCESSFUL - - def preUnmount( - self, gov_robot, puckPos, pinPos, sampID - ): # will somehow know where it came from - absPos = (PINS_PER_PUCK * (puckPos % 3)) + pinPos + 1 - robotOnline = getBlConfig("robot_online") - logger.info("robot online = " + str(robotOnline)) - if robotOnline: - detDist = beamline_lib.motorPosFromDescriptor("detectorDist") - if detDist < DETECTOR_SAFE_DISTANCE[daq_utils.beamline]: - gov_lib.set_detz_out( - gov_robot, DETECTOR_SAFE_DISTANCE[daq_utils.beamline] - ) - if daq_utils.beamline == "fmx": - beamline_lib.mvaDescriptor("omega", 0) - daq_lib.setRobotGovState("SE") - logger.info( - "unmounting " + str(puckPos) + " " + str(pinPos) + " " + str(sampID) - ) - logger.info("absPos = " + str(absPos)) - platePos = int(puckPos / 3) - rotMotTarget = daq_utils.dewarPlateMap[platePos][0] - rotCP = beamline_lib.motorPosFromDescriptor("dewarRot") - logger.info("dewar target,CP") - logger.info("%s %s" % (rotMotTarget, rotCP)) - if abs(rotMotTarget - rotCP) > 1: - logger.info("rot dewar") - try: - RobotControlLib.runCmd("park") - except Exception as e: - e_s = str(e) - message = "ROBOT park ERROR: " + e_s - daq_lib.gui_message(message) - logger.error(message) - return UNMOUNT_FAILURE - beamline_lib.mvaDescriptor("dewarRot", rotMotTarget) - try: - par_init = ( - beamline_support.get_any_epics_pv("SW:RobotState", "VAL") != "Ready" - ) - par_cool = getPvDesc("gripTemp") > -170 - RobotControlLib.unmount1(init=par_init, cooldown=par_cool) + sampYadjust = float(getBlConfig('sampYAdjust')) + if getBlConfig('robot_online'): + if (getBlConfig(TOP_VIEW_CHECK) == 1): + if daq_utils.beamline == "fmx": + try: #make sure workposThread is finished before proceeding to robotGovActive check + timeout = 20 + start_time = time.time() + while self.workposThread.isAlive(): + time.sleep(0.5) + if time.time() - start_time > timeout: + raise Exception(f'setWorkposThread failed to finish before {timeout}s timeout') + logger.info(f'Time waiting for workposThread: {time.time() - start_time}s') except Exception as e: - e_s = str(e) - message = "ROBOT unmount ERROR: " + e_s - daq_lib.gui_message(message) - logger.error(message) - return UNMOUNT_FAILURE - detDist = beamline_lib.motorPosFromDescriptor("detectorDist") - if detDist < DETECTOR_SAFE_DISTANCE[daq_utils.beamline]: - beamline_lib.mvaDescriptor( - "detectorDist", DETECTOR_SAFE_DISTANCE[daq_utils.beamline] - ) - if beamline_lib.motorPosFromDescriptor("detectorDist") < ( - DETECTOR_SAFE_DISTANCE[daq_utils.beamline] - 1.0 - ): - logger.error( - f"ERROR - Detector < {DETECTOR_SAFE_DISTANCE[daq_utils.beamline]}" - ) - return UNMOUNT_FAILURE - return UNMOUNT_STEP_SUCCESSFUL + daq_lib.gui_message(e) + logger.error(e) + return MOUNT_FAILURE + if getPvDesc('robotGovActive') == 0: #HACK, if FMX and top view, if stuck in robot inactive + #(due to setWorkposThread), + logger.info('FMX, top view active, and robot stuck in inactive - restoring to active') + setPvDesc('robotGovActive', 1) #set it active + else: + logger.info('not changing anything as governor is active') + if (sampYadjust == 0): + logger.info("Cannot align pin - Mount next sample.") + gov_status = gov_lib.setGovRobot(gov_robot, 'SA') + if not gov_status.success: + logger.error('Failure during governor change to SA') + return MOUNT_SUCCESSFUL + + + def preUnmount(self, gov_robot, puckPos,pinPos,sampID): #will somehow know where it came from + absPos = (PINS_PER_PUCK*(puckPos%3))+pinPos+1 + robotOnline = getBlConfig('robot_online') + logger.info("robot online = " + str(robotOnline)) + if (robotOnline): + detDist = beamline_lib.motorPosFromDescriptor("detectorDist") + if (detDist1): + logger.info("rot dewar") + try: + RobotControlLib.runCmd("park") + except Exception as e: + e_s = str(e) + message = "ROBOT park ERROR: " + e_s + daq_lib.gui_message(message) + logger.error(message) + return UNMOUNT_FAILURE + beamline_lib.mvaDescriptor("dewarRot",rotMotTarget) + try: + par_init=(beamline_support.get_any_epics_pv("SW:RobotState","VAL")!="Ready") + par_cool=(getPvDesc("gripTemp")>-170) + RobotControlLib.unmount1(init=par_init,cooldown=par_cool) + except Exception as e: + e_s = str(e) + message = "ROBOT unmount ERROR: " + e_s + daq_lib.gui_message(message) + logger.error(message) + return UNMOUNT_FAILURE + detDist = beamline_lib.motorPosFromDescriptor("detectorDist") + if (detDist Date: Thu, 25 Apr 2024 08:42:58 -0400 Subject: [PATCH 5/5] Removed else block --- embl_robot.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/embl_robot.py b/embl_robot.py index 78486af7..d31214b9 100644 --- a/embl_robot.py +++ b/embl_robot.py @@ -298,11 +298,10 @@ def mount(self, gov_robot, puckPos,pinPos,sampID,**kwargs): if (e_s.find("Fatal") != -1): if self.isSampleDetected(e_s): return MOUNT_STEP_SUCCESSFUL - else: - daq_macros.robotOff() - daq_macros.disableMount() - daq_lib.gui_message(e_s + ". FATAL ROBOT ERROR - CALL STAFF! robotOff() executed.") - return MOUNT_FAILURE + daq_macros.robotOff() + daq_macros.disableMount() + daq_lib.gui_message(e_s + ". FATAL ROBOT ERROR - CALL STAFF! robotOff() executed.") + return MOUNT_FAILURE if (e_s.find("tilted") != -1 or e_s.find("Load Sample Failed") != -1 or e_s.find("Fail to calculate Pin Position") != -1): if (getBlConfig("queueCollect") == 0): daq_lib.gui_message(e_s + ". Try mounting again")