ロボットと趣味と自堕落と

ロボットの事なんか一言も書いてない

$ rm -rf で/tmpを削除してしまった話

つい4時間程前の話。
ubuntuで色々作業していた時に、一時作業ディレクトリとして適当な所に

:../hoge/fuga$ mkdir tmp

という感じでtmpディレクトリを作った。

その後作業が終わり、tmpというディレクトリがいらなくなったのでディレクトリごと削除しようとして何も考えずにtab連打で

$ rm -rf /tmp/

なんて打ち込んでしまった。

まぁこの結果はご想像の通り、/boot /devとかの中にある/tmpというディレクトリを削除してしまうことになるわけです。f:id:i-hako:20141209035231p:plain

あまりLinuxについて詳しくは知らないのですが、/tmpは基本的にはその名前の通り一時的なデータを保存するディレクトリらしいです。*1
ところが、このディレクトリには色々な設定とかが書かれているため、/tmpディレクトリごと削除すると色々問題があるわけです。*2



さぁ困った。
とにかく落ち着こう。
こういう時はどうするんだ。そうだ。まずは再起動してみよう。*3

。。。。。再起動。。。。。
起動した…が、おかしい。ログイン画面が現れた。これは設定した覚えがないぞ。
とりあえずパスワード入れてログインを試みる。ログインできない。
ゲストアカウントもダメだ。さてコイツはまずいぞ…


…という感じですごく焦っていたのですが、色々考えてみた所ubuntuをインストールしたLiveCDを使って、LiveCDの/tmpを、起動しないUbuntuが入ったデバイスのルートディレクトリに突っ込めば直せそうだという結論に達した。
とても簡単な話だった。

  1. LiveCDからブートする
    LiveCDを入れてCDブートする
  2. Ubuntuを試すとかでお試し版を起動
    /tmpディレクトリを持ってくるため、お試し版を起動
  3. 起動しないUbuntuが入ったドライブをマウント

    $ sudo su
    ...
    # cd /
    # mount /dev/<device> /mnt/

    とかでマウント。root権限じゃないとマウントできないっぽい

  4. LiveCD側の/tmp以下を/mntにコピー
    LiveCD側のルートディレクトリに移動して以下のコマンドでコピー

    # cp -a /tmp/ /mnt

    "-a"はディレクトリの構造や設定を保ったままコピーしてくれるオプションらしい

  5. 再起動
    あとは再起動してみてちゃんと起動したら成功。
    起動後にエラーメッセージ出るかもしれませんが、ちゃんと詳細を確認して適切な対処をしてください。

こんなんでいいのかどうかわからないけど、とりあえずちゃんと起動できるようになりました。
問題あったらどうしようかな


というわけで、今回はこれだけ。忘れないようにメモ。

*1:再起動の度にデータが掃除されるとかなんとか…

*2:terminal新しく立ち上げたらなんか「hoge.sh XXXXXがありません」的な感じで怒られました

*3:コイツが一番まずかった

Oculus Rift DK1でのプレゼン接続方法について

どうもこんにちは。
11/29、30に東京の目黒で第三回Oculus GameJam in Japanに参加してきました。
僕はプログラム苦手マンなので、今回はまともにスクリプト書いておりませんが、なかなか良い感じのゲームが出来たのではないかと思います.
(成果物を参照出来る何かが無いので詳しいゲーム内容とかについてはとりあえず割愛)

そんなOcuJamもゲームジャムなので、要所要所で参加者に自分たちのチームが作っているゲームを紹介したり進捗報告したりする必要があります。
ところが、実際に各自が作ったゲームのプレイ画面を見せながらプレゼンしようとすると、何故かOculus側に表示がされなかったり、トラッキングが出来なかったりなどで上手く行かなかったチームが割りといた気がします。*1
そこで今回はこの上手く行かなかった表示に対して解決策になるかもしれないアイディアについて述べたいと思います。
参加チームのほとんどがDK2でのアプリ開発で、DK1を使ってるのは僕らだけだったので、正確な問題の切り分けや、DK1/DK2での原因の違いなどはハッキリとわかりませんが、とりあえずDK1ゲームをプレゼンする方法として自分なりの解決策を見つけたので、備忘録的に書いておきます。

目的と構成

目的

「Oculusゲームをリアルタイムでプレイしながらプレゼンしたい」
「プレイ画面をプロジェクタのスクリーンで見せたい」
などのため、unityでビルドされたゲームをOculusで表示しながら且つスクリーンなどの大型ディスプレイに表示する。

