王福印,吕常魁
(南京航空航天大学 机电学院,江苏 南京 210016)
工业机器人解释器是机器人软件系统的关键组成部分。作为机器人控制系统与机器人语言的接口,解释器负责读取机器人源程序,并生成运动控制模块所识别的目标数据。解释器的效率与质量是影响机器人运行精度、实时性与稳定性的控制性因素[1]。
解释器一般包括词法分析、语法分析、语义分析3个基本逻辑环节。传统词法分析与语法分析一般是依次读入单字符,将字符分成运算符、终结符和非终结符等,再按照一定的文法规则进行归约,构造语法树并识别语法错误;语义分析阶段则通过遍历语法树来实现语法制导的翻译过程[2],最终生成目标代码。然而单字符读取与语法树遍历的解释模式往往导致解释过程算法复杂,效率低下。
正则表达式采用直接匹配的解释模式,具有开放性、高效性等特点,在机器人解释器设计中被广泛采用。如文献[2]应用Linux系统自带的regcomp()和regexec()正则表达式处理库函数,完成机器人语言解释器的语法分析;文献[3]基于QT设计了机器人语言系统,采用QRegExp正则表达式规范机器人语言编辑格式,简化了词法分析、语法分析过程;文献[4]在VC开发环境下,通过调用GREAT正则表达式模板类库,对指令代码进行语法分析。
本文基于PCRE正则表达式,提出两遍扫描的解释模式:在第一遍扫描中应用PCRE正则表达式完成程序指令的词法、语法分析;第二遍扫描中采用双向链表结构形式,管理程序中的每条指令,通过查关键字表跳转到相应的处理函数,完成语义分析、信息提取及目标代码的生成。实验结果表明,解释算法稳定可靠,具有较高的执行效率。
动作级机器人语言以控制指令和尺寸信息为主,每一行程序即为一条指令,形式简单,格式固定。这一特征可以直接通过匹配完成语法分析,通过查询关键字表,直接转入行指令对应的处理模块,实现快速语义分析。鉴于此,在解释器的实现过程中,综合考虑程序结构、执行效率和内存消耗等因素,采用两遍扫描的方式[2,5-6]。其流程如图1所示。
第一遍扫描只进行词法和语法分析即错误检测,不进行有关数据的处理。解释器逐行读取源程序,与初始化后的正则表达式进行整行匹配,若匹配有误,说明程序指令存在语法错误,则对该指令进行词法匹配,输出错误信息。若指令没有错误则进行第二遍扫描,完成语义分析、信息提取和目标代码生成。两遍扫描相互独立,可单独调用。
图1 解释器整体流程图
正则表达式是由一系列普通字符和元字符组成的,能明确描述文本字符串的文字匹配模式[7]。PCRE是一个用C语言编写的正则表达式函数库,比Boost之类的正则表达式库小得多,简单易用,性能超过了POSIX正则表达式库和一些经典的正则表达式库。
PCRE在VS2010编译环境下的配置过程十分方便,步骤如下:1) 新建筛选器,命名为pcre;2) 将PCRE软件包头文件及可执行文件添加至pcre文件夹;3) 将pcre中可执行文件属性改为不使用预编译头;4) 修改工程属性,添加宏“_DEBUG”和“HAVE_CONFIG_H”。
Pcre正则表达式提供了19个接口函数。本文采用PCRE进行语法、词法分析时只需调用现有的IsMathch(const char *szPattern,const char *szSrc)函数,参数szPattern为宏定义的指令代码字符串,参数szSrc为要匹配的指令代码。若匹配成功,函数返回值>0,反之<0。该函数中已封装了PCRE正则表达式的pcre_compile()和pcre_exec()接口函数,与传统调用正则表达式的过程相比,实现方式简单、编程难度明显减小。
研究的语言属于动作级机器人语言,结构清晰固定,如运动指令MOVJ P* ,V20 ,Z0 ;流程控制指令JUMP LAB0。此外,在工业机器人实际编程中通常以“选择题式”输入的方式编程,每一行的程序格式由指令编辑器软件严格设定,这种形式有效避免了非字符及非法语法的产生。本文设计的指令窗口,如图2所示。指令代码由树形控件管理,当双击选中的指令,指令将显示在程序编辑窗口中。为检查在参数修改过程中,人为因素带来的词法语法错误,本文提出利用PCRE正则表达式进行先语法后词法的的快速检查方法,其流程图如图3所示。
首先,解释器根据PCRE正则表达式规则建立指令代码的语法和词法匹配表达式,并定义成宏的形式,再将语法匹配表达式装载到数组中以备循环匹配。以运动指令MOVJ为例,定义其语法匹配的正则表达式如下:
#define PCRE_MOVJ “MOVJ (\s+)P\d{1,3}(\s*),(\s*)V(\d{1,2}|100)(\s+),\s*Z[0-4](\s+)”;对应的词法匹配正则表达式为:#define PCRE_P “P\d{1,3}(\s+)”、#define PCRE_V “V(\d{1,2}|100)(\s+)”、#define PCRE_Z “Z[0-4](\s+);”。
图2 指令窗口
图3 第一遍扫描流程图
初始化后,程序读取一行代码进行整体匹配。若匹配正确,则说明此行代码语法正确,程序跳出循环进行下一行代码匹配;若整体匹配有误,则程序跳转到该指令对应的处理函数完成词法分析,并在输出窗口输出发生错误的行号和类型。然后读取下一行代码继续匹配,直至代码行为空,完成对全部指令程序的错误检查。
第一遍扫描如果没有错误则进行第二遍扫描完成语义分析、信息提取和目标代码的生成。在此采用一个双向链表结构管理源程序段,即链表中每一节点对应一行指令;链表结构如下:
Struct SProc_Codelist
{
int rowNum;
char comName[100];//指令代码
int nType;// 指令关键字的宏定义
struct SProc_Codelist *front;
struct SProc_Codelist *next;
};
双链表结构的特点是从双链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后驱结点,使得上下级存在制约关系的指令代码的分析变得简单方便。语义检查、信息提取和目标代码的生成均通过读取链表实现,分析流程图如图4所示。
图4 第二遍扫描流程图
nType用于存储宏形式定义的指令关键字,如运动指令MOVJ的宏定义为:#define MOVJ 1。nType的值通过查找关键字数组表获得。若读取指令不为空,根据关键字调用相应的语义分析函数,若语义分析正确,则进行该指令代码的信息提取并生成目标代码;若语义分析有误,则输出错误信息,程序停止运行。本文对于每一种指令类型,都设计了对应的分析处理函数接口。结构形式如下:
switch(Codelist_p->nType)
{
case MOVJ:deal_Motion_MOVJ();break;
case MOVL:deal_Motion_MOVL();break;
case MOVC:deal_Motion_MOVC();break;
…
default:break;
}
图5以VS2010作为开发工具实现的离线编程系统主界面,含三维视图显示窗口、指令选择窗口、程序编辑窗口、运动控制窗口和信息输出窗口。可以通过离线编程或导入源程序文件实现运动模拟。
为验证该解释器的有效性,应用上述系统对机器人指令进行了大量解释试验。结果显示该解释器能够正确解释机器人指令,当代码出错时,能够正确输出错误信息。在指令信息提取的正确性方面,以图5所示的编辑代码为例,结果显示,机器人能够正确按照指令实现运动模拟。在DOS环境下输出解释器提取的示教点信息和生成的目标代码(图6),与实际数据吻合。
图5 离线仿真系统
图6 指令代码信息提取结果
针对工业机器人语言形式简单、格式固定等特点,提出了两遍扫描的解释模式。基于PCRE正则表达式,采用先整体后局部的匹配方法完成首次扫描,实现了语法、词法的快速检测;为每一指令建立了相应处理函数,并生成了关键字表以便于函数查询。二次扫描过程中,采用双向链表结构形式进行指令管理,通过关键字表查询快速跳转至相应处理函数,完成语义分析、信息提取及目标代码的生成。程序结构清晰,解释算法简单且各模块相互独立,易于维护。实验结果表明,该解释器能够快速完成错误检测,并可靠提取指令相关信息。
[1] 周泽湘, 丁跃浇,张敏. 工业机器人解释器的研究与设计[J]. 机械设计与制造, 2012(12): 154-156.
[2] 郭显金. 工业机器人编程语言的设计与实现[D]. 武汉:华中科技大学,2013.
[3] 杨杏,陈富林,周霏. 基于Qt的工业机器人语言系统的设计[J]. 组合机床与自动化加工技术,2015(3):71-74.
[4] 何嘉健,李伟光. 基于GRETA正则表达式的机器人解释器的研究[J]. 组合机床与自动化加工技术,2012(1):17-19,24.
[5] 王浩,谢存禧. 开放式机器人解释器的研究[J]. 机械设计与制造,2010(8) :167-168.
[6] 王浩. 基于XML的开放式工业机器人解释器的研究[D]. 广州:华南理工大学,2010.
[7] Jeffrey E.F.Friedl. 精通正则表达式[M]. 北京:电子工业出版社,2007.