Source code for genericroboticarm.robo_APIs.precise_flex.imager_pf
"""
Implementation of RoboInterface extending the PF400 to the specific uppsala pf400 in the imaging room.
"""
from .pf_implementation import PFImplementation
import time
import logging
from threading import Thread
from ...control.graph_manager import JointState
[docs]
def approach_position(device: str) -> str:
approach_pos = f"{device}_approach"
logging.debug(f"Approach position to device {device} is {approach_pos}.")
return approach_pos
[docs]
def device_from_identifier(identifier: str) -> str:
device_name = identifier.split('_')[0]
logging.debug(f"{identifier} belongs to device {device_name}.")
return device_name
[docs]
class ImagerPF(PFImplementation):
origin_is_squid = False # whether a picked plate is from a squid
default_offset = dict(z=-3) # grip the lower holes
GRIPPER_OPEN = 95
[docs]
@classmethod
def get_name(cls) -> str:
return "ImagerPF"
def site_to_position_identifier(self, device, slot):
# devices with just one handover position are tagged like this
pos_identifier = f"{device}_nest"
# devices with multiple handover positions have their number attached (starting at 0)
if not self.graph_manager.position_known(pos_identifier):
pos_identifier += str(slot)
if not self.graph_manager.position_known(pos_identifier):
logging.error(f"neither {device}_nest nor {pos_identifier} are known positions")
return pos_identifier
[docs]
def move_to_coordinates(self, coords: JointState, **kwargs) -> None:
prior_profile = self.move_profile
# go slower if the next or last position is a nest or the current position is unknown
if self.speed > 10:
keywords = {"nest"}
if not self.current_position or any(
keyword in self.next_positions[0] or keyword in self.current_position
for keyword in keywords
):
self.move_profile = 1 # profile 1 implies speed = 10 (defined in pf_implementation.py)
super().move_to_coordinates(coords, **kwargs)
self.move_profile = prior_profile
[docs]
def site_to_position_identifier(self, device: str, slot: int) -> str:
# devices with just one handover position are tagged like this
pos_identifier = f"{device}_nest"
# devices with multiple handover positions have their number attached (starting at 0)
if not self.graph_manager.position_known(pos_identifier):
pos_identifier += str(slot)
if not self.graph_manager.position_known(pos_identifier):
logging.error(f"neither {device}_nest nor {pos_identifier} are known positions")
return pos_identifier
[docs]
def move_to_safe_pos(self, identifier: str, offset: dict[str, float] | None = None):
"""
Moves to the approach position belonging to the specified position
:param offset:
:param identifier:
:return:
"""
device_name = device_from_identifier(identifier)
safe_pos = approach_position(device_name)
self.move_to_position(safe_pos, offset=offset)
[docs]
def move_straight_to_position(self, identifier, offset = None):
if not offset:
offset = self.default_offset.copy()
return super().move_straight_to_position(identifier, offset)
[docs]
def move_to_position(self, target_position, offset=None):
if not offset:
offset = self.default_offset.copy()
return super().move_to_position(target_position, offset)
[docs]
def pick_at_position(self, identifier: str, offset: dict[str, float] | None=None):
self.origin_is_squid = "Squid" in identifier
if not offset:
offset = self.default_offset.copy()
# pick from the squid normally
if self.origin_is_squid:
offset["z"] = 0
super().pick_at_position(identifier, offset = offset)
self.move_to_safe_pos(identifier, offset=offset)
if not self.is_in_simulation_mode:
# wait for gripper to fully close and throw an error if no plate is there
self.finish_movement()
if self.gripper_fully_closed:
raise RuntimeError(f"Ecpected a plate at {identifier} while there was none")
[docs]
def place_at_position(self, identifier: str, offset: dict[str, float] | None = None):
if not offset:
offset = self.default_offset.copy()
# we grip a bit higher when coming from a squid, so we add an offset when placing in somewhere but another squid
if self.origin_is_squid and not "Squid" in identifier:
offset["z"] = 2
if identifier in [f"Hotel_nest{i}" for i in list(range(1,11)) + list(range(12, 19))]:
raise RuntimeError("We can not move from Squid to tight(all but 11 and 19) hotel slots.")
if "Squid" in identifier:
# do a regrip when moving to a squid from somewhere but another squid
if not self.origin_is_squid:
self.place_at_position("Hotel_nest11")
self.pick_at_position("Hotel_nest11", offset=dict(z=2))
# place normally in squids
offset["z"] = 0
super().place_at_position(identifier, offset=offset)
self.move_to_safe_pos(identifier, offset=offset)
[docs]
def prepare_for_output(self, internal_pos: int, device: str, position: int) -> bool:
safe_pos = approach_position(device)
self.move_to_position(safe_pos)
return True