今回は、mBot2プログラミングシリーズ(Python編)の第4回です。
この回では、クアッドRGBセンサーを活用して、ラインに沿って自動運転する(ライントレース)プログラムを作成します。
ライントレースの動きは、倉庫内の仕分けロボットや配送ロボットの仕組みにも似ており、実社会での応用例をイメージしながら学ぶことができます。

ライントレース用の黒色ラインの作成には、反射の少ない黒色マスキングテープがお勧めです。
(黒色マジックペンでは、反射してセンサーが黒色を認識しないことがあります)
全講座の一覧はこちら
目標
- クアッドRGBセンサーの仕組みを理解する。
 - クアッドRGBセンサーに関するAPIを理解する。
 - ラインを検知してライントレースするプログラムを作成する。
 
Python環境(mBlock Python editor)の立ち上げ
ここでは、『mBlock Python editor』を使って、Pythonコードでプログラミングしていきます。
事前にPython環境を導入しておいてください。
環境の導入に関しては、次の記事を参考にしてください。
ライントレースとは
ライントレースとは、地面に描かれたライン(通常は黒や白)をセンサーを使って検知し、そのラインに沿ってロボットを走らせる技術です。
mBot2のような教育用ロボット、自動車の高速道路での自動運転や、物流システムの自動化などの分野で広く利用されています。
クアッドRGBセンサーとは
クアッドRGBセンサーは、赤(Red)、緑(Green)、青(Blue)の光を使って色を識別するセンサーです。
mBot2に搭載されたこのセンサーは、4つの独立したRGBセンサーが一列に並んでおり、それぞれが個別に色と明るさを測定します。

上の図の黒っぽい丸の部分がクアッドRGBセンサーで、左から「L2」「L1」「R1」「R2」となります。
その下の白っぽい丸4つが『フィルライト』で、赤(Red)、緑(Green)、青(Blue)の光を発することができます。
これは、センサーが常に正確な色識別と明るさ測定を行えるようにするための重要な役目があります。
クアッドRGBセンサーに関するAPIは、使用用途に応じて、次の6つに分類できます。
今回は1~3のライントレースでの使い方を解説します。
※4~6は次回解説します。
- 【初級】L1とR1(中央の2つのセンサー)でライントレースする場合
 - 【中級】4つのセンサー値でライントレースする場合
 - 【上級】『偏差』を用いてライントレースする場合
 
- フィルライトの色を発光させる場合
 - 色を認識させる場合
 - キャリブレーションする場合
 
APIとは
API(Application Programming Interface)は、ソフトウェアやハードウェアが外部のプログラムとやり取りをするためのインターフェース(接点)です。
簡単に言うと、『決められたルールに従って機能を利用するための仕組み』です。
cyberpiライブラリをインポートすることで、CyberPiや、mBot2、センサーなどの各機能を簡単に利用できます。
【初級】L1とR1(中央の2つのセンサー)でライントレースする場合
L1とR1に関するPython API
quad_rgb_sensor.get_line_sta("middle", index = 1)    #線の識別quad_rgb_sensor.get_ground_sta("middle", index = 1)  #背景の識別L1,R1センサーの値を返します。
- 範囲:00から11までの2進数に対応する0~3の範囲の整数
- 0:線または背景を識別しない
 - 1:線または背景を識別する
 
 
| センサー値 | 2進数 | 線の検出状態 | 
|---|---|---|
| 0 | 00 | ![]()  | 
| 1 | 01 | ![]()  | 
| 2 | 10 | ![]()  | 
| 3 | 11 | ![]()  | 
左右のセンサー値を0,1で並べて、2進数としてみた時の値が0~3となります。
L1,R1センサー値の動作確認
『クアッドRGBセンサー(L1,R1)の値を、CyberPiのディスプレイ上に常時モニタリングする』プログラムを作ってみます。
import cyberpi
while 1:
    cyberpi.table.add(1,1,"L1,R1")
    cyberpi.table.add(1,2,cyberpi.quad_rgb_sensor.get_line_sta("middle",1))クアッドRGBセンサー(L1,R1)の値を、テーブルの1行目に表示させるプログラムです。
CyberPiのディスプレイ表示に関するAPIの詳細は、以下の記事に書いています。
下の写真は、L1が黒(線)、R1が白(背景)の時にセンサー値が2を示しているところです。
検出する色の設定を変更したり、検出する場所を変えたりして、値の変化を確認してみてください。

例題1:L1とR1(中央の2つのセンサー)でライントレース
- 例題
 - 解答例
 
L1とR1のセンサー値を使って『黒いラインの上をライントレースさせる』プログラムを作ってみましょう。
センサーの値による動作は次の通りとします。
- 左右ともライン上の場合:直進
 - 左がラインから外れた場合:右回転
 - 右がラインから外れた場合:左回転
 - 左右ともラインから外れた場合:後退
 
