534 lines
17 KiB
Python
534 lines
17 KiB
Python
###################################################################################################
|
|
# Deployment specific global definitions - executed after startup.py
|
|
###################################################################################################
|
|
import traceback
|
|
import requests
|
|
from ch.psi.pshell.serial import TcpDevice
|
|
from ch.psi.pshell.modbus import ModbusTCP
|
|
import ch.psi.mxsc.Controller as Controller
|
|
import ch.psi.pshell.utils.Nameable as Nameable
|
|
import ch.psi.pshell.utils.Chrono as Chrono
|
|
import ch.psi.mxsc.Controller as Controller
|
|
|
|
|
|
|
|
run("setup/Layout")
|
|
run("data/reports")
|
|
|
|
|
|
|
|
###################################################################################################
|
|
# Configuration
|
|
###################################################################################################
|
|
|
|
IMAGING_ENABLED_PREFERENCE = "imaging_enabled"
|
|
PUCK_TYPES_PREFERENCE = "puck_types"
|
|
BARCODE_READER_SCAN_PUCKS = "barcode_reader_scan_pucks"
|
|
ROOM_TEMPERATURE_ENABLED_PREFERENCE = "room_temperature_enabled"
|
|
BEAMLINE_STATUS_ENABLED_PREFERENCE = "beamline_status_enabled"
|
|
VALVE_CONTROL_ENABLED_PREFERENCE = "valve_control"
|
|
SERVICE_MODE_PREFERENCE = "service_mode"
|
|
|
|
|
|
def is_imaging_enabled():
|
|
setting = get_setting(IMAGING_ENABLED_PREFERENCE)
|
|
return not (str(setting).lower() == 'false')
|
|
|
|
def set_imaging_enabled(value):
|
|
set_setting(IMAGING_ENABLED_PREFERENCE, (True if value else False) )
|
|
|
|
def assert_imaging_enabled():
|
|
if is_imaging_enabled() == False:
|
|
raise Exception ("Imaging is disabled")
|
|
|
|
#"unipuck", "minispine" or "mixed"
|
|
def set_puck_types(value):
|
|
set_setting(PUCK_TYPES_PREFERENCE, True if value else False )
|
|
|
|
def get_puck_types():
|
|
setting = get_setting(PUCK_TYPES_PREFERENCE)
|
|
if setting == "unipuck" or setting == "minispine":
|
|
return setting
|
|
return "mixed"
|
|
|
|
|
|
def is_barcode_reader_scan_pucks():
|
|
setting = get_setting(BARCODE_READER_SCAN_PUCKS)
|
|
return False if setting is None else setting.lower() == "true"
|
|
|
|
def set_barcode_reader_scan_pucks(value):
|
|
set_setting(BARCODE_READER_SCAN_PUCKS, True if value else False )
|
|
|
|
def is_valve_controlled():
|
|
setting = get_setting(VALVE_CONTROL_ENABLED_PREFERENCE)
|
|
return False if setting is None else setting.lower() == "true"
|
|
|
|
def set_valve_controlled(value):
|
|
set_setting(VALVE_CONTROL_ENABLED_PREFERENCE, True if value else False )
|
|
|
|
def reset_mounted_sample_position():
|
|
set_setting("mounted_sample_position", None)
|
|
|
|
def is_service_mode():
|
|
setting = get_setting(SERVICE_MODE_PREFERENCE)
|
|
return False if setting is None else setting.lower() == "true"
|
|
|
|
def set_service_mode(value):
|
|
set_setting(SERVICE_MODE_PREFERENCE, True if value else False )
|
|
|
|
|
|
|
|
|
|
|
|
def get_puck_barcode_reader():
|
|
if is_barcode_reader_scan_pucks():
|
|
return barcode_reader
|
|
else:
|
|
return barcode_reader_puck
|
|
|
|
#In order to apply current config
|
|
set_imaging_enabled(is_imaging_enabled())
|
|
set_puck_types(get_puck_types())
|
|
set_barcode_reader_scan_pucks(is_barcode_reader_scan_pucks())
|
|
set_valve_controlled(is_valve_controlled())
|
|
|
|
if Context.getRunCount() == 0:
|
|
set_service_mode(False) #Always start in normal mode
|
|
else:
|
|
set_service_mode(is_service_mode())
|
|
|
|
|
|
force_dry_mount_count = get_setting("force_dry_mount_count")
|
|
if force_dry_mount_count is None:
|
|
set_setting("force_dry_mount_count", 0)
|
|
|
|
force_dry_timeout = get_setting("force_dry_timeout")
|
|
if force_dry_timeout is None:
|
|
set_setting("force_dry_timeout", 0)
|
|
|
|
|
|
cold_position_timeout = get_setting("cold_position_timeout")
|
|
if cold_position_timeout is None:
|
|
set_setting("cold_position_timeout", 0)
|
|
|
|
|
|
def is_room_temperature_enabled():
|
|
setting = get_setting(ROOM_TEMPERATURE_ENABLED_PREFERENCE)
|
|
return str(setting).lower() == 'true'
|
|
|
|
set_setting(ROOM_TEMPERATURE_ENABLED_PREFERENCE, is_room_temperature_enabled())
|
|
|
|
|
|
def is_beamline_status_enabled():
|
|
setting = get_setting(BEAMLINE_STATUS_ENABLED_PREFERENCE)
|
|
return str(setting).lower() == 'true'
|
|
|
|
set_setting(BEAMLINE_STATUS_ENABLED_PREFERENCE, is_beamline_status_enabled())
|
|
|
|
###################################################################################################
|
|
# Scripted devices and pseudo-devices
|
|
###################################################################################################
|
|
|
|
|
|
|
|
scripted_devices = ["devices/RobotSC", "devices/Wago", "devices/BarcodeReader", "devices/LaserDistance",
|
|
"devices/LedCtrl", "devices/SmartMagnet", "devices/Gonio",
|
|
"devices/VmbCamera",
|
|
]
|
|
|
|
for script in scripted_devices:
|
|
|
|
try:
|
|
print "Running: ", script
|
|
run(script)
|
|
except:
|
|
print >> sys.stderr, traceback.format_exc()
|
|
|
|
|
|
|
|
def set_laser_pos(pos=None):
|
|
url = "http://raspipointer:5000/preset"
|
|
if not pos:
|
|
pos = "Test2"
|
|
requests.post(url, data={"position": pos} )
|
|
|
|
|
|
def is_door_closed():
|
|
return feedback_psys_safety.take()
|
|
|
|
###################################################################################################
|
|
# Utility modules
|
|
###################################################################################################
|
|
|
|
run("data/samples")
|
|
run("data/pucks")
|
|
run("motion/tools")
|
|
run("motion/mount")
|
|
run("motion/unmount")
|
|
run("motion/get_dewar")
|
|
run("motion/put_dewar")
|
|
run("motion/get_gonio")
|
|
run("motion/put_gonio")
|
|
run("motion/move_dewar")
|
|
run("motion/move_gonio")
|
|
run("motion/move_heater")
|
|
run("motion/move_home")
|
|
run("motion/move_park")
|
|
run("motion/move_cold")
|
|
run("motion/move_scanner")
|
|
run("motion/move_aux")
|
|
run("motion/get_aux")
|
|
run("motion/put_aux")
|
|
run("motion/dry")
|
|
run("motion/trash")
|
|
run("motion/calibrate_tool")
|
|
run("motion/scan_pin")
|
|
run("motion/robot_recover")
|
|
run("motion/recover")
|
|
run("tools/Math")
|
|
if is_imaging_enabled():
|
|
run("imgproc/Utils")
|
|
|
|
def system_check(robot_move=True):
|
|
if not air_pressure_ok.read():
|
|
raise Exception("Air pressure is not ok")
|
|
if not n2_pressure_ok.read():
|
|
raise Exception("N2 pressure is not ok")
|
|
if robot_move:
|
|
if not feedback_local_safety.read():
|
|
raise Exception("Local safety not released")
|
|
auto = not is_manual_mode()
|
|
if auto:
|
|
if not feedback_psys_safety.read():
|
|
raise Exception("Psys safety not released")
|
|
#if not guiding_tool_park.read():
|
|
# raise Exception("Guiding tool 1 not parked")
|
|
#if not guiding_tool_park_2.read():
|
|
# raise Exception("Guiding tool 2 not parked")
|
|
|
|
def system_check_msg():
|
|
try:
|
|
system_check(True)
|
|
return "Ok"
|
|
except:
|
|
return sys.exc_info()[1]
|
|
|
|
def get_puck_dev(segment, puck):
|
|
if type(segment) is int:
|
|
segment = chr( ord('A') + (segment-1))
|
|
|
|
return Controller.getInstance().getPuck(str(segment).upper() + str(puck))
|
|
|
|
def get_puck_elect_detection(segment, puck):
|
|
return str(get_puck_dev(segment, puck).detection)
|
|
|
|
def get_puck_img_detection(segment, puck):
|
|
return str(Controller.getInstance().getPuck(str(segment).upper() + str(puck)).imageDetection)
|
|
|
|
def assert_puck_detected(segment, puck):
|
|
if (segment == AUX_SEGMENT) and (puck == 1):
|
|
return
|
|
if get_puck_elect_detection(segment, puck) != "Present":
|
|
raise Exception ("Puck " + str(segment).upper() + str(puck) + " not present")
|
|
|
|
|
|
def start_puck_detection():
|
|
run("tools/RestartPuckDetection")
|
|
|
|
def check_puck_detection():
|
|
return run("tools/CheckPuckDetection")
|
|
|
|
def stop_puck_detection():
|
|
run("tools/StopPuckDetection")
|
|
|
|
|
|
|
|
def get_detected_pucks():
|
|
ret = []
|
|
for i in range(30):
|
|
p = BasePlate.getPucks()[i]
|
|
if (str(p.getDetection()) == "Present"):
|
|
ret.append(str(p.getName()))
|
|
return ret
|
|
|
|
def get_pucks_info():
|
|
ret = []
|
|
for i in range(30):
|
|
p = BasePlate.getPucks()[i]
|
|
name = p.getName()
|
|
det = str(p.getDetection())
|
|
barcode = "" if p.getId() is None else p.getId()
|
|
|
|
ret.append({"puckAddress": name, "puckState": det, "puckBarcode":barcode})
|
|
return json.dumps(ret)
|
|
|
|
|
|
###################################################################################################
|
|
# Device initialization
|
|
###################################################################################################
|
|
|
|
try:
|
|
set_heater(False)
|
|
set_air_stream(False)
|
|
set_pin_cleaner(True)
|
|
except:
|
|
print >> sys.stderr, traceback.format_exc()
|
|
|
|
|
|
try:
|
|
release_local_safety.write(False)
|
|
release_psys_safety.write(False)
|
|
except:
|
|
print >> sys.stderr, traceback.format_exc()
|
|
|
|
|
|
try:
|
|
robot.setPolling(DEFAULT_ROBOT_POLLING)
|
|
robot.set_tool(TOOL_DEFAULT)
|
|
robot.set_frame(FRAME_DEFAULT)
|
|
robot.set_motors_enabled(True)
|
|
robot.set_joint_motors_enabled(True)
|
|
except:
|
|
print >> sys.stderr, traceback.format_exc()
|
|
|
|
if is_imaging_enabled():
|
|
try:
|
|
cam.setGrabMode(Camera.GrabMode.Continuous)
|
|
cam.setTriggerMode(Camera.TriggerMode.Fixed_Rate)
|
|
cam.setAcquirePeriod(330.00)
|
|
cam.setGain(0.0)
|
|
#cam.setROI(int(get_setting("roi_x")), int(get_setting("roi_y")), int(get_setting("roi_w")), int(get_setting("roi_h")))
|
|
|
|
except:
|
|
print >> sys.stderr, traceback.format_exc()
|
|
|
|
#TODO: The Smart Magnet keeps moving sample if detecting is enabled
|
|
# Detection keeps disabled unless during moount/unmount
|
|
try:
|
|
smart_magnet.set_supress(True)
|
|
except:
|
|
print >> sys.stderr, traceback.format_exc()
|
|
|
|
#gripper_cam.paused = True
|
|
###################################################################################################
|
|
# Device monitoring
|
|
###################################################################################################
|
|
|
|
DEWAR_LEVEL_RT = 5.0
|
|
is_room_temperature = False
|
|
|
|
def is_room_temp():
|
|
return is_room_temperature
|
|
|
|
|
|
class DewarLevelListener (DeviceListener):
|
|
def onValueChanged(self, device, value, former):
|
|
global is_room_temperature
|
|
if value is not None:
|
|
is_room_temperature = value <= DEWAR_LEVEL_RT
|
|
dewar_level_listener = DewarLevelListener()
|
|
|
|
for l in dewar_level.listeners:
|
|
#if isinstance(l, DewarLevelListener): #Class changes...
|
|
if Nameable.getShortClassName(l.getClass()) == "DewarLevelListener":
|
|
dewar_level.removeListener(l)
|
|
|
|
dewar_level.addListener(dewar_level_listener)
|
|
dewar_level_listener.onValueChanged(dewar_level, dewar_level.take(), None)
|
|
|
|
|
|
|
|
robot_cleared_cache = False
|
|
class FeedbackPsysListener (DeviceListener):
|
|
def onValueChanged(self, device, value, former):
|
|
global robot_cleared_door
|
|
log("Doors state changed: clearing cover detetection cache")
|
|
robot_cleared_cache = None
|
|
feedback_psys_listener = FeedbackPsysListener()
|
|
|
|
for l in feedback_psys_safety.listeners:
|
|
if Nameable.getShortClassName(l.getClass()) == "FeedbackPsysListener":
|
|
feedback_psys_safety.removeListener(l)
|
|
|
|
feedback_psys_safety.addListener(feedback_psys_listener)
|
|
feedback_psys_listener.onValueChanged(feedback_psys_safety, feedback_psys_safety.take(), None)
|
|
|
|
|
|
#Wait cover_detection to be added asynchronously
|
|
start = time.time()
|
|
while True:
|
|
if get_device("cover_detection") is not None:
|
|
break
|
|
if time.time() - start > 10.0:
|
|
raise Exception("Error creating cover detection device")
|
|
time.sleep(0.01)
|
|
|
|
class CoverDetectionListener (DeviceListener):
|
|
def onValueChanged(self, device, v, former):
|
|
global robot_cleared_door
|
|
if v and not is_string(v):
|
|
if feedback_psys_safety.take():
|
|
robot_cleared_cache = True
|
|
|
|
cover_detection_listener = CoverDetectionListener()
|
|
|
|
for l in cover_detection.listeners:
|
|
if Nameable.getShortClassName(l.getClass()) == "CoverDetectionListener":
|
|
cover_detection.removeListener(l)
|
|
|
|
cover_detection.addListener(cover_detection_listener)
|
|
cover_detection_listener.onValueChanged(cover_detection, cover_detection.take(), None)
|
|
|
|
|
|
###################################################################################################
|
|
# Cover detection
|
|
###################################################################################################
|
|
|
|
CLEAR_STATUS_IN_DEWAR = 1
|
|
CLEAR_STATUS_DOORS_CLOSED = 2
|
|
CLEAR_STATUS_MANUAL_MODE = 3
|
|
CLEAR_STATUS_IN_TASK = 4
|
|
|
|
def get_cover_location_mm(raise_ex=True, print_log=True):
|
|
off_x = off_y = off_sts = clr_sts = 0
|
|
if robot.is_dewar() or robot.is_cold():
|
|
log("Check cover location - in dewar")
|
|
clr_sts = CLEAR_STATUS_IN_DEWAR
|
|
else:
|
|
if is_service_mode():
|
|
if print_log: log("Check cover location - service mode")
|
|
off_sts = 1
|
|
else:
|
|
if cover_detection.age > 10000:
|
|
if print_log: log("Check cover location - offline")
|
|
raise Exception("Cover location detection task is not running")
|
|
v = cover_detection.take()
|
|
if v == "No cover not detected":
|
|
if print_log: log("Check cover location - no cover")
|
|
elif v and not is_string(v):
|
|
off_x, off_y, off_sts = v[4], v[5], 1
|
|
if print_log: log("Check cover location - image: " + str((off_x, off_y)))
|
|
else:
|
|
if print_log: log("Check cover location - error")
|
|
|
|
if is_manual_mode():
|
|
if print_log: log("Check cover location - Robot cleared in manual mode")
|
|
clr_sts = CLEAR_STATUS_MANUAL_MODE
|
|
elif robot_cleared_cache:
|
|
if print_log: log("Check cover location - Robot cleared with doors closed")
|
|
clr_sts = CLEAR_STATUS_DOORS_CLOSED
|
|
if (off_sts==0) and (clr_sts==0):
|
|
if raise_ex:
|
|
raise Exception("Cannot detect cover location and robot is not cleared")
|
|
return [off_x, off_y, off_sts, clr_sts]
|
|
|
|
|
|
def invalidate_cover_info(cover_info):
|
|
cover_info[2]=0
|
|
if cover_info[3]==0:
|
|
log("Invalidate cover location - Robot cleared in task continuation")
|
|
cover_info[3]=CLEAR_STATUS_IN_TASK
|
|
|
|
###################################################################################################
|
|
# Global variables & application state
|
|
###################################################################################################
|
|
|
|
|
|
cover_detection_debug = False
|
|
|
|
in_mount_position = False
|
|
|
|
|
|
def assert_mount_position():
|
|
print "Source: ", get_exec_pars().source
|
|
if not in_mount_position and get_exec_pars().source == CommandSource.server :
|
|
raise Exception("Not in mount position")
|
|
|
|
|
|
"""
|
|
def is_puck_loading():
|
|
guiding_tools_parked = guiding_tool_park.read() and guiding_tool_park_2.read()
|
|
return robot.state == State.Ready and robot.take()["pos"] == 'pPark' and \
|
|
feedback_psys_safety.take() == False and \
|
|
not guiding_tools_parked
|
|
"""
|
|
|
|
def set_pin_offset(val):
|
|
if abs(val) >5:
|
|
raise Exception("Invalid pin offset: " + str(val))
|
|
try:
|
|
set_setting("pin_offset",float(val))
|
|
except:
|
|
log("Error setting pin offset: " + str(sys.exc_info()[1]), False)
|
|
|
|
def get_pin_offset():
|
|
try:
|
|
ret = float(get_setting("pin_offset"))
|
|
if abs(ret) >5:
|
|
raise Exception("Invalid configured pin offset: " + str(ret))
|
|
return ret
|
|
except:
|
|
log("Error getting pin offset: " + str(sys.exc_info()[1]), False)
|
|
return 0.0
|
|
|
|
|
|
def set_pin_angle_offset(val):
|
|
if (abs(val) > 180.0) or (abs(val) < -180.0):
|
|
raise Exception("Invalid pin angle offset: " + str(val))
|
|
try:
|
|
set_setting("pin_angle_offset",float(val))
|
|
except:
|
|
log("Error setting pin angle offset: " + str(sys.exc_info()[1]), False)
|
|
|
|
def get_pin_angle_offset():
|
|
try:
|
|
ret = float(get_setting("pin_angle_offset"))
|
|
if (abs(ret) > 180.0) or (abs(ret) < -180.0):
|
|
raise Exception("Invalid configured pin angle offset: " + str(ret))
|
|
return ret
|
|
except:
|
|
log("Error getting pin angle offset: " + str(sys.exc_info()[1]), False)
|
|
return 0.0
|
|
|
|
def is_force_dry():
|
|
try:
|
|
dry_mount_counter = int(get_setting("dry_mount_counter"))
|
|
except:
|
|
dry_mount_counter = 0
|
|
|
|
try:
|
|
dry_timespan = time.time() - float( get_setting("dry_timestamp"))
|
|
except:
|
|
dry_timespan = 3600
|
|
|
|
try:
|
|
force_dry_mount_count = int(get_setting("force_dry_mount_count"))
|
|
if force_dry_mount_count>0 and dry_mount_counter>=force_dry_mount_count:
|
|
return True
|
|
except:
|
|
pass
|
|
|
|
try:
|
|
force_dry_timeout = float(get_setting("force_dry_timeout"))
|
|
if force_dry_timeout>0 and dry_timespan>=force_dry_timeout:
|
|
return True
|
|
except:
|
|
pass
|
|
return False
|
|
|
|
def assert_detector_safe():
|
|
pass
|
|
|
|
|
|
def onPuckLoadingChange(puck_loading):
|
|
set_led_state(puck_loading)
|
|
#pass
|
|
|
|
|
|
update()
|
|
add_device(Controller.getInstance().basePlate, True)
|
|
restore_samples_info()
|
|
|
|
|
|
print "Initialization complete"
|
|
|