ode在大型mmo场景中的应用

http://blog.csdn.net/fuzb/article/details/2306693

 

 

1)ode 概念

刚体Rigid bodies

 

<!--[if !supportLists]-->l       <!--[endif]-->属性properties

一个刚体从模拟的角度说具有各种属性,

有些属性随时间而变化:// 随时间而变化的属性
●物体参照点的坐标顶点(x,y,z),该点必须是此物体的重心。//Position vector (x,y,z)
●参照点的线性速度,一个矢量(vx,vy,vz)  // Linear velocity (vx,vy,vz).
●物体的方向,代表物体的quaternion(qs,qx,qy,qz)或者一个3X3的旋转矩阵  

 // a quaternion (qs,qx,qy,qz) or a 3x3 rotation matrix.
●用来描述随时间变化的方向的变化量的角速度矢量(wx,wy,wz)

// Angular velocity vector (wx,wy,wz)


其他物体属性常常是固定的:// 固定的属性
●物体的质量 // Mass
●参照点物体的质心位置,在现在的方案中质心必须与参照点物体的位置一致,即与物体的position坐标一致. // the center of mass
Inertia matrix描述物体的质量是如何分存于重心的

注意:物体的形状Shape不是动态属性(insofar除外),只有在碰撞检验的时候才关心物体的形状这一细节

 

<!--[if !supportLists]-->l       <!--[endif]-->坐标系统

