nyabot’s diary

電気猫の夢を見るお話

MJPG-streamerの表示調整(Javascriptでcanvasに表示する画像を90°回転させる)

ロボットにwebカメラを取り付けるとき、基盤の形状と収めるスペースの都合で、90度傾けることになった。
カメラが90度傾いているので、撮影される画像・映像も当然90度傾く。
MJPG-streamerでストリーミングしたいと思っていたのだけれど、ただ表示させるだけだと映像が横を向く。こまった。

ラズパイ用のカメラモジュールを使用する場合は、オプションで角度の変更ができるみたい。
webカメラにはそういうオプションがなさそうだったので、Javascriptで表示するときに調整した。

webカメラを90度傾けて使うというのはたぶん極めて特殊なケースだし、正直もうやらない気がするけど、肝心なところだけメモ。

var imgUrl = "画像のURL";
var imgWidth = "画像の幅";
var imgHeight = "画像の高さ";

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');

canvas.width = imgWidth;
canvas.height = imgHeight;


//画像を90度回転させるため、高さと幅を入れ替えて使用する
var rImgWidth = imgHeight;
var rImgHeight = imgWidth;

ctx.rotate(90 * Math.PI / 180);//時計回りに90度回転させる
ctx.drawImage(imgUrl, 0, -rImgWidth, rImgWidth, rImgHeight);

左上の点を軸として指定した角度回転するので、時計回りに回転させた場合は回転後の幅(=回転前の高さ)と同じだけ描画開始位置を右(下)にずらすのがポイント。

CSSのtransform:rotate()で回転させる(追記)

もっと簡単な方法としては、cssでtransform: rotate(90deg);を指定してcanvas要素ごと回転させてしまう方法もある。
しかし、一つのcanvasに描画する画像が複数ある場合、この方法では特定の画像だけを回転させる(画像ごとに角度を変える)ことはできない。

回転させるためのコードはこんな感じ。キャンバスのサイズ比率(横:縦)は回転前が4:3、回転させたあとが3:4の場合。

var canvas = document.getElementById("canvas");
var canvasHeight;
var canvasWidth;
var isPortrait;

// ウィンドウの高さと幅の短い方にキャンバスの大きさを合わせる
if(window.innerWidth < window.innerHeight){
    isPortrait = true;
}else{
    isPortrait = false;
}

if(isPortrait){// 画面幅<画面高さ
    canvasHeight = window.innerWidth;// 90度回転させるため、ウィンドウの幅を回転前のキャンバスの高さとして指定する
    canvasWidth = 4*canvasHeight/3;
}else{// 画面幅>画面高さ
    canvasWidth = window.innerHeight;// 90度回転させるため、ウィンドウの高さを回転前のキャンバスの幅として指定する
    canvasHeight = 3* canvasWidth/4;
}

canvas.width = canvasWidth;
canvas.height = canvasHeight;

canvas.style.transform = 'rotate(90deg)';
canvas.style.transformOrigin = canvasHeight / 2 + "px";

以上。

つづく。

Raspberry Piに「MJPG-streamer」をインストールする

現在製作中のロボットにはUSBカメラを取り付けてあり、今後、

  • スマホからロボットの視点で操作
  • 画像解析(顔検知など)

を行いたいと考えています。

今回は、カメラの映像を配信可能にする「MJPG-streamer」をインストールしたのでメモ。

カメラはロジクールWebカメラから中身を取り出して、頭部に搭載しています。

nyabot.hatenablog.com

インストール方法や設定に関しては、書籍「実例で学ぶ Raspberry Pi 電子工作」とWeb上の情報を参考にさせていただきました。
このエントリーとは直接関係しないけど、電源OFFボタンの作成や6足歩行ロボットの作り方なども書かれているのでとてもおすすめ。

今回に限らず、Webの情報だけだとうまくいかないケースも多く、一方で書籍だけだと環境が自分と違う(ラズパイ用のカメラモジュールを使用していたり)ので、双方でうまく補完しつつ学んでいます。

MJPG-streamerのインストール

以下のコマンドでインストールと、ファイルのシステム領域への移動を行う。

$ sudo apt-get update
$ sudo apt-get install libjpeg8-dev cmake
$ git clone https://github.com/jacksonliam/mjpg-streamer.git
$ cd mjpg-streamer/mjpg-streamer-experimental
$ make
$ cd
$ sudo mv mjpg-streamer/mjpg-streamer-experimental /opt/mjpg-streamer

MJPG-streamerの起動

起動用のファイルを作成

$ sudo nano /home/pi/mjpg-streamer/start_server.sh

以下の内容を記述して、保存。

#!/bin/sh

PORT="9000" #ポート番号
SIZE="480x640" #画面サイズ
QUALITY="80" #画像クオリティ
FRAMERATE="30" #フレームレート
MJPEGDIR=/home/pi/mjpg-streamer
export LD_LIBRARY_PATH=/usr/local/lib
$MJPEGDIR/mjpg_streamer \
    -i "input_uvc.so -f $FRAMERATE -r $SIZE -q $QUALITY -d /dev/video0 -y -n" \
    -o "output_http.so -w /usr/local/www -p $PORT"

