0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

大象机器人水星MercuryX1轮式人形机器人基于物体标记建模的键盘点按操作!

大象机器人科技 来源:大象机器人科技 作者:大象机器人科技 2024-08-06 09:34 次阅读

引言
在现代科技的推动下,机器人在日常生活和工作场景中的应用越来越广泛。本文将介绍MercuryX1,这款先进的机器人如何通过其手臂末端的摄像头识别并确定键盘的键位,从而进行精确的打字操作。通过这一案例,我们将展示MercuryX1在自动化办公领域的潜力,以及其在提升效率和减少人为错误方面的显著优势。

接下里跟随我们的脚步,我们先简单的介绍一下使用到的产品

Product
Mercury X1
水星Mercury X1是一款轮式人形机器人,整体由水星Mercury B1和高性能移动底座组合而成,拥有19个自由度。其单臂为7自由度的类人手臂结构机械臂。整机配备了英伟达Jetson Xavier主控。

移动底座具备丰富的感知能力,包括高性能激光雷达、超声波传感器和2D视觉传感器。其直驱电机驱动系统使其最大运行速度可达1.2m/s,最大爬坡高度为2CM,最大爬坡角度为15度。整机最大续航时间高达8小时。

此外,Mercury X1支持包括ROS、Moveit、Gazebo和Mujoco等主流仿真软件,提升了机器人智能的自主学习和快速迭代能力。

myCobot Pro Adaptive Gripper
是Mercury X1适配的自适应夹爪,提供较大的加持力,和标准的M8航空插头接口

wKgaomawSg-AKi5NAAFVsqhrYDQ673.pngwKgZomawSiGALOtzAAKWeeUHT-Q811.png

Camera Flange
适配于Mercury X1的摄像头模组可以安装在机械臂双臂的末端,并搭配夹爪使用。通过摄像头,实际获取物体的相关信息,并利用这些数据进行机器视觉识别算法处理。通过USB接口,数据被传输到Jetson Nano主控进行进一步处理。

wKgaomawSiyAc5pgAAMVdMx1Zk0943.pngwKgZomawSjSABmkiAAQ1MX7WccU062.png

技术要点
接下来介绍在项目中使用到的技术点。

pymycobot
pymycobot是Elephant Robotics专为其机械臂产品设计的控制库。通过该库,用户可以方便快捷地调用API,以实现对机器人的精确控制和操作。pymycobot提供了丰富的功能接口,简化了编程流程,使开发者能够专注于应用开发。

pymycobot · PyPI

wKgaomawSkqAcomcAAGdxRkTDis914.png

OpenCV
OpenCV是一个开源的计算机视觉库。通过该库,用户可以方便快捷地调用各种图像处理和计算机视觉的API,以实现图像识别、对象检测和图像转换等操作。OpenCV提供了丰富的功能接口,简化了开发流程,使开发者能够专注于应用实现。

OpenCV - Open Computer Vision Library

wKgZomawSlaAIfMSAADyQ_Fzk5Y581.png

Stag
STag是一种稳定的标记码,广泛应用于计算机视觉和机器人定位领域。通过STag,用户可以实现可靠的物体识别和追踪。STag提供了稳健的性能和易于集成的接口,简化了开发者在定位和识别任务中的工作。

GitHub - bbenligiray/stag: STag: A Stable Fiducial Marker System

wKgaomaxfHKAYWyKABDVuHQfu6o851.png

Project
整个项目最主要的功能就机械臂运动控制,机械臂的手眼标定(坐标系的转化)和机器的视觉识别。我们先来介绍最重要的机器视觉识别。

机器视觉识别
想要让X1进行打字,那么它肯定得认识键盘,机器人咋可能自己就认识键盘呢,所以我们要教他认识键盘,并且告诉他那个键在哪个位置。这就用到了STag和OpenCV,STag的标记码能够确定键盘的位置,并且反馈坐标参数

下面这段代码实现是,刷新相机界面获取实时画面,来检测STag码的位置

