在python中如何使用apriltag视觉定位技术

前一段时间在研究强化学习,想用在机械臂相关的任务上,强化学习中有一个比较重要的部分就是reward的设计,例如机械臂抓取任务,机械臂需要较为精准的到达目标物体的上方,然后再抓取。在这个过程中,如何获得机械臂抓手的位姿,然后判断它与目标物体的相对位置关系就比较重要,我们可以根据抓手与目标物体的距离/IOU等指标判断机械臂是否到达一个合适的位置,如果位置合适的话,reward就高一些,否则reward就低。

在这里插入图片描述

由于我这边是一个纯视觉的环境,所以经过调研,AprilTag视觉定位技术是一个比较精准的技术,以前在项目中也测试过,在5米的位置,10cm以上的tag的大小,位置的准确度能达到<3cm。这次用在机械臂的环境中,由于机械臂大小限制,我用的是1.7cm大小的tag,在0.5米外放置相机,像素分辨率1280*720,也能达到<3cm的精度,还是比较准确的。当然建议在有条件的情况下,尽量选择tag size更大一些的,分辨率更高一些的,精准度更有保障。apriltag本身二维码大家可以检索“openmv apriltag”就可以找到生成方法。

1,坐标系

在apriltag使用中,理清楚坐标系非常重要,网上文章相互抄袭,讲得清楚的凤毛麟角。我经过实验后,下面比较严谨的apriltag坐标系讲得清楚一些。以下图为例,我直接将坐标系渲染在了图片上,其中蓝色为x坐标轴,绿色为y轴,红色为z轴。坐标原点在二维码的中心点(图片渲染的不太对,前几天截图的时候没有注意,后面也没有环境能再截了,所以大家将就一下~~)。
在这里插入图片描述

大家可能会有个疑惑,二维码是正方形的,正方形的哪个边是x,哪个边是y呢?以上面第一张图为例,这个二维码是默认打印出来的,正着放(文字在二维码正下方,代表是正着放)的话,横向就是x轴,正方向朝右,竖向就是y轴,正方向朝下。

apriltag检测结果是二维码坐标系在相机坐标系中的位置(旋转+平移),所以在同一相机坐标系中检测出2个二维码的话,就可以获取这2个二维码之间的关系。

在我贴二维码的过程中,文字都在二维码的左侧,也就是让二维码躺平贴上去的。所有二维码我都是这样贴的,主要目的是人工可以更加方便的对结果进行检查,因为简化了二维码之间的坐标系的旋转关系(也说是2个二维码并排放在一起的话,它们之间的旋转角基本都为0),这点大家仅供参考,不是必须这样的。

2,结果呈现

下面的视频是我录的一个视频,把通过apriltag定位出来的信息放在了视频中。我在机械臂不会动的位置放了一个二维码,在桌面上的目标物体上放了一个二维码,下图中带颜色的box是我根据检测结果,在二维码坐标系原点位置,渲染了一个长宽高为5.6cm, 3cm, 3cm的box。图片中的tag_obj就是目标物体。

distance to tag_obj就是图片中两个二维码坐标系原点的物理距离,单位米。

coord in tag_obj: 以目标物体上贴的二维码坐标系(下面简称目标坐标系)为父坐标系,抓手上的二维码坐标系(下面简称抓手坐标系)为子坐标系,coord就是子坐标系在父坐标系中的坐标,这2个坐标系之间就有外参,coord也就是外参中的平移部分。

euler in tag_obj: 上述外参中的旋转角,本质上代表将父坐标系旋转到与子坐标系对齐,分别在xyz三个坐标轴上的旋转角度。

iou: 代表将抓手上面的box转换到目标坐标系后,在目标坐标系yz平面上与目标物体上的box之间的IOU。iou与reward与我研究的强化学习有关系,这点大家不感观兴趣的不用关注。

episode

3,代码讲解

我已经将apriltag的代码与lerobot环境打通了,代码地址:git@github.com:hxdoit/lerobot.git,在分支:rl上,文件名:lerobot/common/robot_devices/control_utils.py从310行开始。apriltag的代码相对比较独立,大家也可以单独使用。需要pip install apriltag就可以安装依赖。

apriltag需要相机的内参,我是用ros中的相关工具标定出的内参。注意一下,正常标定应该是用的原始相机输出的图像(畸变校正前)进行标定,但我们购买的相机一般内部应该都处理好了,输出的是无畸变的图像,所以标定出来的结果从理论上可能有一些不准,但不太影响,在使用时我这边发现标定出来的畸变参数不使用更加准确,只使用内参即可。

if camera_name == 'desktop':
        print('desktop')
        K = np.array([[1592.776294, 0.000000, 655.148278],
                      [0.000000, 1595.337130, 402.386737],
                      [0.000000, 0.000000, 1.000000]])
        distCoeffs = np.array([0.089836, 0.058097, 0.029668, 0.028918, 0.000000])
    else:
        print('other')
        K = np.array([[671.907962, 0.000000, 639.211904],
                      [0.000000, 674.667340, 360.929253],
                      [0.000000, 0.000000, 1.000000]])
        distCoeffs = np.array([0.109473, -0.127263, 0.000050, 0.003589, 0.000000])
    cameraparam = [K[0, 0], K[1, 1], K[0, 2], K[1, 2]]
    # 不用效果更好
    distCoeffs = None

下面代码用于计算2个二维码坐标系之间的外参:

tag_grasp_2_obj = compute_transform(result, tag_obj_result)

下面代码可以将抓手坐标系中的坐标,通过外参转换到目标坐标系:

temp = (rot_between_2tags @ virtual_obj_on_grasp_3d_corners.T).T + trans_between_2tags

其它代码比较容易理解,不多讲解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值