今回ここではパスワードを設定していないので、将来的に外部からもアクセス可能にする際は注意しないと。


2020.08.31 追記
1年経って上記の方法でやり直したらうまくいきませんでした🥺
原因がわかったら修整予定!


起動確認

以下のコマンドで起動する。

$ sh /home/pi/mjpg-streamer/start_server.sh

http://{Raspberry PiIPアドレス}:{設定したポート番号(9000)}/にブラウザからアクセスして、以下のような画面が表示されたらOK。

mjpg-streamerのデモページ

左側のメニューの「Stream」や「Javascript」から、実際にカメラで撮影している映像を確認できる。

ちなみに終了させる場合は、

$ ps ax | grep mjpg

でプロセスIDを調べて、

$ sudo kill {プロセスID}

でOK。

ラズパイ立ち上げ時に自動起動するよう設定

/etc/rc.local の最後にある、

exit 0

の前に、以下の1行を追加。

sh /home/pi/mjpg-streamer/start_server.sh &

これで、Raspberry Piの起動時にMJPG-streamerが立ち上がるようになりました。
ひとまず今回はインストールと起動設定まで。

つづく。

Raspberry Piに「WebIOPi」を導入する

WebIOPiの導入と初期設定、接続方法をメモ。

簡単に導入できて、ブラウザから端末をほぼ選ばずにラズパイをあれこれ操作できるようにする優れもの。
ロボットをスマホから操作するために使用する。

WebIOPiをダウンロード

WebIOPiの公式サイトにアクセスして、ダウンロード。

http://webiopi.trouch.com/DOWNLOADS.html

WebIOPiをインストール

ファイルをホームディレクトリ(/home/pi)にドラッグ&ドロップで移してから、解凍

$ tar zxf WebIOPi-0.7.1.tar.gz

解凍したフォルダ内に移動して、パッチを適用

$ cd WebIOPi-0.7.1/
$ wget https://raw.githubusercontent.com/doublebind/raspi/master/webiopi-pi2bplus.patch
$ patch -p1 -i webiopi-pi2bplus.patch

セットアップスクリプトを管理者権限で実行。

$ sudo ./setup.sh

「Do you want to access WebIOPi over Internet?」にはn,Enter。
当面は同一ネットワーク内からのアクセスしか予定してないし、外からアクセスしたくなったときは設定変更する。

WebIOPiを起動するために必要なファイルをダウンロードして、システム領域に移動

$ wget https://raw.githubusercontent.com/neuralassembly/raspi/master/webiopi.service
$ sudo mv webiopi.service /etc/systemd/system/

WebIOPiの起動

起動コマンドは以下。どのディレクトリから実行してもOK。

$ sudo service webiopi start

WebIOPiが起動しているかチェック

$ ps ax | grep webiopi

以下のように表示されれば起動ずみ。先頭の数字(プロセスID)はWebIOPiを起動するたびに変わる。

2429 ?        Ssl    0:00 /usr/bin/python3 -m webiopi -l /var/log/webiopi -c /etc/webiopi/config
 2459 pts/1    S+     0:00 grep --color=auto webiopi

正しく起動していないときは、二行目だけが表示される。

WebIOPiの終了

$ sudo service webiopi stop

※上記コマンドでうまく終了しない場合は、先ほど表示されたプロセスIDを用いて、killコマンドで終了させる

$ sudo kill 2429

WebIOPiの自動起動設定

WebIOPiを自動で起動するようにしておくと、毎回ラズパイに接続して起動させなくて済むので便利。なので設定しておく。

自動起動をオンにする

以下のコマンドで、ラズパイの起動時にWebIOPiが立ち上がるようになる。

$ sudo systemctl enable webiopi

自動起動をオフにする

オフにする場合は以下。

$ sudo systemctl disable webiopi

ブラウザからアクセス

IPアドレスを固定している場合はそれを使用。
固定方法はずっと前に書いてました↓(覚えてない…)

nyabot.hatenablog.com

固定していない場合は、以下のコマンドでIPアドレスを調べる。

$ ifconfig

wlan0 の項目の、inet 192.xxx.x.xとなっているところ(xは数字)がIPアドレス

ブラウザに「http://192.xxx.x.x:8000/」と入力すると、ラズパイのWebIOPiにアクセスできる。

ユーザー名とパスワードを尋ねられるので、以下の初期設定値を入力して認証。

  • ユーザー名:webiopi
  • パスワード:raspberry

以上。ちなみに、OSによっては一部コマンドが異なるようなので注意。

つづく。

ロボットの胴体と脚部の作成

前回はロボットの頭部を作った。

nyabot.hatenablog.com

