Skip to content

Commit

Permalink
added calibration state
Browse files Browse the repository at this point in the history
  • Loading branch information
arnobaer committed Dec 15, 2022
1 parent 24e1bf8 commit 479a30b
Show file tree
Hide file tree
Showing 9 changed files with 232 additions and 40 deletions.
10 changes: 10 additions & 0 deletions comet/driver/generic/motion_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ def calibrate(self) -> None:
def range_measure(self) -> None:
...

@property
@abstractmethod
def is_calibrated(self) -> bool:
...

@abstractmethod
def move_absolute(self, value: float) -> None:
...
Expand Down Expand Up @@ -55,6 +60,11 @@ def calibrate(self) -> None:
def range_measure(self) -> None:
...

@property
@abstractmethod
def is_calibrated(self) -> bool:
...

@abstractmethod
def move_absolute(self, position: Position) -> None:
...
Expand Down
26 changes: 21 additions & 5 deletions comet/driver/marzhauser/tango.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@
}


def parse_error(response: str) -> Optional[InstrumentError]:
code = int(response)
if code:
message = ERROR_MESSAGES.get(code, "unknown error")
return InstrumentError(code, message)
return None


class TangoAxis(MotionControllerAxis):

@property
Expand All @@ -66,6 +74,12 @@ def range_measure(self) -> None:
self.resource.write("!autostatus 0")
self.resource.write(f"!rm {self.name}")

@property
def is_calibrated(self) -> bool:
"""Return True if axis is calibrated and range measured."""
result = self.resource.query(f"?calst {self.name}")
return (int(result) & 0x3) == 0x3

def move_absolute(self, value: float) -> None:
self.resource.write("!autostatus 0")
self.resource.write(f"!moa {self.name} {value:.3f}")
Expand Down Expand Up @@ -97,11 +111,7 @@ def clear(self) -> None:
self.resource.write("!err") # clear error state

def next_error(self) -> Optional[InstrumentError]:
code = int(self.resource.query("?err"))
if code:
message = ERROR_MESSAGES.get(code, "unknown error")
return InstrumentError(code, message)
return None
return parse_error(self.resource.query("?err"))

def __getitem__(self, index: int) -> TangoAxis:
return TangoAxis(self.resource, index)
Expand All @@ -114,6 +124,12 @@ def range_measure(self) -> None:
self.resource.write("!autostatus 0")
self.resource.write("!rm")

@property
def is_calibrated(self) -> bool:
"""Return True if all active axes are calibrated and range measured."""
values = self.resource.query("?calst").split()
return [(int(value) & 0x3) for value in values].count(0x3) == len(values)

def move_absolute(self, position: Position) -> None:
values = " ".join([format(value, '.3f') for value in position])
self.resource.write("!autostatus 0")
Expand Down
27 changes: 22 additions & 5 deletions comet/driver/marzhauser/venus.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@
}


def parse_error(response: str) -> Optional[InstrumentError]:
code = int(response)
if code:
message = ERROR_MESSAGES.get(code, "unknown error")
return InstrumentError(code, message)
return None


class VenusAxis(MotionControllerAxis):

def calibrate(self) -> None:
Expand All @@ -60,6 +68,12 @@ def calibrate(self) -> None:
def range_measure(self) -> None:
self.resource.write(f"{self.index:d} nrm")

@property
def is_calibrated(self) -> bool:
"""Return True if axis is calibrated and range measured."""
result = self.resource.query(f"{self.index:d} getcaldone")
return int(result) == 0x3

def move_absolute(self, value: float) -> None:
self.resource.write(f"{value:.3f} {self.index:d} nmove")

Expand Down Expand Up @@ -91,11 +105,8 @@ def clear(self) -> None:
...

def next_error(self) -> Optional[InstrumentError]:
code = int(self.resource.query("geterror"))
if code:
message = ERROR_MESSAGES.get(code, "unknown error")
return InstrumentError(code, message)
return None
response = self.resource.query("geterror")
return parse_error(response)

def __getitem__(self, index: int) -> VenusAxis:
return VenusAxis(self.resource, index)
Expand All @@ -106,6 +117,12 @@ def calibrate(self) -> None:
def range_measure(self) -> None:
self.resource.write("rm")

