Leap Motion 探究 【第三篇】

版权声明:本文为PeterShen原创文章,未经PeterShen允许不得转载。 https://blog.csdn.net/prius0304/article/details/51284814


        刚尝试手势的时候我差点选择放弃,现在想想还是自己不好好看SDK,小心使得万年船啊。

        五一不想断更的,实在是没办法,出去的急忘了带笔记本,只好断更。下午才回来,毕竟这种万年没休的也习惯这种生活方式了,反而出去溜达感到闲的蛋疼。

        废话不多说,直接贴代码,这段代码实现的是在画圈停止后输出一个Gesture通知,代码很顺利,结果很粗糙。由于手部肌肉连带,食指动的时候必然中指也动,加上Leap“超凡的精确度”,导致动了右手食指,出来四胞胎结果——拇指,食指,中指,无名指。


public override void OnFrame(Controller arg0)
        {
            Frame frame = arg0.Frame();
            GestureList gestures = frame.Gestures();
            for (int i = 0; i < gestures.Count; i++)
            {
                Gesture gesture = gestures[i];

                switch (gesture.Type)
                {
                    case Gesture.GestureType.TYPE_CIRCLE:
                        CircleGesture circle = new CircleGesture(gesture);

                        // Calculate clock direction using the angle between circle normal and pointable
                        String clockwiseness;
                        if (circle.Pointable.Direction.AngleTo(circle.Normal) <= Math.PI / 2)
                        {
                            //Clockwise if angle is less than 90 degrees
                            clockwiseness = "clockwise";
                        }
                        else
                        {
                            clockwiseness = "counterclockwise";
                        }

                        float sweptAngle = 0;

                        // Calculate angle swept since last frame
                        if (circle.State != Gesture.GestureState.STATE_START)
                        {
                            CircleGesture previousUpdate = new CircleGesture(arg0.Frame(1).Gesture(circle.Id));
                            sweptAngle = (circle.Progress - previousUpdate.Progress) * 360;
                        }

                        if(circle.State==Gesture.GestureState.STATE_STOP)
                            Console.WriteLine("  Circle id: " + circle.Id
                                            + ", " + circle.State
                                            + ", progress: " + circle.Progress
                                            + ", radius: " + circle.Radius
                                            + ", angle: " + sweptAngle
                                            + ", " + clockwiseness);
                        break;
                }
                    
            }
        }


        修改过一个小东西后,手势明显变得好用了,就是阈值。图上是检测Key_Tap时候的反馈数据,由于设定了min_distance,即最小移动检测阈值,反馈良好,基本不会出现误操作的问题。由此可见好好看SDK是多么重要啊!阈值参数表如下:

画圈手势
Gesture.Circle.MinRadius float5mm
Gesture.Circle.MinArc float1.5 * piradians
按键手势
Gesture.KeyTap.MinDownVelocity float50mm/s
Gesture.KeyTap.HistorySeconds float0.1s
Gesture.KeyTap.MinDistance float3mm
横扫手势
Gesture.Swipe.MinLength float150mm
Gesture.Swipe.MinVelocity float1000mm/s
触摸手势
Gesture.ScreenTap.MinForwardVelocity float50mm/s
Gesture.ScreenTap.HistorySeconds float0.1s
Gesture.ScreenTap.MinDistance float5mm


       第一项为名称,第二项是数据类型(都是float),第三项是默认阈值大小,第四项是单位,csdn的表格有点不方便,然而对于一个写程序刚入门的,还去用dreamwaver编个表格粘到源码里,太麻烦,大家就这么一看,我就这么一画吧。修改阈值的方式也很简单:这里用Circle手势作为参考,修改了最小半径和最小角速度,然后记得保存。

controller.Config.SetFloat ("Gesture.Circle.MinRadius", 10.0f);
controller.Config.SetFloat ("Gesture.Circle.MinArc", .5f);
controller.Config.Save ();

       那么问题又来了,手势是对了,怎么知道是哪根指头操作的呢,不能玩第二根半价(权值选择不读)的游戏啊,肯定得想办法把所有指头都用上。想了两个办法,第一个操作一个Hand循环,采样手指名称,比如finger.type等于“TYPE_INDEX”是食指,是需要的的指头操作,测试发现问题了,因为是foreach fingers,所以只要手指头被检测到,就会被刷出来,第一种方案胎死腹中。第二个方案比较原始,即判断激发点和手指的位置是不是重合,但是由于Finger中并没有postion参数,只好想其他办法,不过下期一定贴代码!

      另外,细心的朋友发现程序失焦后会不工作,这是Leap的一种保护机制,然而这种保护机制我给零分,明明应该是默认读取数据,我可以选择关闭,现在是默认关闭我可以选择打开,好吧,我服,其实就是加了一句话:

Controller.SetPolicy(Controller.PolicyFlag.POLICY_BACKGROUND_FRAMES);

       这样子程序就可以后台继续数据了,回来路上我还纳闷这个问题呢,心想不应该,实在不行创建个新进程单独走,然而SDK再一次告诉我想多了,好好看SDK,东西全在里面,写不出都是自己的问题。现在节奏快,巴不得什么东西都不学,一口吃成个大胖子,唉,急不得啊。

       如果有朋友有finger和gesture匹配的解决方案,记得留言!

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页