關日釗,陳新度,吳 磊
廣東工業大學 機電工程學院,廣州 510006
STL文件格式最早是由美國3D System公司推出,是三維實體模型系統的一個接口標準,其接口格式規范,目前已被工業界認為是快速成型領域的標準描述文件格式,廣泛應用于制造業、地理信息系統、醫學影像等領域[1-2]。其采用以點云數據為基礎,組成一系列無序三角面來表達三維實體模型的表面,在快速成型制造系統中已經成為了一種標準的數據輸入,可以通過三維建模軟件或三維掃描儀生成[3]。
目前,STL模型的位姿調整工作主要利用Solid-Works、UG等建模軟件,通過建模時確定模型的建模坐標系和輸出STL模型格式時改變模型的輸出坐標系這兩種方式來完成。由于建模軟件不能直接操作只有點云數據的STL格式文件以及在修改模型建模坐標系上缺乏靈活性,本文開發出一套面向點云模型的交互式位姿調整系統,其直接的操作對象為STL模型文件,與普通的調整方式相比,其在操作上更加方便和靈活。
系統軟件由Qt與OpenGL作為開發平臺,其中Qt是一個跨平臺應用程序和UI開發框架。使用Qt只需一次性開發應用程序,無需重新編寫源代碼,便可跨不同桌面和嵌入式操作系統部署這些應用程序。而OpenGL是專業的圖形程序接口,功能強大的底層圖形庫,因其硬件無關性、建模方便性、出色編程性等優點,在仿真領域有著廣泛應用[4-5]。
在本系統中OpenGL只處理與3D圖形的繪制,基本上不提供創建用戶界面的功能,所以為OpenGL應用程序創建用戶界面必須使用其他的圖形工其包。而Qt的OpenGL模塊很好地解決了這個問題,它提供了一個繼承自QWidget的OpenGL部件類QGLWidget,使得該部件類能夠像Qt其他部件那樣使用,還可以在繪制窗口部件時直接使用OpenGL的API接口。在Qt中為OpenGL提供支持的類主要有以下幾個:
(1)QGLWidget:用來渲染OpenGL場景的Qt部件。
(2)QGLContext:用來封裝用于OpenGL場景渲染的部件。
(3)initializeGL():注冊函數,在此設置GL的渲染繪制屬性、定義顯示列表、載入固定紋理等初始化工作。initializeGL()在調用paintGL()之前只被調用一次,之后不再調用。
(4)paintGL():繪制函數,在此使用OpenGL中的接口進行場景繪制,QGLWidget的paintEvent()將會自動調用paintGL()進行部件的顯示繪制。
系統框架主要分為6個模塊,分別為GL模塊、UI模塊、IO模塊、圖元模塊、變換模塊和約束模塊。如圖1所示。

圖1 系統框架圖
其中GL模塊負責管理OpenGL各種場景和模型渲染等操作;UI模塊主要負責窗口、菜單等UI界面元素的管理以及鼠標工具的管理;IO模塊負責STL模型文件的輸入與輸出管理;圖元模塊主要負責基本圖元的構建和管理;變換模塊負責模型位姿的變換;約束模塊負責檢測模型變換是否引起沖突。
系統基本操作流程如圖2所示。
下面將對關鍵的步驟進行簡單的描述,具體的實現過程和原理將在第3章論述。
(1)“打開STL文件”操作包含模型載入和顯示兩個過程。在模型載入的過程中,由于STL存在較多的冗余點,因此在載入的過程中需要對冗余點進行濾除。在顯示的過程中,主要利用了OpenGL中的顯示列表對模型進行渲染。
(2)“構建圖元”操作是利用鼠標通過選擇點云來構建直線和平面兩種基本圖元。其中包含了圖元拾取和圖元構建這個兩個方面的內容。
(3)“選擇配合方式”操作是利用直線和平面這兩種基本圖元進行軸配合或平面配合。系統提供5種配合關系選擇,分別是軸平行配合、軸重合配合、平面平行配合、平面重合配合和原點配合。
STL文件的最大特點是由一系列以頂點為基礎的三角形面片以無序排列方式組合在一起,每條邊只能被兩個三角面片共用,而且每一個小三角形面片必須與相鄰的三角形面片共用兩個頂點,每個頂點通常被重用6次左右,造成了巨大的數據冗余。一般情況下,冗余頂點數約為面片數的5/6倍[6-7]。
冗余點的濾除主要在載入文件時進行,若省略這個過程,會給后面構建圖元操作帶來不便。目前對于冗余點濾除的方法主要有平衡二叉樹法[8]、三軸分塊排序法[9]、哈希表法[10-11]等。衛煒[12]等人實驗表明,在三角片數量在5萬以上時,哈希表法在上述三種方法中效率最高的,因此本文選擇哈希表法進行冗余點濾除。

