Android Studioのエミュレータが起動しない

新しいノートPCにAndroid Studioをインストールした際、少々問題が起こったため書き留めます。

環境

PC:HP Spectre x360
Windows10
android studio 3.0.1

エミュレータが起動しない

インストール後、「Hello World」のテスト用アプリをエミュレータで表示しようとしたところ・・・

Intel HAXM is required to run this AVD.
VT-x is disabled in BIOS.

Enable VT-x in your BIOS security settings…

BIOSで何とかしろと言われました。

「VT-x」?・・・これは調べると「Virtualization Technology」仮想化技術を有効にしろという話のようです。

BIOS起動

機種によって違うので、調べる必要があります。
HPの「Spectre x360」では、起動時に「Esc」を連打して、選択画面のようなものが出たら「F10」でBIOSが起動します。

Securityに項目がない

「your BIOS security settings」ということで、「Security」の項目を開いたのですが、VTが見つかりません。

隣の「System Configuration」を開くと、「Virtualization Technology」の文字を発見!

「Disabled(無効)」となっているところを「Enabled(有効)」に切り替え、設定を保存。

Windowsを立ち上げ、Android Studioのエミュレータを実行してみると、無事起動しました。

ログインパスワードは後で聞く

Webサービスのログイン画面で、アカウントだけ先に入力し、パスワードは後で聞かれる経験が増えてきました。

例えばAmazon、Google、Micorosoftなどのログイン画面です。

たしか昔は、アカウントとパスワードをセットで聞かれていたと思います。

間違いを特定できない

アカウントとパスワードのセットだと、ログインできない場合、どちらが間違っているか分かりません。

間違ったアカウントで、ありとあらゆるパスワードを試すこともあります。

そしてロックされる!

セキュリティとしては良いのですが・・・ストレスにはなります。

2段階入力なら間違いが明確

アカウント、パスワードの順で2段階入力する方式なら、アカウントを間違った時点で不毛なパスワード入力がなくなるので、ユーザーにストレスを与える時間を減らすことができます。

アカウントが間違った場合、違うメールアドレスを試してみよう・・・と、迅速に判断を下せます。

余談ですが、Amazonのログイン画面を見ると、「アカウント」という言葉を使わず、「Eメールまたは携帯電話番号」という具体的な文言を使い、ユーザーの迷いを減らす配慮をしています。

Webサービスの利用機会が増え続け、アカウントやパスワードを忘れて困るユーザーが増えていると思います。

単純なログイン画面のUIデザインも、作り込むことで会員の離脱を防ぐことができそうです。

 

動かないカルーセル

前回に引き続き、Amazonカルーセル(画像が横方向に、ビュンビュン切り替わるUI)のスゴイところをもう一つ。

マウス移動中はカルーセルが停止

カルーセルの画像の上で、マウスを動かし続けてみると、一向に次のスライドへ移りません。
マウス移動中はカルーセルが止まります。

マウスが静止してしばらくたつと、またカルーセルが動き出します。

(ちなみにマウスを使わないスマホサイトは、カルーセルが採用されていません。)

ミスクリックをしたことがない

カルーセルはスライドが切り替わるタイミングで、ミスクリックをする可能性があります。

前のスライドをクリックしたかったのに、次のスライドをクリックしてしまった・・・。

Webサイト閲覧時に、たまにやるのですが、Amazonでミスクリックをした記憶がありません。

マウスをカルーセル上で動かしているときは、ユーザーがクリックする可能性があるため、カルーセルを止める配慮をしているのでしょう。

AmazonのUI、UXのこだわりは驚異的です。

待たせない!0.2秒のカルーセル速度

画像が横方向に、ビュンビュン切り替わっていくカルーセルUI。

Amazonのトップページ(2018年1月現在)の切り替わりスピードが速い!?と思い、気になって測定しました。

切り替わりに要する時間は0.2秒

原始的な手法ですが・・・Amazonのトップページを録画し、動画編集ソフトでカルーセルの切り替わり速度を測りました。

0.2秒!

参考までに有名そうなカルーセルライブラリのコード、slickを確認したところ、デモでは0.3秒で設定されていました。