每个物体都内含一个(x,y,z)坐标系统,物体(Body随它而移动和旋转。

这个坐标系统以物体的重心为原点,在ode中,部分值是相对于物体坐标系统的其它的相对于全局坐标系统。

 

321岛和物体失效

物体(Bodies)”通过“关节(joints)”而联系在一起,一个物体“岛(island)”是一组不能分开的物体-换种说法就是每个物体在模拟时岛内的物体是连接在一起的
    在“世界”的模拟步中每个“岛”是作为独立物体对待的,认识到这点非常重要,如果在模拟时有N个相似的“岛”,那么它的时间复杂度为O(N)。
    每个物体可以被设置为“有效”enabled和“无效”disabled,无效的物体被有效地“关掉”,在每个模拟步中无须更新状态。当发现物体不运动或与模拟无关时,将物体设置为无效是一个非常有效的提高计算速度的方法。
    如果在一个岛内有若干个物体被设为有效时,则岛内所有物体在下一个模拟步中将变为有效。要使一个岛无效必须先让岛内的物体均无效才行。如果一个无效的岛接触到另一个有效的物体,则整个岛将有效,就象一个关节将一个有效物体连接到岛上一样。

 

33综合Integration


按时间模拟刚体系统的过程被称为整合,每个整合步按当前时间和步进时间a given step size进行,从而调节每一个新时间的物体状态。

 

3。4力的聚集 Force accumulators

在每个整合步之间用户可以调用函数来给刚体施加力forces,这些力将合起来成为“力聚集”作用于刚体对象之上。当下一个整合步发生时,所作用与物体上的力合在一起推动物体。每一个整合步后力聚集将变为零。These forces are added to "force accumulators" in the rigid body object.When the next integrator step happens, the sum of all the applied forces will be used to push the body around. The forces accumulators are set to zero after each integrator step.

 

3。5联结和约束Joints and constraints

常见的有ball and socket,hinge,slider约束.

Joints是用来连接body的,constraints用来描述这种关系

Each time the integrator takes a step all the joints are allowed to apply constraint forces to the bodies they affect. These forces are calculated such that the bodies move in such a way to preserve all the joint relationships. 任何时候整合系统将根据力聚集计算所有关节的步进,它同时保持所有的节点关联。///翻译得真烂

3。6联结组Joint groups

3。7联结错误和错误消减参数(ERP)Joint error and the error reduction parameter (ERP)

当一个联结关联两个物体时,物体需要处在合理的位置和方向上。然而有可能物体所处位置是联结不能匹配。这种联结错误在两中情况下发生:
1、如用户给一个物体设置了错误的位置/方向,而另一个物体的不匹配。
2、在模拟是,物体从他们的位置移位了。(见图)
   以下是减小联结错误的机制:在每模拟步中对物体施加特殊的力以使之回到正确的位置。这个力有erro reduction parameter来控制,值在(0-1)间。
    ERP指出在下一个模拟步中联结错误须调整的比例。如果ERP=0则不调整,物体最终将飘离模拟过程。如果ERP=1则模拟将在下一个模拟步中尽力修正所 有的错误。然而将ERP设置为1并不推荐,在很多情况下并不是每个联结错误都需要修正的,建议设置ERP为0.1-0.8,默认为0.2。

 

3.8柔约束和约束力混合(CFM)Soft constraint and constraint force mixing (CFM)

自然的大多数约束事“硬的”,这就意味着这样的约束描述条件将永远不不能违反,举个例子,球必须始终在soket种,hinge的两给部分必须始终对齐的。在实际的约束中可能被无意识的错误的介入到系统中而违反,但是ERP可以更正这些错误。

 

 也有一些约束是软的,比如说the contact constraint that prevents colliding objects from penetrating is hard by default, so it acts as though the colliding surfaces are made of steel. But it can be made into a soft constraint to simulate softer materials, thereby allowing some natural penetration of the two objects when they are forced together.

 

There are two parameters that control the distinction between hard and soft constraints. The first is the error reduction parameter (ERP) that has already been introduced. The second is the constraint force mixing (CFM) value, that is described below.

3.8.1. Constraint Force Mixing (CFM)数学理论现在不管

3.8.2. How To Use ERP and CFM

如果CFM设置成0,约束将很牢固,如果CFM设置成0,约束将很牢固,如果CFM设置为一个正值,可能将违反约束的“推动它pushing on it”(例如:对于对接连接将使两个物体连到一起)。换句话说约束将是柔的,而且软度随CFM变量的增大而更柔。

注意:将cfm设置为负值将带来不好的影响,如不稳定,请不要这样做。

 

通过调整ERP和CFM我们能达到各种效果。如你可以模拟弹簧约束,将两个物体用一个弹簧联系。或者你可以模拟更柔性的约束。无需震动。事实上,erp和 cmf可以用来完成任何想要的弹簧和减震系数的效果。如果你的弹性系数是Kp减震系数是Kd,则相应的ODE系数为ERP=hKp/(hKp+Kd)  cfm=1/(hKp+Kd) 其中h是setpsize。这些值将完成弹簧减震系统模拟的一样的效果


    增大DFM,特别是全局的CFM将减少模拟中的算术错误。如果系统是near-singular的,则能够显著的提高稳定性。事实上如果系统是mis-behaving的,要做的第一件事就是增大全局的CFM。

3.9. Collision handling

bodies之间的碰撞或bodies和静态环境之间的碰撞按以下方法处理:


1、在每个模拟步之前,用户调用碰撞检查(collsion detection)函数去决定事什么碰上什么。这些函数将返回一个contact point的列表(list),每个(接触点)contact point指明一个空间位置,一个曲面法向量(normal vector),和一个有效深度(penetration depth)


2、系统将为每一个接触点创建一个特定的接触联结(contact joint)。一些关于联结的额外信息将给contact jiont,例如当前接触面的摩擦力,以及强弱程度以及其他各种属性


3、contact joints被放入到一个joint“group”,这样以允许非常快速的从系统里添加和移除,模拟速度随着接触数量的上升而下降,所以有不同的策略用来限制接触点的数量


4、一个simulation step 发生


5、将所用的contact joints重系统中移除。


注意内建的碰撞检测函数并不一定要使用,其他的碰撞检测库也能使用,只要它能提供正确的接触点的信息。// 我们实际在网络游戏中用物理系统的话就必须结合具体的场景来搞

 

3.10. Typical simulation code

  1. Create a dynamics world.
  2. Create bodies in the dynamics world.
  3. Set the state (position etc) of all bodies.
  4. Create joints in the dynamics world.
  5. Attach the joints to the bodies.
  6. Set the parameters of all joints.
  7. Create a collision world and collision geometry objects, as necessary.
  8. Create a joint group to hold the contact joints.
  9. Loop:
    1. Apply forces to the bodies as necessary.
    2. Adjust the joint parameters as necessary.
    3. Call collision detection.
    4. Create a contact joint for every collision point, and put it in the contact joint group.
    5. Take a simulation step.
    6. Remove all joints in the contact joint group.
  10. Destroy the dynamics and collision worlds.

 

3.11. Physics model

3.11.1. Friction Approximation

ODE's friction models are approximations to the friction cone, for reasons of efficiency. There are currently two approximations to chose from:

  1. The meaning of mu is changed so that it specifies the maximum friction (tangential) force that can be present at a contact, in either of the tangential friction directions. This is rather non physical because it is independent of the normal force, but it can be useful and it is the computationally cheapest option. Note that in this case mu is a force limit an must be chosen appropriate to the simulation.
  2. The friction cone is approximated by a friction pyramid aligned with the first and second friction directions [I really need a picture here]. A further approximation is made: first ODE computes the normal forces assuming that all the contacts are frictionless. Then it computes the maximum limits fm for the friction (tangential) forces from

 

4. Data Types and Conventions

 

4.1. The basic data types

dReal. dVector3, dVector4, dMatrix3, dMatrix4, dQuaternion.

4.2. Objects and IDs

There are various kinds of object that can be created:

  • dWorld - a dynamics world. 一个仿真世界
  • dSpace - a collision space. 一个碰撞世界
  • dBody - a rigid body. 一个刚体
  • dGeom - geometry (for collision). 几何体(为了碰撞)
  • dJoint - a joint节点
  • dJointGroup - a group of joints. 节点组

Functions that deal with these objects take and return object IDs. The object ID types are dWorldID, dBodyID, etc.

4.3. Argument conventions

4.4. C versus C++

4.5. Debugging

5. World

The world object is a container for rigid bodies and joints. Objects in different worlds can not interact, for example rigid bodies from two different worlds can not collide.

Most applications will only need one world.

dWorldID dWorldCreate();

Create a new, empty world and return its ID number.

 

void dWorldDestroy (dWorldID);

Destroy a world and everything in it. This includes all bodies, and all joints that are not part of a joint group. Joints that are part of a joint group will be deactivated, and can be destroyed by calling, for example, dJointGroupEmpty.

void dWorldSetGravity (dWorldID, dReal x, dReal y, dReal z);

void dWorldGetGravity (dWorldID, dVector3 gravity);

Set and get the world's global gravity vector. The units are m/s/s, so Earth's gravity vector would be (0,0,-9.81), assuming that +z is up. The default is no gravity, i.e. (0,0,0).

void dWorldSetERP (dWorldID, dReal erp);

dReal dWorldGetERP (dWorldID);

Set and get the global ERP value, that controls how much error correction is performed in each time step. Typical values are in the range 0.1--0.8. The default is 0.2.

void dWorldSetCFM (dWorldID, dReal cfm);

dReal dWorldGetCFM (dWorldID);

Set and get the global CFM (constraint force mixing) value. Typical values are in the range 10-9 -- 1. The default is 10-5 if single precision is being used, or 10-10 if double precision is being used.

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);

