2014年11月25日火曜日

C++のodr-useについてのメモ


  • 『定義』とは宣言である。 
  • odr-useされるオブジェクトや関数は『定義』されている必要がある。 
  • クラス定義内の静的メンバ変数の宣言は『定義』ではない。
  •  クラスの静的メンバ変数を『定義』するにはクラス定義外に『定義』する必要がある。 
  • odr-useされているかされていないかの厳密な定義はクソ複雑。
  •  ゆるふわな定義としては、オブジェクトはアドレスが取られる場合、もしくは参照される場合、関数はそれが呼び出される場合、もしくはアドレスが取られる場合にodr-useされる。

2014年10月2日木曜日

OpenGLの隠面処理でひっかかったところ

perspectiveのnear引数は正の値でなくてはならない(0は不可)。

☓ glm::mat4 projection_matrix = glm::perspective(20.0f, 4.0f/3.0f, 0.0f, 1000.0f)

○ glm::mat4 projection_matrix = glm::perspective(20.0f, 4.0f/3.0f, 0.1f, 1000.0f)

2014年6月13日金曜日

約1万円で自作できるOculusRiftライクなHMD「DuctBox」

きっかけ

OculusRiftは良い。しかし値段が高すぎる。そして、不自由だ。耐え難いほどに。

もっと安い部品と、自らの労働でほぼ同等なものが安く、より自由なハードウェアとして作ることができるはずだ。

そうしてできるHMDはOculusRiftではない。「DuctBox」と名づけた。

備考

以前の記事でOculusRiftライクなHMDを作ったが、今回作成するHMD「DuctBox」はその後継である。部品をより厳選し、費用を安く抑えながら、より作りやすく、より没入感が増すよう工夫を施した。

目的

安価に、かつ可能な限り難しい工程を経ずにOculusRift(DK1)相当の解像度と没入感があるHMD「DuctBox」を作成する。

ただしヘッドトラッカーは省く。一応考えてはいるのでそれがうまくいけば後日別記事で載せる予定である。

必要な部品

7インチで解像度1280x800のLCDディスプレイとそのコントロールボード:約7000円

電圧12Vで電流2A以上のACアダプター:約500円

直径5cm倍率5倍の虫眼鏡x2:約300円x2個=約600円

レンズは驚きのガラス製だ。柄の部分に謎のライトもついてくるが、明るすぎるからなるべく直視しないようにしよう。レンズを取り出した後はライトは捨ててしまって構わない。

A3サイズの黒いスチレンボード:約800円

近所のホームセンターでは200円だったので、多分にネットで買うより現実の店舗で買ったほうがはるかに安い。輸送費のせいか?

防塵ゴーグルゴムひも:約400円+約400円=約800円

もっと金を払っていいのなら、これらの代わりにスキーゴーグルをおすすめする。ゴムひもは百円均一ショップで売っている可能性がある。

500mlのコカ・コーラのペットボトルx2:約150円x2=約300円

そこらへんに捨ててあるものを拾ってくれば無料だ。別にコカ・コーラのものでなくてもよいが、滑らかなものが良い。

ダンボール:0円

Amazonの箱を使えばよい。なければちょっとコンビニまで行って店員に聞けば裏にあるやつを好きに持って行けと言ってくれるだろう。

必要な工具

A3サイズの厚紙の方眼紙、厚めの両面テープ、カッターナイフ、はさみ、ダクトテープ、のこぎり、油性ペン、ボールペン、コンパス、ステイプラー、細めの針金の切れはし

作成の手順

筐体部分の切り出し1

厚紙の方眼用紙から以下の寸法で台紙を切り出す。(写真では二枚切り出しているが、一枚で十分である)

穴については、コンパスで線を引く。

スチレンボードに台紙を置いて、台紙のヘリにそってボールペンで線を引く。板は二枚切り出すが、一枚には中の穴二つぶんについても丸く線を引いておく。

線に沿ってカッターナイフでスチレンボードを切り出す。

一枚は丸く引いた線に沿って穴も切り出す。

組み合わせるときに上手く組み合わさるようにスチレンボードの辺を斜めに切る。

その際、各辺から4.5mmくらいの位置にボールペンで線を引いておき、その線に沿って表面の黒い紙をカッターナイフで切っておく。こうしておくと、斜めに切るときに紙が引っかからなくなり、仕上がりが綺麗になる。

斜めに切るときは、机のヘリがちょうどスチレンボードの端と重なるようにしておけば、ボードの下面を切り過ぎることを防ぐことができる。

これで筐体の前面と背面部分が切り出せた。

レンズの取り出し

虫眼鏡のレンズの枠をのこぎりで溝が出来るように刃を入れる。レンズはガラス製で硬いので横から当てさえしていればレンズを傷つけることはないので安心して切ればよい。

溝ができれば、そこにマイナスドライバーを差し込んで捻る。そうすると枠が割れてレンズが取り出せる。(分かりにくいが、写真中の虫眼鏡の枠に溝が入っている)

レンズの枠の作成

コカ・コーラのペットボトルをラベルが貼ってある平らな部分の下側の境界に沿ってカッターナイフで両断する。

さらに、平らな部分が2cm程度残るようにハサミで切る。

レンズを口のあるほうに入れて、水平になるように調整する。(写真は平らな部分をまだ切っていないが、切っていたほうが入れやすい)

レンズの上のヘリに沿って外側から油性ペンで線を引く。ペンを当ててペットボトルを回転させるとやりやすい。(写真では上下のヘリで二本引いているが、上の一本だけでよい)

ペットボトルの口の部分をカッターナイフで切除する。この時、先ほど引いた線から1cm以上空けて切るようにする。

写真のように線まで5mm程度の間隔を空けて二本の切込みを入れてから、2回折る。

2回折る理由は、最終的に図の様に折った部分でレンズを固定するためである。

同様にさらに二箇所、最終的に三箇所が配置的に均等になるように(厳密に均等でなくてもよい)これを行う。

レンズを試しにはめ込む。かなりガッチリと固定されるはずである。どうしても入らない場合は切り込みを少し深くして再度折り込み、調節する。

レンズを外して、切込みを入れた方の枠を切って小さくし、切り込みで出来た尖った部分を切って丸くする。言葉だと分かりにくいが、写真のようにすればよい。(写真はレンズがはめ込んであるが、切るときは外したほうがやりやすい)

ヘリを小さく、角を丸くする。上の写真と見比べてほしい。

もう一度同じことを行って、同様なレンズの枠をもうひとつ、計二つ作る。分かりにくく難しそうに見える工程だが、分かればそこまで難しくない。

平らな部分の境界まで適当な間隔で複数の切り込みを入れて、写真のように切り出したスチレンボードの穴にはめ込む。(写真ではスチレンボードのヘリが斜めに切られていないが、本当はこの時点では切られている)

表はこのようになる。

そして、ダクトテープで貼り付ける。

ディスプレイ面の作成

ディスプレイの背面のコネクタ部分が露出するようにスチレンボードにカッターナイフで四角く穴を開ける。

その際、写真のようにコネクタを差し込む方向に大きめにスペースをあけておくことで、コードにかかる曲げ方向の負荷を減らすことができる。

厚い両面テープでディスプレイを貼り付ける。

ただし、ディスプレイの表示部はディスプレイ本体の真ん中には位置していないことに注意すること。ディスプレイ本体ではなく、ディスプレイの表示部がスチレンボードの中心に来るように貼り付ける必要がある。(図はディスプレイ本体とディスプレイ表示部の位置関係を誇張して描いたものである)

奥行きの調節

筐体の側面部のサイズを決定するために、立体的に調度良く見える位置を計測する。動画はこれを使った。

この奥行きは人によって異なる。複数人で計測したところ、5cmから8cmまで幅があった。側面部は完成した後でも交換できるので、とりあえずアバウトに測ってHMDを先に作ってしまうのも手であろう。

本当は後で簡単に変えられるような構造にするべきだ。一応考えてはいるので、今後の改善に期待されたい。

筐体部分の切り出し2

筐体部分の切り出し1で行ったように、今度は側面のスチレンボードを切り出す。サイズは(先ほど計測した奥行き)x 13cmと(先ほど計測した奥行き)x 18cmであり、それぞれ二つずつ切り出す。

辺を斜めにカットするのも忘れないこと。

ゴーグルの細工

防塵ゴーグルのシールドを取り除く

防塵ゴーグルの細いゴムバンドを外し、代わりに用意しておいた幅広のゴムバンドをステイプラ−でとめる。

組み立て

ダクトテープで筐体を組み立てる。

ディスプレイのコントロールボードは両面テープで貼り付ける。

写真のように防塵ゴーグルとHMD筐体に穴を空けて針金で両者を固定する。

後はお好みで外から光が入らないようにダンボールの切れ端で周囲を囲めば完成である。

まとめ

前回の問題点だった、「レンズと目との距離が離れすぎているために視野角が狭い」ことは、ペットボトルをうまく使うことで解決できた。

また、「埃が入り込んで画面に張り付く」問題も密閉することで解決した。「ダクトテープの臭いがひどい」問題もある程度は改善した。

「箱を作るのがめんどくさい問題」は方眼型紙を使って別個に箱の各面を切り出すことで、ある程度作成工程が簡単になったので解決できたと言えるだろう。

「直径5cmで倍率5倍のレンズがなかなか手に入らない」は依然として日本国内ではそうだが、ebayで買えば良いことが分かった。

ただし、「レンズ間の距離が人によって異なり、合わないことがある」問題の解決は諦めた。しかしながら、レンズの特性からか、今回の場合はそこまで問題ではないようだ。

既知の問題点とその解決案

丁度良い奥行きが人によって異なる

筐体の箱を二重にしてスライドして調節できるようにすれば良いが、その場合は固定の問題がある。

隣の画面が見えてしまう

そこまで気にならないが、隣の画面が部分的に見えて画像が端の方では二重に見える。レンズの内側部分を1cmほど覆うと解決するが、見た目が悪くなる。

一部の部品が特定の企業(コカ・コーラ社)に依存している

特定の企業に部品が依存しているのは良くない傾向である。レンズを固定するために丁度良いプラスチック、ないしはそれと似た一定の強度を持ちつつ加工しやすい素材で出来た円錐形のものが身近にあれば良いのだが。現時点で良い解決法は思いつかない。

ただ、3Dプリンタの普及がこの問題を解決する可能性がある。

謝辞

写真を撮ってくれただけでなく、斜めカットやコントロールボードとの接続についてアイデアをくれ、他にも様々な形で協力してくれた師匠と、手製のスコーンを差し入れてくれたY氏、計測についてシニカルに的確で有意義な指摘をくれたT氏、通り過がりで計測に参加してくれたI氏と見知らぬ人たち、その他の協力してくれた人、そしてこの記事を読んでくれたあなたに感謝する。

2014年5月2日金曜日

Arduinoでヘッドマウントディスプレイ用のヘッドトラッカーを作る

きっかけ

Furlan氏のOculusRiftライクなHMDを自作する記事を見て、真似して作ってみたはいいものの、ヘッドトラッカーだけ無い状態だった。 氏の記事ではHillcrest Freespace FSRK-USB-2 IMUを買えとあるが、どうやらもう売ってないみたいだし、そもそも売っていたとしても高すぎる。 そうして、自作することにした。

目的

安価な部品でヘッドトラッカーを作成する。このヘッドトラッカーはUSBでPCと接続し向きを変えることによってマウスカーソルを動かすことができるものである。HMDに設置し、マウスで視点が動かせるようなゲームなどで使用することを想定している。

必要な部品

  • Arduino UNO R3(もしくはUSBシリアル通信のチップがAtmega16u2であるような同等品)
  • Amazonで売ってるが、ebayの互換品のほうが安い。

    USBシリアル通信のチップの背面を見て、Atmega16u2と書いてあればOK。

  • MPU6050モジュール
  • Amazonebayで買える。

  • ブレッドボード
  • 小さいものでOK。とりあえずAmazonで買える。

  • ジャンパーコード
  • 5本必要。Amazonでやっぱり買える。

  • USBケーブル
  • 用意したArduinoと接続できるタイプのもの

  • 段ボール
  • Amazonの箱とかでOK

  • ガムテープ
  • ダクトテープやビニールテープでもOK

必要な工具など

  • ハンダこて
  • ハンダ
  • PC

作り方

Arduinoの開発環境を整える。公式サイトでダウンロードできる。

Arduinoに以下のスケッチを書き込む

github: okdshin/HeadTrackerSketch

dfu-programmerをPCにインストールする。ここでダウンロードできる。

ArduinoをPCにUSBケーブルで接続し、リセットピンをジャンパーコードで3秒くらいショートさせて、Atmega16u2をリセットする。リセットピンの位置はここのStep1に図が載っている。

darran氏のページからArduino-mouse-0.1.hexをダウンロードする。

Arduino-mouse-0.1.hexが存在するディレクトリで次のコマンドを打ち込む

sudo dfu-programmer atmega16u2 erase
sudo dfu-programmer atmega16u2 flash --debug 1 Arduino-mouse-0.1.hex
sudo dfu-programmer atmega16u2 reset

ArduinoとPCを切り離す

MPU6050モジュールをハンダ付けして組み立てる。

ArduinoとMPU6050モジュールをジャンパーコードとブレッドボードで接続する。

わかりやすいつなぎ方の図が載っているページ

完成である。

Arduinoを元に戻したり、スケッチを書き換えたい場合

ArduinoをPCにUSBケーブルで接続し、リセットピンをジャンパーコードで3秒くらいショートさせて、Atmega16u2をリセットする。

次のコマンドを打ち込む。ただしArduino-usbserial-uno.hexはarduino-1.0.5/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial直下にある。arduino-1.0.5の部分は適宜変えること。

sudo dfu-programmer atmega16u2 erase
sudo dfu-programmer atmega16u2 flash --debug 1 Arduino-usbserial-uno.hex
sudo dfu-programmer atmega16u2 reset

ちなみにArduino-usbserial-uno.hex自体はgithubでも中身が見られる。

ArduinoとPCを切り離す。

これでArduinoはスケッチを書き込める元の状態に戻る。

既知の問題

ゆっくり動かす分には大丈夫だが、ちょっとでも速く動かすと累積誤差がひどい。ソースコードを改善する必要がある。そのうちやる予定。というか誰かやってくれ。プルリク歓迎。

備考

マウスカーソルを動かす速度を変えたい場合はスケッチの800行目前後にある

float ratio = 10.0;
の値を変えてください。

参考にしたサイト

Gyroscopes and Accelerometers on a Chip

Turning your Arduino Uno R3 into an USB mouse

2014年4月6日日曜日

OculusRiftライクなHMDを自作する

20140617追記

この記事中で作ったHMDの後継機についての記事がここにあります。

これから作る人は上記事を参考にしたほうが良いです。

きっかけ

Boost.勉強会 #14 東京の懇親会でhecomi氏がOculusRiftをデモしていたのだけれど、その時僕は度肝を抜かれた。懇親会は中華料理屋で行われていて、赤い照明に中華風の装飾の狭い部屋の中にいたはずなのに、手渡されたOculusRiftをかぶるとそこは西洋風の建物の上空で、ジェットコースターのようにレールを走るトロッコの上に僕は突っ立っていた。トロッコが曲がろうとすると、反射的に体を傾けてしまう。落下するときには胃が確かに持ち上がる感覚がした。ソニーのHMZ-T1を持っているが、比べ物にならない自然な没入感があった。hecomi氏は他にもいくつかのデモを見せてくれたが、どれもHMDの新しい可能性を示唆するものだった。

早速、その時やっかいになっていた江添氏の住むシェアハウスに戻ると、僕はOculusRiftを注文した。注文してから、しかしそれでいいのだろうかと思った。江添氏曰く、製品版が近々出るらしいし(実際出たのは製品版ではなくDK2だったが)、そんな不自由なハードウェアを今慌てて買わなくてもいいのではないか(ちなみに、江添氏のOculusRiftを使ってみた感想が含まれる記事)。その通りだと思った。しかし可能ならば今すぐにOculusRiftが欲しい。どうしても欲しかった。

そうして、自作することにした。

幸い、調べると、ネット上には既に自作している人がいて、作り方も公開してくれていた。基本的には、Furlan氏の自作したやり方を参考にすることにした。(この記事はほとんどFurlan氏のやり方を日本語で解説するだけである)

目的

OculusRift(DK1、以下ORDK1と表記する)と同等なHMDを自作する。ただし、今回はヘッドトラッキングシステムは省く(別記事でヘッドトラッキングシステムの自作は載せる予定である)。

必要な材料

5.6インチで画素数は1280x800のTFT液晶ディスプレイとそのコントロールボード、倍率5倍で直径5cmのレンズが2つ、黒い発泡スチロール板、スキー用ゴーグル、黒いダクトテープ、ダンボールの切れ端が少々。

5.6インチのTFT液晶ディスプレイとそのコントロールボードについて

ebayでこれを購入した。ORD1は画素数1280x800で7インチのTFT液晶を使っているらしいが、Furlan氏にならって、画素数は同じだが5.6インチの液晶を使うことにした。ちなみに電源装置が付属していなかったのでAmazonでこれを購入した。

倍率5倍で直径5cmのレンズについて

これを用意するのが一番手間取った。探してもFurlan氏の紹介しているような安いものが日本ではなかなか見つからなかった。結局、品質は疑問("約"5倍ってどういうことだ?)だが、条件に合致して安かったこれを使うことにした。

黒い発泡スチロール板について

A3サイズのものを近所のホームセンターで購入した。Furlan氏は4mm厚のものを使っていたが、なかったので5mm厚のものにした。

スキー用ゴーグルについて

これを購入した。

黒いダクトテープについて

近所のホームセンターで購入した。僕は実際に使用してみるまで、「ダクトテープってガムテープとどう違うの?」という感じだったが、まったく違った。ダクトテープはあなたの想像を凌駕する。何かを強力に貼り付けたい? ダクトテープをどうぞ。何かを完璧に密閉したい? ダクトテープをどうぞ。貼りつけた後きれいに剥がして再度貼りたい? ダクトテープをどうぞ。局部を隠したい? ダクトテープをどうぞ。HMDを作りたい? ダクトテープをどうぞ。

ダンボールについて

Amazonの箱を使った。

必要な道具

カッターナイフ、はさみ、ニッパー、ノコギリ、鉄の定規、A3サイズ以上の方眼用紙、ペン、両面テープ、ガムテープ

作り方

まず、液晶ディスプレイがちゃんと動作するか確かめる。Furlan氏曰く

(略)...次に、LVDSケーブル(訳注:液晶ディスプレイとコントロールボードを繋ぐケーブル)がノイズに弱くないか確かめよう。ちゃんとしたLVDSケーブルはノイズの影響を軽減するために特定のコードのペア同士が撚り合わせられているのだけれど、ebayで売られているほとんどのLVDSケーブルはちゃんと撚り合わせられていないため、画像に変なものが交じる可能性がある。君の購入したLVDSケーブルがちゃんとしているかどうか確かめるには、幾つかの異なる画像を試しに映してみればよい。その時、映してみる画像が多ければ多いほどよい。なぜならば、変なものは特定の色を映した時に現れることがあるからだ。

もし何らかの変なものが映ったならば、それをほとんど、もしくは完璧に全て除去できるいい方法がある。必要なのはテープの切れ端と手伝ってくれる人間だ。まず、LVDSケーブルを優しく力を加え過ぎないように慎重に捻る。そして手伝ってくれる人に捻ったLVDSケーブルをテープで元に戻らないように固定するよう頼む。このトリックは私の場合はいつもうまくいっているんだよ!

僕の場合は、手伝ってくれる人間がいなかったので、ここは適当に省いた。特に気になるような変なものは映らなかったし、必要になった後でもできる。

レンズを用意する。虫眼鏡のレンズ部分を汚さないようにガムテープで覆い、柄をノコギリで切り落とす。本当は枠も外したかったが、レンズとの一体成型のようで外せなかった。直径5cmの中に枠が含まれているのはいかがなものか。レンズについては改めて考える必要がある。覆いのガムテープを剥がすとき、糊がレンズに残る場合があるが、別のガムテープを上から貼って剥がすとうまくとれる。

次に、箱を組み立てる。寸法は以下の通り。ただしレンズとレンズの間の距離は個人によって異なるので自分のものを計測したほうがよい。(僕は7cmだった)

