置頂文字

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

2015年3月31日 星期二

LEGO NXT 網路影片分享

LEGO NXT  網路影片分享


這簡直要膜拜Orz....太強了!!









各式各樣的軌蹟車與跑法值得參考。




WRO 國小組題目....厲害!!

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


2015年3月22日 星期日

Lejos 重要的座標類別 lejos.robotics.navigation

Lejos 重要的座標類別 lejos.robotics.navigation,提供LEGO NXT一個完整的座標系統(X軸、Y軸),當navigation物件被建立出來時的座標為(0,0),而座標上的角度是NXT與X軸之間的夾角來表示方向,且角度的增加是以逆時針方向來累計。


goTo(float X座標,float Y座標);    //移動到指定座標位置

指定座標後機器人會直線前進移動到該做標點。


setPos(float x座標,float y座標,float 角度);    //重設NXT位置與方向


//-------------------------------------------

distanceTo(float X座標,float Y座標);    //取得目前位置與座標位置距離

float x1=navi.distanceTo(50f,80f);


//-------------------------------------

angleTo(float X座標,float Y座標);        // 取得目前位置與座標位置的夾角



rotateUpdate(float X座標,float );

rotateLeft();     //原地左轉  =  streer(200)

rotateRight();  //原地右轉 =  streer(-200)

getPos();     //取得機器目前位置與角度資訊

Pose pos=navi.getPose();

float x1=pos.getX();
float y1=pos.getY();

Point plc=pos.getLocation();    //取得座標點 (X,Y)
float lw=pos.getHeading();      //取得方向


//-------------------------------------






Lejos 重要的馬達兩輪類別 lejos.robotics.DifferentialPilot

Lejos 重要的馬達兩輪類別 lejos.robotics.DifferentialPilot;


原先是lejos.robotics.navigation.TachoPilot  但已經找不到該類別。
lejos.robotics.navigation. LegacyPilot ;  //有一段說明
The LegacyPilot class is a renamed version the TachoPilot class in the 0.85 release
目前仍可使用但不建議,因為已經快停用了(如下圖提示deprecated)。







當NXT設定左右雙輪行走模式總會發現NXT走一直線時總是會越走越偏(不是偏左就是偏右),因為我們在下達指令時都只針對單一馬達,因此就算馬達電力、角度指令完全相同也會發現NXT越走越偏。

這是因為我們沒有隨時隨地收集2顆馬達供電或是轉速資料並分析後讓NXT做出供電或是轉速修正,實際上這是個大工程但也是必要的資訊分析。

Lejos 或是  NXC 都有這類已經開發好的模組類別讓我們使用,這次就是要紀錄lejos裡面的 robotics類別。

import lejos.robotics.navigation.DifferentialPilot;

1.TachoPilot(float 輪子直徑,float 兩輪距離,Motor.A 左馬達,Motor.B 右馬達);

2.TachoPilot(float , float , Motoor.A , Motor.B ,  true/false 是否反向);

3.TachoPilot(float 左輪直徑 , float 右輪直徑 , float 兩輪距離 , Motoor.A , Motor.B ,  true/false 是否反向);


Example
TachoPilot pilot=new TachoPilot(60f , 140f , Motor.A , Motor.B);

TachoPilot常用方法

forward()
backward()
stop()
setSpeed();            //同時設定移動速度與轉彎速度
setMoveSpeed();   //只設定移動時的速度
setTurnSpeend();   //只設定轉彎時的速度

以上速度單位都是(度/秒)

//------------------------


getSpeed();
getMoveSpeed();
getTurnSpeed()


//--------------------------


travel();   //直線行走到特定距離
travel(100f) ;    //前進
travel(-100f);   //後退


rotate();   //原地迴轉某一角度


//----------------------------------------

轉彎率:
steer(float 轉彎率);    //參數: -200 ~  200

streer(200f);   //原地逆時針選轉
streer(-200f);   //原地順時針選轉

streer(100f);   //左輪停止,右輪前進
streer(-100f);   //右輪停止,左輪前進