def stag_identify_loop(self):
       while True:
           self.camera.update_frame()  # 刷新相机界面
           frame = self.camera.color_frame()  # 获取当前帧
           (corners, ids, rejected_corners) = stag.detectMarkers(frame, 11)  # 获取画面中二维码的角度和id
           marker_pos_pack = self.calc_markers_base_position(corners, ids)  # 获取物的坐标(相机系)
           print("Camera coords = ", marker_pos_pack)
           cv2.imshow("按下键盘任意键退出", frame)
           # cv2.waitKey(1)
           # 按下键盘任意键退出
           if cv2.waitKey(1) & 0xFF != 255:
               break


两个STag码是为了确定位置,在用draw在图中画出键盘的位置,在这里需要考虑两个手的情况,当然如果单臂也是能完成的但是我们是要模拟人打字的,左手负责左边的区域,右手负责右边的区域。

def draw(frame, arm):
   global per_right_corners, per_left_corners
   # 将图片灰度
   imGray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
   # 获取图片中二维码的角点
   (corners, ids, rejected_corners) = stag.detectMarkers(imGray, 11)
   # 通过角点获取,二维码相对于相机的位移、旋转向量
   marker_pos_pack = calc_markers_base_position(corners, ids, marker_size, mtx, dist)
   if arm == "left":
       # 获取当前机械臂末端坐标
       stag_cur_coords = np.array(ml.get_base_coords())
       stag_cur_bcl = stag_cur_coords.copy()
       stag_cur_bcl[-3:] *= (np.pi / 180)
       # 通过手眼矩阵获取二维码相对于机械臂基座的坐标
       stag_fact_bcl = Eyes_in_hand(stag_cur_bcl, marker_pos_pack, "left")
       stag_coord = stag_cur_coords.copy()
       stag_coord[0] = stag_fact_bcl[0]
       stag_coord[1] = stag_fact_bcl[1]
       stag_coord[2] = stag_fact_bcl[2]
       # 存入二维码的三维坐标
       keyboard_coords[","] = stag_coord
   else:
       # 获取当前机械臂末端坐标
       stag_cur_coords = np.array(mr.get_base_coords())
       stag_cur_bcl = stag_cur_coords.copy()
       stag_cur_bcl[-3:] *= (np.pi / 180)
       # 通过手眼矩阵获取二维码相对于机械臂基座的坐标
       stag_fact_bcl = Eyes_in_hand(stag_cur_bcl, marker_pos_pack, "right")
       stag_coord = stag_cur_coords.copy()
       stag_coord[0] = stag_fact_bcl[0]
       stag_coord[1] = stag_fact_bcl[1]
       stag_coord[2] = stag_fact_bcl[2]
       # 存入二维码的三维坐标
       keyboard_coords["."] = stag_coord
   # 通过角点获取,二维码相对于相机的位移、旋转向量
   rvecs, tvecs = solve_marker_pnp(corners, marker_size, mtx, dist)
   # 画出坐标系
   cv2.drawFrameAxes(frame, mtx, dist, rvecs, tvecs, 50)
   draw_img = frame

   x1 = corners[0][0][0][0]
   y1 = corners[0][0][0][1]
   x2 = corners[0][0][1][0]
   y2 = corners[0][0][1][1]

   x = x1 - x2
   y = y1 - y2
   # 根据两个交点之间连线的角度获取偏转角
   r = np.arctan(y / x)
   r = abs(r)
   # 获取两个角点之间的距离
   size = abs(x / np.cos(r))
   # 左臂摄像头两个按键x轴之间的距离
   left_x_dis = size * 1.3
   # 左臂摄像头两个按键y轴之间的距离
   left_y_dis = size * 1.35
   # 右臂摄像头两个按键x轴之间的距离
   right_x_dis = size * 1.3
   # 右臂摄像头两个按键y轴之间的距离
   right_y_dis = size * 1.35
   # 按键框的半径
   rad = int(size / 2)
   # 左臂摄像头x轴与第一个字母的偏移距离
   left_add_x = [size * 1.25]
   # 左臂摄像头y轴各行与第一个字母的偏移距离
   left_add_y = [-size * 2, -size * 2.3, -size * 3]
   # 右臂摄像头x轴与第一个字母的偏移距离
   right_add_x = [size * 1.3]
   # 右臂摄像头y轴各行与第一个字母的偏移距离
   right_add_y = [size * 4.1, size * 2.1, size * 1]
   # 获取按键框的中心点
   tray_frame = Path(corners[0][0])
   tray_frame_center_plot = tray_frame.vertices.mean(axis=0)

