[雑記] システムアーキテクト 受験

システムアーキテクトという試験を受験しました。昨年に続いて2度めの受験で、今回は無事合格することができました(昨年度の受験時の記録)。
試験対策および本番で気を付けた点をまとめます。

本番までの準備

基本的な知識は昨年に受験した際に学習したため、今回は「前回学習した内容の再確認」を基本にし、その上で「解答のコツを押さえる」ようにしました。4種類ある各科目の準備は次のように進めました。なお、使った問題集は、『情報処理教科書 [秋期]高度試験午前対策 2009年度版』と『情報処理教科書 システムアーキテクト 2009年度版』の2冊です。(2011年度版のリンク:『情報処理教科書 [秋期]高度試験午前I・II 2011年版 』(午前用)と『情報処理教科書 システムアーキテクト 2011年版 』)
  • 午前I (四択/共通問題): 今回は免除のため対策なし
  • 午前II (四択/分野個別問題):
    1. 問題集を2〜3回解く。
  • 午後I (記述問題):
    1. 問題集の基礎知識部分を一読し、知識を再確認する。(1h)
    2. 過去問題を数問解き、問題の形式に慣れる。(2-5h)
  • 午後II (論文):
    1. 問題集の「論文の書き方」を一読する。
    2. 過去問題を数問解き、問題の形式に慣れる。(3-9h)
    3. プロジェクト例を想定しておく。(2h)
続いて、午後I(記述問題)と午後II(論文問題)について、学習時に意識したことと本番で意識した内容をまとめます。

学習時に意識したこと

午後I (記述問題):
  • 得意分野と不得意分野を明確に把握しておく。不得意分野の過去問題を解くときは知識を付けるようにするが、得意分野の過去問題を解くときは、知識を付けるよりも「どうやって時間内に答えを見つけるか」に重点を置く。
    (私の場合、得意分野は、業務分析・業務設計・UML・開発管理、不得意な分野はシステム移行・パッケージ導入)
午後II (論文):
  • 決まり文句は覚えておく。
    • 例 えばアについては「私はシステムインテグレータB社に属するシステムアーキテクトである。先般私が携わったプロジェクト(以下PJ)は、○○業のA社より 依頼された、○○○○○である。本システムは、○○○○○である。総開発期間は○ヶ月、要員は○人、総工数は○人月である。私は本案件にシステム構築の リーダーとして携わった。」など。
  • 各フェーズ(以下)について、実際に要した時間を記録し、以下の目安からどれだけずれたかを計る。
    • 問題文解読+ストーリー構成:20分 (〜14:55)
    • システム概要記入:5分 (〜15:00)
    • ア (目安700字):20分 (〜15:20)
    • イ (目安1200字):40分 (〜16:00)
    • ウ (目安900字):30分 (〜16:30)
  • 時間をオーバーしてしまった場合は、その原因を必ず分析する。(自分の場合は以下のような原因があった)
    • ストーリー構成で想定した内容は書き終えたものの、字数が足りず、追加内容を考えた。
    • ストーリー構成の内容が多すぎて、削りながら作文したため、時間を要した。
    • 書いているうちに内容の矛盾に気づき、修正方法の検討と修正に時間を要した。
    • 書いているうちに、ストーリー構成で想定した方針からずれていることに気づき、書きなおしたため、時間を要した。
    • 事象を説明するために、予想以上に字数を要してしまい、時間(と字数)を要した。(例えば説明するためにアーキテクチャの詳細にまで触れてしまった場合など)

本番で気をつけたこと

午後I (論述問題):
  • 試験開始前: 解答用紙が配られたときに解答欄を眺めて、どの大問でどのような解答が求められているかを眺め、解きやすそうな大問を見つける。例えば、用語を答える問題 が多いか、40字程度の記述が多いか...など。(自分は、できるだけ用語を答える小問が多い大問を選ぶようにした)
  • 試験開始直後: その解きやすそうな大問を読み、問題の概要を把握する。
    まずはパラグラフのタイトル([]で書かれた部分) だけを読む(※1)。問題なさそうなら、その後、小問を読み始めて解いていく。
  • 小問回答時: 小問が次のどちらであるかを早めに見極める。(→それぞれで戦略が異なるため)
    • 問題文中に書いてある答えを求める問題
    • 問題文中の手がかりをヒントに、システムアーキテクトの常識から答える問題
  • 字数指定の設問は、
    まず、以下を手がかりに解答を組み立てる。
    • 10字:キーワード
    • 20字:短文
    • 30-40字:修飾語をつけた文章
    • 50字:2文
    次に、字数の過不足は、冗長な表現があれば削ったり言い換えたりする、修飾語を挿入/削除する、文末を調整する。
※1 例えば、[現行システムの概要]→[〇〇業務の概要]→[○○業務の問題点]→[○○業務の改善]→[新システムの○○機能] だけを読むと、「既存のシステムを動かしているのだけど、問題があるため、改善し、新機能を追加したのか」といった流れが分かります。

