アイコン

佐藤さとる

梶研 [FA見学 & リアルタイムでスマホの姿勢を表示するアプリ(完成)]

2024年07月16日

thumbnail

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) 昼ごはん

(工場の写真はありません)

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)

ありがとうございます.





Kotlin 辞めた!!!

Android Studio 使いづらい!!
ショトカキー何一つ分からん
時間ないのに Kotlin を学ぶのは間違えている!!

修正後の構成2

センシング側: React(ブラウザ)
表示側: React(ブラウザ)
API側: Python(Fast API)
通信: WebSocket
フィルタ: Madgwickフィルタ

A4 - 1 (1).png (15.6 kB)
  • 加速度と角速度はWebでも取れる
  • 表示もWebで簡単にできる
  • インストール不要!!
  • API側(Python)で処理すればフィルタを転用できる
  • インターネットに繋がっていればどこでもOK
ce61b47a4ec38a37.gif (53.1 kB)

ぜひ使ってください :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回まとめて送っていた
    • データ量の問題(?)かなにかで遅延がすごい
    • センサデータが変化するたびに送信するようにした
  • 単位間違えた
    • DeviceMotionEventrotationRatedeg/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 のライブ行った

IMG_7085.JPG (3.6 MB)




ネタバレ注意!!!









































新曲もりもりで最高です

自分の声入ってたので拾った動画 ※ この曲だけ撮影OKでした IMG_7117.JPG (4.4 MB) IMG_7121.JPG (2.8 MB)