たった0.1秒ですが、1.5倍違いますし、Amazonのカルーセル画像は大きいので、体感速度は恐ろしく速く感じます。

ユーザーを待たせない

これだけ速いのは、カルーセル切り替えの間、ユーザーを待たせないようにする配慮から来たものだと思います。

「読み込みが0.1秒早くなると、売上が1%増加する」というAmazonの発表があったように、待つ要素を極限まで削っているのかもしれません。

0.2秒のスライドは、アニメーションデザインとして見ると体感速度が速すぎ、美しいかどうか分かりませんが、UIデザインとして見ると美しく感じます。

ただし、カルーセルは成果を上げられない事例を良く耳にするので、まずは導入すべきか検討したほうが良さそうです。

 

謎の触覚出力器(画像認識でArduino制御)

カメラで撮影されたボールの位置を、見ないで指だけ(触覚)で分かるようにします。
(何のためにやっているかは省略)

・・・とりあえずOpenCVとNode.JSを使い、Webカメラで画像認識した結果をArduinoに伝えられるか試します。

ボールの位置に応じて鉄の棒が飛び出す

先に結果です。(子供と一緒に試しています。)

分かりにくいですが、右下で鉄の棒がピクピク動いています。

Webカメラで撮影している青いボールのX座標と連動しています。

全体像

下記の構成と流れで、実現しました。

Webカメラ・・・ボール撮影

OpenCV(Python)・・・ボール認識

JSON・・・座標書き込み

Node.JS(chokidar)・・・座標更新を感知

Node.JS(johnny-five)・・・座標に応じた電圧出力をArduinoへ

Arduino・・・リレー回路でソレノイド回路に命令を伝える

ソレノイド・・・ボール座標に応じて鉄の棒が飛び出す

 

広く浅い知識の組み合わせで、なんとかした感じです。

各項目をもう少し詳しく書きます。(逆順でソレノイドから)

ソレノイドを使った触覚出力器

まずは、ボール座標に応じて鉄の棒が飛び出す触覚出力器(?)を作ります。

見なくても触るだけで、ボールの位置が超おおざっぱに分かる機械です。

ソレノイドを4つ並べて、金具で固定します。

見ての通り1つの座標軸にしか対応せず、しかも4段階です。

100個くらいソレノイドを並べ、ボール座標を表そうと企てたのですが、現実的ではありませんでした。(専門家に聞いたところ、マトリクス制御で空気を使ったもっと賢いやり方を教えてくれました。)

私はそこまでスキルがないので、4つのソレノイドで試します。

Arduinoとリレー回路

9V電池とソレノイドを、リレーを挟んで繋げます。
(5Vソレノイドを使っているので変圧しました。)

リレーはArduinoのピン2~5番とつなぎ、ON/OFFを制御します。

Arduino(Nano)には、スケッチ例から Firmata > Standard Firmata を選び、書き込みます。

ケース作り

貧相な試作機を、少しリッチにしましょう。

土台の木を2つ並べてボンドでくっつけ、黒いスプレーで塗装します。

乾かすと、なかなかのツヤがでました。

それに電子回路を詰め込み、上からアクリルを被せます。

なんだか貧弱な機能に反し、すごそうな雰囲気が出てきました。

Node.JSサーバー

雑な説明ですが・・・

Johnny-FiveでArduinoを制御できるようにし、chokidarモジュールでJSONファイルの更新を感知できるようにします。

OpenCVで画像認識

ボールをOpenCVで認識させる方法は過去の記事参照

これに加え、ボールの座標をリアルタイムでJSONに書き出すよう改修しています。

とりあえず完成

ボールの位置に応じて、鉄の棒が飛び出す機械の完成です。

これでボールを見なくても、右か左かおおざっぱに指で感知できます。

私のスキルでは無理ですが、ピンアートくらい緻密に、三次元でボール座標を表現することを目指しています。

リレー回路でソレノイドを動かす

Arduinoでソレノイドを動かします。

前回、電流不足だったので別電源を使い、ソレノイドを動かしましたが、これだとArduinoのプログラムで制御できません。

リレーかトランジスタか

Arduinoで大きな電流が必要な部品を動かす手段として、リレーかトランジスタを使う方法があるようです。

