위치 인식 액션

01. 펜 제스처

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

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

로봇을 움직이기 위해 RobotActivity 클래스를 상속한 액티비티를 만들고, onInitialized(Robot) 메소드와 onExecute() 메소드를 상속받아 새로 구현하자. Activity 클래스의 onDestroy() 메소드도 상속받아 새로 구현하고, 프로젝트에 스마트 로봇 라이브러리를 포함하는 것을 잊지 않기를 바란다.

 public class SampleActivity extends RobotActivity
 {
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
     }

     @Override
     public void onDestroy()
     {
         super.onDestroy();
     }

     @Override
     public void onInitialized(Robot robot)
     {
     }

     @Override
     public void onExecute()
     {
     }
 }

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

 public class SampleActivity extends RobotActivity
 {
     private Action mAction;

     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);

         mAction = Action.obtain(this, Action.Localization.ID); // 액션 객체를 얻는다.
         mAction.activate(); // 액션을 시작한다.
     }

     @Override
     public void onDestroy()
     {
         super.onDestroy();

         mAction.deactivate(); // 액션을 중지한다.
         mAction.dispose(); // 액션을 폐기한다.
     }

     @Override
     public void onInitialized(Robot robot)
     {
     }

     @Override
     public void onExecute()
     {
     }
 }

onCreate(Bundle savedInstanceState) 메소드에서 액션을 얻어서 시작하고 onDestroy() 메소드에서 액션을 중지 및 폐기하였지만 어디에서 해도 상관은 없다. 애플리케이션을 종료하기 전에 액션을 모두 폐기하여야 한다는 것만 잊지 않도록 하자.

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

 public class SampleActivity extends RobotActivity
 {
     private Action mAction;
     private Device mPadSizeDevice;

     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);

         mAction = Action.obtain(this, Action.Localization.ID);
         mPadSizeDevice = mAction.findDeviceById(Action.Localization.COMMAND_PAD_SIZE);
         mPadSizeDevice.write(0, 108); // 가로 크기
         mPadSizeDevice.write(1, 76); // 세로 크기
         mAction.activate();
     }

     @Override
     public void onDestroy()
     {
         super.onDestroy();

         mAction.deactivate();
         mAction.dispose();
     }

     @Override
     public void onInitialized(Robot robot)
     {
     }

     @Override
     public void onExecute()
     {
     }
 }

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

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

 public class SampleActivity extends RobotActivity
 {
     private Action mAction;
     private Device mPadSizeDevice;
     private Device mOIDDevice;
     private Device mPositionDevice;

     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);

         mAction = Action.obtain(this, Action.Localization.ID);
         mPadSizeDevice = mAction.findDeviceById(Action.Localization.COMMAND_PAD_SIZE);
         mOIDDevice = mAction.findDeviceById(Action.Localization.COMMAND_OID);
         mPositionDevice = mAction.findDeviceById(Action.Localization.SENSOR_POSITION);
         mPadSizeDevice.write(0, 108);
         mPadSizeDevice.write(1, 76);
         mAction.activate();
     }

     @Override
     public void onDestroy()
     {
         super.onDestroy();

         mAction.deactivate();
         mAction.dispose();
     }

     @Override
     public void onInitialized(Robot robot)
     {
     }

     @Override
     public void onExecute()
     {
     }
 }

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

 public class SampleActivity extends RobotActivity
 {
     private Action mAction;
     private Device mPadSizeDevice;
     private Device mOIDDevice;
     private Device mPositionDevice;
     private Device mPenOIDDevice;

     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);

         mAction = Action.obtain(this, Action.Localization.ID);
         mPadSizeDevice = mAction.findDeviceById(Action.Localization.COMMAND_PAD_SIZE);
         mOIDDevice = mAction.findDeviceById(Action.Localization.COMMAND_OID);
         mPositionDevice = mAction.findDeviceById(Action.Localization.SENSOR_POSITION);
         mPadSizeDevice.write(0, 108);
         mPadSizeDevice.write(1, 76);
         mAction.activate();
     }

     @Override
     public void onDestroy()
     {
         super.onDestroy();

         mAction.deactivate();
         mAction.dispose();
     }

     @Override
     public void onInitialized(Robot robot)
     {
         mPenOIDDevice = robot.findDeviceById(1, Pen.EVENT_OID);
     }

     @Override
     public void onExecute()
     {
         if(mPenOIDDevice.e())
             mOIDDevice.write(mPenOIDDevice.read());
         int x = mPositionDevice.read(0);
         int y = mPositionDevice.read(1);
     }
 }

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

 public class SampleActivity extends RobotActivity
 {
     private Action mAction;
     private Device mPadSizeDevice;
     private Device mOIDDevice;
     private Device mPositionDevice;
     private Device mPenOIDDevice;
     private Device mLeftWheelDevice;
     private Device mRightWheelDevice;
     private int mOldX, mOldY;
     private boolean mReset = true;

     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);

         mAction = Action.obtain(this, Action.Localization.ID);
         mPadSizeDevice = mAction.findDeviceById(Action.Localization.COMMAND_PAD_SIZE);
         mOIDDevice = mAction.findDeviceById(Action.Localization.COMMAND_OID);
         mPositionDevice = mAction.findDeviceById(Action.Localization.SENSOR_POSITION);
         mPadSizeDevice.write(0, 108);
         mPadSizeDevice.write(1, 76);
         mAction.activate();
     }

     @Override
     public void onDestroy()
     {
         super.onDestroy();

         mAction.deactivate();
         mAction.dispose();
     }

     @Override
     public void onInitialized(Robot robot)
     {
         mPenOIDDevice = robot.findDeviceById(1, Pen.EVENT_OID);
         mLeftWheelDevice = robot.findDeviceById(Albert.EFFECTOR_LEFT_WHEEL);
         mRightWheelDevice = robot.findDeviceById(Albert.EFFECTOR_RIGHT_WHEEL);
     }

     @Override
     public void onExecute()
     {
         if(mPenOIDDevice.e())
             mOIDDevice.write(mPenOIDDevice.read());
         int x = mPositionDevice.read(0);
         int y = mPositionDevice.read(1);

         if(x < 0 || y < 0)
         {
             mReset = true;
             mLeftWheelDevice.write(0);
             mRightWheelDevice.write(0);
         }
         else if(mReset)
         {
             mReset = false;
             mOldX = x;
             mOldY = y;
         }
         else
         {
             int dx = x - mOldX;
             int dy = y - mOldY;
             if(dx != 0 &&  dy != 0)
             {
                 if(Math.abs(dx) > Math.abs(dy))
                 {
                     if(dx > 0)
                     {
                         mLeftWheelDevice.write(20);
                         mRightWheelDevice.write(-20);
                     }
                     else
                     {
                         mLeftWheelDevice.write(-20);
                         mRightWheelDevice.write(20);
                     }
                 }
                 else
                 {
                     if(dy > 0)
                     {
                         mLeftWheelDevice.write(20);
                         mRightWheelDevice.write(20);
                     }
                     else
                     {
                         mLeftWheelDevice.write(-20);
                         mRightWheelDevice.write(-20);
                     }
                 }
             }
         }
     }
 }