This commit is contained in:
gac-S_Changer
2018-08-10 17:02:30 +02:00
parent 9ef973fa49
commit 1709e91d0d
23 changed files with 392 additions and 52 deletions

View File

@@ -1,5 +1,8 @@
img=ch.psi.pshell.prosilica.Prosilica|25001 "PacketSize=1522;PixelFormat=Mono8;BinningX=1;BinningY=1;RegionX=300;RegionY=200;Width=1000;Height=1000;MulticastEnable=Off"|||false
gripper_cam=ch.psi.pshell.imaging.MjpegSource|http://axis-accc8e9cc87b.psi.ch/axis-cgi/mjpg/video.cgi?camera=1||-1|
monitoring_cam=ch.psi.pshell.imaging.MjpegSource|http://axis-accc8e9cc87b.psi.ch/axis-cgi/mjpg/video.cgi?camera=2||-1|
top_cam=ch.psi.pshell.imaging.MjpegSource|http://axis-accc8e9cc87b.psi.ch/axis-cgi/mjpg/video.cgi?camera=3||-1|
#cam=ch.psi.pshell.epics.AreaDetector|MX-SAMCAM|||
microscan=ch.psi.pshell.serial.TcpDevice|MicroHAWK38C528:2001|||
microscan_cmd=ch.psi.pshell.serial.TcpDevice|MicroHAWK38C528:2003|||
ue=LaserUE|COM4|||false
@@ -19,7 +22,6 @@ puck_detection=ch.psi.mxsc.PuckDetection|tell-raspberrypi:5556|||
#robot_req=ch.psi.pshell.modbus.AnalogOutput|robot_modbus 13|||
#robot_ack=ch.psi.pshell.modbus.AnalogInput|robot_modbus 14|||
#robot_ret=ch.psi.pshell.modbus.AnalogInputArray|robot_modbus 15 12|||
#wago_back=ch.psi.pshell.modbus.ModbusTCP|SF-TEST-WAGO1:502|||
wago=ch.psi.pshell.modbus.ModbusTCP|wago-mxsc-1:502|||
led_ok_1=ch.psi.pshell.modbus.DigitalInput|wago 0||1000|
led_ok_2=ch.psi.pshell.modbus.DigitalInput|wago 1||1000|
@@ -70,5 +72,9 @@ led_ctrl_1=ch.psi.pshell.modbus.ProcessVariable|wago 0|||
led_ctrl_2=ch.psi.pshell.modbus.ProcessVariable|wago 1|||
led_ctrl_3=ch.psi.pshell.modbus.ProcessVariable|wago 2|||
smc_current=ch.psi.pshell.modbus.ProcessVariable|wago 3|||
#cam=ch.psi.pshell.epics.AreaDetector|MX-SAMCAM|||
#img_back=ch.psi.pshell.imaging.CameraSource|cam||-100|
#fx=ch.psi.pshell.epics.Motor|SAR-EXPMX:MOT_FX|||true
#fy=ch.psi.pshell.epics.Motor|SAR-EXPMX:MOT_FY|||true
#ry=ch.psi.pshell.epics.Motor|SAR-EXPMX:MOT_ROT_Y|||true
#cz=ch.psi.pshell.epics.Motor|SAR-EXPMX:MOT_CZ|||true
#cx=ch.psi.pshell.epics.Motor|SAR-EXPMX:MOT_CX|||true

17
devices/cx.properties Normal file
View File

@@ -0,0 +1,17 @@
#Fri Aug 10 15:47:53 CEST 2018
defaultSpeed=2.0
estbilizationDelay=0
hasEnable=false
homingType=None
maxSpeed=NaN
maxValue=0.0
minSpeed=NaN
minValue=0.0
offset=0.0
precision=3
resolution=0.001
rotation=false
scale=1.0
sign_bit=0
startRetries=1
unit=mm

17
devices/cz.properties Normal file
View File

