로봇 프로그램

 

프로그램의 천재가 되자 : Richard E. Pattis   Jim Roberts   Mark Stehlik 저, 조범준 역, 내하출판사, 2003 (원서 : Karel the Robot: A Gentle Introduction to the Art of Programming, John Wiley & Sons, 1994), Page 1~31, 229~231

 

1. 로봇 세계

     (1) 로봇의 세계

     (2) 로봇의 능력

     (3) 임무와 상황들

2. 기본 명령들과 간단한 프로그램

     (1) 위치 바꾸기

     (2) 비퍼의 조작

     (3) 임무 종료

     (4) 프로그램의 완성

           ① 프로그램의 실행

           ② 로봇 프로그램의 형식

     (5) 에러 발생 처리 (Error Shutoffs)

     (6) 프로그래밍 에러 (programming Errors)

3. 프로그래밍 요약

1. 로봇 세계

(1) 로봇의 세계

로봇은 현 세상에는 존재하지 않지만 (그곳에는 화산도 없고, 중국식 식당도 없고, 심포니 오케스트라도 없다), 그러나 로봇이 간단하게 할 수 있는 흥미로운 일이 많이 있는 그런 세상에 살고 있다. 로봇이 살고 있는 세상은 로봇이 이동할 수 있는 길이 모두 격자 모양으로 뚫려 있다. 그 길에는 로봇이 감지할 수 있고 조작할 수 있는 특별한 물체가 있다.

그림 1  로봇의 세상

[그림 1] 은 로봇이 존재하는 세상의 구조를 나타내는 지도이다. 일반적으로 동ㆍ서ㆍ남ㆍ북에는 일정 간격으로 포인트가 존재하고 매우 평평한 판 모양을 하고 있다. 이 세계는 서쪽을 기준으로 하여, 북쪽으로 한없이 뻗쳐진 벽이 있고, 남쪽을 기준으로 동쪽으로 한없이 쭉 뻗은 벽이 있다. 이 기준이 되는 벽은 뉴트로니엄 (Neutronium) 이라는 깨지지도 않고 뚫을 수도 없는 금속으로 되어 있어 로봇이 세계의 끝에서 아래로 떨어지는 것을 막을 수 있다.

동에서 서쪽으로 뻗은 Street 와 북에서 남으로 뻗은 Avenue 가 한 블록 간격으로 계속 교차되어 있다. 여러분이 Street 와 Avenue 를 쉽게 구분할 수 있는 방법은 Avenue 의 'A' 는 북쪽을 향해 뾰족하게 나와 있고 'V' 는 남쪽을 가리키고 있다는 것을 기억하면 좋다. 코너란 Street 와 Avenue 가 만나는 교차로 나타낸다. 로봇은 이 코너에만 위치할 수 있다. Steet 와 Avenue 둘 모두 각각 일련 번호가 매겨져 있다. 첫 번째 Street 와 첫 번째 Avenue 가 만나는 교차점을 출발점 (Origin) 이라고 한다. 절대경로 (Absolute) 입장에서 보았을 때 출발점은 첫 번째 Street 와 첫 번째 Avenue 의 교차지점 (Intersection) 을 말하는 것이다. 이 출발점을 상대경로 (Relative) 입장 위치와 로봇 세상의 물체의 위치를 절대경로와 상대경로 모두를 사용하여 나타낼 것이다.

로봇 세상에는 두 종류의 물체가 존재하는데, 첫 번째 물체는 바로 벽 (Wall Section) 이다. 이 벽 역시 뉴트로니엄으로 이루어져 있고 원하는 길이와 모양으로 제조될 수 있다. 이 벽은 Street 코너의 중간 지점에 위치하여 있고 로봇이 한 코너에서 다른 코너로 이동할 때 방향을 가로막을 수 있게 되어 있다. 이렇게 벽은 로봇이 조사해야 할 목표물을 둘러싸고 있는 허들이나 산과 같은 방해물로 생각할 수 있다. 방이나 퍼즐, 그리고 다른 장벽을 이 벽으로 만들 수 있다. [그림 2] 는 벽의 전형적인 예를 보여준다.

그림 2  로봇 세상에 존재할 수 있는 벽들의 모양

로봇의 세상에서 볼 수 있는 두 번째 물체는 비퍼 (Beeper) 이다. 이 비퍼는 조그마한 플라스틱 원뿔 모양으로 생겼고 삐 하는 소리를 낸다. 이것들은 코너에 놓여져 있으며 로봇에 의해서 집어지고, 옮겨지고, 새로운 위치에 놓여질 수 있다. 로봇이 수행하는 몇 가지 임무 중의 하나가 바로 이 비퍼를 정해진 모양대로 집어 올리거나 놓거나, 또는 비퍼를 찾거나 이동시키는 것이다. [그림 3] 은 비퍼가 놓여지는 한가지 모양을 나타낸 것이다.

그림 3  로봇 세상의 비퍼 배열의 한 가지 예

(2) 로봇의 능력

