机器臂(二)--视觉控制关节点

   

       

在先前配置好的机器臂教程接着下做

先是视觉方面demo

手势识别的mediapipe 是谷歌开源项目 这个的主要功能是识别手势 然后封装成类给下面的控制模块调用

import cv2
import mediapipe as mp

class HandDetector:
   
    

    def __init__(self, mode=False, maxHands=2, detectionCon=0.5, minTrackCon=0.5):
       
        self.mode = mode
        self.maxHands = maxHands
        self.detectionCon = detectionCon
        self.minTrackCon = minTrackCon

        self.mpHands = mp.solutions.hands
        self.hands = self.mpHands.Hands(static_image_mode=self.mode, max_num_hands=self.maxHands,
                                        min_detection_confidence=self.detectionCon,
                                        min_tracking_confidence=self.minTrackCon)
        self.mpDraw = mp.solutions.drawing_utils
        self.tipIds = [4, 8, 12, 16, 20]
        self.fingers = []
        self.lmList = []

    def findHands(self, img, draw=True, flipType=True):
        
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        self.results = self.hands.process(imgRGB)
        allHands = []
        h, w, c = img.shape
        if self.results.multi_hand_landmarks:
            for handType, handLms in zip(self.results.multi_handedness, self.results.multi_hand_landmarks):
                myHand = {}
                ## lmList
                mylmList = []
                xList = []
                yList = []
                for id, lm in enumerate(handLms.landmark):
                    px, py, pz = int(lm.x * w), int(lm.y * h), int(lm.z * w)
                    mylmList.append([px, py, pz])
                    xList.append(px)
                    yList.append(py)

                ## bbox
                xmin, xmax = min(xList), max(xList)
                ymin, ymax = min(yList), max(yList)
                boxW, boxH = xmax - xmin, ymax - ymin
                bbox = xmin, ymin, boxW, boxH
                cx, cy = bbox[0] + (bbox[2] // 2), \
                         bbox[1] + (bbox[3] // 2)

                myHand["lmList"] = mylmList
                myHand["bbox"] = bbox
                myHand["center"] = (cx, cy)

                if flipType:
                    if handType.classification[0].label == "Right":
                        myHand["type"] = "Left"
                    else:
                        myHand["type"] = "Right"
                else:
                    myHand["type"] = handType.classification[0].label
                allHands.append(myHand)

                ## draw
                if draw:
                    self.mpDraw.draw_landmarks(img, handLms,
                                               self.mpHands.HAND_CONNECTIONS)
                    cv2.rectangle(img, (bbox[0] - 20, bbox[1] - 20),
                                  (bbox[0] + bbox[2] + 20, bbox[1] + bbox[3] + 20),
                                  (255, 0, 255), 2)
                    cv2.putText(img, myHand["type"], (bbox[0] - 30, bbox[1] - 30), cv2.FONT_HERSHEY_PLAIN,
                                2, (255, 0, 255), 2)
        if draw:
            return allHands, img
        else:
            return allHands

    def fingersUp(self, myHand):
        """
        判断多少个手指起来
        """
        myHandType = myHand["type"]
        myLmList = myHand["lmList"]
        if self.results.multi_hand_landmarks:
            fingers = []
            # Thumb
            if myHandType == "Right":
                fingers.append(0)#右手
                if myLmList[self.tipIds[0]][0] > myLmList[self.tipIds[0] - 1][0]:
                    fingers.append(1)
                else:
                    fingers.append(0)
            else:
                fingers.append(1)#左手
                if myLmList[self.tipIds[0]][0] < myLmList[self.tipIds[0] - 1][0]:
                    fingers.append(1)
                else:
                    fingers.append(0)

            # 4 Fingers
            for id in range(1, 5):
                if myLmList[self.tipIds[id]][1] < myLmList[self.tipIds[id] - 2][1]:
                    fingers.append(1)
                else:
                    fingers.append(0)
        return fingers

def main():
    cap = cv2.VideoCapture(0)
    detector = HandDetector(detectionCon=0.8, maxHands=2)
    while True:
        # Get image frame
        success, img = cap.read()
        # Find the hand and its landmarks
        hands, img = detector.findHands(img)  # with draw
        # hands = detector.findHands(img, draw=False)  # without draw

        if hands:
            # Hand 1
            hand1 = hands[0]
            lmList1 = hand1["lmList"]  # List of 21 Landmark points
            handType1 = hand1["type"]  # Handtype Left or Right
            fingers1 = detector.fingersUp(hand1)
            print(fingers1)
            if len(hands) == 2:
                # Hand 2
                hand2 = hands[1]
                lmList2 = hand2["lmList"]  # List of 21 Landmark points
                bbox2 = hand2["bbox"]  # Bounding box info x,y,w,h
                centerPoint2 = hand2['center']  # center of the hand cx,cy
                handType2 = hand2["type"]  # Hand Type "Left" or "Right"
                fingers2 = detector.fingersUp(hand2)
                print(fingers2)
        # Display
        cv2.imshow("Image", img)
        cv2.waitKey(1)


if __name__ == "__main__":
    main()

控制关节点的python demo 模块

#! /usr/bin/python3.8
# -*- coding: utf-8 -*-
from operator import ge
from time import sleep
import HandTrackingModule as Hd
import rospy
import cv2
from sensor_msgs.msg import JointState
import sys, termios

msg = """
Control Your Turtlebot!
---------------------------
Moving around:
   q    w    e   r   t   y
   a    s    d   f   g   h

j/l : increase/decrease precision by 0.05
space key, k : reset
anything else : stop smoothly
b : switch to arm_four/arm_six
precision is not less than or equal to zero
CTRL-C to quit
"""
  
mode = 0 #六自由度模式

precision = 0.05 #默认精度(rad)

#键值对应转动方向
rotateBindings = {
        'q':(1,1),#第一个关节顺时针
        'a':(1,-1),
        'w':(2,1),
        's':(2,-1),
        'e':(3,1),
        'd':(3,-1),
        'r':(4,1),
        'f':(4,-1),
        't':(5,1),
        'g':(5,-1),
        'y':(6,1),
        'h':(6,-1)
           }

#键值对应精度增量
precisionBindings={
        'j':0.01,
        'l':-0.01
          }

#以字符串格式返回当前控制精度
def prec(precision):
    return "currently:\tprecision %s " %precision
# 检测手势
def detect_hands_gesture(result):
#0 1 2 3 4 5 6 
#7 8 9 10 11 12
    if result[0]==0:
        if (result[1:] == [0,1,0,0,0]):
            gesture = "a" #
            return  gesture
        elif (result[1:] == [0,1,1,0,0]):
            gesture = "s"
            return  gesture
        elif (result[1:] == [0,0,1,1,1]):
            gesture = "d"
            return  gesture
        elif (result[1:] == [0,1,1,1,1]):
            gesture = "f"
            return  gesture
        elif (result[1:] == [1,1,1,1,1]):
            gesture = "g"
            return  gesture
        elif (result[1:] == [1,0,0,0,1]):
            gesture = "h"
            return  gesture
        elif (result[1:] == [1,1,0,0,1]):
            gesture = " " #R&K手臂直立
            return  gesture
    elif result[0]==1:
        if (result[1:] == [0,1,0,0,0]):
            gesture = "q"
            return  gesture
        elif (result[1:] == [0,1,1,0,0]):
            gesture = "w"
            return  gesture
        elif (result[1:] == [0,0,1,1,1]):
            gesture = "e"
            return  gesture
        elif (result[1:] == [0,1,1,1,1]):
            gesture = "r"
            return  gesture
        elif (result[1:] == [1,1,1,1,1]):
            gesture = "t"
            return  gesture
        elif (result[1:] == [1,0,0,0,1]):#小拇指
            gesture = "y"
            return  gesture

   
  
#主函数
if __name__=="__main__":
    settings = termios.tcgetattr(sys.stdin) #获取键值初始化,读取终端相关属性
    rospy.init_node('arm_teleop') #创建ROS节点
    pub = rospy.Publisher('/joint_states', JointState, queue_size=5) #创建机械臂状态话题发布者
    #关节1-6对应弧度状态
    joints = [0,0,0,0,0,0]

    """机械臂关节初始化"""
    jointState = JointState() #创建ROS机械臂装态话题消息变量
    jointState.header.stamp = rospy.Time.now()
    jointState.name=["joint1","joint2","joint3","joint4","joint5","joint6"]
    jointState.position=joints
    pub.publish(jointState) #ROS发布机械臂状态话题
    # 接入USB摄像头时,注意修改cap设备的编号
    cap = cv2.VideoCapture(0)
    detector = Hd.HandDetector(detectionCon=0.8, maxHands=2)
    if not cap.isOpened():
        print("Can not open camera.")
        exit()
    try:
        print(msg) #打印控制说明
        print(prec(precision)) #打印当前精度
        key = " "
        while(1):
            # Get image frame
            success, img = cap.read()
            # Find the hand and its landmarks
            hands, img = detector.findHands(img)  # with draw
            # hands = detector.findHands(img, draw=False)  # without draw
            cv2.imshow("Image", img)
            cv2.waitKey(1)
            if hands :
                 key  = detect_hands_gesture(detector.fingersUp(hands[0])) 
                    #判断键值是在控制机械臂运动的键值内
            
            if key in rotateBindings.keys():
                joints[rotateBindings[key][0]-1] = joints[rotateBindings[key][0]-1] + precision*rotateBindings[key][1]
                if joints[rotateBindings[key][0]-1]>1.57:
                            joints[rotateBindings[key][0]-1]=1.57
                elif joints[rotateBindings[key][0]-1]<-1.57:
                            joints[rotateBindings[key][0]-1]=-1.57
                    #判断键值是否在精度增量键值内
                elif key in precisionBindings.keys():
                    if (precision+precisionBindings[key])<0.01 or (precision+precisionBindings[key])>0.1:
                        pass
                    else:
                            precision+=precisionBindings[key]
                            print(prec(precision)) #精度发生变化,打印出来
                     #根据机械臂自由度给joint_states话题赋予消息
                if mode:
                        jointState.header.stamp = rospy.Time.now()
                        jointState.name=["joint1","joint2","joint3","joint4"]
                        jointState.position=joints[0:4]
                else:
                        jointState.header.stamp = rospy.Time.now()
                        jointState.name=["joint1","joint2","joint3","joint4","joint5","joint6"]
                        jointState.position=joints
                pub.publish(jointState) #ROS发布关节状态话题 
            elif key ==" ":
                  joints = [0,0,0,0,0,0]    

    #运行出现问题则程序终止并打印相关错误信息
    except Exception as e:
        print(e)
        

    #程序结束前发布速度为0的速度话题
    finally:
        print("Keyboard control off")

    #程序结束前打印消息提示
    termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)

感觉判断的地方有点小拉跨

所有的python 写完记得

sudo chmod 777 *.py

启动桌面机器人的基础服务

roslaunch table_arm base_serial.launch

启动

roslaunch table_arm arm_opencv_move.py

机器臂直立 R&K 直立

 

ros_opencv_机器爪控制-2_哔哩哔哩_bilibili

    

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 对于一个六自由度机械,其D-H参数如下: 1. 第一关节:转动关节,没有平移,因此a1=0,d1=0,α1=0。 2. 第二关节:旋转关节,前后无平移,因此a2=0,d2=D2,α2=-90°。 3. 第三关节:旋转关节,前后有平移,因此a3=A3,d3=D3,α3=0。 4. 第四关节:旋转关节,前后有平移,因此a4=A4,d4=0,α4=-90°。 5. 第五关节:旋转关节,前后有平移,因此a5=0,d5=D5,α5=90°。 6. 第六关节:旋转关节,前后无平移,因此a6=0,d6=0,α6=-90°。 其中,A3、A4、D2、D3、D5为机械的设计参数,可以根据实际情况进行调整。 ### 回答2: 六自由度机械是一种具有六个关节机器人,可执行六个自由度的运动。D-H参数是一种描述机械关节之间几何关系的方法,其包括了四个基本参数:连杆长度a、偏距d、连杆扭转角度α和关节转角θ。 D-H参数描述了各个连杆之间的相对位置和朝向关系。偏距d表示相邻两个关节旋转轴之间的距离,连杆长度a表示相邻两个关节旋转轴的距离,连杆扭转角度α表示旋转轴相对于前一个轴的旋转角度,关节转角θ表示每个关节相对于基准位置的旋转角度。 具体来说,对于六自由度机械而言,我们可以依次编号每个关节为1, 2, 3, 4, 5, 6,同时编号每个连杆为0, 1, 2, 3, 4, 5。则对于每个关节,我们可以确定其对应的D-H参数: 关节1:a0 = 0,d1 = 0,α0 = 0,θ1为关节1的转角。 关节2:a1为关节1与关节2之间的连杆长度,d2为连杆2的偏距,α1为连杆2相对于连杆1的旋转角度,θ2为关节2的转角。 关节3、4、5、6的D-H参数同理。 通过确定六个关节的D-H参数,我们可以建立整个六自由度机械的运动学模型,从而计算机械在各个自由度上的位置和姿态。这对于机械的运动规划、轨迹控制等任务非常重要。 ### 回答3: 六自由度机械的D-H参数是描述机械各个关节之间的相对位置和姿态的一组参数。D-H参数是采用Denavitt-Hartenberg(D-H)坐标系方法来描述机械关节的几何特征和运动规律。 具体来说,六自由度机械的D-H参数包括以下几个参数: 1. 链长(Link Length):用L表示,表示相邻关节的连杆的长度。 2. 关节偏移(Joint Offset):用D表示,表示相邻关节的连杆之间的偏移量。 3. 关节旋转角度(Joint Angle):用θ表示,表示一个关节绕着连杆的旋转角度。 4. 关节旋转轴(Joint Axis):用α表示,表示一个关节旋转轴与前一个关节旋转轴的夹角。 关于坐标系的选取,按照D-H参数的规定,相邻关节的旋转轴是平行于某一个坐标轴的,这个坐标轴即为旋转轴坐标系的z轴。而关节的旋转角度即为绕着这个旋转轴的旋转角度。 在确定了每个关节的D-H参数后,可以通过D-H转换矩阵来计算机械末端执行器的位置和姿态。 总之,六自由度机械的D-H参数是用来描述机械关节位置和姿态的一组参数,通过这些参数可以计算出机械末端执行器的位姿。这些参数是根据机械的结构和运动规律来确定的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值