This commit is contained in:
gac-S_Changer
2018-11-07 11:36:38 +01:00
parent bc78e8fd40
commit 92574c1341
23 changed files with 749 additions and 63 deletions

View File

@@ -1,4 +1,4 @@
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
#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 reopen||-200|
monitoring_cam=ch.psi.pshell.imaging.MjpegSource|http://axis-accc8e9cc87b.psi.ch/axis-cgi/mjpg/video.cgi?camera=2 reopen||-200|
top_cam=ch.psi.pshell.imaging.MjpegSource|http://axis-accc8e9cc87b.psi.ch/axis-cgi/mjpg/video.cgi?camera=3 true||-200|

View File

@@ -1,5 +1,5 @@
#Mon Oct 15 11:33:41 CEST 2018
maxValue=1.0
#Thu Oct 25 15:44:44 CEST 2018
maxValue=0.4
minValue=0.0
offset=0.0
precision=2

View File

@@ -1,5 +1,5 @@
#Mon Oct 15 11:33:41 CEST 2018
maxValue=1.0
#Thu Oct 25 15:44:44 CEST 2018
maxValue=0.4
minValue=0.0
offset=0.0
precision=2

View File

@@ -1,5 +1,5 @@
#Mon Oct 15 11:33:41 CEST 2018
maxValue=1.0
#Thu Oct 25 15:44:44 CEST 2018
maxValue=0.4
minValue=0.0
offset=0.0
precision=2

View File

@@ -1,6 +1,8 @@
#Wed Oct 17 16:51:06 CEST 2018
#Thu Oct 25 16:47:21 CEST 2018
holdingCurrent=30.0
mountCurrent=10.0
remanenceCurrent=-10.0
restingCurrent=10.0
reverseCurrent=-10.0
reverseTime=0.4
unmountCurrent=10.0

View File