@@ -0,0 +1,17 @@
#Fri Aug 10 15:47:15 CEST 2018
defaultSpeed=2.0
estbilizationDelay=0
hasEnable=false
homingType=None
maxSpeed=NaN
maxValue=0.0
minSpeed=NaN
minValue=0.0
offset=0.0
precision=3
resolution=0.001
rotation=false
scale=1.0
sign_bit=0
startRetries=1
unit=mm

17
devices/fx.properties Normal file
View File

@@ -0,0 +1,17 @@
#Fri Aug 10 15:47:14 CEST 2018
defaultSpeed=2.0
estbilizationDelay=0
hasEnable=false
homingType=None
maxSpeed=NaN
maxValue=0.0
minSpeed=NaN
minValue=0.0
offset=0.0
precision=3
resolution=0.001
rotation=false
scale=1.0
sign_bit=0
startRetries=1
unit=mm

17
devices/fy.properties Normal file
View File

@@ -0,0 +1,17 @@
#Fri Aug 10 15:47:14 CEST 2018
defaultSpeed=2.0
estbilizationDelay=0
hasEnable=false
homingType=None
maxSpeed=NaN
maxValue=0.0
minSpeed=NaN
minValue=0.0
offset=0.0
precision=3
resolution=0.001
rotation=false
scale=1.0
sign_bit=0
startRetries=1
unit=mm

View File

@@ -1,4 +1,4 @@
#Wed Aug 08 11:53:16 CEST 2018
#Fri Aug 10 15:19:19 CEST 2018
colormap=Grayscale
colormapAutomatic=false
colormapMax=18.133
@@ -9,16 +9,16 @@ grayscale=false
invert=false
rescaleFactor=1.0
rescaleOffset=0.0
roiHeight=-1
roiWidth=-1
roiX=0
roiY=0
rotation=0.0
roiHeight=972
roiWidth=972
roiX=12
roiY=15
rotation=229.8340828443476
rotationCrop=true
scale=1.0
spatialCalOffsetX=NaN
spatialCalOffsetY=NaN
spatialCalScaleX=NaN
spatialCalScaleY=NaN
spatialCalOffsetX=-486.0
spatialCalOffsetY=-486.0
spatialCalScaleX=0.48315133165771174
spatialCalScaleY=0.48314848201202937
spatialCalUnits=mm
transpose=false

View File

@@ -0,0 +1,20 @@
#Thu Aug 09 11:01:09 CEST 2018
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

17
devices/ry.properties Normal file
View File

@@ -0,0 +1,17 @@
#Fri Aug 10 15:47:14 CEST 2018
defaultSpeed=50.0
estbilizationDelay=0
hasEnable=false
homingType=None
maxSpeed=NaN
maxValue=0.0
minSpeed=NaN
minValue=0.0
offset=0.0
precision=3
resolution=0.001
rotation=false
scale=1.0
sign_bit=0
startRetries=1
unit=deg

View File

@@ -0,0 +1,20 @@
#Thu Aug 09 11:46:12 CEST 2018
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

Binary file not shown.

View File

