WindowsでC#とJavaでプロセス間通信する

背景

Windowsはなぜかローカルホストでのソケット通信を許可してくれない。そのため、OSCでプロセス間通信をしていたアプリをWindowsに持ってくると全滅する。Windows使わないという手はあるのだが、今回はKinect SDKを利用したいので、OSC以外の方法でプロセス間通信を実装した。

システム概要

Kinect SDKC#で利用し、その情報をプロセス間通信を利用してProcessing(つまりJava)に投げてProcessing側でメインの処理をする。
プロセス間通信は色々な方法があるが、今回利用したプロセス間通信の手法は『名前付きパイプ(またの名前をFIFO)』である。
送信する情報は"顔の位置と向き"だ。数値を文字列にして渡している。

サーバー側(C#

Kinect SDKを利用して情報を送信するサーバー側はC#である。コードは著作権的ゴニョゴニョにより一部のみしか載せられないので、詳しくは下記のサイトなどを参照だ。なので動作は確認していない。
方法: ネットワークのプロセス間通信で名前付きパイプを使用する
以下のコードのStart()は起動時に一度呼ばれるメソッド。Stop()は止まった時、OnFaceFrameArrived()は顔認識が出来た時に毎回呼び出されるメソッドである。OnFaceFrameArrived()で顔の位置と向きを送信している。クライアント側を止めると例外が投げられるので、パイプの送信するメソッドたちは本来tryを利用して例外をキャッチする必要がある。

NamedPipeServerStream pipeServer;

public void Start()
{
    pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.Out, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
    Console.WriteLine("[PIPE SERVER] thread created");
    pipeServer.BeginWaitForConnection(ConnectCallback, null);
}

public void ConnectCallback(IAsyncResult result)
{
    Console.WriteLine("[PIPE SERVER] Client Connected");
    pipeServer.EndWaitForConnection(result);
    if (pipeServer.IsConnected)
    {
        byte[] message = Encoding.ASCII.GetBytes("START\n");
        pipeServer.BeginWrite(message, 0, message.Length, WriteCallback, null);
    }
}

public void Stop()
{
    this.pipeServer.Close();
}

private void OnFaceFrameArrived(object sender, HighDefinitionFaceFrameArrivedEventArgs e)
{
    using (HighDefinitionFaceFrame faceFrame = e.FrameReference.AcquireFrame())
    {
        if (faceFrame != null && faceFrame.IsFaceTracked)
        {
            faceFrame.GetAndRefreshFaceAlignmentResult(this.faceAlignment);
            if (pipeServer.IsConnected)
            {
                string s = this.faceAlignment.FaceOrientation.Y.ToString() + "," + this.faceAlignment.HeadPivotPoint.X.ToString() + "," + this.faceAlignment.HeadPivotPoint.Z.ToString() + "\n";
                byte[] message = Encoding.ASCII.GetBytes(s);
                pipeServer.BeginWrite(message, 0, message.Length, WriteCallback, null);
            }
        }
    }
}

private void WriteCallback(IAsyncResult ar)
{
    pipeServer.EndWrite(ar);
}

クライアント側(Processing)

サーバー側と同じくプロセス間通信以外のコードを削除したので動作は確認していない。Javaで普通にファイルを読み込む時に利用する"BufferdReader"を利用している。特殊なのは"FileReader"に渡すパスがパイプを指すものになっている。
Processingの仕様でdraw()は毎フレーム呼ばれるので、draw()でポーリングをしているわけだが、この辺りObserverパターンでコールバック関数を呼び出す感じのヤツの方が美しいよな〜と思いながら実装していたので、そういうヤツを実装した人は是非教えてほしい。今回は時間の関係でポーリングになった。

import java.io.FileReader;
import java.io.BufferedReader;

BufferedReader pipeBuffer;

void setup() {
  try {
    pipeBuffer = new BufferedReader(new FileReader("\\\\.\\pipe\\testpipe"));
  }
  catch (Exception e) {
    e.printStackTrace();
  }
}

void draw() {
  if (pipeBuffer != null) {
    try {
      while (pipeBuffer.ready ()) {
        String line = pipeBuffer.readLine();
        parseKinectValue(line);
      }
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}


void exit() {
  if (pipeBuffer != null) {
    try {
      pipeBuffer.close();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
  super.exit();
}

void parseKinectValue(String str) {
  String[] strs = str.split(",");
  if (strs.length == 3) {
    println(str);
    float faceAngle = Float.parseFloat(strs[0]);
    float x = Float.parseFloat(strs[1]);
    float z = Float.parseFloat(strs[2]);
  }
}

Macで自動的に印刷する

自動的に印刷するソリューションを開発したのでメモ。はがきサイズの写真用紙に印刷したいというのが今回の目的。MacのバージョンはOS X Yosemite 10.10.5である。

lprコマンドで印刷する

Macでこういう自動化をしようとすると真っ先にAutomatorAppleScriptが思い浮かぶ。この2つ印刷することは可能なのだが、オプションが選べない。用紙サイズさえ選べないのだ。AppleScriptでオプション選択しようとするとGUIスクリプティングが必要になってちょい手間だし、Automatorも同じだ。その点、lprコマンドはオプションも選べるのでCUIでやる上ではベストな選択肢となる。

システムの構成

今回の自動印刷はAutomatorによってフォルダアクションとシェルスクリプトを組み合わせて実現した。あるフォルダに画像を出力するアプリがあって、その画像をフォルダアクションで取得し、そのままシェルスクリプトに投げる。

今回のコマンド

lpr hoge.png -o PageSize=EPPostcard100x148 -o EPIJ_Medi=65 -o EPIJ_Qual=358 -o EPIJ_OPT_Bi_D=0

lprはMacの印刷コマンドで、こんな感じで使っている。オプション4つをつけている。

  • PageSize:用紙サイズ
  • EPIJ_Medi:用紙種類
  • EPIJ_Qual:印刷品質
  • EPIJ_OPT_Bi_D:高速印刷

オプションはlpoptionsコマンドから調べられる。PageSize以外はすべて今回利用したエプソンのプリンタに依存するオプションだと思う。上で書いたオプションはlpoptions -lで出力された下記のリストから、GUIの印刷ダイアログ(印刷品質のところのキャプチャを下に貼っておく)と照らしあわせて、当たりをつけた。デフォルトの選択肢にアスタリスクがつくのと、数字の大小ではなくダイアログに出てくる順に並んでるから当たりはつけやすい。

EPIJ_Medi/Media Type: *0 56 67 65 59 58 93
EPIJ_Qual/Print Quality: 353 *354 359 355 356 358
EPIJ_OPT_Bi_D/High Speed Printing: 0 *1

f:id:miso_engine:20160329152558p:plain
印刷品質の場合、デフォルトの選択肢が2番目で、ダイアログのデフォルト選択肢も2番目だから"標準"は"354"であることが推測される。最高品質で印刷したいので、高精細に当たると思われる"358"を選んだ。

オプションを詳しく見る

上記の予想の付け方で大体はいいのだが、いかんせんlpoptionsで出力されたオプションの名前と印刷ダイアログの日本語との対応が予想出来ないのもある。そういう場合は、プリンタの設定が書かれたPPD(PostScript Printer Description)ファイルを見ると対応が分かる。
Macの印刷はCUPS(Common Unix Printing System)というAppleが開発をしているオープンソースのシステムによって動いている。このCUPSのヘルプを見たところ、プリンタ毎の設定は、プリンタ毎のPPDファイルから読み込んでいるとのこと。そしてPPDファイルは /etc/cups/ppd/ にあることが分かった。この中にプリンタ名.ppdというファイルが存在するのでそちらを開くとオプションのシステム上での名前と印刷ダイアログでの名前の対応付けが分かるのだ。EPIJ_Qualのところを抜き出すとこんな感じ。"358"は高精細ではなく最高画質でしたね……。

*ja.EPIJ_Qual 353/はやい: ""
*ja.EPIJ_Qual 354/標準: ""
*ja.EPIJ_Qual 359/標準(高発色): ""
*ja.EPIJ_Qual 355/きれい: ""
*ja.EPIJ_Qual 356/高精細: ""
*ja.EPIJ_Qual 358/最高画質: ""

フォルダアクションとシェルスクリプト

Automatorで作成した。
f:id:miso_engine:20160329152742p:plain

for f in "$@"
do
	lpr "$f" -o PageSize=EPPostcard100x148 -o EPIJ_Medi=65 -o EPIJ_Qual=358 -o EPIJ_OPT_Bi_D=0
done

まとめ

EPSONがオプションについての説明をWebに載せてくれてたら……と思いながら作業した。
今回のスクリプトたちはデフォルトのプリンタで印刷することになっていてプリンタの指定はしていない。必要な方は適宜してくだされ。

早稲田大学理工学術院 基幹理工学研究科 表現工学専攻 向け修士論文テンプレート

MacBook Air (11-inch, Mid 2012)でWordを使うと大変重く、またよく落ちるものだから、Wordを使う縛りがない修士論文は、TeXを使ってコーディングし出力した*1。目次、図目次、表目次、参考文献の自動出力は大変使いやすく助かった*2。今回、僕が作成した、所属(早稲田大学理工学術院 基幹理工学研究科 表現工学専攻*3)向けの修士論文テンプレートを公開する。

環境はMac OS X 10.10.5 (Yosemite)とMacTeX-2015である。導入も結構手間があったのだが、来年使うとしたらEl Capitanだろうし、El Capitanではヒラギノフォントの扱いが大きく変わったとのことで、書いても役に立たないし個別の事情が多すぎかつ今更インストールしてなかった状況を再現できないので割愛する。各自導入してほしい。

CotEditor

CotEditor

  • Mineko IMANISHI
  • 仕事効率化
  • 無料
執筆環境としては基本CotEditorで書き、ターミナルでmakeしてコンパイルしていた。CotEditorは本当にいいエディタである。TeXShopbibtexファイル編集用に利用した。

作成したテンプレートの経緯及びライセンス

http://ymrl.github.io/thesis-template/
http://wiki.kurokobo.com/index.php?LaTeX
今回のテンプレートは@ymrlのテンプレートからのフォークである。そして@ymrlテンプレートは@kurokoboテンプレートからのフォークである。@ymrlの改変部分は著作権が放棄されているが@kurokoboのオリジナルの著作権は明示されていないはずである。僕が@ymrlファイルから改変した部分は著作権を放棄するのでどうぞご自由に。

http://shokai.org/blog/archives/4858
なおテンプレートを改変するにあたり@shokai*4が公開していたこの記事を参考にした。

@ymrlテンプレートからの主な改変

ドキュメントクラス

最大の改変である。古い日本語ドキュメントクラスであるjreportを利用していたのを[report]{jsbook}に変更した。それに伴い諸々の設定を削除した。新ドキュメントクラスについて詳しくは以下参照である。
pLaTeX2e 新ドキュメントクラス

Makefile

platexを使っているところをuplatexに修正した。bibtexも同様にupbibtexにしている。

参考文献と発表文献を分けた

分けろという風潮があったので、分けてみた。ほぼ以下の記事の形で利用した。
TeXで2つの参考文献ファイル(.bib)を読み込んで参考文献と発表論文リストに分ける - how to code something

英語に関するアレコレの削除

SFCの流儀で英語のアブスト等もあるのだが、我が所属は必要なかったので削除した。

ファイルの役目

  • main.tex
    • メインのtexファイル
  • main以外.tex
    • 論文中の章ごとに分割したファイル。main.texにインクルードされる形になる
  • bibDB.bib
    • 参考文献のbibtexファイル
  • pubDB.bib
    • 発表文献のbibtexファイル
  • thesis.sty

参考文献の処理法

全自動

bibtexファイルである.bibのファイルに書いてコンパイルすると勝手にやってくれる。テンプレートも自動化を前提としている。

やり方

.bibファイルにbibtex出力したものをコピペしていく。特に管理ソフトは利用していない。

bibtexファイルの入手法

分野的に大体の論文がACMだったので、ACM Digital Libraryからダウンロードでき、書誌情報もbibtexでダウンロードできたので、それを利用した。日本語はCiNii、その他は大体google scholorでいずれもbibtexファイルの出力に対応している。
WebサイトについてはChrome拡張を利用した。今回使った拡張は自動的にアクセス日時もいれてくれて助かった。好みで選べばいいと思う。
BibTeX entry from URL - Chrome Web Store

修論自体とテンプレート作成の参考文献

[改訂第6版] LaTeX2ε美文書作成入門

[改訂第6版] LaTeX2ε美文書作成入門

バイブル。書籍はこれのみでよい。どう書けばよいかな?と思ったらググらずにまずこの書籍にあたるのがベスト。今年さらに改訂されるとのこと*5。あんしん!

参考Webサイト

TeXLaTeXググる時の注意

TeXLaTeXも20世紀からあり、情報が古すぎることがある。そのまま使えるものと使えないものがあり、結構それを区別するのが大変なので、なるべく最新の情報から参考にするとよい。

*1:最終的にコンパイルに30秒かかるようになったけど

*2:Wordも出来るはずだけどね

*3:ところでこれが正確な表記なのかイマイチ自信がない

*4:ところでここに出てきた3人は全てSFCの人間なのだが、僕の出自がSFCだからというのもあるんだが、実際にはたまたまこの3人になってしまったという感じがある。というのも2010年代にTeXのテンプレートを公開している人というのが少なく、コンパイル出来るテンプレートというのがさらに少なかったのだ。たぶんTeXを使ってるんだろうなという研究室、卒論・修論生は多く見かけるのに公開されているテンプレートが少ないのは残念だ。

*5:https://twitter.com/h_okumura/status/693230216794083328

*6:美文書の著者である日本TeX界のグル奥村先生の研究室ドメインにあったのが最近移転。退官やポスト移動のために消えていくことの多い大学研究室ドメインから移転してあんしん!