構成
  • PC: G-tune i990 (ノートPC)
  • OS: Windows8.1 with Update
  • GPU: GTX 870M
  • メモリ: 16GB
  • Unity version: 4.6
  • Oculus: Developer Kit 1

下図の様な接続構成をとって「PC画面を見ながら、プロジェクタでPCディスプレイの複製を表示し、Oculus DK1でもゲームをプレイする」という構成を取りたい。
f:id:i-hako:20141201031438p:plain

Fig.1 構成図
(接続ポートが上図のようになっているのは、今回この構成のみでしか検証していないため。)

問題点

Fig.1のように3画面出力で構成しようとすると、何故かOculusのRuntimeがDK1を認識しなくなり、DK1のヘッドトラッキング機能が使用出来なかった。*2
結局、PCディスプレイとプロジェクタにはミラーリングが反映されているが、Oculus側の入力が全く得られないという問題点が発生した。

解決策

結論

先に結論から述べると、Fig.1の様に3画面同時出力はどうやら無理っぽいです。
そこで、PCディスプレイの画面表示を諦めて、Fig.2の様にプロジェクタとDK1のみに画面表示(複製モード)すると良い。
f:id:i-hako:20141201032327p:plain

Fig.2 成功した構成図
このようにすると、プロジェクタでプレイ画面を表示しながら、Oculusも使う事ができた。

手順

では、Fig.2の様にする構成について説明する。

  1. まずは接続
    PCの各ポートにプロジェクタとOculusを接続し、DK1のUSBケーブルを接続する。(Oculusは電源入れ忘れないように!)
  2. プロジェクタへミラーリング
    デスクトップで右クリックすると「画面の解像度」という項目があるはずです。これを使ってPCの画面をプロジェクタへミラーリングしましょう。
    これは「windowsキー+P」でも出来たと思います。この状態ではOculusは恐らく何も表示されていない筈です。
  3. 表示する画面をプロジェクタとOculusに変更
    ここでノートPCとプロジェクタのミラーリングから、プロジェクタとOculusのミラーリングへ切り替えて、PCに画面表示が出来ない様にしましょう。
    「画面の解像度」の項目で「複数ディスプレイ」というのの中に、「デスクトップを2と3のみに表示」というものがあると思いますので、それを選択し、
    PCディスプレイに画面が表示されない様にします。これで漸くプロジェクタとOculusのみにデスクトップが表示されているはずです。
  4. Oculus Runtimeの確認
    ここで、一度Oculus Runtimeを起動し、DK1が認識されているかどうか確認して下さい。僕の環境では必ずと言っていいほど認識されていない状態になっていました。
    Oculus Runtimeで認識されていなかった場合、一度DK1のUSBケーブルを抜き差しし、Oculus Runtimeで認識される事を確認して下さい。
  5. いざゲーム起動
    ここまで来たらあとはプレイするゲームを起動するだけです。恐らくプロジェクタにPCでのプレイ画面が表示され、DK1側にもちゃんと表示されているはずです。
    この状態ならば、DK1からの入力などをちゃんと得ることができ、ヘッドトラッキングなども問題なく作動しました
(画像などがなく、ちょっと分かり辛いかと思われますので、後日補完します。)

まとめ

あまり問題の切り分けとか他のパターンの検証とかちゃんとやっていないので、多分他にもいろんな問題あると思いますし、根本的な解決方法では無い気もする。
(なにせDK2持ってないので試せなかったし、DK2は他にも色々障壁があるらしいのでDK2勢はこれで上手くいかなくてもご容赦願います><)*3
もしかすると、ディスプレイとか関係無しに、単純にRuntimeの問題だったりするかも…
あるいは、GPU側の問題で接続するポートが物理的にこういうことが出来ない様な接続になっているのかも…
…と、まぁこんな感じで「なんとなく試行錯誤したら上手くいった」程度の解決策なので、試してみて上手く行けば儲けモンぐらいの軽い気持ちで参考にしていただけると助かります。
(すでに他の方法も沢山あると思うけど、僕は知らないのでご存知の方いたらコメントで教えていただけるとすごく嬉しいです。)

なにはともあれ、とりあえずこれで表示は出来ると思うので、困っている方がいらしたら一度試してみてください。

*1:全員の共通点として、「Oculus + PCディスプレイ + プロジェクタ」の構成で3画面出力しようとして上手く表示されなかったという感じ。

*2:僕らの場合、ヘッドトラッキングが要だったのでこれは大問題だった

*3:どなたかDK2僕に買ってください!!!!!!!!!

Ocufes@ニコニコ町会議in須坂に参加した事について