午後II (論文):
  • 具体性を持ったキーワードを意図的に盛り込む。
  • 書いてみた結果字数が足りていなかったら、主張を繰り返して字数を稼ぐ。
  • 数行書くごとに、問題の趣旨に逸脱していないか確認する。(上述の「書いているうちに、ストーリー構成で想定した方針からずれていることに気づき...」への対策)
  • ストーリー構成を行うときは、あまり盛り込み過ぎないようにする。
    「問題文中に現れるキーワードの2〜3点の具体化」+(あれば)「文中にないが類推されるキーワード1点の具体化」程度でよい。
    また、その他のストーリーを書いても意味がない。
  • 主張を明確にするため、原因・方式・対策などの項目を列挙する場合、必ず順位付けをする。これをしておくと、「トレードオフのある複数の項目からひとつを選ぶ」という場合にも説明しやすいと思う。
  • 使えるフレーズ
    • 「○○という状況であった。」
    • 「○○と判明した。」
    • 「本来ならば○○が理想であった。」
    • 「○○という制約があった。」
    • 「○○方式と○○方式が考えられたが、○○方式を採用した。理由は...。」
  • システムアーキテクトの本務ではない業務は書かない。(工数と予算はプロマネと相談する/データベースとネットワークの設計はそれぞれのスペシャリストと相談する/コーディングとテストはPJメンバにさせる)
  • 解答用紙を汚さないため、問題冊子を切り離し、使わない1枚を下敷き替わりにする。(見開きの2ページについて、解答がそれぞれの解答用紙に写ってしまい非常に読みにくくなるのを防ぐため)

参考 (今回受験した際の所感と解答)

所感:
  • 午後I:
    • 問3(設備棚卸システム機能追加)と問4(デジタルサイネージシステム設計)を選択。
    • 問3は、仕事で(人力で)設備の棚卸を行ったことがあるので、題意は理解しやすかったです。ディスプレイとPC本体で同じ資産番号なのに、別々の場所にあったり、別の事業所にあったり...といろいろと面倒だった記憶があります。
    • 問4は、一見解けそうと思い着手したものの、推測で書かせる解答が多く、自分の答えが合っているのかそうでないのか自信が持てず、終始不安でした。
  • 午後II:
    • 問3(組込みシステムでのハードウェアとソフトウェアの機能分担)を選択。
      問2か問3で迷いましたが、問2がだいぶ抽象的で書きにくそうに感じたため。
    • 字数は、ア:約800字、イ:約1000字、ウ:約800字。
    • イとウの内容分担が不明確のまま書いてしまい、少し内容が重複してしまったような気がします。 書いている途中でイとウの内容分担で悩んでしまったためか、時間はぎりぎりでした。
午後Iで書いた解答 (自分のメモより。下線部はおそらく×となったであろう答え)
(ちなみに、80点でした)
  • 問3
    • 設問1:(忘れました...)
    • 設問2(1):同一の資産シールを複数枚発行している資産についての現物数の不足
    • 設問2(2):
      照合内訳数/内訳テーブルの現物照合実施日が初期値の場合のみ、1を加算する。
      最新現物照合実施日/内訳テーブルの現物照合実施日の値と同一とする。
    • 設問3:(忘れました)
    • 設問4(1):遠隔地の資産を回収したとき、システム上照合されていた資産が見つからないこと
    • 設問4(2):(忘れました)
  • 問4
    • 設問1(1):対象のディスプレイ端末、データ保持の有無
    • 設問1(2):プレイリスト
    • 設問2(1):ネットワークの性能、ネットワークの切断
    • 設問2(2):NTPサーバと通信し、各端末の時刻を調整する機能
    • 設問2(3):ディスプレイ端末のバックライトの調節機能
    • 設問3(1):HDDの数およびプロセッサの数
    • 設問3(2):サーバ全体としてデータ伝送性能が向上すること
    • 設問4(1):タッチパネル
    • 設問4(2):転送量が少ないことによる転送時間の短縮
午後IIで書いた解答の骨子 (自分のメモ+一部補完)
  • システム:ロボット制御機器の分散システム制御部。障害検知・フェイルオーバー機能・自己状態最適化機能を備える。
  • イ:ハードウェアとソフトウェアのトレードオフの検討項目
    • 障害検知機能:自社保有技術 (自社保有技術を流用)
    • フェイルオーバ機能: 性能 (完了時間)
      ⇒ハードでもソフトでも可だったので、プロトタイプを作成し評価することにした。
    • 自己状態最適化機能:再利用性(アルゴリズムを置き換えやすくしたい)
    • 全体として: 開発スケジュール、開発・製造コスト
  • ウ:機能分担の内容と評価
    • ハード: 障害検知機能とフェイルオーバ機能
    • ソフト:自己状態最適化機能とした。
    • フェイルオーバ機能はプロトタイプを作成し評価した結果、ソフトウェアでは1msオーダーでの性能が出せなかった。スケジュールは伸び、製造コストはかさんだが、依頼元とPMと相談し合意を得た。
    • 評価:(忘れましたが、「開発コストが○○ほどかかったが、性能を出せた」などと書いたように思います)

※上記リンクは、2011年度版です。

[パズル] 99人の囚人

「99人の囚人」という論理パズルについて、問題と解答を書きます。

