코드 검색

코스 레슨 10개 중 9번째: 라즈베리 파이 피코 4WD 스마트 카를 이용한 장애물 회피

이 수업은 일부입니다.: 라즈베리파이 피코 4WD 스마트카

코스 레슨 10개 중 9번째: 라즈베리 파이 피코 4WD 스마트 카를 이용한 장애물 회피

소개

이 가이드는 Robojax의 코스 레슨 9/10을 기반으로, SunFounder Raspberry Pi Pico 4WD 스마트 카 키트를 사용하여 장애물 회피 로봇을 만드는 방법을 보여줍니다. 이 프로젝트는 서보 구동 초음파 센서와 모터 제어를 결합하여 환경을 자율적으로 탐색할 수 있는 로봇을 만듭니다. 센서를 레이더처럼 회전시키면서 자동차는 장애물을 감지하고 지능적으로 진행할 수 있는 명확한 경로를 선택합니다. 이는 로봇 공학, 센서 통합 및 자율 주행에 대한 완벽한 입문서입니다.

바닥에 장애물이 있는 Sunfounder_Pico4DW-09-장애물 회피 설정

이 프로젝트는 단순한 장난감이 아니라 많은 실용적인 응용 분야의 기초입니다. 영감을 줄 몇 가지 아이디어는 다음과 같습니다:

  • 자율 탐사 로봇: 인간의 개입 없이 방이나 야외 지역을 지도화하고 탐험할 수 있는 로봇을 만드세요.
  • 스마트 청소기: 동일한 원리를 사용하여 청소하면서 가구와 벽을 피해 방을 탐색하는 로봇을 만드세요.
  • 보안 순찰 봇: 자동차가 경계를 순찰하고 초음파 센서를 사용하여 예상치 못한 장애물이나 침입을 감지하고 보고하도록 프로그래밍하세요.
  • AI 교육 플랫폼: 이 프로젝트를 경로 찾기 및 동시 위치 추정 및 지도 작성(SLAM)과 같은 더 복잡한 알고리즘을 배우는 디딤돌로 사용하세요.

이 레슨은 자동차가 결정을 내릴 수 있게 하는 핵심 로직과 코드에 중점을 둡니다. 자동차는 서보 모터를 사용하여 초음파 센서를 회전시키고, 0도에서 180도까지의 거리를 측정하는 레이더 역할을 합니다. 코드는 이 데이터를 분석하여 가장 넓은 빈 경로를 찾고 자동차가 앞으로, 왼쪽 또는 오른쪽으로 이동하도록 지시합니다. 비디오는 개별 구성 요소 테스트부터 실제 미로에서 최종 장애물 회피 알고리즘 실행까지 전체 과정을 보여줍니다.

하드웨어/구성 요소

이 프로젝트는 SunFounder Raspberry Pi Pico 4WD 스마트 카 키트를 기반으로 합니다. 이 레슨에서 사용되는 필수 구성 요소는 다음과 같습니다:

  • Raspberry Pi Pico 마이크로컨트롤러 보드
  • 4개의 모터가 있는 SunFounder 4WD 스마트 카 섀시
  • 모터 드라이버 보드
  • 초음파 거리 센서(HC-SR04 유형)
  • 서보 모터(초음파 센서 회전용)
  • 전원 공급 장치(자동차용 배터리)

배선 가이드

SunFounder 키트는 조립이 쉽도록 설계되었으며, 배선은 일반적으로 전용 확장 보드를 통해 사전 연결됩니다. 초음파 센서는 서보 모터에 장착되며, 서보 모터는 메인 제어 보드에 연결됩니다. 이 설정을 통해 센서를 회전시켜 환경을 스캔할 수 있습니다. 키트별 자세한 배선도는 공식 SunFounder 문서를 참조하십시오.

핵심 연결에는 초음파 센서의 트리거 및 에코 핀과 서보 모터의 신호 핀이 포함되며, 모두 Raspberry Pi Pico의 특정 GPIO 핀에 연결됩니다. 모터 드라이버도 4개의 구동 모터를 제어하기 위해 Pico에 연결됩니다. 비디오에서는 배선도를 포함한 전체 문서가 키트와 함께 다운로드 가능하다고 언급합니다.

초음파가 장애물을 감지할 때 Sunfounder_Pico4DW-09-장애물 회피

코드 설명

이 레슨은 `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: 이는 센티미터 단위의 중요한 안전 거리입니다. 장애물이 이 값보다 가까이 감지되면 자동차는 이를 "위험"으로 간주하고 회피 기동을 시작합니다. 비디오에서는 20cm로 설정되어 있습니다.
  • 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()

필요할 수 있는 것들

자원 및 참고자료

아직 자원이 없습니다.

파일📁

라즈베리 파이 코드