위치 인식 액션

01. 펜 제스처

내비게이션 패드 위에서 펜의 위치를 알 수 있으면 글자 쓰기, 그림 그리기 등의 다양한 작업을 할 수 있다. 여기서는 펜의 위치를 이용하여 간단한 제스처를 인식하고 알버트 로봇을 움직여 보자.

내비게이션 패드 위에서 펜의 위치를 알아내는 프로그램을 작성하시오.

웹 페이지 만들기를 참고하여 안드로이드 프로젝트와 웹 페이지 파일을 만들자. onInitialized(robot) 콜백 함수와 onExecute() 콜백 함수를 만들고, 웹 페이지가 닫힐 때 호출되는 window.onunload 함수도 만들자.

 <script type="text/javascript">

 function onInitialized(robot)
 {
 }

 function onExecute()
 {
 }

 window.onunload = function()
 {
 }
 </script>

Localization 액션의 객체를 얻기 위해서는 Action 객체의 obtain(actionId) 함수에서 actionId에 Action.Localization.ID를 입력하면 된다.

 <script type="text/javascript">

 var action = Action.obtain(Action.Localization.ID); // 액션 객체를 얻는다.
 action.activate(); // 액션을 시작한다.

 function onInitialized(robot)
 {
 }

 function onExecute()
 {
 }

 window.onunload = function()
 {
     action.deactivate(); // 액션을 중지한다.
     action.dispose(); // 액션을 폐기한다.
 }
 </script>

window.onunload 함수에서 액션을 중지 및 폐기하였지만 어디에서 해도 상관은 없다. 웹 페이지가 닫히기 전에 액션을 모두 폐기하여야 한다는 것만 잊지 않도록 하자.

내비게이션 패드 위에서 움직여야 하므로 사용하는 내비게이션 패드의 크기를 입력하도록 하자. Localization 액션에는 패드 크기를 나타내는 디바이스로 COMMAND_PAD_SIZE가 있다. 여기서는 가로 108, 세로 76 크기의 패드를 사용하였다.

 <script type="text/javascript">

 var action = Action.obtain(Action.Localization.ID);
 var padSizeDevice = action.findDeviceById(Action.Localization.COMMAND_PAD_SIZE);
 padSizeDevice.writeAt(0, 108); // 가로 크기
 padSizeDevice.writeAt(1, 76); // 세로 크기
 action.activate();

 function onInitialized(robot)
 {
 }

 function onExecute()
 {
 }

 window.onunload = function()
 {
     action.deactivate();
     action.dispose();
 }
 </script>

Localization 액션은 OID 코드 값을 위치 값으로 변환하는 액션이다. OID 코드를 나타내는 디바이스로 COMMAND_OID가 있는데, 펜의 OID 이벤트 디바이스로부터 얻은 OID 코드 값을 그대로 입력해 주면 된다.

또한, 내비게이션 패드 위에서 위치를 알려주는 디바이스로 SENSOR_POSITION이 있다. X축과 Y축 좌표가 있으므로 위치 데이터는 크기 2의 배열로 되어 있으며, 각각 -1부터 39999까지의 값을 가질 수 있다. 좌표 값은 0부터 시작하기 때문에 0부터 39999까지는 유효한 값이고, -1은 현재 위치를 알지 못할 때 표시하는 값이다.

 <script type="text/javascript">

 var action = Action.obtain(Action.Localization.ID);
 var padSizeDevice = action.findDeviceById(Action.Localization.COMMAND_PAD_SIZE);
 var oidDevice = action.findDeviceById(Action.Localization.COMMAND_OID);
 var positionDevice = action.findDeviceById(Action.Localization.SENSOR_POSITION);
 padSizeDevice.writeAt(0, 108);
 padSizeDevice.writeAt(1, 76);
 action.activate();

 function onInitialized(robot)
 {
 }

 function onExecute()
 {
 }

 window.onunload = function()
 {
     action.deactivate();
     action.dispose();
 }
 </script>