Set and get the default auto-disable parameters for newly created bodies. See section 6.5 for a description of the auto-disable feature. The default parameters are:

  • AutoDisableFlag = disabled
  • AutoDisableLinearThreshold = 0.01
  • AutoDisableAngularThreshold = 0.01
  • AutoDisableSteps = 10
  • AutoDisableTime = 0

void dWorldImpulseToForce (dWorldID, dReal stepsize,

                          dReal ix, dReal iy, dReal iz, dVector3 force);

If you want to apply a linear or angular impulse to a rigid body, instead of a force or a torque, then you can use this function to convert the desired impulse into a force/torque vector before calling the dBodyAdd... function.

This function is given the desired impulse as (ix,iy,iz) and puts the force vector in force. The current algorithm simply scales the impulse by 1/stepsize, where stepsize is the step size for the next step that will be taken.

This function is given a dWorldID because, in the future, the force computation may depend on integrator parameters that are set as properties of the world.

void dCloseODE();

This deallocates some extra memory used by ODE that can not be deallocated using the normal destroy functions, e.g. dWorldDestroy. You can use this function at the end of your application to prevent memory leak checkers from complaining about ODE.

5.1. Stepping Functions

void dWorldStep (dWorldID, dReal stepsize);
void dWorldQuickStep (dWorldID, dReal stepsize);
 
QuickStep非常适合与对象堆栈特别是当在使用auto-disable属性。无论如何,它对near-singular系统而言具有非常差的精 度。near-singular系统会在使用高摩擦contact,motors,或确定精度near-singular系统是发生。举例:一个多腿的机 器人站在地上是可能就是near-singular。

这里有些方法来克服QuickStep不精确问题:

 增大CFM。

 减小你系统种contacts的数量(如:为机器人或生物使用最小数量的脚)。

 不要过多的为contacts使用摩擦friction。

 适当的使用contact slip。

 避免运动学上的循环(尽管kinematic loops对有腿生物是不可避免的)。

 不要对motor使用过大的力strength。

 用基于力的motor来代替基于速度的motor。Use force-based motors instead of velocity-based motors. 

 增加QuickStep iterations的数量也有一点点帮助,但是但你的系统是一个真正的near singular时没多大帮助。
 

5.2. Contact Parameters