@@ -0,0 +1,369 @@
import threading
import time
import sys
import requests
import json
try:
from urllib import quote # Python 2
except ImportError:
from urllib.parse import quote # Python 3
try:
from sseclient import SSEClient
except:
SSEClient = None
class PShellClient:
def __init__(self, url):
self.url = url
self.sse_event_loop_thread = None
self.subscribed_events = None
self.event_callback = None
def _get_response(self, response, is_json=True):
if response.status_code != 200:
raise Exception(response.text)
return json.loads(response.text) if is_json else response.text
def _get_binary_response(self, response):
if response.status_code != 200:
raise Exception(response.text)
return response.raw.read()
def get_version(self):
"""Return application version.
Args:
Returns:
String with application version.
"""
return self._get_response(requests.get(url=self.url+"/version"), False)
def get_config(self):
"""Return application configuration.
Args:
Returns:
Dictionary.
"""
return self._get_response(requests.get(url=self.url+"/config"))
def get_state(self):
"""Return application state.
Args:
Returns:
String: Invalid, Initializing,Ready, Paused, Busy, Disabled, Closing, Fault, Offline
"""
return self._get_response(requests.get(url=self.url+"/state"))
def get_logs(self):
"""Return application logs.
Args:
Returns:
List of logs.
Format of each log: [date, time, origin, level, description]
"""
return self._get_response(requests.get(url=self.url+"/logs"))
def get_history(self, index):
"""Access console command history.
Args:
index(int): Index of history entry (0 is the most recent)
Returns:
History entry
"""
return self._get_response(requests.get(url=self.url+"/history/"+str(index)), False)
def get_script(self, path):
"""Return script.
Args:
path(str): Script path (absolute or relative to script folder)
Returns:
String with file contents.
"""
return self._get_response(requests.get(url=self.url+"/script/"+str(path)), False)
def get_devices(self):
"""Return global devices.
Args:
Returns:
List of devices.
Format of each device record: [name, type, state, value, age]
"""
return self._get_response(requests.get(url=self.url+"/devices"))
def abort(self, command_id=None):
"""Abort execution of command
Args:
command_id(optional, int): id of the command to be aborted.
if None (default), aborts the foreground execution.
Returns:
"""
if command_id is None:
requests.get(url=self.url+"/abort")
else:
return requests.get(url=self.url+"/abort/"+str(command_id))
def reinit(self):
"""Reinitialize the software.
Args:
Returns:
"""
requests.get(url=self.url+"/reinit")
def stop(self):
"""Stop all devices implementing the 'Stoppable' interface.
Args:
Returns:
"""
requests.get(url=self.url+"/stop")
def update(self):
"""Update all global devices.
Args:
Returns:
"""
requests.get(url=self.url+"/update")
def eval(self,statement):
"""Evaluates a statement in the interpreter.
If the statement finishes by '&', it is executed in background.
Otherwise statement is executed in foreground (exclusive).
Args:
statement(str): input statement
Returns:
String containing the console return.
If an exception is produces in the interpretor, it is re-thrown here.
"""
statement = quote(statement)
return self._get_response(requests.get(url=self.url+"/eval/"+statement), False)
def run(self,script, pars=None, background=False):
"""Executes script in the interpreter.
Args:
script(str): name of the script (absolute or relative to the script base folder). Extension may be omitted.
pars(optional, list or dict): if a list is given, it sets sys.argv for the script.
If a dict is given, it sets global variable for the script.
background(optional, bool): if True script is executed in background.
Returns:
Return value of the script.
If an exception is produces in the interpretor, it is re-thrown here.
"""
return self._get_response(requests.put(url=self.url+"/run", json={"script":script, "pars":pars, "background":background, "async":False }))
def start_eval(self,statement):
"""Starts evaluation of a statement in the interpreter.
If the statement finishes by '&', it is executed in background.
Otherwise statement is executed in foreground (exclusive).
Args:
statement(str): input statement
Returns:
Command id (int), which is used to retrieve command execution status/result (get_result).
"""
statement = quote(statement)
return int(self._get_response(requests.get(url=self.url+"/evalAsync/"+statement), False))
def start_run(self,script, pars=None, background=False):
"""Starts execution of a script in the interpreter.
Args:
script(str): name of the script (absolute or relative to the script base folder). Extension may be omitted.
pars(optional, list or dict): if a list is given, it sets sys.argv for the script.
If a dict is given, it sets global variable for the script.
background(optional, bool): if True script is executed in background.
Returns:
Command id (int), which is used to retrieve command execution status/result (get_result).
"""
return int(self._get_response(requests.put(url=self.url+"/run", json={"script":script, "pars":pars, "background":background, "async":True })))
def get_result(self, command_id=-1):
"""Gets status/result of a command executed asynchronously (start_eval and start_run).
Args:
command_id(optional, int): command id. If equals to -1 (default) return status/result of the foreground task.
Returns:
Dictionary with the fields: 'id' (int): command id
'status' (str): unlaunched, invalid, removed, running, aborted, failed or completed.
'exception' (str): if status equals 'failed', holds exception string.
'return' (obj): if status equals 'completed', holds return value of script (start_run)
or console return (start_eval)
"""
return self._get_response(requests.get(url=self.url+"/result/"+str(command_id)))
def help(self, input = "<builtins>"):
"""Returns help or auto-completion strings.
Args:
input(optional, str): - ":" for control commands
- "<builtins>" for builtin functions
- "devices" for device names
- builtin function name for function help
- else contains entry for auto-completion
Returns:
List
"""
return self._get_response(requests.get(url=self.url+"/autocompletion/" + input))
def get_contents(self, path=None):
"""Returns contents of data path.
Args:
path(optional, str): Path to data relative to data home path.
- Folder
- File
- File (data root) | internal path
- internal path (on currently open data root)
Returns:
List of contents
"""
return self._get_response(requests.get(url=self.url+ "/contents" + ("" if path is None else ( "/"+path))), False)
def get_data(self, path, type="txt"):
"""Returns data on a given path.
Args:
path(str): Path to data relative to data home path.
- File (data root) | internal path
- internal path (on currently open data root)
type(optional, str): txt, "json", "bin", "bs"
Returns:
Data accordind to selected format/.
"""
if type == "json":
return self._get_response(requests.get(url=self.url+ "/data-json/"+path), True)
elif type == "bin":
return self._get_binary_response(requests.get(url=self.url+"/data-bin/"+path, stream=True))
elif type == "bs":
from collections import OrderedDict
bs = self._get_binary_response(requests.get(url=self.url+"/data-bs/"+path, stream=True))
index=0
msg = []
for i in range(4):
size =int.from_bytes(bs[index:index+4], byteorder='big', signed=False)
index=index+4
msg.append(bs[index:index+size])
index=index+size
[main_header, data_header, data, timestamp] = msg
main_header = json.loads(main_header, object_pairs_hook=OrderedDict)
data_header = json.loads(data_header, object_pairs_hook=OrderedDict)
channel = data_header["channels"][0]
channel["encoding"] = "<" if channel.get("encoding", "little") else ">"
from bsread.data.helpers import get_channel_reader
channel_value_reader = get_channel_reader(channel)
return channel_value_reader(data)
return self._get_response(requests.get(url=self.url+ "/data" + ("" if path is None else ( "/"+path))), False)
def print_logs(self):
for l in self.get_logs():
print ("%s %s %-20s %-8s %s" % tuple(l))
def print_devices(self):
for l in self.get_devices():
print ("%-16s %-32s %-10s %-32s %s" % tuple(l))
def print_help(self, input = "<builtins>"):
for l in self.help(input):
print (l)
#Events
def _sse_event_loop_task(self):
try:
while True:
try:
messages = SSEClient(self.url+"/events")
for msg in messages:
if (self.subscribed_events is None) or (msg.event in self.subscribed_events):
try:
value = json.loads(msg.data)
except:
value = str(msg.data)
self.event_callback(msg.event, value)
except IOError as e:
#print(e)
pass
except:
print("Error:", sys.exc_info()[1])
#raise
finally:
print ("Exit SSE loop task")
self.sse_event_loop_thread = None
def start_sse_event_loop_task(self, subscribed_events = None, event_callback = None):
"""
Initializes server event loop task.
Args:
subscribed_events: list of event names to substribe to. If None subscribes to all.
event_callback: callback function. If None, self.on_event is called instead.
Usage example:
def on_event(name, value):
if name == "state":
print ("State changed: ", value)
elif name == "record":
print ("Received scan record: ", value)
pc.start_sse_event_loop_task(["state", "record"], on_event)
"""
self.event_callback = event_callback if event_callback is not None else self.on_event
self.subscribed_events = subscribed_events
if SSEClient is not None:
if self.sse_event_loop_thread is None:
self.sse_event_loop_thread = threading.Thread(target=self._sse_event_loop_task, \
args = (), \
kwargs={}, \
daemon=True)
self.sse_event_loop_thread.start()
else:
raise Exception ("sseclient library is not instlled: server events are not available")
def on_event(self, name, value):
pass

