标定demo
标定方法
大致概述:
- 标定板在相机坐标系下的位姿(每张图一帧)
- 通过棋盘格角点 2D 像素坐标 + 棋盘格 3D 物理坐标
- 用 PnP(这里是
solvePnPRansac)解出rvec, tvec - 含义:把标定板坐标系的点变到相机坐标系:
$$
\mathbf{p}{cam} = \mathbf{R}{board\to cam}\mathbf{p}{board} + \mathbf{t}{board\to cam}
$$
- 机器人坐标系与相机坐标系之间的外参(最终目标)
- 额外引入一个“物理约束”:机器人相对标定板的位置已知(dist/height + 板中心偏移 + 固定旋转)
- 于是你能得到
T_robot_board(机器人→标定板) - 再结合
T_board_cam(标定板→相机)推导T_robot_cam
最终你输出的 T_robot_cam 是一个 4×4 齐次矩阵,用于把相机坐标系下的点变到机器人坐标系:
$$
\mathbf{p}{robot} = \mathbf{T}{robot_cam},\mathbf{p}_{cam}
$$
3D->2D的流程:
先假设内参和标定板格子的宽度:
- $f_x=f_y=112.324$
- $c_x=115.284,;c_y=43.4792$
$$
K=
\begin{bmatrix}
112.324 & 0 & 115.284 \
0 & 112.324 & 43.4792 \
0 & 0 & 1
\end{bmatrix}
$$
宽度:s=3.5cm
假设
- 第 3 列第 2 行角点(从 0 开始计数,左上角第一个为0)
$$
P_{board}=(j\cdot s,; i\cdot s,;0)=(2\cdot0.035,;1\cdot0.035,;0)=(0.07,;0.035,;0)
$$
其中,我们假设求出来的R和t如下,真实值:
假设这帧 PnP 真正的位姿(你可以把它当作“真实答案”):
- 旋转:绕 Y 轴 20°
$$
R_y(20^\circ)=
\begin{bmatrix}
\cos20^\circ & 0 & \sin20^\circ \
0 & 1 & 0 \
-\sin20^\circ & 0 & \cos20^\circ
\end{bmatrix}
$$
- 平移(单位 m):
$$
t=(0.02,;-0.01,;0.6)
$$
Step 1:3D 点从棋盘坐标系变到相机坐标系
$$
P_{cam}=R,P_{board}+t
$$
先算 $R,P_{board}$。
$\cos20^\circ \approx 0.9396926,;\sin20^\circ\approx 0.3420201$
$$
\begin{aligned}
X_c &= \cos20^\circ\cdot 0.07 + \sin20^\circ\cdot 0 + 0.02
= 0.9396926\cdot0.07 + 0.02
= 0.0657785 + 0.02
= 0.0857785 \
Y_c &= 1\cdot0.035 + (-0.01) = 0.025 \
Z_c &= -\sin20^\circ\cdot0.07 + \cos20^\circ\cdot0 + 0.6
= -0.3420201\cdot0.07 + 0.6
= -0.0239414 + 0.6
= 0.5760586
\end{aligned}
$$
所以:
$$
P_{cam}\approx(0.0857785,;0.025,;0.5760586)
$$
Step 2:透视投影到归一化平面(除以 Z)
$$
x=\frac{X_c}{Z_c},\quad y=\frac{Y_c}{Z_c}
$$
Step 3:归一化坐标乘以内参得到像素坐标
$$
u=f_x x + c_x,\quad v=f_y y + c_y
$$
最终像素坐标:
$$
\boxed{(u,v)\approx(132.01,;48.35)}
$$
其中,反过来就是RANSAC + PnP(粗解阶段)+目标函数:重投影误差精细化
1 |
|
其中,我们是可以通过机械设备知道标定板中心和机器人底盘中心的大致距离,由于是机器人正对着标定板,所以就只有平移量,但是由于我们标定板的坐标系和机器人的坐标系是不同的,所以还是需要变化,以下是涉及到的坐标系:
1. 核心坐标系定义
程序涉及四个关键坐标系,它们之间的转换关系构成了整个数学模型:
- ${B}$ (Robot Base):机器人基座坐标系(最终目标系)。
- ${C}$ (Camera):相机光心坐标系。
- ${W}$ (World/Board):标定板坐标系,原点位于棋盘格左上角 ID 0。
- ${P}$ (Pixel):图像像素坐标系
1. 图像像素坐标系 ${P}$ (Pixel Coordinate System)
这是最基础的二维坐标系,用于描述点在屏幕/图像上的位置。
- 原点 ($O_p$):位于图像的左上角。
- X轴 ($u$):水平向右。
- Y轴 ($v$):垂直向下。
- 单位:像素 (Pixel)。
注意:它通过相机内参矩阵 $K$ 与相机坐标系相联系。
2. 标定板坐标系 ${W}$ (World/Board Coordinate System)
这是一个用户自定义的右手三维坐标系,用于描述棋盘格上角点的物理位置。
- 原点 ($O_w$):通常定义在棋盘格检测到的第一个角点(ID 0,左上角)。
- X轴 ($X_w$):沿棋盘格横向排列的方向(通常是长边)。
- Y轴 ($Y_w$):沿棋盘格纵向排列的方向(通常是短边)。
- Z轴 ($Z_w$):垂直于标定板平面(根据右手定则确定方向,通常指向板子内部或外部)。
- 单位:米 (m) 或 毫米 (mm)。
3. 相机坐标系 ${C}$ (Camera Coordinate System)
这是以相机光心为原点的三维坐标系。
- 原点 ($O_c$):位于相机透镜的光心。
- Z轴 ($Z_c$):相机的光轴方向,即相机“看”出去的方向。
- X轴 ($X_c$):平行于图像平面的水平轴(向右)。
- Y轴 ($Y_c$):平行于图像平面的垂直轴(向下)。
- 特点:PnP 算法(如
solvePnPRansac)计算出的就是标定板系 ${W}$ 到这个系 ${C}$ 的转换。
4. 机器人基座坐标系 ${B}$ (Robot Base Coordinate System)
这是整个标定系统的最终目标参考系,通常是固定的。
- 原点 ($O_b$):通常位于机器人底座的几何中心。
- Z轴 ($Z_b$):垂直于地面向上。
- X轴 ($X_b$):机器人正前方。
- Y轴 ($Y_b$):根据右手定则确定的侧向方向。
- 意义:所有的视觉结果最终都要通过外参矩阵转换到这个坐标系下,机器人才能根据坐标进行抓取或导航。
理论公式推导
我们要让点在机器人坐标系下和相机坐标系下实现转换。其闭环转换关系如下:
$$P_{robot} = T_{robot}^{board} \cdot P_{board}$$
同时,由相机观测可知:
$$P_{cam} = T_{cam}^{board} \cdot P_{board} \implies P_{board} = (T_{cam}^{board})^{-1} \cdot P_{cam}$$
将 $P_{board}$ 代入第一个方程,得到:
$$P_{robot} = (T_{robot}^{board} \cdot (T_{cam}^{board})^{-1}) \cdot P_{cam}$$
由此得出最终的目标外参矩阵:
$$T_{robot}^{cam} = T_{robot}^{board} \cdot (T_{cam}^{board})^{-1}$$
由于标定板位置固定(通过机械设备计算出来的),程序通过手动输入的物理约束构建 $T_{robot}^{board}$。
旋转矩阵 $R_{robot}^{board}$:代码中定义为 0, 0, 1; -1, 0, 0; 0, -1, 0。
这代表了机器人轴向与标定板轴向的映射关系(例如机器人 X 轴对应标定板 Z 轴)。
平移补偿:
$$t_{robot}^{origin} = t_{robot}^{center} - R_{robot}^{board} \cdot t_{offset}$$
因为物理测量通常是测到标定板中心,但 PnP 算的是左上角 ID 0。需要减去一半的板宽和板高偏移量
简单的demo做完了,后续需要重构以下函数:
1. 空间坐标转换与数学库重构
现状:使用 cv::Mat 处理 4x4 矩阵,频繁进行旋转向量(rvec)与矩阵的转换。
重构方向:全面转向 Eigen。
- 重写逻辑:
- 使用
Eigen::Matrix4d作为位姿载体。 - 使用
Eigen::Quaterniond(四元数)表示旋转。四元数在 Ceres 优化中没有欧拉角的“万向锁”问题,且计算开销小。
- 使用
- 关键函数:
T_robot_cam的逆变换、标定板到相机的相对位姿链。
2. 亚像素精修 (Sub-pixel Corner Refinement)
现状:直接调用 cv::cornerSubPix。
重构方向:基于梯度正交性原理手写迭代解算器。
- 重写逻辑:
- 计算梯度:使用 Sobel 算子获取邻域内每个像素的 $G_x, G_y$。
- 构建方程:根据公式 $\nabla I(p_i)^T \cdot (q - p_i) = 0$,对邻域内所有点构建最小二乘方程 $Ax = b$。
- 迭代求解:使用 Eigen 的
ldlt()求解 $q$ 的位置。
- 面试价值:手写此函数能证明你理解角点提取的物理本质,而不是只会调包。
3. 位姿估计:RANSAC + P3P (初值估计)
现状:调用 cv::solvePnPRansac。
重构方向:手动实现 RANSAC 循环。
- 重写逻辑:
- 随机采样:每次随机选 4 个特征点。
- P3P 求解:手写或引用 P3P 算法(解四次方程)得到 $R, t$ 候选解。
- 内点校验:计算所有点的重投影误差,统计 Inliers。
- 目标:为下一步的 Ceres 非线性优化提供高质量的初始值。
4. 非线性优化 (后端优化层)
现状:OpenCV 内部集成的 LM 算法,黑盒运行。
重构方向:使用 Ceres Solver 实现 BA (Bundle Adjustment)。
- 重写逻辑:
- 定义残差块 (Residual Block):计算 $e = p_{pixel} - K(RP_w + t)$。
- Jacobian 计算:Ceres 会处理自动求导(Auto-diff),计算误差对位姿 $R, t$ 的偏导数。
- 鲁棒核函数:引入
Huber Loss进一步抑制外点干扰,这比 OpenCV 的 RANSAC 阈值更柔性。
- 关键点:这是 VIO 的核心,能够实现“滑动窗口优化”的基础。
5. 状态估计:从 KF 到预积分/图优化
现状:基于单位阵预测的单点卡尔曼滤波。
重构方向:基于 Eigen 的协方差传递与融合。
- 重写逻辑:
- 预测模型:引入运动模型(如果后续加 IMU,则涉及预积分)。
- 状态向量:扩展为 15 维以上(位姿、速度、零偏等)。
- 协方差更新:手动实现 $P = FPF^T + Q$,这需要用 Eigen 处理高维矩阵。