19f02edc8c133.png

来源:第四届3D视觉创新应用竞赛 | 深圳大学 | 吴鹏飞 源代码:https://github.com/3DCVdeveloper/RobotV_Grab-box 相机SDK:奥比中光 Orbbec SDK 机械臂SDK:JAKA SDK


一、项目背景:中国智造的最后一公里

1.1 行业痛点

"中国制造2025"战略正推动我国制造业加速智能化转型,但在物流自动化领域,传统无序抓取技术仍面临严峻挑战:

  • ❌ 遮挡干扰:纸箱随机堆叠,相互遮挡,识别困难
  • ❌ 效率低下:人工搬运劳动强度大、效率低、成本高
  • ❌ 精度不足:传统方法难以准确获取纸箱的6D位姿信息

1.2 解决方案

本项目设计了一套无序场景下的纸箱位姿识别系统,通过 数据采集 → 目标定位 → 位姿估计 → 机械臂抓取 四大核心步骤,实现复杂堆叠场景下的智能抓取。

技术亮点一览:

技术模块 核心技术 优势
🎮 数据采集 NVIDIA Isaac Sim 虚拟仿真 大规模、高质量数据集
👁️ 目标定位 YOLOv8 实例分割 轻量化、高效率
📐 位姿估计 PCA + ICP 联合配准 粗精结合、精度保证
🤖 机械臂控制 节卡 zu12 + 手眼标定 精准抓取

二、系统架构:从"看"到"抓"的完整链路

2.1 整体流程图

19f02f448d100.png

2.2 硬件配置

组件 型号 关键参数
🎥 深度相机 Orbbec Gemini 2 双目结构光、高分辨率深度图
🧠 计算平台 NVIDIA Jetson Orin Nano 边缘AI推理
🤖 机械臂 节卡机器人 zu12 四自由度、精准控制
💾 训练环境 RTX 3090 × 2 深度学习训练

三、虚拟数据集:Isaac Sim仿真训练

3.1 为什么需要虚拟数据?

传统人工采集数据的局限性:

  • 📷 角度覆盖不全,难以获取全视角数据
  • ⏰ 标注效率低,无法快速生成大规模数据集
  • 🏭 真实场景采集成本高、周期长

3.2 Isaac Sim 虚拟仿真流程

# NVIDIA Isaac Sim 虚拟数据生成核心流程
params_json_string = json.dumps({
    "{plane.plane_splitter.icp_boxes}": [
        [300.0, 200.0, 100.0],  # 纸箱尺寸列表
        [400.0, 300.0, 150.0]
    ],
    "{plane.plane_splitter.threshold_height}": 50.0,  # 高度差异阈值
    "${plane.plane_splitter.visualize}": False
})

生成数据包括:

  • JPG格式RGB图像(8位)
  • NPY格式深度图像(16位)
  • 边界框标注
  • 相机位姿变换矩阵
  • 分割图像

虚拟仿真优势:

  • ✅ 场景多样:可随机化光源、材质、纹理、纸箱大小
  • ✅ 物理真实:内置物理引擎模拟纸箱掉落堆叠
  • ✅ 标注自动:自动生成边界框、深度图、位姿标签
  • ✅ 规模可控:可生成任意数量的训练数据

3.3 仿真数据生成步骤

19f02fafa49cb.png

四、目标定位:YOLOv8 实例分割

4.1 为什么选择 YOLOv8?

考虑到纸箱纹理简单、对检测速度要求高(实时抓取),YOLOv8 成为最佳选择:

  • ⚡ One-Stage检测:无需区域建议步长,直接从图像提取预测框
  • 🎯 高精度:相比两阶段检测器,精度相当但速度更快
  • 📦 轻量化:模型小,适合边缘设备部署(Jetson Orin Nano)

4.2 YOLOv8 网络架构

19f0300589f1b.png

4.3 核心代码实现

# main.py - YOLOv8目标检测调用
from ultralytics import YOLO
import open3d as o3d

# 加载训练好的模型
weight_path = '/home/xiaofeifei/Downloads/ultralytics-main/boxs.pt'
model = YOLO(weight_path)

# 获取相机帧
frames = pipeline.wait_for_frames(10000)
color_frame = frames.get_color_frame()
color_image = frame_to_bgr_image(color_frame)

