Leapmotion控制机械臂之二-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 21462|回复: 28

Leapmotion控制机械臂之二

[复制链接]
发表于 2016-7-3 00:52 | 显示全部楼层 |阅读模式
本帖最后由 吹口琴的钢铁侠 于 2016-7-8 13:58 编辑






上位机

上回讲清楚了Arduino端的代码,提到了每次都是Arduino通过串口接受来自电脑端的指令,由于leap motion是实时获取手势信息,那么我们只要能够实时地计算出每个舵机的数据,然后把数据以一定的格式发送给Arduino就能实现控制了,而且在Arduino端我们使用了分割大距离为小距离来转动舵机的算法,实时的改变角度也就不会造成特别大的惯性和损伤。

Leapmotion
Leap_View.jpg
Leapmotion作为一个手势识别装置,我们究竟能从它身上获取到哪些信息呢?
方便起见,我在这里选择了它的python库(主要是因为当时还没开始学C++= =)。
https://developer.leapmotion.com/documentation/v2/python/devguide/Leap_Overview.html
Leap_Axes.png
可以看一下这个Leapmotion给出的API,总体而言,它本身会建立一个空间的直角坐标系,通过它发出的不可见光并接受反射(大概是这样,具体原理我也不清楚),我们就能得到从手臂的肘部一直到手指末端所有的位置和方向,同时它还可以识别手中的一些工具(比如笔),一些手势(包括画圈,点击,扫过)。
Leap_Finger_Model.png
Leap_Palm_Vectors.png

通过这些细致的数据,其实我们已经可以通过数学方法来完全并准确地描述使用者的手臂信息了,但是呢...在下数学欠佳,算法不勤,只能拙略的写出下面的算法,而且在上一篇中也提到过,我的这一个机械臂只是五自由度的,永远无法完整的把手臂给复制出来,在三个姿态量和三个位置量中只能取五个量。(python推荐使用pyCharm IDE)
[mw_shl_code=python,true]import Leap
import serial
import sys


def range_limit(data, minl, maxl):
    if data < minl:
        return minl
    elif data > maxl:
        return maxl
    else:
        return data


def map_transfer(data, fmin, fmax, tmin, tmax):
    return (data - fmin) / (fmax - fmin) * (tmax - tmin) + tmin


def avg(data):
    sum = 0
    for i in range(0,4):
        sum += data
    return sum/4

class SampleListener(Leap.Listener):
    data_1 = [1,2,3,4]
    data_2 = [1,2,3,4]
    data_3 = [1,2,3,4]
    data_4 = [1,2,3,4]
    data_5 = [1,2,3,4]
    data_6 = [1,2,3,4]
    def __init__(self):
        super(SampleListener, self).__init__()
        self.ser = serial.Serial('COM12', 9600)
        print "Serial begin"

    def on_init(self, controller):
        print "Initialized"

    def on_connect(self, controller):
        print "Connected"

    def on_disconnect(self, controller):
        print "Disconnected"

    def on_exit(self, controller):
        print "Exited"

    def on_frame(self, controller):

        frame = controller.frame()
        for hand in frame.hands:

            palmangle = hand.palm_normal.roll * Leap.RAD_TO_DEG
            del self.data_1[0]
            self.data_1.append(palmangle)
            palmangle = avg(self.data_1)
            palmangle = range_limit(palmangle, -50, 50)
            clawdata = map_transfer(palmangle, -50, 50, 2200, 800)



            hand_angle = 90 - hand.direction.pitch * Leap.RAD_TO_DEG
            del self.data_2[0]
            self.data_2.append(hand_angle)
            hand_angle = avg(self.data_2)
            hand_angle = range_limit(hand_angle, 40, 140)
            hand_angle_data = map_transfer(hand_angle, 40, 140, 900, 1400)



            arm_height = hand.arm.elbow_position.y
            arm_height = range_limit(arm_height, 50, 250)
            del self.data_3[0]
            self.data_3.append(arm_height)
            arm_height = avg(self.data_3)
            servo_5 = map_transfer(arm_height, 50, 250, 2000, 1400)
            del self.data_4[0]
            self.data_4.append(servo_5)
            servo_5 = avg(self.data_4)
            servo_4 = map_transfer(servo_5, 1400, 2200, 800, 1500)



            arm_data = hand.arm.direction.yaw * Leap.RAD_TO_DEG
            del self.data_5[0]
            self.data_5.append(arm_data)
            arm_data = avg(self.data_5)
            arm_rotation = map_transfer(arm_data, 50, -50, 1000, 2000)




            indexfinger_direction = hand.fingers[1].bone(2).direction
            middlefinger_direction = hand.fingers[2].bone(2).direction
            finger_data = indexfinger_direction.angle_to(middlefinger_direction) * Leap.RAD_TO_DEG
            del self.data_6[0]
            self.data_6.append(finger_data)
            finger_data = avg(self.data_6)
            finger_angle = map_transfer(finger_data, 40, -40, 1100, 2100)




            print "%d,%d,%d,%d,%d,%d\n" % (finger_angle, clawdata, hand_angle_data, servo_4, servo_5, arm_rotation)
            serial_data = "%d,%d,%d,%d,%d,%d\n" % (finger_angle, clawdata, hand_angle_data, servo_4, servo_5, arm_rotation)

            self.ser.write(serial_data)
        if not (frame.hands.is_empty and frame.gestures().is_empty):
            print ""


