Skip to content

十一、视觉工艺(nrc_craft_vision.h)

视觉工艺接口提供视觉系统的基本参数配置、视觉范围设置、坐标参数配置、视觉标定及标定数据查询、手眼标定计算等功能。支持单机器人和多机器人(_robot 后缀)两种调用方式。

数据结构

VisionParam —— 视觉基本参数

cpp
struct VisionParam {
    CameraList cameraList;      // 相机列表
    Protocol protocol;          // 通讯协议配置
    Socket socket;              // Socket 通讯配置
    Trigger trigger;            // 触发配置
    int userCoordNum;           // 用户坐标编号
};

子结构体说明:

CameraList:

字段类型默认值说明
currentNamestring"customize"当前相机名称
listNumint0相机列表数量

Protocol(通讯协议):

字段类型默认值说明
addDataInitialParastring"GD001"附加数据初始参数
addDataNumint0附加数据数量
angleUnitint1角度单位
endMarkstring"$"结束标志
failFlagstring"NG"失败标志
frameHeaderstring""帧头
hasTCSboolfalse是否有TCS
hasUCSboolfalse是否有UCS
separatorstring","分隔符
singleTargetbooltrue单目标
successFlagstring"OK"成功标志
timeOutint30超时时间
typeint1协议类型

Socket(Socket 通讯配置):

字段类型默认值说明
IPstring"192.168.1.120"IP地址
cameraDataTypeint0相机数据类型
portNumint1端口号
portOneint5050端口1
portTwoint5051端口2
serverbooltrue是否为服务器

Trigger(触发配置):

字段类型默认值说明
IOPortint0IO端口
durationint1000持续时间(ms)
intervalsint35间隔时间(ms)
triggerModeint2触发模式:1=IO,2=EtherCAT
triggerOncebooltrue单次触发
triggerStrstring"TRG"触发字符串

VisionRange —— 视觉范围

cpp
struct VisionRange {
    std::string maxX;  // 最大X坐标
    std::string maxY;  // 最大Y坐标
    std::string maxZ;  // 最大Z坐标
    std::string minX;  // 最小X坐标
    std::string minY;  // 最小Y坐标
    std::string minZ;  // 最小Z坐标
};

VisionPositionParam —— 视觉坐标参数

cpp
struct VisionPositionParam {
    Position position;  // 位置数据
    int protocol;       // 协议类型
};

Position 子结构体包含: 视角方向(angleDirection)、相机数据(cameraData)、相机点位(cameraPoint,长度14)、参考点位(datumPoint,长度14)、偏移量(Excursion:X/Y/Z 偏移 + 角度)、接收点类型(recvPointsType)、样本数据(sampleData)、比例(scale)。

VisionCalibrationData —— 视觉标定数据

cpp
struct VisionCalibrationData {
    int visionNum;              // 视觉编号
    Calibration calibration;    // 校准数据(含标定点列表,默认点数6,范围[6,30])
};

Calibration 包含: calibrated(是否已校准)、point(标定点列表)、point_num(点数量)。

CalibrationPoint 包含: pixel_pos(像素位置,长度7)、pixel_pos_deg(像素位置角度,长度7)、robot_pos(机器人位置,长度7)、robot_pos_deg(机器人位置角度,长度7)。


11.1 基本参数配置

vision_set_basic_parameter / vision_set_basic_parameter_robot

设置视觉系统的基本参数,包括相机列表、通讯协议、Socket 配置和触发方式。

函数签名:

cpp
Result vision_set_basic_parameter(SOCKETFD socketFd, int visionNum, VisionParam vsPamrm);
Result vision_set_basic_parameter_robot(SOCKETFD socketFd, int robotNum, int visionNum, VisionParam vsPamrm);

参数说明:

参数类型输入/输出说明
socketFdSOCKETFD输入连接句柄
robotNumint输入机器人编号(仅 _robot 版本)
visionNumint输入视觉ID编号
vsPamrmVisionParam输入视觉基本参数结构体

返回值: Result 枚举,0 表示成功,-1 表示等待消息失败,-2 表示找不到指定的客户端。

使用示例:

cpp
// 配置视觉系统基本参数
VisionParam param;
// 设置相机名称
param.cameraList.currentName = "camera_01";
param.cameraList.listNum = 1;

// 设置通讯协议
param.protocol.addDataInitialPara = "GD001";
param.protocol.endMark = "$";
param.protocol.failFlag = "NG";
param.protocol.successFlag = "OK";
param.protocol.separator = ",";
param.protocol.timeOut = 30;
param.protocol.type = 1;

// 设置Socket通讯
param.socket.IP = "192.168.1.120";
param.socket.portOne = 5050;
param.socket.portTwo = 5051;
param.socket.server = true;