随后就是通过算法来确定每个键位的坐标如何计算的问题了。将圈选出来的键位存入数组当中,规定左手负责的区域,规定右手负责的区域

   # 左臂键盘布局
   left_keyboard_txt = [
       ["q", "w", "e", "r", "t", "y", "u", "i", "o", "p"],
       ["a", "s", "d", "f", "g", "h", "j", "k", "l"],
       ["z", "x", "c", "v", "b", "n", "m"]
   ]
   # 右臂键盘布局
   right_keyboard_txt = [
       ["m", "n", "b", "v", "c", "x", "z"],
       ["l", "k", "j", "h", "g", "f", "d", "s", "a"],
       ["p", "o", "i", "u", "y", "t", "r", "e", "w", "q"],
   ]
   # 左臂点按的字母
   left_control = ["q", "w", "e", "r", "t",
                   "a", "s", "d", "f", "g",
                   "z", "x", "c", "v", ","]
   # 左臂点按的字母
   right_control = ["y", "u", "i", "o", "p",
                    "h", "j", "k", "l",
                    "b", "n", "m", "."]

这样X1就能够知道键盘是什么,以及相对应的键位在哪里了,接下来就要解决的是机械臂的手眼标定的问题了,需要将目标的物体的坐标系和机械臂末端的坐标系转化到同一个坐标系当中去。

手眼标定-眼在手中
1. 标记检测

使用相机捕获图像,并检测STag标记,获取到标记码的三维坐标。调用 solve_marker_pnp 计算标记在相机坐标系中的位置和方向。

def calc_markers_base_position(corners: NDArray, ids: T.List, marker_size: int, mtx: NDArray, dist: NDArray) -> T.List:
   if len(corners) == 0:
       return []
   rvecs, tvecs = solve_marker_pnp(corners, marker_size, mtx, dist)
   res = []
   for i, tvec, rvec in zip(ids, tvecs, rvecs):
       tvec = tvec.squeeze().tolist()
       rvec = rvec.squeeze().tolist()
       rotvector = np.array([[rvec[0], rvec[1], rvec[2]]])
       Rotation = cv2.Rodrigues(rotvector)[0]
       Euler = CvtRotationMatrixToEulerAngle(Rotation)
       cam_coords = tvec + rvec
       target_coords = cam_coords
   return target_coords


2. 坐标转换

将标记的旋转向量转换为旋转矩阵,再转换为欧拉角,以便于进一步的计算和分析,组合平移向量和旋转向量,得到目标坐标。

cv2.Rodrigues 函数用于在旋转向量和旋转矩阵之间进行转换。这个函数将旋转向量转换为旋转矩阵,或者将旋转矩阵转换为旋转向量。

rotvector = np.array([[rvec[0], rvec[1], rvec[2]]])
Rotation = cv2.Rodrigues(rotvector)[0]

#欧拉角和旋转矩阵的相互转换
def CvtRotationMatrixToEulerAngle(pdtRotationMatrix):
   pdtEulerAngle = np.zeros(3)
   pdtEulerAngle[2] = np.arctan2(pdtRotationMatrix[1, 0], pdtRotationMatrix[0, 0])
   fCosRoll = np.cos(pdtEulerAngle[2])
   fSinRoll = np.sin(pdtEulerAngle[2])
   pdtEulerAngle[1] = np.arctan2(-pdtRotationMatrix[2, 0], (fCosRoll * pdtRotationMatrix[0, 0]) + (fSinRoll * pdtRotationMatrix[1, 0]))
   pdtEulerAngle[0] = np.arctan2((fSinRoll * pdtRotationMatrix[0, 2]) - (fCosRoll * pdtRotationMatrix[1, 2]), (-fSinRoll * pdtRotationMatrix[0, 1]) + (fCosRoll * pdtRotationMatrix[1, 1]))
   return pdtEulerAngle

def CvtEulerAngleToRotationMatrix(ptrEulerAngle):
   ptrSinAngle = np.sin(ptrEulerAngle)
   ptrCosAngle = np.cos(ptrEulerAngle)
   ptrRotationMatrix = np.zeros((3, 3))
   ptrRotationMatrix[0, 0] = ptrCosAngle[2] * ptrCosAngle[1]
   ptrRotationMatrix[0, 1] = ptrCosAngle[2] * ptrSinAngle[1] * ptrSinAngle[0] - ptrSinAngle[2] * ptrCosAngle[0]
   ptrRotationMatrix[0, 2] = ptrCosAngle[2] * ptrSinAngle[1] * ptrCosAngle[0] + ptrSinAngle[2] * ptrSinAngle[0]
   ptrRotationMatrix[1, 0] = ptrSinAngle[2] * ptrCosAngle[1]
   ptrRotationMatrix[1, 1] = ptrSinAngle[2] * ptrSinAngle[1] * ptrSinAngle[0] + ptrCosAngle[2] * ptrCosAngle[0]
   ptrRotationMatrix[1, 2] = ptrSinAngle[2] * ptrSinAngle[1] * ptrCosAngle[0] - ptrCosAngle[2] * ptrSinAngle[0]
   ptrRotationMatrix[2, 0] = -ptrSinAngle[1]
   ptrRotationMatrix[2, 1] = ptrCosAngle[1] * ptrSinAngle[0]
   ptrRotationMatrix[2, 2] = ptrCosAngle[1] * ptrCosAngle[0]
   return ptrRotationMatrix

#合并旋转和平移向量
cam_coords = tvec + rvec
target_coords = cam_coords

他们本身不是一个世界的人,现在强行转化到一个世界里,就能够互相知道在哪里了!这样就能够直接获取到键盘键位的result了 。

机械臂的运动控制
当我们有了目标物体的坐标之后,就到我们的X1闪亮登场了,开始执行运动,这里我们用到pymycobot来控制机械臂运动。

   r是右手的控制,l是左手的控制
   mr = Mercury("/dev/ttyACM0")
   ml = Mercury("/dev/ttyTHS0")
   #发送角度位置和速度给机械臂,
   mr.send_angles(mr_pos, sp)
   ml.send_angles(ml_pos, sp)
   #发送坐标和速度给机械臂
   mr.send_coords(mr_pos, sp)
   ml.send_coords(ml_pos, sp)


就是将目标的坐标传递给机械臂去运动,就能实现打字了,我们一起来看看运动的效果如何。

总结
通过本文,我们详细介绍了Mercury X1轮式人形机器人在打字任务中的应用实例。Mercury X1凭借其19自由度的灵活结构、丰富的感知能力和高性能的控制系统,展示了在自动化办公领域的巨大潜力。结合适配的摄像头模组和先进的机器视觉算法,Mercury X1能够精准识别并操作键盘,显著提升了工作效率和准确性。随着技术的不断进步,我们期待Mercury X1在更多领域展现其卓越的性能,为智能自动化带来更多可能性。

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 机器人
    +关注

    关注

    211

    文章

    28373

    浏览量

    206896
  • 开源
    +关注

    关注

    3

    文章

    3305

    浏览量

    42460
  • 机械臂
    +关注

    关注

    12

    文章

    513

    浏览量

    24550
  • 人形机器人
    +关注

    关注

    2

    文章

    442

    浏览量

    16547