//----------------------------

轉彎率+角度
streer(float 轉彎率,float 角度);    //轉彎到設定角度時停止

streer(0,90f);     //左右兩輪等速馬達轉到特定角度,所以直線前進

streer(25f,90f);   //左輪速度為外(右)輪的75%,左轉前進

streer(25f,-90f);   //左輪速度為外(右)輪的75%,左轉後退

streer(100f,90f);   //左輪停止,外(右)輪轉動,左轉前進

streer(-100f,90f);   //左輪停止,外(右)輪轉動,右轉前進

streer(200f,90f);   //車子原地逆時針旋轉
streer(-200f,90f);   //車子原地順時針旋轉

//--------------------------------

streer(float 轉彎率,float 度,boolean 是否立即回傳);


//-----------------------------

isMoving();   //檢查是否正在移動

reset();   /重設左右馬達角度為 0

//---------------------------------------
forward()
backward()
stop()
isMoving(); //true/false是否在運轉
setSpeed();        //同時設定移動速度與轉彎速度
setMoveSpeed();    //只設定移動時的速度
setTurnSpeend();   //只設定轉彎時的速度
reset(); //將兩輪角度值重設為0

getSpeed()
getMoveSpeed()
getTurnSpeed()

robot.travel(100f); //直線前進或後退指定距離
robot.rotate(90f);  //原地旋轉角度
robot.steer(); //轉彎率

robot.steer(0); //直線前進
robot.steer(25f); //左輪出力25%轉動、右輪出力75%轉動=向左轉
robot.steer(-25f); //右輪輪出力25%轉動、左輪出力75%轉動=向右轉

robot.steer(200f); //原地逆時針旋轉
robot.steer(-200f); //原地順時針旋轉
robot.steer(100f); //左輪停止右輪轉動=向左轉
robot.steer(-100f); //右輪停止左輪轉動=向右轉

robot.steer(25f,90f); //左輪出力25%轉動、右輪出力75%轉動=向左轉90度
robot.steer(25f,-90f); //左輪出力25%轉動、右輪出力75%轉動=向左(後)轉90度
robot.steer(100f,90f); //左輪停止轉動、右輪出力100%轉動=向左轉90度
robot.steer(-100f,90f); //右輪停止轉動、左輪出力100%轉動=向右轉90度
robot.steer(200f,90f); //原地逆時針旋轉90度
robot.steer(-200f,90f); //原地順時針旋轉90度

robot.steer(200f,90f,true); //原地逆時針旋轉90度並即刻回傳資料,如果false就是等轉完才回傳資料

Lejos 馬達 Motor 紀錄

LEGO Mindstorms 的馬達(Motor)是最常使用的組件也是最需要了解的部份

樂高官網上EV3馬達照片