void dWorldSetContactMaxCorrectingVel (dWorldID, dReal vel);
dReal dWorldGetContactMaxCorrectingVel (dWorldID);
设置得到contacts允许产生的最大的正确速度。缺省时无穷大,即没限制。减小这个数值可以帮助防止"popping" of deeply embedded objects。

void dWorldSetContactSurfaceLayer (dWorldID, dReal depth);

dReal dWorldGetContactSurfaceLayer (dWorldID);

设置得到所有几何物体的表面深度。contact按给定的允许沉入物体表面。缺省的值为0,可以增大一点点如0.001来帮助防止物体接触时不停跳动的问题(jittering problems)。
 

6. Rigid Body Functions

6.1. Creating and Destroying Bodies

 

dBodyID dBodyCreate (dWorldID);

Create a body in the given world with default mass parameters at position (0,0,0). Return its ID.

void dBodyDestroy (dBodyID);

Destroy a body. All joints that are attached to this body will be put into limbo (i.e. unattached and not affecting the simulation, but they will NOT be deleted).

6.2. Position and orientation

void dBodySetPosition   (dBodyID, dReal x, dReal y, dReal z);
void dBodySetRotation   (dBodyID, const dMatrix3 R);
void dBodySetQuaternion (dBodyID, const dQuaternion q);
void dBodySetLinearVel  (dBodyID, dReal x, dReal y, dReal z);
void dBodySetAngularVel (dBodyID, dReal x, dReal y, dReal z);
const dReal * dBodyGetPosition   (dBodyID);
const dReal * dBodyGetRotation   (dBodyID);
const dReal * dBodyGetQuaternion (dBodyID);
const dReal * dBodyGetLinearVel  (dBodyID);
const dReal * dBodyGetAngularVel (dBodyID);
 

这些函数设置或返回物体的位置, 旋转, 线速度和角速度。 在设置了一组物体后, 如果在新的设置中与当前的连接/约束不一致的话,摹拟的结果将变的不明确。当返回时,返回的是指向内部数据结构的一个指针,所以当做任何改变时这些改变会影响到物体.
dBodyGetRotation 返回一个4x3 旋转矩阵

 

6.3. Mass and force质量和力

void dBodySetMass (dBodyID, const dMass *mass);
void dBodyGetMass (dBodyID, dMass *mass);

 

void dBodyAddForce            (dBodyID, dReal fx, dReal fy, dReal fz);
void dBodyAddTorque           (dBodyID, dReal fx, dReal fy, dReal fz);
void dBodyAddRelForce         (dBodyID, dReal fx, dReal fy, dReal fz);
void dBodyAddRelTorque        (dBodyID, dReal fx, dReal fy, dReal fz);
void dBodyAddForceAtPos       (dBodyID, dReal fx, dReal fy, dReal fz,
                                        dReal px, dReal py, dReal pz);
void dBodyAddForceAtRelPos    (dBodyID, dReal fx, dReal fy, dReal fz,
                                        dReal px, dReal py, dReal pz);
void dBodyAddRelForceAtPos    (dBodyID, dReal fx, dReal fy, dReal fz,
                                        dReal px, dReal py, dReal pz);
void dBodyAddRelForceAtRelPos (dBodyID, dReal fx, dReal fy, dReal fz,
                                        dReal px, dReal py, dReal pz);
 

Add forces to bodies (absolute or relative coordinates). The forces are accumulated on to each body, and the accumulators are zeroed after each time step.

The ...RelForce and ...RelTorque functions take force vectors that are relative to the body's own frame of reference.

The ...ForceAtPos and ...ForceAtRelPos functions take an extra position vector (in global or body-relative coordinates respectively) that specifies the point at which the force is applied. All other functions apply the force at the center of mass.

给物体加力(绝对/相对坐标) 。 力被聚集到每一个物体上,当经过一个时间步长时力集聚将变为0.
...RelForce and ...RelTorque functions  力向量将相对于物体自已的坐标系统。

 ...ForceAtPos and ...ForceAtRelPos  在一个外部点施加一个力(在全局或物体相对坐标系), 其它函数都是作用于物体的质心的。


const dReal* dBodyGetForce(dBodyID);
const dReal* dBodyGetTorque(dBodyID);

返回力聚集和扭矩向量,返是一个指向3个dReal的数组指针,它是指向内部结构的,所以对它的改变会影响到刚体。

void dBodySetForce;(dBodyID b , dReal x , dReal y,dReal z)
void dBodySetTorque;(dBodyID b , dReal x , dReal y,dReal z)

设置物体的力和扭矩向量,它可以在物体有效前将其力和扭矩向量置为0,
设定本文力和转矩聚积矢量。 在他们被使恢复现役之前 , 这大概是有用为移除的本文对准零位力和转矩,在增加力的功能被拜访他们的外壳中当他们被移除的时候。

 