# YOLOv8预测
results = model.predict(source=color_image)

# 可视化检测结果
annotated_frame = results[0].plot()
cv2.imshow("Color Viewer", annotated_frame)

# 获取检测结果用于位姿估计
# results[0].obb.xywhr 包含检测框的中心点、宽高、旋转角度
maskrcnn_result = results[0].obb.xywhr.tolist()

关键参数配置:

Method: YOLOv8
Backbone: CSPDarknet53+Focus
Neck: PANet
Head: Decoupled Head
学习率: SGD, lr=0.01, momentum=0.9
输入尺寸: 640 × 640
数据增强: 随机裁剪、随机翻转、归一化

五、位姿估计:PCA + ICP 联合配准

5.1 6D位姿估计概述

位姿估计的目标是求解物体坐标系O到相机坐标系C的刚性变换:

T_OC = [R_3×3 | t_3×1]

其中:

  • R:3D旋转矩阵
  • t:3D平移向量

两阶段配准策略:

粗配准(PCA) → 快速获得初始位姿 精配准(ICP) → 迭代优化精细结果

5.2 PCA 粗配准原理

PCA(主成分分析)通过分析点云的主要分布方向,快速获得纸箱的大致位姿:

# PCA粗配准核心流程
def pca_alignment(point_cloud):
    # 1. 计算点云的协方差矩阵
    covariance_matrix = np.cov(point_cloud.T)
    
    # 2. SVD分解获取特征向量
    eigenvalues, eigenvectors = np.linalg.eig(covariance_matrix)
    
    # 3. 特征向量即为点云的主方向(纸箱的长宽轴)
    principal_axes = eigenvectors[:3]
    
    # 4. 根据主方向计算旋转矩阵R
    R = compute_rotation_matrix(principal_axes)
    
    # 5. 计算平移向量t(点云中心到原点)
    t = -point_cloud.mean(axis=0)
    
    return R, t

【此处插入PCA位姿估计效果图】

5.3 ICP 精配准原理

获得粗配准结果后,使用ICP(Iterative Closest Point)算法进行精细优化:

# ICP精配准算法
def icp_registration(source_cloud, target_cloud, initial_pose):
    """
    ICP算法核心步骤:
    1. 根据当前位姿变换源点云
    2. 寻找最近点对应关系
    3. 最小化点对距离(SVD求解最优R,t)
    4. 迭代直到收敛
    """
    # ICP目标函数:最小化配准误差
    # E = Σ||Qi - (Pi·R + T)||²
    
    for iteration in range(max_iterations):
        # 步骤1:变换源点云
        transformed = apply_transform(source_cloud, current_pose)
        
        # 步骤2:寻找最近点对应关系
        correspondences = find_nearest_neighbors(transformed, target_cloud)
        
        # 步骤3:SVD求解最优变换
        R, t = svd_alignment(source_cloud, correspondences)
        
        # 步骤4:更新位姿
        current_pose = compose_transform(R, t, current_pose)
        
        # 步骤5:检查收敛条件
        if check_convergence(current_pose, prev_pose):
            break
    
    return current_pose

ICP关键参数配置:

voxel_size: 5                    # 栅格化尺寸 (mm)
max_correspondence_distance: 0.03 # 最大对应点距离 (m)
max_iter: 30                     # 最大迭代次数
relative_fitness: 1e-6           # 收敛阈值
relative_rmse: 1e-6              # RMSE收敛阈值

【此处插入ICP精配准效果图】

5.4 配准结果对比

配准阶段 算法 精度 速度 适用场景
粗配准 PCA ★★★ ⚡⚡⚡ 初始位姿估计
精配准 ICP ★★★★★ ⚡⚡ 精细优化

六、机械臂抓取:手眼协同控制

6.1 手眼标定原理

手眼标定用于确定相机坐标系与机械臂坐标系之间的转换关系:

T_robot = T_camera→robot · T_object→camera

Eye-to-Hand(眼在手外)配置:

相机 (Gemini 2) 固定安装于工作空间正上方,俯视整个抓取区域 ↓ 手眼标定矩阵 机械臂 (末端夹爪) 节卡 zu12,执行抓取动作

6.2 手眼标定步骤