@property
def is_calibrated(self) -> bool:
"""Return True if all active axes are calibrated and range measured."""
values = self.resource.query(f"getcaldone").split()
return [int(value) for value in values].count(0x3) == len(values)

def move_absolute(self, position: Position) -> None:
values = " ".join([format(value, '.3f') for value in position])
self.resource.write(f"{values} move")
Expand Down
27 changes: 22 additions & 5 deletions comet/driver/smc/corvus.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@
}


def parse_error(response: str) -> Optional[InstrumentError]:
code = int(response)
if code:
message = ERROR_MESSAGES.get(code, "unknown error")
return InstrumentError(code, message)
return None


class CorvusAxis(MotionControllerAxis):

def calibrate(self) -> None:
Expand All @@ -31,6 +39,12 @@ def calibrate(self) -> None:
def range_measure(self) -> None:
self.resource.write(f"{self.index:d} nrm")

@property
def is_calibrated(self) -> bool:
"""Return True if axis is calibrated and range measured."""
result = self.resource.query(f"{self.index:d} getcaldone")
return int(result) == 0x3

def move_absolute(self, value: float) -> None:
self.resource.write(f"{value:.3f} {self.index:d} nmove")

Expand Down Expand Up @@ -60,11 +74,8 @@ def clear(self) -> None:
...

def next_error(self) -> Optional[InstrumentError]:
code = int(self.resource.query("geterror"))
if code:
message = ERROR_MESSAGES.get(code, "unknown error")
return InstrumentError(code, message)
return None
response = self.resource.query("geterror")
return parse_error(response)

def __getitem__(self, index: int) -> CorvusAxis:
return CorvusAxis(self.resource, index)
Expand All @@ -75,6 +86,12 @@ def calibrate(self) -> None:
def range_measure(self) -> None:
self.resource.write("rm")

@property
def is_calibrated(self) -> bool:
"""Return True if all active axes are calibrated and range measured."""
values = self.resource.query(f"getcaldone").split()
return [int(value) for value in values].count(0x3) == len(values)

def move_absolute(self, position: Position) -> None:
values = " ".join([format(value, '.3f') for value in position])
self.resource.write(f"{values} move")
Expand Down
120 changes: 98 additions & 22 deletions comet/emulator/marzhauser/tango.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,74 +16,150 @@ def __init__(self):
self.calst = {"x": 3, "y": 3, "z": 3}
self.statusaxis = {"x": "@", "y": "@", "z": "@"}
self.velocity = {"x": 10.0, "y": 10.0, "z": 10.0}
self.autostatus = True

# Controller informations

@message(r'\??version')
@message(r'^\??version$')
def get_version(self):
return type(self).version_string

@message(r'\??err')
@message(r'^\?autostatus$')
def get_autostatus(self):
return f"{self.autostatus:d}"

@message(r'^\!autostatus (0|1)$')
def set_autostatus(self, value):
self.autostatus = {"0": False, "1": True}[value]

@message(r'^\??err$')
def get_error(self):
return "0"

# Calibration

@message(r'^\!?cal$')
def set_cal(self):
self.calst["x"] |= 0x1
self.calst["y"] |= 0x1
self.calst["z"] |= 0x1
if self.autostatus:
return "AAA-."

@message(r'^\!?cal (x|y|z)$')
def set_cal_xyz(self, axes):
self.calst[axes] |= 0x1
if self.autostatus:
return "A"

@message(r'^\!?rm$')
def set_rm(self):
self.calst["x"] |= 0x2
self.calst["y"] |= 0x2
self.calst["z"] |= 0x2
if self.autostatus:
return "DDD-."

@message(r'^\!?rm (x|y|z)$')
def set_rm_xyz(self, axes):
self.calst[axes] &= 0x1
if self.autostatus:
return "D"

@message(r'^\??calst$')
def get_calst(self):
x = self.calst.get("x", 0)
y = self.calst.get("y", 0)
z = self.calst.get("z", 0)
return f"{x:d} {y:d} {z:d}"

@message(r'^\?calst (x|y|z)$')
def get_calst_xyz(self, axis):
value = self.calst.get(axis, 0)
return f"{value:d}"

# Positioning

