# utils_robot.py # 同济子豪兄 2024-5-22 # 启动并连接机械臂,导入各种工具包 print('导入机械臂连接模块') from lebai import zeroconf, l_master import cv2 import numpy as np import time # 连接机械臂 # 实例化一个Discovery类用来存储设备发现的信息 d = zeroconf.Discovery() # 搜索局域网内设备,返回一个最多16个元素的列表 controllers = d.resolve() robot = l_master.Robot(controllers[0].ip_address) def back_zero(): ''' 机械臂归零 ''' print('机械臂归零') robot.movej( {"j1": 0.0, "j2": 0.0, "j3": 0.0, "j4": 0.0, "j5": 0.0, "j6": 0.0}, 1.0, 1.0, 0.0, 0.0) time.sleep(3) def relax_arms(): print('放松机械臂关节') robot.teach_mode() def move_to_coords(X=150, Y=-130, Z=0.35): print('移动至指定坐标:X {} Y {}'.format(X, Y)) X, Y = eye2hand(X, Y) cartesian_pose = {'x' : X, 'y' : Y, 'z' : Z, 'rz' : 0, 'ry' : 0, 'rx' : np.pi} # 目标位姿笛卡尔数据 a = 0.5 # 关节加速度 (rad/s2) v = 0.2 # 关节速度 (rad/s) t = 0 # 运动时间 (s)。 当 t > 0 时,参数速度 v 和加速度 a 无效 r = 0 # 交融半径 (m)。用于指定路径的平滑效果 robot.movel(cartesian_pose, a, v, t, r) # 直线运动 https://help.lebai.ltd/sdk/motion.html#%E7%9B%B4%E7%BA%BF%E8%BF%90%E5%8A%A8 robot.wait_move() # 等待运动完成 time.sleep(4) def single_joint_move(joint_index, angle): print('关节 {} 旋转至 {} 度'.format(joint_index, angle)) robot.movej( { f"j{joint_index}" : angle / 180 * np.pi }, 1.0, 1.0, 0.0, 0.0 ) time.sleep(2) def move_to_top_view(): print('移动至俯视姿态') joint_pose = [np.pi / 2, -np.pi / 2, -np.pi / 2, -np.pi / 2, np.pi / 2, 0] # 目标位姿关节数据 a = 0.5 # 关节加速度 (rad/s2) v = 0.2 # 关节速度 (rad/s) t = 0 # 运动时间 (s)。 当 t > 0 时,参数速度 v 和加速度 a 无效 r = 0 # 交融半径 (m)。用于指定路径的平滑效果 robot.movej(joint_pose, a, v, t, r) # 关节运动 https://help.lebai.ltd/sdk/motion.html#%E5%85%B3%E8%8A%82%E8%BF%90%E5%8A%A8 def top_view_shot(check=False): ''' 拍摄一张图片并保存 check:是否需要人工看屏幕确认拍照成功,再在键盘上按q键确认继续 ''' print(' 移动至俯视姿态') move_to_top_view() # 获取摄像头,传入0表示获取系统默认摄像头 cap = cv2.VideoCapture(0, cv2.CAP_DSHOW) # 打开cap cap.open(0, cv2.CAP_DSHOW) time.sleep(0.3) success, img_bgr = cap.read() # 保存图像 print(' 保存至temp/vl_now.jpg') cv2.imwrite('temp/vl_now.jpg', img_bgr) # 屏幕上展示图像 cv2.destroyAllWindows() # 关闭所有opencv窗口 cv2.imshow('vlm_agent', img_bgr) if check: print('请确认拍照成功,按c键继续,按q键退出') while(True): key = cv2.waitKey(10) & 0xFF if key == ord('c'): # 按c键继续 break if key == ord('q'): # 按q键退出 # exit() cv2.destroyAllWindows() # 关闭所有opencv窗口 raise NameError('按q退出') else: if cv2.waitKey(10) & 0xFF == None: pass # 关闭摄像头 cap.release() # 关闭图像窗口 # cv2.destroyAllWindows() def eye2hand(X_im=160, Y_im=120): ''' 输入目标点在图像中的像素坐标,转换为机械臂坐标 ''' cali_ims = [ (270, 223), (592, 279), (418, 333), ] cali_mcs = [ (0.190, 0.229), (-0.095, 0.270), (0.065, 0.300), ] X_cali_im = [cali_im[0] for cali_im in cali_ims] # 像素坐标 X_cali_mc = [cali_mc[0] for cali_mc in cali_mcs] # 机械臂坐标 Y_cali_im = [cali_im[1] for cali_im in cali_ims] # 像素坐标 Y_cali_mc = [cali_mc[1] for cali_mc in cali_mcs] # 机械臂坐标 # 拟合三次多项式 X_poly = np.polyfit(X_cali_im, X_cali_mc, deg=2) Y_poly = np.polyfit(Y_cali_im, Y_cali_mc, deg=2) # 使用多项式模型进行插值 X_mc = np.polyval(X_poly, X_im) Y_mc = np.polyval(Y_poly, Y_im) return X_mc, Y_mc def gripper_open(): ''' 打开夹爪 ''' robot.set_claw(50, 100) def gripper_close(): ''' 关闭夹爪 ''' robot.set_claw(10, 0) # 夹爪抓取并移动物体 def gripper_move(XY_START=[0.383, 0.121], HEIGHT_START=0.20, XY_END=[0.3, 0.12], HEIGHT_END=0.20, HEIGHT_SAFE=0.35): ''' 用夹爪,将物体从起点吸取移动至终点 XY_START:起点机械臂坐标 (m) HEIGHT_START:起点高度 (m),方块用 0.09,药盒子用 0.07 XY_END:终点机械臂坐标 (m) HEIGHT_END:终点高度 (m) HEIGHT_SAFE:搬运途中安全高度 (m) ''' a = 0.5 # 关节加速度 (rad/s2) v = 0.2 # 关节速度 (rad/s) t = 0 # 运动时间 (s)。 当 t > 0 时,参数速度 v 和加速度 a 无效 r = 0 # 交融半径 (m)。用于指定路径的平滑效果 # 夹爪移动至物体上方 print(' 夹爪移动至物体上方') cartesian_pose = {'x' : XY_START[0], 'y' : XY_START[1], 'z' : HEIGHT_SAFE, 'rz' : 0, 'ry' : 0, 'rx' : np.pi} # 目标位姿笛卡尔数据 robot.movel(cartesian_pose, a, v, t, r) # 直线运动 https://help.lebai.ltd/sdk/motion.html#%E7%9B%B4%E7%BA%BF%E8%BF%90%E5%8A%A8 robot.wait_move() # 等待运动完成 # 夹爪向下抓取物体 print(' 夹爪向下抓取物体') gripper_open() cartesian_pose = {'x' : XY_START[0], 'y' : XY_START[1], 'z' : HEIGHT_START, 'rz' : 0, 'ry' : 0, 'rx' : np.pi} robot.movel(cartesian_pose, a, v, t, r) robot.wait_move() gripper_close() # 升起物体 print(' 升起物体') cartesian_pose = {'x' : XY_START[0], 'y' : XY_START[1], 'z' : HEIGHT_SAFE, 'rz' : 0, 'ry' : 0, 'rx' : np.pi} robot.movel(cartesian_pose, a, v, t, r) robot.wait_move() # 搬运物体至目标上方 print(' 搬运物体至目标上方') cartesian_pose = {'x' : XY_END[0], 'y' : XY_END[1], 'z' : HEIGHT_SAFE, 'rz' : 0, 'ry' : 0, 'rx' : np.pi} robot.movel(cartesian_pose, a, v, t, r) robot.wait_move() # 向下放下物体 print(' 向下放下物体') cartesian_pose = {'x' : XY_END[0], 'y' : XY_END[1], 'z' : HEIGHT_END, 'rz' : 0, 'ry' : 0, 'rx' : np.pi} robot.movel(cartesian_pose, a, v, t, r) robot.wait_move() gripper_open() time.sleep(1) # 移动至俯视姿态 print(' 移动至俯视姿态') move_to_top_view()