167
script/client/TellClient.py Normal file
View File

@@ -0,0 +1,167 @@
from PShellClient import PShellClient
import json
import time
import sys
class TellClient(PShellClient):
def __init__(self, url):
PShellClient.__init__(self, url)
self.start_sse_event_loop_task(["state", "shell"])
self.state = self.get_state()
self.debug=False
def on_event(self, name, value):
if name == "state":
self.state = value
print ("State: ", value)
elif name == "shell":
if self.debug:
print ("> ", value)
def get_state(self):
self.state = PShellClient.get_state(self)
return self.state
def wait_ready(self):
count = 0
#Monitors event but polls every second just n case an event is missed
while (True):
if self.state != "Busy":
break
time.sleep(0.01)
count = count + 1
if count>=100:
count=0
self.get_state()
if self.state != "Ready":
raise Exception("Invalid state: " + str(self.state))
def get_samples_info(self):
return json.loads(self.eval("get_samples_info()&"))
def set_samples_info(self, info):
#c.run("data/set_samples_info", pars= [info,], background=True)
self.eval("set_samples_info(" + json.dumps(info) + ")&")
def start_cmd(self, cmd, *argv):
cmd = cmd + "("
for a in argv:
cmd = cmd + (("'" + a + "'") if type(a) is str else str(a) ) + ", "
cmd = cmd + ")"
ret = self.start_eval(cmd)
self.get_state()
return ret
def wait_cmd(self, cmd):
self.wait_ready()
result = self.get_result(cmd)
#print (result)
if result["exception"] is not None:
raise Exception(result["exception"] )
return result["return"]
def mount(self, segment, puck, sample, force=False, read_dm=False):
#return self.run("motion/mount", pars= [segment,puck, sample, force, read_dm], background=True)
return self.start_cmd("mount", segment, puck, sample, force, read_dm)
def unmount(self, segment = None, puck = None, sample = None, force=False):
return self.start_cmd("unmount", segment, puck, sample, force)
def scan_pin(self, segment, puck, sample, force=False):
return self.start_cmd("scan_pin", segment, puck, sample, force)
def scan_puck(self, segment, puck, force=False):
return self.start_cmd("scan_puck", segment, puck, force)
def dry(heat_time=30.0, speed=0.5, wait_cold = 30.0):
return self.start_cmd("dry", heat_time, speed, wait_cold)
def move_cold(self):
return self.start_cmd("move_cold")
def trash(self):
return self.start_cmd("trash")
def abort_cmd(self):
self.abort()
self.eval("robot.stop_task()&")
def get_mounted_sample(self):
ret = self.eval("get_setting('mounted_sample_position')&").strip()
return None if len(ret)==0 else ret
def get_system_check(self):
try:
ret = self.eval("system_check()&")
except Exception as ex:
return ex
return "Ok"
def get_robot_state(self):
return self.eval("robot.state&")
def get_robot_status(self):
status = self.eval("robot.take()&")
return status
def get_detected_pucks(self):
return self.eval("get_detected_pucks()&")
def print_info(self):
print ("State: " + str(self.get_state()))
print ("Mounted Sample: " + str(self.get_mounted_sample()))
print ("System Check: " + str(self.get_system_check()))
print ("Robot state: " + str(self.get_robot_state()))
print ("Robot status: " + str(self.get_robot_status()))
print ("Detected Pucks: " + str(self.get_detected_pucks()))
print ("")
if __name__ == "__main__":
tell = TellClient("http://Alexandres-MBP.psi.ch:8080")
tell.print_info()
info = [
{
"userName": "User",
"dewarName": "Dewar",
"puckName": "Puck",
"puckBarcode": "XXX0001",
"puckType": "Minispine",
"puckAddress": "",
"sampleName": "Sample",
"sampleBarcode": "YYY0001",
"samplePosition": "1",
"sampleStatus": "Present",
"sampleMountCount": "0" ,
},
]
print (tell.get_samples_info())
tell.set_samples_info(info)
print (tell.get_samples_info())
tell.abort_cmd()
cmd = tell.move_cold()
print (tell.wait_cmd(cmd))
cmd = tell.trash()
print (tell.wait_cmd(cmd))
cmd = tell.scan_pin("A", 1, 1)
print (tell.wait_cmd(cmd))
cmd = tell.scan_puck("A", 1, 1)
print (tell.wait_cmd(cmd))
cmd = tell.mount("A", 1, 1)
print (tell.wait_cmd(cmd))
print ("Mounted sample: " + str(tell.get_mounted_sample()))
cmd = tell.unmount()
print (tell.wait_cmd(cmd))
print ("Mounted sample: " + str(tell.get_mounted_sample()))

42
script/client/tell.py Normal file
View File

@@ -0,0 +1,42 @@
import sys
from TellClient import TellClient
import code
tell = TellClient("http://Alexandres-MBP.psi.ch:8080")
def info():
tell.print_info()
def help():
print ("Commands: help(), info(), mount(segment, puck, sample), unmount(), scan(segment, puck, sample=None), move_cold(), trash(), abort()\n")
def mount(segment, puck, sample):
tell.mount(segment, puck, sample, True, True)
def move_cold():
tell.mount(force=True)
def unmount():
tell.move_cold()
def trash():
tell.trash()
def abort():
tell.abort_cmd()
def scan(segment, puck, sample=None):
if sample is None:
tell.scan_pin(segment, puck, True)
else:
tell.scan_pin(segment, puck, sample, True)
info()
help()
#for line in sys.stdin:
# tell.print_info()
#print ("", end='\r> ')
code.interact(local=locals())

View File

@@ -48,8 +48,8 @@ def restore_samples_info():
set_samples_info(info)
def get_samples_info(as_json=True):
global sample_info
return json.dumps(samples_info) if as_json else samples_info
global samples_info
return json.dumps(to_list(samples_info)) if as_json else samples_info
def has_puck_datamatrix(datamatrix):
if samples_info is not None:

