13
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

unity > 時系列グラフの描画 > timeGraph > UDPで "時:分,データ" を受信してグラフ化 / y軸の範囲も変更できる / y軸のmin,max表示 / x軸:daily,weekly,monthly,yearly / データexport機能付き

Last updated at Posted at 2015-09-09
実装
Unity 5.1.2-f1 on MacOS X 10.8.5

http://qiita.com/7of9/items/c346562cefa42bfd981e
にて時系列グラフを描画できるようになったが、時刻については現在時刻を使用しているのでフレキシブルではない。

"12:30,0.3" (12時30分に数値0.3)
という形式のデータを受信してグラフ描画したい。

code

v0.3 @ github

v0.3への変更においては主に以下を変更した。

udpReceiverScript.cs
...
	string extractCsvRow(string src, int idx)
	{
		string[] splitted = src.Split(new string[] { System.Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);
		string res = "";
		foreach(string each in splitted) {
			string [] elements = each.Split(',');
			res = res + elements[idx] + System.Environment.NewLine;
		}
		return res;
	}

	void sendToGraph(string text)
	{
		// udp text should be in the form of "12:30,-0.2"
		// where 
		//   "12:30" is hour and minutes,
		//   and "-0.2" should be in range [-1.0, 1.0]
	
		string first = extractCsvRow (text, /* idx=*/0);
		string second = extractCsvRow (text, /* idx=*/1);

		// TODO: input error check

		System.DateTime dt = System.DateTime.Parse (first);
		float yval = float.Parse (second);
		timeGraphScript.SetXYVal (dt, yval);
	}

"12:30,0.3"をextractCsvRow()でパースして、12:30をSystem.DateTime.Parse()で時刻情報に変換している。

実行環境

  • 送信側 > 192.168.10.8 : データをUDPで送信する (OS: CentOS 6.5で確認)
  • 受信側 > 192.168.10.3 : 本アプリの実行 (OS: MacOS X 10.8.5で確認)

192.168.10.8 >> UDP(6000) >> 192.168.10.3

192.168.10.8からの送信は以下のスクリプトを使用。
5秒ごとにデータ文字列 ("02:10,-0.9"など)を送信する。
http://qiita.com/7of9/items/1cf64a125784db309100

udpSend-exec
# !/bin/env bash

for data in \
"00:00,0.2" "02:10,-0.9" "03:40,0.3" \
"05:30,-0.9" "09:30,0.2" "11:30,0.4" \
"13:30,0.1" "16:30,0.5" "18:30,0.9" "22:00,-0.9";do
  sleep 4
  ## echo $data | nc -u 192.168.10.3 6000 &
  echo $data | nc -w 1 -u 192.168.10.3 6000 
done

[2015/09/10追記]
上記のコメントアウトした行のようにncに&をつけた方法はncのプロセスが残ってしまうようです。

ncコマンドは-w 1で1秒のタイムアウトにできるようなので、上記のように訂正しました。これでncのプロセスが残りません。

結果

CentOS側 (送信側 192.168.10.8)

$ bash udpSend-exec 
00:00,0.2
02:10,-0.9
03:40,0.3
05:30,-0.9
09:30,0.2
11:30,0.4
13:30,0.1
16:30,0.5
18:30,0.9
[tmp]$ 22:00,-0.9

Unityアプリ側 (受信側 192.168.10.3)

udpTimeGraphMac_と_Main_unity_-150908-udpTimeGraph-PC__Mac___Linux_Standalone__Personal__と_Assembly-CSharp-udpReceiverScript_cs-_MonoDevelop-Unity.jpg

UDP送信したものをグラフ化できた。

v0.4 (y rangeの変更コマンド追加)

v0.4 @ github

変更点

  • UDP通信にsetコマンド対応を追加
  • setコマンドの1つとしてyrange対応を追加。グラフのy軸範囲を変更可能
set,yrange,-3.0,3.0

上記コマンドによりグラフのy軸表示範囲が[-3.0, 3.0]に変更できる。

例として以下は[-1.0,1.0]で描画している。

Main_unity_-150908-udpTimeGraph-PC__Mac___Linux_Standalone__Personal.jpg

set,yrange,-3.0,3.0をUDP送信すると以下のようになる。

Main_unity_-150908-udpTimeGraph-PC__Mac___Linux_Standalone__Personal.jpg

v0.5 (y軸のmin, maxを表示)

v0.5 @ github
関数の説明 @ mindmup

Panelの近くにTextを表示する方法を学んで、グラフのy軸のmin, maxを表示するように変更した。

  • graphScale というTagをタグリストに追加
  • drawGraphScale()を実装
    • "graphScale"タグのGameObjectを削除
    • drawTextOnTheLeftOfPanel()にてmin, maxの値を表示

Main_unity_-150908-udpTimeGraph-PC__Mac___Linux_Standalone__Personal.jpg

v0.6 (v0.5のリファクタ版)

v0.6 @ github

timeGraphScriptの処理の可読性を上げるため、timeGraphScript.csで実装していたPanel関連のものを MyPanelUtil.cs に移した。
DrawLineはまだ移動していない。

v0.7 (Dictionaryを保持)

v0.7 @ github

今後、横軸をhour:minutes以外の表示に変更するための前段階として、以下の変更をした。

[変更前]
SetXYVal()されるたびに(System.DateTime, float)のデータを(float, float)に変換した上でListに保持

[変更後]
SetXYVal()されるたびに(System.DateTime, float)をDictionaryに追加。
グラフ描画前に refreshGraphPoints()にて全データについてSystem.DateTimeの値から横軸を計算。

v0.6まで
void Update() {
		accTime += Time.deltaTime;
		if (accTime < 0.3f) { // for every 300 msec
			return;
		}
		accTime = 0.0f;
		
		clearGraph (timeGraphPanel);
		
		if (isSet) {
			isSet = false;
			timeGraph_xy (timeData, timeGraphPanel, xval, yval);
		}
		
		drawGraph (timeData, timeGraphPanel);
	}
v0.7から
    static public void SetXYVal(System.DateTime time, float yval_)
	{
		dateTime_val_dic.Add (time, yval_);
	}
	void Update() {
		accTime += Time.deltaTime;
		if (accTime < 0.3f) { // for every 300 msec
			return;
		}
		accTime = 0.0f;

		clearGraph (timeGraphPanel);
		refreshGraphPoints (dateTime_val_dic, timeGraphPanel); 
		drawGraph (graphPoints, timeGraphPanel);
	}

v0.8 (x軸のスケール[dailyのみだった]にweekly追加)

v0.8 @ github

以下を追加した

  • set,xtype,[種類]コマンドを追加
    • set,xtype,daily
    • set,xtype,weekly
    • set,xtype,monthly (計算の実装は途中)
    • set,xtype,yearly (計算の実装は途中)
  • 上記のdailyとweeklyについて、x軸の位置計算を実装

送信側(CentOS)のスクリプト

# !/bin/env bash

toadr="192.168.10.3"
sleep 5

echo "set,xtype,weekly" | nc -w 1 -u $toadr 6000

for data in \
"2015/9/10 00:00,0.1" \
"2015/9/10 02:10,0.45" \
"2015/9/11 03:40,-0.45" \
"2015/9/11 05:30,-0.45" \
"2015/9/12 09:30,0.2"  \
"2015/9/12 11:30,0.4" \
"13:30,0.1" "16:30,0.5" "18:30,0.9" "22:00,-0.9";do
#  sleep 1
  echo $data | nc -w 1 -u $toadr 6000 
done

sleep 3
echo "set,yrange,-3.0,3.0" | nc -w 1 -u $toadr 6000
sleep 3
echo "set,yrange,-1.0,1.0" | nc -w 1 -u $toadr 6000

結果

daily表示 (set,xtype,daily コマンド発行後)

Main_unity_-150908-udpTimeGraph-PC__Mac___Linux_Standalone__Personal.jpg

weekly表示 (set,xtype,weekly コマンド発行後)

Main_unity_-150908-udpTimeGraph-PC__Mac___Linux_Standalone__Personal.jpg

bug: "12:30,0.3", "2015/09/10,0.5"のように、日付なしとありのデータが混ざっているとX軸の計算が失敗している。

v0.10 (montly, yearlyグラフ対応)

v0.10 @ github

v0.8以降の変更は以下の通り。

  • テスト用GameObjectを追加
    • TestRelated/Test_xscaletype : グラフにサンプル用時系列データを追加
    • TestRelated/Test_xcalechange : Activeにすることで時系列の表示タイプを変更できる
  • バグ修正
    • dailyグラフ表示 : 他の日のデータも表示されていた
    • weeklyグラフ表示 : 他の週のデータも表示されていた
  • 機能追加
    • MyTimeUtil.cs追加 : 時系列関連の計算用
    • monthlyグラフ表示追加
    • yearlyグラフ表示追加

使用例

プレイモードにて実行

Test_xscaletypeをActiveにすることで、グラフにサンプルデータが追加される。最初はdailyグラフが表示される。

Main_unity_-150908-udpTimeGraph-PC__Mac___Linux_Standalone__Personal.jpg

Main_unity_-150908-udpTimeGraph-PC__Mac___Linux_Standalone__Personal.jpg

Test_xcalechangeをActiveにして、XTypeの値を変更する。
0:Daily, 1:Weekly, 2:Monthly, 3:Yearly.
下の例ではWeeklyにしている。

Main_unity_-150908-udpTimeGraph-PC__Mac___Linux_Standalone__Personal.jpg

Main_unity_-150908-udpTimeGraph-PC__Mac___Linux_Standalone__Personal.jpg

以下はMonthlyやYearlyにした例。

Main_unity_-150908-udpTimeGraph-PC__Mac___Linux_Standalone__Personal.jpg

Main_unity_-150908-udpTimeGraph-PC__Mac___Linux_Standalone__Personal.jpg

サンプルデータ生成部分

以下の日時データ(縦軸は乱数)が上のグラフではきちんと表示されているようだ。

Test_xscaletype.cs
...

	void Test_addData() {
		string [] dts = new string[]{ 
			"2015/01/10 05:30",
			"2015/02/05 12:30",
			"2015/03/01 08:30",
			"2015/04/07 23:50",
			"2015/07/11 09:30",
			"2015/08/12 12:30",
			// for today (as of Sep.13, 2015)
			"2015/09/13 8:30",
			"2015/09/13 10:00",
			"2015/09/13 11:30",
			"2015/09/13 16:30",
			"2015/09/13 20:10",
			"2015/09/13 23:40",
			//
			"2015/09/14 09:30", 
			"2015/09/15 11:30", 
			"2015/09/16 13:30",
			"2015/09/17 13:30",
		};

		System.DateTime curDt;
		float yval;
		int idx = 0;

		foreach(var dt in dts) {
			curDt = System.DateTime.Parse(dt);
			yval = Random.Range(-1.0f, 1.0f);
			timeGraphScript.SetXYVal(curDt, yval);
			idx++;
		}
...

サンプルデータ表示後は TestRelated/Test_xcalechange をDeactivateにして、UDP通信でグラフの縦軸、横軸の変更が可能。

v0.11 (データexport機能追加)

グラフに表示したものを後で取り出して使いたい、ということはありそうなので、data export機能を追加した。

UDPコマンドは以下で取り出せる。

set,export

v0.11 @ github

(追記 2015/09/13) 時刻表記が12時間表記だったのを24時間表記に修正。同じv0.11としてタグづけした。

主な変更箇所

timeGraphScript.csにおいて、データ辞書であるdateTime_val_dicをstatic public定義に変更 (udpReceiverScriptでアクセスするため)。

static public Dictionary<System.DateTime, float> dateTime_val_dic;

udpReceiverScript.csにおいてexportData()を追加し、"set,export"を受信したら実行するようにした。

udpReceiverScript.cs
...
	private void exportData(ref UdpClient client, ref IPEndPoint anyIP) 
	{
		byte[] data;
		string text;

		text = "SOT"; // start of table
		text = text + System.Environment.NewLine;
		data = System.Text.Encoding.ASCII.GetBytes(text);
		client.Send(data, data.Length, anyIP);

		foreach (var ptr in timeGraphScript.dateTime_val_dic) {
			text = ptr.Key.ToString("yyyy/MM/dd HH:mm:ss");
			text = text + ",";
			text = text + ptr.Value.ToString();
			text = text + System.Environment.NewLine;

			data = System.Text.Encoding.ASCII.GetBytes(text);
			client.Send(data, data.Length, anyIP);
		}

		text = "EOT"; // end of table
		text = text + System.Environment.NewLine;
		data = System.Text.Encoding.ASCII.GetBytes(text);
		client.Send(data, data.Length, anyIP);
	}

実行例

プレイモードで実行後、サンプルデータを足すため Test_xscaletypeゲームオブジェクトをActiveにする (通常使用時はUDP通信[データコマンド]でデータを送信し続けてデータを蓄積しておく)。

Main_unity_-150908-udpTimeGraph-PC__Mac___Linux_Standalone__Personal.jpg

データを受けたい側(例: 192.168.10.6 CentOS)でset,exportコマンドを発行して、受信し続ける(データはプロトコル通信ではなく、一気に送られる)。

CentOS6.5側実行例
$echo "set,export" | nc -u 192.168.10.3 6000
SOT
2015/01/10 05:30:00,-0.1320719
2015/02/05 12:30:00,0.2371362
2015/03/01 08:30:00,-0.6964777
2015/04/07 11:50:00,-0.1670557
2015/07/11 09:30:00,0.07135642
2015/08/12 12:30:00,-0.2585875
2015/09/13 08:30:00,-0.4348444
2015/09/13 10:00:00,-0.4057344
2015/09/13 11:30:00,-0.9436774
2015/09/13 04:30:00,0.2064427
2015/09/13 08:10:00,0.678241
2015/09/13 11:40:00,-0.9753504
2015/09/14 09:30:00,-0.5227482
2015/09/15 11:30:00,-0.4138082
2015/09/16 01:30:00,-0.4343764
2015/09/17 01:30:00,0.1775364
EOT
^C

上記のSOT(Start of Table)からEOT(End of Table)の間のデータが日時と値のセット。

一気に送られるので、受信側はEOTを受けるまで受信し続けないといけない。

今後

今後の予定

13
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?