6. 햄스터 로봇과 함께하는 프로젝트

햄스터 로봇의 기초 명령어를 연습을 통해 프로그래밍 방법뿐만 아니라 동작과 센서의 기본 원리도 익혀 보았다. 앞으로는 실생활과 관련된 몇 가지 프로젝트를 해결해 볼 텐데, 스스로 혹은 친구들과 협력하여 해결하다 보면 어느덧 창의적 문제해결능력이 길러져 있을 것이다. 그럼 시작해 보자.

프로젝트

1

도전! 햄스터 로봇 Driving License

자동차를 운전하기 위해서는 운전면허증이 필요한 것처럼 햄스터 로봇 역시 마찬가지이다. S자 도로, O자 회전, 비상 신호음 테스트를 모두 통과하고 햄스터 로봇 면허를 발급받아 보자.


가. 첫 번째는 가장 쉬운 난이도의 S자 도로 주행이다. 햄스터 로봇이 S자 도로를 주행할 수 있도록 프로그래밍 해 보자.


이미지. 햄스터 로봇이 S자 모양으로 이동하는 모습의 사진. 햄스터 로봇이 이동할 경로에 선이 그어져 있고 곡선 부분에 화살표가 그러져 있다.
이미지. 햄스터 로봇이 S자 모양으로 이동하는 동영상의 스크린샷.

[생각 정리하기]

햄스터 로봇의 3가지 회전 방식 중에 어떤 것을 선택해야 S자를 그리며 움직일 수 있을까? 그리고 일정 시간을 회전한 후 회전의 방향이 바뀌도록 하려면 어떻게 해야 할까?


[생각을 프로그래밍으로 구현하기]


from roboid import *


h=Hamster()


h.wheels(20, 40)

wait(5000) # 왼쪽 방향으로 5초 동안 원을 그리며 회전한다.


h.wheels(40, 20)

wait(5000) # 오른쪽 방향으로 5초 동안 원을 그리며 회전한 후 멈춘다.


h.stop()


나. 두 번째는 O자 회전 코스이다. A4용지를 말아서 원기둥 모양으로 만들고 햄스터 로봇이 A4 원기둥을 따라 O자 회전을 하도록 프로그래밍 해 보자.


이미지. 햄스터 로봇이 A4 원기둥을 따라 O자 회전하는 모습의 사진.
이미지. 햄스터 로봇이 A4 원기둥을 따라 O자 회전하는 동영상의 스크린샷.

[생각 정리하기]

단순히 회전하는 명령을 통해 A4 원기둥을 돌며 움직이도록 할 수 있지만 여기서는 햄스터 로봇의 왼쪽 근접센서를 사용하여 반시계 방향으로 A4 원기둥을 따라 회전하도록 해 보자. 왼쪽 근접센서와 A4 원기둥이 가까울 때와 멀어질 때, 그 움직임이 어떻게 달라져야 할까? O자 회전의 알고리즘을 생각해 보자.


[생각을 프로그래밍으로 구현하기]


from roboid import *


h=Hamster()


while True:

    sensor=h.left_proximity()

    h.wheels(40, 20)

    if sensor > 10:

        h.wheels(50, 10)


    else:

        h.wheels(10, 50) # 왼쪽 근접센서의 값이 10보다 크면(A4 원기둥과 가까워지면) 오른쪽 방향으로 회전하고, 그렇지 않으면 왼쪽 방향으로 회전한다.


    wait(20)

- 지그재그로 움직이면서 A4 원기둥을 따라 회전하는 햄스터 로봇이 되었다. 왼쪽과 오른쪽 바퀴의 속도 차이와 회전 움직임과는 어떤 관련이 있을까? 또 왼쪽 근접센서의 기준값과 회전 움직임과는 어떤 관련이 있을까? 한 번 생각해 보자.



다. 마지막은 비상 신호음 테스트이다. 햄스터 로봇이 직진하다 장애물이 나타나면 멈추고 비상 신호음을 내도록 프로그래밍 해 보자. 물론 장애물이 없어지면 다시 직진해야 한다.

이미지. 햄스터 로봇이 직진하다 장애물이 감지되면 바로 멈추고 비상 신호음을 내는 동영상의 스크린샷.

[생각 정리하기]

직진하다 왼쪽 또는 오른쪽 근접센서에 장애물이 감지되면 바로 멈추고 비상 신호음을 내야 한다. 비상 신호음 내는 부분을 함수로 만들어서 코드를 간결히 해보면 어떨까?


[생각을 프로그래밍으로 구현하기]


from roboid import *


h=Hamster()


def beep():

    h.buzzer(1000)

    wait(500)

    h.buzzer(0)

    wait(500) # 비상신호음을 내는 beep() 함수를 정의한다.


