検索コード

コース レッスン9/10: Raspberry Pi Pico 4WDスマートカーを使用した障害物回避

このレッスンはの一部です: Raspberry Pi Pico 4WDスマートカー

コース レッスン9/10: Raspberry Pi Pico 4WDスマートカーを使用した障害物回避

はじめに

このガイドは、Robojaxのコースレッスン9/10に基づき、SunFounder Raspberry Pi Pico 4WDスマートカーキットを使用して障害物回避ロボットを構築する方法を説明します。このプロジェクトは、サーボ駆動の超音波センサーとモーター制御を組み合わせ、環境を自律的に移動できるロボットを作り出します。センサーをレーダーのようにスイープさせることで、車は障害物を検出し、進むべき明確な経路をインテリジェントに選択します。これは、ロボット工学、センサー統合、自律ナビゲーションへの完璧な入門となります。

Sunfounder_Pico4DW-09-Obstacle-avoidance 床に障害物を置いたセットアップ

このプロジェクトは単なるおもちゃではなく、多くの実用的なアプリケーションの基盤です。以下に、あなたを刺激するいくつかのアイデアを示します:

  • 自律探査ロボット:人間の介入なしに部屋や屋外エリアをマッピングして探索できるロボットを構築します。
  • スマート掃除機:同じ原理を使用して、掃除中に家具や壁を回避しながら部屋を移動するロボットを作成します。
  • 警備パトロールボット:車を周囲のパトロール用にプログラムし、超音波センサーを使用して予期しない障害物や侵入を検出して報告します。
  • AIの教育プラットフォーム:このプロジェクトを足がかりとして、経路探索やSLAM(自己位置推定と地図作成)などのより複雑なアルゴリズムを学びます。

このレッスンでは、車が意思決定を行うためのコアロジックとコードに焦点を当てます。車はサーボモーターを使用して超音波センサーを回転させ、レーダーとして機能して0度から180度までの距離を測定します。コードはこのデータを分析して最も広い空き経路を見つけ、それに応じて車を前進、左折、または右折させます。ビデオでは、個々のコンポーネントのテストから、実際の迷路での最終的な障害物回避アルゴリズムの実行まで、プロセス全体を示しています。

ハードウェア/コンポーネント

このプロジェクトは、SunFounder Raspberry Pi Pico 4WDスマートカーキットに基づいています。このレッスンで使用される主要コンポーネントは次のとおりです:

  • Raspberry Pi Picoマイクロコントローラーボード
  • 4つのモーターを備えたSunFounder 4WDスマートカーチャシス
  • モータードライバーボード
  • 超音波距離センサー(HC-SR04タイプ)
  • サーボモーター(超音波センサーを回転させるため)
  • 電源(車用バッテリー)

配線ガイド

SunFounderキットは簡単な組み立て用に設計されており、配線は通常、専用の拡張ボードを介して事前に接続されています。超音波センサーはサーボモーターに取り付けられ、それがメイン制御ボードに接続されます。このセットアップにより、センサーを回転させて環境をスキャンできます。お使いのキットに固有の詳細な配線図については、公式のSunFounderドキュメントを参照してください。

主要な接続には、超音波センサーのトリガーおよびエコーピン、サーボモーターのシグナルピンが含まれ、これらはすべてRaspberry Pi Picoの特定のGPIOピンに接続されます。モータードライバーもPicoに接続され、4つの駆動モーターを制御します。ビデオでは、配線図を含む完全なドキュメントがキットと一緒にダウンロード可能であることが言及されています。

Sunfounder_Pico4DW-09-Obstacle-avoidance_超音波が障害物を検出したとき

コードの説明

このレッスンでは、`obstacle_avoid` サンプル内のロジックに焦点を当てます。コードはMicroPythonで書かれています。完全なプログラムはダウンロード可能ですが、車の動作を制御する主要なユーザー設定可能なパラメータに焦点を当てます。これらは通常、スクリプトの先頭にあります。

ロボットのパフォーマンスを微調整するために調整できる主な変数は次のとおりです:


# レーダーおよび移動パラメータ
radar_reference = 20  # 安全と見なされる最小距離(cm)
step_angle = 10       # 各レーダースキャンステップの角度増分
forward_speed = 30    # 前進時のモーター速度(0〜100)
turn_speed = 50       # 旋回時のモーター速度(0〜100)
forward_scan_angle = 50  # 障害物が検出されないときにサーボがスキャンする角度
  • radar_reference:これはセンチメートル単位の重要な安全距離です。障害物がこの値より近くで検出された場合、車はそれを「危険」と見なし、回避操作を開始します。ビデオでは、これは20 cmに設定されています。
  • step_angle:これはレーダースキャンの解像度を定義します。小さい値(例:10度)はより詳細なスキャンを意味しますが、時間がかかります。大きい値は高速ですが、狭い障害物を見逃す可能性があります。
  • forward_speed & turn_speed:これらはモーターに送られる電力を制御します。車の全体的な速度と機動性を変更するために調整できます。旋回速度は、車が効果的にピボットできるようにするため、しばしば高く設定されます。
  • forward_scan_angle:前方に差し迫った危険がない場合、車はスキャンをこの角度(前方を中心)に狭め、直接経路上の障害物をより頻繁にチェックし、スムーズな前進移動を可能にします。

