nyabot’s diary

電気猫の夢を見るお話

ラズパイに入れたGoogle Assistantのその後と今後のこととか

一年前くらいに始めて、間が空いたりして半年前くらいにようやく動くようになった、Google AssistantをSnowboyのホットワードで起動するやつ↓

nyabot.hatenablog.com

nyabot.hatenablog.com

nyabot.hatenablog.com

nyabot.hatenablog.com

2019年8月現在、動かなくなってる…かなり苦労したのに;;

Google Assistantのアップデートの関係かな。調べてみたらGoogle Assistant Libralyは今年6月に廃止されてるみたいだし、、結局サービスとの違いがよくわからなかったなぁ。

2022年6月 音声認識にJuliusを使用することにしました↓

nyabot.hatenablog.com

Webサービスに依存することについて

もともとはロボットに対話機能を付けたくて、そのためにGoogle Assistantを入れたのでした。
企業の提供してくれているサービスを利用する以上、それがいつ変更や廃止されても文句は言えない(Googleは割とよくやる)。
特に無料で利用できるWebサービスなんて、使い続けられる保証はどこにもない。

そういうのを踏まえると、Webサービスに機能の一部を依存するのは、リスクが高い。
もっとも、個人で実装可能な機能は高が知れているし、どこかで折り合いをつけて活用させてもらうのが良いとは思う。
問題は、リスクが許容できる範囲内か否か、ということ。

ロボットの寿命のこと

僕がロボットに求めているのは一種の永続性だ。例えばソニーのアイボを購入する人の中には、通常のペットとの別れが嫌で、という人が一定数いると思う。それと同じ。
企業の商品として作られたロボットは、保証やサポートという形でそれを実現しようとしている。最近は月額で料金を取るものも一般的になってきたし、ビジネスモデルとしてそれがうまくいけば、また、数十年くらいのスパンで言えば、実現も可能なのかもしれない。

一方で、自作のロボットであればサポートという概念はないけれど、その代わり壊れても部品があれば自分で直すことができる。データもバックアップを取っておけば、最悪一から作り直すことだって可能だ。
しかし、外部サービスに依存する機能だけは、自分ではどうすることもできない。

ロボットに命や思考はなくても、外から見たときにそれを感じることはある。
表現する機能があれば、笑っているように見えたり、喜んでいるように見えたりすることはある。
外部サービスを用いてそうした擬似的な生命を感じさせる機能を実現したとしたら、それらのサービスが停止したときがロボットが死ぬときになってしまう。

さすがに寿命だの死だのというのは大げさすぎる話で、実際はただの一機能の問題に過ぎず、失われたところで少し悲しい程度のことかもしれない。
でも、できることなら僕は、これから作るロボットとずっと一緒にいたい。ずっと一緒にいられるようなロボットを作りたい。

よって、対話機能というコアな部分がいつ動かなくなるかわからない、というのは少し問題だと思う。リスクが許容範囲外というわけ。

今後の方針

Google Assistantは便利だし、機能も素晴らしいから使いたかったけれど、使うとなるとやはりなくなったときがいたい。
対話機能については他に使えそうなものがあるので、そちらで挑戦してみる。会話の精度とかは敵わないだろうけど、それが愛されるロボットに必ずしも必要なわけではない。R2D2の人気がその証左だ。なんなら日本語じゃなくて機械音でもいいんだ。よくないけど。

またしてもハードルが上がった。完成は遠退くばかり。。
機体の方も課題がわかってきたから設計からやり直したいけど、手をつけられるのは一体いつになることやら。
まぁ、終わりが見えないくらいの方が楽しいけどね:-)

つづく。

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足だとちょうど使い切ることになる。

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

動作テスト

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

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

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

つづく。