この問題は、職場の先輩のブログ: にゃんたこす!徒然草。99人の囚人 問題編(数学パズル)という記事に載っていたものです。面白い問題と思ったので、自分のブログにも転載させて頂きます。解答は私が書いたのですが、結構ややこしいものになってしまいました。エレガントな解答を思いついた方がいらっしゃいましたら、ぜひコメントにて指摘頂ければと思います。


ではまず問題から。(前述のブログから引用)

問題

99人の囚人がいます。彼らの頭に1~100までのナンバーカードが貼りつけられた帽子をランダムにかぶせます。
他人の帽子は見ることができても、自分の帽子は見ることができません。
帽子の数は全部で100なので、一つ使われずに余ります。
そのナンバーは囚人達にはわからないようにしておきます。
この状況で、囚人たちに一斉に自分のナンバーを宣言させて、全員が正解だったら釈放するという賭けをします。
囚人たちには帽子をかぶせられる前に相談タイムが設けられています。
どういう戦略を取れば、助かる確率を最も高くできるでしょうか?

以下では、ヒントと答えを書きます。


ヒント

各囚人は、自分以外の98人の囚人のナンバーカードを見ることができます。ナンバーカードは全部で100個あるため、自分のナンバーは2通りある (すなわち、1〜100の数のうち、他の囚人98人が被っている98個の数 以外の2つの数) ことが分かります。その2通りの数のうち、1つは自分のナンバー、もうひとつは、使われなかったナンバーということになります。下の表では、各囚人にとってどの番号を見ることができるかを示します (未使用の番号を61としています)。

囚人1
の番号
囚人2
の番号
...囚人i-1
の番号
囚人i囚人i+1
の番号
...囚人99
の番号
未使用
の番号
見えない
囚人1にとって38...205914...796と61
囚人2にとって96...205914...738と61
:::...:::...:::
囚人iにとって9638...2014...759と61
:::...:::...::
:
囚人99にとって9638...205914...7と61


ヒントの1つめ
「見えない2つの数を元に必ず自分の番号を当てる方法」は存在し得ません。なぜなら、ある囚人にとって、「他の囚人が被っている帽子の番号の情報(98個の整数)」のみでは、2つの可能性を1つに絞ることができないからです。(※1)。
そこで、答えは、「あらかじめ2つの可能性を1つに絞るためのルールを決めておく」、より正確には「相談タイムにて『各囚人があるルールに基づいて2つの数のうちの一方を宣言する』と取り決め、各囚人はその通りに宣言する」となります。

ちなみに、各囚人が「見えない2つ数のうちの1つを適当に宣言する」とすれば、全員が釈放される可能性はほぼゼロ (1/2の100乗≒宝くじで1等を5連続で当てる確率) となります。

ヒントの2つめ
次の性質を持つルールが存在します: そのルールに基づいて各囚人が宣言した場合、1/2の確率で「全員が正しい数を宣言する」が、1/2の確率で「全員が間違った数を宣言する」。

※1 もし問題に条件を追加して、「他の人が被っている帽子を見た後、何らかの意思疎通を行って良い」とか、「宣言する際には一斉に行う必要はない」とかとするならば、100%の確率で脱出できる答えが出てきます。


答え

答えは「相談タイムにて『(囚人1の番号, 囚人2の番号, ..., 囚人99の番号, 未使用の番号) という順列が偶順列(※2)である』と山を掛ける。各囚人は、他の囚人の番号を見て、前述の順列が偶順列となるように自分の番号を決め、それを宣言する」です。
このようにすると、50%の確率で全員が解放されます。もし、山が当たった場合(すなわち前述の順列が偶順列であった場合)、全ての囚人は自分の番号を正しく定めることができるため、開放されます。一方、不幸にも前述の順列が奇順列であった場合は、全ての囚人が自分の番号を誤ります。

各囚人は、必ず一意に自分の番号を決めることができます。自分の番号となる数は2つあり、そのうち1つを選ぶと前述の順列が偶順列となり、もう1つを選ぶと奇順列となります。理由は、任意の2要素に対して、それらを交換した順列は奇偶が逆になる(※3)ためです。

# 順列の偶奇を使わずに解く方法を考えてみたのですが、思いつきませんでした。もし思いついた方がいらっしゃいましたらぜひ教えて下さい。


注:
  • ※2 異なる整数からなる順列 (a1, ..., ai, ...)があるとき、「その順列に対する転倒数」を、「ijかつ aiaj である組(i, j)の個数」と定めます。転倒数が偶数である順列を偶順列、奇数である順列を奇順列と定めます。
  • ※3 順列 (..., ai, ..., aj, ...) と、2要素 aiaj を入れ替えた順列 (..., aj, ..., ai, ...) の偶奇が逆になる理由について説明します。まず、順列の i<・<j 番目の部分で、aiよりも小さい要素の個数をm個、ajよりも大きい要素の個数をn個とします。すると、入れ替えることによって、以下の理由から、順列の転倒数の偶奇は反転します。
    • aiの位置がi番目からj番目に移ることにより、転倒数はm減り、(ji−1)−m増えます。
    • ajの位置がj番目からi番目に移ることにより、転倒数はn減り、(ji−1)−n増えます。
    • aiajについて、もしaiajならば転倒数は1増え、aiajならば転倒数は1減ります。
    • 上の3点を合わせると、転倒数は −m(ji−1)−mn(ji−1)−n±1=2(−mnji−1)±1 だけ増えることとなり、転倒数の偶奇が反転します。