자! 이제 로봇의 세계에서 눈을 떼고 로봇 자체에 관심을 돌려보자. 로봇은 자신이 바라보고 있는 방향으로 전진할 수 있고 회전할 수도 있는 이동 가능한 로봇이다. 로봇은 빛, 소리, 방향 그리고 촉각과 같은 기본적인 감각으로 그의 주변에 있는 것들을 감지해 낼 수 있다.

로봇은 앞, 좌, 우에 설치된 TV 카메라 중 하나로 볼 수도 있다. 이 카메라들은 자신으로부터 정확히 반 블록 떨어진 곳까지 볼 수 있다. 또한 로봇은 비퍼의 소리를 들을 수 있는 능력이 있는데 비퍼가 같은 코너에 있을 때만 가능하다. 로봇은 자신이 어느 위치를 보고 서 있는지도 판단할 수 있다. 마지막으로 로봇은 비퍼를 들어올리거나 내려놓을 수 있는 강철로 된 팔이 있다. 그리고 비퍼를 나르기 위해서 허리 부분에 방음장치가 된 가방 (Beeper Bag) 을 장착하고 있다. 그리고 로봇은 가방을 살펴봄으로써 그가 비퍼를 운반하고 있는지를 알 수 있다.

우리가 로봇에게 어떠한 임무를 줄 때, 그 일을 해내는 데 필요한 세부 사항들을 하나하나 정확하게 설명해 주어야 한다. 로봇은 프로그램 (Program) 이라는 명령문들을 읽고 그대로 임무를 수행할 수가 있는 것이다. 그러면 어떤 언어로 로봇을 조정하는 프로그램 (여기서 프로그램이란 명령들을 열거하는 것을 말한다) 을 만들 것인가? 한국어처럼 이미 알고 있는 언어로 프로그램을 하는 대신, 우리는 로봇 프로그램을 작성하는 데 매우 유용하도록 설계된 언어를 사용할 것이다. 그 언어는 단어, 구두점 그리고 문법도 가지고 있다. 이 언어는 매우 단순해서 로봇이 이해할 수 있고 또한 우리가 로봇을 위해서 간단하고 명료하게 프로그램할 수 있게 되어 있다.

(3) 임무와 상황들

임무 (Task) 란 우리가 로봇에게 하기를 원하는 일을 말한다. 아래의 내용은 로봇이 할 수 있는 몇 가지 임무의 예들이다.

  • 15 번째 동서간 도로와 10 번째 남북간 도로의 코너로 움직여라.
  • 장애물 경기를 해라 (Wall Section 으로 장애물을 나타낸다).
  • 문이 하나 있는 방에서 나와라.
  • 비퍼를 찾아 원점에 갖다 놓아라.
  • 미로를 빠져 나와라.

이러한 것들은 매우 간단한 훈련들에 해당한다.

상황 (Situation) 이란 로봇의 세계를 정확하게 묘사하는 것을 뜻한다. 로봇 세계의 기본적인 구조뿐만 아니라, 벽들과 비퍼들을 포함시켜 모든 상황을 나타내는 것이다. 상황을 완벽하게 설명하기 위해서는 우리는 다음과 같은 정보를 나타내 주어야 한다.

  • 로봇의 현재 위치는 어디인가? 우리는 로봇의 위치 (절대적 혹은 상대적) 와 로봇이 향하고 있는 방향, 모두를 나타내 주어야 한다.
  • 이 세계에서 각 벽의 위치와 크기는 어떻게 되는가?
  • 이 세계에서 각 비퍼의 위치가 어디인가?

 

그림 4  로봇이 해야 할 서로 다른 6 가지 임무

이 책에서는 작은 지도그림이나 간단한 설명으로 이러한 상황을 명시해 줄 것이다. 만약에 우리가 로봇의 비퍼백 (Beeper Bag) 에 있는 비퍼의 개수를 알고 있다면 이것도 알려 주어야 한다. [그림 4] 는 앞으로 로봇이 해야 할 몇 가지 임무의 서로 다른 초기상황을 나타내고 있다. 어떤 임무라도 초기상황 (Initial Situation) 에는 로봇이 임무를 시작할 초기 위치를 표시하여야 한다. 종료 상황 (Final Situation) 은 로봇이 자신의 스위치를 끌 때의 위치를 나타낸다. 다른 말이 없는 이상 로봇은 빈 비퍼백으로 임무를 시작한다고 생각할 수 있다.

2. 기본 명령들과 간단한 프로그램

(1) 위치 바꾸기

로봇의 위치를 바꾸도록 하는 데는 두 가지의 기본 명령을 사용할 수 있다. 그 첫번째 것이 move 라는 명령어이다.

>> move <<

로봇이 move 라는 명령어를 수행할 때에는 자신이 향하고 있는 방향으로 1 블록 앞으로 이동해서 그 방향을 그대로 유지하는 것을 뜻한다. 로봇은 자신의 앞에 벽과 같은 장애물이 있으면 앞으로 움직이지 않고 그 대신에 자신의 전원을 꺼버릴 것이다. 이 행동을 Error Shutoff 라 하는데, (5) 에서 더 자세하게 설명하겠다.