View File

@@ -5,15 +5,19 @@ import json
class Hexiposi(DiscretePositionerBase):
def __init__(self, name, url):
DiscretePositionerBase.__init__(self, name, ["A","B","C","D","E","F"])
self.PORT_SET=8002
self.PORT_GET=8002
if not url.startswith("http://"):
url = "http://" + url
if not url.endswith("/"):
url = url + "/"
self.url = url
if not url.endswith(":"):
url = url + ":"
self.url_set = url + str (self.PORT_SET)+ "/hexiposi/"
self.url_get = url + str (self.PORT_GET)+ "/hexiposi/"
self.moved = True
self.homing_state = State.Disabled
self.rback = self.UNKNOWN_POSITION
self.timeout = 3.0
self.offline = False
def doInitialize(self):
super(Hexiposi, self).doInitialize()
@@ -25,40 +29,46 @@ class Hexiposi(DiscretePositionerBase):
return json.loads(response.text)
def get_status(self):
self.status = self.get_response(requests.get(url=self.url+"get", timeout=self.timeout))
self.estop = self.status["estop"]
self.homed = self.status["homed"]
self.error = self.status["errorCode"]
self.remote = self.status["mode"] == "remote"
self.moving = self.status["errorCode"]
self.pos = self.status["position"]
self.moving = self.status["moving"]
self.offset = self.status["offset"]
self.dpos = self.status["discretePosition"]
if (self.homed==False): rback = self.UNKNOWN_POSITION
elif self.dpos == 1: rback = "A"
elif self.dpos == 2: rback = "B"
elif self.dpos == 4: rback = "C"
elif self.dpos == 8: rback = "D"
elif self.dpos == 16: rback = "E"
elif self.dpos == 32: rback = "F"
else: rback = self.UNKNOWN_POSITION
if (rback == self.UNKNOWN_POSITION) or (rback != self.rback):
self.moved = True
self.rback = rback
return self.status
try:
self.status = self.get_response(requests.get(url=self.url_get+"get", timeout=self.timeout))
self.estop = self.status["estop"]
self.homed = self.status["homed"]
self.error = self.status["errorCode"]
self.remote = self.status["mode"] == "remote"
self.moving = self.status["errorCode"]
self.pos = self.status["position"]
self.moving = self.status["moving"]
self.offset = self.status["offset"]
self.dpos = self.status["discretePosition"]
if (self.homed==False): rback = self.UNKNOWN_POSITION
elif self.dpos == 1: rback = "A"
elif self.dpos == 2: rback = "B"
elif self.dpos == 4: rback = "C"
elif self.dpos == 8: rback = "D"
elif self.dpos == 16: rback = "E"
elif self.dpos == 32: rback = "F"
else: rback = self.UNKNOWN_POSITION
if (rback == self.UNKNOWN_POSITION) or (rback != self.rback):
self.moved = True
self.rback = rback
self.offline = False
return self.status
except:
self.offline = True
self.updateState()
raise
def set_deadband(self, value = 0.1): #degrees
ret = self.get_response(requests.get(url=self.url+"setDeadband?deadband=" + str(value), timeout=self.timeout))
ret = self.get_response(requests.get(url=self.url_set+"setDeadband?deadband=" + str(value), timeout=self.timeout))
if ret["deadbandOutput"] == value:
return value
raise Excepiton("Error setting deadband: " + str(ret))
def move_pos(self, pos):
return self.get_response(requests.get(url=self.url+"set?pos=" + str(pos), timeout=self.timeout))
return self.get_response(requests.get(url=self.url_set+"set?pos=" + str(pos), timeout=self.timeout))
def move_home(self):
ret = self.get_response(requests.get(url=self.url+"set?home=1", timeout=self.timeout))
ret = self.get_response(requests.get(url=self.url_set+"set?home=1", timeout=self.timeout))
try:
self.waitState(self.homing_state,1200)
except:
@@ -66,10 +76,10 @@ class Hexiposi(DiscretePositionerBase):
return ret
def stop_move(self):
return self.get_response(requests.get(url=self.url+"set?stop=1", timeout=self.timeout))
return self.get_response(requests.get(url=self.url_set+"set?stop=1", timeout=self.timeout))
def set_offset(self, offset):
return self.get_response(requests.get(url=self.url+"setOffset?offset="+str(offset), timeout=self.timeout))
return self.get_response(requests.get(url=self.url_set+"setOffset?offset="+str(offset), timeout=self.timeout))
def doUpdate(self):
self.get_status()
@@ -124,7 +134,9 @@ class Hexiposi(DiscretePositionerBase):
# return self.moving == False
def updateState(self):
if self.homed == False:
if self.offline:
self.setState(State.Offline)
elif self.homed == False:
self.setState(self.homing_state)
elif self.moving:
self.setState(State.Busy)
@@ -133,8 +145,8 @@ class Hexiposi(DiscretePositionerBase):
#http://myriotell:8002/hexiposi/get
dev = Hexiposi("hexiposi", "myriotell:8002/hexiposi")
#http://myriotell:8003/hexiposi/get
dev = Hexiposi("hexiposi", "myriotell")
add_device(dev, True)
hexiposi.polling=1000