リレーは別電源回路のスイッチを制御
トランジスタは電流を増幅

・・・というような、おおざっぱな理解でいます。

ソレノイドを動かすサンプルとして、トランジスタ「TIP 120」をよく見かけますが、すぐに手に入らず、リレーを使うことにしました。

リレー回路

写真左がリレーです。4つ制御できるタイプのやつです。

Arduinoの小さな電流をリレーに伝えると、大きな電流を扱う回路のスイッチが入るようになります。

小さい電流の回路→大きい電流の回路に伝えるということで、リレーと呼ばれます。

1秒ごとに飛び出す

プログラムはLチカとまったく同じです。

#define LED_PIN 2
 
void setup(){ 
 pinMode(LED_PIN, OUTPUT);
}
 
void loop() {
  digitalWrite(LED_PIN, HIGH);
  delay(1000);
  digitalWrite(LED_PIN, LOW);
  delay(1000);
}

2番ピンとリレーのINをつなぎ・・・
(GNDやVCCもつなぎますが、勘で分かるくらい単純です)

実行。

よし、動きました。

大きな電流を扱うときに

リレー回路は、直感的に分かりやすいので、気持ちが楽です。

リレーの知識があれば、前に扱いに困ったパワーLEDも制御できるようになります。

開発の幅が広がりました。

棒が飛び出すソレノイド

金属の棒が飛び出す部品が欲しくて探していたら・・・ありました。
「ソレノイド」というらしいです。

ソレノイドは単純構造

秋月で「ソレノイド 5V ZHO-0420S-05A4.5 プッシュ型」を購入しました。

電磁石で金属の棒が押し出され、電流を止めればバネで金属の棒が戻ります。
プラスもマイナスもなく単純な構造。

ただし、電気の逆流を防ぐため、ショットキーダイオードはセットで使われるようです。

電流不足で単純にはいかない

Arduinoの5Vにつないでソレノイドを動かしてみます。

・・・静かにArduinoの電源が落ちました。

動作に1.1Aくらい電流が必要みたいなので、足りません。

外部電源を確保

家庭用コンセントから5Vの電源を作ることにしました。

まずは動作確認のため、Arduinoにつながず、ソレノイドを物理スイッチで制御します。

写真右側、3端子レギュレータの裏に、スライド式のスイッチを設置。

スイッチを入れると、ソレノイドの棒が飛び出しました。

とりあえず動作確認はできましたので、次はArduinoで制御できるように組み替えます。

 

・・・なお、3端子レギュレータは非常に熱くなるので、これと隣接してスイッチを配置するのは、もはやトラップです。

スイッチを切り替えいるたびに熱いです。愚かな設計です。

コンセントから5V電圧を作る

家庭用100V交流電源のコンセントから、直流の5Vを作ります。

モーターを動かす時など、Arduinoで流せる電流(200mA?)程度では不足することがあるので、大きな電源を確保することにしました。

5VのACアダプターDCジャックを買えば解決のような気がしますが、手元にある部品でやってみます。

理解が浅いので、この情報は参考程度に・・・

使ったもの

今回は安定した電圧を供給してくれるACアダプターを使っているので必要ないですが、一応下記コンデンサーも使用。

  • 0.1μF セラミックコンデンサー ×2
  • 47μF 電解コンデンサー(100μF程度が良い?)

冒頭の写真のような回路になります。
電圧が安定しないACアダプターを挿した場合、コンデンサーは役立つかもしれません。

ちなみに、コンデンサーを刺さない場合、下記の写真のような単純な回路となります。

電圧は5V弱?

本当に5Vになっているか自信がないので測ります。

結果、コンデンサーがあってもなくても4.96V。

ちょっと低いですね。

個人的にはぜんぜん許容範囲なのですが・・・LEDを光らせると、電圧が下がったりするのでしょうか?

まあ、この電源で、5Vのモーターが動いてくれたので、良しとします。

現実とCGの連動 WebカメラとWebGL

Webカメラに映った赤いボールを認識し、WebGLで生成した赤いボールと連動させます。

うまく説明できないので、先に結果を・・・

球技をリアルタイムで3Dに置き換えるときなどに使えます。

