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

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

windows10にアップグレードしたら死んだ話

経緯

7/29から一般リリースされたwindows10が気になって、アップグレード通知が来るまで待てなかったので手動でアップグレードした。
元のOSはwindows7 Pro。
なお手動アップグレードの方法はこれ
http://www.microsoft.com/ja-jp/software-download/windows10
手順通りにやったらwindows10にアップグレードは出来たもののなんだか色々ぶっ壊れてた。
「何もしてないのにこわれた!」
という気持ち。

何が死んだのか。何が壊れているのか。

具体的には、以下の通り

  • 僕のグラボのドライバがwindows10に対応していなかった*1(そしてこれが大本の原因)
  • windows10からwindows7にもどせなくなった。*2
  • explorer周りが完全に死んでいる。
  • OSのブートマネージャが死んだ*3

おそらく他にも気づいてない細かい点があると思うけど、多分クリティカルなのはこれぐらい。

それぞれの原因と時系列

原因

上記の問題はそれぞれ下記の原因によって起こっているらしい。*4

  • ドライバがwindows10に対応していなかった
  • 何らかの原因でwindows7のバックアップが作成されなかった
  • インストールが正しく行われていない。あるいはインストール後に何らかの原因で破損した。
  • BCDがプライマリディスク*5から何故か消失している。

実はこれらの問題は僕のとある動作によって引き起こされている可能性が高い。

時系列

windows10にインストール後ディスプレイドライバが死んでるのでドライバ入れなおす(nVidia)
-> 対応したハードウェアが見つからないと言われる(大本のドライバがぶっ壊れている)
-> win7の時に使用したドライバディスクでドライバインストール
-> OSがHDDブートしなくなる(ブルスク)
-> USBでレスキューディスク作ってスタートアップ修復(何回やっても失敗)
-> 何故かUSBを挿せばブート出来るようになった(何故かBCDがUSBに作られてしまった。)
-> explorer周りが死んでる事に気づく。
-> windows7に戻せなくなってる事に気づく。

という感じ。

解決方法

以上の問題の解決方法について数回に分けて書いていく。*6
今回はディスプレイドライバの話とOSがHDDブートできなくなった事に対する解決案みたいな話。

ディスプレイドライバ

僕が使ってるPCのグラボはGeForce GTS450という割と古い物で、標準のドライバだとwin10に対応してないっぽい。
これはnVidiaがwin10リリース後に配布したドライバソフトをインストールする事で解決した。
http://www.geforce.com/drivers/results/87789
上記URLのドライバをインストールしたらちゃんと機能したので、グラフィック周りがおかしい人は試してみると良いかもしれない*7

OSがHDDブートできなくなった事について

今回は原因とMSのサポートに聞いた解決案についてだけ。*8

原因

windowsは起動に関してどのディスクのどこにwindowsがインストールされているのかという事を記録しているファイルが存在する。
これはBCD(Boot Configuration Data)と言うファイルで、このファイルにパラメータが記述されているらしい。
通常はC:\windows\Boot下に存在するが、何故か僕のwindowsではBCDのみが消えていた。

解決案①

幾つか試してみたがとりあえずMSサポートに言われた内容を記載。
とてもシンプルだが、今回僕のケースではUSBからブート出来るという事で、USBにBCDがある事がわかった。
そこで、プライマリHDDにUSBにある"Boot"というフォルダと"bootmgr"をコピーしてスタートアップ修復を2回行えとの事だった。
(試してみたが、結論から言うとだめだった。どうやらbootmgrがブートするディスクを読みに行けないらしい。)

解決案②

ちょいと技術的な話。このページに掲載されていた。
pcsupport.about.com

~> bootrec /rebuildbcd

ここでwindowsが見つかればwindowsがインストールされているディスクをBCDに設定しておしまい。
見つからなければ。

  • 現在設定されているBCDのバックアップをとる
~> bcdedit /export C:\bcdbackup

なお、ここでのドライブはCかどうかは自分のパソコンに合わせて。

  • 続いてBCDのアクセス権を自由にする。
~> attrib C:\boot\bcd -h -r -s
  • BCDをリネームする。
~> ren C:\boot\bcd bcd.old
~> bootrec /rebuildbcd

見つかればwindowsBCDに設定して終了。
どうやらwindowsが見つけられる*9状態であれば、BCDwindowsに設定しそこねているだけらしいので、おそらくこれでうまくいくらしい。

やっぱりだめっぽい

ブルスクになった段階で結構変なところを弄ってしまったらしく、僕のPCは現在windowsがインストールされている領域が何故かロックされているとみなされてしまう。
そのため、上記の解決策ではどちらも上手く行かなかった…

