diff --git a/config/plugins.properties b/config/plugins.properties index 618a8b9..d3f5fef 100644 --- a/config/plugins.properties +++ b/config/plugins.properties @@ -1,4 +1,5 @@ -Image_Correlator.java=enabled +MXSC-1.21.0.jar=disabled +Image_Correlator.java=disabled MXSC-1.14.0.jar=disabled MXSC-1.15.0.jar=disabled Commands.java=disabled diff --git a/config/settings.properties b/config/settings.properties index 586ce7f..ae97d10 100644 --- a/config/settings.properties +++ b/config/settings.properties @@ -1,13 +1,14 @@ -#Tue Nov 05 14:53:35 CET 2024 +#Thu Jan 09 14:25:02 CET 2025 barcode_reader_scan_pucks=false beamline_status_enabled=false cold_position_timeout=3600 -dry_mount_counter=0 -dry_timestamp=1.69564645367E9 -force_dry_mount_count=4 +dry_mount_counter=1 +dry_timestamp=1.736347752038E9 +force_dry_mount_count=15 force_dry_timeout=27000 imaging_enabled=true led_level=0.0 +mounted_sample=A213 pin_cleaner_timer=60 pin_offset=0 puck_types=true @@ -18,3 +19,4 @@ roi_y=123 room_temperature_enabled=false service_mode=false valve_control=true +zac=ohyes diff --git a/devices/A1.properties b/devices/A1.properties index 6739e4f..3bfa720 100644 --- a/devices/A1.properties +++ b/devices/A1.properties @@ -1,3 +1,3 @@ -#Wed Jul 14 16:02:00 CEST 2021 -detection=Mechanical +#Wed Dec 04 10:49:43 CET 2024 +detection=Inductive disabled=false diff --git a/devices/A2.properties b/devices/A2.properties index 57b0ea4..0198043 100644 --- a/devices/A2.properties +++ b/devices/A2.properties @@ -1,3 +1,3 @@ -#Thu Jun 06 15:47:03 CEST 2019 -detection=Mechanical +#Wed Dec 04 10:49:50 CET 2024 +detection=Inductive disabled=false diff --git a/devices/A3.properties b/devices/A3.properties index c936a3e..fefeba3 100644 --- a/devices/A3.properties +++ b/devices/A3.properties @@ -1,3 +1,3 @@ -#Tue Jan 21 09:46:43 CET 2020 -detection=Mechanical +#Wed Dec 04 10:49:55 CET 2024 +detection=Inductive disabled=false diff --git a/devices/A4.properties b/devices/A4.properties index 7dad517..afd64a1 100644 --- a/devices/A4.properties +++ b/devices/A4.properties @@ -1,3 +1,3 @@ -#Thu Jun 06 15:40:34 CEST 2019 -detection=Mechanical +#Wed Dec 04 10:50:00 CET 2024 +detection=Inductive disabled=false diff --git a/devices/A5.properties b/devices/A5.properties index f886a5f..d93a1dd 100644 --- a/devices/A5.properties +++ b/devices/A5.properties @@ -1,3 +1,3 @@ -#Tue Jan 21 09:46:49 CET 2020 -detection=Mechanical +#Wed Dec 04 10:50:04 CET 2024 +detection=Inductive disabled=false diff --git a/devices/cover_detection.properties b/devices/cover_detection.properties index b33f44d..4c4d361 100644 --- a/devices/cover_detection.properties +++ b/devices/cover_detection.properties @@ -1,17 +1,17 @@ -#Tue Nov 05 14:53:21 CET 2024 +#Thu Jan 09 14:25:04 CET 2025 border_dewar=0.56 -center_x=1022.0 -center_y=1048.0 +center_x=1020.0 +center_y=1047.0 continuous=false correlation_threshold=0.0 dewar_wall=0.56 diam_dewar=null diam_disk=null diam_target=null -diameter_cover=1787 +diameter_cover=1800 diameter_dewar=1798 diameter_disk=670 -diameter_target=100 +diameter_target=75 diamter_dewar=1800 diamter_disk=670 disc_marker_ov=null @@ -23,8 +23,9 @@ number_images=1 offset_threshold=null open_strategy=both rotation_degrees=0.0 -scale_x=0.3969679955081415 -scale_y=0.3943112102621305 +scale_x=0.3932146829810901 +scale_y=0.39234184239733627 size_mask_dewar=0.98 size_mask_disk=0.8 +target_time_tolerance=20.0 threshold_method=IsoData diff --git a/devices/ip_ref_fe.png.properties b/devices/ip_ref_fe.png.properties new file mode 100644 index 0000000..ca3cbe5 --- /dev/null +++ b/devices/ip_ref_fe.png.properties @@ -0,0 +1,20 @@ +#Tue Nov 05 16:27:22 CET 2024 +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=NaN +spatialCalOffsetY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN +spatialCalUnits=mm +transpose=false diff --git a/devices/led_ctrl_1.properties b/devices/led_ctrl_1.properties index 21fdc8c..0a984be 100644 --- a/devices/led_ctrl_1.properties +++ b/devices/led_ctrl_1.properties @@ -1,6 +1,6 @@ -#Thu Aug 15 14:00:10 CEST 2024 +#Wed Jan 08 16:13:51 CET 2025 description=null -maxValue=0.4 +maxValue=1.0 minValue=0.0 offset=0.0 precision=2 diff --git a/devices/led_ctrl_2.properties b/devices/led_ctrl_2.properties index 21fdc8c..0a984be 100644 --- a/devices/led_ctrl_2.properties +++ b/devices/led_ctrl_2.properties @@ -1,6 +1,6 @@ -#Thu Aug 15 14:00:10 CEST 2024 +#Wed Jan 08 16:13:51 CET 2025 description=null -maxValue=0.4 +maxValue=1.0 minValue=0.0 offset=0.0 precision=2 diff --git a/devices/led_ctrl_3.properties b/devices/led_ctrl_3.properties index 21fdc8c..0a984be 100644 --- a/devices/led_ctrl_3.properties +++ b/devices/led_ctrl_3.properties @@ -1,6 +1,6 @@ -#Thu Aug 15 14:00:10 CEST 2024 +#Wed Jan 08 16:13:51 CET 2025 description=null -maxValue=0.4 +maxValue=1.0 minValue=0.0 offset=0.0 precision=2 diff --git a/plugins/MXSC-1.21.0.jar b/plugins/MXSC-1.21.0.jar index 955ec01..6039932 100644 Binary files a/plugins/MXSC-1.21.0.jar and b/plugins/MXSC-1.21.0.jar differ diff --git a/script/data/pucks.py b/script/data/pucks.py index 3228c34..32bdd07 100644 --- a/script/data/pucks.py +++ b/script/data/pucks.py @@ -2,11 +2,12 @@ def get_puck_names(): return [str(a)+str(b) for a in BLOCKS for b in range(1,6)] -def get_puck_info(): +def get_puck_info(status=None): ret = [] #for puck in get_puck_names(): for puck in BasePlate.pucks: - ret.append({"address" : str(puck.name), "status": str(puck.status), "barcode" : str(puck.id)}) + if (status is None) or (status==puck.status): + ret.append({"address" : str(puck.name), "status": str(puck.status), "barcode" : str(puck.id)}) return ret @@ -14,11 +15,19 @@ def get_puck_obj(address): return BasePlate.getChild(address) -def get_puck_obj_by_id(puck_id): - for puck in BasePlate.pucks: - if puck.id == puck_id: - return puck - return None +def get_puck_obj_by_id(puck_id, approx=True): + if puck_id: + for puck in BasePlate.pucks: + if puck.id == puck_id: + return puck + + if approx: + puck_id = barcode_clean_re.sub("", puck_id.upper()) + for puck in BasePlate.pucks: + if puck.id: + if barcode_clean_re.sub("", puck.id.upper()) == puck_id: + return puck + return None def set_puck_info(puck_info): diff --git a/script/data/samples.py b/script/data/samples.py index cbb0756..3d5844e 100644 --- a/script/data/samples.py +++ b/script/data/samples.py @@ -95,13 +95,14 @@ def remove_puck_datamatrix(barcode): barcode_clean_re = re.compile("[^a-zA-Z0-9]") -def is_same_datamatrix(table, reading): +def is_same_datamatrix(table, reading, do_log=True): if table == reading: return True table2 = barcode_clean_re.sub("", table.upper()) reading2 = barcode_clean_re.sub("", reading.upper()) if table2 == reading2: - log("Assigning aproximative datamatrix " + reading ) + if do_log: + log("Assigning aproximative datamatrix " + reading ) return True return False @@ -138,8 +139,20 @@ def get_puck_datamatrix(): return ret -def get_puck_datamatrix_info(): +def get_puck_from_datamatrix(datamatrix): + try: + for dm,puck in get_puck_datamatrix().items(): + if is_same_datamatrix(dm,datamatrix): + return puck + except: + pass + return None + + +def get_puck_datamatrix_info(use_puck_detection=True): ret = {} + #get_puck_obj_by_id("A-10").getName() + for si in samples_info: if si["puckBarcode"] is not None and si["puckBarcode"]!="": info = {} @@ -149,6 +162,35 @@ def get_puck_datamatrix_info(): info["user"] = si ["userName"] info["type"] = si ["puckType"] ret[si["puckBarcode"]] = info + + if use_puck_detection: + detected_pucks = get_puck_info("Present") # + for p in detected_pucks: + address = str(p['address']) + barcode = str(p['barcode']) + if barcode and barcode != str(None): + insert = True + for id,info in ret.items(): + add = info["address"] + if is_same_datamatrix(barcode, id, False): + insert = False + if str(add).strip() != address: + log("Apdating address from DM info: " + add ) + for entry in ret.values(): + if str(entry['address']).strip() == address: + entry['address']="" + info["address"] = address + break + #Different address: + if insert: + info = {} + info["address"] = address + info["dewar"] = "" + info["name"] = "" + info["user"] = "" + info["type"] = "" + ret[barcode] = info + return ret def get_puck_address(barcode): diff --git a/script/devices/CoverDetection.py b/script/devices/CoverDetection.py index 391abbb..522a9e6 100644 --- a/script/devices/CoverDetection.py +++ b/script/devices/CoverDetection.py @@ -19,6 +19,7 @@ class CoverDetectionConfig(RegisterConfig): self.border_dewar=0.56 self.size_mask_disk=0.8 self.size_mask_dewar=0.98 + self.target_time_tolerance = 20.0 self.max_detect_offset=10 self.open_strategy = "both" self.threshold_method = "IsoData" @@ -53,7 +54,7 @@ class CoverDetection(ReadonlyAsyncRegisterBase, ReadonlyRegisterArray): self.error_overlay=None self.img_counter, self.proc_counter = 0, 0 self.offset_px = self.offset_um = None - self.correlation = CoverCorrelation("cover_correlation") + #self.correlation = CoverCorrelation("cover_correlation") self.correlation_error = False self.disc_marker_ov = None self.center_marker_ov = None @@ -70,7 +71,7 @@ class CoverDetection(ReadonlyAsyncRegisterBase, ReadonlyRegisterArray): def doClose(self): self.disable() - self.correlation.close() + #self.correlation.close() def set_renderer(self, renderer): self.clear() @@ -93,7 +94,7 @@ class CoverDetection(ReadonlyAsyncRegisterBase, ReadonlyRegisterArray): def clear(self): self.set_marker(None) self.set_error_overlay(None) - self.set_correlation(None) + #self.set_correlation(None) def append(self, image): self.img_counter += 1 @@ -112,11 +113,11 @@ class CoverDetection(ReadonlyAsyncRegisterBase, ReadonlyRegisterArray): self.error = None center = (self.config.center_x, self.config.center_y) try: - x,y = detect_covert_position(ip, center, \ + x,y = detect_cover_position(ip, center, \ diam_target=self.config.diameter_target, diam_disk= self.config.diameter_disk, diam_dewar=self.config.diameter_dewar, \ mask_disk=self.config.size_mask_disk, mask_dewar=self.config.size_mask_dewar, border_dewar = self.config.border_dewar, \ - offset_threshold=self.config.max_detect_offset ,open_strategy= self.config.open_strategy, threshold_method=self.config.threshold_method, \ - debug=self.debug) + offset_threshold=self.config.max_detect_offset , target_time_tolerance= self.config.target_time_tolerance, \ + open_strategy= self.config.open_strategy, threshold_method=self.config.threshold_method, debug=self.debug) except Exception as e: self.error = e @@ -133,14 +134,14 @@ class CoverDetection(ReadonlyAsyncRegisterBase, ReadonlyRegisterArray): self.processing_time = time.time()-start self.proc_counter += 1 - try: - corr = get_correlation(ip.getBufferedImage()) - self.correlation.set(corr) - self.set_correlation(corr) - except Exception as e: - #traceback.print_exc() - if self.error is None: - self.error = e + #try: + # corr = get_correlation(ip.getBufferedImage()) + # self.correlation.set(corr) + # self.set_correlation(corr) + #except Exception as e: + # #traceback.print_exc() + # if self.error is None: + # self.error = e self.set(x, y, self.processing_time * 1000, self.error) #traceback.print_exc() @@ -215,26 +216,26 @@ class CoverDetection(ReadonlyAsyncRegisterBase, ReadonlyRegisterArray): images.append(ip) self.image.waitNext(-1) ip = integrate(images) - img = ip.getBufferedImage() + image = ip.getBufferedImage() else: - img = self.image.output - save_ref_img(img) + image = self.image.output + save_ref_img(image) - def set_correlation(self, corr): - self.corr = corr - error = corr is not None and corr < self.config.correlation_threshold - if error != self.correlation_error: - self.correlation_error = error - if error: - print ("Image anomally detected") - else: - print ("Image ok") - if error: - raise Exception ("Image anomally detected") + #def set_correlation(self, corr): + # self.corr = corr + # error = corr is not None and corr < self.config.correlation_threshold + # if error != self.correlation_error: + # self.correlation_error = error + # if error: + # print ("Image anomally detected") + # else: + # print ("Image ok") + # if error: + # raise Exception ("Image anomally detected") def show_disk_marker(self): size = int(DISK_SIZE_MM * (self.config.scale_x + self.config.scale_y)/2.0) - pn = show_panel(img) + pn = show_panel(self.image) ov=Overlays.Ellipse(Pen(Color.RED), Point(0,0), Dimension(661,661)) ov.movable=True ov.solid=True @@ -242,8 +243,8 @@ class CoverDetection(ReadonlyAsyncRegisterBase, ReadonlyRegisterArray): self.disc_marker_ov = ov def show_center_marker(self): - pn = show_panel(img) - ov=Overlays.Crosshairs(Pen(Color.RED), Point(int(cover_detection.config.center_x), int(cover_detection.config.center_y)), Dimension(-1,-1)) + pn = show_panel(self.image) + ov=Overlays.Crosshairs(Pen(Color.RED), Point(int(self.config.center_x), int(self.config.center_y)), Dimension(-1,-1)) ov.movable=False pn.updateOverlays(ov, self.center_marker_ov) self.center_marker_ov = ov @@ -251,7 +252,7 @@ class CoverDetection(ReadonlyAsyncRegisterBase, ReadonlyRegisterArray): add_device(CoverDetection("cover_detection", img), force = True) -add_device(cover_detection.correlation, force = True) +#add_device(cover_detection.correlation, force = True) #renderer=show_panel(img) #cover_detection.set_renderer(renderer) diff --git a/script/devices/RobotSC.py b/script/devices/RobotSC.py index 47cbc34..8d2a345 100644 --- a/script/devices/RobotSC.py +++ b/script/devices/RobotSC.py @@ -17,6 +17,8 @@ RT_SEGMENT = "R" DEFAULT_ROBOT_POLLING = 500 TASK_WAIT_ROBOT_POLLING = 50 +SAME_LOCATION = (1000, 1000) + run("devices/RobotTCP") @@ -45,19 +47,20 @@ class RobotSC(RobotTCP): self.last_command_timestamp = time.time() self.ongoing_task = None - def move_dewar_async(self, off_x, off_y): - self.start_task('moveDewar', off_x,off_y) - self.ongoing_task = ("dewar", self.assert_dewar) + def move_dewar_async(self, off_x, off_y, sts_det, sta_clr): + status = sts_det + sta_clr*10 + self.start_task('moveDewar', off_x,off_y, status) + self.ongoing_task = ("dewar", self.assert_dewar) - def move_dewar(self, off_x,off_y): - self.move_dewar_async(off_x,off_y) + def move_dewar(self, off_x, off_y, sts_det, sta_clr): + self.move_dewar_async(off_x, off_y, sts_det, sta_clr) self.wait_async_motion() def move_cold_async(self): self.start_task('moveCold') self.ongoing_task = ("cold", self.assert_cold) - def move_cold(self): + def move_cold(self): self.move_cold_async() self.wait_async_motion() @@ -73,7 +76,7 @@ class RobotSC(RobotTCP): segment = self.toSegmentNumber(segment) self.start_task('getDewar',segment, puck, sample, is_room_temp()) self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) - self.assert_dewar() + self.assert_cold() self.last_command_position = "dewar" self.last_command_timestamp = time.time() diff --git a/script/devices/RobotTCP.py b/script/devices/RobotTCP.py index 4727d68..2a3c2f8 100644 --- a/script/devices/RobotTCP.py +++ b/script/devices/RobotTCP.py @@ -50,6 +50,7 @@ class RobotTCP(TcpDevice, Stoppable): self.default_speed = 100 self.latency = 0 self.last_msg_timestamp = 0 + self.debug=False self.task_start_retries = 3 self.exception_on_task_start_failure = True #Tasks may start and be finished when checked @@ -167,7 +168,12 @@ class RobotTCP(TcpDevice, Stoppable): try: id = "%03d" % self.msg_id self.msg_id = (self.msg_id+1)%1000 - return self._sendReceive(id, msg, timeout) + if self.debug: + print "TX: ", msg + ret = self._sendReceive(id, msg, timeout) + if self.debug: + print "RX: ", ret + return ret finally: self.lock.release() diff --git a/script/imgproc/CoverCorrelation.py b/script/imgproc/CoverCorrelation.py index aae1d39..9792c01 100644 --- a/script/imgproc/CoverCorrelation.py +++ b/script/imgproc/CoverCorrelation.py @@ -87,15 +87,19 @@ def get_edge_img(ib): def save_ref_img(img): global ip_ref_fe - path = os.path.abspath(expand_path("{images}/ip_ref.png")) + path = os.path.abspath(expand_path("{images}/Correlation/ip_ref.png")) roi=get_roi_img(img, offset_x=0, offset_y=0) ImageBuffer.saveImage(roi, path, "png") + path = os.path.abspath(expand_path("{images}/Correlation/ip_ref_f.png")) + ip_ref_f = image_fft(load_image(roi)) + ImageBuffer.saveImage(ip_ref_f.getBufferedImage(), path, "png") - path = os.path.abspath(expand_path("{images}/ip_ref_e.png")) - ip_ref_e =get_edge_img(roi) + path = os.path.abspath(expand_path("{images}/Correlation/ip_ref_e.png")) + ip_ref_e = get_edge_img(roi) ImageBuffer.saveImage(ip_ref_e.getBufferedImage(), path, "png") - path = os.path.abspath(expand_path("{images}/ip_ref_fe.png")) + + path = os.path.abspath(expand_path("{images}/Correlation/ip_ref_fe.png")) ip_ref_fe = image_fft(ip_ref_e) ImageBuffer.saveImage(ip_ref_fe.getBufferedImage(), path, "png") @@ -114,10 +118,12 @@ def put_mark(ib): for y in range(650, 700): ib.setRGB(x,y, 0) -def get_correlation(img): +def get_correlation(image=None): + if image is None: + image = img.output global ip_ref_fe if "ip_ref_fe" not in globals() or ip_ref_fe is None: - path = os.path.abspath(expand_path("{images}/ip_ref.png")) + path = os.path.abspath(expand_path("{images}/Correlation/ip_ref.png")) roi = ImagingUtils.newImage(path) #ip_ref_fe=open_imagroie(path+"ip_ref_fe.png" ,"png") #ip_ref = load_image(roi, title="ip_ref") @@ -126,7 +132,7 @@ def get_correlation(img): #ip_ref_fe = clear_dc(ip_ref_fe) print "Opened reference image" - roi =get_roi_img(img, offset_x=-offset, offset_y=-offset) + roi =get_roi_img(image, offset_x=-offset, offset_y=-offset) if add_mark: put_mark(roi) #ip_cur = load_image(roi, title="Ref") @@ -136,4 +142,14 @@ def get_correlation(img): #ip_cur_fe = clear_dc(ip_cur_fe) return max(correlator.getCorrelation(ip_ref_fe, ip_cur_fe)[0], 0.0) - \ No newline at end of file + +class CorrFilter(Filter): + def process(self, image, data): + roi=get_roi_img(image, offset_x=0, offset_y=0) + #ip_ref_f = image_fft(load_image(roi)) + ip_ref_e = get_edge_img(roi) + ip_ref_fe = image_fft(ip_ref_e) + return ip_ref_fe.getBufferedImage() + + +corr_filter = CorrFilter() \ No newline at end of file diff --git a/script/imgproc/CoverDetection.py b/script/imgproc/CoverDetection.py index caabd1d..46664af 100644 --- a/script/imgproc/CoverDetection.py +++ b/script/imgproc/CoverDetection.py @@ -6,7 +6,7 @@ COVER_SIZE_MM = 707.0 DISK_SIZE_MM = 260.0 TARGET_SIZE_MM = 40.0 -TARGET_HOLES = True +TARGET_HOLES = False def set_circle_mask(ip, center_x, center_y, radius, bitwise=False): w, h = ip.getWidth(), ip.getHeight() @@ -24,8 +24,13 @@ def set_circle_mask(ip, center_x, center_y, radius, bitwise=False): ip.copyBits(mask, 0, 0, Blitter.AND) # Apply the mask using a bitwise AND -def detect_covert_position( ip, center=None, diam_target=95, diam_disk=670, diam_dewar=1800, mask_disk=0.8, mask_dewar=0.98, border_dewar=0.7, offset_threshold=10,\ - open_strategy = "both", print_table=False, output_image=False, threshold_method="IsoData", debug=False): +last_target_detection = None +use_target_cache = False + +def detect_cover_position( ip, center=None, diam_target=95, diam_disk=670, diam_dewar=1800, mask_disk=0.8, mask_dewar=0.98, border_dewar=0.7, offset_threshold=10,\ + target_time_tolerance=0.0, open_strategy = "both", print_table=False, output_image=False, threshold_method="IsoData", debug=False): + global last_target_detection, use_target_cache + use_target_cache = False if output_image==True: output_image= "outlines" if ip.getProcessor().isGrayscale(): @@ -89,26 +94,31 @@ def detect_covert_position( ip, center=None, diam_target=95, diam_disk=670, diam px = int(pow(diam_target/2,2) * math.pi) (res1,out1)=analyse_particles(it, px/2, px*2, \ fill_holes = True, exclude_edges = True, print_table=print_table, \ - output_image = output_image, minCirc = 0.6 if TARGET_HOLES else 0.8 , maxCirc = 1.0) + output_image = output_image, minCirc = 0.8 if TARGET_HOLES else 0.8 , maxCirc = 1.0) if res1.size() != 1: - msg = "Target detection error: " + ("none" if res1.size()==0 else "") - for i in range( res1.size()): - msg = msg + "(" + str(res1.getValue("XM", 0)) + ", " + str( res2.res1("YM", 0)) + "), " - raise Exception( msg ) - - x1,y1 = res1.getValue("XM", 0), res1.getValue("YM", 0) + x1, y1, timestamp = last_target_detection if (last_target_detection is not None) else (0,0,0) + #Uses previoes inner position if close to center of outter, for during certain time + if (target_time_tolerance<=0) or (time.time() - timestamp > target_time_tolerance): + msg = "Target detection error: " + ("none" if res1.size()==0 else "") + for i in range( res1.size()): + msg = msg + "(" + str(res1.getValue("XM", 0)) + ", " + str( res2.res1("YM", 0)) + "), " + raise Exception( msg ) + use_target_cache = True + else: + x1,y1 = res1.getValue("XM", 0), res1.getValue("YM", 0) + last_target_detection = (x1,y1, time.time()) if abs(x1-x2) > offset_threshold or abs(y1-y2) > offset_threshold: msg = "Disk/Target offset error: " + "(" + str(int(x1-x2)) + ", " + str(int(y1-y2)) + ")" raise Exception( msg ) + border_dewar = 0.9 distance = math.hypot(x1-center[0], y1-center[1]) distance_threshold = border_dewar * diam_dewar /2 if distance > distance_threshold: msg = "Cover position outside dewar: " + "(" + str(int(x1)) + ", " + str(int(y1)) + ")" - raise Exception( msg ) - + raise Exception( msg ) return x1,y1 diff --git a/script/local.py b/script/local.py index 7fcd073..862ddd0 100644 --- a/script/local.py +++ b/script/local.py @@ -149,22 +149,11 @@ def set_laser_pos(pos=None): url = "http://raspipointer:5000/preset" if not pos: pos = "Test2" - requests.post(url, data={"position": pos} ) + requests.post(url, data={"position": pos} ) -def get_cover_location_mm(raise_ex=True): - if is_service_mode(): - return 0.0, 0.0 - v = cover_detection.take() - if v == "No cover not detected": - return 0.0, 0.0 - if v and not is_string(v): - return v[4], v[5] - if raise_ex: - raise Exception("Cannot detect cover location") - - - +def is_door_closed(): + return feedback_psys_safety.take() ################################################################################################### # Utility modules @@ -211,10 +200,10 @@ def system_check(robot_move=True): 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") + #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: @@ -344,6 +333,99 @@ for l in dewar_level.listeners: 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 ################################################################################################### @@ -361,12 +443,13 @@ def assert_mount_position(): 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: @@ -438,11 +521,12 @@ def assert_detector_safe(): def onPuckLoadingChange(puck_loading): set_led_state(puck_loading) #pass + update() add_device(Controller.getInstance().basePlate, True) restore_samples_info() - + print "Initialization complete" \ No newline at end of file diff --git a/script/motion/dry.py b/script/motion/dry.py index 40650c2..9b96d77 100644 --- a/script/motion/dry.py +++ b/script/motion/dry.py @@ -48,11 +48,11 @@ def dry(heat_time=None, speed=None, wait_cold = None): set_setting("dry_mount_counter", 0) - set_setting("dry_timestamp",time.time()) + set_setting("dry_timestamp", time.time()) if wait_cold >=0 : - off_x,off_y = get_cover_location_mm() - robot.move_dewar(off_x,off_y) + cover_info = get_cover_location_mm() + robot.move_dewar(*cover_info) robot.move_cold() time.sleep(wait_cold) else: diff --git a/script/motion/get_dewar.py b/script/motion/get_dewar.py index 9049cec..523b2c9 100644 --- a/script/motion/get_dewar.py +++ b/script/motion/get_dewar.py @@ -2,7 +2,7 @@ def get_dewar(segment, puck, sample, force=False): """ """ print "get_dewar: ", segment, puck, sample, force - off_x,off_y = get_cover_location_mm() + cover_info = get_cover_location_mm() #Initial checks assert_valid_address(segment, puck, sample) @@ -16,8 +16,7 @@ def get_dewar(segment, puck, sample, force=False): #Enabling enable_motion() - + #added or robot.is_cold in condition if not robot.is_dewar(): - robot.move_dewar(off_x,off_y) - + robot.move_dewar(*cover_info) robot.get_dewar(segment, puck, sample) diff --git a/script/motion/mount.py b/script/motion/mount.py index 11202a2..c6afca4 100644 --- a/script/motion/mount.py +++ b/script/motion/mount.py @@ -9,7 +9,7 @@ def mount(segment, puck, sample, force=False, read_dm=False, auto_unmount=False) print "mount(\"%s\", %d, %d, force=%d, read_dm=%d, auto_unmount=%d)" % (segment, puck, sample, force, read_dm, auto_unmount) start = time.time() - off_x,off_y = get_cover_location_mm() + cover_info = get_cover_location_mm() was_cold = robot.is_cold() is_aux = segment == AUX_SEGMENT is_rt = segment == RT_SEGMENT @@ -61,9 +61,10 @@ def mount(segment, puck, sample, force=False, read_dm=False, auto_unmount=False) try: #ZACH if needs_chilling and not delayed_chill: - robot.move_dewar(off_x,off_y) + robot.move_dewar(*cover_info) robot.move_cold() time.sleep(30.0) + invalidate_cover_info(cover_info) if smart_magnet.get_supress() == True: smart_magnet.set_supress(False) @@ -94,9 +95,10 @@ def mount(segment, puck, sample, force=False, read_dm=False, auto_unmount=False) enable_motion() if delayed_chill: - robot.move_dewar(off_x,off_y) + robot.move_dewar(*cover_info) robot.move_cold() time.sleep(30.0) + invalidate_cover_info(cover_info) #ZACH # a room temp pin is being mounted but the gripper is cold @@ -111,7 +113,8 @@ def mount(segment, puck, sample, force=False, read_dm=False, auto_unmount=False) else: if not robot.is_dewar(): - robot.move_dewar(off_x,off_y) + robot.move_dewar(*cover_info) + invalidate_cover_info(cover_info) robot.get_dewar(segment, puck, sample) @@ -121,9 +124,9 @@ def mount(segment, puck, sample, force=False, read_dm=False, auto_unmount=False) robot.move_scanner() #time.sleep(1.0) - print "moving cryo out to 17" + #print "moving cryo out to 17" cryostage.moveAsync(17.0) - print "waiting cryo out to 17" + #print "waiting cryo out to 17" cryostage.waitInPosition(17.0, 3500) print "move_gonio" robot.move_gonio() @@ -156,8 +159,11 @@ def mount(segment, puck, sample, force=False, read_dm=False, auto_unmount=False) if is_aux: robot.move_park_async() else: - robot.move_dewar(off_x,off_y) - robot.move_cold_async() + robot.move_dewar(*cover_info) + if is_force_dry(): + robot.move_park_async() + else: + robot.move_cold_async() robot.wait_async_motion() diff --git a/script/motion/move_cold.py b/script/motion/move_cold.py index e9fb0f8..fce0f25 100644 --- a/script/motion/move_cold.py +++ b/script/motion/move_cold.py @@ -23,6 +23,6 @@ def move_cold(reset_timestamp=False): if not robot.is_cold(): - off_x,off_y = get_cover_location_mm() - robot.move_dewar(off_x,off_y) + cover_info = get_cover_location_mm() + robot.move_dewar(*cover_info) robot.move_cold() \ No newline at end of file diff --git a/script/motion/move_dewar.py b/script/motion/move_dewar.py index 3a43122..e2b645e 100644 --- a/script/motion/move_dewar.py +++ b/script/motion/move_dewar.py @@ -3,7 +3,7 @@ def move_dewar(): """ print "move_dewar" - off_x,off_y = get_cover_location_mm() + cover_info = get_cover_location_mm() #Initial checks robot.assert_no_task() robot.reset_motion() @@ -16,4 +16,15 @@ def move_dewar(): if not robot.is_dewar(): - robot.move_dewar(off_x,off_y) \ No newline at end of file + robot.move_dewar(*cover_info) + +""" +class Test: + def move_dewar(self, off_x, off_y, sts_det, sta_clr): + print off_x, off_y, sts_det, sta_clr + +test=Test() + +cover_info = get_cover_location_mm() +test.move_dewar(*cover_info) +""" \ No newline at end of file diff --git a/script/motion/move_home.py b/script/motion/move_home.py index 30592d6..8167a17 100644 --- a/script/motion/move_home.py +++ b/script/motion/move_home.py @@ -15,4 +15,4 @@ def move_home(): if not robot.is_home(): - robot.move_home() + robot.move_home() diff --git a/script/motion/put_dewar.py b/script/motion/put_dewar.py index b161377..24e270d 100644 --- a/script/motion/put_dewar.py +++ b/script/motion/put_dewar.py @@ -2,7 +2,8 @@ def put_dewar(segment, puck, sample, force=False): """ """ print "put_dewar: ", segment, puck, sample, force - off_x,off_y = get_cover_location_mm() + + cover_info = get_cover_location_mm() #Initial checks assert_valid_address(segment, puck, sample) assert_puck_detected(segment, puck) @@ -16,6 +17,6 @@ def put_dewar(segment, puck, sample, force=False): if not robot.is_dewar(): - robot.move_dewar(off_x,off_y) - + robot.move_dewar(*cover_info) + robot.put_dewar(segment, puck, sample) diff --git a/script/motion/recover.py b/script/motion/recover.py index f4e61af..46b78ca 100644 --- a/script/motion/recover.py +++ b/script/motion/recover.py @@ -11,12 +11,14 @@ known_segments = [ ("pGonioA", "pGonioG", 10), \ ("pScan", "pHeater", 50), \ ("pHome", "pDewar", 10), \ ("pHeater", "pHeatB", 10), \ - ("pHome", "pAux", 50), \ + #("pHome", "pAux", 50), \ ] + def get_robot_position(): - return robot.get_cartesian_pos() + return robot.get_cartesian_pos(tool=TOOL_DEFAULT, frame=FRAME_DEFAULT) + def get_dist_to_line(segment): @@ -117,12 +119,12 @@ def move_to_safest_point(segment, vicinity_tolerance = 100): #print "Recovered to point " + str(robot.get_curjoint_or_pointrent_point()) def is_in_dewar(): - z_hom = robot.get_pnt('pHome')[2] - z_cur=get_robot_position()[2] - if z_cur < (z_hom + 30): + in_dewar = robot.get_pnt('pInDewar') + cur=get_robot_position() + if cur[2] > in_dewar[2]: return False - d_dwr = robot.get_distance_to_pnt('pDewar') - if d_dwr > 300: + d=math.hypot(cur[0]-in_dewar[0], cur[1]-in_dewar[1]) + if d > 250: return False return True diff --git a/script/motion/scan_pin.py b/script/motion/scan_pin.py index d3de217..552a551 100644 --- a/script/motion/scan_pin.py +++ b/script/motion/scan_pin.py @@ -7,7 +7,7 @@ def scan_pin(segment, puck, sample, force=False): pin_name = get_sample_name(segment, puck, sample) print "scan pin", pin_name - off_x,off_y = get_cover_location_mm() + cover_info = get_cover_location_mm() #Initial checks assert_valid_address(segment, puck, sample) #assert_puck_detected(segment, puck) @@ -36,7 +36,7 @@ def scan_pin(segment, puck, sample, force=False): robot.get_aux(sample) else: if not robot.is_dewar(): - robot.move_dewar(off_x,off_y) + robot.move_dewar(*cover_info) robot.get_dewar(segment, puck, sample) @@ -47,7 +47,7 @@ def scan_pin(segment, puck, sample, force=False): robot.move_aux() robot.put_aux( sample) else: - robot.move_dewar(off_x,off_y) + robot.move_dewar(*cover_info) robot.put_dewar(segment, puck, sample) ret = "Empty" if detected: @@ -121,7 +121,7 @@ def scan_gripper(): (detected, dm) = move_scanner() - robot.move_home() + robot.move_park() ret = "Empty" if detected: diff --git a/script/motion/trash.py b/script/motion/trash.py index 3ad311c..38c934d 100644 --- a/script/motion/trash.py +++ b/script/motion/trash.py @@ -31,8 +31,8 @@ def trash(): robot.move_heater(to_bottom = False) - off_x,off_y = get_cover_location_mm() - robot.move_dewar(off_x,off_y) + cover_info = get_cover_location_mm() + robot.move_dewar(*cover_info) robot.move_cold() \ No newline at end of file diff --git a/script/motion/unmount.py b/script/motion/unmount.py index b097090..3a984a1 100644 --- a/script/motion/unmount.py +++ b/script/motion/unmount.py @@ -9,7 +9,7 @@ def unmount(segment = None, puck = None, sample = None, force=False, auto_unmoun """ evlog = Controller.getInstance().logEvent print "unmount: ", segment, puck, sample, force - off_x,off_y = get_cover_location_mm() + cover_info = get_cover_location_mm() if (segment is None) or (puck is None) or (sample is None): pos = get_setting("mounted_sample_position") @@ -80,9 +80,11 @@ def unmount(segment = None, puck = None, sample = None, force=False, auto_unmoun if not is_aux: if needs_chilling: - robot.move_dewar(off_x,off_y) + robot.move_dewar(*cover_info) robot.move_cold() time.sleep(30.) + invalidate_cover_info(cover_info) + else: if needs_drying: dry(wait_cold=-1) @@ -111,7 +113,7 @@ def unmount(segment = None, puck = None, sample = None, force=False, auto_unmoun else: #TODO: Should check if smart magnet detection is off? update_samples_info_sample_unmount(get_puck_name(segment, puck), sample) - robot.move_dewar(off_x,off_y) + robot.move_dewar(*cover_info) robot.put_dewar(segment, puck, sample) if mount_sample_detected: diff --git a/script/setup/CoverDetectionExposureScan.py b/script/setup/CoverDetectionExposureScan.py index b5943f6..cdf109e 100644 --- a/script/setup/CoverDetectionExposureScan.py +++ b/script/setup/CoverDetectionExposureScan.py @@ -1,30 +1,34 @@ from ijutils import * +RANGE = (10, 40) +STEP_SIZE = 2.0 + diam_disk = cover_detection.config.diameter_disk diam_target = cover_detection.config.diameter_target diam_dewar = cover_detection.config.diameter_dewar threshold_method = cover_detection.config.threshold_method center_x, center_y = ( cover_detection.config.center_x, cover_detection.config.center_y) -radius_dewar = diam_dewar /2.0 +radius_dewar = diam_dewar/2.0 roi = Rectangle(int(center_x-radius_dewar), int(center_y-radius_dewar), int(diam_dewar), int(diam_dewar)) area_disc = int(pow(diam_disk/2,2) * math.pi) area_target = int(pow(diam_target/2,2) * math.pi) area = area_disc - area_target if TARGET_HOLES: area -= int(4* pow(12/2,2) * math.pi) -debug=False -settling_time = 0.4 +debug=True +settling_time = cam.getAcquirePeriod()/1000.0 + 0.3 class Fitness(Readable): def read(self): try: ip = load_image(ImagingUtils.grayscale(img.output, None)) set_circle_mask(ip.getProcessor(), center_x=center_x, center_y=center_y, radius=radius_dewar, bitwise=False) - it = auto_threshold(ip, dark_background=True, method=threshold_method, in_place=False) + #it = auto_threshold(ip, dark_background=True, method=threshold_method, in_place=False) + it = threshold(ip, 128, 255, in_place=False) binary_open(it, dark_background=True, iterations=1, count=1); binary_open(it, dark_background=False, iterations=1, count=1); if debug: - ImageBuffer.saveImage(it.getBufferedImage(), os.path.abspath(expand_path("{images}/ExposureScan.png")), "png") + ImageBuffer.saveImage(it.getBufferedImage(), os.path.abspath(expand_path("{images}/ExposureScan/" + str( cam.getExposure()) + ".png")), "png") h = get_histogram(it) b,w= h[0], h[-1] @@ -42,7 +46,7 @@ class Exposure(Writable): fitness=Fitness() exposure=Exposure() -ret = lscan(exposure,fitness,10, 60, 2.0, settling_time, save=False) +ret = lscan(exposure,fitness,RANGE[0], RANGE[1], STEP_SIZE, settling_time, save=False) y, x = ret.getReadable(0), ret.getPositions(0) m=x[y.index(min(y))] p=get_plots()[0] diff --git a/script/test/mount_profile.py b/script/test/mount_profile.py index 2abeed7..92976c9 100644 --- a/script/test/mount_profile.py +++ b/script/test/mount_profile.py @@ -6,7 +6,7 @@ def mount(segment, puck, sample, force=False, read_dm=False, auto_unmount=False) """ global mount_sample_id, mount_sample_detected print "mount: ", segment, puck, sample, force - off_x,off_y = get_cover_location_mm() + cover_info = get_cover_location_mm() start = time.time() @@ -92,7 +92,7 @@ def mount(segment, puck, sample, force=False, read_dm=False, auto_unmount=False) visual_check_hexiposi(segment) if not robot.is_dewar(): - robot.move_dewar(off_x,off_y) + robot.move_dewar(*cover_info) print "Pass 4b: ", time.time() - start; start = time.time() robot.get_dewar(segment, puck, sample) print "Pass 5: ", time.time() - start; start = time.time() diff --git a/script/test/unmount_profile.py b/script/test/unmount_profile.py index 5adcdb3..0dd0b2b 100644 --- a/script/test/unmount_profile.py +++ b/script/test/unmount_profile.py @@ -87,7 +87,7 @@ def unmount(segment = None, puck = None, sample = None, force=False, auto_unmoun else: #TODO: Shuld check if smart magnet detection is off? update_samples_info_sample_unmount(get_puck_name(segment, puck), sample) - robot.move_dewar() + robot.move_dewar(*cover_info) print "Pass H: " , time.time() - start; start = time.time() robot.put_dewar(segment, puck, sample) print "Pass I: " , time.time() - start; start = time.time()