陳 偉 王士軍 張臨松 周永鑫
(山東理工大學(xué)機(jī)械工程學(xué)院,山東淄博255000)
SLM是一種金屬粉末在高能束激光的作用下快 速融化并快速冷卻凝固成型的技術(shù)[1],計(jì)算機(jī)控制系統(tǒng)根據(jù)二維切片信息控制激光掃描路徑,通過(guò)層層掃描和層層累積形成三維實(shí)體。與數(shù)控機(jī)床一樣[2],SLM 3D打印機(jī)(增材制造)也是靠編制數(shù)控加工程序來(lái)驅(qū)動(dòng)激光掃描振鏡中的擺動(dòng)伺服電動(dòng)機(jī)進(jìn)行加工的。那么如何正確、高效地對(duì)3D打印切片軟件(CAM軟件)產(chǎn)生的控制代碼進(jìn)行譯碼就成為SLM 3D打印機(jī)控制系統(tǒng)開(kāi)發(fā)過(guò)程中的關(guān)鍵性技術(shù)問(wèn)題。
以往譯碼模塊設(shè)計(jì)方法[3-4],一般使用定義關(guān)鍵字符集的方式進(jìn)行指令的識(shí)別及加工參數(shù)的提取,程序編制過(guò)程繁瑣,容易出錯(cuò)且譯碼效率不高,通用性差。文獻(xiàn)[2]中,將GRETA正則表達(dá)式應(yīng)用于車(chē)銑復(fù)合數(shù)控機(jī)床編譯器的研究。文獻(xiàn)[5]中,將GRETA正則表達(dá)式應(yīng)用于機(jī)器人解釋器的研究。以上均在程序設(shè)計(jì)上不夠完善,程序結(jié)構(gòu)不夠清晰,沒(méi)有充分發(fā)揮GRETA正則表達(dá)式的強(qiáng)大功能,只是簡(jiǎn)單使用了GRETA正則表達(dá)式的rpattern::match函數(shù)。
針對(duì)上述情況,本文以Visual C++6.0作為程序開(kāi)發(fā)平臺(tái),在充分利用了GRETA正則庫(kù)中rpattern類(lèi)的對(duì)象及其成員函數(shù)rpattern::substitute與放置替換結(jié)果的容器subst_results的基礎(chǔ)上,并結(jié)合MFC相關(guān)函數(shù),將GRETA正則表達(dá)式應(yīng)用于SLM 3D打印機(jī)開(kāi)發(fā)了控制系統(tǒng)譯碼模塊,準(zhǔn)確、高效地實(shí)現(xiàn)了對(duì)3D打印切片軟件生成的控制代碼的譯碼工作,為后續(xù)SLM 3D打印機(jī)控制系統(tǒng)的開(kāi)發(fā)打下了堅(jiān)實(shí)的基礎(chǔ)。
正則表達(dá)式是一種用于模式匹配和替換的強(qiáng)有力工具,即通過(guò)使用一系列的特殊字符建立匹配模式,然后將匹配模式與待比較字符串等目標(biāo)對(duì)象進(jìn)行對(duì)比,根據(jù)比較對(duì)象中是否包含匹配模式,再執(zhí)行相應(yīng)的程序[6]。在字符串處理方面,正則表達(dá)式表現(xiàn)出非常強(qiáng)大的功能。GRETA正則庫(kù)是微軟研究院推出的一個(gè)快速、靈活、完全兼容Perl 5正則語(yǔ)法的C++正則表達(dá)式模板類(lèi)庫(kù)。關(guān)于匹配速度,GRETA的開(kāi)發(fā)者Eric Niebler測(cè)試使用正則表達(dá)式“^([0-9]+)(\\-||$)(.?)$”去匹配字符串“100-this is a line of ftp response which contains a message string”,結(jié)果表明GRETA的匹配速度比Boost正則表達(dá)式快大約7倍,比ATL7正則表達(dá)式類(lèi)快大約10倍。匹配速度之快,正好適應(yīng)我們對(duì)高譯碼效率的要求。關(guān)于GRETA正則表達(dá)式的詳細(xì)信息和使用方法[7]本文省略。
GRETA正則庫(kù)是一個(gè)完全開(kāi)源的庫(kù),當(dāng)前最新版本是GRETA-2.6.4,可到微軟官網(wǎng)搜索下載獲取GRETA源文件。在Visual C++6.0程序開(kāi)發(fā)平臺(tái)下,GRETA的使用方法有兩種:一種是直接把GRETA源文件加入工程中,一般不推薦使用此法,原因是源文件的加入會(huì)使工程里有過(guò)多的類(lèi)而使程序顯得不清晰,容易出錯(cuò);另外一種是將GRETA源文件編譯生成geeta.lib靜態(tài)庫(kù),再鏈接到工程當(dāng)中,使用時(shí)只需包含regexpr2.h頭文件即可。
本譯碼模塊采用層次化的編程方法[3],在譯碼過(guò)程的每個(gè)階段只設(shè)置一個(gè)處理函數(shù),各函數(shù)彼此之間相互獨(dú)立,調(diào)用函數(shù)完成相應(yīng)階段的代碼處理工作。通過(guò)層次化的編程方法設(shè)計(jì)的譯碼模塊,易于擴(kuò)展和移植。面對(duì)不同3D打印切片軟件產(chǎn)生的控制代碼時(shí),只需在各階段函數(shù)中對(duì)用于匹配替換的正則表達(dá)式做相應(yīng)更改即可,并且用戶還可以很容易擴(kuò)展一些個(gè)性化功能。
譯碼模塊的譯碼流程如下:
(1)從???.txt文件中讀取一行程序段。
(2)對(duì)讀取的每一行程序段,調(diào)用預(yù)處理函數(shù)BOOL PreProcess(string&strLine)進(jìn)行預(yù)處理,去除非幾何信息和工藝信息(包括空格、注釋等),獲得有效程序段。
(3)對(duì)預(yù)處理無(wú)異常的程序段,調(diào)用詞法檢查函數(shù)BOOL LexCheck(string&strLine)進(jìn)行詞法檢查,主要任務(wù)是識(shí)別出程序段中出現(xiàn)的不合法或者未定義功能的字符。若檢查出錯(cuò)誤,提示錯(cuò)誤的存在并將詳細(xì)錯(cuò)誤信息記錄到錯(cuò)誤報(bào)告中。
(4)對(duì)詞法檢查無(wú)異常的程序段,調(diào)用語(yǔ)法檢查函數(shù)BOOL GramCheck(string&strLine)進(jìn)行語(yǔ)法檢查及加工信息的提取,并將編程值轉(zhuǎn)化為運(yùn)動(dòng)控制器可以識(shí)別的電動(dòng)機(jī)脈沖數(shù)存儲(chǔ)到定制的鏈表中。如果語(yǔ)法檢查出現(xiàn)錯(cuò)誤,提示錯(cuò)誤的存在并將詳細(xì)錯(cuò)誤信息記錄到錯(cuò)誤報(bào)告中。譯碼模塊的總工作流程,如圖1所示。
本文設(shè)計(jì)的譯碼模塊是參考專(zhuān)業(yè)級(jí)切片軟件Simplify 3D后處理生成的控制代碼進(jìn)行譯碼模塊設(shè)計(jì),定義程序段書(shū)寫(xiě)格式為:
[Gnn](0或多個(gè))[X[-]nnn.nnn][Y[-]nnn.nnn][Z[-]nnn.nnn][I[-]nnn.nnn][J[-]nnn.nnn][K[-]nnn.nnn][R[-]nnn.nnn][E[-]nnn.nnn][Fnnn.nnn][Mnn]。其中,中括號(hào)的意思是其中的內(nèi)容可以不出現(xiàn)。本模塊定義的功能字(GXYZIJKREFM),其次序不可以隨便顛倒,否則將提示錯(cuò)誤。3D打印指令代碼遵循NIST RS274NGC標(biāo)準(zhǔn),詳細(xì)的指令含義可參考國(guó)外開(kāi)源網(wǎng)站RepRap.org。
本文設(shè)計(jì)的譯碼模塊,根據(jù)上述定義的程序段書(shū)寫(xiě)格式,在譯碼過(guò)程每個(gè)階段利用GRETA正則表達(dá)式,通過(guò)匹配替換、提取替換結(jié)果的操作方法,自頂向下逐行掃描。首先進(jìn)行預(yù)處理,然后進(jìn)行詞法檢查、語(yǔ)法檢查以及加工信息的提取[8]。
程序開(kāi)始,首先將 NC文件打開(kāi),調(diào)用 MFC中CStdioFile類(lèi)的成員函數(shù)BOOL ReadString(CString&strLine)讀取一行程序段,然后調(diào)用預(yù)處理函數(shù) BOOL PreProcess(string&strLine),去除控制代碼中的非幾何信息和工藝信息(包括空格、注釋等),以獲得有效程序段。
在預(yù)處理函數(shù)中,首先定義兩個(gè)描述匹配空格和注釋的模板字符串(即正則表達(dá)式)CString Space_str(“\\\\s”)和 CString Note_str(“;.?”),模板字符串中“ \\s”、點(diǎn)號(hào)(.)和星號(hào)(?)都是元字符。 “ \\s”的意思是匹配任意的空白符,包括空格、回車(chē)、換行等。點(diǎn)號(hào)(.)的意思是匹配除換行符以外的任意字符。星號(hào)(?)的意思是指定星號(hào)(?)前面的內(nèi)容可以連續(xù)出現(xiàn)N次。
然后用它們來(lái)初始化兩個(gè)rpattern類(lèi)的對(duì)象Space_pat和Note_pat:
static constr pattern Space_pat((LPCTSTR)Space_str,””,NOBACKREFS|GLOBAL);
static const rpattern Note_pat((LPCTSTR)Note_str,””,NOBACKREFS);
其中,參數(shù)””是空字符串,默認(rèn)省略,是執(zhí)行替換操作時(shí)的替換字符串。參數(shù)GLOBAL表示執(zhí)行替換操作時(shí)替換所有與模板字符串相匹配的字段。參數(shù)NOBACKREFS表示不記錄backref,執(zhí)行替換操作時(shí)使用此參數(shù),可大幅提高替換速度。
最后把讀入的一行程序段作為傳遞參數(shù),調(diào)用rpattern類(lèi)的替換函數(shù)Space_pat.substitute(strLine,results)和 Note_pat.substitute(strLine,results)將程序段中所有與模板字符串相匹配的字段替換為空串,已達(dá)到除去空格、注釋的目的,完成預(yù)處理工作。
若程序預(yù)處理完成的程序段為空字符串,則進(jìn)入下一次輪回,讀取下一行程序段。若不為空字符串,調(diào)用詞法檢查函數(shù)BOOL LexCheck(string&strLine)進(jìn)行詞法檢查。詞法檢查主要是找出程序段中出現(xiàn)的不合法或者未定義功能的字符,識(shí)別出控制代碼中的各個(gè)單詞。
根據(jù)本節(jié)開(kāi)頭講到的程序段書(shū)寫(xiě)格式,可定義用于詞法檢查的模板字符串static const CString Lex_str("(G\\d{1,2})?(X-? \\d+( \\.\\d+)?)?(Y-?\\d+( \\.\\d+)?)?(Z-? \\d+( \\. \\d+)?)?...…(E-? \\d+(\\.\\d+)?)?(F \\d{3,})?(M84)?"),該模板字符串中,\\d表示匹配任意一個(gè)阿拉伯?dāng)?shù)字。大括號(hào)表示指定它前面的字符或字符串出現(xiàn)的次數(shù)。?為元字符,表示指定它前面的字符或字符串可以出現(xiàn)0次或1次。+為元字符,表示指定它前面的字符或字符串可以出現(xiàn)一次或更多次。使用該模板字符串,可以檢索控制代碼中出現(xiàn)的指令字是否符合本控制系統(tǒng)的規(guī)定。
在詞法檢查函數(shù)中,使用模板字符串Lex_Reg初始化rapattern類(lèi)對(duì)象Lex_pat:
static const rpattern Lex_pat((LPCTSTR)Lex_str,GLOBAL);
通過(guò)調(diào)用函數(shù)Lex_pat.substitute(strLine,results)完成匹配替換操作,將所有與模板字符串相匹配的字段替換為空串,最后余留的就是不合法字符或者未定義功能的字符。參數(shù)resullts是subst_results類(lèi)的對(duì)象(即放置替換結(jié)果的容器),替換后的所有結(jié)果都放置在這個(gè)容器中,通過(guò)調(diào)用其成員函數(shù)subst_results::backref_str()可提取詞法檢查無(wú)異常的程序段。詞法檢查流程圖,如圖2所示。
在詞法檢查無(wú)異常的情況下,根據(jù)數(shù)控語(yǔ)言的語(yǔ)法規(guī)則,調(diào)用語(yǔ)法檢查函數(shù)BOOL GramCheck(string&strLine)對(duì)控制代碼進(jìn)行語(yǔ)法檢查。語(yǔ)法檢查[9]的主要任務(wù)是檢查每行程序段是否存在同組模態(tài)G代碼錯(cuò)誤、是否缺少相關(guān)指令參數(shù)。
G指令和M指令是一段加工程序中所占比重較大的指令代碼,搭起了整個(gè)加工程序的框架,對(duì)于其中功能相同或相近的指令,它們不能出現(xiàn)在同一程序段中。比如,在每一行程序段中,同組模態(tài)代碼出現(xiàn)的次數(shù)不可多于一次。依據(jù)這一特征把具有同屬性的代碼放在一組中,以指令參數(shù)區(qū)分本組不同代碼,在全局空間進(jìn)行存放。當(dāng)在一行程序段中提取到多個(gè)G指令時(shí),循環(huán)匹配記錄同組模態(tài)代碼出現(xiàn)的次數(shù)。
GRETA正則表達(dá)式在執(zhí)行完匹配替換操作后,與整個(gè)模板字符串相匹配的字段被存儲(chǔ)在backref 0中,與第一個(gè)圓括號(hào)內(nèi)的模板字符串相匹配的字段被存儲(chǔ)在backref 1中,與第二個(gè)圓括號(hào)內(nèi)的模板字符串相匹配的字段被存儲(chǔ)在backref 2中,以此類(lèi)推。基于此特點(diǎn),我們利用圓括號(hào)對(duì)指令字和其后的指令參數(shù)進(jìn)行細(xì)化分割,設(shè)計(jì)模板字符串,完成加工信息的提取工作。例如,匹配G指令的模板字符串為 CString G_str(“(G)(\\d{1,2})”),使用括號(hào)將 G 指令分成兩組,后續(xù)可通過(guò)指定組號(hào),利用替換容器類(lèi)的成員函數(shù)subst_results::backref(size_t cbackref)對(duì)指令參數(shù)進(jìn)行提取。出于提高譯碼效率的目的,在進(jìn)行語(yǔ)法檢查的同時(shí),對(duì)控制代碼加工指令和指令參數(shù)進(jìn)行提取,保存到定制的鏈表中。語(yǔ)法檢查與加工信息提取流程圖,如圖3所示。
本文以Visual C++6.0作為程序開(kāi)發(fā)平臺(tái)進(jìn)行SLM 3D打印機(jī)控制系統(tǒng)譯碼模塊開(kāi)發(fā),其控制系統(tǒng)的用戶界面,如圖4、圖5所示。編寫(xiě)以下具有典型錯(cuò)誤的控制代碼程序進(jìn)行仿真測(cè)試:
測(cè)試后的結(jié)果,如圖4所示。
將以上錯(cuò)誤代碼修正后,重新加載到控制系統(tǒng)中,仿真程序得到了預(yù)期圖形,說(shuō)明本文開(kāi)發(fā)的譯碼模塊得到了正確的結(jié)果。其仿真測(cè)試界面如圖5所示。
本文利用GRETA正則表達(dá)式開(kāi)發(fā)的SLM 3D打印控制系統(tǒng)譯碼模塊,能夠?qū)崿F(xiàn)快速、準(zhǔn)確地提取加工信息。GRETA正則表達(dá)式自由、靈活,易于理解。層次化的編程方法,使開(kāi)發(fā)的譯碼模塊具有良好的可擴(kuò)展性與可移植性,為后期基于運(yùn)動(dòng)控制卡的SLM 3D打印機(jī)控制系統(tǒng)開(kāi)發(fā)奠定了堅(jiān)實(shí)的基礎(chǔ)。