收藏 人收藏

    评论

    相关推荐

    轮式机器人

    我是新人,求帮助啊,明天需要提交轮式机器人应用的报告,求大神给点建议,可用轮式机器人应用于那些方面,要求实际可行,应用于生活,农业,军事都可以,谢谢啦
    发表于 04-17 16:32

    为什么人形机器人更讨人喜欢?

    。相比之下,人形机器人(又称“仿人机器人”或“类人机器人”)比那些非人形机器人更讨人喜欢。从心理
    发表于 05-12 09:55

    桁架机器人核心配件介绍

    桁架机器人核心配件介绍1.控制器在数控机床机器人控制器方面,目前通用的多轴控制器平台主要分为以嵌入处理器(DSP,POWERPC)为核心的运动控制卡和以工控机加实时系统为核心的PLC
    发表于 11-22 12:08

    机器人基础书籍

    列举部分学习过程中接触的部分书籍,部分有中文版,部分有更新版本。1.机器人基础书籍适合入门的书籍:机器人机器人建模规划与控制
    发表于 05-22 06:53

    机器人接触物体探测的接触方式有哪些?

    机器人接触物体探测技术电路设计
    发表于 03-02 11:06

    基于TRIZ轮式机器人驱动轮的研究

    基于TRIZ轮式机器人驱动轮的研究 根据亚太机器人大赛规则,要求机器人车轮与地面有较大的摩擦力,以保证机器人在规定的时间内完成比赛任务。文中
    发表于 09-13 07:12

    六足机器人轮式移动方式的优势

    科学技术发展和人类社会进步的需要。地形不规则和崎岖不平是这些环境的共同特点。从而使轮式机器人和履带机器人的应用受到限制。以往的研究表明轮式
    发表于 09-13 06:47

    机器人是什么?

    自主机器人。这些都是机器人的智能艺术。除了这个被广泛接受的分类,机器人可以根据它们的运动方式和工作环境进行分类,如轮式机器人、腿
    发表于 03-31 10:31

    【开发教程1人形街舞机器人-套件检测教程

    多自由度人形双足舞蹈机器人套件检测教程——机器人开发系列配套资料:https://www.fengke.club/GeekMart/su_fV1WzKsGQ.jsp 配套视频:http
    发表于 04-22 14:14

    【教程1人形街舞机器人-套件检测教程

    多自由度人形双足舞蹈机器人——疯壳·机器人开发系列套件检测教程内容简介本文档主要介绍在如何验证多自由度人形双足街舞机器人套件正常,包括具体线
    发表于 08-12 15:55

    轮式机器人怎么样

    ,人类友好型机器人开始在实体店进行实时盘点,这使得超市能够减少每种产品的货架空间,并增加给定时间内可以携带的库存量。轮式机器人甚至可以进军宾馆,提供从入住到客房服务的接待服务。 对于这
    发表于 11-09 07:49

    大象机器人首发万元级水星Mercury人形机器人系列

    水星Mercury机器人系列共有三款产品:水星Mercury A1 七轴协作机械臂和水星Mercury B
    发表于 01-03 09:59 275次阅读
    ​<b class='flag-5'>大象</b><b class='flag-5'>机器人</b>首发万元级<b class='flag-5'>水星</b>Mercury<b class='flag-5'>人形</b><b class='flag-5'>机器人</b>系列

    技术融合与创新大象机器人水星Mercury X1人形机器人案例研究!

    引言 在科技迅速发展的当下,人形机器人正变得日益重要,其应用范围从工业自动化到服务业不断扩展。本文将通过Mercury X1大象人形机器人
    的头像 发表于 04-28 14:18 569次阅读
    技术融合与创新<b class='flag-5'>大象</b><b class='flag-5'>机器人</b><b class='flag-5'>水星</b>Mercury X<b class='flag-5'>1</b><b class='flag-5'>人形</b><b class='flag-5'>机器人</b>案例研究!

    大象机器人完成Pre-B融资,致力打造全新机器人生态!

    近日,深圳市大象机器人科技有限公司(以下简称「大象机器人」)近日完成Pre-B融资,本轮融资由清辉投资领投、云卓资本跟投,资金将用于
    的头像 发表于 05-22 14:46 891次阅读

    七腾机器人:防爆轮式机器人-四八驱全新上线

    今日,七腾机器人有限公司(以下简称“七腾机器人”)推出全新产品:防爆轮式机器人-四八驱。该款产品是七腾
    的头像 发表于 10-21 16:32 174次阅读
    七腾<b class='flag-5'>机器人</b>:防爆<b class='flag-5'>轮式</b><b class='flag-5'>机器人</b>-四<b class='flag-5'>轮</b>八驱全新上线