置頂文字

歡迎來訪 !! 如有任何問題歡迎一起討論或是 eMail 給我 legorunmail@Gmail.com

2015年3月23日 星期一

Lejos 重要的行為類別 Lejos.subsumption.Behavior

Lejos.subsumption.Behavior  行為類別

如果NXT接了TouchSensor、LightSensor、UltraSonic偵測設備,而我們必須根據這三種設備回傳的資料做判斷,在傳統程式while(true){...}必須一直做迴圈判斷以避免這三種資料互相衝突。

例如TouchSensor要倒退20公分、UltraSonic測到距離範圍是要前進,這時NXT是要前進還是後退呢???有時候就會看到NXT一下前進一下後退。這是因為這三種回傳資料沒優先順序,通常我們會加入許多判斷旗號True、False來輔助,不過實際會發現有些旗號不會如你預定的流程走該True的時候竟然還是False,這種經驗相信很多人都曾有過。

而Lejos在類別Class已經加入了行為模式Behavior  讓我們應用,因為行為模式讓我們自己定義優先順序因此在程式撰寫時就不會雜亂無章,TouchSensor與UltraSonic一定要定義誰先誰後這樣一來程式就比較好維護,NXT在執行時也不會亂成一團。




Interface Behavior 屬於界面因此有3個必須實做的方法(Method)

1.
boolean takeControl():如果該定義行為被啟動時傳回true
例如TouchSensor被碰觸時就會回傳true

Returns a boolean value to indicate if this behavior should become active. For example, if a touch sensor indicates the robot has bumped into an object, this method should return true. This method should return quickly, not perform a long calculation.

2.
void action() :被啟用時的需要執行動作
例如TouchSensor被碰觸時需要後退Motor.A.backward 並轉向

The code in this method begins performing its task when the behavior becomes active. For example, if takeControl() detects the robot has collided with an object, the action() code could make the robot back up and turn away from the object.

A behavior is active as long as its action() method is running, so the action() method should exit when its task is complete. Also, the action() method should exit promptly when suppress() is called. When it exits, it should leave the robot in a safe state for the next behavior.

3.
void suppress() :
仲裁者(Arbitrator) 呼叫 suppres()時會立刻停止 void action()的執行動作

The code in the suppress() method should immediately terminate the code running in the action() method. It also should exit quickly.

仲裁者(Arbitrator)依行動者(behaviors)陣列索引由大至小來進行,因此那個行為最高優先的要放最後面。
仲裁者(Arbitrator)先檢查boolean takeControl()是否回傳Ture,接著執行void action(),這期間如果有其他更高優先權的行為發生時仲裁者(Arbitrator)會執行現在行為的void suppress() ,因此程式在執行時必須要注意void suppress()的變化來決定是否要停止或繼續執行。


因此有上述三種行為定義時就可以讓我們開發程式時能適當的使用


Lejos官網上的範例程式如下
準備NXT+2顆馬達+LightSensor
LightSensor接Port1
馬達接B、C

package org.lejos.sample.linefollower;
import lejos.nxt.Button;
import lejos.nxt.LCD;
import lejos.nxt.LightSensor;
import lejos.nxt.SensorPort;
import lejos.robotics.RegulatedMotor;
import lejos.robotics.navigation.DifferentialPilot;
import lejos.robotics.navigation.RotateMoveController;
import lejos.robotics.subsumption.Arbitrator;
import lejos.robotics.subsumption.Behavior;
import lejos.util.PilotProps;

/**
 * Demonstration of use of the Behavior and Pilot classes to
 * implement a simple line following robot.
 *
 * Requires a wheeled vehicle with two independently controlled
 * wheels with motors connected to motor ports A and C, and a light
 * sensor mounted forwards and pointing down, connected to sensor port 1.
 *
 * Press ENTER to start the robot.
 *
 * You can run the PilotParams sample to create a property file which
 * sets the parameters of the Pilot to the dimensions
 * and motor connections for your robot.
 *
 * @author Lawrie Griffiths
 *
 */
public class LineFollower {

public static void main (String[] aArg)
throws Exception
{
      PilotProps pp = new PilotProps();
    pp.loadPersistentValues();
    float wheelDiameter = Float.parseFloat(pp.getProperty(PilotProps.KEY_WHEELDIAMETER, "4.96"));
    float trackWidth = Float.parseFloat(pp.getProperty(PilotProps.KEY_TRACKWIDTH, "13.0"));
    RegulatedMotor leftMotor = PilotProps.getMotor(pp.getProperty(PilotProps.KEY_LEFTMOTOR, "B"));
    RegulatedMotor rightMotor = PilotProps.getMotor(pp.getProperty(PilotProps.KEY_RIGHTMOTOR, "C"));
    boolean reverse = Boolean.parseBoolean(pp.getProperty(PilotProps.KEY_REVERSE,"false"));
   
// Change last parameter of Pilot to specify on which
// direction you want to be "forward" for your vehicle.
// The wheel and axle dimension parameters should be
// set for your robot, but are not critical.
final RotateMoveController pilot = new DifferentialPilot(wheelDiameter, trackWidth, leftMotor, rightMotor, reverse);
final LightSensor light = new LightSensor(SensorPort.S1);
        pilot.setRotateSpeed(180);
        /**
         * this behavior wants to take control when the light sensor sees the line
         */
Behavior DriveForward = new Behavior()
{
public boolean takeControl() {
return light.readValue() <= 40;
}

public void suppress() {
pilot.stop();
}
public void action() {
pilot.forward();
                while(light.readValue() <= 40)
                Thread.yield(); //action complete when not on line
}
};

Behavior OffLine = new Behavior()
{
private boolean suppress = false;

public boolean takeControl() {
return light.readValue() > 40;
}

public void suppress() {
suppress = true;
}

public void action() {
int sweep = 10;
while (!suppress) {
pilot.rotate(sweep,true);
while (!suppress && pilot.isMoving())
Thread.yield();
sweep *= -2;
}
pilot.stop();
suppress = false;
}
};

Behavior[] bArray = {OffLine, DriveForward};
        LCD.drawString("Line ", 0, 1);
        Button.waitForAnyPress();
   (new Arbitrator(bArray)).start();
}
}


沒有留言:

張貼留言