
本講習会を受講している中学生の塩谷和紀さんがプログラムの作例を書いてくれました。
以下で紹介します。
=====================
Pythonで制作した加減速とジャイロのプログラムをベースに、小学生の皆さんにも使いやすいspike3のワードブロックで加減速のプログラム、ジャイロのプログラムを作りました!ぜひ試してみてください。
〔加減速のプログラム〕
from hub import port,motion_sensor
import motor_pair,motor,color_sensor,math,runloop,time
# ------------------------------
# 初期化(ポート等は環境に合わせてください)
motor_pair.pair(motor_pair.PAIR_1,port.A,port.E)
# ------------------------------
# 定数・設定パラメータ
# ------------------------------
TARGET_REFLECTION = 40.0# 目標反射率(環境に合わせて調整)#(黒の反射-白の反射光)/2
ANGLE = 1
KP = 0.2 #Pの定数
KI = 0.005 #Iの定数
KD = 0.01 #Dの定数
MIN_SPEED = 300# 最低速度
MAX_SPEED = 700# 最高速度
ACC_DISTANCE = 3# 加速区間(cm)
DEC_DISTANCE = 5# 減速区間(cm)
TOTAL_DISTANCE = 100.0# 今回は100cm走行
WHEEL_CIRCUMFERENCE = 11.3# ホイールの円周(cm)
speed=500
# ------------------------------
# エンコーダの開始時の値を記録
# ------------------------------
left_initial = motor.relative_position(port.A)
right_initial = motor.relative_position(port.E)
def get_distance_traveled():
#左右のモーターのエンコーダの変化平均から進んだ距離(cm)を計算する
left_delta = abs(motor.relative_position(port.A) - left_initial)
right_delta = abs(motor.relative_position(port.E) - right_initial)
avg_delta = (left_delta + right_delta) / 2.0
return (avg_delta / 360.0) * WHEEL_CIRCUMFERENCE
def smooth_speed(distance,total_abs_distance,max_speed,min_speed,acc_distance,dec_distance):
"""
コサイン補間を用いて、加減速区間のスムーズな速度変更を実現する
"""
remaining = total_abs_distance - distance
if distance < acc_distance:
safe_ACC = acc_distance if acc_distance != 0 else 0.01
ratio = distance / safe_ACC
cos_interp = (1 - math.cos(math.pi * ratio)) / 2
speed = min_speed + (max_speed - min_speed) * cos_interp
elif remaining < dec_distance:
safe_DEC = dec_distance if dec_distance != 0 else 0.01
ratio = 1 - remaining / safe_DEC
cos_interp = (1 - math.cos(math.pi * ratio)) / 2
speed = min_speed + (max_speed - min_speed) * (1 - cos_interp)
else: #いままでの場合でないなら(加速終了&減速前)
speed = max_speed #スピードを最高速度にする
print(speed)
return int(speed) #今のスピードを整数にして値を返す
async def run(total_distance=TOTAL_DISTANCE,max_speed=MAX_SPEED,min_speed=MIN_SPEED,acc_distance=ACC_DISTANCE,dec_distance=DEC_DISTANCE):
"""
ライントレース処理を一つの関数としてまとめています。
カラーセンサによるPID制御と、コサイン補間を用いた加減速により
指定距離(total_distance)走行します。また以下の実装では、目標のループ周期を一定(0.02秒)に固定しています。
"""
direction = 1 if total_distance >= 0 else -1
total_abs_distance = abs(total_distance)
global left_initial, right_initial
# 開始時のエンコーダ値を再取得
left_initial = motor.relative_position(port.A)
right_initial = motor.relative_position(port.E)
# 目標ループ周期(秒)
target_period = 0.01
while get_distance_traveled() < total_abs_distance: #リセットしたエンコーダ値のところから何㎝動いたかみてrun()で進みたい距離を超えるまで繰り返す
loop_start_time = time.ticks_ms()
current_time = time.ticks_ms()
dt = current_time - loop_start_time
if dt == 0:
dt = 0.01# 念のための値#もし値時間の差が0秒だった場合dtに0.01を代入する(割り算にエラーが出るので0,01にしている
current_distance = get_distance_traveled()
base_speed = smooth_speed(current_distance,total_abs_distance,max_speed,min_speed,acc_distance,dec_distance)
drive_speed = direction * base_speed
# モーター動作開始
motor_pair.move(motor_pair.PAIR_1,0,velocity=drive_speed)
print(drive_speed)
# ループ周期を一定にするための待機
loop_elapsed = time.ticks_ms() - loop_start_time#今の時刻-ループ初めの時刻→loop_elapsedに代入(1周に何秒かかったか調べる)
sleep_time = target_period - loop_elapsed#目指している1周のループタイム-1周にかかった時間→sleep_timeに代入(目標のタイムからどれくらいずれているか)
if sleep_time > 0:#もし目標タイムからのずれが0秒以上あるなら...(目標より早い→待つ、目標より遅い→すぐい次のループ)
time.sleep(sleep_time)#目標タイムのずれの分待つ
motor_pair.stop(motor_pair.PAIR_1)#モーターを止める
async def main():
await run(100,700,300,10,10)
runloop.run(main())
このプログラムは直進しながら加速し、じょじょに減速するというプログラムです。加減速することで、機体のブレが減り、安定した走行ができるようになります。
<使い方>
runというマイブロックがあり、その値を変えることで進みたい距離、加減速距離、最高スピード、最低スピードを変えることができます。
run(進みたい距離 ,最高速度 ,最低速度 ,加速距離 ,減速距離)
