GrabBag/Module/HandEyeCalib/Doc/HandEyeCalib.md

5.0 KiB
Raw Blame History

HandEyeCalib

HandEyeCalib 提供手眼标定、TCP 标定,以及基于标定结果的点位/姿态转换能力。

当前模块由两部分组成:

  • IHandEyeCalib 面向应用和工具的标定算法接口。
  • Utils/CoordinateTransform 面向业务侧的坐标变换工具函数。

当前保留的公开能力

IHandEyeCalib

virtual int CalculateRT(
    const std::vector<HECPoint3D>& eyePoints,
    const std::vector<HECPoint3D>& robotPoints,
    HECCalibResult& result) = 0;

virtual int CalculateRT(
    const std::vector<HECCalibPointPair>& pointPairs,
    HECCalibResult& result) = 0;

virtual void TransformPoint(
    const HECRotationMatrix& R,
    const HECTranslationVector& T,
    const HECPoint3D& srcPoint,
    HECPoint3D& dstPoint) = 0;

virtual void RotatePoint(
    const HECRotationMatrix& R,
    const HECPoint3D& srcPoint,
    HECPoint3D& dstPoint) = 0;

virtual void RotationMatrixToEuler(
    const HECRotationMatrix& R,
    HECEulerOrder order,
    HECEulerAngles& angles) = 0;

virtual void EulerToRotationMatrix(
    const HECEulerAngles& angles,
    HECEulerOrder order,
    HECRotationMatrix& R) = 0;

virtual bool TransformPose(
    const HECCalibResult& calibResult,
    const HECPoint3D& eyeCenter,
    const HECPoint3D& longAxisDir,
    const HECPoint3D& normalDir,
    int dirVectorInvert,
    HECEulerOrder eulerOrder,
    HECLongAxisDir longAxisMapping,
    HECPoseResult& poseResult) = 0;

virtual double CalculateError(
    const std::vector<HECPoint3D>& eyePoints,
    const std::vector<HECPoint3D>& robotPoints,
    const HECCalibResult& calibResult) = 0;

virtual int CalculateEyeInHand(
    const std::vector<HECEyeInHandData>& calibData,
    HECCalibResult& result) = 0;

virtual HECTCPCalibResult CalculateTCP(
    const HECTCPCalibData& data) = 0;

virtual int CalculateEyeToHandWithPose(
    const std::vector<HECEyeToHandData>& calibData,
    HECCalibResult& result) = 0;

CoordinateTransform

主要保留两类场景:

  • threeAxis* 三轴设备坐标转换
  • sixAxis* 六轴设备坐标转换

其中六轴眼在手上转换的核心接口为:

CTHomogeneousMatrix sixAxisEyeInHandBuildTransform(
    const CTRobotPose& robotPose,
    CTEulerOrder eulerOrder,
    const CTHomogeneousMatrix& handEyeMatrix);

约定robotPose.rx / ry / rz 必须已经是真实绕 X/Y/Z 轴的角(弧度)。 若机器人报文的字段排列不是 RX, RY, RZ(例如配天 A=RZ, B=RY, C=RX),调用方需要先把字段按真实轴含义装进 CTRobotPose,再调用本函数。

已移除的旧接口

以下接口已经从公开 API 中移除,不建议继续使用:

  • TransformPointWithCenter
  • RotationMatrixToEulerZYX
  • EulerZYXToRotationMatrix
  • 旧版 TransformPose(calibResult, eyePoint, eyeDirVectors, invertYZ, ...)
  • CalculateEyeInHandWithTarget

原因:

  • 仓库内已无实际调用
  • 与现有接口功能重复
  • 增加维护成本,容易让业务层误选旧接口

使用示例

1. 创建与销毁实例

#include "IHandEyeCalib.h"

IHandEyeCalib* calib = CreateHandEyeCalibInstance();
// ...
DestroyHandEyeCalibInstance(calib);

2. 对应点刚体变换标定

std::vector<HECPoint3D> eyePoints;
std::vector<HECPoint3D> robotPoints;

HECCalibResult result;
int ret = calib->CalculateRT(eyePoints, robotPoints, result);

3. Eye-In-Hand 标定

std::vector<HECEyeInHandData> calibData;

HECCalibResult result;
int ret = calib->CalculateEyeInHand(calibData, result);

4. 欧拉角与旋转矩阵互转

HECEulerAngles srcAngles;
srcAngles.roll = 0.1;
srcAngles.pitch = 0.2;
srcAngles.yaw = 0.3;

HECRotationMatrix rotation;
calib->EulerToRotationMatrix(srcAngles, HECEulerOrder::ZYX, rotation);

HECEulerAngles dstAngles;
calib->RotationMatrixToEuler(rotation, HECEulerOrder::ZYX, dstAngles);

5. 由中心点和方向种子生成机器人姿态

HECPoseResult poseResult;
bool ok = calib->TransformPose(
    calibResult,
    HECPoint3D(100.0, 50.0, 200.0),   // eyeCenter
    HECPoint3D(1.0, 0.0, 0.0),        // longAxisDir
    HECPoint3D(0.0, 0.0, 1.0),        // normalDir
    0,                                // dirVectorInvert
    HECEulerOrder::ZYX,
    HECLongAxisDir::AxisX,
    poseResult);

6. 业务侧直接做六轴眼在手上转换

#include "CoordinateTransform.h"

// 若机器人协议字段是 (A, B, C) 对应 (RZ, RY, RX)
// 调用前需按真实轴含义把 C 放 rx、B 放 ry、A 放 rz。
CTRobotPose robotPose = CTRobotPose::fromDegrees(
    x, y, z,
    c, b, a);

CTHomogeneousMatrix total = CCoordinateTransform::sixAxisEyeInHandBuildTransform(
    robotPose,
    CTEulerOrder::ZYX,
    handEyeMatrix);

CTVec3D ptRobot = total.transformPoint(CTVec3D(camX, camY, camZ));

整理原则

  • 算法能力放在 IHandEyeCalib
  • 通用坐标变换放在 CoordinateTransform
  • 业务层只负责选择配置和调用
  • 同一能力只保留一套主入口,避免重复接口长期并存