Kinect ハック on Mac OS X:(3) デモプログラム glview

過去2回、OpenKinectについて書きました(第1回(サンプルの実行)第2回(APIの概要))。今回はデモプログラムであるglviewについて調べてみます。

ポイントは、(1)OpenKinectのAPIをどのように使っているか、(2)OpenGL(GLUT)をどのように使っているか の2点だと思います。今回の目次はこのようになります。
  • main関数の処理内容
  • 描画処理 (gl_threadfunc関数, DrawGLScene関数)の処理内容
  • カメラからの情報取得コールバック関数(depth_cb関数, rgb_cb関数)の処理内容
  • ユーザ入力を受ける関数 (keyPressed関数) の処理内容

main関数の処理内容

main関数の処理の流れは、次のようになっています。(各種APIは第2回(APIの概要)を参照して下さい)
  1. t_gamma配列(※)の事前計算  (※深度カメラからの情報を距離情報に直すときに利用)
  2. コンテキストの作成 (freenect_init関数)
  3. ログレベルの設定 (freenect_set_log_level関数)
  4. 利用するデバイスの決定 (freenect_set_log_level関数):
    プログラム起動時の引数が渡されていれば、その番号のデバイスを利用します。渡されていなければ0番(最初の)デバイスを利用します。もし利用可能なデバイスがなければ、終了します。
  5. デバイスのオープン (freenect_open_device関数)
  6. 種々の設定
    • 傾きの設定 (freenect_set_tilt_degs関数):
      初期設定では0度(==freenect_angle)
    • LEDの設定 (freenect_set_led関数):
      初期設定では赤(==LED_RED)
    • カメラの情報を受け取るコールバック関数の設定(freenect_set_depth_callback関数, freenect_set_rgb_callback関数):
      それぞれdepth_cb関数とrgb_cb関数を設定
    • カメラの情報を受け取る際のフォーマットの指定 (freenect_set_rgb_format関数, freenect_set_depth_format)
    • : それぞれRGB、11bitを指定
  7. 新規スレッドにてgl_threadfunc関数(後に説明)を実行
  8. カメラ情報取得開始 (freenect_start_depth関数, freenect_start_rgb関数)
  9. 正常に処理が行われている間、加速度情報をコンソールに表示 (freenect_get_raw_accel関数, freenect_get_mks_accel関数)
  10. カメラ情報取得終了 (freenect_stop_depth関数, freenect_stop_rgb関数)

描画処理 (gl_threadfunc関数, DrawGLScene関数)の処理内容

描画処理の初期化を行う関数が、gl_threadfunc関数です。main関数から呼ばれ、次の処理を行います。
  1. ウィンドウの作成
  2. 描画関数を設定(DrawGLScene関数)
  3. キー押し下げ時の処理関数の設定(keyPressed関数)
  4. 描画の開始。
gl_threadfunc関数で設定した描画関数(DrawGLScene関数)は、何度も実行され、カメラから取得した情報をOpenGLのウィンドウに表示します。カメラから取得できる深度とRGBはともに、幅640×高さ480の形になっています。その情報は、gl_depth_back配列, gl_rgb_back配列に入っており(カメラからの情報取得用のコールバック(depth_cb関数, rgb_cb関数)で設定されます)、その情報を一旦コピーしてから(gl_depth_front配列, gl_rgb_back配列)、ウィンドウに表示します (※)。深度情報はウィンドウ左側0<x<640の領域に、RGB情報はウィンドウ右側の640<x<1280の領域に描画されます。

※ このようにback(カメラからの取得用)、front(描画用)の2つの分けている理由は、処理速度を上げるため。もし一つの配列を使ってデータをやりとりすると、カメラから情報を取得できても、描画が完全に終わるまでは取得した情報を書き込めず、パフォーマンスが低下します。

カメラからの情報取得コールバック関数(depth_cb関数, rgb_cb関数)の処理内容

カメラからの取得できる情報には、深度情報とRGB情報があります。それらはOpenKinectから定期的に呼ばれるコールバック関数で受け取ることができます。

まず、RGB情報について(rgb_cb関数)は、引数として渡された領域(変数rgb)を、gl_rgb_back配列にそのままコピー(memcpy)しています。(前述の通り、書きこまれたgl_rgb_back配列の情報は、描画処理(DrawGLScene関数)内でgl_rgb_front配列にコピーされた上で描画されます)

