Help us understand the problem. What is going on with this article?

JINS MEMEのデータをtcp socket通信で出力、Processingに流してグラフ化してみる

More than 3 years have passed since last update.

What's JINS MEME

以前まとめたものがありますので、そちらをご参考ください。
http://qiita.com/mito_log/items/020a87996ed2b9d793e6

Why

前回、JINS MEMEのデータをxx秒おきにGoogle SpreadSheetに流すをやりましたが、それはリアルタイムデータの取得&解析用といった感じなので今度はリアルタイムに且つ視覚的にデータを見てみようと思います。今回もRxSwiftで書きました。

ちなみに...
ios上でのグラフ化はAdventCalendar3日目がよくできています!今回は可視化という部分で重複しますが、tcp socket通信の部分も含みますので、とりあえず進めてみました。

What I created

  • JINS MEMEのリアルタイムモードのデータをtcpソケット通信で特定のIP/Portに出力
  • 受け側のアプリをProcessingで作成しグラフ化

というものを作りました。

※ 検討段階ではwebsocketやudpで~と思いましたが過去の遺産を漁ってみたらtcpが楽そうだったのでとりあえずそれでやっています

github

https://github.com/mitolog/JINSMEMESampler

※ 今回のソースはProcessingのフォルダ配下

Screenshots

ios
JINSMEME_Processing_iphone.png

Proecssing
JINSMEME_Proecssing_ps.png

How to Use

JINSMEMESample_Processing.png

  1. まずiOSデバイスとProcessingの走るマシンを同じローカルエリアネットワーク内に参加させます。
  2. ProcessingのJava applet(サーバ)から立ち上げ、次にiOSアプリ(クライアント)を起動します。
  3. 起動したら、iOS側でサーバのIPとポートを指定して、スタートボタンを押すと通信が開始されます。

Miscellaneous

  • IPとポートのTextFieldにバリデーションを入れていて、IPは4つのセグメントがないといけません、ポートはtcpの自由割当ポート(49152から65535)の中に収まっていないといけません
  • Processingでは、画面上をクリックすると、ソケット通信をON/OFFできます。
  • Processingでは、fpsを左下にプロットしていて、JINS MEMEの通信速度20Hz(20fps)を下回るとデータ落ちしますので、遅延がひどくかんじられます

Recap

About RxSwift

Validation, Sync multiple inputs with combineLatest

combineLatestは、複数のObservableを引数にとり、どちらか一方の引数で最新の値が来ると、それをトリガーにして最終引数にセットされたクロージャに値が引き渡されます。クロージャでそれらの値をよしなに処理してreturnすると、ObservableでラップされてsubscribeするObserverに値が渡されます。

combinelatest.png
画像: RxSwiftのPlaygroundより

Playground(Combining_Observables)
example("combineLatest 1") {
    let intOb1 = PublishSubject<String>()
    let intOb2 = PublishSubject<Int>()

    _ = combineLatest(intOb1, intOb2) {
        "\($0) \($1)"
        }
        .subscribe {
            print($0)
        }

    intOb1.on(.Next("A"))

    intOb2.on(.Next(1))

    intOb1.on(.Next("B"))

    intOb2.on(.Next(2))
}

/*
Codes above will prints like below:
Next(A 1)
Next(B 1)
Next(B 2)  
*/

今回は、このcombineLatestの、引数としてとる値が少なくとも1回以上publishされていないとクロージャに処理が回ってこない。という性質を利用しました。具体的には、

  • IPアドレスとポートをきちんと入力しないと通信開始ボタンが押せないようにする
  • 通信開始ボタン、tcpソケット接続完了、JINS MEMEのデータ取得のタイミングが揃ったタイミングでcsvデータをProcessingに送信

という機能を実現するためにcombineLatestを使っています。

About socket communication

Tcp socket communication using NSStream

今回、tcpソケット通信を行うクラスとして、TcpSocketManagerというクラスを作りました。そこでは、NSStreamとNSOperationを組み合わせて新規にスレッドを作成し、そこでrunloopを回して、socketデータのI/Oを管理しています。

基本的には、以下のサイトを参考しています。
NSStreamを利用してiRemoconと通信する
Setting Up Socket Streams

ソース中でautoreleasepoolディレクティブを使っている箇所は、データ更新頻度が多いため、ARCでなるべく早いタイミングでメモリ解放させるためにセットされているかと思います。

また、ちょっとトリッキーなところとしては、main関数の中で、

TcpSocketManager.swift
repeat{
    autoreleasepool {
        self.runloop.runUntilDate(NSDate(timeIntervalSinceNow:0.1))
    }
} while (_executing)

とすることで、実行中0.1秒ごとにrunloopが延命され、その間はずっとstreamが維持される仕組みになっています。

About Processing

Server (Processing built-in socket communication library)

ProcessingにはServerというtcpソケット通信を可能にするクラスがネットワークライブラリの一部としてデフォルトで備わっています。使い方は簡単で、以下のように使うことができます。

import processing.net.*;

Server myServer;
int val = 0;

void setup() {
  size(200, 200);
  // Starts a myServer on port 5204
  myServer = new Server(this, 5204); 
}

void draw() {
  val = (val + 1) % 255;
  background(val);
  myServer.write(val);
}

ServerがあるのでClientもありますが、今回は使っていません。
ライブラリのリファレンスはこちらからどうぞ。

About JINS MEME

Yaw value is...

グラフ化してみるとわかるのですが、頭のx,y,z軸方向の回転量を示すroll, pitch, yawの値のうち、yawがどうもおかしいようです。値が連続的ではなく急に変化しています。具体的には、0度から急に-300~くらいの値になってしまいます。

本来はこちらの記事と同じで、

roll: 0° -> 90° -> 0° -> -90° -> 0°
pitch: 0° -> 90° -> -180°/180° -> -90° -> 0°
yaw: 0° -> 90 -> 180 -> 270 -> 360°

となるはずですが、yawの値にマイナスがついてしまっています。310~320くらいでマイナスに転じているので、符号化bit云々の話かもしれません。そこはちょっと内部の処理になりますので組込な方がいれば教えて欲しいところです。もしくはSDKの改善に期待です。

EyeBlink :) , Eyemove :(

大体どちらの値もメガネをかけてしばらくすると安定してデータが取れるようになります。
グラフでみると、まばたきの検知は結構感度いいですが、目線の移動はそこまで正確にとれないようで、こちらもSDKの改善に期待したいと思います。

todo

yaw値がグラフからはみ出ていますが、上記のyaw値の関係で一旦スルーして、0を中心に+180, -180°の範囲にしています。ここはyaw値が修正され次第修正したいと思います。

References

IRMCommandOperation
Tcpソケット通信のクラスを作る上でベースにさせていただきました。ありがとうございます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした