위치 인식 액션

01. 펜 제스처

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

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

새 프로젝트 만들기를 참고하여 안드로이드 프로젝트와 플래시 파일을 만들고, setOnInitialized(callback:Function) 메소드와 setOnExecute(callback:Function) 메소드를 사용하여 콜백 함수를 등록하자. 또한, 플래시가 종료될 때 호출되는 리스너 함수를 등록하고, activate() 메소드를 호출하여 스마트 로봇 론처와 연결하도록 하자.

 import flash.events.Event;
 import org.smartrobot.android.SmartRobot;
 import org.roboid.robot.Robot;

 NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, handleDeactivate, false, 0, true);
 SmartRobot.setOnInitialized(onInitialized);
 SmartRobot.setOnExecute(onExecute);
 SmartRobot.activate();

 function onInitialized(robot:Robot):void
 {
 }

 function onExecute():void
 {
 }

 function handleDeactivate(evt:Event):void
 {
     SmartRobot.deactivate();
 }

Localization 액션의 객체를 얻기 위해서는 Action 클래스의 obtain(actionId:String) 메소드에서 actionId에 Action.Localization.ID를 입력하면 된다.

 import flash.events.Event;
 import org.smartrobot.android.SmartRobot;
 import org.roboid.robot.Robot;
 import org.smartrobot.android.action.Action;

 NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, handleDeactivate, false, 0, true);
 SmartRobot.setOnInitialized(onInitialized);
 SmartRobot.setOnExecute(onExecute);
 SmartRobot.activate();
 
 var action:Action = Action.obtain(Action.Localization.ID); // 액션 객체를 얻는다.
 action.activate(); // 액션을 시작한다.

 function onInitialized(robot:Robot):void
 {
 }

 function onExecute():void
 {
 }

 function handleDeactivate(evt:Event):void
 {
     action.deactivate(); // 액션을 중지한다.
     action.dispose(); // 액션을 폐기한다.
     SmartRobot.deactivate();
 }

handleDeactivated 메소드에서 액션을 중지 및 폐기하였지만 어디에서 해도 상관은 없다. 플래시가 종료되기 전에 액션을 모두 폐기하여야 한다는 것만 잊지 않도록 하자.

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

 import flash.events.Event;
 import org.smartrobot.android.SmartRobot;
 import org.roboid.robot.Robot;
 import org.smartrobot.android.action.Action;
 import org.roboid.robot.Device;

 NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, handleDeactivate, false, 0, true);
 SmartRobot.setOnInitialized(onInitialized);
 SmartRobot.setOnExecute(onExecute);
 SmartRobot.activate();
 
 var action:Action = Action.obtain(Action.Localization.ID);
 var padSizeDevice:Device = action.findDeviceById(Action.Localization.COMMAND_PAD_SIZE);
 padSizeDevice.writeAt(0, 108); // 가로 크기
 padSizeDevice.writeAt(1, 76); // 세로 크기
 action.activate();

 function onInitialized(robot:Robot):void
 {
 }

 function onExecute():void
 {
 }

 function handleDeactivate(evt:Event):void
 {
     action.deactivate();
     action.dispose();
     SmartRobot.deactivate();
 }

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

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

 import flash.events.Event;
 import org.smartrobot.android.SmartRobot;
 import org.roboid.robot.Robot;
 import org.smartrobot.android.action.Action;
 import org.roboid.robot.Device;

 NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, handleDeactivate, false, 0, true);
 SmartRobot.setOnInitialized(onInitialized);
 SmartRobot.setOnExecute(onExecute);
 SmartRobot.activate();
 
 var action:Action = Action.obtain(Action.Localization.ID);
 var padSizeDevice:Device = action.findDeviceById(Action.Localization.COMMAND_PAD_SIZE);
 padSizeDevice.writeAt(0, 108);
 padSizeDevice.writeAt(1, 76);
 var oidDevice:Device = action.findDeviceById(Action.Localization.COMMAND_OID);
 var positionDevice:Device = action.findDeviceById(Action.Localization.SENSOR_POSITION);
 action.activate();

 function onInitialized(robot:Robot):void
 {
 }

 function onExecute():void
 {
 }

 function handleDeactivate(evt:Event):void
 {
     action.deactivate();
     action.dispose();
     SmartRobot.deactivate();
 }

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

 import flash.events.Event;
 import org.smartrobot.android.SmartRobot;
 import org.roboid.robot.Robot;
 import org.smartrobot.android.action.Action;
 import org.roboid.robot.Device;

 NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, handleDeactivate, false, 0, true);
 SmartRobot.setOnInitialized(onInitialized);
 SmartRobot.setOnExecute(onExecute);
 SmartRobot.activate();
 
 var penOIDDevice:Device;

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

 function onInitialized(robot:Robot):void
 {
     penOIDDevice = robot.findDeviceById(1, Pen.EVENT_OID);
 }

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

 function handleDeactivate(evt:Event):void
 {
     action.deactivate();
     action.dispose();
     SmartRobot.deactivate();
 }

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

 import flash.events.Event;
 import org.smartrobot.android.SmartRobot;
 import org.roboid.robot.Robot;
 import org.smartrobot.android.action.Action;
 import org.roboid.robot.Device;
 import kr.robomation.physical.Albert;

 NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, handleDeactivate, false, 0, true);
 SmartRobot.setOnInitialized(onInitialized);
 SmartRobot.setOnExecute(onExecute);
 SmartRobot.activate();
 
 var penOIDDevice:Device;
 var leftWheelDevice:Device;
 var rightWheelDevice:Device;
 var oldX:int = 0;
 var oldY:int = 0;
 var reset:Boolean = true;

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

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

 function onExecute():void
 {
     if(penOIDDevice.e())
         oidDevice.write(penOIDDevice.read());
     var x:int = positionDevice.readAt(0);
     var y:int = 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:int = x - mOldX;
         var dy:int = y - mOldY;
         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);
                 }
             }
         }
     }
 }

 function handleDeactivate(evt:Event):void
 {
     action.deactivate();
     action.dispose();
     SmartRobot.deactivate();
 }