View File

@@ -28,7 +28,8 @@ class RobotSC(RobotTCP):
RobotTCP.__init__(self, name, server, timeout, retries)
self.set_tasks(["getDewar", "putDewar", "putGonio", "getGonio", "recover", "moveDewar", "moveCold", "movePark", "moveGonio","moveHeater", "moveScanner","moveHome", "moveAux"])
self.set_known_points(["pPark", "pGonio", "pDewar", "pGonioG", "pScan", "pHeater", "pHeat", "pHeatB", "pScanStop","pHelium", "pHome", "pCold", "pAux"])
self.setPolling(DEFAULT_ROBOT_POLLING)
self.setPolling(DEFAULT_ROBOT_POLLING)
self.setSimulated()
def move_dewar(self):
self.start_task('moveDewar')

View File

@@ -141,6 +141,8 @@ class RobotTCP(TcpDevice, Stoppable):
raise Exception("Exceeded maximum message size")
self.getLogger().finer("TX = '" + str(tx)+ "'")
if (self.trailer != None): tx = tx + self.trailer
if self.isSimulated():
return ""
rx = self.sendReceive(tx, msg_id, self.trailer , 0, self.timeout if timeout is None else timeout, self.retries)
rx=rx[:-1] #Remove 0A
self.getLogger().finer("RX = '" + str(rx) + "'")
@@ -257,14 +259,20 @@ class RobotTCP(TcpDevice, Stoppable):
self.set_trsf(trsf, name+".trsf")
def eval_int(self, cmd):
if self.isSimulated():
return 0
self.evaluate("tcp_n=" + cmd)
return self.get_int()
def eval_float(self, cmd):
if self.isSimulated():
return 0.0
self.evaluate("tcp_n=" + cmd)
return self.get_float()
def eval_bool(self, cmd):
if self.isSimulated():
return False
self.evaluate("tcp_b=" + cmd)
return self.get_bool()
@@ -547,6 +555,8 @@ class RobotTCP(TcpDevice, Stoppable):
self.execute('kill', str(name), timeout=5000)
def get_task_status(self, name):
if self.isSimulated():
return (-1,"Stopped")
code = self.eval_int('taskStatus("' + str(name)+ '")')
#TODO: String assignments in $exec causes application to freeze
#status = self
@@ -575,7 +585,6 @@ class RobotTCP(TcpDevice, Stoppable):
self.check_task()
if self.current_task is not None:
print "Ongoing task: " + self.current_task
if (not self.settled) or (self.current_task is not None): self.setState(State.Busy)
elif not self.empty: self.setState(State.Paused)
else: self.setState(State.Ready)
@@ -584,12 +593,19 @@ class RobotTCP(TcpDevice, Stoppable):
try:
start = time.time()
cur_task = self.current_task #Can change in background so cache it
sts = self.execute("get_status", cur_task)
if self.isSimulated():
sts = [1, 1,"1", 100, "1", "1", 0, 0, \
0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, \
]
else:
sts = self.execute("get_status", cur_task)
self._update_working_mode(int(sts[0]), int(sts[1]))
self.powered = sts[2] == "1"
self.speed = int(sts[3])
self.empty = sts[4] == "1"
self.settled = sts[5] == "1"
#TODO: add tool open
if cur_task is not None:
if int(sts[6]) < 0:
@@ -602,14 +618,14 @@ class RobotTCP(TcpDevice, Stoppable):
self.joint_pos[i] = float(sts[8 + i])
for i in range(6):
self.cartesian_pos[i] = float(sts[14 + i])
ev_index = 20 #7
ev = sts[ev_index] if len(sts)>ev_index else ""
if len(ev.strip()) >0:
self.getLogger().info(ev)
self.on_event(ev)
self._update_state()
self._update_state()
self.reset = False
self.setCache({"powered": self.powered,
"speed": self.speed,
@@ -621,6 +637,7 @@ class RobotTCP(TcpDevice, Stoppable):
"open": self.tool_open,
"pos": self.get_current_point_cached() if self.state==State.Ready else None #TODO: make it calculated in robot by polling funtion
}, None)
if self.cartesian_motors_enabled:
for m in self.cartesian_motors:
m.readback.update()