去る2014/7/19にドワンゴが主催する「ニコニコ町会議」なるイベントが長野県須坂市で開催され、そのイベントと併催して行われたOcufesというイベントにて出品(?)してきました。

Ocufesとは

経緯を書く前にとりあえずOcufesの概要的な何かを。
Ocufesとは、Oculus VR社が開発した没入型ヘッドマウントディスプレイを利用したアプリケーションをデベロッパーが作り、来場者にアプリケーションを体験させる会みたいなものです。(これであってるのかしら?)


出品の経緯

開催の1ヶ月前頃に長野県内でOcufesが開催される事を@takashiskiさん経由で知り、僕もOculus Riftを持っている事やAR/VRなどに大変興味を抱いている事などが有り、@yuujiiさんのお手伝いと言うことで立候補しました。
最初は特に出品する予定も無くただの手伝いのつもりだったのですが、いつの間にか@takashiskiさんと一緒に出品することになってました(ちなみにこの時開催1週間前)


やったこと

ARマーカー*1を使って現実世界に仮想の武器を作り、それをOVRvision*2を経由してOculus Riftで見るという感じのことをしました。
f:id:i-hako:20140723021856j:plain

ARマーカー(ID:22)
このアイディア自体はありふれた内容なので,技術的な事は僕が下手な説明をするよりも他の何処かいいかんじの人が説明してるHPを観たほうがいいと思うので割愛します。

僕らがやったのは下図のように棒の4面にARマーカーを貼り付けて実際に棒を振ることで擬似的に武器を振るってるようにする事です。
f:id:i-hako:20140723032847p:plain

イメージ
4面にマーカーを貼り付けることで手に持ってる棒を回転させて複数の武器を出現させることができます。
f:id:i-hako:20140724033126j:plain
実際にOVRvisionでみた状態


技術的ななにか

どのようにして実現したかという事を書こうとおもうけど、基本的に既に用意されているサンプルを少し改変した程度なのであまりまともなことは書けません。
OVRvisionのUnitySDKのサンプルにあるunity_ar_exampleをそのまま使いました。
このサンプルではマーカー上に白いcubeを出現させるやつだったので、そのcubeを武器にすげ替えることで実現しました。
また、ARマーカーについては@hecomiさんのブログを参考にして生成しました。
あとは上述したように棒の4面に貼り付けるためにダンボールをカットし、適当な棒*3に貼り付けました。


当日の反応

雨天にも関わらずたくさんの人が来ていて十数人が体験していった感じでした。
なんにせよ完成度が低かった*4ので、体験者の反応は割と微妙な感じだった。*5
ただ、数人は「これすごい!対戦とかのゲーム性があるともっといいかも!」と言った反応だったので、ひとまずは良いのかなぁと。


反省とか

今回の出品を通してかなりの問題点があったので、箇条書きにしてみました。

  1. 構想が固まるのが遅すぎた
  2. 2人で作る際に相互のビジョンに相違があった
  3. 完成が当日になってしまった
  4. ボランティアスタッフの方に説明ができてなかった
  5. 展示の時にいい感じの演出ができなかった
  6. 地味にクオリティが低い

それぞれの反省について

  1. とりかかったのが前日で、原因はそれまでに作ってたやつ*6が全然怖くなさ気だったため。これは最初の構想の段階で使えるデバイスとSDK周りを正確に把握できてれば回避できた可能性が高い。次回は最初から構想を深める必要がある。
  2. 話し合い不足が原因だった。@takashiskiさんが当日車を運転する事になっていた*7ので、先に休んでもらって、その間に僕が作業&ブラッシュアップをする予定だったが、お互いがこのアプリに対して違う捉え方をしていた。*8
    おそらくアプリの完成度重視か、演出重視かの違いも関わってくるとは思うけれど、ゲームやこういう体験には完成度・演出の両要素とも重要なので、ビジョン確認と同時に優先順位も決める必要が有りそう。*9
  3. 当日会場についた段階でα版程度だった。これは僕がUnityに全然慣れていないのもあるが、お互いのビジョンのズレというのもある。
  4. これは割と問題だった。当日僕が常にPCにつきっきりで作り直したりしてたので、ボランティアで来てくれた方にまともに説明出来なかったため、彼が体験者にする説明には一部誤りがあった。*10
    彼を責めるつもりは毛頭無いが、これを解決するには1〜3の事項が解決してようが居なかろうが必ず開始前にはちゃんと説明をしておく必要がある。
  5. これは僕の悪い癖である。なんだかんだ技術的なことを説明してもあまり理解できないかもしれないと思い面倒な説明を省いてしまうのだ。この原因はおそらく今回のアプリを「技術的な物」としてしか捉えておらず、エンターテインメント性を排除して考えてしまっていたからだ。
    来場者はエンターテインメントを求めて来ているので、もう少し世界観とか相手の驚きとかを考慮すべきだった。
    事前に文言とかを決めといたほうがいいのかな?
  6. 完成品はただARマーカーの紹介のようなものになってしまい、ゲーム性やエンタメ性が全くなかった。*11できれば対人戦とかモンスターを倒すとかのゲーム性が有ったほうがよかったなーと思う。