次に、深度情報について(depth_cb関数)ですが、RGB情報と比べて処理が多少複雑です。というのは、RGBの場合はそのまま表示すれば良かったのですが、深度情報の場合は、(1)深度情報を距離に直す (2)視覚化するために深度情報を色情報に変換(※)する ためです。処理内容は次の通りです。
(※ カメラから近い順に、白→赤→黄→緑→水色→青→黒 と段階的に変化するようにします)
  1. ピクセルの数(FREENECT_FRAME_PIX == 640×480)だけループし、それぞれについて次の処理を行います。
    1. ピクセルの深度の値(depth[i])を距離に補正し、変数pvalに格納します。(main関数であらかじめ計算しておいたt_gamma配列を利用します)
    2. 補正した値pvalを、下位8ビットと上位のビットに分離します。下位の値(0〜255)は変数lbに格納します。
    3. 上位のビットの値に応じて、色分けをします。
      • 上位ビット値=0 (0〜255)の場合:下位ビットの値に応じて白(pval=0)→赤(pval=255)に段階的に変化
      • 上位ビット値=1 (256〜511)の場合:同様に赤(pval=256)→黄(pval=511) に段階的に変化
      • 上位ビット値=2 の場合:黄→緑 に段階的に変化
      • 上位ビット値=3 の場合:緑→水色 に段階的に変化
      • 上位ビット値=4 の場合:水色→青 に段階的に変化
      • 上位ビット値=5 の場合:青→黒 に段階的に変化
      • 上位ビット値>5 の場合:黒(一色)

ユーザ入力を受ける関数 (keyPressed関数) の処理内容

この関数は、OpenGLに登録され、表示しているウィンドウ上でキー入力があった場合に実行されます。
  • 'w', 's', 'x'が押された場合、Kinectの傾きをそれぞれ1度上昇、水平、1度下降とします (関数の最後で、freenect_set_tilt_degs関数を呼び出します)。
  • '0'〜'6'が押された場合、数字の値に応じてLEDを点滅させます。0:無灯、1:緑、2:赤、3:黄(※)、4:黄点滅(※)、5:緑点滅、6:赤と黄(※)を交互に点滅。(※:黄色は、実際のところは橙色のようです)


今回は、前回調べたAPIをもとに、サンプルプログラムの挙動を把握しました。次回は、深度情報と色情報をもとに、データを立体的に表示するプログラムを作ってみたいと思います。

Kinect ハック on Mac OS X:(2) OpenKinect APIの概要

前回(OpenKinect サンプルの実行)に引き続き、今回もOpenKinectについて書いてみます。今回は、現時点で公開されている OpenKinect (正確にはOpenKinectのCモジュール(?)) のAPIについて調べてみました。以下、目次です。
  • モジュール構成
  • core.c (コア部分)
  • camera.c (カメラ情報取得)
  • tilt.c (傾斜制御・LED制御・加速度センサ情報)
なお、ここで書くAPIは、随時変わる可能性があると思います。

モジュール構成

3つのモジュール(コア部分、カメラ情報取得、傾斜制御・LED制御・加速度センサ情報)から構成されています。
  • core.c:OpenKinectのコア部分のモジュール
  • camera.c:Kinectのカメラ情報を取得するモジュール
  • tilt.c:Kinectの傾き制御、KinectのLED制御、Kinectの加速度センサに関するモジュール

core.c (コア部分)

Kinectのベースとなる関数が含まれます。実際の処理の流れは次のようになると思います:コンテキストの作成(freenect_init)→デバイスのオープン(freenect_open_device)→処理→デバイスのクローズ(freenect_close_device)→コンテキストの破棄(freenect_shutdown)。また、ログ関連の関数や、ユーザ情報を構造体に設定/取得する関数等も含まれます。
  • コンテキストの作成 (コンテキストを作成し、指定されたアドレスへポインタを設定する):
    int freenect_init(freenect_context **ctx, freenect_usb_context *usb_ctx);
  • コンテキストの破棄 (指定されたコンテキストを破棄する):
    int freenect_shutdown(freenect_context *ctx);
  • ログレベルの設定 (指定されたコンテキストのログレベルを設定する。※後注1):
    void freenect_set_log_level(freenect_context *ctx, freenect_loglevel level);
  • ログ出力関数の設定 (指定されたコンテキストにログ出力を行う関数を設定する。※後注2):
    void freenect_set_log_callback(freenect_context *ctx, freenect_log_cb cb);
  • イベント処理の実行 (指定されたコンテキストに溜まっているイベントを処理する):
    int freenect_process_events(freenect_context *ctx);
  • コンテキストに含まれるデバイス数の取得
    int freenect_num_devices(freenect_context *ctx);
  • デバイスのオープン
    int freenect_open_device(freenect_context *ctx, freenect_device **dev, int index);
  • デバイスのクローズ
    int freenect_close_device(freenect_device *dev);
  • ユーザーデータのポインタの設定と取得
    void freenect_set_user(freenect_device *dev, void *user);
    void *freenect_get_user(freenect_device *dev);
  • ログの出力
    void fn_log(freenect_context *ctx, freenect_loglevel level, const char *fmt, ...)

camera.c (カメラ情報取得)

Kinectから取得できるカメラ情報には、RGB情報と深度情報があります。それぞれの情報は、あらかじめ指定したコールバック関数に、定期的に渡されます。
  • コールバック関数の登録 (カメラからの情報を処理するコールバック関数の登録):
    void freenect_set_{depth,rgb}_callback(freenect_device *dev, freenect_{depth,rgb}_cb cb);
  • 取得する情報のフォーマットの設定(後注3):
    int freenect_set_{depth,rgb}_format(freenect_device *dev, freenect_{depth,rgb}_format fmt);
  • 情報取得の開始
    int freenect_start_{depth,rgb}(freenect_device *dev);
  • 情報取得の停止
    int freenect_stop_{depth,rgb}(freenect_device *dev);