@message(r'\?pos')
@message(r'^\?pos$')
def get_pos(self):
x = self.position.get("x")
y = self.position.get("y")
z = self.position.get("z")
x = self.position.get("x", 0)
y = self.position.get("y", 0)
z = self.position.get("z", 0)
return f"{x:.3f} {y:.3f} {z:.3f}"

@message(r'\?pos (x|y|z)')
@message(r'^\?pos (x|y|z)$')
def get_pos_xyz(self, axis):
value = self.position.get(axis)
return f"{value:.3f}"

@message(r'^\!?moa (x|y|z) ([^\s]+)')
@message(r'^\!?moa ([^\sxyza]+) ([^\s]+) ([^\s]+)$')
def set_move_absolute(self, x, y, z):
self.position["x"] = float(x)
self.position["y"] = float(y)
self.position["z"] = float(z)
if self.autostatus:
return "@@@-."

@message(r'^\!?moa (x|y|z) ([^\s]+)$')
def set_move_absolute_xyz(self, axis, value):
self.position[axis] = float(value)
return "@@@-."
if self.autostatus:
return "@@@-."

@message(r'^\!?mor ([^\sxyza]+) ([^\s]+) ([^\s]+)$')
def set_move_relative(self, x, y, z):
self.position["x"] = float(x)
self.position["y"] = float(y)
self.position["z"] = float(z)
if self.autostatus:
return "@@@-."

@message(r'^\!?mor (x|y|z) ([^\s]+)$')
def set_move_relative_xyz(self, axis, value):
self.position[axis] = float(value)
if self.autostatus:
return "@@@-."

@message(r'^\?statusaxis (x|y|z)')
@message(r'^\?statusaxis$')
def get_statusaxis(self):
x = self.statusaxis.get("x", "-")
y = self.statusaxis.get("y", "-")
z = self.statusaxis.get("z", "-")
return f"{x}{y}{z}-.-"

@message(r'^\?statusaxis (x|y|z)$')
def get_statusaxis_xyz(self, axis):
value = self.statusaxis.get(axis, "@")
value = self.statusaxis.get(axis, "-")
return f"{value}"

@message(r'^\?calst (x|y|z)')
def get_calst_xyz(self, axis):
value = self.calst.get(axis, 0)
return f"{value:d}"

@message(r'\?vel')
@message(r'^\?vel$')
def get_vel(self):
x = self.velocity.get("x")
y = self.velocity.get("y")
z = self.velocity.get("z")
return f"{x:.3f} {y:.3f} {z:.3f}"

@message(r'\?vel (x|y|z)')
@message(r'^\?vel (x|y|z)$')
def get_vel_xyz(self, axis):
value = self.velocity.get(axis)
return f"{value:.3f}"

@message(r'^!vel (x|y|z) ([^\s]+)')
@message(r'^!vel (x|y|z) ([^\s]+)$')
def set_vel_xyz(self, axis, value):
self.velocity[axis]= float(value)
return "@@@-."

# System configuration

@message(r'save')
@message(r'^save$')
def action_save(self):
...

@message(r'restore')
@message(r'^restore$')
def action_restore(self):
...

@message(r'reset')
@message(r'^reset$')
def action_reset(self):
...

Expand Down
12 changes: 10 additions & 2 deletions tests/test_driver_marzhauser_tango.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ def test_tango():
assert instr.range_measure() is None
assert resource.buffer == ["!autostatus 0", "!rm"]

resource.buffer = ["3 3 3"]
assert instr.is_calibrated
assert resource.buffer == ["?calst"]

resource.buffer = ["3 2"]
assert not instr.is_calibrated
assert resource.buffer == ["?calst"]

resource.buffer = []
assert instr.move_absolute([2.1, 4.2]) is None
assert resource.buffer == ["!autostatus 0", "!moa 2.100 4.200"]
Expand All @@ -39,11 +47,11 @@ def test_tango():
assert instr.position == [2.1, 4.2]
assert resource.buffer == ["?pos"]

resource.buffer = ["@@M-"]
resource.buffer = ["@@M-."]
assert instr.is_moving
assert resource.buffer == ["?statusaxis"]

resource.buffer = ["@@@-"]
resource.buffer = ["@@@-."]
assert not instr.is_moving
assert resource.buffer == ["?statusaxis"]

Expand Down
Loading

0 comments on commit 479a30b

Please sign in to comment.