ODE手册(4)World
4.1 常用函数
在ODE中,world对象是一个用来容纳刚体和关节的容器,处于不用world中的对象之间不能进行交互。例如:在两个不同world中的刚体就不可能发生碰撞。在同一个world中的所有对象都处于同一个时间点上,因此使用多个独立world的一个理由就是用来模拟不同等级的系统。但是大多数的应用都只需要一个world。
dWorldID dWorldCreate();
用于创建一个新的、空白的world并且返回它的ID。
dWorldID dWorldDestroy();
销毁一个world和它里面的所有东西,像在world中的所有刚体,不属于任何关节组中的所有关节都会被销毁掉。在关节组中的关节将会被释放,并且能够通过调用相应的函数销毁掉,例如:dJointGroupEmpty。
void dWorldSetGravity (dWorldID, dReal x, dReal y, dReal z);
void dWorldGetGravity (dWorldID, dVector3 gravity);
上面两个函数分别用来设置和获取指定world的重力向量。在SI单元中地球的重力向量为(0,0,-9.81),假设+z是向上的。默认没有重力,如(0,0,0)。
void dWorldSetERP (dWorldID, dReal erp);
dReal dWorldGetERP (dWorldID);
这两个函数分别用来设置和获取全局的ERP(容错系数)值,用来控制在每一个时间步长的执行中有多少误差会被自动纠正。一般取值范围在[0.1,0.8],默认为0.2。
void dWorldSetCFM (dWorldID, dReal cfm);
dReal dWorldGetCFM (dWorldID);
当然,上面的两个函数必然是分别用来设置和获取全局的CFM(混力约束因子)值。一般取值范围在[10-9,1],如果采用的是单精度计算默认为10-5,双精度默认为10-10。
void dWorldSetAutoDisableFlag (dWorldID, int do_auto_disable);
int dWorldGetAutoDisableFlag (dWorldID);
void dWorldSetAutoDisableLinearThreshold (dWorldID, dReal linear_threshold);
dReal dWorldGetAutoDisableLinearThreshold (dWorldID);
void dWorldSetAutoDisableAngularThreshold (dWorldID, dReal angular_threshold);dReal dWorldGetAutoDisableAngularThreshold (dWorldID);
void dWorldSetAutoDisableSteps (dWorldID, int steps);
int dWorldGetAutoDisableSteps (dWorldID);
void dWorldSetAutoDisableTime (dWorldID, dReal time);
dReal dWorldGetAutoDisableTime (dWorldID);
上面列出的函数比较多,我会在后面ODE API整理部分作出更加详细的说明,这里只做简要介绍,望见谅;-)通过函数的命名方式我们可以知道上面的函数是对(新创建的)刚体的auto-disable(后面的翻译部分会做详细介绍,这里暂略)参数进行设置和获取的。另有一些参数的默认值如下:
- AutoDisableFlag = disabled
- AutoDisableLinearThreshold = 0.01
- AutoDisableAngularThreshold = 0.01
- AutoDisableStepd = 10
- AutoDisableTime = 0
void dWorldImpulseToForce (dWorldID, dReal stepsize, dReal ix, dReal iy, dReal iz, dVector3 force);
如果你想给某个刚体施加一个线性冲量或者角冲量以代替某个力或者扭矩,那你可以通过上面的函数将你想要施加的冲量在调用dBodyAdd***(以dBodyAdd开头的一系列函数)函数之前转化为相应的力或者扭矩。其中(ix,iy,iz)即为你所期望的冲量,force即为相应的力向量。当前的算法通过1/stepsize简单地度量冲量,其中stepsize为在下一个仿真步中将被采用的时间步长。另外,之所以给这个函数一个dWorldID参数是因为在将来,力的计算有可能依赖于积分器的参数,而这些参数获取会成为world的属性之一。
4.2 步进函数
void dWorldStep (dWorldID, dReal stepsize);
ODE world中的步进函数,采用“大矩阵”的方法实现。时间复杂度为O(m3),空间复杂度为O(m2),其中m是约束的个数。对于比较大的仿真系统来说,这种方法无疑会耗费比较大的内存空间并且会降低模拟速度,但同时也是目前最精确的方法。
void dWorldQuickStep (dWorldID, dReal stepsize);
ODE world中的另一个步进函数,采用一种迭代的方法。时间复杂度为O(m*N),空间复杂度为O(m),其中m是约束的个数,N是迭代的次数。这种方法对于较大的仿真系统来说,其速度远远快于dWorldStep,但它的精确度却相对较低。QuickStep对堆栈对象很有益,尤其是当auto-disable启用的时候。然而对“近奇异”的系统而言它的精确度有限。在那些存在高摩擦的接触、电机或者特定铰接结构的系统中通常会出现“近奇异”的特性。例如:一个坐在地上的有多条腿的机器人就可能是“近奇异”的。
下面有几种方法可以用来克服QuickStep的不精确性问题:
- 适当地增大CFM
- 降低系统中的接触量(例如:在一个仿真的类人机器人或有足生物的脚上使用最小的接触量)
- 尽量不要在接触中使用过多的摩擦约束
- 在接触中尽可能地使用滑动
- 避免动力学上的循环(然而,对有足仿真对象而言动力学上的循环是不可避免的)
- 不要过多地使用电机牵引
- 尽可能以基于力的电机代替基于速度的电机
void dWorldSetQuickStepNumIterations (dWorldID, int num);
int dWorldGetQuickStepNumIterations (dWorldID)
通过上面的两个函数,我们可以设置或者获取在每一个执行步中QuickStep方法的迭代次数。通常迭代次数越多的话,仿真的精度就越高,但是会耗费较长的时间。ODE中QuickStep的默认迭代值为20。
void dWorldSetQuickStepW (WorldID, dReal over_relaxation);
dReal dWorldGetQuickStepW (dWorldID);
这两个函数分别用来设置和获取QuickStep SOR(Successive Over Relaxation:超松弛迭代法)算法中的over-relaxation参数。
4.2.1 可变步长:(慎用!!!)
在你的仿真系统中步长应该是一个常量,如果你打算或者已经使用可变步长,你就准备好头疼吧!例如,想象一个在地面上静止的物体,实际上它会陷入到地面中一点以保持自身的稳定。当采用可变步长的时候,在每一个仿真步中它的理想的稳定位置将会不断变化,或许还会导致它看起来在不断的抖动(并且有可能获得能量!)。
在ODE中,设计者的初衷是使用固定步长,但也不是说使用可变步长是不可能的,当然也是不简单的(并且编者(非译者)是不会帮助你的)。
4.3 阻尼
dReal dWorldGetLinearDamping (dWorldID);
dReal dWorldGetAngularDamping (dWorldID);
void dWorldSetLinearDamping (dWorldID, dReal scale);
void dWorldSetAngularDamping (dWorldID, dReal scale);
void dWorldSetDamping (dWorldID, dReal linear_scale, dReal angular_scale);
dReal dWorldGetLinearDampingThreshold (dWorldID);
dReal dWorldGetAngularDampingThreshold (dWorldID);
void dWorldSetLinearDampingThreshold (dWorldID, dReal threshold);
void dWorldSetAngularDampingThreshold(dWorldID, dReal threshold);
上面的函数用来设置或者获取world中默认的阻尼参数(刚体将会默认使用world的参数)。默认阈值为0.01,默认阻尼参数为0(即不存在阻尼)。
dReal dWorldGetMaxAngularSpeed (dWorldID);
void dWorldSetMaxAngularSpeed (dWorldID, dReal max_speed);
为新创建的刚体设置角速度,或者获取它们的角速度。
4.4 接触参数
void dWorldSetContactMaxCorrectingVel (dWorldID, dReal vel);
dReal dWorldGetContactMaxCorrectingVel (dWorldID);
设置或者获取在接触面上允许产生的最大校正速度,默认为无限大(即没有任何限制)。降低此值可以防止深度潜入的物体弹出。
void dWorldSetContactSurfaceLayer (dWorldID, dReal depth);
dReal dWorldGetContactSurfaceLayer (dWorldID);
最后这连个函数分别用于设置或者获取几何体周围表层的深度。在ODE中,接触的物体在变为静止之间,允许下陷到表层以下给定的最大深度。系统默认值为0,稍稍地增加此值(如0.001)可以防止由于不断形成和破裂的接触引起的抖动。
扫雷区:(用于对一些非本博文主题内的技术名词和其它关键词进行简要介绍)
奇异 (singular)|近奇异( near-singular):从数学角度来说,所谓奇异性就是指函数的不连续或导数不存在,表现出奇异性的点称为奇异点。在线性代数中有奇异矩阵的概念,判断方法:设A为n阶方阵,若存在另一n阶方阵B,使得AB=BA=I,则称A为非奇异矩阵,若不存在,则为奇异矩阵。在数据处理时,控制变量个数太多而样本量太小(损耗过多自由度,尤其是在时间序列中,若时间窗口较窄),都有可能出现奇异矩阵的问题。要改变的话只有增加样本量或减少控制变量的个数。
注:以上解释是译者对网络上不同解释的综合,并非译者观点(译者很是汗颜,数学功底不够~~)。