위의 정의에서 알 수 있듯이 move 라는 명령은 로봇을 한 블록 앞으로 이동시키는 것이다. 그리고 벽에 부딪쳤을 때는 Erro Shutoff 를 실행하는 것이다. 다음 그림에 이 두 가지 상황을 나타내었다. [그림 1] 은  성공적으로 move 명령어를 수행한 경우로서 벽은 로봇의 위치에서 반 블록 이상 떨어져 있다.

그림 1  (A) move 명령 전의 초기 상태, (B) move 명령 후의 최종 상태

반면에 [그림 2] 는 잘못된 move 명령의 수행을 나타내 준다. 로봇은 아래 상황에서 move 라는 명령어를 수행하려고 하지만 벽을 보게 되고 그의 자기 보호 본능에 따라서 Error Shutoff 라는 과정을 수행한다.

그림 2  앞이 막혀 있을 때 Error Shutoff 를 수행한 결과

로봇을 움직이게 하는데 사용되는 두 번째 기본 명령은 turnleft 이다. 이 명령어는 로봇이 향하는 방향을 바꾸지만 그의 위치는 변화시키지 않는다.

>> turnleft <<

로봇은 turnleft 명령을 받게 되면 왼쪽으로 90° 돈다. 여기에서 로봇은 방향을 바꾸지만 위치는 그대로이며, 벽이 로봇을 막는다는 것은 불가능하기 때문에 turnleft 명령어는 Error Shutoff 를 유발시킬 수가 없다.

로봇은 항상 어떤 코너에서 동서남북의 한 방향을 바라보면서 임무를 시작한다. 로봇은 반 블록씩 이동한다든가 90° 이외의 각도로는 방향을 바꾸지 않는다. move 난 turnleft 가 비록 로봇의 위치나 방향을 바꾸기는 하지만 여전히 로봇은 세상의 어느 한 코너에서 있게 된다.

로봇의 기본 언어에는 turnleft 라는 단어가 없다. turnleft 라는 단어가 있다고 해서 지금의 5 개 명령어로 하지 못하는 새로운 테스크를 풀어 낼 수 있을까? 잠깐 생각해 보면 turnleft 라는 단어는 불필요하다는 것을 느낄 수가 있다. turnleft 가 있음으로서 새로운 일을 해내는 것도 아니고, 3 번의 turnleft 명령을 내리면 turnleft 와 같아진다는 것을 알 수 있기 때문이다.

(2) 비퍼의 조작

로봇은 비퍼를 다루는 2 가지의 기본 명령어를 알고 있다. 이 두 가지 명령어는 서로 반대되는 행동을 한다.

>> pickbeeper <<

로봇이 pickbeeper 의 명령을 수행할 때 로봇은 비퍼를 그가 서 있는 코너에서 주워서 자신의 비퍼백에 넣는다. 만약에 비퍼가 없는 코너에서 pickbeeper 라는 명령을 수행하도록 하면 로봇은 Error Shutoff 명령을 수행해 버린다. 비퍼가 1 개 이상있는 코너에도 로봇은 오직 1 개씩만 주워서 비퍼백에 넣는다.

>> putbeeper <<

로봇은 putbeeper 라는 명령어를 받게 되면 자신의 비퍼백에서 비퍼를 하나 빼서 자신이 서 있는 코너에 내려놓는다. 만약 로봇에게 putbeeper 명령을 수행하도록할 때 비퍼백이 비어있으면 로봇은 바로 Error Shutoff 를 실행해 버린다.

비퍼는 그 크기가 워낙 작아서 로봇이 움직이는데 장애물이 되지는 못한다. 오직 벽만이 로봇이 가는 길을 막을 수 있다.

(3) 임무 종료

마지막으로 로봇에게 임무를 아주 잘 끝마쳤다는 것을 알려줄 필요가 있다. 이때 turnoff 명령어를 사용한다.

>> turnoff <<

로봇이 turnoff 명령어를 받게 되면 자신의 스위치를 끄고 새로운 임무를 시작하기 전까지 어떠한 명령어도 수행할 수 없는 상태가 된다. 모든 프로그램의 마지막 명령어는 항상 turnoff 이다.

(4) 프로그램의 완성

이번 절에서는 로봇에게 하나의 임무를 수행할 수 있도록 하나의 완벽한 프로그램을 줄 것이다. [그림 3] 에서 나와 있는 것처럼 로봇의 임무는 비퍼를 2 번째 Street 와 4 번째 Avenue 에서 4 번째 Street 와 5 번째 Avenue 로 옮겨 놓는 것이다. 비퍼를 내려놓은 후 로봇은 북쪽으로 1 블록 더 이동하여 자신의 스위치를 끄는 것이다.

그림 3  (A) 임무의 초기 상태, (B) 임무의 최종 상태

아래에 쓰여 있는 프로그램을 로봇에게 주면 위의 임무를 로봇이 완벽하게 실행해낸다. 이 프로그램은 로봇의 기본적인 5 가지의 명령어와 로봇의 사전에 있는 몇가지의 기본적인 단어, 그리고 세미콜론 (;) 으로 이루어져 있다. 먼저, 로봇의 프로그램 실행에 대해서 이야기하고 그 다음에 이 로봇 프로그램의 구조에 대해서 분석해 보겠다.

