<IoT×Unity>加速度センサで3Dオブジェクトをネット越しにグリグリしてみた

今回は凹 (id:hecomi) さんに触発されて(SerialPort または Uniduino を使った Unity と Arduino を連携させる方法調べてみた - 凹みTips)書いた記事といっても過言ではないです。
というよりもここ最近の記事は全て今日のための布石といってもいいくらいな感じです
凹 (id:hecomi) さんが作っていたのがこれ↓

加速度センサでグリグリさせるやつこれを
私もやってみたい・・・
ただ真似しても面白くないのでMQTTでネット越しにやってみた


加速度センサでUnityオブジェクトをぐりぐりしてみた - YouTube


ちょっと遅いけどできた!

ちなみに
加速度センサはラズパイに繋げている詳細は以下
<IoT>加速度センサの値をMQTTを使ってネット越しにやりとりする - xhatenenの日記
加速度センサのPub側のコーディングも、上記の記事の無限ループverをそのまま利用した

Sub側に関しては
凹 (id:hecomi) さんの記事と
<IoT×Unity>MQTTをUnityで受けてみた! - xhatenenの日記
を組み合わせて以下のようにコーディングした

using UnityEngine;
using System.Collections;

using uPLibrary.Networking.M2Mqtt;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using uPLibrary.Networking.M2Mqtt.Messages;

public class Rotation : MonoBehaviour {
 
    private MqttClient4Unity client;
    
    public string brokerHostname = "*********";
    public int brokerPort = ******;
    public string userName = null;
    public string password = null;
    public string topic = "***********";

    private Queue msgq = new Queue();

    string lastMessage = null;

    private List angleCache = new List();
    public int angleCacheNum = 10;
    public Vector3 angle {
        private set {
            angleCache.Add(value);
            if (angleCache.Count > angleCacheNum) {
                angleCache.RemoveAt(0);
            }
        }
        get {
            if (angleCache.Count > 0) {
                var sum = Vector3.zero;
                angleCache.ForEach(angle => { sum += angle; });
                return sum / angleCache.Count;
            } else {
                return Vector3.zero;
            }
        }
    }

    
    void Start () {
        if (brokerHostname != null && userName != null && password != null) {
            Connect ();
            client.Subscribe(topic);
        }
    }
    
    
    float anglex;
    float angley;
    float anglez;
    float pitch;
    float roll;

    void Update () {
        while (client.Count() > 0) {
            string s = client.Receive();
            msgq.Enqueue(s);
            String str;
            str = s.Split(new char{':'});
            Debug.Log("received :" + str[0]);
            Debug.Log("received :" + str[1]);
            Debug.Log("received :" + str[2]);
	//角度のベクトルを取得
            anglex = float.Parse (str[0]);
            angley = float.Parse(str[1]);
            anglez = float.Parse(str[2]);
	//ロール角、ピッチ角の算出
            roll = -1*Mathf.Atan(angley/anglez) * Mathf.Rad2Deg;
            pitch = -1*Mathf.Atan(anglex/anglez) * Mathf.Rad2Deg;
	//アングルに設定
            angle = new Vector3(pitch,0,roll);
	//回転させる
            transform.rotation = Quaternion.Euler(angle);
        }
        
        if (Input.GetMouseButtonDown (0) == true) {
            client.Publish(topic, System.Text.Encoding.ASCII.GetBytes("nice click!"));
        }
    
    }

    void OnGUI() {
        if (msgq != null && msgq.Count > 0)
        {
            if (lastMessage == null) {
                lastMessage = (string)msgq.Dequeue();
            }else{
                lastMessage = (string)msgq.Dequeue();
                lastMessage = null;
            }
        }
        GUILayout.Label(lastMessage);
    }

    public void Connect()
    {
        // SSL使用時はtrue、CAを指定
        client = new MqttClient4Unity(brokerHostname, brokerPort, false,
                                      null);
        // clientidを生成
        string clientId = Guid.NewGuid().ToString();
        client.Connect(clientId, userName, password);
    }

    public void Publish(string _topic, string msg)
    {
        client.Publish(
            _topic, Encoding.UTF8.GetBytes(msg),
            MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE, false); // retainがfalse
    }
}

Quaternionが何者かよくわからないがそれについては
UnityのベクトルとQuaternionによる回転について - テラシュールブログ
をよく読めばわかる...はず!

一番苦労したのは、ロール角、ピッチ角の計算久しぶりすぎてまじ全然できなかった
(加速度センサの値のオイラー角化は私はできない...)
最終的に回し方をオイラー角で回しているせいでなんか回り方が微妙
ロール、ピッチで回す方法で

Quaternion.CreateFromYawPitchRoll(yaw, pitch, roll);

というのがあるという記事を読んだが、こちらも現在使えなかった

「Unityでロール、ピッチで回す方法」か「加速度センサ値のオイラー角化」を知りたい...