佐藤さとる

佐藤さとる

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

2024年07月16日

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

出席率

スケジュール

短期的な予定

進捗報告

ST-GCN

夏休みに託します

FA見学した

MEEさんの名古屋製作所にいった

昼ごはん

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

Webエンジニアだけで人生終えるのは勿体無いと改めて感じた.

<p style="font-size:13px">人工衛星とか夢があるなぁ(鎌倉でやってるらしい)</p>

リアルタイムでスマホの姿勢を表示するアプリ

前回

センシング側: React Native

表示側: Tauri

通信: Socket(TCP)

フィルタ: 相補フィルタ→(Madgwickフィルタ)

で、ほぼできた. 動いているときの姿勢推定が上手くいかない

作り直した!!!

修正後の構成

React Native → Kotlin: 始めからスマホで見れる機能あるし、なんでもできるし

Socket(TCP) → Bluetooth: ネットワークに依存したくない

スクリーンショット 2024-07-08 23.49.03.png (241.1 kB)

ありがとうございます.

<br /><br /><br /><br />

Kotlin 辞めた!!!

Android Studio 使いづらい!!

ショトカキー何一つ分からん

時間ないのに Kotlin を学ぶのは間違えている!!

修正後の構成2

センシング側: React(ブラウザ)

表示側: React(ブラウザ)

API側: Python(Fast API)

通信: WebSocket

フィルタ: Madgwickフィルタ

A4 - 1 (1).png (15.6 kB)
ce61b47a4ec38a37.gif (53.1 kB)

ぜひ使ってください :sore-web-de-dekimasu:

(モバイル版もあります)

APIサーバつくる

簡単にできた

@app.post("/api/raw")
async def post_raw_data(req: Request):
    data = await req.json()
    sensorData = validate_sensor_data(data) # データが正しい形式か確認
    quaternions = filter.update(sensorData) # フィルターを適用
    response_data = {"quaternions": quaternions}

    # データを WebSocket で接続しているクライアントに送信
    await manager.send_text(json.dumps(response_data))

    # 返す
    return response_data
@app.websocket("/ws/posture")
async def websocket_endpoint(websocket: WebSocket):
    # WebSocket 接続を管理するクラスに登録
    await manager.connect(websocket)

    try:
        while True:
            # メッセージを受信
            data = await websocket.receive_text()
            # 全てのクライアントにメッセージを送信
            await manager.send_text(f"Received: {data}")

    except WebSocketDisconnect:
        # WebSocket 接続が切断された場合は解除
        manager.disconnect(websocket)

フィルタは西先輩にアウトソーシングしました.

ありがとうございます

センシング側をつくる

devicemotionイベントで加速度と角速度を取得できた

export function useSensor(callack?: Callback & CallbackPromise) {
  ...
  useEffect(() => {
    if (!isPermissionGranted) return;

    window.addEventListener('devicemotion', handleMotion);

    return () => {
      window.removeEventListener('devicemotion', handleMotion);
    };
  }, [isPermissionGranted, handleMotion]);
  ...
const [sensorData, { requestPermission }] = useSensor(async (data) => await fetchSensorData(data));

表示側

websocket を扱うためのカスタムフック作った!!

export const useWS = (url: string, callBack: CallBack) => {
  const [ws, setWS] = useState(() => new WebSocket(url));

  useEffect(() => {
    ws.onmessage = (e) => {
      const data = JSON.parse(e.data);
      console.log(data);
      callBack(data);
    };

    return () => {
      ws.close();
    };
  }, []);

  function send<T>(data: T): boolean {
    if (ws.readyState !== ws.OPEN) return false;

    ws.send(JSON.stringify(data));
    return true;
  }

  function reConnect() {
    setWS(new WebSocket(url));
  }

  return { send, reConnect } as const;
};
  useWS(url.href, (data) => {
    const isValid = quatResponseSchema.safeParse(data);
    if (!isValid.success) return;

    setQuaternion(isValid.data.quaternions[0]);
  });

いい感じにデプロイした

APIを梶研サーバにデプロイした

uvicorn + FastAPI でデプロイするときは --host 0.0.0.0 をつけよう

例: uvicorn main:app --host 0.0.0.0

省略

(鹿さんありがとうございます)

荒ぶった

問題点

リポジトリ

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)

<br /><br /><br />

<p style="font-size:20px">ネタバレ注意!!!</p>

<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />

新曲もりもりで最高です

<blockquote class="twitter-tweet" data-media-max-width="560"><p lang="ja" dir="ltr">⚠️ネタバレ注意<br>7月6日 Mrs.GreenApple のゼンジン未到とヴェルトラウム銘々編無事終了<br>めちゃくちゃ楽しかったぜ!!<br>magicだけ撮影オッケーになったから撮ってきたぜ!<a href="https://twitter.com/hashtag/Mrs%EA%93%B8GREENAPPLE?src=hash&amp;refsrc=twsrc%5Etfw">#MrsꓸGREENAPPLE</a> <a href="https://twitter.com/hashtag/%E3%82%BC%E3%83%B3%E3%82%B8%E3%83%B3?src=hash&amp;refsrc=twsrc%5Etfw">#ゼンジン</a> <a href="https://twitter.com/hashtag/%E3%83%9F%E3%82%BB%E3%82%B9?src=hash&amp;refsrc=twsrc%5Etfw">#ミセス</a> <a href="https://twitter.com/hashtag/%E3%82%BC%E3%83%B3%E3%82%B8%E3%83%B3%E6%9C%AA%E5%88%B0%E3%81%A8%E3%83%B4%E3%82%A7%E3%83%AB%E3%83%88%E3%83%A9%E3%82%A6%E3%83%A0?src=hash&amp;refsrc=twsrc%5Etfw">#ゼンジン未到とヴェルトラウム</a> <a href="https://twitter.com/hashtag/MrsGREENAPPLE?src=hash&amp;refsrc=twsrc%5Etfw">#MrsGREENAPPLE</a> <a href="https://twitter.com/hashtag/%E3%83%8E%E3%82%A8%E3%83%93%E3%82%A2%E3%82%B9%E3%82%BF%E3%82%B8%E3%82%A2%E3%83%A0%E7%A5%9E%E6%88%B8?src=hash&amp;refsrc=twsrc%5Etfw">#ノエビアスタジアム神戸</a> <a href="https://twitter.com/hashtag/%E3%83%8E%E3%82%A8%E3%82%B9%E3%82%BF?src=hash&amp;refsrc=twsrc%5Etfw">#ノエスタ</a> <a href="https://twitter.com/hashtag/magic?src=hash&amp;refsrc=twsrc%5Etfw">#magic</a> <a href="https://t.co/AdiKF7w5zO">pic.twitter.com/AdiKF7w5zO</a></p>&mdash; ミズキ🏳️‍🌈 (@mizuki09232003) <a href="https://twitter.com/mizuki09232003/status/1809584134345617834?ref_src=twsrc%5Etfw">July 6, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

自分の声入ってたので拾った動画

※ この曲だけ撮影OKでした

IMG_7117.JPG (4.4 MB)

<iframe width="1214" height="683" src="https://www.youtube.com/embed/xk7czF1H2No" title="Mrs. GREEN APPLE 看板すごい" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

IMG_7121.JPG (2.8 MB)