program ~~~~~

      BEGINNING-OF-PROGRAM

              BEGINNING-OF-EXECUTION

                          move;

                          move;

                          pickbeeper ;

                          move;

                          turnleft;

                          move;

                          move;

                          putbeeper;

                          move;

                          turnoff

              END-OF-EXECUTION

      END-OF-PROGRAM

위의 프로그램은 주어진 임무를 실행하는 수없이 많은 명령의 조합 중의 하나라는 것을 명심해야 한다.

① 프로그램의 실행

로봇이 프로그램을 실행하기 전에 아무런 문제가 생기지 않도록 하기 위해 한 번 프로그램을 읽어본다. 에러에 관해서는 다음에 설명하기로 하고 지금은 우리의 프로그램이 오류가 없는 완벽한 프로그램이라고 가정해 보자.

로봇이 프로그램을 어떻게 실행하는 것일까? 로봇은 BEGINNING-OF-EXECUTION 과 END-OF-EXECUTION 의 사이에 있는 각 명령어를 하나도 빼지 않고 위에서 아래로 순서대로 수행해 나간다. 로봇은 turnoff 명령어를 받거나 에러에 의한 종료가 되기 전까지는 계속 명령어를 수행해 나간다.

물론, 우리는 로봇이 죽기를 바라지 않기 때문에 로봇에게 프로그램을 줄 때에 항상 문제가 있는지 없는지 살펴보게 된다. 혹시 로봇이 Wall Section 에 부딪히지는 않는지, 비퍼가 없는데도 주우려고 하지는 않는지 등을 확인해 보게 된다. 이러한 것을 시뮬레이션이라 한다. 우리는 로봇이 하려는 모든 행동에 대해서 체계적으로 정리하고 저장함으로써 시뮬레이션을 할 수 있다. 그 방법 중의 하나가 종이 위에 그림을 그리면서 프로그램을 시뮬레이션해 보는 것이다. 우리는 로봇이 명령을 수행하는 순서를 그대로 따라해 봄으로써 프로그램에 문제가 없는지 추적해 볼 수 있다. 로봇의 행동을 정확하고 빠르게 파악해 내는 것은 우리가 습득해야 할 중요한 기술 중의 하나이다. 다음의 프로그램을 시뮬레이션해 보자. 2, 2 는 2 번째 Street 와 2 번째 Avenue 를 뜻한다.

program ~~~~~

    BEGINNING-OF-PROGRAM

            BEGINNING-OF-EXECUTION

     

                        move;

     

                        move;

     

                        pickbeeper ;

     

                        move;

     

                        turnleft;

     

                        move;

     

                        move;

     

                        putbeeper;

     

                        move;

     

                        turnoff

     

            END-OF-EXECUTION

    END-OF-PROGRAM

 

로봇은 2, 2 코너에서 동쪽을 바라보고 있으며, 비퍼백에는 비퍼가 하나도 없다.

로봇은 동쪽으로 1 칸 움직여, 2, 3 에 도달한다.

로봇은 동쪽으로 1 칸 움직여, 2, 4 에 위치한다.

로봇은 비퍼 1 개를 줍는다. 비퍼백에 비퍼가 1 개 있다.

로봇은 동쪽으로 1 칸 움직여, 2, 5 에 도달한다.

로봇은 2, 5 에서 왼쪽으로 돌아 북쪽을 향한다.

로봇은 북쪽으로 1 칸 움직여 3, 5 에 위치한다.

로봇은 북쪽으로 1 칸 움직여 4, 5 에 위치한다.

로봇은 비퍼 1 개를 내려놓는다. 비퍼백에는 비퍼가 1 개도 없다.

로봇은 북쪽으로 1 칸 움직여 5, 5 에 위치한다.

로복은 5, 5 에서 북쪽을 향하면서 자신의 스위치를 끈다.

 

 

로봇이 임무를 모두 완수했다. 그리고 우리는 이 프로그램의 시뮬레이션을 통해, 이 프로그램에 에러 (Error) 가 없다는 것을 밝혀냈다.

② 로봇 프로그램의 형식

로봇이 어떻게 프로그램을 수행하는지 보았기 때문에, 이제는 로봇과 의사 소통하는 데 필요한 문법에 대해 알아보자. 로봇의 언어는 문법과 구두법이 굉장히 까다롭다. 그러므로 우리는 여기에서 그러한 법칙에 대해서 자세하게 공부해 놓으면 좋다. 로봇이 이해할 수 있는 모든 내용 (Symbol) 을 세 가지 클래스 (Class) 로 구분하는 것부터 시작해 보자. 첫 번째 클래스는 구두점인 쎄미콜론 (;) 이다. 다음 두 가지는 로봇의 단어사전에 있는데 예제에서 보았던 기본 명령어들과, 예약어 (Reserved Words) 들이다.

예약어 (Reserved Word) 는 로봇의 언어의 원시적인 명령들을 구조적으로 조직하기 위해서 사용된다. 프로그램을 읽기 쉽게 하기 위해서, 예약어는 대문자로, 기본 명령어는 소문자로 표기를 했다. 이렇게 하면 예약어와 기본 명령어를 구별해 내는데 쉬울 것이다. 하지만 이것은 우리들에게 도움이 되라고 하는 것이지 로봇에게는 상관이 없다. 로봇은 대문자와 소문자를 구별하지 않기 때문이다.