def main():
    listener = SampleListener()
    controller = Leap.Controller()

    controller.add_listener(listener)

    print "Press Enter to quit..."
    try:
        sys.stdin.readline()
    except KeyboardInterrupt:
        pass
    finally:
        controller.remove_listener(listener)


if __name__ == "__main__":
    main()
[/mw_shl_code]

发表于 2016-7-4 12:40 | 显示全部楼层
Leapmotion是有专门的模块吗?他这么给Arduino发指令 啊
 楼主| 发表于 2016-7-5 08:28 | 显示全部楼层
liyming 发表于 2016-7-4 12:40
Leapmotion是有专门的模块吗?他这么给Arduino发指令 啊

LeapMotion 只能识别出手势,要通过算法运算然后以一定的格式通过电脑和Arduino串口连接之后发送过去每个舵机的旋转位置
发表于 2016-7-5 11:25 | 显示全部楼层
吹口琴的钢铁侠 发表于 2016-7-5 08:28
LeapMotion 只能识别出手势,要通过算法运算然后以一定的格式通过电脑和Arduino串口连接之后发送过去每个 ...

ok我也买一个试试,有机会多交流哈~LeapMotion也hi一个坑吗?
 楼主| 发表于 2016-7-5 19:10 | 显示全部楼层
liyming 发表于 2016-7-5 11:25
ok我也买一个试试,有机会多交流哈~LeapMotion也hi一个坑吗?

Leap motion算是挺便宜了。。精度在这个价格上是能接受的
发表于 2016-7-8 16:42 来自手机 | 显示全部楼层
(๑•̀ㅂ•́)و✧用手遥控机械臂太棒了。
发表于 2016-7-19 00:08 | 显示全部楼层
不错 我也研究下
发表于 2016-8-27 10:54 | 显示全部楼层
lz还在么?一起探讨一下。 我是从leapmotion的websocket读jsonframe,然后用node.js 的serialport往arduino写数据。 一起探讨一下六轴啊。 我认为是可以读到六轴数据的。
 楼主| 发表于 2016-8-28 08:56 | 显示全部楼层
邬指导 发表于 2016-8-27 10:54
lz还在么?一起探讨一下。 我是从leapmotion的websocket读jsonframe,然后用node.js 的serialport往arduino ...

六轴??什么意思,六自由度吗
发表于 2016-9-30 09:24 来自手机 | 显示全部楼层
漂亮的作品,再赞一次(ง •_•)ง
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 09:26 , Processed in 0.090679 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表