@@ -2,6 +2,7 @@
* Copyright (c) 2014-2017 Paul Scherrer Institute. All rights reserved.
*/
import ch.psi.pshell.device.Device;
import ch.psi.pshell.ui.Panel;
import ch.psi.utils.State;
import ch.psi.utils.swing.SwingUtils;
@@ -42,24 +43,32 @@ public class Recovery extends Panel {
@Override
protected void onTimer() {
try{
List segment = (List) eval("get_current_segment()", true);
ledValidSegment.setColor((segment == null) ? Color.RED : Color.GREEN);
textSegment.setText((segment == null) ? "": segment.get(0) + "->" + segment.get(1) + " [" + segment.get(2) + "mm]");
} catch (Exception ex) {
System.out.println(ex);
Device robot = getContext().getDevicePool().getByName("robot", Device.class);
if (!robot.getState().isNormal()){
ledValidSegment.setColor(Color.BLACK);
textSegment.setText("");
}
try{
String point = (String) eval("robot.get_current_point()", true);
ledKnownPosition.setColor((point == null) ? Color.RED : Color.GREEN);
textPosition.setText((point == null) ? "": point);
} catch (Exception ex) {
System.out.println(ex);
textSegment.setText("");
ledKnownPosition.setColor(Color.BLACK);
textPosition.setText("");
}
} else {
try{
List segment = (List) eval("get_current_segment()", true);
ledValidSegment.setColor((segment == null) ? Color.RED : Color.GREEN);
textSegment.setText((segment == null) ? "": segment.get(0) + "->" + segment.get(1) + " [" + segment.get(2) + "mm]");
} catch (Exception ex) {
System.out.println(ex);
ledValidSegment.setColor(Color.BLACK);
textSegment.setText("");
}
try{
String point = (String) eval("robot.get_current_point()", true);
ledKnownPosition.setColor((point == null) ? Color.RED : Color.GREEN);
textPosition.setText((point == null) ? "": point);
} catch (Exception ex) {
System.out.println(ex);
ledKnownPosition.setColor(Color.BLACK);
textPosition.setText("");
}
}
updateButton();
}

37
script/devices/Gonio.py Normal file
View File

@@ -0,0 +1,37 @@
def home_fast_table():
caput ("SAR-EXPMX:ASYN.AOUT", "enable plc 1")
def get_fx_pos():
return caget("SAR-EXPMX:MOT_FX.RBV", 'f')
def set_fx_pos(pos):
return caput("SAR-EXPMX:MOT_FX.VAL", float(pos))
def get_fy_pos():
return caget("SAR-EXPMX:MOT_FY.RBV", 'f')
def set_fy_pos(pos):
return caput("SAR-EXPMX:MOT_FY.VAL", float(pos))
def get_ry_pos():
return caget("SAR-EXPMX:MOT_ROT_Y.RBV", 'f')
def set_ry_pos(pos):
return caput("SAR-EXPMX:MOT_ROT_Y.VAL", float(pos))
def get_cz_pos():
return caget("SAR-EXPMX:MOT_CZ.RBV", 'f')
def set_cz_pos(pos):
return caput("SAR-EXPMX:MOT_CZ.VAL", float(pos))
def get_cx_pos():
return caget("SAR-EXPMX:MOT_CX.RBV", 'f')
def set_cx_pos(pos):
return caput("SAR-EXPMX:MOT_CX.VAL", float(pos))

View File

@@ -95,10 +95,16 @@ class Hexiposi(DiscretePositionerBase):
self.move_pos(self.val)
#Workaround as state does not changes immediatelly
if moving:
try:
self.waitState(State.Busy,1200)
except:
pass
#try:
# self.waitState(State.Busy,1200)
#except:
# print sys.exc_info()[1]
start = time.time()
while self.state != State.Busy:
if time.time() - start > 1.5:
print "Timeout waiting Hexiposi busy"
break
self.update()
def is_in_position(self, pos):
return take() == pos
@@ -131,7 +137,7 @@ class Hexiposi(DiscretePositionerBase):
dev = Hexiposi("hexiposi", "myriotell:8002/hexiposi")
add_device(dev, True)
hexiposi.polling=500
hexiposi.polling=1000
#print dev.url
#print dev.get_status()
@@ -144,4 +150,4 @@ class hexiposi_position(ReadonlyRegisterBase):
add_device(hexiposi_position(), True)
hexiposi_position.polling = 1000
hexiposi.set_deadband(0.5)

View File

@@ -112,6 +112,8 @@ def release_psys():
"""
Release psys safety
"""
if is_manual_mode():
raise Exception ("Cannot release PSYS in manual mode")
release_psys_safety.write(False)
time.sleep(0.01)
release_psys_safety.write(True)

View File

@@ -2,6 +2,9 @@ import ch.psi.pshell.device.Camera as Camera
import ch.psi.pshell.imaging.RendererMode as RendererMode
import ch.psi.pshell.imaging.Calibration as Calibration
from ch.psi.pshell.imaging.Overlays import *
import ch.psi.utils.swing.SwingUtils as SwingUtils
import javax.swing.SwingUtilities as SwingUtilities
from swingutils.threads.swing import callSwing
#SIMULATION = ch.psi.pshell.imaging.FileSource
"""
img.camera.setColorMode(Camera.ColorMode.Mono)
@@ -15,9 +18,10 @@ img.config.rotationCrop=True
"""
MOVE_HEXIPOSI = True
ROTATION_OFFSET = 180.0
if MOVE_HEXIPOSI:
enable_motion()
release_safety() #enable_motion()
sensor_width,sensor_height = img.camera.getSensorSize()
img.camera.setROI(0, 0,sensor_width, sensor_height)
@@ -29,11 +33,17 @@ img.camera.start()
p = show_panel(img)
dlg = SwingUtilities.getWindowAncestor(p)
dlg.setSize(800,800)
frm=SwingUtils.getFrame(p)
dlg.setLocationRelativeTo(frm)
p.setMode(RendererMode.Fit)
ov_text = Text(Pen(java.awt.Color.GREEN.darker()), "", java.awt.Font("Verdana", java.awt.Font.PLAIN, 24), java.awt.Point(20,20))
ov_text.setFixed(True)
p.addOverlay(ov_text)
try:
#Find image center and Prosilica ROI
ov_text.update("Click on the center of the Dewar...")
@@ -130,10 +140,12 @@ try:
print a, sx, sy, roi_w, roi_h
img.config.rotation=-a
img.config.rotation=-a + ROTATION_OFFSET
img.config.roiX,img.config.roiY, img.config.roiWidth,img.config.roiHeight = roi_x, roi_y, roi_w, roi_h
img.config.setCalibration(Calibration(sx, sy, -roi_w/2, -roi_h/2))
img.config.save()
set_return ("Success calibrating the camera")
finally:
set_led_state(False)

View File

@@ -6,11 +6,15 @@
FRAMES_INTEGRATION = 3
STEP_SIZE = 2
POSITION_NAMES = [ 'A','B','C','D', 'E', 'F']
POSITION_ANGLES = [330, 30, 90, 150, 210, 270]
#POSITION_ANGLES = [ 330, 30, 90, 150, 210, 270 ]
POSITION_ANGLES = [ 0, 60, 120, 180, 240, 300 ]
POSITION_TOLERANCE = 3
MINIMUM_CONFIDENCE = 10
MINIMUM_CONFIDENCE = 3
DEBUG = cover_detection_debug
REFERENCE_IMG = "ref2"
#REFERENCE_IMG = "ref2"
REFERENCE_IMG = "ref1"
BORDER = 7
#Load reference image
ref = load_image(str("{images}/cover/" + REFERENCE_IMG + ".png") , title="Line")
@@ -23,9 +27,16 @@ smooth(ip)
#bandpass_filter(ip, 30, 1000)
edges(ip)
auto_threshold(ip, method = "MaxEntropy")
#binary_erode(ip, False)
#binary_dilate(ip, True)
ip.getProcessor().erode(1, 255)
cx,cy = int(ip.width/2), int(ip.height/2)
ip = sub_image(ip, cx-ref.width/2, cy-ref.height/2, ref.width, ref.height)
if BORDER>0:
sip = sub_image(ip, BORDER,BORDER, ref.width-2*BORDER, ref.height-2*BORDER)
ip = pad_image(sip, BORDER, BORDER, BORDER, BORDER, fill_color=Color.WHITE)
#Show ROI of pre-processed image
if DEBUG:
image_panel = show_panel(ip.bufferedImage)
@@ -49,6 +60,14 @@ for i in xdata:
peaks = estimate_peak_indexes(ydata, xdata, (min(ydata) + max(ydata))/2, 25.0)
peaks_x = map(lambda x:xdata[x], peaks)
peaks_y = map(lambda x:ydata[x], peaks)
if len(peaks_x) > 1:
#remoce close peaks between 350 deg and 10 deg
if ((peaks_x[0]<10) and (peaks_x[1]>350)) or ((peaks_x[1]<10) and (peaks_x[0]>350)):
peaks.pop(1)
peaks_x.pop(1)
peaks_y.pop(1)
confidence = None if len(peaks_x)<2 else int(((float(peaks_y[0])/peaks_y[1])-1) * 1000)
angle = (None if len(peaks_x)==0 else peaks_x[0])

View File

@@ -0,0 +1,40 @@
#Parameters
FRAMES_INTEGRATION = 3
MINIMUM_CONFIDENCE = 10
DEBUG = cover_detection_debug
REFERENCE_IMG = "ref1"
ERODE_ITERATIONS = 2
#Load reference image
SIZE = [128,128]
BORDER = 7
hexiposi.move("A")
#Pre-process camera image
#ip = load_image("{images}/cover/Cover_000" + str(index) + ".png", title="Img")
ip = integrate_frames(FRAMES_INTEGRATION)
ip = grayscale(ip, True)
smooth(ip)
#bandpass_filter(ip, 30, 1000)
edges(ip)
auto_threshold(ip, method = "MaxEntropy")
#binary_dilate(ip, True, 2)
for i in range(ERODE_ITERATIONS):
ip.getProcessor().erode(1, 255)
cx,cy = int(ip.width/2), int(ip.height/2)
ip = sub_image(ip, cx-SIZE[0]/2, cy-SIZE[1]/2, SIZE[0], SIZE[1])
invert(ip)
ip = grayscale(ip, True)
#smooth(ip)
if BORDER > 0:
sip = sub_image(ip, BORDER,BORDER, SIZE[0]-2*BORDER, SIZE[1]-2*BORDER)
ip = pad_image(sip, BORDER, BORDER, BORDER, BORDER)
if DEBUG:
image_panel = show_panel(ip.bufferedImage)
save_image(ip, str("{images}/cover/" + REFERENCE_IMG + ".png") ,"png")

View File

@@ -16,7 +16,7 @@ run("setup/Layout")
###################################################################################################
for script in ["devices/RobotSC", "devices/Wago", "devices/BarcodeReader", "devices/LaserDistance", \
"devices/LedCtrl", "devices/SmartMagnet", "devices/HexiPosi"]:
"devices/LedCtrl", "devices/SmartMagnet", "devices/HexiPosi", "devices/Gonio"]:
try:
run(script)
except:
@@ -71,7 +71,7 @@ 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 get_puck_detection(segment, puck) != "Present":
if get_puck_elect_detection(segment, puck) != "Present":
raise Exception ("Puck " + str(segment).upper() + str(puck) + " not present")
@@ -122,7 +122,7 @@ try:
#img.camera.setDataType(Camera.DataType.UInt8)
img.camera.setGrabMode(Camera.GrabMode.Continuous)
img.camera.setTriggerMode(Camera.TriggerMode.Fixed_Rate)
img.camera.setExposure(50.00)
img.camera.setExposure(25.00)
img.camera.setAcquirePeriod(200.00)
img.camera.setGain(0.0)
#img.camera.setROI(200, 0,1200,1200)

