如何用手機模擬激光筆


引言

你是否注意到,這些年我們越來越少在演講中看到演講人用激光筆給觀眾指示所講的內容。先說激光筆,激光筆的工作原理是射出一束激光,照射到幕布上並反射到觀眾的眼睛里,於是大家可以看到一個很亮的紅色光點。但現在因為大尺寸屏幕越來越便宜,我們越來越少使用幕布這種傳統投影顯示設備了,畢竟屏幕的顯示效果要更好。而屏幕為了保證良好的顯示效果,往往都會在表面的玻璃上使用大量抗反射技術。這些抗反射技術的運用大大減弱了激光的反射,所以最終用戶看到的紅色光點就不那么顯眼了,激光筆的效果大打折扣。

那么有沒有可能用大家出門唯一願意攜帶的手機來替代激光筆呢?我嘗試了下面兩種方案。

3D 模擬方案

簡單來說就是用手機內置的姿態傳感器和加速度傳感器來構建出手機和顯示屏在三維空間中的方位和姿態,再以此模擬計算如果從手機發出一束激光,會照射到屏幕上的哪個位置,並在屏幕上的相應位置繪制一個紅點,這樣來實現手機模擬激光筆的效果。

 

 

 

如上圖所示,假設一塊屏幕的兩條鄰邊分別平行與 X 軸和 Z 軸。當手機從 A 點沿着屏幕的一條邊移動到 B 點,再從 B 點沿着屏幕的另一條邊移動到 C 點,我們就可以計算出屏幕在以 A 點為原點的三維空間中的具體位置。

計算方法其實很簡單,比如當我們計算從 A 到 B 的過程時,只需要用手機上的加速度傳感器取出時時刻刻手機在 x 軸方向上的加速度,再乘以時間,就可以得到手機時時刻刻在 x 軸方向的速度,速度再乘以時間就可以得出手機在 x 軸方向移動了多少距離。簡單說就是對手機在 x 軸方向的加速度做了兩次時間維度上的積分。

能夠通過把手機從 A 點移動到 B 點和 C 點來計算出屏幕的位置,自然也可以在接下來計算出任意時刻手機相對屏幕的空間位置和姿態方向,並模擬計算從手機射出一束激光會照射到屏幕的哪個位置。

 

 

 

可是,實驗過后我發現這個方案雖然在理論上是可行的,但因為累積誤差的存在,實際並不可行。

我們拿手機從 A 點移動到 B 點這個最基礎的場景來舉例。當一個人拿着手機從 A 移動到 B 的時候,手機的加速度、速度和移動距離可以用下面三幅圖來描述。

 

 

 

橫軸 t 表示時間,縱軸 a、v、d 分別表示手機在 x 方向的加速度、速度和移動距離。

第一幅圖中,加速度前半程是正的,后半程是負的,所以手機在 x 方向上先加速后減速,速度從 0 增長到最大,后又慢慢減為 0,而移動距離一開始因為速度比較慢,所以增長慢,中間速度達到最大值,移動距離也增長得最快,最后速度歸 0,移動距離也不在增長。

可問題就出在加速度上。本來加速度正的部分的積分和負的部分的積分,也就是藍色區域的面積和黃色區域的面積,是完全一致的,這樣當運動過程結束時手機的速度就會恢復為 0,但實際情況並非如此。

 

 

 

首先,真實世界的物理量是連續的,加速度當然也是連續的,但在手機上通過操作系統提供的各種接口取到的加速度是不可能連續的,而是每 16ms 才能取一個值。於是在計算藍色和黃色區域的面積的時候,只能通過計算若干個矩形的面積並求和來得到一個近似值。

 

 

 

其次,手機操作系統通過接口提供的加速度和真實的加速度必然是有差別的,任何測量都有誤差,只有真實的值才會使得藍色和黃色區域的面積完全相同。

所以,由於上述的兩個原因,在手機從 A 點移動到 B 點后,我們經過測量加速度和計算速度,最后會發現手機到達 B 點后速度依然沒有歸 0,而速度沒有歸 0 意味着系統以為手機依然在勻速沿 x 軸移動,最終使得整個系統都不可用。

3D 模擬方案的根本問題在於我們需要對一個存在誤差的量做時間上的積分,我們都知道誤差並不可怕,幾乎所有的測量量都有誤差,比較可怕的是累積誤差,它會讓你的系統運行一段時間后完全失控,而 3D 模擬方案更糟糕的地方在於這個誤差是在時間維度上累積的,而時間不會停止。

姿態模擬方案

在 3D 模擬方案失敗后,我又想到一個簡化版的方案,既然加速度因為有誤差而無法使用,那能不能考慮簡單一點,只用沒有累積誤差的方向傳感器來實現控制呢?

 

 

 

假設手機的初始位置是正對屏幕的正中心,那么只要知道手機到屏幕的距離,以及手機繞 x 軸旋轉的角度 beta,就可以算出紅色光電會向上移動多少距離了。但我們沒有距離傳感器,前面也說了不能用加速度來計算距離,那我們干脆再進一步簡化,不考慮距離,只考慮角度。

我們認為設定手機手機初始位置正對屏幕正中,繞 x 軸向上旋轉 25 度時,紅點從屏幕正中移動到屏幕頂部,繞 x 軸向下旋轉 25 度時,紅點移動到屏幕底部。手機繞 z 軸左右旋轉 25 度時,紅點分別移動到屏幕的最左邊和最右邊。這樣,我們就可以只用一個簡單的姿態傳感器實現模擬激光筆的效果了。

實驗表明,這種方案完全可行,而且代碼邏輯簡單。當然,這種方式假定了手機的初始姿態,其實也假定了手機到屏幕的距離(可以思考一下為啥也假定了手機到屏幕的距離^_^),用戶在使用的時候可能會稍微感到有一點點不自然。同時,為了更好更方便的控制體驗,還需要加一些讓用戶重置手機姿態的功能。

Demo

本文中所講的姿態模擬方案,大家可以在 Laser Pen Demo 體驗,相關代碼在 Laser Pen - Github 的 example 目錄下。 在 pc 瀏覽器中打開 demo 頁面后稍等幾秒,你應該會看到頁面的頭部生成了一個二維碼。

 

 

 

  

當手機上的控制頁面顯示「Connected」的時候,你就可以嘗試揮動手機來控制 pc 頁面上的小紅點啦。

 

 

關於這個 demo 還有兩點說明。

首先,demo 中獲取的手機姿態數據是通過 WebRTC 技術直接發到 pc 頁面的,所以你完全不用擔心有個人敏感信息泄露的問題。

其次,demo 的主要通信手段雖然是 WebRTC,但 WebRTC 鏈接建立的過程是需要一些消息推送手段的,所以 demo 也用到了 socket.io

最后,demo 用了一個免費的后端服務,這個服務一段時間沒有人訪問后會自動停止,下次再訪問就得等將近兩分鍾服務才能啟起來。所以如果你打開 pc 頁面后發現二維碼沒有顯示出來,可以先去喝杯水,再回來刷新一下頁面試試。

最后

歡迎大家 star、pr、issue 我的項目 Laser Pen - Github

歡迎關注我的微信公眾號:老虎的小窩

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM