揚げログ

更新休止中・Karaageの活動報告とメモ

AR kit で顔面キャスアプリを作る (その4 transformから目の回転角を求める)

だいぶ間が空いてしまいました。

この間は、AR kit FaceTracking Configurationで、表情の値(blendshapes)を取得しましたが、今回は目の動きを取ってみたいと思います。

全体手順

  1. AR kitのFaceTrackingで、目の動きを数値データで取り出す
  2. ソケット通信でサーバーに送信
  3. クライアント側で数値を受信
  4. three.js VRMloaderでVRMデータを読み込む
  5. VRMデータに数値を反映させる

2, 3は、前回までで動作確認まで終わっています。

4, 5は次回の記事に多分書きます。

コード

下記コードは、1,2を行う処理で、func rendererは顔情報がアップデートされるたび(didUpdate)に呼ばれる関数です。

コードの全体は、

facecast_ios/eyeGaze.swift at master · krgpi/facecast_ios · GitHub

です。

class eyeGaze: NSObject, VirtualContentController { 
    var emitArray:[String: Float] = ["eyeL": 0.00, "eyeR": 0.00, "faceDir": 0.00]
//中略
    func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
        guard #available(iOS 12.0, *), let faceAnchor = anchor as? ARFaceAnchor
            else { return }
        
        emitArray["eyeL"] = asin(faceAnchor.leftEyeTransform.columns.2.x)
        emitArray["eyeR"] = asin(faceAnchor.rightEyeTransform.columns.2.x)
        emitArray["faceDir"] = asin(faceAnchor.transform.columns.2.x)

        do {
            let e = try JSONSerialization.data(withJSONObject: emitArray, options: .prettyPrinted)
            let str = String(bytes: e, encoding: .utf8)
            socket.socketIOClient.emit("chat message", str!)
        } catch  {
            print("err")
        }

    }
//後略
}

AR kit の Transformについて

ここで出てくる、leftEyeTransform, rightEyeTransform, transformは、いずれも

transform - ARAnchor | Apple Developer Documentation

にあるように、基準ベクトル(正面向き・まっすぐ前向き)から現在のベクトルへの変換行列です。3次元の変換行列なので、以下のようにパラメータを定めた時、

params 内容
d_{x} x方向への移動距離
d_{y} y方向への移動距離
d_{z} z方向への移動距離
\theta_{x} x軸周りの回転角
\theta_{y} y軸周りの回転角
\theta_{z} z軸周りの回転角

ただし、EyeTransformに関しては、

^\forall \theta_{z} = 0

AR kitでは、右手系(親指から順にx,y,z軸)を用いていて、目の奥から先に向かう軸をZ軸としています。

目はX, Y軸中心にしか回転しないので、Z軸回りの回転角が常に0です。

今回の計算

今回は、目の水平方向の回転を取り出したいので、 \theta_{y} を求めたいと思います。

^\forall \theta_{z} = 0 の時の3次元変換行列は、
\left(\begin{array}{rrrr}\cos{\theta_{y}} & 0 & -\sin{\theta_{y}} & d_{x}\\ \sin{\theta_{x}}sin{\theta_{y}} & cos{\theta_{x}} & \sin{\theta_{x}}cos{\theta_{y}}  & d_{y} \\ \cos{\theta_{x}}sin{\theta_{y}}  & -\sin{\theta_{x}} & \cos{\theta_{x}}cos{\theta_{y}}  & d_{z} \\0 & 0 & 0 & 1\\\end{array}\right)
です。

transformのデータ型は simd_float4x4 という型で、transform.colums.0, 1, 2, 3 という形で、まず列が取り出せます。

さらに、transform.colums.0.x, y, x, wという形で、行数を選択することができます。

ここで、 \theta_{y}=\arcsin({transform.colums.2.x}) となります。

まとめの図

f:id:en0qi:20190319111231j:plain
transform(simd_float4x4)

iPad Pro、便利ですね!!

次回はthree.jsを使ったウェブビューワーの作成の記事を投げます!

enPiTビジネスシステムデザイン分野ワークショップ2018に参加してきた

筑波大学で開かれた、enPiT(エンピット)の最終成果発表会に参加してきたので、メモ兼感想を残します。

イベント概要

enPiTとは?

  • 成長分野を支える情報技術人材の育成拠点の形成
  • チームで開発を行い、その過程で学生が主体的に学ぶ授業形態
  • 主にチーム開発手法全般を学ぶ(アジャイルスクラムが多かった)

www.enpit.jp

enPiTビジネスシステムデザイン分野では

  • 実践的な問題解決を自発的に行えるイノベーティブな人材を育成
  • 基本的な型(既存の問題点を洗い出し→チームで開発→アウトプット)をベースに、それぞれのプロジェクトチームでカスタマイズをしていく

→大学・学生・地域で特色が生まれる

  • 一方で、同じ枠組みで情報共有のコミュニティが生まれる

→その一例が、今回のワークショップ

ワークショップでは

口頭発表

  • 全国10拠点から選ばれた代表チームが口頭発表
  • サービスを作るに至った出発点、ターゲットの説明
  • 作ったサービス(Webアプリ、スマホアプリ)の紹介
  • チーム開発をやってみた後の、感想や評価、反省点
  • 気軽に問題解決をする場所がない、チーム連携が取りにくい → 日報制度導入:誰がどこに詰まっているかを可視化(公立はこだて未来大学チーム)
  • 対象のユーザーが広く必要な機能が定まらないまま開発を始めてしまった(琉球大学チーム)

デモンストレーション

  • ポスター展示
  • 実機デモ
  • チーム開発体験

学生ブース

嘉悦大学チーム アジャイル開発

  • チームの参加者が経済学部生で、開発経験が0だった

→ モブプログラミング実施したことで、経験の差を埋めた

開発ベロシティグラフを作成したことで、振り返り時に開発の滞った時期や原因を客観的に見ることが出来た

企業ブース

トリスタ

  • タスクの粒度を小さく
  • タスクを1時間程度で、チーム内の誰でも着手可能なように、小さく設定
  • チーム内に共通認識を構築し、全員が開発の流れ、今の立ち位置、目標、技術面を把握
  • 分担を分野単位にしていない(サーバーもいじれるし、フロントもいじれる)

pixiv

  • 社内にサービス毎にチームがたくさんある
  • それぞれのチームは各分野(サーバー、フロント、デザインなど)の人が集まっている
  • 社内のほぼ全員がgitにcommit可能(チーム外からのissue投げやcontributeもある)

感想

(ここから個人の感想です)

これまでのチーム開発経験での問題点

  • 経験の差が開き、置いていかれる人が出る
  • 各人の開発状況が不透明になる→歩調が合わなくなる

今回のワークショップに参加し、様々な経験談や事例を聞いてきました。

解決法

  • 分野で担当をわけず、チーム全員が、何を使ってどう開発が進んでいくか把握した状態を維持する
  • モブプログラミングを実施し、わからない人を置いていかない&コードレビューしてもらい技量アップ
  • Slackで一人一つ独り言チャンネルを作成し、作業メモをしながら開発を進める(困った点などは見てる人がサポート)
  • タスクの粒度を小さくする
  • アジャイル開発においてスプリントを短く設定する

こんなところが学びとしては大きかったです。

AR kit で顔面キャスアプリを作る (その3 顔面情報の送受信)

今回やること

今回は、その2で確認した、顔面各パーツの数値データを、アプリとサーバーの間で送受信します。

送信

こんな感じでサーバーに数値をリアルタイムに送信することに成功しました。

FaceTracking中にfaceGeometryがアップデートされた時に呼ばれる関数に、Socketに値を送信するコードを挿入しました。

受信

サーバーから受信した値を元に顔の3Dオブジェクトを動かします。

続きを読む