// 设置触发方式
param.trigger.triggerMode = 2;      // EtherCAT触发
param.trigger.duration = 1000;
param.trigger.intervals = 35;
param.trigger.triggerStr = "TRG";

// 设置用户坐标
param.userCoordNum = 1;

Result result = vision_set_basic_parameter(fd, 1, param);
if (result == 0) {
    printf("视觉基本参数设置成功\n");
}

vision_get_basic_parameter / vision_get_basic_parameter_robot

查询视觉系统已配置的基本参数。

函数签名:

cpp
Result vision_get_basic_parameter(SOCKETFD socketFd, int visionNum, VisionParam& vsPamrm);
Result vision_get_basic_parameter_robot(SOCKETFD socketFd, int robotNum, int visionNum, VisionParam& vsPamrm);

参数说明:

参数类型输入/输出说明
socketFdSOCKETFD输入连接句柄
robotNumint输入机器人编号(仅 _robot 版本)
visionNumint输入视觉ID编号
vsPamrmVisionParam&输出接收视觉基本参数

返回值: Result 枚举,0 表示成功,-1 表示等待消息失败,-2 表示找不到指定的客户端。

使用示例:

cpp
VisionParam param;
Result result = vision_get_basic_parameter(fd, 1, param);
if (result == 0) {
    printf("视觉基本参数:\n");
    printf("  相机名称: %s\n", param.cameraList.currentName.c_str());
    printf("  IP地址: %s\n", param.socket.IP.c_str());
    printf("  端口1: %d\n", param.socket.portOne);
    printf("  触发模式: %d\n", param.trigger.triggerMode);
    printf("  用户坐标编号: %d\n", param.userCoordNum);
}

11.2 视觉范围配置

vision_set_range / vision_set_range_robot

设置视觉识别的空间范围(包围盒),用于限定视觉检测的有效区域。

函数签名:

cpp
Result vision_set_range(SOCKETFD socketFd, int visionNum, VisionRange vsPamrm);
Result vision_set_range_robot(SOCKETFD socketFd, int robotNum, int visionNum, VisionRange vsPamrm);

参数说明:

参数类型输入/输出说明
socketFdSOCKETFD输入连接句柄
robotNumint输入机器人编号(仅 _robot 版本)
visionNumint输入视觉ID编号
vsPamrmVisionRange输入视觉范围参数(min/max XYZ)

返回值: Result 枚举,0 表示成功,-1 表示等待消息失败,-2 表示找不到指定的客户端。

使用示例:

cpp
// 设置视觉检测范围:X[0,500], Y[-200,200], Z[0,300]
VisionRange range;
range.minX = "0";
range.maxX = "500";
range.minY = "-200";
range.maxY = "200";
range.minZ = "0";
range.maxZ = "300";

Result result = vision_set_range(fd, 1, range);
if (result == 0) {
    printf("视觉范围设置成功\n");
}

vision_get_range / vision_get_range_robot

查询视觉已配置的空间范围参数。

函数签名:

cpp
Result vision_get_range(SOCKETFD socketFd, int visionNum, VisionRange& vsPamrm);
Result vision_get_range_robot(SOCKETFD socketFd, int robotNum, int visionNum, VisionRange& vsPamrm);

参数说明:

参数类型输入/输出说明
socketFdSOCKETFD输入连接句柄
robotNumint输入机器人编号(仅 _robot 版本)
visionNumint输入视觉ID编号
vsPamrmVisionRange&输出接收视觉范围参数

返回值: Result 枚举,0 表示成功,-1 表示等待消息失败,-2 表示找不到指定的客户端。

使用示例:

cpp
VisionRange range;
Result result = vision_get_range(fd, 1, range);
if (result == 0) {
    printf("视觉范围:\n");
    printf("  X: [%s, %s]\n", range.minX.c_str(), range.maxX.c_str());
    printf("  Y: [%s, %s]\n", range.minY.c_str(), range.maxY.c_str());
    printf("  Z: [%s, %s]\n", range.minZ.c_str(), range.maxZ.c_str());
}

11.3 坐标参数配置

vision_set_position_parameter / vision_set_position_parameter_robot

设置视觉坐标参数,包括拍照位置、参考点位、偏移量和样本数据格式等。

函数签名:

cpp
Result vision_set_position_parameter(SOCKETFD socketFd, int visionNum, VisionPositionParam vsPamrm);
Result vision_set_position_parameter_robot(SOCKETFD socketFd, int robotNum, int visionNum, VisionPositionParam vsPamrm);

参数说明:

参数类型输入/输出说明
socketFdSOCKETFD输入连接句柄
robotNumint输入机器人编号(仅 _robot 版本)
visionNumint输入视觉ID编号
vsPamrmVisionPositionParam输入视觉坐标参数

返回值: Result 枚举,0 表示成功,-1 表示等待消息失败,-2 表示找不到指定的客户端。

