力反馈技术是一种新型的人机交互技术,它允许用户借助力反馈设备触碰、操纵计算机生成的虚拟环境中的物体,并感知物体的运动和相应的力反馈信息,实现人机力觉交互。虽然传统的鼠标、键盘、触摸屏等交互手段可以满足用户与环境中物体交互的需求,但是缺乏力觉交互信息的反馈。力反馈技术结合其他的虚拟现实技术,使用户在交互过程中不仅能够通过视、听觉通道获取信息,还能够通过触觉通道感受模拟现实世界力觉交互的“触感”。因此,力反馈技术的引入,使交互体验更加自然、真实。
力反馈系统的实现过程中涉及到以下关键问题: 力反馈计算模型设计、碰撞检测、视觉与力觉的同步渲染,相应地产生了针对解决上述问题的一系列算法和接口。
1. 设计力反馈计算模型
力反馈计算模型用于计算虚拟环境中物体间交互时产生的力,并由力反馈设备传递给用户。目前,力反馈算法主要采用基于物理建模方法的有限元模型和弹簧—质点模型。其中,有限元模型将连续体离散为多个单元,分别对每个单元进行模拟, 之后连接各单元模拟整个连续体,最后通过解方程组计算质点的受力;弹簧—质点模型首先将物体质量离散到各个质点,并通过弹簧连接柔性物体离散后的质点,依据胡克定律计算质点之间的力,从而模拟整个物体的受力。有限元模型能够较好地满足交互的真实性需求,但是运算量大、求解过程复杂,难以满足交互的实时性需求;而弹簧—质点模型具有建模过程简单、计算量较小、交互实时性较好的特点。
2. 实现碰撞检测
碰撞检测用于实时检测虚拟环境中物体间的碰撞情况,为之后图形信息的绘制及力反馈信息的计算奠定基础。当前的碰撞检测算法主要采用包围盒技术, 首先对物体的包围盒进行相交检测( 模糊碰撞检测), 当包围盒相交时其包围的物体才有可能相交。然后进行物体间的精细碰撞检测,当包围盒不相交时,其包围的物体一定不相交,结束物体间的碰撞检测。
3. 增强力觉真实感
视觉与力觉的同步渲染用于保持较低刷新频率的视觉信息(30fps ~ 60fps) 和较高刷新频率的力觉信息(1000fps) 的一致性。目前,主流的力反馈接口OpenHaptics、CHAI3D等都支持视觉与力觉融合的应用开发。其中,OpenHaptics是SenseAble 公司针对Phantom系列力反馈设备研发的开发工具包,包括QuickHaptics API、Haptic Device API、Haptic Library API 三个不同层次的接口库,能够满足不同用户的设计需求;CHAI3D(Computer Haptics and Active Interface)是由斯坦福大学人工智能实验室研发的支持多种力反馈设备的开源开发工具包,它具有较好的可扩展性,允许用户在已有视觉、力觉渲染算法的基础上根据自己的需要设计新的渲染算法,也可以通过添加驱动的方法支持新的力反馈设备。
VREP中集成了CHAI3D插件,用户可以在Lua脚本中调用其接口编写基于力反馈设备的仿真程序。在VREP的模型浏览器(Model browser/other/Interface to haptic device.ttm)中有一个力反馈设备接口模型,如下图所示:
将其拖入场景中进行仿真,但出现了CHAI3D初始化失败的错误:
解决方法是可以下载一个32位版本的VREP,然后重新编译生成CHAI3D插件的动态链接库。下载CHAI3D 3.2后解压,在modules\V-REP目录下打开相应版本的VS解决方案文件(e.g. CHAI3D-V-REP-VS2013.sln
if using VisualStudio 2013),然后生成Release版本下的32位动态链接库,并将VREP安装目录中的替换掉。
In summary:
- Compile the V-REP module in RELEASE mode in 32-bit configuration.
- Copy the file v_repExtCHAI3D.dll in the base directory of V-REP.
- If you are using the Phantom haptic device, please also copy the file hdPhantom32.dll in the base directory of V-REP. Copy any of the other files if you are using some other devices.
The CHAI3D scene can be controlled from V-REP through a set of LUA functions that allow the user to perform the following tasks:
- connect to haptic devices(Haptic devices can be connected to the CHAI3D scene by calling the simExtCHAI3D_start() LUA function)
- copy V-REP objects to the CHAI3D scene so that they can be "felt" with the haptic device
- keep the position and orientation of the CHAI3D objects in sync with their V-REP counterparts while the simulation is running
- constrain the behavior of the haptic device (e.g. to emulate a 2D force-feedback joystick by constraining the haptic device in a plane)
- change the characteristics of the haptic device constraints to reflect changes in the simulation
为了能让设备输出交互力,在VREP场景中创建好的物体还需要通过simExtCHAI3D_addShape()函数将其添加到CHAI3D的世界中去。添加到CHAI3D场景中后,连接好的力反馈设备就能“感受到”这个物体。如果物体在VREP场景中发生了变化,比如移动或旋转,那么CHAI3D场景中对应的物体也要通过simExtCHAI3D_updateShape()函数进行更新。Any object contained in the V-REP scene can be added to the CHAI3D world by using the simExtCHAI3D_addShape() LUA function. Once an object is added to the CHAI3D scene, it can be "felt" and explored haptically using any haptic device connected to the scene. If the object is moving in the V-REP simulation, it can be kept in sync on the CHAI3D side by using the simExtCHAI3D_updateShape() LUA function.
接下来在VREP中通过CHAI3D插件提供的Lua函数创建一个简单的静态场景。小球代表力反馈设备末端的位置,立方体代表场景中的墙(或需要接触交互的其它物体),当移动末端让小球碰撞到立方体时设备能输出一定的力让用户感受到。如下图所示当小球贴着立方体正面移动时,用户能感受到“墙”的存在,且越靠向墙,受到的反作用越大。当小球移开墙面时,力又变为零。状态栏中输出了小球位置、输出力大小以及操作杆按钮状态(按下按钮变为1):
脚本代码如下:
addCuboid=function(siz,pos,orient) if CHAI3DPluginInitialized then local cuboidHandle=simCreatePureShape(0,4+16,siz,1) simSetObjectParent(cuboidHandle,modelHandle,true) simSetObjectPosition(cuboidHandle,modelHandle,pos) simSetObjectOrientation(cuboidHandle,modelHandle,orient) return addMesh(cuboidHandle,true), cuboidHandle end return -1, -1 end -- copy V-REP objects to the CHAI3D scene so that they can be "felt" with the haptic device addMesh=function(shapeHandle,whenRemovedEraseMesh) if CHAI3DPluginInitialized then if not objCont then objCont={} end objCont[#objCont+1]=shapeHandle local vertices,indices=simGetShapeMesh(shapeHandle) local pos=simGetObjectPosition(shapeHandle,modelHandle) local orient=simGetObjectOrientation(shapeHandle,modelHandle) local hapticObjId=simExtCHAI3D_addShape(vertices,indices,pos,orient,1000) objCont[#objCont+1]=hapticObjId objCont[#objCont+1]=whenRemovedEraseMesh return hapticObjId end return -1 end removeAllObjects=function() if CHAI3DPluginInitialized then if objCont then for i=1,(#objCont)/3,1 do local obj=objCont[3*(i-1)+1] if objCont[3*(i-1)+3] then simRemoveObject(obj) end simExtCHAI3D_removeObject(objCont[3*(i-1)+2]) end end objCont=nil end end if (sim_call_type==sim_childscriptcall_initialization) then modelHandle=simGetObjectAssociatedWithScript(sim_handle_self) -- Check if the plugin is loaded: moduleName=0 moduleVersion=0 index=0 pluginNotFound=true while moduleName do moduleName,moduleVersion=simGetModuleName(index) if (moduleName==‘CHAI3D‘) then pluginNotFound=false end index=index+1 end if (pluginNotFound) then simDisplayDialog(‘Error‘,‘CHAI3D plugin was not found, or was not correctly initialized (v_repExtCHAI3D.dll).‘,sim_dlgstyle_ok,false,nil,{0.8,0,0,0,0,0},{0.5,0,0,1,1,1}) else -- Start the device: local toolRadius=0.005 -- the radius of the tool local workspaceRadius=0.2 -- the workspace radius if simExtCHAI3D_start(0,toolRadius,workspaceRadius)~=1 then simDisplayDialog(‘Error‘,‘Device failed to initialize.‘,sim_dlgstyle_ok,false,nil,{0.8,0,0,0,0,0},{0.5,0,0,1,1,1}) else CHAI3DPluginInitialized=true toolSphereHandle=simCreatePureShape(1,4+16,{toolRadius*2,toolRadius*2,toolRadius*2},1) simSetObjectParent(toolSphereHandle,modelHandle,true) simSetShapeColor(toolSphereHandle,‘‘,0,{1,1,1}) -- Create a haptic cuboid: local cuboidSize={0.1,0.1,0.1} local cuboidPosition={0.01,-0.01,0.05} local cuboidOrientation={0,0,0} cuboidId,cuboidHandle=addCuboid(cuboidSize,cuboidPosition,cuboidOrientation) --[[ -- Create a haptic mesh from an existing V-REP shape: meshHandle=simGetObjectHandle(‘mesh‘) local removeOriginalShapeWhenDone=false meshId=addMesh(meshHandle,removeOriginalShapeWhenDone) --]] end end end if (sim_call_type==sim_childscriptcall_actuation) then end if (sim_call_type==sim_childscriptcall_sensing) then if CHAI3DPluginInitialized then -- Read the position of the cursor: local p=simExtCHAI3D_readPosition(0) -- Reflect the position of the cursor in V-REP: simSetObjectPosition(toolSphereHandle,modelHandle,p) -- Read the the interaction force: local f=simExtCHAI3D_readForce(0) -- Read the buttons of the device: local b = simExtCHAI3D_readButtons(0) local info = string.format("Position:%.2f,%.2f,%.2f Force:%.2f,%.2f,%.2f Button State:%d",p[1],p[2],p[3],f[1],f[2],f[3],b) simAddStatusbarMessage(info) end end if (sim_call_type==sim_childscriptcall_cleanup) then if CHAI3DPluginInitialized then -- Remove all Haptic objects (objects and forces): removeAllObjects() -- Remove all objects in the haptic scene: simExtCHAI3D_reset() end end
可以看出使用CHAI3D就能很方便的让力反馈设备感知场景中的环境,输出力。如果不使用CHAI3D,则需要自行获取VREP中物理引擎计算的接触力信息,然后转换成合适的值发送给设备去渲染接触力。
参考:
CHAI3D plugin for V-REP Documentation
Haptic Data Retrieve—VREP Forum
CHAI3D Current Release (Version 3.2)