圖2 系統操作流程圖
哈希表是將一組關鍵字映射到一個有限的連續的地址集上,并以關鍵字在地址集中的“像”作為記錄在表中的存儲位置的一種表。本算法中使用鏈地址法處理沖突的哈希表[13],如圖3所示,Array是一個鏈表數組,每一個元素代表鏈表的頭指針,其大小是隨STL頂點數變化而變化的。Node是鏈表中的節點存儲結構,如圖4所示,每一個節點包含了一個點的X、Y、Z坐標和一個指向下一個節點的指針。

圖3 哈希表結構圖

圖4 節點結構圖
哈希函數的“好壞”直接影響出現出圖的頻繁程度,也即直接影響哈希表的查詢效率。STL冗余節點濾除的依據是頂點坐標,即哈希表的關鍵字為頂點坐標(X,Y,Z)。本算法根據關鍵字可以計算出哈希表鍵值,取值為:

其中

由上述可知,Q代表記錄在哈希表的位置,通過每一個頂點坐標計算出來的鍵值可以馬上定位到該點所屬的鏈表,然后在所屬鏈表中通過與每個節點數據進行比較去篩選出相同或者相近的點出來,本文是通過篩選相近的點來進一步減少冗余點數量。表1為算法針對4個不同的STL三維模型篩選后的結果。

表1 哈希表冗余點濾除算法結果
圖元拾取過程是利用鼠標拾取OpenGL渲染環境下的各種圖元,是圖元構建和圖元配合兩個步驟的實現基礎。
3.2.1圖元拾取原理
OpenGL為了解決拾取問題,提供了一種基于名字堆棧和命終記錄的選擇機制。在OpenGL中,拾取物體是利用拾取矩陣和投影變換,將拾取的范圍限制在鼠標熱點的有效區中,一旦觸發鼠標事件就進入選擇模式并將有效區初始化,最后利用拾取矩陣拾取有效區內的物體。有效區的定義由glPickMatrix()函數來完成。一旦拾取成功,就以記錄的形式返回與拾取物體相關的信息,并生成一個記錄表示一個物體被命中。
3.2.2 圖元拾取步驟
(1)調用void glSelectBuffer()函數指定用于返回點擊記錄的數組,其中size決定了拾取一次最多可以返回多少個被選取對象。
(2)調用 Glint glRenderMode()函數并傳入 GL_SELECT作為參數進入選擇模式。
(3)使用void glInitNames()和glPushName()對名字棧進行初始化,其中name是一個無符號整型參數,代表了每一個物體的ID,選取操作就是利用這個ID來獲取被選中的物體對象。
(4)定義用于選擇的視景體并且通過gluPickMatrix()函數構造出一個挑選矩陣,并協同投影矩陣,把繪圖限制在視口的一個小區域內,一般是靠近光標的位置。在確立了選擇模式并使用了特殊的挑選矩陣之后,在靠近光標位置處繪制物體就會導致選擇點擊[5]。
(5)交替調用繪制圖元的函數和操縱名字棧的函數,為每一個相關的圖元分配一個適當的名稱。
(6)退出選擇模式,并處理返回的選擇數據。
圖元的構建需要通過STL模型的點云數據進行構建,如圖5所示。圖中淺藍色的點云為工業機器人底座的STL模型數據。本系統提供直線圖元和平面圖元構建功能。

圖5 底座模型點云渲染圖
3.3.1 直線圖元構建
直線圖元的構建需要通過選擇兩個頂點來進行構建,如圖6所示。紅色直線是利用鼠標在點云中選擇兩個點構建出來的。

圖6 直線圖元構建圖
3.3.2 圓形平面圖元構建
圓形平面圖元的構建是根據“三點一面”原理。如圖7所示。圖中紅色平面是利用鼠標在點云中選擇三個點構建出來的。

圖7 平面圖元構建圖
3.3.3 對稱平面圖元構建
對稱面的構建必須構造兩個面,并且兩個面之間的夾角不為0°或180°,如圖8所示。

圖8 對稱面構造示意圖
構建步驟主要為:
(1)將Normal2和Normal1進行叉乘得:

(2)將Normal1和CrossLine1進行叉乘得:

(3)將模型上所有的點同時投影到CrossLine2上,投影過程中通過比較獲得在CrossLine2上投影距離最長的兩個點P1和P2。
(4)過P1點沿Normal1的方向上確定一個點P3,過P1、P2、P3三點作一圓面,該圓面便是模型的對稱面,如圖9所示,紅色平面為對稱面。

圖9 對稱平面圖元構建圖
3.4.1 配合關系
整個配合過程是利用新構建的直線或者平面圖元對已知的坐標系進行軸配合、平面配合或點配合,此坐標系是一個自定義的右手坐標系,可以當作新的建模坐標系,如圖10所示,紅線、綠線和藍線分別代表X軸、Y軸和Z軸。圖中模型為機器人底座的STL模型渲染圖。