次回

まだ今回の事が結論出てないので、まずはもう少し試してみる。
解決したら次のexplorerの問題とダウングレードできない問題を解決していくつもり。

2020/11/22追記
そういえば、この問題、解決していくつもりと言いつつ、何もしてなかったことを思い出した。
結局色々*10試したけど、だめだったのでクリーンインストールしました…


はー…なんでぶっ壊れるかなぁ…

*1:現在は対応済み

*2:大変つらい

*3:一番でかい!

*4:MSサポート曰く

*5:windowsがインストールされてるディスク

*6:僕もまだ全部解決できてない。

*7:自己責任で

*8:解決できてない

*9:bootrec.exeがOSが入っているディスクにアクセス出来る

*10:ドライバ再インストールとか、OS領域を別のストレージにクローンしてみるとか

dpkgのlock解除

最近全くブログ書いてない事に気づいた。*1
研究が忙しかったということにしておこう。

今回はVirtualBoxの話。というかUbuntuの話。

普段研究室でUbuntu使ってて、家で作業の続きをする時には家のWindowsPCにVirtualBox入れて仮想マシンとしてubuntuで作業をしてる。
また、個人的なファイルとかはDropboxで共有してるのだけれど家のUbuntuに入れてなかった事に気づいたので先日インストールしようとしたところ、なんか失敗した。*2

結論からいうと、インストール中にフリーズしたため強制的に再起動した所apt-get updateとかができなくなった。

E: /var/lib/apt/lists/lock が取得できませんでした - open (11: リソースが一時的に利用できません)
E: ディレクトリ /var/lib/apt/lists/ をロックできません
E: ロック /var/lib/dpkg/lock が取得できませんでした - open (11: リソースが一時的に利用できません)
E: 管理用ディレクトリ (/var/lib/dpkg/) をロックできません。これを使う別のプロセスが動いていませんか?

って感じの事言われた。


今回はこれの解除方法とかを書こうとおもう。
早速ググってみたらドンピシャな事書いてあった記事があった。ankyo.blog.so-net.ne.jp

大変ありがたいので、備忘録的に書いていく。

方法

まずリカバリーモードで立ち上げる。
shiftキー押しながら起動するとリカバリーモードになる。

リカバリーモードでrootを選択し、以下のコマンドを入力する。

rm /var/lib/apt/lists/lock
rm /var/lib/dpkg/lock
apt-get update
apt-get install -f

あとは再起動。

怒られた

僕が上記の方法でlockファイル削除しようとしたら「Read Onlyだから消せない」って怒られた。
これも調べてみると再マウントする事で解決出来るらしいということがわかった。qiita.com
大変ありがたい。いんたーねっとは偉大である。

というわけでこちらに書いてある通りに下記コマンドを入力してリマウント

mount -o remount,rw /

あとは上に書いたコマンドでlockファイルを削除して、アップデートと強制インストールをしたら再起動しておしまい。

ちゃんと上手くいった。
大変ありがたいので、今後忘れないようにしよう。

*1:めっちゃツイートしてるくせにブログ更新してない

*2:面倒臭がってソフトウェアセンター使ったのが問題

std::stringstreamをクリアする

やり方

すごく初歩的な事だけど、最近知ったので。
std::stringstreamに格納されてる値をクリアにして別の値を入れる時に必要な処理

#include <iostream>
#include <sstream>

using namespace std;
int main(int argc, char* argv[]){
  stringstream ss;
  ss << "hoge";

  cout << ss.str() << endl;

  //ssをクリアする
  ss.str("");
  ss.clear(stringstream::goodbit);

  ss << "fuga";
  cout << ss.str() << endl;

  return 0;
}
hoge
fuga

ソースコードから複数のディレクトリに入ってるファイルを逐次参照するプログラムとかに使える。

使ってみた

data
  L dir1
      L file1.dat
    dir2
      L file2.dat
    dir3
      L file3.dat
    dir4
      L file4.dat

みたいなディレクトリ階層を作って、各ディレクトリのfile*.datを見るプログラムを作ってみた。
各file*.datにはファイルパスを書いておく。

#include <iostream>
#include <sstream>
#include <fstream>

using namespace std;
int main(int argc, char* argv[]){
  stringstream dir;
  string path = "./data/dir";
  string file = "file"

  for(int i = 0; i < 4; i++){
    dir << path << i+1 << "/" << file << i+1 << ".dat";
    ifstream ifs(dir.str().c_str());
    string line;
    while(getline(ifs, line)){
      cout << line << endl;
    }
    dir.str("");
    dir.clear(stringstream::goodbit);
  }

  return 0;
}
./data/dir1/file1.dat
./data/dir2/file2.dat
./data/dir3/file3.dat
./data/dir4/file4.dat