다음의 프로그램을 가지고 사용된 네 개의 예약어와 구문의 규칙에 대해서 이야기해 보겠다. 진행하기에 앞서 다시 한번 프로그램을 살펴보자.

program ~~~~~

      BEGINNING-OF-PROGRAM

              BEGINNING-OF-EXECUTION

                          move;

                          move;

                          pickbeeper ;

                          move;

                          turnleft;

                          move;

                          move;

                          putbeeper;

                          move;

                          turnoff

              END-OF-EXECUTION

      END-OF-PROGRAM

모든 로봇 프로그램은 꼭 BEGINNING-OF-PROGRAM 이라는 예약어로 시작해야 하고, 다음에는 BEGINNING-OF-EXECUTION 이라는 예약어가 나오고 기본 명령어들은 그 다음에 나온다. 이 기본 명령어들 뒤에는 END-OF-EXECUTION 과 END-OF-PROGRAM 이라는 예약어가 순서대로 나온다. BEGIN 과 END 예약어의 조합은 시작과 끝을 나타내는 중요한 요소이기 때문에 경계기호 (Delimiter) 라고도 부른다.

BEGINNING-OF-EXECUTION 이라는 예약어는 로봇에게 프로그램의 어느 곳에서부터 기본 명령어들을 실행해야 하는지를 가르쳐 준다. END-OF-EXECUTION 이라는 예약어는 로봇의 명령 실행이 끝났다는 것을 의미하는 것이 아니다. turnoff 라는 기본 명령어가 그 역할을 하는 것이다. END-OF-EXECUTION 이라는 예약어는 단지 로봇이 실행해야 하는 기본 명령어들이 끝났음을 나타내기만 한다. 만약에 로봇이 프로그램을 실행하는데 turnoff 가 나오기 전에 END-OF-EXECUTION 에 도달하면 로봇은 잘못 수행되었는 줄 알고 에러를 출력한다.

이제 로봇의 언어에서 쎄미콜론 (;) 에 관한 규칙에 대하여 자세히 살펴보자. 쎄미콜론은 연속되는 기본 명령어들을 불리하기 위해서 사용한다. 쎄미콜론의 사용 규칙은 "각각의 명령은 다음 명령과 반드시 쎄미콜론으로 분리되어야 한다" 이다. 즉, 두 개의 기본 명령어 중 첫 번째 기본 명령어 바로 다음에 쎄미콜론을 쓴다. 이처럼 간단한 규칙인데도 많은 사람들이 "명령어 뒤에는 반드시 쎄미콜론을 쓴다" 라고 잘못 이해하는 경우가 종종 있다. 이 두 문장의 차이점은 이 프로그램의 turnoff 명령어를 살펴봄으로써 알 수 있다. turnoff 명령어 뒤에는 쎄미콜론이 없어야 정상이다. 왜냐하면 turnoff 다음에 기본 명령어가 아닌 예약어 즉, END-OF-EXECUTION 이 나오기 때문이다. 기본 명령어와 예약어를 쎄미콜론으로 구별해야 한다는 규칙은 없다. "기본 명령어 다음에 쎄미콜론" 이라는 규칙은 실패하며, "기본 명령어들 사이에 쎄미콜론" 의 규칙은 성공적이다. 또한 BEGINNING-OF-PROGRAM 과 BEGINNING-OF-EXECUTION 과 같이 연속되는 예약어 다음에는 쎄미콜론을 사용하지 않는다 (BEGINNING-OF-PROGRAM 뒤에 BEGINNIG-OF-EXECUTION 이 꼭 연달아 나오지 않아도 된다. 다음 장에서 이 두 예약어들 사이에 무엇이 들어갈 수 있는지에 대해 알아본다).

이 규칙은 수학에서 집합을 표시할 때 사용하는 방법과 비슷하다. 예를 들어 1, 4, 7 의 원소를 가지고 있는 집합을 {1, 4, 7} 과 같이 쓸 때 유추해 보면, 괄호는 중요한 부분의 시작과 끝을 알려주는 구별 문자이고, 숫자는 기본 명령어와 같고, 콤마 (Comma) 는 쎄미콜론과 같다. 만약에 {1, 4, 7} 과 같이 쓰면 꼭 숫자 하나를 잊어버리고 안 쓴 것처럼 보일 것이다. 비슷하게,  turnoff 다음에 쎄미콜론을 쓰면 로봇은 또 다른 기본 명령어가 있다고 생각한다. 프로그램을 작성할 때 이와 같은 규칙을 조심해야 한다. 왜냐하면 많은 문법적인 에러 (Error) 가 쎄미콜론을 잘못 사용하여 발생하기 때문이다.

마지막으로 프로그램 전체가 보기 좋게 들여쓰기를 했다는 것에 주목해 보자. 정리가 잘 되었기 때문에 읽기가 편하다. 대ㆍ소문자의 사용법에서와 마찬가지로 이 들여쓰기는 우리가 편리하기 위해서 하는 것이다. 로봇은 대ㆍ소문자를 구별하지 않듯이, 들여쓰기도 상관하지 않는다. 로봇은 아래의 프로그램도 앞에서 설명한 프로그램과 똑같이 읽는다.

