大象机器人六轴协作机械臂myCobot 320 进行手势识别

引言

我是一名专注于机器学习和机器人技术自由者。我的热情始于大学期间的人工智能课程,这促使我探索人机交互的新方法。尤其对于机械臂的操作,我一直想要简化其复杂性,使之更加直观和易于使用。

这个项目的灵感源自于我对创新技术的热爱以及对改善人机互动方式的追求。我的目标是开发一个基于手势的机械臂控制系统,使非专业人士也能轻松操作。为此,我选择了Google的MediaPipe库进行手势识别,并以myCobot 320 m5作为实验平台。

技术概述

Google MediaPipe

MediaPipe是由Google开发的一个开源跨平台框架,专门用于构建各种感知管道。这个框架提供了丰富的工具和预先构建的模块,使得开发者能够轻松地构建和部署复杂的机器学习模型和算法,尤其在图像和视频分析方面。

MediaPipe的一个显著特点是它对实时手势和面部识别的支持。它能够高效地处理视频流,并实时识别和追踪人的手势、面部特征等。这种能力使其在交互式应用程序、增强现实(AR)、虚拟现实(VR)以及机器人技术中变得极其有用。

你可以尝试试用一下手势识别在线功能,无需安装。

https://mediapipe-studio.webapps.google.com/home

它的简单易用的API和丰富的文档使得更容易集成这个框架,非常适合使用在机器学习和计算机视觉领域当中。

pymycobot

pymycobot 是一个用于与 mycobot 机械臂进行串行通信和控制的 Python API。这个库是为了方便开发者使用 Python 语言控制 mycobot 机械臂而设计的。它提供了一系列的函数和命令,让用户可以通过编程方式控制机械臂的动作和行为。例如,用户可以使用该库获取机械臂的角度、发送角度指令来控制机械臂的移动,或者获取和发送机械臂的坐标信息。

使用这个库唯一的标准是,得使用mycobot 系列的机械臂,这是专门为mycobot进行适配的一款机械臂。

产品介绍

myCobot 320M5 stack

myCobot 320 M5 是大象机器人开发的一款面向用户的六轴协作机械臂。它具有350mm的工作半径和最大1000g的负载能力。该机械臂适用于开放的ROS仿真开发环境,并包含运动学正逆解算法。它支持多种编程语言,包括Python、C++、Arduino、C# 和 JavaScript,且兼容Android、Windows、Mac OSX和Linux平台。myCobot 320 M5的多功能性使其适用于多种开发和集成应用。

2D 相机

一个能够安装在mycobot320末端的2D相机,用USB数据线进行通信。能够呈现机械臂末端所看到的视野。

开发过程

项目架构

我将该项目主要分为三个木块功能:

Gesture Recognition: 主要用来处理手势的识别,能够返回信息当欠手势是什么,比如说竖大拇指等等。

Robotic Arm Control:主要功能用于设置机械臂的运动控制,例如坐标控制,角度控制等等。

Program logic:用来处理程序运行的逻辑,设置确认手势时间,重置识别时间等,后续将一一详细介绍。

编译环境

操作系统:windows 11

编程语言:Python3.9+

使用的库:opencv,mediapipe,pymycobot,time

手势的识别

做识别首先得获得到相机的一个画面,这里我们就用到了opencv库来获取相机的画面

import cv2# 获取相机流,默认的摄像头-0 外接的摄像头按照顺序往上- 1,2,3
cap = cv2.VideoCapture(1)# 持续获取相机画面
while cap.isOpened():
    #获取当前图像画面
    ret, frame = cap.read()
    # 将BGR图像转换为RGB
    rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)    
    # 在电脑中显示画面
    cv2.imshow('gesture control',frame)
    # 按下 'q' 键退出,避免死循环
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break    

到这里图像画面就获取成功了,接下来我们用mediapipe手势进行识别。

import mediapipe as mp# 初始化MediaPipe Hands模块
mp_hands = mp.solutions.hands
hands = mp_hands.Hands()
mp_draw = mp.solutions.drawing_utils# 处理图像并检测手部
result = hands.process(rgb_frame)if result.multi_hand_landmarks:
    for hand_landmarks in result.multi_hand_landmarks:
        mp_draw.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)

这是识别手势之后的输出的结果,它能够精准的识别出手上的每个关节,并且将每个关节的点都命名。MediaPipe Hands 提供了21个手部关键点(landmarks),这些关键点共同描绘了手的结构,包括手腕、各个手指的各个关节。以大拇指举例子,一共有四个关节,从下往上分别是CMC,MCP,IP,TIP.