while True:

    if h.left_proximity() > 30 or h.right_proximity() > 30:

        h.wheels(0)

        beep() # 왼쪽 또는 오른쪽 근접센서에 중에서 하나라도 장애물을 감지하면 즉시 멈추고 비상신호음을 낸다.

    else:

        h.wheels(30) # 장애물이 감지되지 않으면 직진한다.

    wait(20)

프로젝트

2

로봇 청소기처럼!

로봇 청소기는 여러 가지 센서로 장애물을 감지하고 스스로 실내를 청소한다. 이런 빈틈없는 모습에 반해 햄스터 로봇은 로봇 청소기가 되고 싶어한다. 물론 햄스터 로봇이 먼지를 빨아들이는 등의 청소는 할 수 없지만 로봇 청소기처럼 동작하는 햄스터 로봇으로 변신시켜 보자.


가. 기본적인 로봇 청소기의 움직임을 구현해 보자. 벽이나 장애물을 만나면 무작위로 방향을 바꾼 후 직진하면서 실내를 빠짐없이 청소하도록 프로그래밍 해 보자. 우선, 햄스터 로봇이 청소할 수 있는 공간이 필요할 것이다. 근접센서가 감지될 만큼의 두꺼운 책으로 둘레를 막아도 좋고, 미로판으로 만들어도 좋다.


이미지. 두꺼운 책으로 둘러싼 곳에 햄스터 로봇이 놓여있는 사진.
이미지. 미로판에 햄스터 로봇이 놓여있는 사진.
이미지. 햄스터 로봇이 벽이나 장애물을 만날 경우 회전하는 동영상의 스크린샷.

[생각 정리하기]

햄스터 로봇이 직진하다가 왼쪽 근접센서가 벽을 감지하면 오른쪽으로 회전하게 하고, 오른쪽 근접센서가 벽을 감지하면 왼쪽으로 회전한 후 직진해야 벽에 부딪치지 않고 안전하게 동작할 수 있을 것이다. 이것을 어떻게 구현할 수 있을까?


[생각을 프로그래밍으로 구현하기]


import random


from roboid import *


h=Hamster()


while True:

    if h.left_proximity() > 50:

        h.wheels(30, -30)

        wait(random.randint(0, 1000)) # 왼쪽 근접센서의 값이 50보다 크면(벽을 감지하면) 오른쪽 방향으로 무작위 시간 동안(최대 1초) 회전한다.

    elif h.right_proximity() > 50:

        h.wheels(-30, 30)

        wait(random.randint(0, 1000)) # 오른쪽 근접센서의 값이 50보다 크면(벽을 감지하면) 왼쪽 방향으로 무작위 시간 동안(최대 1초) 회전한다.

    else

        h.wheels(30) # 벽을 감지하지 않으면 직진한다.

    wait(20)


나. 벽 주변에 먼지가 많이 있다. 이번에는 벽을 따라가면서 청소하는 햄스터 로봇을 만들어 보자.

이미지. 햄스터 로봇이 왼쪽 근접센서 값에 따라 왼쪽 회전, 오른쪽 회전, 후진하는 동영상의 스크린샷.

[생각 정리하기]

가장자리의 벽을 따라가면서 햄스터 로봇이 움직이려면 어떻게 해야 할까? 왼쪽 근접센서가 벽에 가까워지면 오른쪽으로 회전하고, 그렇지 않으면 왼쪽으로 회전하도록 명령하면 햄스터 로봇은 어떤 움직임을 나타낼까? 또 적외선 센서의 특성상 벽과 가까워지면 근접센서의 값이 커지지만 너무 근접해 버리면 오히려 값이 작아지는 문제점이 있다. 이 문제를 어떻게 해결할 수 있을까?


[생각을 프로그래밍으로 구현하기]


from roboid import *


h=Hamster()


while True:

    if h.left_proximity() > 50:

        h.wheels(50, 10) # 왼쪽 근접센서의 값이 50보다 크면(벽을 감지하면) 오른쪽 방향으로 회전한다.

    elif h.left_proximity() < 15:

        h.wheels(-50, -50)

        wait(300) # 왼쪽 근접센서의 값이 15보다 작으면(벽에 너무 근접하면) 0.3초 동안 후진하여 벽에 닿아 있는 상황을 탈출한다.

    else:

        h.wheels(10, 50)

    wait(10) # 왼쪽 근접센서의 값이 위의 두 조건에 해당하지 않으면 왼쪽 방향으로 회전한다.

- 코드를 실행해보면 벽을 따라가는 움직임이 원활하지 않을 것이다. 왜 이런 문제가 발생하는 것일까? 그 이유는 근접센서가 측면을 감지하지 않기 때문이다. 햄스터 로봇 액세서리 중에서 ‘햄스터 미로 찾기용 커버’를 사용하면 이 문제를 해결할 수 있다. 좌측 센서 반사판은 측면을 감지하도록 도와준다.

햄스터 미로 찾기용 커버
이미지. 햄스터 미로 찾기용 커버 사진. 5개의 부품으로 구성되어 있다.
프로젝트