# 手眼标定核心流程
def eye_hand_calibration():
    """
    使用标准球法进行手眼标定:
    1. 将标准球固定于机械臂末端
    2. 机械臂带动标准球在相机视野内移动
    3. 采集多组(平移+旋转)点位数据
    4. 使用UMEYAMA算法求解转换矩阵
    """
    # 采集纯旋转点位
    rotation_points = []
    for i in range(N_ROTATION):
        robot_arm.move_to(rotation_poses[i])
        ball_center = detect_ball_center()  # 点云中定位球心
        rotation_points.append(ball_center)
    
    # 采集纯平移点位
    translation_points = []
    for i in range(N_TRANSLATION):
        robot_arm.move_to(translation_poses[i])
        ball_center = detect_ball_center()
        translation_points.append(ball_center)
    
    # 使用UMEYAMA算法求解转换矩阵
    T_camera_robot = umeyama_algorithm(rotation_points, translation_points)
    return T_camera_robot

6.3 节卡机械臂控制

# Instruct.py - 节卡机械臂SDK封装
import jkrc
import numpy as np
import open3d as o3d

class JakaRobotController:
    def __init__(self, ip="192.168.137.164"):
        self.robot_arm = jkrc.RC(ip)
        self.speed = 500.0  # 运动速度 mm/s
    
    def login(self):
        """登录并使能机械臂"""
        self.robot_arm.login()
        self.robot_arm.power_on()
        self.robot_arm.enable_robot()
    
    def moving(self, pose_matrix):
        """线性运动到目标位置"""
        xyzabc = self.get_xyzabc_from_matrix(pose_matrix)
        self.robot_arm.linear_move(xyzabc, 0, True, self.speed)
    
    def grasp(self, status=1):
        """夹爪控制"""
        self.robot_arm.set_digital_output(0, 0, status)

七、完整抓取流程代码

# main.py - 完整抓取流程
from pyorbbecsdk import *
from ultralytics import YOLO
import open3d as o3d

def main():
    # 初始化
    ROBOT.log_in()                          # 机械臂登录
    model = YOLO('boxs.pt')                # 加载检测模型
    pipeline = Pipeline()
    pipeline.start(Config())
    
    while True:
        # 1. 获取相机数据
        frames = pipeline.wait_for_frames()
        color_frame = frames.get_color_frame()
        color_image = frame_to_bgr_image(color_frame)
        
        # 2. YOLOv8目标检测
        results = model.predict(source=color_image)
        
        # 3. 获取点云数据
        camera_param = pipeline.get_camera_param()
        points = frames.convert_to_color_points(camera_param)
        points_array = np.array([[p.x, p.y, p.z] for p in points])
        
        # 4. 位姿估计(PCA+ICP)
        POSE.z_plane_registration_run2(inputDatas)
        pose_result = POSE.get_output("result.Matrices")
        
        # 5. 机械臂运动规划
        ROBOT.moving(pose_result)
        
        # 6. 执行抓取
        ROBOT.grasp()

八、技术指标与创新点

8.1 核心性能指标

指标 数值 说明
🎯 检测精度 >95% YOLOv8实例分割准确率
📐 位姿精度 <5mm ICP精配准后误差
⚡ 处理速度 30fps Jetson Orin Nano实时处理
🤝 抓取成功率 >90% 实测无序堆叠场景

8.2 关键技术创新

创新点 技术方案 达到效果
🎮 虚拟数据 Isaac Sim物理仿真 1000+张高质量训练数据
⚡ 实时检测 YOLOv8轻量化模型 边缘设备实时推理
📐 粗精配准 PCA + ICP联合 兼顾速度与精度
🔧 手眼协同 UMEYAMA标定 坐标系精确转换

8.3 未来优化方向

模块 当前问题 优化方案
数据集 只能标注正对相机情形 多角度自动标注
点云 SDK每帧点云不一致 滤波算法优化
精度 遮挡时精度下降 迁移学习增强泛化

九、技术栈总结

类别 技术选型
🎮 仿真平台 NVIDIA Isaac Sim / Omniverse
🎥 深度视觉 奥比中光 Gemini 2 SDK
🧠 边缘计算 NVIDIA Jetson Orin Nano
🔍 目标检测 YOLOv8 (Ultralytics)
📐 点云处理 Open3D
🤖 机械臂 节卡机器人 zu12 SDK
🐍 开发语言 Python 3.11

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注