ロボットを遠隔操作する

前回まででロボットを前後左右に動かす python の命令ができたと思います。 今回はキーボード、スマホを使って動かすようにしてみましょう。

キーボードを使って操作する

python では,ユーザー入力に input を使うことが多いですが,この関数では文字を打った後必ずリターンキーを押す必要があります.ゲーム等で操作する時には,キーを押されたらキャラクターがすぐに動きますが,そのような操作を可能にするために,kbhit を使います.通常 Terminal でキーボードの入力を制御したい場合には termio という制御ライブラリを使いますが,今回は,その制御を簡単に使えるようにしたライブラリkbhit.pyを使います.

まずは

python kbhit.py

で kbhit の使い方を確認してください.(このプログラムの動作の確認は mac でもラズパイでもどちらで行っても構いません) キーボードを打つと,そのキーボードに対応した文字と,その文字に対応した番号が表示されます.ESCキーを押すと終了します.

kbhit を外部から使うには import kbhit とします。以下は kbhit のサンプルプログラムです。

import kbhit


kb = kbhit.KBHIT()

while True:
    if kb.kbhit():
        c = kb.getch()
        if c == 'a':
            print("a is pushed!")
        if ord(c) == 27:
            break

print("owari")

例えば,上記のプログラムを "kb_test.py" とすると,kbhit.py のあるディレクトリで

python kb_test.py

と実行すると、a のキーを押すと、"a is pushed" というメッセージが現れ、esc キーを押すとプログラムが終了します。

__main__ とは?

"kbhit.py" のプログラムの最後を見ると,

if __name__ == "__main__":

なる記述があります.これはどういう意味でしょう?

Pythonの__name__は、モジュールが直接実行されているか、他のモジュールからインポートされているかを識別するために使用される特別な変数です。

具体的には、__name__には2つの可能な値があります。

1. モジュールが直接実行されている場合:

スクリプトが直接実行されると、name__の値は"__main"になります。

if __name__ == "__main__":
    print("このスクリプトは直接実行されています")

2. モジュールが他のモジュールからインポートされた場合:

他のモジュールがインポートされると、そのモジュールの__name__は、モジュールのファイル名(拡張子を除いた部分)になります。

# モジュールが script.py という名前の場合
import script
print(script.__name__)  # "script" と表示される

この仕組みにより、Pythonのコードを再利用可能にし、直接実行する場合と他のプログラムからインポートして使用する場合で、異なる動作をさせることができます。(以上,ChatGPTの説明)

通常ライブラリの使い方のサンプルが if __name__ == "__main__": を使って書かれていることが多いです.

課題2

前回作成した Wheel クラスと kbhit を使い,

  • 's' が押されたら止まる
  • 'f' が押されたら前進
  • 'b' が押されたら後退
  • 'r' が押されたらその場で右回転
  • 'l' が押されたらその場で左回転

となるプログラムを作成してください。

動作が確認できたら、遠隔操作ができるようにラズパイはロボットの上に乗せ、モバイルバッテリーを電源にして動作させます。(ディスプレイも外します)

そして、ssh を使って macbook からラズパイに接続し、プログラムを実行して、キーボードで動作ができることを確認してみてください。

Flask

次に、スマホからロボットを操作できるようにしてみましょう。そのために python の Webアプリケーションフレームワークである Flask を使います。

まずは Flask を pip でインストールします.

pip install flask

そして,最初のプログラムとして,以下のプログラム hello.py を作成してください.

from flask import Flask

app = Flask(__name__)

@app.route("/test")
def hello_world():
    return "<p>Hello world!</p>"

if __name__ == "__main__":
    app.run(host="127.0.0.1", port=5001, debug=True)

実行は,このプログラムのあるディレクトリで

python hello.py

とします.すると,

$ python hello.py 
 * Serving Flask app "hello" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://127.0.0.1:5001/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 220-515-480

のようにメッセージが出ます。 http://127.0.0.1:5001/test に動作させているコンピュータのブラウザ(Macの場合はMacのブラウザ、ラズパイの場合はラズパイのブラウザ)でアクセスすると,Hello world! と書かれたページが確認できると思います.(Ctl-c でプログラムは終了します)

このように,関数で web ページにアクセスされた時の振る舞いを記述していくのが flask のプログラミングとなります.

課題

上の hello.py を改変して http://127.0.0.1:5001/bye にアクセスしたら,さようなら と出るプログラムを書いてください.

Flask でリモコンを作る

次に flask でボタンを作ってみます. 以下のサンプルプログラムをダウンロードしてください.

まず,webapp.py を実行します.

python webapp.py

このプログラムでは,ボタンが押されると Car クラスの go 関数が実行されます.

よくみると,このボタンを押すたびに画面が遷移していることがわかります. 画面遷移がおこると,それだけ時間がかかりますので,画面遷移をしないように ajax を使います.

ajax とは「JavaScriptとXMLを使って非同期にサーバとの間の通信を行うこと。」です.google map などは画面遷移をせずに,ユーザーからの操作に応じて新しいデータを読み込み,画面を更新していますが,その仕組みに使われています.

これを使ったプログラムが webapp2.py に実行されていますので,これを実行してください.

python webapp2.py

スマホからの接続

"127.0.0.1" の IPアドレスは自分自身のコンピュータを指す特別なIPアドレスです.flask 内の

app.run(host="127.0.0.1", port=5001, debug=True)

app.run(host="0.0.0.0", port=5001, debug=True)

とすることで、作成した flask プログラムは同じ LAN 内であれば他のコンピュータからも接続可能となります.

まず、TC306 の無線環境である tc-room に接続してください。 次に、ラズパイのアドレスを確認してみてください.

ifconfig

さまざまに表示される情報のうち,wlan0 に相当するのが,無線LANになります.

ifconfig -l | xargs -n1 ipconfig getifaddr

のコマンドではIPアドレスだけを取り出すことができます.

ここで得られたアドレスを 172.19.193.xxx とすると,スマホのブラウザで

http://172.19.193.xxx:5001/

のURLを開けることで,flask に接続することができます.

課題

  1. 別のコンピュータ,あるいはスマホからflask プログラムに接続できることを確認してください.
  2. "car.py", "webapp2.py" を編集して,ブラウザからロボットが前進,後退,左右回転,停止ができるようにしてください.
  3. スマホからリモコンで操作できるようにしてください.
  4. ボタンを十字に配置して、リモコンっぽくなるようにインタフェースを工夫してみてください。
    • ChatGPT などを使うと簡単にコードを生成してくれます。