使用示例:

cpp
VisionPositionParam posParam;
// 设置协议类型
posParam.protocol = 0;

// 设置位置数据
posParam.position.angleDirection = 0;
posParam.position.cameraData = "";
posParam.position.recvPointsType = 0;
posParam.position.sampleData = "x,y,Rz,h,$";
posParam.position.scale = 1.0;

// 设置偏移量
posParam.position.excursion.Xexcursion = 0.0;
posParam.position.excursion.Yexcursion = 0.0;
posParam.position.excursion.Zexcursion = 0.0;
posParam.position.excursion.angle = 0.0;

Result result = vision_set_position_parameter(fd, 1, posParam);
if (result == 0) {
    printf("视觉坐标参数设置成功\n");
}

vision_get_position_parameter / vision_get_position_parameter_robot

查询视觉已配置的坐标参数。

函数签名:

cpp
Result vision_get_position_parameter(SOCKETFD socketFd, int visionId, VisionPositionParam& vsPamrm);
Result vision_get_position_parameter_robot(SOCKETFD socketFd, int robotNum, int visionId, VisionPositionParam& vsPamrm);

参数说明:

参数类型输入/输出说明
socketFdSOCKETFD输入连接句柄
robotNumint输入机器人编号(仅 _robot 版本)
visionIdint输入视觉ID编号
vsPamrmVisionPositionParam&输出接收视觉坐标参数

返回值: Result 枚举,0 表示成功,-1 表示等待消息失败,-2 表示找不到指定的客户端。

使用示例:

cpp
VisionPositionParam posParam;
Result result = vision_get_position_parameter(fd, 1, posParam);
if (result == 0) {
    printf("视觉坐标参数:\n");
    printf("  协议类型: %d\n", posParam.protocol);
    printf("  样本数据格式: %s\n", posParam.position.sampleData.c_str());
    printf("  偏移: X=%.2f Y=%.2f Z=%.2f Angle=%.2f\n",
           posParam.position.excursion.Xexcursion,
           posParam.position.excursion.Yexcursion,
           posParam.position.excursion.Zexcursion,
           posParam.position.excursion.angle);
}

11.4 视觉标定

vision_calibrate / vision_calibrate_robot

执行视觉标定操作,设置标定相关的点位数据。

函数签名:

cpp
Result vision_calibrate(SOCKETFD socketFd, int visionId, VisionCalibrationData vsPamrm);
Result vision_calibrate_robot(SOCKETFD socketFd, int robotNum, int visionId, VisionCalibrationData vsPamrm);

参数说明:

参数类型输入/输出说明
socketFdSOCKETFD输入连接句柄
robotNumint输入机器人编号(仅 _robot 版本)
visionIdint输入视觉ID编号
vsPamrmVisionCalibrationData输入标定数据,含像素位置和机器人位置

返回值: Result 枚举,0 表示成功,-1 表示等待消息失败,-2 表示找不到指定的客户端。

注意事项: 标定前需确保视觉基本参数和坐标参数已正确配置。标定点数默认为 6,范围 [6, 30],点数越多标定精度越高。

使用示例:

cpp
// 创建标定数据(默认6个标定点)
VisionCalibrationData calibData(6);
calibData.visionNum = 1;

// 添加标定点(示例:第1个点)
CalibrationPoint point1;
// 像素位置(x, y, z, rx, ry, rz, 保留)
point1.pixel_pos = {100.0, 200.0, 0.0, 0.0, 0.0, 0.0, 0.0};
// 机器人实际位置
point1.robot_pos = {400.0, 150.0, 50.0, 180.0, 0.0, 0.0, 0.0};
calibData.calibration.addCalibrationPoint(point1);

// ... 继续添加其余5个标定点

// 执行标定
Result result = vision_calibrate(fd, 1, calibData);
if (result == 0) {
    printf("视觉标定完成\n");
}

vision_get_calibrate_data / vision_get_calibrate_data_robot

查询已保存的视觉标定数据。

函数签名:

cpp
Result vision_get_calibrate_data(SOCKETFD socketFd, int visionId, VisionCalibrationData& vsPamrm);
Result vision_get_calibrate_data_robot(SOCKETFD socketFd, int robotNum, int visionId, VisionCalibrationData& vsPamrm);

参数说明:

参数类型输入/输出说明
socketFdSOCKETFD输入连接句柄
robotNumint输入机器人编号(仅 _robot 版本)
visionIdint输入视觉ID编号
vsPamrmVisionCalibrationData&输出接收标定数据

返回值: Result 枚举,0 表示成功,-1 表示等待消息失败,-2 表示找不到指定的客户端。

使用示例:

cpp
VisionCalibrationData calibData;
Result result = vision_get_calibrate_data(fd, 1, calibData);
if (result == 0) {
    printf("视觉标定数据(视觉编号=%d):\n", calibData.visionNum);
    printf("  已校准: %s\n", calibData.calibration.calibrated ? "是" : "否");
    printf("  标定点数: %d\n", calibData.calibration.point_num);
    for (int i = 0; i < calibData.calibration.point_num; i++) {
        auto pt = calibData.calibration.getPoint(i);
        printf("  点%d: 像素(%.1f,%.1f) -> 机器人(%.1f,%.1f,%.1f)\n",
               i + 1,
               pt.pixel_pos[0], pt.pixel_pos[1],
               pt.robot_pos[0], pt.robot_pos[1], pt.robot_pos[2]);
    }
}

vision_hand_eye_calibration_calculation / vision_hand_eye_calibration_calculation_robot

执行手眼标定计算。在标定点数据全部录入后,调用此接口计算手眼关系矩阵。

函数签名:

cpp
Result vision_hand_eye_calibration_calculation(SOCKETFD socketFd, int visionNum);
Result vision_hand_eye_calibration_calculation_robot(SOCKETFD socketFd, int robotNum, int visionNum);

参数说明:

参数类型输入/输出说明
socketFdSOCKETFD输入连接句柄
robotNumint输入机器人编号(仅 _robot 版本)
visionNumint输入视觉ID编号

返回值: Result 枚举,0 表示成功,-1 表示等待消息失败,-2 表示找不到指定的客户端。

注意事项: 手眼标定计算前需确保所有标定点(像素位置和对应的机器人位置)已通过 vision_calibrate 录入。计算完成后,视觉系统即可将相机识别到的像素坐标转换为机器人坐标系下的空间位置。

使用示例:

cpp
// 标定点全部录入后,执行手眼标定计算
Result result = vision_hand_eye_calibration_calculation(fd, 1);
if (result == 0) {
    printf("手眼标定计算完成,视觉系统已校准\n");
} else {
    printf("手眼标定计算失败,请检查标定点数据\n");
}

11.5 完整视觉标定流程示例

cpp
#include "nrc_craft_vision.h"
#include "nrc_interface.h"
#include <stdio.h>

int main() {
    SOCKETFD fd = connect_robot("192.168.1.15", "6001");
    if (fd <= 0) {
        printf("连接失败\n");
        return -1;
    }

    // 1. 配置视觉基本参数
    VisionParam visionParam;
    visionParam.cameraList.currentName = "camera_01";
    visionParam.cameraList.listNum = 1;
    visionParam.socket.IP = "192.168.1.120";
    visionParam.socket.portOne = 5050;
    visionParam.socket.portTwo = 5051;
    visionParam.socket.server = true;
    visionParam.trigger.triggerMode = 2;  // EtherCAT触发
    visionParam.userCoordNum = 1;

    Result ret = vision_set_basic_parameter(fd, 1, visionParam);
    if (ret != 0) { printf("视觉基本参数配置失败\n"); return -1; }

    // 2. 设置视觉范围
    VisionRange range;
    range.minX = "0";    range.maxX = "500";
    range.minY = "-200"; range.maxY = "200";
    range.minZ = "0";    range.maxZ = "300";
    vision_set_range(fd, 1, range);

    // 3. 设置坐标参数
    VisionPositionParam posParam;
    posParam.protocol = 0;
    posParam.position.sampleData = "x,y,Rz,h,$";
    posParam.position.scale = 1.0;
    vision_set_position_parameter(fd, 1, posParam);

    // 4. 执行6点标定
    VisionCalibrationData calibData(6);
    calibData.visionNum = 1;

    // 标定点采集(此处为示意,实际需移动机器人到各标定点)
    for (int i = 0; i < 6; i++) {
        printf("请移动机器人到标定点%d...\n", i + 1);
        // robot_movel(fd, ...);  // 移动到目标位置

        CalibrationPoint point;
        // 从相机获取像素坐标
        point.pixel_pos = {100.0 * i, 200.0, 0, 0, 0, 0, 0};
        // 获取当前机器人位置
        point.robot_pos = {400.0, 150.0 + i * 50, 50.0, 180.0, 0, 0, 0};
        calibData.calibration.addCalibrationPoint(point);

        printf("标定点%d已采集\n", i + 1);
        sleep(1);
    }

    // 5. 提交标定数据
    ret = vision_calibrate(fd, 1, calibData);
    if (ret != 0) { printf("标定数据提交失败\n"); return -1; }

    // 6. 执行手眼标定计算
    ret = vision_hand_eye_calibration_calculation(fd, 1);
    if (ret == 0) {
        printf("手眼标定完成!\n");
    } else {
        printf("手眼标定计算失败\n");
        return -1;
    }

    printf("视觉标定流程结束\n");
    return 0;
}