cmc: Carpometacarpal Joint
mcp:Metacarpophalangeal Joint
ip:Interphalangeal Joint
tip:tip

有了这些还不够,我们要让他识别特定的手势,要需要去设定一个方法,来确定这个手势,比如说我想要一个手势是竖大拇指,那么我们分析在竖大拇指的时候,拇指的指尖的位置是在整个手掌的最上方,这样就容易多了。只要确定在画面中大拇指的指尖是高于其他所有手指头的都指尖,那么这个手势就是竖大拇指。(也可以通过别的进行分析)

一般情况下,我们可以获取到某个关节的X,Y,Z的三个属性,表示改关节在图像中的位置。

#获取大拇指指尖的属性
thump_tip = hand_landmarks.landmark[mp.hands.HandLandmark.THUMB_TIP]#获取大拇指指尖的高度
thump_tip.y#判断竖大拇指手势
def is_thump_up(hand_landmarks):thumb_tip = hand_landmarks.landmark[mp_hands.HandLandmark.THUMB_TIP]
    index_tip = hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP]
    # 判断那个关节比较高。
    if thumb_tip.y < index_tip.y:
        return True    return False

如果想要别的手势的话,也可以根据手型的特点来设定一个专门的辨别方法。到这里手势的识别就完成了。

机械臂运动控制

我一开始的想法是,当相机识别到手势的时候就会给机械臂发送一条控制命令,这里我们先简单的设置一个让机械臂点头的动作。

pymycobot 这个功能库,开放了很多功能在控制机械臂的时候非常的方便。

from pymycobot.mycobot import Mycobot
import time
#链接机械臂
mc = Mycobot(port,baud)#以关节角度控制机械臂运动
mc.send_angles([angles_list],speed)#以坐标控制机械臂进行运动
mc.send_coords([coords_list],speed,mode)#点头动作
def ThumpUpAction(self):    self.mc.send_angles([0.96, 86.22, -98.26, 10.54, 86.92, -2.37], 60)
        time.sleep(1.5)
        for count in range(3):
            self.mc.send_angles([0.79, 2.46, (-8.17), 4.3, 88.94, 0.26], 70)
            time.sleep(1)
            self.mc.send_angles([(-3.6), 30.32, (-45.79), (-46.84), 97.38, 0.35], 70)
            time.sleep(1)
        self.mc.send_angles([0.79, 2.46, (-8.17), 4.3, 88.94, 0.26], 70)
        time.sleep(1)
        self.mc.send_angles([0.96, 86.22, -98.26, 10.54, 86.92, -2.37], 60)

为了让整体代码看起来可读性高,可修改性高,创建机械臂类方便进行调用和修改

class RobotArmController:    def __init__(self,port):
        #初始化链接
        self.mc = MyCobot(port, 115200)
        self.init_pose = [0.96, 86.22, -98.26, 10.54, 86.92, -2.37]
        self.coords = [-40, -92.5, 392.7, -92.19, -1.91, -94.14]
        self.speed = 60
        self.mode = 0        def ThumpUpAction(self):...def OtherAction(self):...

程序逻辑的处理

在调试的过程中,出现了一些问题,在识别收拾的时候,它是一直识别,这就意味着如果在1s中内识别了10次的话,会给机械臂发送10个命令,这样肯定不是我一开始所设想的。

所以在逻辑上就要有所处理,下面是我处理的方式。

# 设置一个2S的时间来确定这个手势,当竖大拇指出现2s的时候才进行下发机械臂控制的命令,用控制变量的方式来进行。#初始化变量
#检测手势是否存在的变量
gesture_detected = False
#确定手势出现后计时的变量
gesture_start_time = None
# 设定手势出现2s后的变量
gesture_confirmation_time = 2后续的处理逻辑:
当特定手势出现的时候,gesture_start_time就开始计时,这个时候在不停的做判断如果时间到达了2S之后,确定手势接下来执行相对应手势的机械臂运动。current_time = time.time()
if current_gesture:
    if not gesture_detected:gesture_detected = True
        gesture_start_time = current_time
    elif current_time - gesture_start_time > gesture_confirmation_time and not action_triggered:
        # 根据手势执行相应动作
        if current_gesture == "thumb_up":
            robotic arm action()