tilt.c (傾斜制御・LED制御・加速度センサ情報)

Kinectは、傾斜を変えたり(±15度)、LEDを点灯(後注4)させることができます。また加速度センサがあります。角度を指定する時には、目的の角度を2倍して(+31〜-31度)指定します。
  • 傾斜 (指定された角度にKinectを傾けます):
    int freenect_set_tilt_degs(freenect_device *dev, double angle);
  • LEDの点灯 (指定された方法(後注4)でLEDを光らせます):
    int freenect_set_led(freenect_device *dev, freenect_led_options option);
  • 加速度情報の取得 (Kinect内蔵の素子の加速度情報を取得します):
    int freenect_get_raw_accel(freenect_device *dev, int16_t* x, int16_t* y, int16_t* z);
  • 加速度情報(補正)の取得 (加速度情報をMKS単位系に単位換算して取得します):
    int freenect_get_mks_accel(freenect_device *dev, double* x, double* y, double* z);

補足

  1. ログレベルはlibfreenect.h参照
  2. ログコールバックを設定しない場合は、ログは標準エラー出力に出力される。
  3. RGB情報のフォーマットは、RGBとベイヤ型配列の2種類。深度情報のフォーマットは、11bit, 10bit, packed-11bit, packed-10bit の4種類。(libfreenect.h参照)
  4. LEDの光らせ方は、LED_GREEN, LED_RED, LED_YELLOW, LED_BLINK_YELLOW, LED_BLINK_GREEN, LED_BLINK_RED_YELLOW の6種類。(libfreenect.h参照)


次回は、デモプログラム(glview.c)とOpenGLについて調べてみようと思います。

Kinect ハック on Mac OS X:(1) OpenKinect サンプルの実行

Kinectとは、11月に発売された、MicrosoftのXbox 360用のデバイス。カメラの他に深度センサーやマイクが付いており、プレイヤーはコントローラを持たずにゲームを操作できます。今までのゲームコントローラとは異なる、最先端のデバイスです。
KinectはXbox用のコントローラなのですが、既にいくつかの機能がハックされ、Windows, Linux, Mac OS X用のドライバが出されています(OpenKinect Project)。こんなデバイスが簡単に使えるようになっているのであれば、色々と試してみる価値はありそうです(※ちなみに価格も11,693円(Amazon)と安価)。
そこで、このOpenKinectを使って、Kinectを使ったプログラムを作ってみようと思います。このブログでは覚え書きをまとめておきます。

目次

  • 環境
  • 事前準備
  • OpenKinectのビルド
  • サンプルプログラムの実行


環境

  • iMac (Early 2006)
  • Mac OS X 10.6.5
  • Xcode 3.2.4

事前準備

  • Xcode(開発環境):
    インストールされていなければ、 Mac OS Xのインストールディスクを挿入し、Optional Install→XcodeToolsと辿り、XcodeTools.mpkgをダブルクリックします。
  • gitとcmake:
    インストールされていなければ、下記のように、MacPortをインストールした後で、git-coreとcmakeをインストールします。
    • http://www.macports.org/install.php からインストーラをダウンロードし、実行
    • ターミナルから、sudo port install git-core を実行
    • ターミナルから、sudo port install cmake を実行

OpenKinectのビルド

基本的にhttp://openkinect.org/wiki/Getting_Started#OS_Xに従って行います。
  1. OpenKinectとlibusbをダウンロード:
    • git clone https://github.com/OpenKinect/libfreenect.git
      git clone git://git.libusb.org/libusb.gi
  2. libusbにパッチを当てた上でインストール:
    • cd libusb
      ./autogen.sh
      patch -p1 < ../libfreenect/platform/osx/libusb-osx-kinect.diff
      ./configure
      make
      sudo make install
  3. OpenKinectをconfigure:
    • まずはccmake (※Xcodeを使いたいため最後のccmakeには "-G Xcode"を渡す):
      • cd ../libfreenect/
        cd c
        mkdir build
        cd build
        ccmake -G Xcode ..
    • 画面に "Required library USB NOT FOUND."と表示されます。キーボードで'e'を押して、編集モードに入ります。
    • カーソルを下に動かし、"USB_INCLUDE_DIR-NOTFOUND" の行に合わせます。
    • Enterを押し、"/usr/local/include/libusb-1.0/"を入力し、再度Enterを押します。
    • キーボードから、'c'を2回押してconfigureを2度実行し、その後'g'を押して設定ファイルを生成します。
    • 最後に cmake:
      • cmake -G Xcode ..
    • "Build files have been written to: (略)"と表示されていれば成功
  4. Xcodeから、buildディレクトリにあるlibfreenect.xcodeprojを開く。
  5. "Build and Run" アイコンをクリックする。 ("Build Succeeded" と表示されていれば成功。逆にErrorと表示されていれば失敗(後注))