今回はロボットの胴体と脚部について。
ブログは空いた時間に書き溜めてまとめて投稿しているけれど、実際はかなり時間かかってます。。

胴体部について

主要な部品は頭部に詰め込んだので、胴体には以下が収まるようにする。

  • Raspberry Pi
  • Raspberry Pi用バッテリー
  • サーボドライバ
  • サーボ用電池ボックス
  • ブレッドボード

今作成中のロボットは、今後も長期的に機能の追加・変更やテストを行う予定なので、ブレッドボードを乗せたまま動作させる。
サーボドライバは複数のサーボモータを動作させるためのもの。サーボモータを動かすための電池も、ラズパイ用の電源とは別に用意する。

サーボドライバについては過去記事にて。

nyabot.hatenablog.com

試作段階なのでコードを抜き差しすることも多く、足回りも稼働を最優先させたいため、外観は重視しないことにする。 素材は厚さ2mmのPP板。基盤を直接上に乗せたりもするので、電気を通さない素材にした。

脚部について

サーボモータを用いた2自由度の足を8本作る。
素材はアルミニウム。強度と加工の容易さから選択。 初めは6足での歩行を予定していたものの、実際に作ってみると自重に耐えられず、2本増やすことに。
ちなみに、今回使用したサーボドライバは単体で動作させられるサーボモータの最大数が16個なので、2自由度×8足だとちょうど使い切ることになる。

足はそれぞれ胴体にネジで固定。
サーボモータをホーンだけそのまま固定するとぐらつきが大きいため、一工夫必要。 アルミ板でブラケットを作って両軸化させたり、固定していない側に板を当て挟み込むようにした。

動作テスト

胴体にラズパイやバッテリーを載せ、足を付けたら動作を確認。 サーボを動かすコードは以前サーボドライバのテスト時に作ったものをカスタマイズして利用。

実際に動かした様子が以下↓(動画を貼り付けるためについったのアカウント作った)

やっぱり動くっていいなぁ!
モーションは最適化の余地ありあり。
実際には動かすまでさらに色々問題があったのだけど、それはまた別のお話。

つづく。

ロボットの頭部の作成

ロボットの頭部には、以下の機能を搭載する。

  • スピーカー
  • マイク
  • カメラ
  • LEDライト

色々考えた結果、それぞれのパーツを頭部の以下の部位に配置することにした。

  • スピーカー → 耳
  • マイク → 鼻
  • カメラ → 口
  • LEDライト → 目

本音を言えば、目にカメラ、耳にマイク、など生物の場合の機能に合わせて配置したかったのだけれど、サイズの都合で断念。 また、目にLEDは譲れなかった。やっぱり目は光らないと。

スピーカー

スピーカーはダイソーの300円スピーカーを使用。 外装をノコギリで切り開いて中身だけ取り出して、3mmのボルトで固定。 ボリューム調整のダイヤル部分は、頭部内の空いたスペースに納めた

マイクとカメラ

マイクとカメラは以前購入しておいたロジクールのウェブカメラを使用。 こちらも外装を取り中身だけを使う。

RGBフルカラーLED

LEDはソケットに入れて使用。
金属製のソケットに入れると、むき出しで使うよりかなりそれっぽく見える。
ソケットは単色LED用に設計されているものだったので、RGBフルカラーLEDだとそのままでは使えず、外径を小さくするために少し削ったりした。

もともとLEDは電源や状態のON/OFFを視覚的に判断するために取り付けたいと考えていて、その点では二色でも問題なかった。が、フルカラーLEDが意外と安価で売られていたので使うことに。
赤、緑、青のON/OFFの組み合わせだけで、黄、青緑、紫、そして白と、計7色になるため、各色の出力を細かく調整しなくても十分楽しめる。スタンバイ中は赤、動作中は緑、手動操作中は青、とか。
目の色は全体の印象を大きく左右することがわかったので、後々は感情表現等にも使えたらいいなと思う。
なんにせよ、ロボットの目が光るのはロマン。電源が入ったことを示す目の発光に、命や魂が宿る暗喩を感じるのではないかと思う。

かわいく作る←重要

私が作っているのは猫型ロボットで、故に顔が可愛いのは最重要事項だ。
必要な部品を全部詰め込んで、それなりにかわいい猫っぽい顔にするのが本当に大変で大変で……。スピーカーとか大きすぎるし!
誰かの作品を参考にしようにも、個人制作のロボットのビジュアルでかわいいものというのはネット上でもほとんど見つからず(そもそも猫型ロボット作っている人がいない)、試行錯誤と情熱とほんの少しの妥協の結果がこれ。

f:id:sizohu:20190824142031j:plain

個人的には満足しているけど、どこかアイアンマンの最初のやつを思い出す風貌。いずれmarkII、markIIIと見た目が良くなっていくんだきっと。 あるいは、サイボーグクロちゃんのようにぬいぐるみをかぶせるのもアリかも。。

つづく。