Source code for genericroboticarm.robo_APIs.precise_flex.pf_on_rail

"""
Implementation of RoboInterface for a PF400 on a rail.
This extends the PF400 implementation
"""
from typing import List, Tuple
from math import dist

from genericroboticarm.control.graph_manager import JointState
from genericroboticarm.robo_APIs.precise_flex import PFImplementation

MAX_Z_COORDINATE = 690.0

[docs] class PFonRail(PFImplementation): def __init__(self, start_simulating: bool = True, host: str = "10.10.0.98", port: int = 10100): super().__init__(start_simulating, host, port) self.set_metrik(self.my_dist)
[docs] @classmethod def get_name(cls) -> str: return "PFonRail"
[docs] def my_dist(self, u: JointState, v: JointState) -> float: carth_u = [u[coord] for coord in "xyz"] carth_v = [v[coord] for coord in "xyz"] #TODO: the rail coordinate gets added to the y-coordinate rail_diff = abs(u["rail"] - v["rail"]) # to avoid the slow rail movements we add that distance instead of including it in eucledean distance distance = dist(carth_u, carth_v) + rail_diff return distance
@property def joint_names(self) -> list[str]: return ["x", "y", "z", "dir", "rail", "joint2", "joint3"]
[docs] def move_relative(self, movements: List[Tuple[str, float]], **kwargs): """ we simply forbid simultaneous movements of rail and head """ move_dict = dict(movements) carth_coords = ["x", "y", "z", "dir"] rail_diff = move_dict.get("rail", 0) if any(coord in move_dict for coord in carth_coords): # use carthesian coordinates together with destC for manual movements without rail destination_str = self.socket.send_command("DestC") dest_coordinates = destination_str.split(" ")[1:7] # manipulate the destination coordinates for idx, coord in enumerate(carth_coords): diff = move_dict.get(coord, 0) curr_dest = float(dest_coordinates[idx]) new_dest = curr_dest + diff # there is a maximum height if coord == "z": new_dest = max(0., min(MAX_Z_COORDINATE, new_dest)) dest_coordinates[idx] = str(new_dest) position_str = " ".join(dest_coordinates) cmd = f"MoveC {self.move_profile} {position_str}" self.socket.send_command(cmd) elif rail_diff: # use move_joint together with DestJ for rail movements destj_str = self.socket.send_command("DestJ") curr_rail_dest_str = destj_str.split(" ")[6] new_rail_dest = float(curr_rail_dest_str) + rail_diff self.move_joint(5, new_rail_dest)
@property def current_coordinates(self) -> JointState: # internally work in joint space when on normal operation joint_position_str = self.socket.send_command("wherej") joint_positions = joint_position_str.split(' ')[1:7] carth_position_str = self.socket.send_command("wherec") carth_positions = carth_position_str.split(' ')[1:7] # the gripper is the 5th joint but should not be included in movements joint_state = dict( x=float(carth_positions[0]), y=float(carth_positions[1]), z=float(joint_positions[0]), dir=float(joint_positions[3]), rail=float(joint_positions[5]), joint2=float(joint_positions[1]), joint3=float(joint_positions[2]), ) return joint_state
[docs] def move_to_coordinates(self, coords: JointState, **kwargs) -> None: destj_str = self.socket.send_command("DestJ") gripper_pos = destj_str.split()[5] # 5th joint and one buffer number # we move in the joint space target_pos = [coords["z"], coords["joint2"], coords["joint3"], coords["dir"], gripper_pos, coords["rail"]] position_str = " ".join(str(s) for s in target_pos) cmd = f'MoveJ {self.move_profile} {position_str}' self.socket.send_command(cmd)