mBot2のモーター制御に関するAPIの詳細は、以下の記事に書いています。
from cyberpi import mbot2,quad_rgb_sensor,event
@event.is_press("b")
def callback():
    while 1:
        sta = quad_rgb_sensor.get_line_sta("middle",1)
        
        if sta == 0:
            mbot2.backward(50)
        elif sta == 1:
            mbot2.turn_right(50)
        elif sta == 2:
            mbot2.turn_left(50)
        elif sta == 3:
            mbot2.forward(50)Bボタンを押したときのイベントで動作するようにしています。
L1,R1のセンサー値をローカル変数に代入し、その変数を用いて、0~3の時のmBot2の動作を定義します。
CyberPiのイベント駆動に関するAPIの詳細は、以下の記事に書いています。
【中級】4つのセンサーでライントレースする場合
4つのセンサー(L2~R2)に関するPython API
quad_rgb_sensor.get_line_sta("all",index = 1)      #線の識別quad_rgb_sensor.get_ground_sta("all",index = 1)    #背景の識別L2,L1,R1,R2の4つセンサーの値を返します。
- 範囲:0000から1111までの2進数に対応する0~15の範囲の整数
- 0:線または背景を識別しない
 - 1:線または背景を識別する
 
 
| センサー値 | 2進数 | 線の検出状態 | 
|---|---|---|
| 0 | 0000 | ![]()  | 
| 1 | 0001 | ![]()  | 
| 2 | 0010 | ![]()  | 
| 3 | 0011 | ![]()  | 
| 4 | 0100 | ![]()  | 
| 5 | 0101 | ![]()  | 
| 6 | 0110 | ![]()  | 
| 7 | 0111 | ![]()  | 
| 8 | 1000 | ![]()  | 
| 9 | 1001 | ![]()  | 
| 10 | 1010 | ![]()  | 
| 11 | 1011 | ![]()  | 
| 12 | 1100 | ![]()  | 
| 13 | 1101 | ![]()  | 
| 14 | 1110 | ![]()  | 
| 15 | 1111 | ![]()  | 
4つのセンサー値を0,1で並べて、2進数としてみた時の値が0~15となります。
L2,L1,R1,R2センサー値の動作確認
『クアッドRGBセンサー(L2,L1,R1,R2)の値を、CyberPiのディスプレイ上に常時モニタリングする』プログラムを作ってみます。
import cyberpi
while 1:
    #1行目 L1,R1
    cyberpi.table.add(1,1,"L1,R1")
    cyberpi.table.add(1,2,cyberpi.quad_rgb_sensor.get_line_sta("middle",1))
    
    #2行目 L2,L1,R1,R2
    cyberpi.table.add(2,1,"L2~R2")
    cyberpi.table.add(2,2,cyberpi.quad_rgb_sensor.get_line_sta("all",1))クアッドRGBセンサー(L2,L1,R1,R2)の値を、テーブルの2行目に表示させるプログラムです。
下の写真は、センサー値が12を示しているところです。
検出する色の設定を変更したり、検出する場所を変えたりして、値の変化を確認してみてください。

例題2:4つのセンサーでライントレース
- 例題
 - 解答例
 
L2,L1,R1とR2の4つのセンサー値を使って『黒いラインの上をライントレースさせる』プログラムを作ってみましょう。
4つのセンサー値の組み合わせは全部で16通りあります。
様々なライントレースのパターンが考えられますので、自由に考えてみてください。
from cyberpi import mbot2,quad_rgb_sensor,event
@event.is_press("b")
def callback():
    while 1:
        sta = quad_rgb_sensor.get_line_sta("all",1)
        
        if sta == 8:
            mbot2.turn_left(50)
        elif sta == 1:
            mbot2.turn_right(50)
        else:
            mbot2.forward(50)上記はあくまでも一例です。
あらかじめL2,R2が線をまたいで置かれている前提のプログラムです。
プログラムの内容は次の通りです。
・センサー値が『8』:左端のL2のみライン上にある時は左回転
・センサー値が『1』:右端のR2のみライン上にある時は右回転
・どちらにも当てはまらない時は前進

【上級】『偏差』を用いてライントレースする場合
『偏差』に関するPython API
quad_rgb_sensor.get_offset_track(index = 1)クアッドRGBセンサーが、ラインからどれだけ逸脱しているか(偏差)を取得します。
- 範囲:-100~100
 
-100:センサーがラインの左側にある
 100:センサーがラインの右側にある

『偏差』の動作確認プログラム
『偏差の値を、CyberPiのディスプレイ上に常時モニタリングする』プログラムを作ってみます。
import cyberpi
while 1:
    #1行目 L1,R1
    cyberpi.table.add(1,1,"L1,R1")
    cyberpi.table.add(1,2,cyberpi.quad_rgb_sensor.get_line_sta("middle",1))
    
    #2行目 L2,L1,R1,R2
    cyberpi.table.add(2,1,"L2~R2")
    cyberpi.table.add(2,2,cyberpi.quad_rgb_sensor.get_line_sta("all",1))
    #3行目 偏差
    cyberpi.table.add(3,1,"L2~R2")
    cyberpi.table.add(3,2,cyberpi.quad_rgb_sensor.get_offset_track(1))偏差の値を、テーブルの3行目に表示させるプログラムです。
下の写真は、ラインの右側にmBot2を置いた場合です。
偏差が+60付近を示していることが分かります。