3

힘을 모아 목적지까지!

끝으로 친구와 함께 힘을 모아 목적지까지 이어달리기를 하는 햄스터 로봇을 만들어 보겠다. 먼저 햄스터 로봇이 선을 따라 달릴 수 있도록 검정 테이프를 바닥에 길게 붙여 준다. 출발점에 위치한 햄스터 로봇은 중간지점에 위치한 햄스터 로봇까지 선을 따라 달리기를 하고 두 번째 햄스터 로봇이 목적지까지 이어달리기를 하도록 해 보자.

(단, 본 프로젝트는 친구와 2인 1조가 되어 협력을 통해 문제를 해결하는 활동이지만 여기에서는 한 대의 PC에서 두 대의 햄스터 로봇을 제어하는 방식으로 진행해 보겠다.)


이미지. 두대의 햄스터 로봇이 이어달리기를 하기 위해 간격을 두고 검정 테이프 오른쪽에 위치한 사진.

가. 햄스터 로봇이 선을 따라 달리기를 할 수 있는 알고리즘을 만들어 보자. 두 개의 바닥 센서를 사용하여 선을 따라가기에는 검정 테이프가 두꺼우므로 왼쪽 바닥 센서만 사용하도록 하겠다.

이미지. 햄스터 로봇이 검정 테이프를 따라 지그재그로 따라가는 동영상의 스크린샷.

[생각 정리하기]

선을 따라가기 위해서는 왼쪽 바닥 센서가 검정 선에 닿은 상황과 그렇지 않은 상황으로 나눠볼 수 있다. 그리고 햄스터 로봇 2대가 모두 선을 따라가는 같은 알고리즘을 적용하게 되는데, 같은 코드를 두 번 작성한다면 뭔가 비효율적이다. 이런 경우에는 함수로 만드는 것이 편리할 것이다. 조건에 따른 햄스터 로봇의 움직임을 생각하여 알고리즘을 완성하여 보자.


[생각을 프로그래밍으로 구현하기]


from roboid import *

h1=Hamster()

h2=Hamster()


def linetrace(robot):

    if robot.left_floor() < 50:

        robot.wheels(35, 5)

    else:

        robot.wheels(5, 35) # 'linetrace' 함수를 만들고 선을 따라가는 알고리즘을 적용한다. 왼쪽 근접센서의 값이 50보다 작으면(검은색 선에 닿으면) 오른쪽으로 회전하고, 그렇지 않으면 왼쪽으로 회전한다.


while True:

    linetrace(h1) # 코드가 실행되면 첫 번째 햄스터 로봇이 검은색 선을 따라간다.

    wait(20)


나. 햄스터 로봇을 검정 테이프의 오른쪽에 두고 코드를 실행하면 지그재그로 검은색 선을 따라가게 된다. 이제는 두 대의 햄스터 로봇이 이어달리기를 하도록 프로그래밍 해 보자.

이미지. 두 대의 햄스터 로봇으로 검정 테이프를 따라 이어달리는 동영상의 스크린샷.

[생각 정리하기]

햄스터 로봇이 다음 주자에게 바통을 건네주는 것은 어려우므로 밝기 센서를 사용해 보면 어떨까? 우선, 두 햄스터 로봇은 마주 보고 있어야 한다. 그리고 첫 번째 햄스터 로봇이 두 번째 햄스터 로봇에게 다가가 맞닿으면 밝기 센서의 값이 낮아지므로 이 조건이 될 때까지 선을 따라 달리기를 하게 한다. 두 번째 햄스터 로봇 역시 첫 번째 햄스터 로봇이 다가와 밝기 센서의 값이 낮아질 때까지 기다리다 조건에 이르면 목적지까지 이어달리기를 시작하도록 명령해 볼 것이다. 이런 식으로 여러 대의 햄스터 로봇 이어달리기도 가능하다.


[생각을 프로그래밍으로 구현하기]


from roboid import *

h1=Hamster()

h2=Hamster()


def linetrace(robot):

    if robot.left_floor() < 50:

        robot.wheels(35, 5)

    else:

        robot.wheels(5, 35)


while True:

    if h1.light() < 10:

        break

    else:

        linetrace(h1)

    wait(20) # 첫 번째 햄스터 로봇의 밝기 센서 값이 10보다 작으면(두 번째 햄스터 로봇과 맞닿으면) 반복문을 빠져나온다.


h1.stop() # 첫 번째 햄스터 로봇이 정지한다.


h2.wheels(30, -30)

wait(1900) # 두 번째 햄스터 로봇이 180° 회전한다.


while True:

    if h2.light() < 10:

        break

    else:

        linetrace(h2)

    wait(20) # 두 번째 햄스터 로봇의 밝기 센서 값이 10보다 작으면(목적지에 도달하면)반복문을 빠져나온다.


h2.stop() # 두 번째 햄스터 로봇이 정지한다.