梶研 [FA見学 & リアルタイムでスマホの姿勢を表示するアプリ(完成)]
2024年07月16日
![thumbnail](https://img.esa.io/uploads/production/attachments/13979/2024/07/09/148142/4bce1067-af03-494d-ba8d-8f0091b587d7.jpg)
FA見学 & リアルタイムでスマホの姿勢を表示するアプリ(完成)
出席率
- 3年セミナー:??%
スケジュール
短期的な予定
- mocopi と お料理センシング
- シーンとランドマークを決める(~2月上旬)
- SVM で動作判別する
- 機械学習を深める
- お料理センシング
- お料理でどんな動作があるかを知る
- レシピを決める
- 関節を3次元座標に変換する
-
関節を2次元座標に変換する - ST-GCN を大体理解
- ST-GCN で動作推定
- 伊達巻きで動作推定する
- レシピ(手順書)を元に動作推定を補う
- 論文書く
- 発表
- BookWorm
- Pasori と デスクトップアプリを接続する(技術検証)
- nfc読み込み機能 & 画面を作る
- API と連携させる
- 管理者画面を作る
進捗報告
ST-GCN
夏休みに託します
FA見学した
MEEさんの名古屋製作所にいった
![IMG_7078.jpg (1.0 MB)](https://img.esa.io/uploads/production/attachments/13979/2024/07/09/148142/4bce1067-af03-494d-ba8d-8f0091b587d7.jpg)
(工場の写真はありません)
Webエンジニアだけで人生終えるのは勿体無いと改めて感じた.
人工衛星とか夢があるなぁ(鎌倉でやってるらしい)
リアルタイムでスマホの姿勢を表示するアプリ
前回
センシング側: React Native
表示側: Tauri
通信: Socket(TCP)
フィルタ: 相補フィルタ→(Madgwickフィルタ)
で、ほぼできた. 動いているときの姿勢推定が上手くいかない
作り直した!!!
- React Native の開発環境が気に入らない
- dev環境を開きづらい
- ビルドが expoのクラウド上 でしかできない
- もっと汎用的にしたい
- アプリインストールするの面倒
- 同じネットワーク内でしかできない
修正後の構成
React Native → Kotlin: 始めからスマホで見れる機能あるし、なんでもできるし
Socket(TCP) → Bluetooth: ネットワークに依存したくない
![スクリーンショット 2024-07-08 23.49.03.png (241.1 kB)](https://img.esa.io/uploads/production/attachments/13979/2024/07/08/148142/d08d039e-480c-4db9-ac10-ece4e8f354fb.png)
ありがとうございます.
Kotlin 辞めた!!!
Android Studio 使いづらい!!
ショトカキー何一つ分からん
時間ないのに Kotlin を学ぶのは間違えている!!
修正後の構成2
センシング側: React(ブラウザ)
表示側: React(ブラウザ)
API側: Python(Fast API)
通信: WebSocket
フィルタ: Madgwickフィルタ
![A4 - 1 (1).png (15.6 kB)](https://img.esa.io/uploads/production/attachments/13979/2024/07/09/148142/16e959a7-a36e-43c7-ae02-096ba2c26a66.png)
- 加速度と角速度はWebでも取れる
- 表示もWebで簡単にできる
- インストール不要!!
- API側(Python)で処理すればフィルタを転用できる
- インターネットに繋がっていればどこでもOK
![ce61b47a4ec38a37.gif (53.1 kB)](https://img.esa.io/uploads/production/attachments/13979/2024/07/08/148142/398a8552-c6dc-48bc-902c-737ee3dd9ec7.gif)
ぜひ使ってください :sore-web-de-dekimasu:
(モバイル版もあります)
APIサーバつくる
簡単にできた
1@app.post("/api/raw") 2async def post_raw_data(req: Request): 3 data = await req.json() 4 sensorData = validate_sensor_data(data) # データが正しい形式か確認 5 quaternions = filter.update(sensorData) # フィルターを適用 6 response_data = {"quaternions": quaternions} 7 8 # データを WebSocket で接続しているクライアントに送信 9 await manager.send_text(json.dumps(response_data)) 10 11 # 返す 12 return response_data
1@app.websocket("/ws/posture") 2async def websocket_endpoint(websocket: WebSocket): 3 # WebSocket 接続を管理するクラスに登録 4 await manager.connect(websocket) 5 6 try: 7 while True: 8 # メッセージを受信 9 data = await websocket.receive_text() 10 # 全てのクライアントにメッセージを送信 11 await manager.send_text(f"Received: {data}") 12 13 except WebSocketDisconnect: 14 # WebSocket 接続が切断された場合は解除 15 manager.disconnect(websocket)
フィルタは西先輩にアウトソーシングしました.
ありがとうございます
センシング側をつくる
devicemotion
イベントで加速度と角速度を取得できた
1export function useSensor(callack?: Callback & CallbackPromise) { 2 ... 3 useEffect(() => { 4 if (!isPermissionGranted) return; 5 6 window.addEventListener('devicemotion', handleMotion); 7 8 return () => { 9 window.removeEventListener('devicemotion', handleMotion); 10 }; 11 }, [isPermissionGranted, handleMotion]); 12 ...
1const [sensorData, { requestPermission }] = useSensor(async (data) => await fetchSensorData(data));
表示側
websocket を扱うためのカスタムフック作った!!
1export const useWS = (url: string, callBack: CallBack) => { 2 const [ws, setWS] = useState(() => new WebSocket(url)); 3 4 useEffect(() => { 5 ws.onmessage = (e) => { 6 const data = JSON.parse(e.data); 7 console.log(data); 8 callBack(data); 9 }; 10 11 return () => { 12 ws.close(); 13 }; 14 }, []); 15 16 function send<T>(data: T): boolean { 17 if (ws.readyState !== ws.OPEN) return false; 18 19 ws.send(JSON.stringify(data)); 20 return true; 21 } 22 23 function reConnect() { 24 setWS(new WebSocket(url)); 25 } 26 27 return { send, reConnect } as const; 28};
1 useWS(url.href, (data) => { 2 const isValid = quatResponseSchema.safeParse(data); 3 if (!isValid.success) return; 4 5 setQuaternion(isValid.data.quaternions[0]); 6 });
いい感じにデプロイした
APIを梶研サーバにデプロイした
uvicorn + FastAPI でデプロイするときは --host 0.0.0.0
をつけよう
例: uvicorn main:app --host 0.0.0.0
省略
(鹿さんありがとうございます)
荒ぶった
問題点
- Madgwickフィルタのサンプリングレートが間違えていた
- とりあえず 100fps にしていたが実際は60fps
- 通信が不安定
- 0.5秒に1回まとめて送っていた
- データ量の問題(?)かなにかで遅延がすごい
- センサデータが変化するたびに送信するようにした
- 単位間違えた
DeviceMotionEvent
のrotationRate
はdeg/s
だった. (rad/s
のつもりだった)
- Hooks の使い方ミスった
- ダメ:
const [ws, setWS] = useState(new WebSocket(url));
- WebSocket に接続してから、渡す
- マウント時であれば保持, それ以外は無視
- 良い:
const [ws, setWS] = useState(() => new WebSocket(url));
- WebSocket に接続する関数を渡す(接続はしていない)
- マウント時であれば接続してから保持, それ以外は無視
- めっちゃ接続&切断しまくってた
- ダメ:
リポジトリ
API側: https://github.com/kajiLabTeam/realtime-de-smartphone-no-posture-wo-show-suruzo-server
センシング側: https://github.com/kajiLabTeam/realtime-de-smartphone-no-posture-wo-show-suruzo-sensing-web
表示側: https://github.com/kajiLabTeam/realtime-de-smartphone-no-posture-wo-show-suruzo-display
デプロイ先
取得側: https://realtime-zou-sensing.satooru.dev
表示側: https://realtime-zou-display.satooru.dev
一旦個人の Cloudflare Pages にデプロイしています.
必要であれば梶研 Cloudflare にデプロイしてください
(環境変数を設定する必要があります)
進路関係
余談
Mrs. GREEN APPLE のライブ行った
ネタバレ注意!!!
新曲もりもりで最高です
自分の声入ってたので拾った動画 ※ この曲だけ撮影OKでした⚠️ネタバレ注意
— ミズキ🏳️🌈 (@mizuki_09232003) July 6, 2024
7月6日 Mrs.GreenApple のゼンジン未到とヴェルトラウム銘々編無事終了
めちゃくちゃ楽しかったぜ!!
magicだけ撮影オッケーになったから撮ってきたぜ!#MrsꓸGREENAPPLE #ゼンジン #ミセス #ゼンジン未到とヴェルトラウム #MrsGREENAPPLE #ノエビアスタジアム神戸 #ノエスタ #magic pic.twitter.com/AdiKF7w5zO