ライントレースに『偏差』を使う方法
『偏差』を使ってライントレースさせる流れを解説していきます。
- ライン上での速度『基準速度』の決定
 - 偏差が生じた時の『左右のタイヤ速度の調整量』の決定
 - 『基準速度』-『調整量』をプログラムする
 
順に解説します。
- まず、偏差がゼロ(ライン上)の時の『基準速度』を決めます。
最大速度は200RPMです。
調整量により、速度を増やす可能性があることを考慮し、ここでは100RPMとします。base_spd = 100 
- 次に、偏差が生じた時のタイヤ速度の『調整量』を決めます。
左にズレた時は、左タイヤの速度を増やし、右タイヤの速度を減らすことで、右回転する方向に動かします。
逆に、右にズレた時は、左タイヤの速度を減らし、右タイヤの速度を増やします(左回転)。
その調整量は、線から離れるほど大きく、線に近づくほど小さくするため、『偏差』の情報を調整量に用います。kp * quad_rgb_sensor.get_offset_track(1)
「Kp」を偏差にかけることで、速度を微調整します。 - 最後に、『基準速度』-『調整量』をタイヤ速度に設定します。
まず左タイヤについて考えます。
mBot2が右にズレたとき、左回転させるために、左のタイヤを減速させる必要があります。
右にズレると偏差は正になるため、左タイヤ速度を『基準速度』-『Kp×偏差(=調整量)』とすることで、ラインへの追従が可能となります。base_spd - (kp * quad_rgb_sensor.get_offset_track(1))
この式を左タイヤ速度に決定します。left_spd = base_spd - (kp * quad_rgb_sensor.get_offset_track(1))
Kpの調整法は様々ですが、試行錯誤的に調整すれば良いでしょう。
たとえば、Kp=1のとき、偏差=100であれば、『基準速度100RPM-調整量100』で速度はゼロとなります。
この調整が大きすぎる場合は、Kp=0.5として、『基準速度100RPM-調整量50(=0.5×100)』で速度は50となります。
逆に、Kp=0.1では『基準速度100RPM-調整量10(=0.1×100)』で速度は90となり、これでは調整が小さすぎるかもしれません。
様々な値を設定してみて、動作を確認してみてください。 
例題3:『偏差』を用いてライントレース
- 例題
 - 解答例
 
以下のプログラムは、『偏差』を用いたライントレースプログラムです。
Kpと右タイヤ速度を決定して、ライントレースできるようにしましょう。
from cyberpi import mbot2,quad_rgb_sensor,event
@event.is_press("b")
def callback():
    base_spd = 100  #基準速度
    kp = 「例題」    #Kp
    while 1:
        #左タイヤ速度
        left_spd = base_spd - (kp * quad_rgb_sensor.get_offset_track(1))
        
        #右タイヤ速度
        right_spd = 「例題」
        #左右タイヤを個別に制御        
        mbot2.drive_speed(left_spd, right_spd)from cyberpi import mbot2,quad_rgb_sensor,event
@event.is_press("b")
def callback():
    base_spd = 100  #基準速度
    kp = 0.8        #Kp
    while 1:
        #左タイヤ速度
        left_spd = base_spd - (kp * quad_rgb_sensor.get_offset_track(1))
        
        #右タイヤ速度
        right_spd = - base_spd - (kp * quad_rgb_sensor.get_offset_track(1))
        #左右タイヤを個別に制御        
        mbot2.drive_speed(left_spd, right_spd)右タイヤ速度は、左タイヤとは正負が逆になることに注意が必要です。
(『調整量』の正負は同じです)
Kpの解答例はあくまでも一例です。
コースに応じて、基準速度とKpは調整が必要となってきますので、その都度、適切な値を導き出すようにしてください。
突如現れた『Kp』ですが、これには意味があります。
偏差を使って制御をおこなう方法に、『PID制御』というものがあります。
・P制御:『偏差』に比例して、操作量を変化させる制御
・I制御:『偏差』の積分値に比例して、操作量を変化させる制御
・D制御:『偏差』の微分値に比例して、操作量を変化させる制御
この3つを組み合わせたものがPID制御です。
そして、それぞれの微調整要素が、
・Kp:比例ゲイン
・Ki:積分ゲイン
・Kd:微分ゲイン
となります。
今回は、PID制御におけるP(比例)制御をおこなった形です。
話せば長くなりますので、ご興味のある方は『PID制御』を調べてみてください。
まとめ
今回は、クアッドRGBセンサーを使ったライントレースについて、3種類の方法を解説しました。
コースによって、3種類の方法を使い分けることで、効率的にプログラミングすることできます。
また、『偏差』を用いたプログラムでは、今回は比例制御を実施しましたが、PID制御を用いることで、より高度な制御が可能となりますので、是非挑戦してみてください!
次回は、今回説明しきれなかった、クアッドRGBセンサーでの色の定義やキャリブレーションについて解説します。
mBlockを使ったmBot2のプログラミング方法を丁寧に解説していておススメです。
CyberPi単体でもプログラミング教育に非常に役立ちます!

  
  
  
  
					





					
					















					
					
					