方眼紙に寸法通りの線を引いて、発泡スチロール板に両面テープで貼り付けて、カッターナイフで切り出す。各折り目の部分に曲げるためのVカットを施す。カットが深かったり浅かったりして折り曲げた時割れても気にしなくてよい。何かを強力に貼り付けたい? ダクトテープをどうぞ。思う存分補強すればよい。辺の部分も折りあわせた時にうまく重なるように斜めに切り込みを入れておく。

レンズをはめ込むための穴をあける。試しにレンズをはめてみて、きちんとはまるまで少しずつ穴をカッターナイフで削って大きくしていくとうまくいく。

箱をとりあえず組み立ててみて、顔に当ててみる。鼻がぶつからないように切り込みを適当に入れる。

Vカットが表になるように発泡スチロール板を置き、レンズの"太ったほう"の面が同じく表を向くように穴にはめこむ。ダクトテープでレンズの端を固定する。

液晶ディスプレイにかからないように、ディスプレイの枠をダクトテープで発泡スチロール板に固定する。上下の向きに注意すること。枠が若干はみ出したのでニッパーでネジ止めの部分を切った。

液晶ディスプレイのコントロールボードを液晶ディスプレイの貼り付けられた面の裏にダクトテープを輪っかにして両面テープのようにしたもので仮固定する。

液晶ディスプレイとコントロールボードを繋ぐケーブル用の穴としての切り込みを適当に入れる。(写真は完成後だが、切り込みにケーブルを通しているのが分かる)

箱を組み立てる。ダクトテープをどうぞ。

ここで、Furlan氏曰く、

私はテープの切れ端で左のレンズの左側と、右のレンズの右側のそれぞれ1cmを覆ったが、君もそうすることをおすすめする...(略)...そうすることでディスプレイの端が視界に入らなくなり、より没入できるHMDになるはずだ。

そうらしいので、僕もそうした。(しかし7インチのディスプレイならばこうした問題は起きなかった可能性がある)

ここで一度、動作確認をする。適当にOculusRift用の映像を流しつつ、顔に当てて確かめる。

ゴーグルの板を外して組み立てた発泡スチロール箱にダクトテープで固定する。ゴーグルの枠は湾曲しているので隙間があくが、ダンボールの切れ端で上から覆って適当に塞ぎながら固定するとよい。

ダクトテープで液晶ディスプレイのコントロールボードを落ちないように固定する。

完成である。

サンプル動画

とりあえずYoutubeに落ちているOculusRift用の動画を見ると楽しい。

Oculus Rift Canyon Run

既知の問題点とその解決方法案

次回作る場合や、このページを見て自作する人に向けた改善したらいいと思う点。

レンズと目との距離が離れすぎているために視野角が狭い

単なる距離の問題である。ゴーグルを削るか、発泡スチロール箱を削って、ゴーグルの中にレンズを押し込めるようにすれば、レンズと目との距離が縮まり、改善するだろう。

レンズ間の距離が人によって異なり、合わないことがある

何らかの後からアジャストできる仕組みが必要である。スライドできるような感じにできればいいのだが。

ダクトテープの臭いがひどい

鼻をダクトテープで固めた箱に突っ込んでいるせいである。鼻あてを別に作って貼り付ければ改善する(はず)。

埃が入り込んで画面に張り付く

発泡スチロール箱を完全に密封するか、後で開けられるようにしておくことで対応できるだろう。

発泡スチロール板の値段が高い

今からしてみればダンボールで十分だったかもしれない。実際にググるとダンボールで作っているひともけっこういる。

箱を作るのがめんどくさい

タッパーで作ったらどうかと考えている。フタにディスプレイを貼り付けたら簡単に着脱できるし便利だ。

直径5cmで倍率5倍のレンズがなかなか手に入らない

倍率が低いレンズを複数枚重ねたり、倍率が低いレンズで箱の奥行きを大きくして対応したりすることが解決法として考えられる。

まとめ

けっこういきあたりばったりで作ったが、そこそこのクオリティのものができた。今後はもっと工程を省略して、材料も安く、どこでも手に入るようなもので作れるように、既知の問題点も含め改善していきたい。