6.4. Utility

6.5. Automatic Enabling and Disabling

每个body可以被启用和禁用。启用的body参与模拟,而禁用的body被关闭,而且在一个simulation step种不会更新状态。新的body创建时始终时启用状态。一个禁用的body通过joint联结到一个启用物体上后在下一个simulation step时自动被重启用
被禁用body不消耗CPU时间,因此要提高速度就要当物体处于rest时disabled掉。这个事情可以交给auto-disabled特性自动处理。

如果一个body将auto-disable标志打开,当它空闲了一个给定的模拟步时时它将自动的被disabled。
    它也可以通过给定一个模拟时间来时状态处于idle空闲。
    当一个body的线速度和角速度低于一个给定极限值时将被认为时空闲的。因而没个body有5个auto-disabled参数:一个enabled标志,一个空闲步数,一个空闲时间,一个线/角速度的阈值。新创建的body的这些参数从world上得到。
    一下时设置和得到body的enable/disable参数的函数。
    void dBodyEnable (dBodyID);
    void dBodyDisable (dBodyID);
    手动的启用禁用body。注意一个禁用的body通过joint联结到一个启用物体上后在下一个simulation step时自动被重启用。

int dBodyIsEnabled (dBodyID);如果一个body被enabled返回1时否则返回0。
void  dBodySetAutoDisableFlag (dBodyID, int do_auto_disable);
int   dBodyGetAutoDisableFlag (dBodyID);
设置和得到body的auto-disable标志。如果一个auto-disable非零则body将在idle了足够长的时间后自动disabled。
void  dBodySetAutoDisableLinearThreshold (dBodyID, dReal linear_threshold);
dReal dBodyGetAutoDisableLinearThreshold (dBodyID);
linear_threshold
设为无穷大dInfinity时将不考虑线速度因素。

void  dBodySetAutoDisableAngularThreshold (dBodyID, dReal angular_threshold);
dReal dBodyGetAutoDisableAngularThreshold (dBodyID);
angular_threshold
设为无穷大dInfinity时将不考虑角速度因素。

void  dBodySetAutoDisableSteps (dBodyID, int steps);
int   dBodyGetAutoDisableSteps (dBodyID);
设steps为零时不考虑该因素

void  dBodySetAutoDisableTime (dBodyID, dReal time);
dReal dBodyGetAutoDisableTime (dBodyID);
设time为零时不考虑该因素

void  dBodySetAutoDisableDefaults (dBodyID);
从world那里得到缺省的auto-disable参数

6.6. Miscellaneous Body Functions

void  dBodySetData (dBodyID, void *data);
void *dBodyGetData (dBodyID);

设置和得到body的用户数据指针user-data pointer.
 

void dBodySetFiniteRotationMode (dBodyID, int mode);
这个函数时用来控制每step中更新body的orientation的方式。mode可以是:
0:“infinitesimal”无穷小。这是计算速度最快的方式,但是当body高速转动是会偶尔导致不精确,特别是这些bodies joined to 其他bodies。这是body创建时的缺省值。
This function controls the way a body's orientation is updated at each time step. The mode argument can be:
1:“finite”,这是一个比较昂贵的计算方式,但在高速转动时会更加精确。注意高速转动可以导致很多种类型的计算错误,它只是可以解决其中的一个错误。

int dBodyGetFiniteRotationMode (dBodyID);返回当前的mode(0 or 1).

void dBodySetFiniteRotationAxis (dBodyID, dReal x, dReal y, dReal z);
设置body的有限旋转轴,只有当用了finite rotation mode 1 时才有效,如果轴是(0,0,0)full finite rotations are performed on the body。如果这个轴不是零,body

If this axis is nonzero, the body is rotated by performing a partial finite rotation along the axis direction followed by an infinitesimal rotation along an orthogonal direction.
××××××
这能减轻body快速旋转导致的确定 错误源的错误。例如,一个车的轮子转的很快时,你可以调用这个函数,用车轮hinge axis作为参数来提高其性能。This can be useful to alleviate certain sources of error caused by quickly spinning bodies.

void dBodyGetFiniteRotationAxis (dBodyID, dVector3 result);返回这个轴

int dBodyGetNumJoints (dBodyID b);返回与这个bodyjoint的body数

Return the number of joints that are attached to this body.

dJointID dBodyGetJoint (dBodyID, int index);通过索引返回与这个body相关的joints,索引从0 to n-1 ,n是通过dBodyGetNumJoints得到的。