program ~~~~~

    beginning-of-program beginning-of-execution move; move; pickbeeper; move; turnleft; move; move; putbeeper; move; turnoff end-of-execution end-of-program

이 예가 보여주듯이 우리가 읽기 편한 프로그래밍 스타일을 사용하는 것이 매우 중요하다. 그래야만 로봇에게 문제가 발생할 수 있는 프로그램을 주지 않기 때문이다.

(5) 에러 발생 처리 (Error Shutoffs)

로봇은 기본 명령어들을 성공적으로 수행할 수 없게 되었을 때, 앞에서 얘기한 것처럼 자신의 전원을 꺼버린다. 이와 같은 행동을 Error Shutoffs 라고 하는데 그 효과는 로봇이 turnoff 명령을 수행하는 것과 같은 것이다. 전원을 끄는 것을 바라지 않을 때도 있지만 그렇게 되면 로봇이 성공적으로 수행할 수 없는 명령을 만났을 때, 그것을 무시하고 그냥 다른 명령을 실행하게 될 것이다. 이 방법을 이용하면 로봇은 마치 불안정한 명령을 받은 적이 없는 듯이 프로그램의 실행을 계속한다.

하지만 Error Shutoff 를 사용해야 하는 이유를 설명해 보겠다. 로봇이 예상하지 못한 어떠한 상황 즉, 명령의 성공적인 실행을 방해하는 상황이 일어난다면 로봇은 임무 전체를 완수할 수 없을 것이다. 이러한 상황에서 계속적으로 프로그램을 실행할 때 당신이 로봇에게 내렸던 임무와 로봇이 실제로 수행한 결과에는 큰 차이가 날 것이다. 그러므로 가장 좋은 방법은 로봇이 처음에 문제를 발견했을 때 전원을 끄도록 하는 것이다.

지금까지 우리는 Error Shutoff 를 일으킬 수 있는 명령어 세 개 (move, pickbeeper, putbeeper) 를 배웠다. Error Shutoff 가 일어나지 않도록 다음의 조건들이 항상 만족되게 프로그램을 작성해야 한다.

  • 로봇은 자신의 바로 앞에 있는 길이 가로 막혀져 있지 않을 때에만 move 명령을 수행한다.
  • 로봇은 자신이 서 있는 코너에 최소한 1 개의 비퍼가 있어야 pickbeeper 명령을 수행한다.
  • 로봇의 비퍼백이 비어 있지 않을 때에만 putbeeper 명령을 수행한다.

프로그램을 작성하기 전에 로봇이 어떠한 상태에 처음 놓여지게 될지를 미리 알면 위의 조건들을 만족시키기 쉽다.

turnoff 라는 명령어를 프로그램에서 빼놓게 되면 로봇은 에러가 발생했다고 생각한다. 그렇기에 프로그램의 마지막에 기본 명령어인 turnoff 를 꼭 써야 한다는 것을 잊지 말아야 한다.

(6) 프로그래밍 에러 (programming Errors)

이 절에서는 모든 프로그래밍 에러들을 어휘, 구문, 실행 그리고 함의적 에러라는 4 가지 큰 관점에서 살펴보겠다. 각 에러의 특성을 확실하게 이해할 수 있게 예를 들어 위의 네 가지 항목에 대해서 설명하겠다. 그렇다면 "왜 일어나지도 않을 수 있는 에러에 이렇게 많은 시간을 보내야만 하는가?" 라고 물어볼 수도 있다. 하지만 프로그래밍이라는 것은 굉장한 정확도가 필요할 뿐만 아니라 이론적으로는 전혀 문제가 없어 에러가 발생하지 않아야 하는 데도 불구하고, 실제로 실행 단계에서는 에러가 자주 발생한다. 그러므로 시뮬레이션을 통해서 에러를 빨리 찾아 고칠 수 있어야 하는 것이다.

먼저, 어휘 에러 (Lexical Error) 는 로봇이 자신의 어휘사전에 포함되어 있지 않는 단어를 볼 때마다 발생한다. 예를 들어 우리가 샌프란시스코의 한 거리에 서 있는데 지나가는 운전자 한 사람이 "오레건 주에 있는 포틀랜드로 가려면 어떻게 하죠?" 라는 질문을 했을 때, 우리가 "프젯트 데스트 젭피 이란셋 피짓쇼 미나럳자" 라는 식으로 대답을 한다면 우리는 어휘 에러를 일으킨 것이다. 그 운전자는 우리가 한 말 자체를 이해할 수 없기 때문에 우리가 가르쳐 준 길의 방향을 알 수가 없다. 이처럼 로봇도 프로그램 내에 있는 각 단어를 이해할 수 있어야만 한다.

다음은 어휘 에러가 있는 프로그램이다.

program ~~~~~

    BEGINNING OF PROGRAM

            GEBINNING-OF-EXECUTION

                         move;

                         mvoe;

                         pick;

                         move;

                         turnright;

                         move;

하이픈이 없다.

철자법이 틀렸고 빈 공간이 있다.

 

철자법이 틀렸다.