環境・バージョン

Windows10
Python 3.6.1
OpenCV 3.3.1
Node.js 6.11.0

WebGL連動までの流れ

Python初心者が、できるだけJavaScriptとJSONでなんとかしたいと思ったら、こうなってしまいました・・・。

1.Webカメラでボール撮影

2.Python(OpenCV)でボールを認識

3.ボールの座標をJSONファイルに書き込み

4.Node.js(chokidar)でJSONファイル変更を感知

5.soket.ioで座標をブラウザに通知

6.ボール座標をWebGL(three.js)に取り込みレンダリング

 

今回は、流れを書くのみに留めます。

OpenCVでボールの軌道描画

前回まで、OpenCVでボールを認識させるプログラムを書きました。

今度はボールの軌道を描画します。

環境・バージョン

Windows10
Python 3.6.1
OpenCV 3.3.1

ボール軌道に点を打つ

先に出力結果です。

赤いボールが通った道に、ピンクの点が描かれます。
(素材動画のコマ落ちで、点が一つ抜けています。)

なお、マニアックですが・・・この動画は、ボッチャの「クッションボール」という技の軌道を表したものです。

他のボールに当てて軌道を変え、ターゲットの白いボールに近づけています。

ボール軌道描画のコード

毎フレーム、ボールの座標を配列に記録し、forで配列の分だけ円(点)を描画する流れです。(もっと賢い書き方がありそう・・・)

import cv2
import numpy as np

cap = cv2.VideoCapture('xxxxx.mp4') # 任意の動画

# 動画出力設定
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
out = cv2.VideoWriter('output.avi',fourcc, 23.0, (1280,720))

orbit = []

while(1):
    _, frame = cap.read()

    #マスク画像取得
    def getMask(l, u):
        # HSVに変換
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

        lower = np.array(l)
        upper = np.array(u)
        if lower[0] >= 0:
            mask = cv2.inRange(hsv, lower, upper)
        else:
            #赤用(彩度、明度判定は簡略化)
            h = hsv[:, :, 0]
            s = hsv[:, :, 1]
            mask = np.zeros(h.shape, dtype=np.uint8)
            mask[((h < lower[0]*-1) | (h > upper[0])) & (s > lower[1])] = 255

        return cv2.bitwise_and(frame,frame, mask= mask)

    # 輪郭取得
    def getContours(img,t,r,drawOrbit):
        gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
        ret, thresh = cv2.threshold(gray, t, 255, cv2.THRESH_BINARY)
        imgEdge, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

        # 一番大きい輪郭を抽出
        contours.sort(key=cv2.contourArea, reverse=True)
        cnt = contours[0]

        # 円描画
        (x,y), radius = cv2.minEnclosingCircle(cnt)
        center = (int(x),int(y))
        radius = int(radius)

        if radius > r:
            if drawOrbit == 1:
                orbit.append(center)
                for j in orbit:
                    cv2.circle(frame,j,10,(128,128,255),-1) # 軌道描画
            return cv2.circle(frame,center,radius,(0,255,0),2) # 最小外接円描画
        else:
            return frame

    # 白・赤マスク
    res_white = getMask([0,0,100], [180,45,255])
    res_red = getMask([-10,45,30], [170,255,255])

    # 輪郭取得
    getContours(res_white, 45, 75, 0) # (画像, 明度閾値, 最小半径, 軌道描画 0=なし 1=あり)
    contours_frame = getContours(res_red, 45, 75 ,1)

    # 動画書き込み
    out.write(contours_frame)

    # 再生
    cv2.imshow('video',contours_frame)
    k = cv2.waitKey(46) & 0xFF

    #Q で終了
    if k == ord('q'):
        break

out.release()
cv2.destroyAllWindows()

軌道描画の他、動画をAVIで保存するように改修しています。

軌道描画の使い道

ボールの軌道を可視化することで、自分の投球のブレや距離を分析し、技術向上に使えます。

また将棋の「棋譜」のように記録していけば、うまい選手の戦術・戦略を学習できそうです。

初心者のために使うのであれば、戦術・技を教えるときに、可視化されていれば、理解が深まるでしょう。