基于JAVA3D的工业机器人建模与远程控制
2009-01-05
作者:赵军,李祥
引言
机器人技术是综合了计算机、控制论、机构学、信息和传感技术、人工智能、仿生学等多学科而形成的高新技术,是当代研究十分活跃,应用日益广泛的领域。机器人的应用情况,是一个国家工业自动化水平的重要标志。
Java3D是美国Sun公司为了弥补Java语言在多媒体及图形编程方面的不足而推出的一系列标准扩展API,Java3D的推出使Java开发人员具备了开发三维视觉的小应用程序和应用程序,这些程序还具有与客户交互的能力。这使得Java在视觉上,互动性上产生了一次飞跃。
基于Java3D的这种特性,本文在利用Java3D便利的,面向对象的三维图形程序设计来实现对工业机器人的建模与远程控制。
一 工业机器人技术简介
现代机器人的历史是从1959年美国英格伯格和德沃尔制造出世界上第一台工业机器人开始的。机器人的发展大致经历了三个成长阶段。第一代为简单个体机器人,第二代为群体劳动机器人,第三代为类似人类的智能机器人。
机器人的外形是多种多样的,往往决定于它的功能,工作环境等,但有一个共同点:服从人类指令,代替人力自动工作。当然,由于机器人的智能仍然有限,所以某些特殊的场合仍然需要人类对其进行必要的控制,例如探测机器人。美国著名科普作家艾萨克.阿西莫夫为机器人提出了三条原则,即“机器人三定律”:
第一定律——机器人不得伤害人,或任人受到伤害而无所作为;
第二定律——机器人应服从人的一切命令,但命令与第一定律相抵触时例外;
第三定律——机器人必须保护自身的安全,但不得与第一、第二定律相抵触。
这些“定律”构成了支配机器人行为的道德标准,机器人必须按人的指令行事,为人类生产和生活服务。
工业机器人是机器人家族中最重要的成员,它广泛地被应用于各种自动化的生产线上。工业机器人由操作机(机械本体)、控制器、伺服驱动系统和检测传感装置构成。操作机基本上分为两大类:一类是操作本体机构,它类似人的手臂和手腕,配上各种手爪与末端操作器后可进行各种抓取动作和操作作业,工业机器人主要采用这种结构。另一类为移动型本体结构,主要目的是实现移动功能,主要有轮式、履带式、足腿式结构以及蛇行、蠕动、变形运动等机构。壁面爬行、水下推动等机构也可归于这一类。控制器通常是由几级计算机系统构成,通过对各个传感器发回的信息进行计算后再发出相应的指令。侍服驱动系统由驱动单元和侍服驱动控制器两个部分组成,侍服驱动控制器负责控制驱动单元带动操作机朝减少偏差的方向动作。检测传感装置的作用是将各种外界环境参数发回控制器,例如温度,气压,受力等,这使得机器人能够与周围环境保持密切联系,对外界的各种变化做出及时的应变。
二JAVA3D技术
在Java语言推出并大获成功后,Sun公司开始考虑如何建立一个真正完整强大的Java平台。其中达成的一个共识就是要强化Java1.0内核平台中功能有限的图形API。Sun公司在Java1.1将内核增强了不少,但始终缺了一点什么。好在Sun公司与其合作伙伴很快开发出了Java Media和Communication API,弥补了Java在多媒体编程方面的缺憾。其中两个最大的弱项,2D和3D图形部分,分别由Java 2D,3D API填补了空白。不过,Java2D API从Java1.2起是作为内核平台的API出现的,而Java3D则是在Java1.2推出后的稍晚些时候作为扩展API出现的。
Java3D的推出使Java开发人员具备了开发三维视觉的小应用程序和应用程序,这些程序还具有与客户交互的能力。这使得Java在视觉上,互动性上产生了一次飞跃。
Java3D的API属于低阶的API,这些低阶API为在场景图结构中建立3D几何体提供了一种规范的,独立于底层硬件的方法,并提供了场景预编译等优化技术。这些API按作用可分为几个大的模块:基本场景图和形体,形体的分组和几何变换,3D图形文件的导入,光照和材质等等。这几个部分之间的关系如下图所示:
由上图可知,Java3D的场景构成可以有丰富的组合,而本文中机器人的操作机正是利用这种组合构造起来的。
三 利用Java3D实现工业机器人计算机模拟的建模
在建模之前,需要进行总体外形的设计,绘制出草图,确定各个构件的外形尺寸以及各个关节转动副之间的距离。这一点非常重要,因为这决定了在虚拟空间中各个构件的相对运动是否协调,合理。这一步完成后就可以进行部件3D模型的建立。
在Java3D中要构造一个复杂形体(Shape)大体上有两种办法。一种是利用Java3D中自有的API产生基本形体,然后再将这些基本形体组合。或者计算出这个复杂形体的各个顶点,然后利用生成面的API来形成这个形体。这种使用Java3D API来生成形体的方法,优点是对形体的操作比较方便,可以使形体在运行中产生变化。缺点在于这种建立3D模型的方法不直观,调试形状比较麻烦。另一种方法就是利用Sun公司或其他机构为Java3D开发的Loader来载入其他格式存储的3D模型,这些模型可以在诸如Maya,3Dmax,AutoCad等3D生成工具中可视化地生成。这种方法的优点显而易见,那就是建模非常简便,缺点在于在程序运行中这些模型的形状是不能改变的。因为本文是对工业机器人进行模拟,所以一些柔性的附件可以省略,余下的均为刚性部件,不会产生形变,所以采用后一种方法是适宜的。
本文中机器人所有部件的3D模型均由3Dmax建模,输出为Vrml97格式,然后利用VRML97-Java工作组提供的Vrml97 Loader导入虚拟空间中。 在建立部件模型的过程中需要注意的主要问题是要把形体的坐标系原点调整到这个部件的转动轴心处,这样在装配这些部件时就能比较容易地将其转动轴心调整至关节转动副轴线处。导入3D模型需要用到com.sun.j3d.loaders.vrml97.VrmlLoader和com.sun.j3d.loaders.Scene两个由Sun公司提供的类,其中VrmlLoader提供了用于载入图形文件的方法,Scene对象则用来容纳载入的图形。当Scene的对象中赋以图形对象后,可使用TransformGroup对象装载该图形对象中的3D模型,以便于今后对该3D模型的方位调整。整个过程如下:
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);
}
当机器人各个部件建模完成并导入场景后,便可以利用Java3D中形体变换类 TransformGroup,Transform3D来组装这些部件。但是这里存在两个问题,那就是如何组装才能使每一个部件自身的运动对其他部件的影响如何才能正确体现出来,并且这些部件能够正确动作?
对于第一个问题,我们先举人的手臂为例来说明什么是一个部件对另一个部件的正确影响。当人的上臂活动时,小臂应当随着上臂移动,而小臂活动时,上臂未必动作。而本文模拟的工业机器人的运动基本与此相似。在Java3D中这个问题可以利用其构成场景图的特点来解决。具体方法是将动作从属于部件A的部件B的transformGroupB加入到A的transformGroupA中。其关系类似于图1-1中所示,transformGroupB及其子节点都成为transformGroupB的子节点。这样,当transformGroupA动作时,其所有子节点将同时动作,这也就实现了我们最初的目的。
而第二个问题中所谓正确的动作是指各个部件能绕正确的轴心转动。本文中虚拟的机器人没有平移运动,只利用各个关节的转动来实现运动目的。因此这些部件正确的运动,最根本的问题是转动的轴心位置要正确。
在Java3D中,物体的方位设置通常是通过TransformGroup和Transform3D两个类实现的。每个TransformGroup对象都有自己的一个坐标系,所有作为子节点加入到这个对象中的形体的位置都以这个坐标系为基准,而这个坐标系同时也代表了这个TransformGroup对象在父节点的坐标系中的空间位置和方向。这个TransformGroup对象如果要调整在父节点中的方位,只需要利用Transform3D对象来调整该对象的坐标系位置即可。调整坐标系位置大体上有两种途径,一是直接设置该调整的变换矩阵,这种方法的优点是步骤简单快捷,缺点是矩阵的计算比较复杂,不易把握尺度;二是通过Transform3D类提供的各种方法来达到目的,这种方法的优点是比较直观,更易于理解,不需要复杂的计算,而缺点在于为了实现比较复杂的运动需要配合多个子TransformGroup对象。本文中将采取第二种方法,以便读者能更直观地理解该机器人的运动实现过程。
在组装这些部件的3D模型时,每一个形体必须载入到一个transformGroup中,由于这一形体上可能有需要运动的子形体,而该子形体运动的基准位置通常是在其父形体上的转轴孔处。因此这里产生了一个问题,一个transformGroup对象中需要有两个坐标系,一个用于该级形体在父形体中的定位,另一个作为子形体运动的基准。为了解决这个问题,可以为每一级形体建立一个container,这个container将容纳由外部文件导入的形体,以及坐标系调整到下级形体转轴处的一个Axis对象,这样将下一级形体的container加入到这个Axis对象中,即可使下一级形体转动的轴心处于正确位置。一级形体与其下级形体之间的关系如下图所示:
下图是已组装好的机器人:
四远程控制的实现
机器人的建模部分完成了,接下来的工作是完成机器人的远程控制部分。本文以本地的机器人对象模拟远程控制的监视窗口,通过Java Socket将本地的控制信息同步的传送到Applet远程端,那里也实现了一个机器人对象,用来模拟实际的操作机。这里为了简化问题,并没有设置远程端反馈的回路,而是控制端设置为服务器发送消息,远程端设置为客户端接收消息。
该控制系统控制端与远程端的结构分别如左下图和右下图所示:
其中控制端的键盘输入接口通过继承Java3D的Behavior类实现,这个接口将唤醒条件设置为按下按键,然后通过本地实现的processStimulus方法分析输入情况,随后根据输入参数调用相应的机器人控制接口使机器人做出响应。
控制端与远程端的机器人控制接口是基本相同的。由于机器钳部分是由两个部件组成,而这两个部件的行为总是对称的,这与其他的部分有显著不同,因此控制接口使用了方法重载来分别处理这两种情况:
public void rotArm(float delta);//处理机械钳的运动
public void rotArm(int code,float delta);//其他部件的运动是相似的,故可用一//个方法来实现
在rotArm方法中,部件的运动是通过对Container做坐标变换实现的:
Transform3D t=new Transform3D();
t.rotY(delta);// 部件沿哪一根轴转动根据其初始位置来决定
moduleContainer.setTransform(t);
在控制端中,对本地对象变换的同时,rotArm方法调用了网络控制接口。
netIo.send(code,delta);
控制端的网络接口基于ServerSocket,在接口中设置有接口状态标志,初始值为接口不可用,当连接建立后,该标志被置为接口可用。消息在发送之前将按照控制协议格式化,远程端在接收到控制消息后,将其解码,然后调用机器人控制接口,实现远程机器人的控制。远程端的网络接口是基于Socket的,在程序启动时初始化。控制端与远程端的网络接口均继承了Thread多线程类,控制端中子线程用于等待远程端连接,而远程端中则用于持续接收控制端消息。
五参考文献
1. Steven Holzner 著,江帆,郑伟,郭春 等译,JAVA2技术内幕,中国水利水电出版社。
2. Bruce Eckel 著,候捷译,Java编程思想,机械工业出版社。
3. Cay S.Horstmann,Gary Cornell著,李如豹,刚冬梅 等译,Java2核心技术 卷I:原理,机械工业出版社。
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编程实践,清华大学出版社。
6. Harvey M.Deitel,Paul J. Deitel,Sean E.Santry 著,钱方,梅皓,周璐,吴志英 等译,高级Java2大学教程,电子工业出版社。
7. 赖维德 ,工业机器人技术,www.e-works.net.cn/ewkArticles/Category68/Article6938.htm。
8. 机器人的诞生,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。