といった感じ。
OpenCVとかで作った行列データをyamlにして別々のディレクトリに保存したり読みだしたりする場合とかに使える。
(std::ifstreamのところはdir.str().c_str()としててちょっとアレだけど…)

参考HP

stringstreamのクリアの仕方 - りんでん記


[追記 2015/3/18]
ファイル逐次読み出しのソースをちょっと改変

謹賀新年

あけましておめでとうございます。

去年は色々有りました。幾つかイベントに参加したし、いっぱい勉強になりました。
まだまだいっぱいやることあって未熟者ですが、いっぱい頑張っていきたいと思います。
今年2015年は過去のいくつものSF作品などの時代設定で使用されている年でもあるので、僕もいい感じの事を出来るように色々やっていきたいですね。(適当)

今年もよろしくお願いします。

出かける前に予定とかを教えてくれるシステムを作った話

この記事はお家ハックAdvent Calendar 2014の17日目の記事です。

今回は朝の外出前に予定とか天気とか携行品を通知してくれるシステムを作った話です。(実は今年の8月ぐらいに作ったというのは内緒)

コンセプト

忙しい現代人は朝ゆっくりする時間が無い人が多い*1
僕も朝は決まってドタバタしてる。しかも急いで色々準備するもんだから忘れ物などをよくする。*2
忘れ物は人によっては結構深刻な問題に発展しかねない。
そういう失敗を起こさないための予防策として、外出前に今日の携行品とか予定を確認できる様なシステムがあればすごく嬉しいなーと思い、そういうサポートをしてくれるシステムを作りました。

概要

前提

朝の行動として以下の行動が考えられる

  • 起床
  • 洗顔など
  • 朝食
  • 気象情報確認
  • 気象情報に基づいた着替え
  • 予定確認
  • 携行品準備
  • 消灯
  • 外出

上記のうち太字の行動に何らかのサポートを行う事で外出前に効率的かつ失敗の少ない行動を行うことが出来ると考えました。

システムについて

必要要件
  • 当日の予定をメール通知
  • 持ち物を音声で通知
  • 天候情報を音声で通知
  • 消灯機構

以上を行う

システム概略図

基本はPCとUSBカメラとマイクとスピーカーがあれば出来る様にしたいと考え下図のようにした。(ちょっとわかりにくいけど・・・)
f:id:i-hako:20141217222005p:plain
天気情報や予定、持ち物などを各種APIを使用してウェブから取得してくる。
また、ユーザインターフェースとして音声を用いることにした。
音声UIとしてrospeexというクラウド音声合成サービスを使用した。*3

動作概要

システムの動作の概要は下図の通り
f:id:i-hako:20141217230615p:plain

  • 事前作業として、ユーザはgoogleカレンダーに事前に予定と必要物品を登録しておく。
  • ユーザが音声で予定を尋ねると、それを認識しgoogleカレンダーに予め登録されている予定を読みだしてメールで送信する。
  • 更にその後ユーザが外出準備に取り掛かり、携行品を準備しようとすると、動体を検出してその日必要な携行品を音声で通知してくれる。
  • また、外出直前に天気などを尋ねると、yahoo! weatherから天気情報を取得してその日の天候について教えてくれる。
  • 最後に、「電気を消して」と言うと電気を消す。

という感じです。


まとめ

感想

実際にやった場所は研究室だったので、厳密な意味でのお家ハックかと言われるとちょっとあれな感じはあるけれど*4、カメラとスピーカーとマイクがあれば好きな所で必要な情報をサポートしてくれるので、割りと便利かも知れない。
むしろ頼りすぎて余計に物忘れが激しくなりそうな感じはある。
一番きつかったのは各状態の制御をrosmessageでやってるので、ちょっと同期などが難しかった感じがあります。
(ROSについてはググってください。僕はあまり説明出来ません…(申し訳ない))

今後について

結局リマインダーの強化版みたいな感じで、事前にgoogleカレンダーに手動で予定や必要物品を登録しなきゃいけないのでもうちょっと賢い感じで予定とか立ててくれると嬉しいなーとか…

*1:早起きすればいいとかそういう話もあるけど…

*2:予定をすっぽかす事も有ります

*3:画像はhttp://rospeex.org/top-ja/より拝借

*4:まぁでもほとんど住んでるも同然だし良いよね!!!!!

$ 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僕に買ってください!!!!!!!!!