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