void dBodySetGravityMode (dBodyID b, int mode);
int dBodyGetGravityMode (dBodyID b);

设置和得到body是不是受world的重力加速度的影响。如果mode为非零,受影响,为零不受。新建的body总是受影响的。

 

7. Joint Types and Joint Functions

7.1. Creating and Destroying Joints

7.2. Miscellaneous Joint Functions

7.3. Joint parameter setting functions

7.3.1. Ball and Socket

<!--[if !vml]--><!--[endif]-->

void dJointSetBallAnchor (dJointID, dReal x, dReal y, dReal z);
void dJointGetBallAnchor (dJointID, dVector3 result);
void dJointGetBallAnchor2 (dJointID, dVector3 result);

7.3.2. Hinge

<!--[if !vml]--><!--[endif]-->

void dJointSetHingeAnchor (dJointID, dReal x, dReal y, dReal z);
void dJointSetHingeAxis (dJointID, dReal x, dReal y, dReal z);

……

7.3.3. Slider

<!--[if !vml]--><!--[endif]-->

void dJointSetSliderAxis (dJointID, dReal x, dReal y, dReal z);
void dJointGetSliderAxis (dJointID, dVector3 result);
dReal dJointGetSliderPosition (dJointID);
dReal dJointGetSliderPositionRate (dJointID);

7.3.4. Universal

 

<!--[if !vml]--><!--[endif]-->

void dJointSetUniversalAnchor (dJointID, dReal x, dReal y, dReal z);
void dJointSetUniversalAxis1 (dJointID, dReal x, dReal y, dReal z);
void dJointSetUniversalAxis2 (dJointID, dReal x, dReal y, dReal z);

……

7.3.5. Hinge-2

<!--[if !vml]--><!--[endif]-->

7.3.6. Fixed

void dJointSetFixed (dJointID);

7.3.7. Contact

 <!--[if !vml]--><!--[endif]-->

7.3.8. Angular Motor

 <!--[if !vml]--><!--[endif]-->

7.4. General

7.5. Stop and motor parameters

7.5.1. Parameter Functions

7.6. Setting Joint Torques/Forces Directly

8. StepFast

8.1. When to use StepFast1

8.2. When NOT to use StepFast1

8.3. How it works

8.4. Experimental Utilities included with StepFast1

8.5. API

9. Support Functions

9.1. Rotation functions

9.2. Mass functions

9.3. Math functions

9.4. Error and memory functions

10. Collision Detection

ODE有两个主要的组件:一个动态的仿真引擎和一个碰撞检测引擎。各个body的形状信息shape给到的碰撞引擎。每一个模拟步它将给出那些物体相接触,并将这些 信息用接触点contact point的形式传递给用户。用户就可以按照这些点的信息在body间创建contact joints。使用ODE的碰撞检测是可选项--如果可以通过其他的碰撞检测系统来得到正确的contact信息的话。

10.1. Contact points

 
struct dContactGeom {
  dVector3 pos;       // contact position
  dVector3 normal;    // normal vector
  dReal depth;        // penetration depth
  dGeomID g1,g2;      // the colliding geoms
};
协定是,如果body1是沿着法向量移动一段深度(或者同样的body2沿着法向量的反方向移动一段深度)则contact depth减为零。这就意味着法向量指入body1。

    在现实生活中,两个body间的接触是个复杂的问题。用接触点来表示只是个近似的方法。接触“片”或接触“面”可能更确切些,但是用这样的东西来表现对于快速仿真来说是个挑战。

    每一个接触点模拟中都将降低速度,因此有时因为速度的原因我们被迫的忽略接触点。例如,当两个盒子相碰为了正常表现这种状态有许多接触点需要表示出来,但是我们可能只选择关键的3个。

10.2. Geoms

几何体对象(或geoms)是碰撞系统中的基本对象。

在刚体仿真中使用碰撞引擎,可置位的geoms与刚性body对象联系在一起。这就允许碰撞引擎可以从bodies上得到geoms的位置和方向。注意 geoms和bodies的区别是geoms具有几何属性(尺寸,形状,位置和方向)但是没有动态属性(如速度和质量),一个body和一个geom联系 再一起表示出了仿真对象的全部属性。

10.3. Spaces

A space is a non-placeable geom that can contain other geoms. It is similar to the rigid body concept of the ``world'', except that it applies to collision instead of dynamics.

space对象的存在使得碰撞检测加快,没有spaces,你可能在你的仿真中要通过调用dCollide来从每对geoms中获得接触点来创建contacts。N个geoms的复杂度是o(N^2),这是非常昂贵的计算。