View File

@@ -6,6 +6,8 @@ class SmartMagnet(DeviceBase):
"restingCurrent":0.0,
"mountCurrent":0.0,
"unmountCurrent":0.0,
"reverseCurrent":0.0,
"reverseTime":0.0,
}))
def doInitialize(self):
@@ -89,8 +91,8 @@ class SmartMagnet(DeviceBase):
def set_unmount_current(self):
self.set_current(self.config.getFieldValue("unmountCurrent"))
def set_remanence_current(self):
self.set_current(self.config.getFieldValue("remanenceCurrent"))
def set_reverse_current(self):
self.set_current(self.config.getFieldValue("reverseCurrent"))
def set_default_current(self):
if self.is_mounted():
@@ -104,6 +106,10 @@ class SmartMagnet(DeviceBase):
#Setting resting current to better detect sample
def enforce_sample_detection(self):
reverse_wait = float(self.config.getFieldValue("reverseTime"))
if reverse_wait >0:
self.set_reverse_current()
time.sleep(reverse_wait)
if not self.is_resting_current():
self.set_resting_current()
time.sleep(0.2)

View File

@@ -25,10 +25,10 @@ BARCODE_READER_SCAN_PUCKS = "barcode_reader_scan_pucks"
def is_imaging_enabled():
setting = get_setting(IMAGING_ENABLED_PREFERENCE)
return not (str(setting) == 'False')
return not (str(setting).lower() == 'false')
def set_imaging_enabled(value):
set_setting(IMAGING_ENABLED_PREFERENCE, True if value else False )
set_setting(IMAGING_ENABLED_PREFERENCE, (True if value else False) )
def assert_imaging_enabled():
if is_imaging_enabled() == False:
@@ -69,8 +69,9 @@ for script in ["devices/RobotSC", "devices/Wago", "devices/BarcodeReader", "devi
except:
print >> sys.stderr, traceback.format_exc()
add_device(img.getContrast(), force = True)
add_device(img.getCamera(), force = True)
if is_imaging_enabled():
add_device(img.getContrast(), force = True)
add_device(img.getCamera(), force = True)
###################################################################################################
@@ -103,8 +104,9 @@ run("motion/calibrate_tool")
run("motion/scan_pin")
run("motion/robot_recover")
run("motion/recover")
run("imgproc/Utils")
run("tools/Math")
if is_imaging_enabled():
run("imgproc/Utils")
def system_check(robot_move=True):
if not air_pressure_ok.read():
@@ -176,7 +178,8 @@ try:
except:
print >> sys.stderr, traceback.format_exc()
try:
if is_imaging_enabled():
try:
import ch.psi.pshell.device.Camera as Camera
#img.camera.setColorMode(Camera.ColorMode.Mono)
#img.camera.setDataType(Camera.DataType.UInt8)
@@ -196,7 +199,7 @@ try:
img.camera.stop()
img.camera.start()
except:
except:
print >> sys.stderr, traceback.format_exc()

View File

@@ -29,4 +29,4 @@ def calibrate_tool():
robot.put_calibration_tool()
#robot.save_program()
robot.save_program()

View File

@@ -8,7 +8,12 @@ def dry(heat_time=30.0, speed=0.5, wait_cold = 30.0):
Else move to cold and wait (in seconds) before returning.
"""
print "dry"
if robot.simulated:
time.sleep(3.0)
return
#Initial chec
robot.assert_no_task()
robot.reset_motion()

View File

@@ -22,6 +22,15 @@ def mount(segment, puck, sample, force=False, read_dm=False):
#Initial checks
assert_valid_address(segment, puck, sample)
assert_puck_detected(segment, puck)
if robot.simulated:
time.sleep(3.0)
mount_sample_detected = True
mount_sample_id = "YYY0001"
update_samples_info_sample_mount(get_puck_name(segment, puck), sample, mount_sample_detected, mount_sample_id)
set_setting("mounted_sample_position", get_sample_name(segment, puck, sample))
return [mount_sample_detected, mount_sample_id]
robot.assert_no_task()
robot.reset_motion()
robot.wait_ready()
@@ -84,8 +93,7 @@ def mount(segment, puck, sample, force=False, read_dm=False):
except:
dry_mount_count = 0
set_setting("dry_mount_counter", dry_mount_count+1)
#TODO: Auto-dry procedure
if is_aux:
robot.move_home()
else:
@@ -98,6 +106,7 @@ def mount(segment, puck, sample, force=False, read_dm=False):
raise Exception("No pin detected on gonio")
if is_force_dry():
smart_magnet.set_default_current()
print "Auto dry"
log("Starting auto dry", False)
dry()

View File

@@ -3,6 +3,10 @@ def move_cold():
"""
print "move_cold"
if robot.simulated:
time.sleep(3.0)
return
#Initial checks
robot.assert_no_task()
robot.reset_motion()

View File

@@ -2,6 +2,11 @@ def put_gonio(force=False):
"""
"""
print "put_gonio: ", force
if robot.simulated:
time.sleep(3.0)
return
#Initial checks
robot.assert_no_task()

View File

@@ -6,6 +6,10 @@ def scan_pin(segment, puck, sample, force=False):
assert_valid_address(segment, puck, sample)
assert_puck_detected(segment, puck)
is_aux = (segment == AUX_SEGMENT)
if robot.simulated:
time.sleep(0.5)
return "Present"
robot.assert_no_task()
robot.reset_motion()

View File

@@ -2,6 +2,10 @@ def trash():
"""
"""
print "trash"
if robot.simulated:
time.sleep(3.0)
return
#Initial checks
robot.assert_no_task()

View File

@@ -14,6 +14,12 @@ def unmount(segment = None, puck = None, sample = None, force=False):
#Initial checks
assert_valid_address(segment, puck, sample)
assert_puck_detected(segment, puck)
if robot.simulated:
time.sleep(3.0)
update_samples_info_sample_unmount(get_puck_name(segment, puck), sample)
set_setting("mounted_sample_position", None)
return
robot.assert_no_task()
robot.reset_motion()

30
script/test/TestCalib.py Normal file
View File

@@ -0,0 +1,30 @@
print "calibrate_tool"
#Initial checks
robot.assert_no_task()
robot.reset_motion()
robot.wait_ready()
robot.assert_cleared()
#robot.assert_in_known_point()
#Enabling
enable_motion()
(detected, dm) = move_scanner()
if detected:
print "Pin detected, trashing..."
trash()
(detected, dm) = move_scanner()
if detected:
raise Exception("Cannot trash pin")
robot.open_tool()
robot.get_calibration_tool()
run("calibration/ToolCalibration3")
robot.put_calibration_tool()
robot.save_program()