View File

@@ -1,10 +1,21 @@
POSITION_TOLERANCE = 50
def enable_motion():
def is_manual_mode():
"""
Check safety and enable arm power if in remote mode
return if operating in local mode. TODO: should be based on IO, not on robot flag.
"""
return robot.working_mode == "manual"
def release_safety():
"""
auto = robot.working_mode != "manual"
Release sefety signals acording to working mode
"""
if air_pressure_ok.take() != True:
raise Exception("Cannot release safety: air preassure not ok")
if n2_pressure_ok.take() != True:
raise Exception("Cannot release safety: n2 pressure not ok")
auto = not is_manual_mode()
if auto:
if feedback_psys_safety.read() == False:
release_psys()
@@ -18,6 +29,12 @@ def enable_motion():
if feedback_local_safety.read() == False:
raise Exception("Cannot enable power: check sample changer emergency stop button")
def enable_motion():
"""
Check safety and enable arm power if in remote mode
"""
release_safety()
auto = not is_manual_mode()
if auto:
if not robot.state.isNormal():
raise Exception("Cannot enable power: robot state is " + str(robot.state))
@@ -31,7 +48,7 @@ def set_hexiposi(pos, force = False):
if hexiposi.position == pos:
return
if robot.working_mode == "manual":
if is_manual_mode():
set_status("Move Hexiposi to position " + str(pos) + " ...")
try:
hexiposi.waitInPosition(pos, -1)
@@ -48,7 +65,7 @@ def _set_hexiposi(pos):
def visual_check_hexiposi(segment):
#if robot.working_mode == "manual" ?
#if is_manual_mode(): ?
if hexiposi.moved:
#Clearing for image processing
if not robot.is_park():