spaces能够容纳其他的spaces。这是对划分一个碰撞环境到几个层次来进一步优化碰撞检测速度是非常有效。下面将有更细节的描述。

10.4. General geom functions

10.5. Collision detection

一个碰撞检测world是被一个创建的space以及向里面添加的geom后创建的。在每个模拟步我们都想产生一个所有的geom相互接触的contacts的列表。有三个函数用来做这件事情:
    a、dCollide让两个geom交叉并产生接触点contact points;
    b、dSpaceCollide决定在一个space中的那些geom对有潜在相交,并为候选的“对”调用回调函数。它步直接产生接触点,因为也许用户想 对一些对进行特殊处理——如忽略他们或不同的接触产生策略。这些决定在回调函数中作出,可以选择是否为这些对调用dCollide。
    c、dSpaceCollide2决定在一个space中的那些geoms与另一个space中的geoms有潜在相交,并为候选的“对”调用回调函数。 它也能对一个单独的不隶属与space的geom进行测试。这个函数对存在一个碰撞层次时时很有用的,即当一个space中包括有另一个space时。
    碰撞系统设计得可以给用户具有最大得灵活性来决定在那些对象间进行检测。这就是为什么有3个碰撞函数得原因,例如,一个函数产生所有接触点。
    space中可以包含space。这些下级space将代表
一个space可以包含其它space,
These sub-spaces will typically represent a collection of geoms (or other spaces) that are located near each other. This is useful for gaining extra collision performance by dividing the collision world into hierarchies. Here is an example of where this is useful:

假如在一些地形上有两辆行驶的汽车,每个汽车都是有很多个几何体组成,如果所有的几何体都被插入到相同的space,则碰撞检测时间将与这引起车的几何体总数成正比,或是这些数目的平方,这依赖于采用哪种space类型。

一 个加速的方法是为每个汽车创建一个space, 将每个汽车的几何体都加入进来,然后将这个space加入到最外层space, 在最外层space每个时间步中调用dSpaceCollide进行车之间的碰撞测试,(实际是在它们的绑定盒上进行的),然后再在汽车的space中调 用dSpaceCollide2进行进行几何体之间的碰撞测试。这有利于加减少浪费的时间。

If space hierarchies are being used then the callback function may be called recursively(递归), e.g. if dSpaceCollide calls the callback which in turn calls dSpaceCollide with the same callback function. In this case the user must make sure that the callback function is properly reentrant(重入).

Here is a sample callback function that traverses through all spaces and sub-spaces, generating all possible contact points for all intersecting geoms:

  void nearCallback (void *data, dGeomID o1, dGeomID o2)
  {
    if (dGeomIsSpace (o1) || dGeomIsSpace (o2)) {
      // colliding a space with something
      dSpaceCollide2 (o1,o2,data,&nearCallback);
      // collide all geoms internal to the space(s)
      if (dGeomIsSpace (o1)) dSpaceCollide (o1,data,&nearCallback);
      if (dGeomIsSpace (o2)) dSpaceCollide (o2,data,&nearCallback);
    }
    else {
      // colliding two non-space geoms, so generate contact
      // points between o1 and o2
      int num_contact = dCollide (o1,o2,max_contacts,contact_array,skip);
      // add these contact points to the simulation
      ...
    }
  }

  ...

  // collide all objects together
  dSpaceCollide (top_level_space,0,&nearCallback);

A space callback function is not allowed to modify a space while that space is being processed with dSpaceCollide or dSpaceCollide2. For example, you can not add or remove geoms from a space, and you can not reposition the geoms within a space. Doing so will trigger a runtime error in the debug build of ODE. 

10.5.1. Category and Collide Bitfields

// test if geom o1 and geom o2 can collide
  cat1 = dGeomGetCategoryBits (o1);
  cat2 = dGeomGetCategoryBits (o2);
  col1 = dGeomGetCollideBits (o1);
  col2 = dGeomGetCollideBits (o2);
  if ((cat1 & col2) || (cat2 & col1)) {
    // call the callback with o1 and o2
  }
  else {
    // do nothing, o1 and o2 do not collide
  }

 

10.5.2. Collision Detection Functions

10.6. Space functions

10.7. Geometry Classes

10.7.1. Sphere Class

10.7.2. Box Class

10.7.3. Plane Class

10.7.4. Capped Cylinder Class

10.7.5. Ray Class

10.7.6. Triangle Mesh Class

10.7.7. Geometry Transform Class

10.8. User defined classes

10.9. Composite objects

10.10. Utility functions

10.11. Implementation notes

