import signal from typing import Any, Sequence import control_core as _core """ 对外兼容入口。 这个文件主要做两件事: 1. 暴露和旧版本一致的函数名,方便 UI 或外部脚本继续调用; 2. 在真正进入核心逻辑前,把这里可修改的配置同步到 `control_core.py`。 """ # -------------------- 设备连接参数 -------------------- ROBOT_IP = "192.168.192.100" ROBOT_PORT = 30004 M_PI = _core.M_PI AGV_IP = "192.168.192.100" AGV_PORT = 30104 AGV_SPEED_FORWARD = 0 AGV_SPEED_STOP = 0.0 AGV_RUN_DISTANCE = 5.0 # -------------------- 运行时长与检测参数 -------------------- TOTAL_DURATION = 300 AGV_STOP_TIMEOUT = 10 AGV_PICK_SETTLE_DELAY = 1.0 YOLO_MODEL_PATH = "best.pt" YOLO_DETECT_CONF = 0.5 PICK_CONFIDENCE_THRESHOLD = 0.7 # -------------------- 位姿与轨迹参数 -------------------- # Home 是机械臂的初始/复位关节位。 HOME_JOINTS = [-1.5247, 1.0899, 2.4671, 1.2761, 1.5113, 0.0001] # 视觉算出的目标点会再叠加这两个偏移: # APPROACH_Y_OFFSET 用于先到预抓取点; # LIFT_Z_OFFSET 用于修正真正执行抓取时的高度。 APPROACH_Y_OFFSET = 0.15 LIFT_Z_OFFSET = 0.035 PICKUP_X_OFFSET = 0.0 PICKUP_Y_OFFSET = -0.013 PICK_ANGLE_ORIENTATION_INDEX = 4 PICK_ANGLE_SIGN = 1.0 MAX_PICK_ANGLE_DEG = 30.0 # 当前项目只使用一个放置位,仍保留列表结构以兼容 control_core。 place_positions = [[-0.6203, 0.026, 0.1078, 2.9923, 0.0366, -1.4157]] # -------------------- 夹爪与机械臂运动参数 -------------------- GRIPPER_CLOSE_IO = 1 GRIPPER_OPEN_IO = 0 GRIPPER_ACTION_DELAY = 2.0 PICK_POINT_ARRIVAL_DELAY = 1.0 SCISSORS_ENABLED = True # 这里沿用底层 SDK 的弧度制。 ARM_SPEED = 150 * (M_PI / 180) ARM_ACCEL = 120 * (M_PI / 180) # -------------------- 参数同步清单 -------------------- _CONFIG_NAMES = ( "ROBOT_IP", "ROBOT_PORT", "AGV_IP", "AGV_PORT", "AGV_SPEED_FORWARD", "AGV_SPEED_STOP", "AGV_RUN_DISTANCE", "TOTAL_DURATION", "AGV_STOP_TIMEOUT", "AGV_PICK_SETTLE_DELAY", "YOLO_MODEL_PATH", "YOLO_DETECT_CONF", "PICK_CONFIDENCE_THRESHOLD", "HOME_JOINTS", "APPROACH_Y_OFFSET", "LIFT_Z_OFFSET", "PICKUP_X_OFFSET", "PICKUP_Y_OFFSET", "PICK_ANGLE_ORIENTATION_INDEX", "PICK_ANGLE_SIGN", "MAX_PICK_ANGLE_DEG", "GRIPPER_CLOSE_IO", "GRIPPER_OPEN_IO", "GRIPPER_ACTION_DELAY", "PICK_POINT_ARRIVAL_DELAY", "SCISSORS_ENABLED", "ARM_SPEED", "ARM_ACCEL", "place_positions", ) # -------------------- 运行状态别名 -------------------- running = _core.running has_tomato = _core.has_tomato picking_done = _core.picking_done robot_rpc_client = _core.robot_rpc_client ui_callback = _core.ui_callback def _sync_config() -> None: # 如果 UI 或外部脚本只改了 control.py,这里会在进入核心逻辑前同步到 control_core。 config = {name: globals()[name] for name in _CONFIG_NAMES} if place_positions and isinstance(place_positions[0], (list, tuple)): config["place_positions"] = [list(position) for position in place_positions] else: config["place_positions"] = [list(place_positions)] config["HOME_JOINTS"] = list(HOME_JOINTS) _core.configure(config) def set_ui_callback(callback): global ui_callback ui_callback = callback _core.set_ui_callback(callback) def exampleState(robot_name: str): return _core.exampleState(robot_name) def get_robot_end_effector_pose(robot_name: str): return _core.get_robot_end_effector_pose(robot_name) def exampleInverseK(robot_name: str, pose: Sequence[float], reference_q: Sequence[float]): return _core.exampleInverseK(robot_name, pose, reference_q) def exampleStartup(): _sync_config() return _core.exampleStartup() def quaternion_to_rotation_matrix(q: Sequence[float]): return _core.quaternion_to_rotation_matrix(q) def euler_to_rotation_matrix(roll: float, pitch: float, yaw: float): return _core.euler_to_rotation_matrix(roll, pitch, yaw) def get_robot_end_matrix(robot_name: str): return _core.get_robot_end_matrix(robot_name) def camera_to_base(point_cam: Sequence[float], robot_name: str): return _core.camera_to_base(point_cam, robot_name) def check_joint_position(robot_name: str, target_joints: Sequence[float]): return _core.check_joint_position(robot_name, target_joints) def check_tcp_pose(robot_name: str, target_pose: Sequence[float]): return _core.check_tcp_pose(robot_name, target_pose) def waitArrival(impl: Any, target_joints=None, target_pose=None): return _core.waitArrival(impl, target_joints=target_joints, target_pose=target_pose) def control_tool_io(robot_name: str, io_index: int, state: bool): return _core.control_tool_io(robot_name, io_index, state) def get_next_placement(): _sync_config() return _core.get_next_placement() def get_placement_index(): return _core.get_placement_index() def create_placement_manager(): _sync_config() return _core.create_placement_manager() def return_to_home(robot_name: str): _sync_config() return _core.return_to_home(robot_name) def control_robot(robot_name: str, pose: Sequence[float], angle_rad: float): _sync_config() return _core.control_robot(robot_name, pose, angle_rad) def init_camera(): _sync_config() return _core.init_camera() def init_tomato_detector(model_path=None): _sync_config() return _core.init_tomato_detector(model_path) def filter_ripe_tomatoes(results, confidence_threshold=None): _sync_config() return _core.filter_ripe_tomatoes(results, confidence_threshold) def draw_tomato_tilt_line(color_image, x1, y1, x2, y2, pixel_x): return _core.draw_tomato_tilt_line(color_image, x1, y1, x2, y2, pixel_x) def fit_red_line(crop_image, x1, y1): return _core.fit_red_line(crop_image, x1, y1) def vision_detection_thread(pipeline, align, depth_intrinsics, model, robot_name: str): _sync_config() return _core.vision_detection_thread(pipeline, align, depth_intrinsics, model, robot_name) def agv_control_thread(agv_client): _sync_config() return _core.agv_control_thread(agv_client) def main(): # control.py 本身只做兼容和配置转发,真正业务流程在 control_core.main()。 _sync_config() return _core.main() def signal_handler(sig: int, frame: Any): _sync_config() return _core.signal_handler(sig, frame) if __name__ == "__main__": signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) main()