EV3を動かしてみる (3) 〜 変数・関数・繰り返し 〜

ロボティクス入門ゼミ 教材 2017-10-27

変数を使う

変数とは値を入れておくための「箱」で、 プログラムが実行されている時にその値を変更することができる。 変数には、整数型、浮動小数点型、文字列型などいろいろな「型」の値を 格納することができる。 また、pythonではC言語などと違って変数の型を宣言する必要はない (自動で判別してくれる)。

次の例では、move_time という名前を付けた変数を使っている。

#!/usr/bin/env python3
from ev3dev.ev3 import *
from time import sleep

mL = LargeMotor('outA')
mR = LargeMotor('outB')

def motor_init():
    mL.reset()
    mR.reset()

def move_forward(t):
    mL.run_timed(time_sp=t, speed_sp=500, stop_action='brake')
    mR.run_timed(time_sp=t, speed_sp=500, stop_action='brake')
    sleep(t/1000)

if __name__ == '__main__':
    motor_init()
    move_time = 2000            # move_time という変数を定義し2000を代入
    move_forward(move_time)     # move_timeには2000という値が入っている
    sleep(1)
    move_time = move_time/2     # move_time/2 を新たに move_time に代入
    move_forward(move_time)     # このとき move_time には 1000 という値が入っている
    sleep(1)
    move_time = move_time/2
    move_forward(move_time)     # このとき move_time には 1000 という値が入っている

整数や浮動小数点型の変数に対しては、この例のように通常の四則演算ができる (足し算は「+」、引き算は「-」、掛け算は「*」、割り算は「/」)。

また上の例の、 move_time = move_time/2 は move_time /= 2 と書くこともできる。 つまり、/= 2 は、変数の値を 2で割って、その結果を再びその変数に格納する、という意味である。 同様に += , -= , *= も使える。

forを使った繰り返し

上で作成したプログラムを少し改良・変更して、次のような例からスタートする。

#!/usr/bin/env python3
from ev3dev.ev3 import *
from time import sleep

mL = LargeMotor('outA')
mR = LargeMotor('outB')

def motor_init():
    mL.reset()
    mR.reset()
    mL.speed_sp=500
    mR.speed_sp=500
    mL.stop_action='brake'
    mR.stop_action='brake'

def move_forward(t):
    mL.run_timed(time_sp=t)
    mR.run_timed(time_sp=t)
    sleep(t/1000)

def main():
    motor_init()
    move_forward(2000)

if __name__ == '__main__':
    main()

簡単のため、左右のモータのスピード設定値とブレーキモードは motor_init()の中で初期化してある。 また、実際の動作も main() 関数の中で記述し、スクリプトを起動したときに「関数」として実行するようにしてある。

for を使った繰り返しでは、まず「リスト」と呼ばれるデータの集まりを用意し、 その中の要素を1つずつ「ループ変数」に当てはめて繰り返しを実行する。 他の言語の forearch や for each に相当する。 基本的な書式は次の通り。

for ループ変数 in リスト:
    処理
    ...

pythonのリストは、[1,2,3] や ['a','b','c'] のように、 各要素をコンマで区切って全体を [ と ] で囲む。

以下は、上の例の motor_init() の中を for ループを使って簡略したものである。

#!/usr/bin/env python3
from ev3dev.ev3 import *
from time import sleep

mL = LargeMotor('outA')
mR = LargeMotor('outB')

def motor_init():
    for m in [mL,mR]:     # ループ変数mにmLとmRを入れて繰り返す
        m.reset()
        m.speed_sp=500
        m.stop_action='brake'

def move_forward(t):
    mL.run_timed(time_sp=t)
    mR.run_timed(time_sp=t)
    sleep(t/1000)

def main():
    motor_init()
    move_forward(2000)

if __name__ == '__main__':
    main()

for ループの場合も他のブロック同様、for 文の最後に : をつける、ループさせる部分をインデントする、 ということを忘れないように。

次に、回数を指定して繰り返しをさせてみる。

... 以上省略 ...

def main():
    motor_init()
    for i in ['a', 'b', 'c']:
        move_forward(2000)
        sleep(1)

... 以下省略 ...

この例では、ループ変数iに、文字列'a','b','c'がそれぞれ代入されて、 move_forward(2000)とsleep(1)が繰り返される。 実はこのループの中では、i というループ変数は一切使われていない。 つまり、単に3回繰り返すだけであれば、3つの要素を持つリストなら何でもよい。 が、通常は次のように数字のリストの方が簡単に書ける。

... 以上省略 ...
  
def main():
    motor_init()
    for i in [0,1,2]:
        move_forward(2000)
        sleep(1)

... 以下省略 ...

もちろん [0,1,2]の代わりに [1,1,1] と書いても [6,4,2] と書いても [0,'x','abc'] と書いても同じ動きをする (pythonのリストは、整数も文字列も一緒にリストの要素にできる)。

数字の並びの場合は、range()という関数を使って書くこともできる。 さらに、この例のようにループ変数がダミーの場合には、変数名として dummy や _ (単なるアンダースコア)が使われることがよくある。

... 以上省略 ...
  
def main():
    motor_init()
    for _ in range(3):         # range(3) は [0,1,2]
        move_forward(2000)
        sleep(1)

... 以下省略 ...

range()は連続した数字を要素としてもつリストを作成ための関数で、 始まりと終わりや、ステップを指定することもできる。 上の例では、range(0,3) あるいは、range(0,3,1)と書いても同じである (0から始まって3未満の整数まで)。

実際にループ変数にどのような値が入っているのか、画面に表示させてみる。

... 以上省略 ...
  
def main():
    motor_init()
    for i in range(2,10,3):         # range(2,10,3) は [2,5,8]
        print(i)                    # iの値を画面に表示
        move_forward(2000)
        sleep(1)

... 以下省略 ...

【練習問題】0.5秒ごとにスピードを 0,200,400,600,400,200,0,-200,-400,-600,-400,-200,0 と変化させて動くロボットを作りなさい。

whileを使った繰り返し

ある条件を満たしている間だけ処理を繰り返したい場合は、while を使う。

基本的な書式は次の通り。

while 条件:
    処理
    ...

前節の例を while を使って書いてみる。 そのためには、1回繰り返すごとに1増える変数(カウンタ)を用意して、 この変数が指定した値を超えない間だけ処理を繰り返す。

... 以上省略 ...
  
def main():
    motor_init()
    i=0                     # 繰り返しの回数を数える変数を用意
    while i<3 :             # i<3 の間繰り返す
        move_forward(2000)
        sleep(1)
        i+=1                # iを1だけ増やす ( i = i+1 と同じ )

... 以下省略 ...