Motor 常用的指令:

   Motor.A.setSpeed(720);// 單位「度/秒」:設定每秒的轉動角度720度(2 RPM),也就是每秒轉2圈的速度(NXT會根據每個馬達實際的狀況或是物理性做調整供電,務必讓每個馬達能維持每秒2圈的速度),維持固定的速度

   Motor.A.forward();    // 開始前進用每秒轉2圈的速度前進
   Morot.A.backward();    // 開始後退用每秒轉2圈的速度後退
   Thread.sleep (1000);  //NXT 延遲1秒鐘,但馬達繼續轉1秒鐘
   Motor.A.stop();       //馬達立刻煞車

   Motor.A.getMode();    //取得馬達狀態 
   1:正轉(forward) 
   2:反轉(backward)  
   3:停止(stop)  
   4:解鎖(flt / float)


   Motor.A.isMoving();  //回傳 boolean 值 true/false
   Motor.A.isRegulating();   //回傳 bollean 值,取得是否啟用電力調整 true:是  false:否
   

   //----------------

   Motor.A.setPower(0~100);  //直接設定電力值,但由於馬達A、B、C各自有的損耗與物理性所以既使都給相同電力也會有不同的速度表現,

   Motor.A.getPower();   //讀取電力設定值


   Motor.A.regulaitionSpeen(true/false);   //開啟時NXT會調整電力來維持固定的轉動速度。
   Motor.A.regulaitionSpeen(true);  //轉速固定 與 setSpeed()類似,看運用的方式。
   Motor.A.regulaitionSpeen(false);  //電力固定 但馬達的會各自表現不同的速度 。

   Motor.A.isRegulating();   //回傳 bollean 值,取得是否啟用電力調整 true:是  false:否


   //-----------------
   
   
   Motor.A.rotate(360); //馬達正轉360度就立刻煞車,馬達轉動過程中NXT「會等待」馬達轉到360度才會繼續下個指令,每次執行時馬達會累計角度值。

   Motor.A.rotateTo(360); //馬達正轉360度就立刻煞車,馬達轉動過程中NXT「會等待」馬達轉到360度才會繼續下個指令,每次執行時馬達會先把且始角度設為0度。

   Motor.A.rotate(-720,true);  //馬達反轉720度,馬達轉動過程中NXT「不會等待」馬達轉到720度才執行下個指令,而是馬上執行下個指令。



   //-----------------------

   Motor.A.getTachoCount();   //讀取馬達「實際」轉動的角度,該指令是以馬達最初的角度0作為起始點而回傳一個整數值。

   Motor.A.resetTachoCount();   //重設馬達轉動的角度值:也就是之前馬達如果已經有累計值也會歸零。

   

   while(Motor.A.isMoving() :Thread.yield();

   int angle = Motor.A.getTachoCount(); // should be -360


   LCD.drawInt(angle,0,0);
    

   //-------------------------




   Motor.A.flt();   //馬達解鎖,當NXT供電且程式執行時,馬達因為供電的關係而無法用手轉動,這時如果用手硬轉動馬達會傷及馬達與裡面的齒輪,因此請注意不要這麼做。

   Motor.A.lock(30); //參數值代表電力1~100,當馬達負荷重物時(例如吊掛零件)而又必須維持馬達不動,可以用lock(1~100)鎖定馬達不動。預設值為30


   Motor.A.serBreakPower(20);   //馬達轉動時設定煞車力道(電力)

   Motor.A.smoothAcceleration(true/false); //開啟時可以讓馬達在改變速度時更為平滑,不然當馬達在速度起伏較大時NXT會有停頓感,預設為開啟true


   Motor.A.reversDirection();  //根據之前馬達的設定參數但是做反方向的轉動。

蘋果電腦在 Eclipse 安裝Lejos須注意的事項

蘋果電腦 Eclipse 安裝Lejos須注意的事項,除了下載Mac版本的 Lejos外也必須在Eclipse裡面Preferences中設定 Lejos >> NXJ_Home的實際位置,這樣在開發Lejos專案時才不會發生錯誤。另外如果你跟我一樣用NXT那Eclipse 要安裝32Bit版本的 Eclipse,因為我安裝64bit版本在撰寫程式時沒問題但要upload程式到NXT時會有錯誤訊息「this java instance does not support a 32-bit JVM」,我移除64bit重新安裝32bit Eclipse就能順利執行Lejos程式





Eclipse 安裝 Lejos PlugIn



在Work with中輸入 http://www.lejos.org/tools/eclipse/plugin/nxj/


2015年3月19日 星期四

Lejos Java 常用語法紀錄

這篇要紀錄Lejos Java常用語法與參數,不然一堆語法、參數資料每次都要翻書、上網找,不如有用到就紀錄下來


Java 是個非常強大的程式語言,尤其是物件導向能夠讓程式碼條理分明。
‧ 這裡有個網站介紹 Java 語法可以作為入門導覽

1.ColorSensor 顏色參數

int brightness=0;
int colorID=0;

ColorSensor color = new ColorSensor(SensorPort.S2);  //設定ColorSensorPort位置

brightness = color.getLightValue(); //讀取亮度、明暗度用於軌跡車

colorID=color.getColorID();  //讀取顏色碼 -1 ~12如上表

LCD.drawString("Brightness=" + brightness, 0, 0);
LCD.drawString("ColorID=" + colorID, 0, 2);



2.Lejos Java程式因為不像NXT-G或是NXC程式執行時按 Escape鍵就能離開執行程式,所以在程式開始的地方要自己寫進去Escape按下去時離開執行程式,不然程式會一直執行除非要拆電池才能停止程式執行。


public static void main(String[] args) {

        Button.ESCAPE.addButtonListener(new ButtonListener(){

                     //因為事界面所以要實做兩個 Event :buttonPressed與buttonReleased

public void buttonPressed(Button b){
                              System.exit(1);   //離開程式
                        }

                       //java語法規定界面實做時就算沒用到也要實做,不然程式編譯會有Error
public void buttonReleased(Button b){

                      }
});
}


3.時間延遲函數:Delay.msDelay(毫秒)  1000毫秒=1秒
NXT在執行程式時很常用到 Delay因為有些Seneor在讀取資料或是馬達動作時需要有緩衝時間讓NXT處資料,因此Delay會常常出現在程式各處。


LEGO mindstorms NXT 執行Java的準備動作

許多人一開始入手LEGO   Mindstorms 都是用原廠程式NXT-G來玩NXT,但只要程式複雜一點時都會發現變數的儲存、讀取、邏輯判斷都會讓畫面上的圖形複雜,其實這些變數與邏輯判斷在Java、NXC程式上都非常簡單明瞭反而更清楚程式流程。所以當原場NXT-G無法滿足你時可以試試 Lejos Java、 NXC、LabVIEW,當然刷機後都可以刷回LEGO原廠的Firmware所以不用擔心「回不去!!」

樂高LEGO Mindstorms NXT要能執行Java 程式的首要動作就是刷機,網路上的資訊很多我把步驟紀錄下來。

1.下載 Lejos最新版的韌體 firmware  ,請選擇對應要刷機的機型EV3、NXT、RCX




2.下載WIndows或是Mac的刷機軟體,安裝後就有Lejos刷機軟體了


3.執行刷機程式,如果Lejos沒抓到你的機器代表須安裝對應 Lego driver 讓電腦能讀取,請注意一定要電力飽滿的電池,我就發生在80%更新時USB線突然離線NXT Brick變磚,變磚後螢幕沒有任何訊息只有機身發生滴答、滴答聲,最後重刷還好能復活正常運作。(刷機有風險請自行評估)

電腦選單上找到NXJ Flash



準備執行刷機前LEGO NXT請開機讓刷機程式透過USB線能抓到機器,連線後程式會詢問是否要執行刷機接著就是回答Yes後開始刷機了。


刷機成功應該會有下面這兩張圖的樣子,接這就是可以開發Lejos Java程式到NXT上執行






4.當刷機成功後就是安裝開發環境Eclipse,首先下載JRE、JDK然後解壓縮在指定目錄,再來就是安裝Lejos Plugin
執行Install New Software



在Work with 輸入「http://www.lejos.org/tools/eclipse/plugin/nxj/

5.完成以上步驟後就能在 Eclipse IDE環境上開發並Upload到 LEGO NXT Brick上執行Java程式,當然在開發過程中會有一些小狀況像是程式語法錯誤、電腦抓不到NXT 等,請慢慢測試找出問題例如driver 32bit/64bit 、軟體對應版本等。
開新專案撰寫簡單測試程式Upload 到NXT上執行


6.如果你真的不幸刷機失敗機器變磚,請參考下面這些資訊




其實只要電腦能抓到NXT機身都代表有機會重刷,所以問題多在LEGO Driver是否正常有時需要移除driver重裝,因為現在windows有32bit/64bit區分有時候driver64bit出問題時請找台32bit的電腦重刷,我就是在windows7 64bit有時抓的到有時抓不到NXT後來找台舊電腦windows XP接上USB線就抓到了...重刷復活,以上方法都無效時請洽樂高原廠服務。