サンプルプログラムの実行

  1. ターミナル上からglviewを実行 (もしくはXcode上でglviewをダブルクリック):
    • cd examples/Debug/
      ./glview
  2. 次のように表示されていれば成功:
    • Kinect camera test
      Number of devices found: 0
実はまだKinectが届いていないのですが、プログラム上では問題なさそうなので、後はKinectが届いてからUSBに接続すれば動くはず...です。
次はサンプルプログラムのソースコードを読んで、Kinectからのデータ取得方法を調べてみます。

注: 自分の環境では、最初に実行したときに、エラーが出てビルドできませんでした。そこで以下の方法で暫定的に回避しました。(ビルド時のライブラリへのパスを指定する方法が分からなかったので...汚い方法です)
  • エラーの内容:
    ld: library not found for -lJPEG
    collect2: ld returned 1 exit status
    Command /Developer/usr/bin/gcc-4.2 failed with exit code 1
  • 回避方法:
    • MacPortでjpegライブラリをインストール:
      • sudo port install jpeg +universal
    • /opt/local/lib/libjpeg.* を libfreenect/c/build/lib にコピー。

Simutrans: オープンソースの交通機関シミュレーションゲーム

とあるゲームにはまってしまいました。Simutrans という交通機関シミュレーションゲーム(※)。主にバス、トラック、鉄道、船舶、航空機などの交通機関を作っていき、街を作り上げていくゲームです。説明はWikipediaから引用すると、
プレイヤーはゲーム開始時にマップを作成し、町や工場の需要に応じた各種交通機関を建設して、旅客や貨物を輸送し、利益を得ていく。MicroProseより発売されたトランスポートタイクーンに似ている。マップ作成時には起伏や街の数などの様々な設定を変更できるため、自分好みのマップを作成することができる。
ゲーム内で使用できる交通機関には、鉄道、路面電車、モノレール、リニアモーターカー、新交通システム、自動車、船舶、飛行機がある。旅客、貨物、郵便を輸送することができ、その収入によって利益を得ることができる。ただ、闇雲に建設していけばよいわけではなく、黒字となるように建設、運営していかなければならない。赤字が3ヶ月以上続くと破産してしまう。
※ Simutrans: http://www.simutrans.com/ , Simutrans Japan (Simutrans 日本語化/解説ページ): http://japanese.simutrans.com/

このゲームの良いところを自分なりに挙げてみると、3つあります。まず一つめは、多言語化されていること。日本語をはじめ15ヶ国語でプレイできます。ローカライズされているものはメニューだけではなく、プレイデータもその国のものになっています。例えば日本語化すると、建物や乗り物が日本のものになっていて(車も左側通行)、さらに産業には米が追加されています。

次はカスタマイズ性。アドインを入れるという形で、ゲーム中のあらゆるものをカスタマイズできます。独自の車両を作って走らせることや独自の建物を追加するのはもちろん、産業を追加することもできるそうです。日本語化ページには、たくさんの日本の電車用のアドインがありました。また、本家ページには、風景や建物を、ペンシル画風にするものや漫画風にするものがあり、さらには火星のようにするものもありました (ただし火星のはまだ公開されていないようです)。

最後は、AI(人工知能)が装備されていること。自分だけが街を作るのではなく最大12のAIのプレーヤーと一緒に街を作っていくことができます。

一方、欠点としては、まだ発展途上で、インストーラやマニュアルが不完全だったりします。自分も最初に何をしてよいかは分からず、日本語サイトや本家サイトを見ながらやっていました。ゲームの全体像を理解するのに少し一苦労、そして例えば電車を走らせるにしても多くの手順を踏まなければならず、また路線が完成したと思っても電車が動いてくれなかったり...。とりあえずは「まずは動かしてみよう」というページと、各交通機関の扱い方のページがあると、もっとユーザが増えるのではと思います。

最後に、自分の今の楽しみ方は、AIが街を発展させていくのを眺めること (上記の「まずは動かしてみよう」に該当するかも)。まずは初期マップをランダムに作り、その後、AIをオンに設定し、そして早送りすると、AIがどんどん街を作っていきます。発展するものもあればそうでないものもあり、見ていて飽きません。ある程度になったら、混んでいる道路を舗装して混雑を緩和したり、街を追加したり... とするとより発展するかも。

『社会言語学入門—生きた言葉のおもしろさに迫る』

社会言語学とは言語学の一種で、言語を、社会との関わりという視点から捉える学問です。その触りの部分を紹介する本、『社会言語学入門』(東照二著) を読みました。本書では、さまざまな例を示しながら、社会言語学の全体像を解説しています。

本書では世界の様々な言語について述べられていています (主に英語と日本語が中心ですが)。
以下、私が興味深く感じた内容について述べます。

diglossia (二言語使い分け)
diglossiaとは、言葉が使われるシチュエーションによって異なる言語が使われている状態のことです。例えばアラビア圏では、教会や学校では古典アラビア語が使われ、日常生活ではモロッコアラビア語が使われています。
diglossiaに現れる二言語には主に、高い言葉と低い言葉に分けられます。高い言葉は、公的な場所で使われ、低い言葉は、日常的な用途で使われるのだそう。