但是这样还不够,因为手如果出现超过2s后也会持续发送机械臂的指令,这里我们需要在设置一个冷却的时间,有充足的时间让机械臂完成运动。

#冷却时间的变量
#机械臂是否完成动作的变量
action_triggered = False
#冷却时间计时的变量
cooldown_start_time = None
#固定2s冷却时间
cooldown_period = 2

这样就能够满足需求了。完整的逻辑代码处理如下

# 处理手势
                current_time = time.time()if current_gesture:if not gesture_detected:
                        gesture_detected = True
                        gesture_start_time = current_timeelif current_time - gesture_start_time > gesture_confirmation_time and not action_triggered:# 根据手势执行相应动作if current_gesture == "thumb_up":print('good good')
                            mc.thum_up()elif current_gesture == "palm_open":print('forward')
                            mc.increment_x_and_send()# 可以添加更多手势和对应动作的判断
                        action_triggered = True
                        cooldown_start_time = current_timeelse:
                    gesture_detected = False
                    gesture_start_time = Noneif action_triggered and current_time - cooldown_start_time > cooldown_period:print('can continue')
                        action_triggered = False
                        cooldown_start_time = None

演示

https://youtu.be/9vOPKO_IG9M

总结

这个项目展示了使用手势识别控制myCobot 320的方法,开创了人机互动的新形式。尽管目前仅实现了有限的几个手势与机械臂动作的对应,但它为未来更广泛的机械臂应用奠定了基础。结合手势与机械臂的创新尝试不仅提升了我的编程技能,还锻炼了我的问题解决能力,为未来的相关项目提供了宝贵经验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/248672.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何保证MySQL数据一致性

在当今大数据时代&#xff0c;数据库系统扮演着至关重要的角色&#xff0c;而MySQL作为一种流行的关系型数据库管理系统&#xff0c;在数据一致性方面拥有着丰富的机制和技术。下面简单的探讨MySQL是如何保证数据一致性的。 事务与ACID特性 要了解MySQL如何保证数据一致性&am…

【JAVA】Long类型返回到前端,精度丢失

一. 问题阐述 20位long类型的数字&#xff0c;从后端接口返回到前端后【四舍五入】 MYSQL端 &#xff08;1&#xff09;bigint (20) &#xff08;2&#xff09;具体某一条数据 JAVA端 &#xff08;1&#xff09;实体类 &#xff08;2&#xff09;服务类 &#xff08;3&…

32GPIO输入LED闪烁蜂鸣器

目录 一.GPIO简介 二.具体电路结构 三.具体的GPIO模式 四.GPIO的寄存器 五.&#xff53;&#xff54;&#xff4d;&#xff13;&#xff12;外部的设备和电路 六.代码实现 一.点亮LED 二.LED闪烁 三.LED流水灯 四.蜂鸣器 一.GPIO简介 所有的GPIO都挂载到APB2上&#x…

统计学-R语言-7.3

文章目录 前言总体方差的检验一个总体方差的检验两个总体方差比的检验 非参数检验总体分布的检验正态性检验的图示法Shapiro-Wilk和K-S正态性检验总体位置参数的检验 练习 前言 本篇文章继续对总体方差的检验进行介绍。 总体方差的检验 一个总体方差的检验 在生产和生活的许多…

电脑可以设置代理IP吗

首先需要回答的是&#xff0c;电脑可以设置代理IP&#xff0c;下面我们详细说说如何设置。 首先&#xff0c;我们使用工具来完成&#xff0c;使用工具的好处就是可以设置单独的软件使用代理&#xff0c;也可以设置全局&#xff0c;比较方便 我们解压这个文件出来&#xff0c;打…

pytest框架的基本使用

1. 测试框架的作用 测试框架不关系用例的内容 它关心的是&#xff1a;用例编排和结果收集 2. pytest框架的特点 1. 适用于python语言 2. 用法符合python风格 3. 有丰富的生态 3. 安装pytest框架 1. 新建一个项目 2. 在项目终端窗口输入如下命令&#xff0c;用于安装py…

redisTemplate.opsForValue()

redisTemplate ​在Spring Data Redis中&#xff0c;redisTemplate 是一个非常重要的组件&#xff0c;它为开发者提供了各种操作 Redis 的方法。对于 opsForValue() 方法&#xff0c;它是用来获取一个操作字符串值的操作对象。这意味着你可以使用它来执行各种字符串相关的操作…