View File

@@ -12,18 +12,22 @@ class Contrast(Readable):
def read(self):
data = img.getData()
#roi = Data(data.getRectSelection(500,300,700,600), False)
return data.getGradientVariance(False, Rectangle(480,0,600,670))
#return data.getGradientVariance(False, Rectangle(480,0,600,670))
return data.getGradientVariance(False, None)
contrast=Contrast()
#a= lscan(exposure,img.getContrast(), 0.5, 1.0, 0.01, 0.5)
#a= lscan(exposure,contrast, 0.2, 0.4, 0.01, 0.7)
a= lscan(exposure,contrast, 10.0, 250.0, 10.0, 0.7)
(n, m, s) = fit(a.getReadable(0), xdata=a.getPositions(0))
if m is None:
m=max(a.getReadable(0))
ret= lscan(exposure,contrast, 10.0, 150.0, 5.0, 0.5)
y, x = ret.getReadable(0), ret.getPositions(0)
#(n, m, s) = fit(a.getReadable(0), xdata=a.getPositions(0))
#if m is None:
# m=max(a.getReadable(0))
m=x[y.index(max(y))]
p=get_plots()[0]
p.addMarker(m, p.AxisId.X, str(m), Color.RED)
print "Setting exposure = ", m
exposure.write(m)