ここからは私の所感ですが、日本語はdiglossiaではありませんが、公的な言葉と日常的な言葉では、用語や文法が若干異なると思うので、これも広い意味でのdiglossiaになるのかなと思います。(例えば、くだけた表現(例えば「〜してる」「食べれる」「あたし」「〜じゃねーか」)は公式な場では使われないと思います。)

コードスイッチング
コードスイッチングとは、談話中に複数言語が入り交じること。最も簡単な例では「I was とても驚いた」とか。

アメリカのあるラジオ局の放送では、英語とスペイン語が適度にコードスイッチされているそうです。
# 聞いてみたい

また、私が最近会ったフランス出身の友人から聞いた話。彼は、スペイン語は会話できるが、ポルトガル語は聞けるが話せないとのこと。だから、彼はスペイン語だけを話し、彼の友人はポルトガル語だけを話すという状態で、会話が成立するのだと言っていました (しかもこれはよくあるシチュエーションだそう)。

意識と発音の相関性
アメリカのMassachusetts州にある、Martha's Vinyard島での話。ここでは、母音/ai/の発音が、/ai/と/əi/の二種類で発音(※)されており、しかもそれが、島のアイデンティティとの相関があるそうです。島を愛して島に残りたい人は/əi/と発音し、そうでない人は英語の標準的と同じ[ai]と発音する傾向が見られたそうです。(※例えば、likeを発音すると、[laik](ライク)、[ləik](レイク)となります。)

そういえば以前、「イラク」"Iraq" の発音が、話者の政治ポリシーによって変わるという調査結果を見つけました。第二音節を、民主的な立場の人は/ah/と発音し、共和的な立場の人は/æ/と発音するそうです。(http://www.slideshare.net/dialect/the-pronunciation-of-iraq)

# ちょっとした疑問ですが、日本語でもこういった、立場によって発音が変わる例はあるか知りたいです。

社会的ステータスと文法の誤りの相関性
英語では、より社会的なステータスが高い人ほど、文法的に正しいと認識されている用法(※)を使う傾向が顕著に見られるそうです。(※ rの発音を落とさない、"the"を省略しないなど)

文法と親和度との相関
話者同士で同じ文法を使うと、話者同士の親和度も高まってくるのだそうです。特に親和度の高い会話では、文法ミス発生率も似てくるのだとか。
しかも、精神療法ではカウンセリング時に、相手と文法を合わせるように気をつけるのだそうです。


[雑記] 2010年の目標

明けましておめでとうございます/寒中お見舞い申し上げます。
皆様が、幸せな1年、そして素晴らしい new decade を過ごせますように。

***
新しい1年の始まりとして目標設定をします。この目標は、年末に旧年を振り返りつつマインドマップに描いたものです。今日は気の置けない友人にちょっとだけ話したのですが、まぁせっかく書いたのだからブログに公開しても良いかと思ったので、載せることにしました。ただし量が多いので抜粋。そして要望があればマインドマップもお見せします。

目標の重点項目としては、
・無駄な時間を作らないようにする。
・常に人のことを意識する。
・文章力を鍛える。→日記を書く、ブログを適度に更新する。
・キャリアについては常に考える。

これらを設定するに至ったきっかけはたくさんありますが、一言で表せば、自分に足りていなくて、かつ今身につけたいもの。


続いて、専門分野(IT)では、
・システムアーキテクトとプロジェクトマネージャを取得する。
・システム設計やプログラミング技術を、定期的に学習する。
・Webサービスを作成する。
そして語学(英語)では、
・単語と親しくなる。
・Time, New York Times, TechCrunchを読み続ける。
・英会話レッスンを受ける。
・会を開く。
また非専門分野では、
・言語学、感性、集合知、言語処理、経営、会計 について少しずつ学習

といったところ。

設定後に見返したときの反省点として、マインドマップにはもう少し具体的に描かれてはいるものの、抽象的というか、アクションが不明瞭だったり達成成果が見えづらいものがほとんどということです。次にレビューするのは4月の予定で、その時にはそれを意識するようにします。

***
さて、別の視点、というかより上位の視点から目標を立てるとすれば、自分を認識することだと思います。具体的には、上でやったような自己分析をして自分を観察しつつ、また外からの情報も取り入れて、自分をより認識することだと思っています。

自分のことはまだまだ把握できていないように感じます。上のように目標を書いてみたものの、自分としては、本当に望んでいるものと比べて抜けやズレがたくさんあるように感じます。自分自身で納得できる目標が書けてないということは、自分のビジョンが不完全だったり、自己のことを十分に理解していないということだと思います (まぁ自分が納得できるレベルが高いせいも若干はあるかもしれませんが)。

また、自分を把握するには、こうやって自己分析をするだけではなく、人に会ったり本を読んだりと外の空気に触れて自分のことを相対的に把握することも大事だと思います。

ということで、目標である「自己を把握すること」が達成できたならば、2011年の元旦に自分らしい目標設定ができていると言えると思うので、こちらも頑張りたいと思います。

***
最後に、今年も、どうぞ宜しくお願い致します。