Linux进程间通信(IPC)机制之一:共享内存

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;Nonsense—Sabrina Carpenter 0:50━━━━━━️&#x1f49f;──────── 2:43 &#x1f504; ◀️ ⏸ ▶️ …

【Linux C | 网络编程】getsockname 和 getpeername函数详解及C语言例子

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

Opencv——霍夫变换

霍夫直线变换 霍夫直线变换(Hough Line Transform)用来做直线检测 为了加升大家对霍夫直线的理解,我在左图左上角大了一个点,然后在右图中绘制出来经过这点可能的所有直线 绘制经过某点的所有直线的示例代码如下,这个代码可以直接拷贝运行 import cv2 as cv import matplot…

Android systemui 编译

目录 简介&#xff1a; 一、步骤 二、下载源码 三、环境配置 四、确定好需要编译版本 五、编译SystemUI 步骤1&#xff1a;进入源代码目录 步骤2&#xff1a;初始化编译环境 步骤3&#xff1a;选择目标设备 步骤4&#xff1a;编译SystemUI 步骤5&#xff1a;查找生成…

Unity3D正则表达式的使用

系列文章目录 unity工具 文章目录 系列文章目录前言一、匹配正整数的使用方法1-1、代码如下1-2、结果如下 二、匹配大写字母2-1、代码如下1-2、结果如下 三、Regex类3-1、Match&#xff08;&#xff09;3-2、Matches()3-3、IsMatch&#xff08;&#xff09; 四、定义正则表达式…

ModelArts加速识别,助力新零售电商业务功能的实现

前言 如果说为客户提供最好的商品是产品眼中零售的本质&#xff0c;那么用户的思维是什么呢&#xff1f; 在用户眼中&#xff0c;极致的服务体验与优质的商品同等重要。 企业想要满足上面两项服务&#xff0c;关键在于提升效率&#xff0c;也就是需要有更高效率的零售&#…

ISCTF wp

web 圣杯战争 题目源码 <?php highlight_file(__FILE__); error_reporting(0);class artifact{public $excalibuer;public $arrow;public function __toString(){echo "为Saber选择了对的武器!<br>";return $this->excalibuer->arrow;} }class pre…

vue预览pdf文件的几种方法

文章目录 vue预览pdf集中方法方法一&#xff1a;方法二&#xff1a;展示效果&#xff1a;需要包依赖&#xff1a;代码&#xff1a; 方法三&#xff1a;展示效果&#xff1a;需要包依赖&#xff1a;代码&#xff1a;自己调参数&#xff0c;选择符合自己的 vue预览pdf集中方法 我…

WordPress主题YIA导航菜单中如何添加Iconfont字体图标?

YIA主题自带的字体图标比较少&#xff0c;一般用于文章属性或分享、点赞等地方&#xff0c;而导航菜单中的字体图标可以说没有&#xff0c;所以想要在菜单中添加字体图标的话&#xff0c;只能自行添加了。下面boke112百科就跟大家详细说一说WordPress主题YIA导航菜单中添加Icon…

【算法】登山(线性DP,最长上升)

题目 五一到了&#xff0c;ACM队组织大家去登山观光&#xff0c;队员们发现山上一共有N个景点&#xff0c;并且决定按照顺序来浏览这些景点&#xff0c;即每次所浏览景点的编号都要大于前一个浏览景点的编号。 同时队员们还有另一个登山习惯&#xff0c;就是不连续浏览海拔相…

单元/集成测试服务

服务概述 单元/集成测试旨在证明被测软件实现其单元/架构设计规范、证明被测软件不包含非预期功能。经纬恒润测试团队拥有丰富的研发经验、严格的流程管控&#xff0c;依据ISO26262/ASPICE等开展符合要求的单元测试/集成测试工作。 在ISO 26262 - part6 部分产品开发&#xff…

Android Studio 安装配置教程 - Windows版

Android Studio下载 安装&#xff1a; 下载&#xff1a; Android Studio Hedgehog | 2023.1.1 | Android Developers (google.cn) 安装&#xff1a; 基本不需要思考跟着走 默认下一步 默认下一步 自定义修改路径&#xff0c;下一步 默认下一步&#xff0c;不勾选 默认下一…

状态码400以及状态码415

首先检查前端传递的参数是放在header里边还是放在body里边。 此图前端传参post请求&#xff0c;定义为’Content-Type’&#xff1a;‘application/x-www-form-urlencoded’ 此刻他的参数在FormData中。看下图 后端接参数应为&#xff08;此刻参数前边什么都不加默认为requestP…