이제 펜의 OID 코드 값을 넣어주고 위치 값을 읽어 보자.

 <script type="text/javascript">

 var penOIDDevice;
 var action = Action.obtain(Action.Localization.ID);
 var padSizeDevice = action.findDeviceById(Action.Localization.COMMAND_PAD_SIZE);
 var oidDevice = action.findDeviceById(Action.Localization.COMMAND_OID);
 var positionDevice = action.findDeviceById(Action.Localization.SENSOR_POSITION);
 padSizeDevice.writeAt(0, 108);
 padSizeDevice.writeAt(1, 76);
 action.activate();

 function onInitialized(robot)
 {
     penOIDDevice = robot.findPeripheralDeviceById(1, Pen.EVENT_OID);
 }

 function onExecute()
 {
     if(penOIDDevice.e())
         oidDevice.write(penOIDDevice.read());
     var x = positionDevice.readAt(0);
     var y = positionDevice.readAt(1);
 }

 window.onunload = function()
 {
     action.deactivate();
     action.dispose();
 }
 </script>

내비게이션 패드 위에서 펜을 위로 이동하면 로봇이 전진, 아래로 이동하면 후진, 오른쪽으로 이동하면 우회전, 왼쪽으로 이동하면 좌회전하도록 하고, 내비게이션 패드에서 펜을 떼면 로봇이 정지하도록 해보자. 펜을 너무 빨리 움직이면 OID 코드를 잘 읽지 못하기 때문에 펜을 천천히 이동시키도록 하자.

 <script type="text/javascript">

 var penOIDDevice;
 var leftWheelDevice;
 var rightWheelDevice;
 var oldX = 0;
 var oldY = 0;
 var reset = true;
 var action = Action.obtain(Action.Localization.ID);
 var padSizeDevice = action.findDeviceById(Action.Localization.COMMAND_PAD_SIZE);
 var oidDevice = action.findDeviceById(Action.Localization.COMMAND_OID);
 var positionDevice = action.findDeviceById(Action.Localization.SENSOR_POSITION);
 padSizeDevice.writeAt(0, 108);
 padSizeDevice.writeAt(1, 76);
 action.activate();

 function onInitialized(robot)
 {
     penOIDDevice = robot.findPeripheralDeviceById(1, Pen.EVENT_OID);
     leftWheelDevice = robot.findDeviceById(Albert.EFFECTOR_LEFT_WHEEL);
     rightWheelDevice = robot.findDeviceById(Albert.EFFECTOR_RIGHT_WHEEL);
 }

 function onExecute()
 {
     if(penOIDDevice.e())
         oidDevice.write(penOIDDevice.read());
     var x = positionDevice.readAt(0);
     var y = positionDevice.readAt(1);

     if(x < 0 || y < 0)
     {
         reset = true;
         leftWheelDevice.write(0);
         rightWheelDevice.write(0);
     }
     else if(reset)
     {
         reset = false;
         oldX = x;
         oldY = y;
     }
     else
     {
         var dx = x - oldX;
         var dy = y - oldY;
         if(dx != 0 &&  dy != 0)
         {
             if(Math.abs(dx) > Math.abs(dy))
             {
                 if(dx > 0)
                 {
                     leftWheelDevice.write(20);
                     rightWheelDevice.write(-20);
                 }
                 else
                 {
                     leftWheelDevice.write(-20);
                     rightWheelDevice.write(20);
                 }
             }
             else
             {
                 if(dy > 0)
                 {
                     leftWheelDevice.write(20);
                     rightWheelDevice.write(20);
                 }
                 else
                 {
                     leftWheelDevice.write(-20);
                     rightWheelDevice.write(-20);
                 }
             }
         }
     }
 }

 window.onunload = function()
 {
     action.deactivate();
     action.dispose();
 }