7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ラズパイにて、ラジコンカーを自作する-その3

Last updated at Posted at 2020-03-15

はじめに

ラズベリーパイにて、自作のラジコンカーをつくったので紹介します。
今回は、ネットワーク越しのラジコン制御になります。

output_img_0008.gif

ラジコンカー関連の記事

紹介する内容

  • ラズパイ側のwebサーバ側の作成
  • 外部PCからの制御
  • iPhone(Pythonista)からの制御

作るものの全体

rajikon-qiita3.png

ラズパイ側のサーバーおよび外部制御プログラムです。

作業環境

  • ラズベリーパイ3
    • Raspbian Buster with desktop and recommended software
      • Version:February 2020
      • Release date:2020-02-13
      • Kernel version:4.19
      • Python3.7.3
  • ホストPC
    • windows10 64bit
      • Python3.7.4
  • iPhone
    • Pythonista

作業手順

今回も、すべてPythonで実装します。
まずは、ラズパイ側のサーバを作ります。
※動く程度のものなので、書き方として間違っている場合があります

ラズパイ側のサーバ - responder

Python WebFrameworkである[responder]を使用します。
responder自体の記事は、
人間のためのイケてるPython WebFramework「responder」、そして作者のKenneth Reitzについて
がすごくわかりやすいです。

注意点として、responderは、python3.6.1以上でないと動作しません。
Raspbianの古いものは、python3.5がインストールされていたかと思います。
必要に応じて、アップデートしてください。

responderのインストール

$ pip install responder

以上。

サーバー側の仕様

以下のような動作にします。

  • 送信側
    • GETリクエスト : http://[ラズパイIPアドレス]:5042/pi_car/[動作コマンド]
  • 受信側
    • レスポンス : "ok [動作コマンド]!"

具体例は、以下の通りです。

サーバー側のコード

前回記事のコードはそのまま使用します。
ファイル構成は、下記のとおりです。

$ ls
picar.py  rc_server.py  ta7291p.py

コードは以下となります。

ファイル名:rc_server.py

import responder
import picar

api = responder.API()
pi_car = picar.PiCar()

@api.route("/picar/{prm}")
def control_picar(req, resp, *, prm):

    if "turn_left" in prm:
        pi_car.turn_left()
    if "turn_right" in prm:
        pi_car.turn_right()
    if "forward" in prm:
        pi_car.forward()
    if "back" in prm:
        pi_car.back()
    if "brake" in prm:
        pi_car.brake()
    if "acceloff" in prm:
        pi_car.acceloff()
    if "debug_proc" in prm:
        pi_car.debug_proc()

    resp.text = f"ok, {prm}!"


@api.route("/picar/speed/{prm}")
def control_picar_speed(req, resp, *, prm):
    pi_car.speed(int(prm))
    resp.text = f"ok_speed, {prm}!"


if __name__ == '__main__':
    api.run(address='0.0.0.0', port=5042)

※address='0.0.0.0'は、外部アクセス可とするため

実行と動作確認

実行は下記のとおりです。

$ python rc_server.py 
INFO:     Started server process [3392]
INFO:     Uvicorn running on http://0.0.0.0:5042 (Press CTRL+C to quit)
INFO:     Waiting for application startup.
INFO:     Application startup complete.

外部PCより、GETリクエストをなげて確認します。
※本環境では、chromeを使用しました。

  • 外部PC - 送信側

    • chromeのアドレスバーに以下を入力し、実行
    http://192.168.11.29:5042/picar/forward
    
    • 302.PNG
  • ラズパイ側

    • 下記のログが表示される
INFO:     192.168.11.17:63850 - "GET /picar/forward HTTP/1.1" 200 OK
forward : run
forward : over
  • →ラジコンカーが前進する

以上でサーバ側の動作は完了です。

クライアント側(ホストPC)

GETのリクエストを投げるだけなので、さらっと。

コード

以下がコードとなります。
※IPアドレスは必要に応じて変更してください。

ファイル名:car_test.py

import requests
import time

url = 'http://192.168.11.29:5042/picar/'
cmds = ["forward", "back", "brake", "turn_left", "turn_right", "acceloff"]

def main():
    for cmd in cmds:
        curl = url + cmd
        print(cmd)
        response = requests.get(curl)
        time.sleep(3)


if __name__ == '__main__':
    main()

実行

> python .\car_test.py
forward
back
brake
turn_left
turn_right
acceloff

前進→バック→ブレーキ→左旋回→右旋回→→停止
の順に動作したかと思います。

クライアント側(iPhone)

せっかくラジコンをつくったので、やっぱり手元で手軽に動かしたいです。
今回は、iPhoneからPython経由で制御します。

Pythonistaについて

Pythonista は、iOS上で動作するPythonの統合開発環境です。
有料アプリではありますが、とても気に入っています。
Pythonistaの詳細は、下記の記事が参考になります。

iPhoneでiPhoneアプリを作ろう

AppStoreでのアイコンは以下です。

302_1.png

UIと動作仕様

UIは以下となります。
303.png

  • [forward]のボタンをタップ -> ラジコン前進
  • [back]のボタンをタップ -> ラジコンバック
  • [turn_left]のボタンをタップ -> ラジコン左旋回
  • [turn_right]のボタンをタップ -> ラジコン右旋回
  • [acceloff]のボタンをタップ -> ラジコン停止

早速コードに移ります。

コード

以下がコードとなります。

ファイル名:car_remo.py

from objc_util import *
import ui
import console

import requests
import time

url = 'http://192.168.11.29:5042/picar/'

def btn_turn_left_tapped(sender):
    curl = url + "turn_left"
    response = requests.get(curl)

def btn_turn_right_tapped(sender):
    curl = url + "turn_right"
    response = requests.get(curl)

def btn_forward_tapped(sender):
    curl = url + "forward"
    response = requests.get(curl)

def btn_brake_tapped(sender):
    curl = url + "brake"
    response = requests.get(curl)

def btn_back_tapped(sender):
    curl = url + "back"
    response = requests.get(curl)

def btn_acceloff_tapped(sender):
    curl = url + "acceloff"
    response = requests.get(curl)


def main():
    # メイン画面の作成
    main_view = ui.View(frame=(0, 0, 375, 667))
    main_view.name = 'test view'
    main_view.background_color = ('white')

    width_unit = main_view.width // 4
    height_unit = main_view.width // 4

    # ボタンの追加
    btn_forward = ui.Button()
    btn_forward.frame = (1*width_unit, 0*height_unit, width_unit, height_unit)
    btn_forward.title = 'forward'
    btn_forward.action = btn_forward_tapped
    btn_forward.background_color = (0, 0, 0, 0.5)
    btn_forward.tint_color = ('white')
    main_view.add_subview(btn_forward)

    # ボタンの追加
    btn_acceloff = ui.Button()
    btn_acceloff.frame = (1*width_unit, 1*height_unit, width_unit, height_unit)
    btn_acceloff.title = 'acceloff'
    btn_acceloff.action = btn_acceloff_tapped
    btn_acceloff.background_color = (0, 0, 0, 0.5)
    btn_acceloff.tint_color = ('white')
    main_view.add_subview(btn_acceloff)

    # ボタンの追加
    btn_back = ui.Button()
    btn_back.frame = (1*width_unit, 2*height_unit, width_unit, height_unit)
    btn_back.title = 'back'
    btn_back.action = btn_back_tapped
    btn_back.background_color = (0, 0, 0, 0.5)
    btn_back.tint_color = ('white')
    main_view.add_subview(btn_back)

    # ボタンの追加
    btn_turn_left = ui.Button()
    btn_turn_left.frame = (0*width_unit, 1*height_unit, width_unit, height_unit)
    btn_turn_left.title = 'turn_left'
    btn_turn_left.action = btn_turn_left_tapped
    btn_turn_left.background_color = (0, 0, 0, 0.5)
    btn_turn_left.tint_color = ('white')
    main_view.add_subview(btn_turn_left)

    # ボタンの追加
    btn_turn_right = ui.Button()
    btn_turn_right.frame = (2*width_unit, 1*height_unit, width_unit, height_unit)
    btn_turn_right.title = 'turn_right'
    btn_turn_right.action = btn_turn_right_tapped
    btn_turn_right.background_color = (0, 0, 0, 0.5)
    btn_turn_right.tint_color = ('white')
    main_view.add_subview(btn_turn_right)

    main_view.present('sheet')
    main_view.wait_modal()

if __name__ == '__main__':
    main()

実行

iPhone - PythonistaのUIよりプログラムを実行します。

305.PNG

UIが起動しますので、各ボタンをタップして確認します。
303.png

さいごに

とりあえず、イメージした動きになってよかったです。
余裕があれば、カメラを搭載して、自動で動作するようにしたいです。
あと、ラズパイゼロ or ESP32に置き換えて、完全コードレスにしようと思います。

参考

7
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?