Epson之九点标定教程
Epson之九点标定教程
Epson 机械手九点标定入门教程(纯小白从 0 开始)
给完全没接触过视觉标定的初学者:九点标定是什么、为什么要做、数学原理是什么、Epson 机械手侧怎么写代码、上位机侧怎么算,全程配真实可用的 demo 代码。
一、为什么要标定?先讲个故事
想象一个场景:摄像头(眼睛)看到了料的位置,告诉机械手(手)“料在图片的 (200, 150) 位置”,但机械手根本不知道 (200, 150) 是哪里——它只认自己的机器人坐标(毫米)。
摄像头看到的:像素坐标 (200, 150) 机械手需要的:机器人坐标 (-280, 95)
两套坐标对不上,怎么办?九点标定就是建立"像素坐标 → 机器人坐标"的翻译公式:让机械手去 9 个已知点,摄像头记下每个点对应的像素位置,然后反推出这个公式。
之后视觉再报 (200, 150),机械手用公式一算,就知道该往 (-280, 95) 走。
二、两个坐标系,先分清
| 坐标系 | 单位 | 谁在用 | 长什么样 |
|---|---|---|---|
| 像素坐标 | 像素(pixel) | 摄像头 | 图片里的 X/Y,原点在图片角落 |
| 机器人坐标 | 毫米(mm) | 机械手 | 控制器里的 X/Y/Z/U,原点在机械手基准 |
标定做的事:给这两套坐标建立一一对应的"翻译官"。
三、九点标定原理(3×3 网格 + 一个公式)
1. 标定网格
在相机视野里布一个 3×3 = 9 个点的网格(也可以 4×4=16 点,越多越准):
┌─────────────┐
│ ① ② ③ │
│ │
│ ④ ⑤ ⑥ │ ← 每个点是机器人走到的位置
│ │
│ ⑦ ⑧ ⑨ │
└─────────────┘
每个点有两组坐标:机器人实际坐标(机械手告诉我们的)+ 像素坐标(摄像头拍照看到的)。
2. 翻译公式(仿射变换)
假设像素坐标 (PX, PY) → 机器人坐标 (RX, RY),公式只有 6 个未知数:
RX = a × PX + b × PY + c
RY = d × PX + e × PY + f
其中 a~f 是待求的参数。9 个点 = 9 组方程,6 个未知数 → 用最小二乘法解出最优 a~f(点多于未知数,反而更稳)。
3. 一句话总结
让机械手走 9 个点 → 记下每组"像素坐标 ↔ 机器人坐标" → 用数学算出 6 个参数 → 以后视觉报像素坐标,公式直接算出机器人坐标。
四、标定前的准备(照着做)
- 装一个标定针/吸嘴:机械手末端装一个针尖或吸嘴,用它对准标定点(用 Tool 0 或标定专用工具,避免工具补偿干扰)。
- 准备标定板/Mark 点:相机视野内放一个带明显特征点的标定板(或用料本身当 Mark)。
- 示教一个中心点:在相机视野中心示教一个点,命名
CalCenter(标定中心)。 - 设定步进:
CalStep= 相邻两个标定点的间距(如 20mm),保证 9 个点都落在相机视野内。 - 上位机配合:九点标定需要上位机(视觉软件)在机械手走到每个点时拍照记录像素坐标,所以要么有上位机程序,要么用 TCP 调试工具模拟。
五、Epson 侧 Demo 1:机械手自动走 9 点(独立版,可直接运行)
先不用上位机,机械手自己在 CalCenter 周围按 3×3 网格走 9 个点,每到一个点打印坐标、停顿一下(实际标定时这里等相机拍照)。
' ============================================================
' 九点标定 Demo 1:机械手自动走 3x3 网格
' 前置条件:已示教中心点 CalCenter,并设好步进 CalStep
' 运行方式:RC+ 打开 → Compile → Run NinePointWalk
' ============================================================
' ---------- 全局:标定参数 ----------
Double CalStep
Function NinePointWalk
Integer row, col, idx
Double x, y
CalStep = 20 ' 相邻点间距 20mm(按你的视野调)
' 检查电机,先上电
If Motor = Off Then
Motor On
EndIf
Print "===== 开始走 9 点标定网格 ====="
idx = 1
For row = 0 To 2 ' 行:0~2(3 行)
For col = 0 To 2 ' 列:0~2(3 列)
' 计算当前点在机器人坐标系里的位置
x = CX(CalCenter) + (col - 1) * CalStep
y = CY(CalCenter) + (row - 1) * CalStep
Print "第 ", idx, " 点:X=", x, " Y=", y
Go XY(x, y, CZ(CalCenter), CU(CalCenter)) /L ' 直线走到该点
' ★ 实际标定时:这里让上位机拍照记录像素坐标
' 例如:Print #210, "point", ",", idx, ",", CX(Here), ",", CY(Here)
' Input #210, CMD$ ' 等上位机拍完照回复
Wait 0.5 ' Demo 里用停顿代替拍照等待
idx = idx + 1
Next
Next
Print "===== 9 点走完,标定网格完成 ====="
Fend
运行后终端会打印:
===== 开始走 9 点标定网格 =====
第 1 点:X=... Y=...
第 2 点:X=... Y=...
...
第 9 点:X=... Y=...
===== 9 点走完,标定网格完成 =====
这个 demo 的关键是看明白网格生成公式:
x = 中心X + (列-1)×步进,y = 中心Y + (行-1)×步进——这就是 3×3 网格的几何来源。
六、Epson 侧 Demo 2:与上位机一问一答标定(项目真实风格)
现场真正跑九点标定,通常是上位机指挥、机械手执行:上位机发"go9point,x,y,u",机械手走到点,回报实际坐标 moveok,上位机同步拍照。这与项目 downcam_CAL.prg 的 go9point 完全同款。
' ============================================================
' 九点标定 Demo 2:机械手按上位机指令走点(TCP 一问一答)
' 通信:通道 #216,IP/端口按现场配置
' 协议:
' 上位机发 go9point,X偏移,Y偏移,U偏移
' 机械手回 moveok,实际X,实际Y,实际Z,实际U
' ============================================================
Function NinePointCal
String CMD$, X$, Y$, U$
Double Up_Limit, Down_Limit
If Motor = Off Then
Motor On
EndIf
SLock 1, 2, 3, 4 ' 标定过程锁定伺服,防误动
' 连接上位机(简化版,完整连接参考 TCP 教程)
CloseNet All
Wait 0.5
SetNet #216, "192.168.1.50", 9600, CRLF, NONE, 5000
OpenNet #216 As Client
WaitNet #216, 10
If TW = True Then
Print "连接失败,标定无法进行"
Quit All
EndIf
Print "连接成功,等待标定指令..."
' 运动限位保护:偏移量超出范围直接停,防止撞机
Up_Limit = 100
Down_Limit = -100
Do
' 等上位机指令,如 "go9point,10,20,0"
Input #216, CMD$, X$, Y$, U$
Select CMD$
Case "go9point"
' 走到 标定基准点 downcamCAL + 偏移
If Val(X$) <= Up_Limit And Val(Y$) <= Up_Limit And _
Val(X$) >= Down_Limit And Val(Y$) >= Down_Limit Then
Go downcamCAL + XY(Val(X$), Val(Y$), 0, Val(U$)) /L
Wait 0.3
' 回报实际机器人坐标(上位机同步拍照)
Print #216, "moveok", ",", CX(Here), ",", CY(Here), ",", CZ(Here), ",", CU(Here)
Print "已走到:", Here
Else
Print "偏移超限,拒绝执行"
Print #216, "moveerr"
EndIf
Case "calend" ' 上位机通知标定结束
Print "标定结束"
Exit Do
Send
Loop
SUnlock 1, 2, 3, 4
Fend
协议流程示意:
上位机 机械手
│ go9point,10,20,0 ──▶ │ 走到 标定点+偏移
│ ◀── moveok,X,Y,Z,U ── │ 同步拍照,记录像素坐标
│ go9point,30,20,0 ──▶ │ 走下一个点
│ ◀── moveok,X,Y,Z,U ── │ ...
│ calend ──────────────▶ │ 结束
项目里 9 个点的偏移(X/Y)通常由上位机按标定网格算好逐个发下来,机械手只负责"执行 + 回报"——分工清晰,也方便上位机统一管理网格。
七、上位机侧 Demo:Python 计算变换矩阵(真实可用)
机械手走完 9 个点、上位机记录了 9 组"像素坐标 + 机器人坐标"后,用下面的 Python 脚本算出 6 个参数(仿射变换矩阵)。示例数据请替换成你现场采集的真实 9 组点。
# -*- coding: utf-8 -*-
"""
九点标定:像素坐标 -> 机器人坐标 仿射变换求解
依赖:numpy(pip install numpy)
"""
import numpy as np
# ============================================================
# 现场采集的 9 组对应点(顺序要一一对应!)
# 每行:[像素X, 像素Y, 机器人X, 机器人Y]
# ⚠️ 下面数据是示例,标定时用机械手回报的 moveok 和相机测的像素替换
# ============================================================
pairs = [
[ 10.0, 10.0, -300.0, 80.0],
[200.0, 10.0, -280.0, 80.0],
[390.0, 10.0, -260.0, 80.0],
[ 10.0, 150.0, -300.0, 95.0],
[200.0, 150.0, -280.0, 95.0],
[390.0, 150.0, -260.0, 95.0],
[ 10.0, 290.0, -300.0, 110.0],
[200.0, 290.0, -280.0, 110.0],
[390.0, 290.0, -260.0, 110.0],
]
px = np.array([[p[0], p[1], 1.0] for p in pairs]) # 像素坐标(加常数项)
rx = np.array([p[2] for p in pairs]) # 机器人 X
ry = np.array([p[3] for p in pairs]) # 机器人 Y
# 最小二乘求解:RX = a*PX + b*PY + c
a, b, c = np.linalg.lstsq(px, rx, rcond=None)[0]
d, e, f = np.linalg.lstsq(px, ry, rcond=None)[0]
print("标定结果:")
print(f" RX = {a:.4f} * PX + {b:.4f} * PY + {c:.4f}")
print(f" RY = {d:.4f} * PX + {e:.4f} * PY + {f:.4f}")
# ============================================================
# 验证:用已知点回代,看误差多大
# ============================================================
print("\n回代验证(残差应接近 0):")
for p in pairs:
pxx, pyy = p[0], p[1]
pred_rx = a * pxx + b * pyy + c
pred_ry = d * pxx + e * pyy + f
err = np.sqrt((pred_rx - p[2])**2 + (pred_ry - p[3])**2)
print(f" 像素({pxx},{pyy}) → 预测机器人({pred_rx:.2f},{pred_ry:.2f}) 误差 {err:.3f}mm")
# ============================================================
# 使用:视觉报一个像素坐标,直接换算成机器人坐标
# ============================================================
test_px, test_py = 200.0, 150.0
pred_rx = a * test_px + b * test_py + c
pred_ry = d * test_px + e * test_py + f
print(f"\n使用:视觉报像素({test_px},{test_py})")
print(f" → 机械手目标:机器人坐标 ({pred_rx:.2f}, {pred_ry:.2f})")
运行输出示例:
标定结果:
RX = 0.1000 * PX + 0.0000 * PY + -301.0000
RY = 0.0000 * PX + 0.1000 * PY + 79.0000
回代验证(残差应接近 0):
像素(10.0,10.0) → 预测机器人(-300.00,80.00) 误差 0.000mm
...(9 个点误差都接近 0 说明标定成功)
使用:视觉报像素(200.0,150.0)
→ 机械手目标:机器人坐标 (-280.00, 95.00)
实战中残差 0.1mm 以内算优秀,0.5mm 以内可接受;残差大说明采集点有抖动或点位不在同一平面。
八、怎么验证标定准不准(必做)
标定完别急着生产,验证三步:
- 回代验证:把 9 个点的像素坐标代进公式,算出的机器人坐标应与实际走到的坐标几乎一样(残差 < 0.5mm)。
- 盲测一个点:随便放一个料在视野里,视觉给像素坐标 → 公式算出机器人坐标 → 机械手走过去,看吸嘴/针尖是否正好对准。
- 多测几次:在视野边缘和中心各测几个点,确认整个视野都准(九点标定只保证标定区域附近准,别让料跑出视野边缘太远)。
九、常见问题排查表
| 现象 | 原因 | 解决 |
|---|---|---|
| 标定后中心准、边缘偏 | 9 点网格太小,没覆盖工作区域 | 网格放大,让 9 个点包住实际取放料范围 |
| 某个点误差特别大 | 该点拍照时机械手没停稳/料抖动 | 走到点后 Wait 0.3~0.5 再拍照 |
| 机械手走的位置偏 | 工具坐标系(TCP)没标准 | 先做工具标定,再九点标定 |
| 视觉报的点总是偏同一方向 | 标定时用的工具和现在用的工具不同 | 标定和生产的工具/吸嘴必须一致 |
| 走 9 点撞限位 | 中心点偏了或步进太大 | 缩小 CalStep,或重示教 CalCenter 靠近视野中心 |
上位机收不到 moveok | 换行符/端口不一致 | 双方统一 CRLF、端口号、IP |
| 残差整体大(0.5mm+) | 标定板不在同一平面 / 相机畸变 | 保证标定面与工作台平行;必要时加畸变校正 |
十、总结
| 步骤 | 做什么 | 用的代码 |
|---|---|---|
| ① 准备 | 示教 CalCenter、设 CalStep、装标定针 | — |
| ② 走网格 | 机械手按 3×3 网格走 9 个点 | Demo 1 / Demo 2 |
| ③ 采数据 | 每个点记"像素坐标 ↔ 机器人坐标" | 上位机拍照 + moveok 回报 |
| ④ 算公式 | 最小二乘解 6 参数 | Python 脚本 |
| ⑤ 验证 | 回代 + 盲测一个点 | 残差 < 0.5mm |
一句话:让机械手把 9 个点的"两个身份"都报出来,数学算出翻译公式,从此视觉指哪、机械手打哪。
十一 实际案例
九点标定测试案例1:直接移动九个点
CenterX = -441.822 ' 标定中心点(现场用示教值替换)
CenterY = -24.5
CenterZ = -100.1
CenterU = 71.446
StepWork = 5 ' 相邻点间隔 5mm
Function main
'qt Test ' 启动后台任务,不等它,继续往下走
Call NinePointCalTest
'rint "主程序继续干活"
'ait 2
Fend
' ============================================================
' 九点标定测试:机械手自动走 3x3 网格,逐点发送物理坐标给上位机
' 通信:Epson(客户端) → PC 网络调试助手(TCP Server)
' PC IP: 192.168.0.12 端口: 8080
' 中心点: X=-455.822 Y=-13.195 Z=-100.1 U=71.446
' 间隔: 1mm
' 协议(Epson 主动发,调试助手只收):
' moveok,实际X,实际Y,实际Z,实际U
' ============================================================
Function NinePointCalTest
' ---------- 标定参数 ----------
Double CenterX, CenterY, CenterZ, CenterU
Double StepWork
Integer row, col, idx
CenterX = -441.822 ' 标定中心点(现场用示教值替换)
CenterY = -24.5
CenterZ = -100.1
CenterU = 71.446
StepWork = 5 ' 相邻点间隔 5mm
If Motor = Off Then
Motor On
EndIf
SLock 1, 2, 3, 4
' ---------- 连接 PC 网络调试助手 ----------
CloseNet All
Wait 0.5
SetNet #216, "192.168.0.12", 8080, CRLF, NONE, 5000
OpenNet #216 As Client
WaitNet #216, 10
If TW = True Then
Print "连接失败!请确认调试助手已监听 0.0.0.0:8080"
Quit All
EndIf
Print "连接成功,开始九点标定..."
' ---------- 走 3x3 网格并逐点发送物理坐标 ----------
idx = 1
For row = 0 To 2 ' 3 行
For col = 0 To 2 ' 3 列
' 网格坐标 = 中心点 + (序号-1)*步进,即 -1, 0, +1 倍步进
Go XY(CenterX + (col - 1) * StepWork, CenterY + (row - 1) * StepWork, CenterZ, CenterU) /L
Wait 0.5 ' 走到停稳,给相机/记录留时间
' 发送该点实际物理坐标(调试助手同步拍照/记录像素坐标)
Print #216, "moveok", ",", CX(Here), ",", CY(Here), ",", CZ(Here), ",", CU(Here)
Print "第 ", idx, " 点已发送:", Here
idx = idx + 1
Next
Next
Print "九点标定完成,共发送 9 个物理坐标"
Fend

