진동 액션

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();
 }

Vibration 액션의 객체를 얻기 위해서는 Action 클래스의 obtain(actionId:String) 메소드에서 actionId에 Action.Vibration.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.Vibration.ID); // 액션 객체를 얻는다.

 function onInitialized(robot:Robot):void
 {
 }

 function onExecute():void
 {
 }

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

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

Vibration 액션에는 진동의 지속 시간을 나타내는 디바이스로 COMMAND_TIME이 있다. 진동의 지속 시간을 1000분의 1초 단위(ms)로 나타내며, 0부터 65535까지의 값을 가질 수 있다.

 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.Vibration.ID);
 var timeDevice:Device = action.findDeviceById(Action.Vibration.COMMAND_TIME);
 timeDevice.write(100); // 진동의 지속 시간을 쓴다.

 function onInitialized(robot:Robot):void
 {
 }

 function onExecute():void
 {
 }

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

이제 알버트 로봇이 전진하다가 장애물을 만나면 진동을 울리도록 해보자.

 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 leftProximityDevice:Device;
 var rightProximityDevice:Device;
 var leftWheelDevice:Device;
 var rightWheelDevice:Device;
 
 var action:Action = Action.obtain(Action.Vibration.ID);
 var timeDevice:Device = action.findDeviceById(Action.Vibration.COMMAND_TIME);
 timeDevice.write(100);

 function onInitialized(robot:Robot):void
 {
     leftProximityDevice = robot.findDeviceById(Albert.SENSOR_LEFT_PROXIMITY);
     rightProximityDevice = robot.findDeviceById(Albert.SENSOR_RIGHT_PROXIMITY);
     leftWheelDevice = robot.findDeviceById(Albert.EFFECTOR_LEFT_WHEEL);
     rightWheelDevice = robot.findDeviceById(Albert.EFFECTOR_RIGHT_WHEEL);
 }

 function onExecute():void
 {
     var leftProximity:int = leftProximityDevice.read();
     var rightProximity:int = rightProximityDevice.read();
     if(leftProximity > 50 || rightProximity > 50)
     {
         leftWheelDevice.write(0);
         rightWheelDevice.write(0);
         action.activate(); // 액션을 시작한다.
     }
     else
     {
         leftWheelDevice.write(20);
         rightWheelDevice.write(20);
     }
 }

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

프로그램을 실행하고 앞으로 달려가는 알버트 로봇의 앞을 손으로 막으면 전방 센서의 값이 50보다 커져서 알버트 로봇이 정지하고 스마트 폰의 진동이 울릴 것이다.

02. 후진합니다. 비켜 나세요.

장애물을 만나면 뒤로 후진하면서 뚜뚜뚜 빠르게 진동을 울리도록 해보자. 대신, 전진할 때는 알버트 로봇의 심장 박동을 진동으로 표현하도록 하자.

알버트 로봇이 전진할 때는 진동을 천천히 울리고, 앞에 장애물이 나타나면 후진하면서 빠르게 진동을 울리는 프로그램을 작성하시오.

앞에서 작성한 프로그램을 약간 수정하면 되는데, 진동을 계속 울리는 것이 아니라 뚜뚜뚜 울리도록 하기 위해서는 진동 패턴을 만들어야 한다.

두 가지 진동 패턴이 있기 때문에 진동 액션을 두 개 얻어서 경우에 따라 다른 액션을 시작하면 된다고 생각할 수 있지만 같은 ID를 가진 액션은 여러 개 만들 수 없다. 따라서 전진할 때와 후진할 때 진동 패턴만 다르게 주면 된다.

또한 액션이 시작되어 실행되고 있는 중에 activate() 메소드를 호출하면 액션이 다시 시작되므로 플래그를 두어 다시 시작되지 않도록 하자.

 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 leftProximityDevice:Device;
 var rightProximityDevice:Device;
 var leftWheelDevice:Device;
 var rightWheelDevice:Device;
 var forward:Boolean = false;
 
 var action:Action = Action.obtain(Action.Vibration.ID);
 var patternDevice:Device = action.findDeviceById(Action.Vibration.COMMAND_PATTERN);
 var repeatDevice:Device = action.findDeviceById(Action.Vibration.COMMAND_REPEAT);
 repeatDevice.write(0); // 패턴의 처음부터 반복한다.

 function onInitialized(robot:Robot):void
 {
     leftProximityDevice = robot.findDeviceById(Albert.SENSOR_LEFT_PROXIMITY);
     rightProximityDevice = robot.findDeviceById(Albert.SENSOR_RIGHT_PROXIMITY);
     leftWheelDevice = robot.findDeviceById(Albert.EFFECTOR_LEFT_WHEEL);
     rightWheelDevice = robot.findDeviceById(Albert.EFFECTOR_RIGHT_WHEEL);
 }

 function onExecute():void
 {
     var leftProximity:int = leftProximityDevice.read();
     var rightProximity:int = rightProximityDevice.read();
     if(leftProximity > 50 || rightProximity > 50)
     {
         leftWheelDevice.write(-20);
         rightWheelDevice.write(-20);
         if(forward)
         {
             forward = false;
             patternDevice.writeArray([ 0, 100, 100 ]); // 빠른 진동 패턴을 쓴다.
             action.activate();
         }
     }
     else
     {
         leftWheelDevice.write(20);
         rightWheelDevice.write(20);
         if(!forward)
         {
             forward = true;
             patternDevice.writeArray([ 0, 100, 1000 ]); // 느린 진동 패턴을 쓴다.
             action.activate();
         }
     }
 }

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