View File

@@ -0,0 +1,31 @@
number_frames = 5
number_backgrounds = 5
minimum_size = 78 # r = 5 # 150
maximum_size = 750 # r = 15 #1500
min_circ = 0.2
threshold_method = "MaxEntropy"
threshold_method,threshold_range = "Manual", (0, 215)
exclude_edges = True
led_latency = 0.5 #0.1
set_led_state(False)
time.sleep(led_latency)
img.waitNext(2000)
background = average_frames(number_backgrounds)
#background = integrate_frames(number_backgrounds)
set_led_state(True)
time.sleep(led_latency)
img.waitNext(2000)
image = average_frames(number_frames)
#image = integrate_frames(number_frames)
set_led_state(False)
op_image(image, background, "subtract", float_result=True, in_place=True)
image=grayscale(image)
show_panel(image.getBufferedImage())

View File

@@ -0,0 +1,8 @@
index = 1
while(True):
for pos in ['A', 'B', 'C', 'D', 'E', 'F']:
hexiposi.move(pos)
visual_check_hexiposi(pos)
print "Ok: " + pos
print index
index = index + 1

View File

@@ -0,0 +1,24 @@
import ch.psi.pshell.imaging.RendererMode as RendererMode
import ch.psi.pshell.imaging.Calibration as Calibration
from ch.psi.pshell.imaging.Overlays import *
import ch.psi.utils.swing.SwingUtils as SwingUtils
import javax.swing.SwingUtilities as SwingUtilities
from swingutils.threads.swing import callSwing
p = show_panel(img)
dlg = SwingUtilities.getWindowAncestor(p)
dlg.setSize(800,800)
frm=SwingUtils.getFrame(p)
dlg.setLocationRelativeTo(frm)
def update_frame(frm):
SwingUtilities.updateComponentTreeUI(frm)
frm.validate()
frm.repaint()
#$callSwing(update_frame, frm)
x=0
for i in range(0,10000000):
x=x+1