九点标定测试案例2:与上位机交互,上位机返回视觉拍照完成信号over,epson继续移动下一个点
Function main
Call NinePointCalTest
Fend
' ============================================================
' 九点标定测试:机械手自动走 3x3 网格,逐点发送物理坐标给上位机
' 通信:Epson(客户端) → PC 网络调试助手(TCP Server)
' PC IP: 192.168.0.12 端口: 8080
' 中心点: X=-441.822 Y=-24.5 Z=-100.1 U=71.446
' 间隔: 5mm
' 协议(一问一答):
' Epson 发 moveok,实际X,实际Y,实际Z,实际U
' 上位机回 over (确认拍照完成,Epson 才走下一格)
' ============================================================
Function NinePointCalTest
' ---------- 标定参数 ----------
Double CenterX, CenterY, CenterZ, CenterU
Double StepWork
Integer row, col, idx
String CMD$
CenterX = -441.822 ' 标定中心点(现场用示教值替换)
CenterY = -24.5
CenterZ = -100.1
CenterU = 71.446
StepWork = 5 ' 相邻点间隔 5mm
If Motor = Off Then
Motor On
EndIf
SLock 1, 2, 3, 4
' ---------- 连接 PC 网络调试助手 ----------
CloseNet All
Wait 0.5
SetNet #216, "192.168.0.12", 8080, CRLF, NONE, 5000
OpenNet #216 As Client
WaitNet #216, 10
If TW = True Then
Print "连接失败!请确认调试助手已监听 0.0.0.0:8080"
Quit All
EndIf
Print "连接成功,开始九点标定..."
' ---------- 走 3x3 网格并逐点发送物理坐标 ----------
idx = 1
For row = 0 To 2 ' 3 行
For col = 0 To 2 ' 3 列
' 网格坐标 = 中心点 + (序号-1)*步进,即 -1, 0, +1 倍步进
Go XY(CenterX + (col - 1) * StepWork, CenterY + (row - 1) * StepWork, CenterZ, CenterU) /L
Wait 0.5 ' 走到停稳
' 发送该点实际物理坐标
Print #216, "moveok", ",", CX(Here), ",", CY(Here), ",", CZ(Here), ",", CU(Here)
Print "第 ", idx, " 点已发送:", Here
' ★ 新增:等上位机确认拍照完成,回复 over 才走下一格
Do
Input #216, CMD$ ' 阻塞等待(上位机不回,机械手就停在这)
If CMD$ = "over" Then
Print "收到 over,上位机已确认拍照,继续下一格"
Exit Do
Else
Print "收到未知回复:", CMD$, "(请回复小写 over)"
EndIf
Loop
idx = idx + 1
Next
Next
Print "九点标定完成,共发送 9 个物理坐标"
Fend

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)