모르는 단어이다.

 

모르는 단어이다.

 

로봇이 프로그램의 모든 단어를 안다고 해도, 그 프로그램은 문법 에러 (Syntactic Error) 를 일으킬 수도 있다. 이러한 에러는 우리가 잘못된 문법이나 구두법을 사용할 때 발생한다. 다시 앞의 운전자의 예로 돌아가 보자. 우리가 만약 "쭉 그냥 800 정도 되요 마일 앞으로" 라고 대답하면 그 운전자는 각 단어는 이해할 수 있어도 전체 문장은 이해할 수 없을 것이다. 각 단어는 이해를 해도 우리가 그 단어들을 문법에 맞지 않게 조합했기 때문에 그 사람은 여전히 이해를 하지 못하게 된다 (앞의 2의 (4) 절 로봇프로그램의 형식에서 로봇에게 맞는 문법은 무엇인지에 대해서 공부했었다.)

다음의 프로그램은 어휘적 에러는 없지만 문법적 에러가 있는 프로그램이다.

program ~~~~~

    BEGINNING-OF-EXECUTION

            BEGINNING-OF-PROGRAM

     

                         move;

                         move;

                         pickbeeper;

                         move;

                         turnleft;

                         move;

                         move;

                         putbeeper;

            END-OF-EXECUTION

     

                         move;

                         turnoff

    END-OF-PROGRAM

문법적 에러 - 이 명령어는 프로그램의 두번째 줄에 있어야 한다.

문법적 에러 - 이 명령어는 프로그램의 첫번째 줄에 있어야 한다.

 

 

 

구두점 에러 - ';' 이 없다.

 

 

 

문법적 에러 - 여기에 있어야 할 문장이 아니다.

 

 

 

프로그램에 어휘 또는 문법적 에러가 있다면 로봇은 프로그램을 읽으면서 에러들을 발견할 것이다. 이 두 에러에 대하여 로봇은 우리가 무슨 말을 하려고 했는지를 모르기 때문에 에러를 고칠 생각을 하지 않는다. 대신에 로봇은 우리에게 에러가 있다고 보고하고, 자신이 충분히 이해하지 못하는 프로그램을 실행할 수 없기 때문에 자신의 전원을 꺼버린다. 이것은 Error Shutoff 는 아니다. 왜냐하면 로봇이 프로그램의 실행을 시작조차 하지 않았기 때문이다. 다음으로는 남은 두 가지의 에러를 다룰 때는 로봇이 어휘나 문법적 에러를 발견할 수 없는 프로그램이고, 실행을 시작했다고 가정한다.

세 번째 에러는 실행 에러 (Execution Error) 이다. 어휘 및 문법적 에러와 같이 로봇은 이 에러도 감지해 낼 수가 있다. 로봇이 하나의 명령을 완벽하게 수행하지 못하고 Error Shutoff 를 해야 할 때 실행 에러가 발생한다. 다시 샌프란시스코에서 포틀랜드까지 가려는 운전자의 예로 돌아가서, 우리가 "오던 길로 쭉 800 마일만 가세요" 라고 했을 수도 있다. 하지만 그 상황에서 운전자가 서쪽을 향하고 있었고 우리가 준 명령을 말 그대로 이해를 하고 실행을 했다면 그는 몇 마일 가지 않아서 태평양을 바라보고 있을 것이다. 이 상황에서 그 운전자는 우리의 명령이 실행될 수 없다는 사실을 깨닫고 멈출 것이다.

비슷하게, 로봇은 자신이 완벽하게 수행할 수 없는 기본 명령을 받았을 때 Error Shutoff 를 실행한다. 앞이 막혀있는데 로봇에게 move 라는 명령을 내린다거나, 비퍼가 없는데 pickbeeper 라는 명령을 하거나, 비퍼백이 비어있는데 putbeeper 라는 명령을 내릴 때 등 모두가 다 실행 에러 (Execution Error) 의 한 종류가 된다. 이 모든 상황에서 로봇은 Error Shutoff 를 실행하게 된다.

마지막 에러가 가장 어렵다. 왜냐하면 로봇이 이런 종류의 에러는 감지하지 못하기 때문이다. 이것을 함의적 에러 (Intent Error) 라고 부른다. 로봇이 당신이 준 프로그램은 끝까지 완벽하게 실행을 했는데, 당신이 의도한 임무는 완벽하게 수행하지 못하였을 때 함의적 에러가 발생하였다고 한다. 예를 들어 그 운전자가 남쪽을 향하고 있는데, 우리가 "오던 길로 쭉 800 마일만 가세요" 라고 했다고 가정해 보자. 이 명령을 그 운전자가 제대로 끝까지 실행을 할 수는 있다. 하지만 실행 후에 그는 포틀랜드가 아닌 멕시코 어딘가에 위치하게 될 것이다 (위의 실행 에러와 다른 이유는 실행 에러에서는 더 이상 육지가 없기 때문에 800 마일을 가라는 우리의 얘기를 그 운전자가 실행할 수 없는 것이고, 함의적 에러는 그 운전자가 800 마일을 갈 수는 있지만 우리가 포틀랜드로 가게 하려는 의도와는 달리 엉뚱한 곳에 가있게 되는 것이다).

