引言
機(jī)器人技術(shù)是綜合了計算機(jī)、控制論、機(jī)構(gòu)學(xué)、信息和傳感技術(shù)、人工智能、仿生學(xué)等多學(xué)科而形成的高新技術(shù),是當(dāng)代研究十分活躍,應(yīng)用日益廣泛的領(lǐng)域。機(jī)器人的應(yīng)用情況,是一個國家工業(yè)自動化水平的重要標(biāo)志。?
Java3D是美國Sun公司為了彌補(bǔ)Java語言在多媒體及圖形編程方面的不足而推出的一系列標(biāo)準(zhǔn)擴(kuò)展API,Java3D的推出使Java開發(fā)人員具備了開發(fā)三維視覺的小應(yīng)用程序和應(yīng)用程序,這些程序還具有與客戶交互的能力。這使得Java在視覺上,互動性上產(chǎn)生了一次飛躍。
基于Java3D的這種特性,本文在利用Java3D便利的,面向?qū)ο蟮娜S圖形程序設(shè)計來實現(xiàn)對工業(yè)機(jī)器人的建模與遠(yuǎn)程控制。
一 工業(yè)機(jī)器人技術(shù)簡介
現(xiàn)代機(jī)器人的歷史是從1959年美國英格伯格和德沃爾制造出世界上第一臺工業(yè)機(jī)器人開始的。機(jī)器人的發(fā)展大致經(jīng)歷了三個成長階段。第一代為簡單個體機(jī)器人,第二代為群體勞動機(jī)器人,第三代為類似人類的智能機(jī)器人。?
機(jī)器人的外形是多種多樣的,往往決定于它的功能,工作環(huán)境等,但有一個共同點:服從人類指令,代替人力自動工作。當(dāng)然,由于機(jī)器人的智能仍然有限,所以某些特殊的場合仍然需要人類對其進(jìn)行必要的控制,例如探測機(jī)器人。美國著名科普作家艾薩克.阿西莫夫為機(jī)器人提出了三條原則,即“機(jī)器人三定律”:?
第一定律——機(jī)器人不得傷害人,或任人受到傷害而無所作為;?
第二定律——機(jī)器人應(yīng)服從人的一切命令,但命令與第一定律相抵觸時例外;?
第三定律——機(jī)器人必須保護(hù)自身的安全,但不得與第一、第二定律相抵觸。?
這些“定律”構(gòu)成了支配機(jī)器人行為的道德標(biāo)準(zhǔn),機(jī)器人必須按人的指令行事,為人類生產(chǎn)和生活服務(wù)。?
工業(yè)機(jī)器人是機(jī)器人家族中最重要的成員,它廣泛地被應(yīng)用于各種自動化的生產(chǎn)線上。工業(yè)機(jī)器人由操作機(jī)(機(jī)械本體)、控制器、伺服驅(qū)動系統(tǒng)和檢測傳感裝置構(gòu)成。操作機(jī)基本上分為兩大類:一類是操作本體機(jī)構(gòu),它類似人的手臂和手腕,配上各種手爪與末端操作器后可進(jìn)行各種抓取動作和操作作業(yè),工業(yè)機(jī)器人主要采用這種結(jié)構(gòu)。另一類為移動型本體結(jié)構(gòu),主要目的是實現(xiàn)移動功能,主要有輪式、履帶式、足腿式結(jié)構(gòu)以及蛇行、蠕動、變形運(yùn)動等機(jī)構(gòu)。壁面爬行、水下推動等機(jī)構(gòu)也可歸于這一類??刂破魍ǔJ怯蓭准売嬎銠C(jī)系統(tǒng)構(gòu)成,通過對各個傳感器發(fā)回的信息進(jìn)行計算后再發(fā)出相應(yīng)的指令。侍服驅(qū)動系統(tǒng)由驅(qū)動單元和侍服驅(qū)動控制器兩個部分組成,侍服驅(qū)動控制器負(fù)責(zé)控制驅(qū)動單元帶動操作機(jī)朝減少偏差的方向動作。檢測傳感裝置的作用是將各種外界環(huán)境參數(shù)發(fā)回控制器,例如溫度,氣壓,受力等,這使得機(jī)器人能夠與周圍環(huán)境保持密切聯(lián)系,對外界的各種變化做出及時的應(yīng)變。?
二?JAVA3D技術(shù)
在Java語言推出并大獲成功后,Sun公司開始考慮如何建立一個真正完整強(qiáng)大的Java平臺。其中達(dá)成的一個共識就是要強(qiáng)化Java1.0內(nèi)核平臺中功能有限的圖形API。Sun公司在Java1.1將內(nèi)核增強(qiáng)了不少,但始終缺了一點什么。好在Sun公司與其合作伙伴很快開發(fā)出了Java Media和Communication API,彌補(bǔ)了Java在多媒體編程方面的缺憾。其中兩個最大的弱項,2D和3D圖形部分,分別由Java 2D,3D API填補(bǔ)了空白。不過,Java2D API從Java1.2起是作為內(nèi)核平臺的API出現(xiàn)的,而Java3D則是在Java1.2推出后的稍晚些時候作為擴(kuò)展API出現(xiàn)的。
Java3D的推出使Java開發(fā)人員具備了開發(fā)三維視覺的小應(yīng)用程序和應(yīng)用程序,這些程序還具有與客戶交互的能力。這使得Java在視覺上,互動性上產(chǎn)生了一次飛躍。
Java3D的API屬于低階的API,這些低階API為在場景圖結(jié)構(gòu)中建立3D幾何體提供了一種規(guī)范的,獨立于底層硬件的方法,并提供了場景預(yù)編譯等優(yōu)化技術(shù)。這些API按作用可分為幾個大的模塊:基本場景圖和形體,形體的分組和幾何變換,3D圖形文件的導(dǎo)入,光照和材質(zhì)等等。這幾個部分之間的關(guān)系如下圖所示:
由上圖可知,Java3D的場景構(gòu)成可以有豐富的組合,而本文中機(jī)器人的操作機(jī)正是利用這種組合構(gòu)造起來的。
三 利用Java3D實現(xiàn)工業(yè)機(jī)器人計算機(jī)模擬的建模
在建模之前,需要進(jìn)行總體外形的設(shè)計,繪制出草圖,確定各個構(gòu)件的外形尺寸以及各個關(guān)節(jié)轉(zhuǎn)動副之間的距離。這一點非常重要,因為這決定了在虛擬空間中各個構(gòu)件的相對運(yùn)動是否協(xié)調(diào),合理。這一步完成后就可以進(jìn)行部件3D模型的建立。
在Java3D中要構(gòu)造一個復(fù)雜形體(Shape)大體上有兩種辦法。一種是利用Java3D中自有的API產(chǎn)生基本形體,然后再將這些基本形體組合?;蛘哂嬎愠鲞@個復(fù)雜形體的各個頂點,然后利用生成面的API來形成這個形體。這種使用Java3D API來生成形體的方法,優(yōu)點是對形體的操作比較方便,可以使形體在運(yùn)行中產(chǎn)生變化。缺點在于這種建立3D模型的方法不直觀,調(diào)試形狀比較麻煩。另一種方法就是利用Sun公司或其他機(jī)構(gòu)為Java3D開發(fā)的Loader來載入其他格式存儲的3D模型,這些模型可以在諸如Maya,3Dmax,AutoCad等3D生成工具中可視化地生成。這種方法的優(yōu)點顯而易見,那就是建模非常簡便,缺點在于在程序運(yùn)行中這些模型的形狀是不能改變的。因為本文是對工業(yè)機(jī)器人進(jìn)行模擬,所以一些柔性的附件可以省略,余下的均為剛性部件,不會產(chǎn)生形變,所以采用后一種方法是適宜的。
本文中機(jī)器人所有部件的3D模型均由3Dmax建模,輸出為Vrml97格式,然后利用VRML97-Java工作組提供的Vrml97 Loader導(dǎo)入虛擬空間中。 在建立部件模型的過程中需要注意的主要問題是要把形體的坐標(biāo)系原點調(diào)整到這個部件的轉(zhuǎn)動軸心處,這樣在裝配這些部件時就能比較容易地將其轉(zhuǎn)動軸心調(diào)整至關(guān)節(jié)轉(zhuǎn)動副軸線處。導(dǎo)入3D模型需要用到com.sun.j3d.loaders.vrml97.VrmlLoader和com.sun.j3d.loaders.Scene兩個由Sun公司提供的類,其中VrmlLoader提供了用于載入圖形文件的方法,Scene對象則用來容納載入的圖形。當(dāng)Scene的對象中賦以圖形對象后,可使用TransformGroup對象裝載該圖形對象中的3D模型,以便于今后對該3D模型的方位調(diào)整。整個過程如下:
???????? Scene scene=null;
???????? VrmlLoader loader=new VrmlLoader();
???? TransformGroup module=new TransformGroup();
???????? module.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
???????? module.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
???????? try
???????? {
?????????????????????? scene=loader.load(fileName);//fileName為外部圖形文件名,本文中
???????????????????????????????????? //使用的為vrml文件*.wrl。
?????????????????????? module.addChild(scene.getSceneGroup());
???????? }
???????? catch(Exception e)
???????? {
??????????????? System.err.println(e);
??????????????? System.exit(0);
???????? }
當(dāng)機(jī)器人各個部件建模完成并導(dǎo)入場景后,便可以利用Java3D中形體變換類 TransformGroup,Transform3D來組裝這些部件。但是這里存在兩個問題,那就是如何組裝才能使每一個部件自身的運(yùn)動對其他部件的影響如何才能正確體現(xiàn)出來,并且這些部件能夠正確動作?
對于第一個問題,我們先舉人的手臂為例來說明什么是一個部件對另一個部件的正確影響。當(dāng)人的上臂活動時,小臂應(yīng)當(dāng)隨著上臂移動,而小臂活動時,上臂未必動作。而本文模擬的工業(yè)機(jī)器人的運(yùn)動基本與此相似。在Java3D中這個問題可以利用其構(gòu)成場景圖的特點來解決。具體方法是將動作從屬于部件A的部件B的transformGroupB加入到A的transformGroupA中。其關(guān)系類似于圖1-1中所示,transformGroupB及其子節(jié)點都成為transformGroupB的子節(jié)點。這樣,當(dāng)transformGroupA動作時,其所有子節(jié)點將同時動作,這也就實現(xiàn)了我們最初的目的。
而第二個問題中所謂正確的動作是指各個部件能繞正確的軸心轉(zhuǎn)動。本文中虛擬的機(jī)器人沒有平移運(yùn)動,只利用各個關(guān)節(jié)的轉(zhuǎn)動來實現(xiàn)運(yùn)動目的。因此這些部件正確的運(yùn)動,最根本的問題是轉(zhuǎn)動的軸心位置要正確。
在Java3D中,物體的方位設(shè)置通常是通過TransformGroup和Transform3D兩個類實現(xiàn)的。每個TransformGroup對象都有自己的一個坐標(biāo)系,所有作為子節(jié)點加入到這個對象中的形體的位置都以這個坐標(biāo)系為基準(zhǔn),而這個坐標(biāo)系同時也代表了這個TransformGroup對象在父節(jié)點的坐標(biāo)系中的空間位置和方向。這個TransformGroup對象如果要調(diào)整在父節(jié)點中的方位,只需要利用Transform3D對象來調(diào)整該對象的坐標(biāo)系位置即可。調(diào)整坐標(biāo)系位置大體上有兩種途徑,一是直接設(shè)置該調(diào)整的變換矩陣,這種方法的優(yōu)點是步驟簡單快捷,缺點是矩陣的計算比較復(fù)雜,不易把握尺度;二是通過Transform3D類提供的各種方法來達(dá)到目的,這種方法的優(yōu)點是比較直觀,更易于理解,不需要復(fù)雜的計算,而缺點在于為了實現(xiàn)比較復(fù)雜的運(yùn)動需要配合多個子TransformGroup對象。本文中將采取第二種方法,以便讀者能更直觀地理解該機(jī)器人的運(yùn)動實現(xiàn)過程。
在組裝這些部件的3D模型時,每一個形體必須載入到一個transformGroup中,由于這一形體上可能有需要運(yùn)動的子形體,而該子形體運(yùn)動的基準(zhǔn)位置通常是在其父形體上的轉(zhuǎn)軸孔處。因此這里產(chǎn)生了一個問題,一個transformGroup對象中需要有兩個坐標(biāo)系,一個用于該級形體在父形體中的定位,另一個作為子形體運(yùn)動的基準(zhǔn)。為了解決這個問題,可以為每一級形體建立一個container,這個container將容納由外部文件導(dǎo)入的形體,以及坐標(biāo)系調(diào)整到下級形體轉(zhuǎn)軸處的一個Axis對象,這樣將下一級形體的container加入到這個Axis對象中,即可使下一級形體轉(zhuǎn)動的軸心處于正確位置。一級形體與其下級形體之間的關(guān)系如下圖所示:
下圖是已組裝好的機(jī)器人:
四 ?遠(yuǎn)程控制的實現(xiàn)
機(jī)器人的建模部分完成了,接下來的工作是完成機(jī)器人的遠(yuǎn)程控制部分。本文以本地的機(jī)器人對象模擬遠(yuǎn)程控制的監(jiān)視窗口,通過Java Socket將本地的控制信息同步的傳送到Applet遠(yuǎn)程端,那里也實現(xiàn)了一個機(jī)器人對象,用來模擬實際的操作機(jī)。這里為了簡化問題,并沒有設(shè)置遠(yuǎn)程端反饋的回路,而是控制端設(shè)置為服務(wù)器發(fā)送消息,遠(yuǎn)程端設(shè)置為客戶端接收消息。
該控制系統(tǒng)控制端與遠(yuǎn)程端的結(jié)構(gòu)分別如左下圖和右下圖所示:
????其中控制端的鍵盤輸入接口通過繼承Java3D的Behavior類實現(xiàn),這個接口將喚醒條件設(shè)置為按下按鍵,然后通過本地實現(xiàn)的processStimulus方法分析輸入情況,隨后根據(jù)輸入?yún)?shù)調(diào)用相應(yīng)的機(jī)器人控制接口使機(jī)器人做出響應(yīng)。
控制端與遠(yuǎn)程端的機(jī)器人控制接口是基本相同的。由于機(jī)器鉗部分是由兩個部件組成,而這兩個部件的行為總是對稱的,這與其他的部分有顯著不同,因此控制接口使用了方法重載來分別處理這兩種情況:
public void rotArm(float delta);//處理機(jī)械鉗的運(yùn)動
public void rotArm(int code,float delta);//其他部件的運(yùn)動是相似的,故可用一//個方法來實現(xiàn)
在rotArm方法中,部件的運(yùn)動是通過對Container做坐標(biāo)變換實現(xiàn)的:
Transform3D t=new Transform3D();
t.rotY(delta);// 部件沿哪一根軸轉(zhuǎn)動根據(jù)其初始位置來決定
moduleContainer.setTransform(t);
在控制端中,對本地對象變換的同時,rotArm方法調(diào)用了網(wǎng)絡(luò)控制接口。
netIo.send(code,delta);
??
控制端的網(wǎng)絡(luò)接口基于ServerSocket,在接口中設(shè)置有接口狀態(tài)標(biāo)志,初始值為接口不可用,當(dāng)連接建立后,該標(biāo)志被置為接口可用。消息在發(fā)送之前將按照控制協(xié)議格式化,遠(yuǎn)程端在接收到控制消息后,將其解碼,然后調(diào)用機(jī)器人控制接口,實現(xiàn)遠(yuǎn)程機(jī)器人的控制。遠(yuǎn)程端的網(wǎng)絡(luò)接口是基于Socket的,在程序啟動時初始化??刂贫伺c遠(yuǎn)程端的網(wǎng)絡(luò)接口均繼承了Thread多線程類,控制端中子線程用于等待遠(yuǎn)程端連接,而遠(yuǎn)程端中則用于持續(xù)接收控制端消息。
五 參考文獻(xiàn)
1.? Steven Holzner 著,江帆,鄭偉,郭春 等譯,JAVA2技術(shù)內(nèi)幕,中國水利水電出版社。
2.? Bruce Eckel 著,候捷譯,Java編程思想,機(jī)械工業(yè)出版社。?
3.? Cay S.Horstmann,Gary Cornell著,李如豹,剛冬梅 等譯,Java2核心技術(shù) 卷I:原理,機(jī)械工業(yè)出版社。
4.? David R. Nadeau,An Introduction to Programming AR and VR Applications with Java 3D,http://www.sdsc.edu/~nadeau/nadeau_courses.html。
5.? 顧雷,劉鵬,房冰,都志輝 編著,都志輝 主編,劉鵬,陳渝 副主編,Java3D編程實踐,清華大學(xué)出版社。
6.? Harvey M.Deitel,Paul J. Deitel,Sean E.Santry 著,錢方,梅皓,周璐,吳志英 等譯,高級Java2大學(xué)教程,電子工業(yè)出版社。
7.? 賴維德?,工業(yè)機(jī)器人技術(shù),??www.e-works.net.cn/ewkArticles/Category68/Article6938.htm。
8.? 機(jī)器人的誕生,www.cpus.gov.cn/kjsh/jqrsh/jqrdds.htm。
9.? www.siasun.com/jsfw/jsjz.htm。
10. Getting Started with the Java 3D API,java.sun.com/products/java-media/3D/ collateral。