from pathlib import Path import sys import time ROOT = Path(__file__).resolve().parents[1] if str(ROOT) not in sys.path: sys.path.insert(0, str(ROOT)) CLOSE_SCISSORS_ON_PICK = True # Fill these before running: [x, y, z, roll, pitch, yaw] PRE_PICK_POSE = [] PICK_POSE = [] control = None control_core = None def _load_project(): global control, control_core if control is None or control_core is None: import control as control_module import control_core as control_core_module control = control_module control_core = control_core_module return control, control_core def _checked_pose(pose, name): if ( not isinstance(pose, (list, tuple)) or len(pose) != 6 or any(not isinstance(value, (int, float)) for value in pose) ): raise ValueError(f"{name} must be [x, y, z, roll, pitch, yaw]") return [float(value) for value in pose] def _pulse_scissors(robot_name, io_index, off_index): project, _ = _load_project() project.control_tool_io(robot_name, off_index, False) project.control_tool_io(robot_name, io_index, True) time.sleep(float(project.GRIPPER_ACTION_DELAY)) project.control_tool_io(robot_name, io_index, False) def open_scissors(robot_name): _pulse_scissors(robot_name, control.GRIPPER_OPEN_IO, control.GRIPPER_CLOSE_IO) def close_scissors(robot_name): _pulse_scissors(robot_name, control.GRIPPER_CLOSE_IO, control.GRIPPER_OPEN_IO) def _move_pose_or_fail(arm, pose, reference_joints, description): joints = arm.move_pose(pose, reference_joints, description=description) if joints is None: raise RuntimeError(f"{description} failed") return joints def run_teach_pick_once(): arm = None core = None try: pre_pick_pose = _checked_pose(PRE_PICK_POSE, "PRE_PICK_POSE") pick_pose = _checked_pose(PICK_POSE, "PICK_POSE") project, core = _load_project() project._sync_config() core.reset_runtime_state() core.placement_manager.reset() arm = core.connect_robot_arm() open_scissors(arm.robot_name) if not arm.return_home(): raise RuntimeError("return Home failed") reference_joints = arm.get_joint_positions() or project.HOME_JOINTS pre_joints = _move_pose_or_fail(arm, pre_pick_pose, reference_joints, "move to pre-pick pose") pick_joints = _move_pose_or_fail(arm, pick_pose, pre_joints, "move to pick pose") delay = float(project.PICK_POINT_ARRIVAL_DELAY) if delay > 0: print(f"Arrived at pick pose, waiting {delay:.1f}s") time.sleep(delay) if CLOSE_SCISSORS_ON_PICK: close_scissors(arm.robot_name) else: print("CLOSE_SCISSORS_ON_PICK=False, skip closing scissors") _move_pose_or_fail(arm, pre_pick_pose, pick_joints, "return to pre-pick pose") if not arm.return_home(): raise RuntimeError("return Home after pick failed") place_pose, place_index = project.get_next_placement() reference_joints = arm.get_joint_positions() or project.HOME_JOINTS _move_pose_or_fail(arm, place_pose, reference_joints, f"move to place pose {place_index}") open_scissors(arm.robot_name) if not arm.return_home(): raise RuntimeError("final return Home failed") print("Teach pick flow finished") return True except Exception as exc: print(f"Teach pick flow failed: {exc}") if arm is not None: try: arm.return_home() except Exception as home_exc: print(f"Return Home during cleanup failed: {home_exc}") return False finally: if core is not None: core.release_robot_arm() def _self_test(): assert _checked_pose([1, 2, 3, 4, 5, 6], "POSE") == [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] try: _checked_pose([], "POSE") except ValueError: pass else: raise AssertionError("empty pose must fail") assert isinstance(CLOSE_SCISSORS_ON_PICK, bool) if __name__ == "__main__": if "--self-test" in sys.argv: _self_test() else: raise SystemExit(0 if run_teach_pick_once() else 1)