圖10 建模坐標系與STL模型圖
軸配合中的“軸”指的此坐標系的X軸、Y軸和Z軸,平面配合中的“平面”指的是此坐標系X-Y平面、Y-Z平面和Z-X平面,點配合中的“點”指的是此坐標系的原點。
(1)當選擇直線圖元進行軸配合的時候,可分為兩種情況,一種是軸平行配合,如圖11所示。另一種是軸重合配合,如圖12所示。圖中黑線為選中的直線圖元,與X軸進行軸配合。

圖11 軸平行配合

圖12 軸重合配合
(2)當選擇平面圖元進行面配合的時候,也可以分為兩種情況,一種是面平行配合,如圖13所示。另外一種是面重合配合,如圖14所示。圖中黑線為選中平面圖元的法線,平面圖元與平面Z-X進行面配合。

圖13 面平行配合

圖14 面重合配合
當選擇原點配合的時候,此時配合的圖元可以是直線圖元的首點或者平面圖元的圓心。圖15為直線原點配合,圖中黑線為所選直線圖元。圖16為面原點配合,圖中黑色透明平面為所選平面圖元。

圖15 直線原點配合

圖16 平面原點配合
3.4.2配合原理
整個配合的結果是通過進行直線或平面配合而得出一個旋轉平移矩陣,然后利用這個矩陣對模型進行相對于新的建模坐標系的一次位姿變換,從而實現了改變模型建模坐標系位姿的效果。
上面提到在配合過程中需要計算一個旋轉平移矩陣。其中旋轉矩陣是一個可以繞任意軸的旋轉矩陣,計算此矩陣需要用到旋轉四元數法。四元數是一種高級的數學工具,被應用于各種工程領域,如導航、機器人和計算機圖形學[14],它是一種高階復數,可以表示為式(5)[15]:

其中,i,j,k滿足式(6)和式(7):

由于i,j,k的性質和笛卡爾坐標系三個軸叉乘的性質很像,所以可以將四元數寫成一個向量和一個實數組合的形式,如式(8)所示:

假設向量V繞任意軸N(nx,ny,nz)旋轉α角度得到向量V1,定義此變換過程的四元數表示為Q(x,y,z),那么 Q(x,y,z)可以表示為式(9)[16]:

在實際OpenGL編程中要實現模型的旋轉操作需要利用到旋轉矩陣去實現,所以就需要把四元數公式轉化成矩陣形式來表示,如式(10)所示:

其中nx,ny,nz為任意旋轉軸,α為旋轉角度。
結合式(9)和式(10)可推導出式(11)為:

把式(11)代進旋轉矩陣可以得出四元數的矩陣表現形式,如式(12)所示:

當對直線進行X軸平行配合時,假設所選擇的直線圖元由a和b兩點組成,可以表示成一個向量Vab,設向量Vx=(1,0,0),則根據式(13)計算出Vab與Vx之間的夾角θ1:

在求出夾角后,對Vab與Vx進行叉乘得到旋轉軸Vr。最后把θ1和Vr代入式(12)便可求出旋轉矩陣。
當對平面進行X-Y面平行配合時,求出所選擇平面的法向量Vn,已知X-Y面的法向量為Vxoy=(0,0,1),利用Vn和Vxoy兩個向量則可以根據上述直線配合中求夾角和旋轉軸的方法算出最后的旋轉矩陣。
非掃描型STL模型指的是利用三維建模軟件建模導出的STL文件。圖17為一個待調姿機器人底座的STL模型。

圖17 待調姿機器人底座模型
通過構建底座平面作為變換對象,再進行“原點配合”變換操作來完成調姿工作。圖18為最終的調整效果。

圖18 調姿后機器人底座模型
掃描型STL模型指的是利用三維掃描儀掃描導出的STL文件,圖19為一個待調姿的馬桶STL模型。

圖19 待調姿馬桶模型
由于馬桶模型不是通過一般的軟件來建模,而是通過三維掃描儀進行三維重建建模的,所以通過簡單的構建平面去進行調整是比較困難的,因此需要通過構建模型的對稱面作為變換對象,當對稱面與Z-X平面重合便達到所需要的效果,如圖20所示。

圖20 調姿后馬桶模型
本文結合Qt+OpenGL平臺開發出一套面向STL點云模型的交互式位姿調整系統可以改變STL模型建模坐標系的位置姿態。通過交互式的手段構建出輔助圖元,利用這些輔助圖元來實現模型建模坐標系的位姿調整。適用于通過建模軟件導出的STL模型和通過三維掃描儀生成的STL模型。此外,在機器人離線編程領域中經常需要用到STL模型建立仿真環境,無可避免需要對導入的STL模型進行位置姿態調整。因此,本系統在離線編程軟件的開發中具有輔助性的作用。