このビデオでは、主要な意思決定ロジックについても説明しています。関数`get_direction()`は、距離測定値のリスト(安全/不安全を1と0に変換したもの)を分析して、最も広い連続した「1」の経路を見つけます。この最も広い経路がどこにあるかに基づいて、関数は「forward」「left」「right」のいずれかの方向を返します。メインループはその後、対応するアクションを実行し、車を回転させて前方の経路がクリアになるまで再スキャンします。

ライブプロジェクト/デモンストレーション

このビデオでは、プロジェクトの詳細なデモンストレーションを提供しています。まず、超音波センサー単体をテストし、距離を測定してシェルに値を出力する方法を示します。次に、インストラクターがフローチャートを使用して障害物回避アルゴリズムを説明し、左右に曲がるための意思決定プロセスを詳しく解説します。最後に、車を箱で作られた小さな迷路に置き、実際の障害物回避動作を完全にデモンストレーションします。車は迷路をうまく進み、左右に曲がって前方のクリアな経路を見つけます。

ビデオチャプター

  • [00:00] 障害物回避の紹介
  • [01:31] SunFounderスマートカーキットと機能の概要
  • [02:47] 障害物回避機能の仕組み
  • [03:34] 超音波センサーのテスト
  • [07:45] 障害物回避アルゴリズムとフローチャートの説明
  • [12:49] 主要な障害物回避コードの分析
  • [15:43] 障害物回避ロジックのライブデモンストレーション
  • [22:53] 障害物の迷路を使った最終デモンストレーション
  • [24:35] 結論と次のステップ

画像

pico-4wd_main
pico-4wd_main
PICOBOARDWHITEANGLE2_1200x857
PICOBOARDWHITEANGLE2_1200x857
Sunfounder_Pico4DW-09-Obstacle-avoidance setup with obstacle on the floor
Sunfounder_Pico4DW-09-Obstacle-avoidance setup with obstacle on the floor
Sunfounder_Pico4DW-09-Obstacle-avoidance_when ultrasonic detects obstacle
Sunfounder_Pico4DW-09-Obstacle-avoidance_when ultrasonic detects obstacle
909-Lesson 9/10 Pi Pico 4WD card Python code: obstacle avoid
言語: C++
# Lesson 9/10 Pi Car Pico 4WD: Obstacle avoid
# Download and resource page https://robojax.com/RJT631
import pico_4wd as car
import time

car.RADAR_REFERENCE = 20
car.RADAR_STEP_ANGLE = 10
MOTOR_FORWARD_POWER = 30
MOTOR_TURNING_POWER = 50

FORWARD_SCAN_ANGLE = 50

car.set_radar_scan_angle(FORWARD_SCAN_ANGLE)
status = "Danger"

def get_dir(radar_data):
    # get scan status of 0, 1
    # print(radar_data)
    radar_data = [str(i) for i in radar_data]
    radar_data = "".join(radar_data)
    # Split 0, leaves the free path
    paths = radar_data.split("0")
    # print(paths)
    # print("paths: %s" % paths)
    length_list = []
    # Calculate where is the widest
    for path in paths:
        length_list.append(len(path))
    if max(length_list) < 4:
        return "left"
    # Calculate the direction of the widest 
    i = length_list.index(max(length_list))
    pos = radar_data.index(paths[i])
    pos += (len(paths[i]) - 1) / 2
    delta = len(radar_data) / 3
    
    if pos < delta:
        return "left"
    elif pos > 2 * delta:
        return "right"
    else:
        return "forward"

def main():
    global status
    # General
    while True:
        radar_data = car.radar_scan()
        # print("radar_data: %s" % radar_data)
        # If radar data return a int, means scan not finished, and the int is current angle status
        if isinstance(radar_data, int):
            if radar_data == 0 and status != "Danger":
                print("Danger!")
                status = "Danger"
                car.move("stop")
                car.set_radar_scan_angle(180)
            continue
        else:
            status = "Save"
        
        direction = get_dir(radar_data)

        if direction == "left":
            print("turn left")
            distance = car.get_radar_distance_at(-FORWARD_SCAN_ANGLE/2)
            time.sleep(0.5)
            car.move("left", MOTOR_TURNING_POWER)
            while True:
                distance = car.get_radar_distance_at(-FORWARD_SCAN_ANGLE/2)
                status = car.get_radar_status(distance)
                if status == 1:
                    break
            car.move("stop")
            car.set_radar_scan_angle(FORWARD_SCAN_ANGLE)
        elif direction == "right":
            print("turn right")
            distance = car.get_radar_distance_at(FORWARD_SCAN_ANGLE/2)
            time.sleep(0.5)
            car.move("right", MOTOR_TURNING_POWER)
            while True:
                distance = car.get_radar_distance_at(FORWARD_SCAN_ANGLE/2)
                status = car.get_radar_status(distance)
                if status == 1:
                    break
            car.move("stop")
            car.set_radar_scan_angle(FORWARD_SCAN_ANGLE)
        else:
            print("forward")
            car.set_radar_scan_angle(FORWARD_SCAN_ANGLE)
            car.move("forward", MOTOR_FORWARD_POWER)

try:
    main()
finally:
    car.move("stop")
    car.set_light_off()

リソースと参考文献

まだリソースはありません。

ファイル📁

ラズベリーパイコード