反省する点が多かったが、まとめると

開発エンジンに慣れたうえでもっと早くからちゃんと話しあって動いておけば解決できたね

ということだ。*12


全体を通した感想

以前からニコニコ技術部やOculus勢に憧れており、僕の中では「技術部タグ」をつけて動画サイトに投稿することはひとつのステータスになっており、ニコニコ町(超)会議やOcufesというのはそんな事をやってる人たちの作品に実際に触れることができる場だ。
そんな場に破れかぶれでも参加できたことはこの上なく素晴らしい経験で、大変貴重な経験ができたと考えておる。
これを一過性の体験で終わらせるのはあまりにも勿体無いので、これをきっかけにどんどん次の物を作っていきたいと思う。
また、今回は様々な人に助けてもらってなんとか完成に漕ぎつけた*13が、次回こそは一人で一からやってみたい。
もちろんそのためには技術的に向上させなきゃいけない事項が大量にあるが、焦らずやっていこうと思う。
最後に、お世話になった@takashiskiさんと@yuujiiさんにお礼を述べて締めたいと思う。
ありがとうございました。

*1:マーカーが置かれた現実をカメラを経由することで拡張情報を提示することを可能にするもの

*2:しのびや.comさんが開発したOculus Riftに装着出来るステレオカメラ

*3:今回使用したのは以前100均で購入したペンライト

*4:α版というのもおこがましい程度だった

*5:「おぉー…いいですね!」ぐらい

*6:ホラー?系

*7:僕が免許を持っていないため

*8:正確に言うと僕は「ARマーカーで武器を持つことができる体験」と考えており、@takashiskiさんは「ボロボロのただの棒をHMDを通して見ることでファンタジーな武器に変わる体験」という感じで捉えていた

*9:完成度と演出どちらにステ振りするかってことで

*10:僕も会場で彼の説明を聞いた時に違和感が有ったが、ある意味イメージしやすい説明だったのでスルーしてしまったのも問題

*11:人によってはそれでも面白かったようだが。

*12:多方面から「それが出来ればこんな苦労しない!」と言われそう…

*13:主に@takashiskiさんの足を引っ張ってただけだが…

天気情報を取得する(Python weather API)

今研究で作ってるシステムで天気情報を取得する必要があったので忘備録的なあれで記事を書こうと思う.
天気取得の為のAPIは色々と調べてみたらいくつか使えそうなのがあった

僕はこの中で導入が簡単そうなpython weather apiを使用しているのでpython weather apiを使った天気情報取得について説明しようとおもう.
このAPIは本来なら

  • Google weather
  • Yahoo weather
  • NOAA

の3種類の天候取得APIから天気を取得する事ができる.
(現在はgoogle weatherが使えないのと,日本ではNOAAが利用できないのでYahoo weatherのみの利用が可能)


【利用環境】
OS:Ubuntu 12.04LTS
使用言語:python(v2.7)

導入

導入にはここ*1を参考にした.
パッケージが用意されているので,apt-getでインストールできる.

$ sudo apt-get install python-pywapi

使い方

まずはここに書いてあるサンプルを動かしてみる.

import  pywapi
import string

yahoo_result = pywapi.get_weather_from_yahoo('10001')

print "Yahoo says: It is " + string.lower(yahoo_result['condition']['text']) + " and " + yahoo_result['condition']['temp'] + "C now in New York.\n\n"

結果

Yahoo says: It is fog and 14C now in New York.

どうやら地域ID的なのがわかればその土地の天気情報を取得する事ができるようです.
そこで,先ほどのHPのサンプルを借りて使ってみました.

import  pywapi
import string

result = pywapi.get_weather_from_yahoo('JAXX0105')

print '---'
print result['title']
print 'city: ' + result['location']['city']
print 'date_time: ' + result['condition']['date']
print 'condition: ' + result['condition']['text']
print 'temp: ' + result['condition']['temp'] + '('+ result['units']['temperature'] + ')'
print 'geo(lat,long): ' + result['geo']['lat'] + ',' + result['geo']['long']
print '---'

