Leap Motion 探究 【第三篇】


        剛嘗試手勢的時候我差點選擇放棄,現在想想還是自己不好好看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匹配的解決方案,記得留言!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章