10.11.1. Large Environments

Often the collision world will contain many objects that are part of the static environment, that are not associated with rigid bodies. ODE's collision detection is optimized to detect geoms that do not move and to precompute as much information as possible about these objects to save time. For example, bounding boxes and internal collision data structures are precomputed.

10.11.2. Using a Different Collision Library

 

 

 

 

2) mmo应用
由于地形数据庞大,直接拿一般的trimesh来做地形 geom,生成的时候会比较慢,一种更好的办法是自己用
dCreateGeom创建一种新的几何体,作为我们的地形几何体,然后自己实现各种其他集合体跟他的碰撞。

 // register our custom collider class
dGeomClass customColliderClass;
  customColliderClass.bytes:=0; // I don't need any memory
  customColliderClass.collider:=CustomGetColliderFnFn;
  customColliderClass.aabb:=dInfiniteAABB;
  customColliderClass.aabb_test:=nil;
  customColliderClass.dtor:=nil;
  newClassNum:=dCreateGeomClass(customColliderClass);

 

// create a geom of that class and add it to the space 

 newCollider:=dCreateGeom(newClassNum);

dSpaceAdd(space, newCollider);

dColliderFn *CustomGetColliderFnFn(int num)

{

  if (num = dSphereClass )

    Result:= CustomColliderFnSphere

  else if (num = dBoxClass then)

    Result:= CustomColliderFnBox

  else

    Result:= nil;

end;

 

int CustomColliderFnBox(dGeomID o1,dGeomID o2,int flags,dContactGeom * contact,int skip)

{

   // 根据地形高度得出碰撞点就可以了

}

展开阅读全文

大型仓库中无线设备的应用

04-22

大型仓库中无线设备的应用rnrnrn本文出自洲际鼎通科技有限公司 详细信息登陆:www.widock.com.cnrn大型仓库中应用的许多设备,只有串口,要把它们管理起来并实施交换数据有一定的难度。目前,市场上有许多串口服务器,但是其中很多仅仅只能提供串口连接功能,当面临将串口设备连接到有线/无线网络的问题时,这样仅是串口简单的连接就有很多潜在的问题需要考虑。rnrn无线网络安全 rn大多数串口服务器仅支持WEP和WPA-PSK协议,无线串口设备服务器SX-500和SX-550支持WPA2/802.11i,WPA,WEP,802.1X(LEAP,TLS,TTLS,FAST,PEAPrnrn数据的传输问题 rn一般串口服务器速度在230.4Kbps或更少,rnrn无线串口设备服务器SX-500和SX-550支持921.6Kbps用来适应最新的高速串口设备rnrn rnrn控制能力 rn控制设备服务器和被连接设备的命令可以遍及真个网络或是通过串口rnrnAT指挥台(列出在指定的时间和日期在计算机上运行的已计划命令或计划命令和程序) rn标准的AT命令可以允许在开始网络连接到移动电脑时设备连接到Silex设备服务器的串口,断开,控制返回,发射控制台命令或者更多。rnrn控制台命令是十分强大的,因为它允许设备访问Silex设备服务器的全部功能。rnrnRFC2217, rnTelnet rnIP暂停休息, rn在用户指定静止时间内,设备服务器可以编译为自动中断TCP/IP的连接rnrn强大的工具 rn无线串口设备服务器SX-500或SX-550 rnrnExtendView(Windows视窗中,用来配置多个串口设备服务器的工具软件。) rn网页和命令行配置 rn自动分配IP功能。 rn固件更新功能。大部分设备服务器都需要不断的更新固件,通常都是通过TFTP协议完成,这就要求你需要在主机的上配置一个TFTP软件,Silex具有简单的Windows视窗升级工具以便可以在网络中立即下载固件升级 rnFTP,FTP是一种简便的方法测试用来测试设备服务器的容量。设备服务器做为FTP服务器,所以任何PC都可以通过FTP命令发送文件给设备服务器 rn rnrn桥接模式 rnSX-550可以被作为以太网桥,允许以太网设备与无线产品的连接(基于嵌入式的SX-2500CG但是又加强了企业安全性的内容)。rnrn rnrn强大无线漫游功能――无线串口设备服务器SX-500和SX-550应用在世界上很多超大型仓库中。 rn出售铲车为仓库/船运应用。 rnSX-500用来连接称与 rn铲车起重机,升降机,包装和规模自动重包装 rnSX-500无线地将重量信息传输给控制电脑。 rn无线企业安全(802.1X)是尤为重要。 rn漫游功能很强大。 rnrn 论坛

没有更多推荐了,返回首页