Raspberry Piのマルチコア並列処理でロボットを制御する

  • URLをコピーしました!

今回は先日記事にしたRaspberry Piのマルチコア、マルチプロセスによる並列処理で実際にロボットを制御してみたいと思います。言語はPythonになります。

目次

並列処理でやりたいこと

これまで当ブログで、Raspberry Piをコントローラーとして動作するスパイダーロボット、PiCrawlerのサーボモータの制御や画像処理をするアプリケーションを紹介してきました。
今までは機能ごとにアプリケーション単体で動かしていましたが、個々の機能がある程度仕上がってきたため、それらの機能を同時に動かしたいと思っています。

通常の組み込み処理では機能ごとの優先度を決め、高優先の処理が空いている時間に低優先の処理を実行するなどのタスク管理をして複数の機能を動作させます。
しかし、Raspberry PiはCPUコアが4つあり、別々のコアで物理的に並列に処理を実行できますので、そのマルチコアを活かして制御と画像処理を両立させてみたいと思います。

動作環境

ハードウェア:Raspberry Pi 3 ModelB
OS:Raspbian 10.11
OpenCV:4.1.0.25
カメラ:OV5647

使用するロボット

当ブログではおなじみのPiCrawlerです。詳細は以下のページで解説しています。

マルチコア、マルチプロセスによる実装方法

Raspberry Piのマルチコアを利用して実際に並列処理をする方法は、以前の記事で紹介しています。

作成したソースコード

今回作成したPythonのソースコードは以下の通りです。
ロボットをその場で回転させる制御プログラムと、カメラモジュールで撮影した映像を表示する画像処理プログラムを、別々のプロセスで同時に実行します。

from picrawler import Picrawler
from time import sleep
import sys
import tty
import termios
import multiprocessing as mp
import cv2

#カメラ初期化
#VideoCaptureオブジェクト取得
cap = cv2.VideoCapture(-1)

#ロボット初期化
crawler = Picrawler([10,11,12,4,5,6,1,2,3,7,8,9])

#ロボットの動作速度
speed =100

#UI文字列
manual = '''
Press keys on keyboard to control PiSloth!
    W: Forward
    A: Turn left
    S: Backward
    D: Turn right
'''

#ロボットサーボ制御
def robot_ctl(q):

    print(manual)
    while True:
        key = "A"
        print(key)
        if 'w' == key or 'W' == key:
            crawler.do_action('forward',1,speed)
        elif 's' == key or 'S' == key:
            crawler.do_action('backward',1,speed)
        elif 'a' == key or 'A' == key:
            crawler.do_action('turn left',1,speed)
        elif 'd' == key or 'D' == key:
            crawler.do_action('turn right',1,speed)
        elif chr(27) == key:# 27 for ESC
            break
        sleep(0.05)
        
    #終了メッセージ    
    print("End robot_ctl Process")
    
#カメラ制御
def cam_ctl(q):

    while(True):
        #フレームを取得
        ret, frame = cap.read()
        
        #画面サイズを指定
        frame = cv2.resize(frame, (640, 480))
        
        #取得したフレームをウインドウ上に表示する
        cv2.imshow("frame", frame)
        
        #キーボード入力処理
        key = cv2.waitKey(1)
        if key == 13: #enterキーの場合処理を抜ける
            break
            
    #カメラデバイスクローズ
    cap.release()
    
    #ウィンドウクローズ
    cv2.destroyAllWindows()
    
    #終了メッセージ
    print("End cam_ctl Process")
    
    
if __name__ == "__main__":
    #キューの生成
    queue = mp.Queue()
    
    #プロセス生成
    ps_control = mp.Process(target=robot_ctl, args=(queue,))
    ps_cam = mp.Process(target=cam_ctl, args=(queue,))    
    
    #プロセスのスタート
    ps_control.start()
    ps_cam.start()

27行目:
サーボモーターの制御メソッドです。

50行目:
カメラモジュールの制御メソッドです。

81~82行目:
サーボ、カメラそれぞれの制御メソッドのプロセスを生成します。

84~85行目:
プロセスを実行します。

動作確認

作成したプログラムをロボットのRaspberry Piで実行した動画です。
ロボットが回転しながら、カメラモジュールの画像を表示することができました。動画の前半がロボットの動作、後半がロボットのカメラで取り込んだ映像を映している様子です。

まとめ

マルチプロセスで動作するプログラムを作成することで、ロボットに複数の動作を同時にさせることができるようになりました。今後はこの処理をさらに拡張して、ディープラーニングでリアルタイムに物体認識をさせながら、認識したオブジェクトに向かって移動する、といった動作をさせられるようにする予定です。

また、Pythonのプログラミングについてさらに深く学びたい方にはUdemyの以下の講座がおすすめです。

Raspberry PiとPythonでIoTはじめの一歩~IoTキッチンガーデン講座~ icon



それでは、また次の記事でお会いしましょう。

よかったらシェアしてね!
  • URLをコピーしました!
目次