出力結果

---
Yahoo! Weather - Nagano, JA
city: Nagano
date_time: Sun, 20 Jul 2014 2:59 pm JST
condition: Mostly Cloudy
temp: 28(C)
geo(lat,long): 36.67,138.2
---

いい感じで取れてる.

地域IDについて

さてここまで来て問題になるのが,地域IDをどうやって取得するかである.
上記のHPではYahoo! weatherのwebページに行ってページソースから日本の地域のIDであるJAXX----なる文字列を探していたようです.
僕は取得可能な地域の全国のIDを使える必要があるので,この方法だと割りと辛い.
そこで,とりあえず適当なスクリプトを書いてJAXX----に該当する地域IDをJAXX0000~JAXX9999まで自動取得してみました.

#coding: UTF-8
import pywapi
import string
fp = open("location_result.dat", "w")
fp.write("location ID   Name   Geodata(lat,long)\n")

for num in xrange(10000):
        tag_num = '{0:04}'.format(num+1)
        tag_name = "JAXX" + str(tag_num)
        try:
            result = pywapi.get_weather_from_yahoo(tag_name)
            fp.write(tag_name + " " + result['location']['city'] + " " + result['geo']['lat'] + "," + result['geo']['long'])
            fp.write("\n")
        except:
            fp.write(tag_name + " N/A" + " N/A,N/A")
            fp.write("\n")
fp.close()

(割りと雑なコードはご愛嬌)

これで取得した地域IDを見たところJAXX0148までしかIDが存在せず,それ以降のJAXX0149~JAXX9999には地域が設定されていませんでした*2
Wikipediによると2014年4月5日の時点で市が790,特別区が23,町が745,村が183の合計1,741の地域が存在するとのことなので,IDの数と比較すると取得可能地域の粒度としては少し大きすぎるので,ちょっと粗い範囲での地域天気情報の取得になるのかなーとおもいます.

まとめ

割りと簡単にインストールできるし,純粋なpythonのみのAPIで使い方も楽なので地域情報をとりあえず取得したいというぐらいなら問題なく使えると思います.

*1:2014/07/20現在記事にアクセスできなくなっているようです2014/07/22接続可能であることを確認しました

*2:取得データのリストはこちらでDL可能

Ubuntu12.04アンインストール(windows7とデュアルブート)

なにを今更という内容ですが、さらっとググった結果、まとめて書かれてるエントリがなかった気がするので、防備録的に書いておくことにします。


【状況】
windows7とUbuntu12.04デュアルブート済みPCからUbuntuのみをアンインストールする


【手順】
1.WindowsMbr*1を修復
2.Ubuntuアンインストール

1.WindowsMbrを修復する

既にWindows7がインストールされてるPCにUbuntu12.04をインストールして、特に何も設定していなければ、起動時にGNU GRUBというOS選択画面が出ると思います。(下図参照*2
なお、GRUBについてはあまり詳しく知らないので、勉強中
f:id:i-hako:20140625021204j:plain

ここでwindows7をリカバリーモードで起動*3*4し、「システム回復オプション」からコマンドプロンプトを立ち上げましょう。
f:id:i-hako:20140625022650j:plain

コマンドプロンプトで下のコマンドを入力すると、次回起動時にgnu grubではなくwindowsが起動するはずです。

bootrec.exe /fixmbr

これでMBRが修復されたはずです。

2.Ubuntuアンインストール

無事にMBRが修復されたところで、続いてUbuntuをアンインストールしましょう。*5
これはストレージのUbuntu記録領域を消去してあげればいいので、EaseUS Partition Master*6でもつかってアンインストールしましょう。
無事に終われば多分元のwindows7シングルブートPCに戻ってるはずです。







今回この記事を書くにあたってwindows7すっ飛ばしかけたりしたので、多少なりとも役に立てばいいかなーと思っております。
とは言っても、しくじった所で

grub rescue>

とか出るぐらいなので特に焦る必要も有りませんし、仮にGRUBぶっ壊れてもこのへんはググれば何とかなるので、あきらめないことが肝心な気がしました。





*1:Master Boot Record

*2:Win7とUbuntu12のデュアルブート環境でgrubがどっか行った| アイディア・ボードより拝借

*3:多分、F8押しっぱなしでリカバリーモード起動します

*4:あるいは、リカバリーディスクから起動してもいいかと

*5:当たり前ですがUbutu領域に保存してたデータはすべて消えます

*6:EaseUS|データ復旧、データバックアップ、バーティション管理専門家