다음은 프로그램에서의 함의적 에러를 나타낸 것이다. 로봇은 비퍼를 주워 북쪽으로 1 칸 이동한 후, 비퍼를 내려놓고, 1 칸 더 북쪽으로 이동하고 turnoff 해야 한다 ([그림 4] 를 참고하라).

program ~~~~~

    BEGINNING-OF-PROGRAM

            BEGINNING-OF-EXECUTION

                         move;

                         pickbeeper;

                         move;

                         turnleft;

                         putbeeper;

                         move;

                         turnoff

            END-OF-EXECUTION

    END-OF-PROGRAM

이 프로그램에는 어휘, 문법, 실행 에러는 없다. 로봇의 입장에서 보았을 때, 그가 turnoff 를 실행하는데 있어서까지 아무런 에러도 없이 모든 것은 완벽하다. 하지만 임무와 프로그램을 살펴보아라. 무엇이 문제인지 알겠는가? 임무는 로봇이 비퍼를 북쪽으로 1 칸 옮기도록 하는 것이었는데, 로봇은 비퍼를 동쪽으로 1 칸 옮겨놓았다. 우리가 의도한 것은 북쪽으로 이동하는 것이었는데, 마지막 결과는 동쪽으로 이동된 비퍼였다. 이 프로그램은 우리가 제시해 놓은 임무를 충실히 수행하지 못했다. 그러므로 이 프로그램에는 함의적 에러가 있는 것이다.

그림 4  로봇의 초기 상황

로봇은 우리가 어떠한 임무를 수행하도록 프로그램을 작성하였다는 사실을 모르고 있다는 것을 알아야 한다. 로봇이 할 수 있는 것은 프로그램에 적힌 명령어들을 그대로 실행할 수 있는 일뿐이다. 그러므로 우리가 원했던 일을 로봇이 수행하지 못했다는 사실을 알 리가 없다.

종종 함의적 에러는 프로그램의 처음 부분에서 발생하여 후반에 가서는 실행 에러로 발전해 나간다. 로봇이 한 번 방향을 잘못 틀거나, 엉뚱하게 움직이면, 로봇이 벽을 뚫고 가려는 움직임을 한다든지, 비퍼가 없는데 pickbeeper 명령을 수행하려고 하는 것은 시간 문제이다. 그렇기 때문에 Error Shutoff 가 발생했다고 해서 그 순간에 실행되었던 명령만 잘못되었다고 생각해서는 안 된다. 그 전에 실행되었던 명령들이 이제서야 문제를 일으킨 것일 수도 있기 때문이다. 이와 같은 경우에는 로봇이 Error Shutoff 를 한 순간에서부터 잘못이 어디에 있는지, 어떤 명령으로부터 잘못된 길에 접어들었는지 역추적해 나가야 한다. 이와 같은 상황을 해결할 수 있도록 연습 문제 1 번에 함의적 에러와 실행 에러가 혼합된 문제를 실었다.

① 버그 (Bugs) 와 디버깅 (Debugging)

프로그래밍 언어로 모든 종류의 에러를 버그 (Bug) 라고 한다. 이 용어의 기원으로는 여러 가지가 있다. 한 이야기에서는 버그라는 단어가 전화 회사 엔지니어들로부터 유래되었다고 한다. 그들은 전기회로 상에서 발생하는 여러 가지 소리를 지칭하는데 버그라는 단어를 사용하였고 "회로 안에 벌레가 있다" 는 형태로 표현을 했다고 한다. 또 다른 이야기는 Admirla Grace Murray Hopper 와 Harvard Mark I Computer 로부터 유래되었다는 것이다. Mark I Computer 가 잘못된 답안을 내놓자, 기술자들은 문제를 해결하기 위해 컴퓨터를 분해해 보았다. 릴레이의 접속 부분에 죽은 나방이 문제를 발생시키는 것을 알게 되었고, 이것이 바로 세계 최초의 컴퓨터 버그라고 불린다. 다른 여러 이야기들도 많기 때문에 이 단어의 실질적인 기원을 알기는 쉽지 않을 것 같다.

버그라는 용어는 프로그래머들이 자신의 프로그램에 많은 에러가 있다는 사실을 실토하기 싫어하는 자존심 때문에 더 널리 퍼져 사용되고 있다고 한다. 즉, 그들은 자신의 프로그램에 버그가 있다고 말하는 것을 더 즐겼다. 버그를 발견하기는 쉽지 않지만 발견된 버그는 처리하기가 쉽기 때문에 이런 비유는 매우 적절하다고 볼 수 있다. 그렇지만 그 프로그램에서 모든 버그들이 발견되어 제거되었다고 보장하기는 쉬운 일이 아니다. 디버깅 (Debugging) 이란 프로그래머가 자신들의 프로그램에서 에러를 없애는 과정을 말한다.

3. 프로그래밍 요약

>> 기본명령어 <<

>> 블록 구조 명령어 <<

 >> 조건부 명령어들 <<

>> 반복 명령어들 <<

>> 새로운 명령어를 정의하는 방법 <<

>> 완전한 프로그램 <<

>> 단어 요약 <<