PhysX3 User Guide 03 Joint

 1 Joint Creation  
Joint提供了一种联系俩Actor的途径。典型的例子如门上的合页,人物的肩膀。.

创建Joint的方法:
PxRevoluteJointCreate(PxPhysics& physics,
                      PxRigidActor
* actor0, const PxTransform& localFrame0,
                      PxRigidActor
* actor1, const PxTransform& localFrame1);

必须有一个Actor可以动,是PxRigidDynamic,要不就是PxArticulationLink. 另一个Actor无所谓。

localFrame参数表示Actor的相对PxTransform,包括位置和姿态,position and orientation. 上面的例子是一个revolute joint,localFrame须指定原点和旋转轴。

PhysX提供了6中Joint:
    1. 固定。不能相对运动。a fixed joint locks the orientations and origins rigidly together 
    2. 距离。Actor之间像栓了绳子。a distance joint keeps the origins within a certain distance range 
    3. 球体。原点重合,姿态自由。a spherical joint (sometimes known as as a ball-and-socket) keeps the origins together, but allows the orientations to vary freely. 
    4. 开阖。门的合页那样的。a revolute joint (often referred to as a hinge) keeps the origins and x-axes of the frames together, and allows free rotation around this common axis. 
    5. 截面。移门那样的。a prismatic joint keeps the orientations identical, but allows the origin of one actor to slide freely along the line defined by the origin and x-axis of the other. This kind of joint models a sliding door. 
    6. D6。高度自定义的一类,可以高度自由也可以高度固定。a D6 joint is a highly configurable joint that allows specification of individual degrees of freedom either to move freely or be locked together. It can be used to implement a wide variety of mechanical and anatomical joints, but is somewhat less intuitive to configure than the other joint types. 
应用程序可以添加向框架添加新的Joint扩展现有类型。

Note: PhysX中的角度是以弧度为单位。

 2 Beyond the Basics  
  Visualization  
所有PhysX的标准joints都支持debug visualization.因此..

但 joint本身是不可见的. 为使其可见, 要将设置其constraint flag为visualization,并改变场景的visualization parameters:
scene->setVisualizationParameter(PxVisualizationParameter::eJOINT_FRAMES, 1.0f);
scene
->setVisualizationParameter(PxVisualizationParameter::eJOINT_LIMITS, 1.0f);

...

joint
->setConstraintFlag(PxConstraintFlag::eVISUALIZATION)

  Force Reporting  
Jonit连接的Actor每帧都要保存连接它俩的force的信息。通过设置reporting constraint flag启用该功能,然后就可以用Joint对象的getForce方法获得force信息。
joint->setConstraintFlag(PxConstraintFlag::eREPORTING)
...

scene
->fetchResults(...)
joint
->getForce(force, torque);

The force is resolved at the origin of actor1’s joint frame.

  Breakage  
PhysX的标准joint都是可以被掰开的breakable. 可以定义这个临界force和torgue。 joint被掰开会引发一个simulate event(参看PxSimulationEventCallback::onJointBreak), 这个joint尽管可能仍然存在与场景中,但也不再参与运算。

但joint默认是不可掰开的。开启该属性,方法如下,首先设置一个临界force和torgue,然后设置breakable constraint flag为true。
joint->setBreakForce(100.0f100.0f);
joint
->setConstraintFlag(PxConstraintFlag::eBREAKABLE, true);

  Projection  
Under stressful conditions, PhysX’ dynamics solver may not be able to accurately enforce the constraints specified by the joint. For joints where this is problematic you can enable kinematic projection, which tries to bring violated constraints back into alignment. Projection is not a physical process and doesn’t preserve momentum or respect collision geometry. It should be avoided where practical, but it can be useful in improving simulation quality where joint separation results in unacceptable artifacts.(这段很迷糊)

在突发情况(有外力情况?)下,PhysX 的dynamics slover(dynamic物体的计算器?)可能会没办法正确操作joint定义的Actor之间约束关系。这显然不太妙。你可以启用kinematic projection(运动投影?),它会尝试纠正。但Projection并非物理过程,它不会遵守动量守恒也不会管图形是否碰撞。实际应用中应该避免使用projection,但它在改善什么什么效果时很有用。-_-b

 

projection也是默认不可用的。启用方法如下,首先设置会引起joint被project的临界linear tolerance和angular tolerance,然后开启那啥constraint flag.

joint->setProjectionLinearTolerance(0.1f);
joint
->setConstraintFlag(PxConstraintFlag::ePROJECTION, true);

Very small tolerance values for projection may result in jittering around the joint.

  Limits  
joint限制相关的Actor如何旋转或只能沿某方向平移,同时可进一步设置这种可旋转和可移动的范围。例如revolute joint,合页关节,默认是绕轴的任意角度的旋转,如果需要,你可以开启limit,然后定义个旋转的最大角度和最小角度。

Limits可以看做collision碰撞的一种。stable limit需要定义最大最小距离,和一个tolerance。blabla..要说的是limit的模拟开销是很昂贵的。

设置limit要配置limit的geometry,然后设置joint的limit flag为true。
revolute->setLimit(PxJointLimitPair(-PxPi/4, PxPi/40.1f)); // upper, lower, tolerance
revolute->setRevoluteJointFlag(PxRevoluteJointFlag::eLIMIT_ENABLED, true);

Limit可硬可软。硬就是让joint的运动立刻停下来,如果这是limit被设置为non-zero restitution,会被弹回。软的就是有阻尼效果。默认的limit是不会回弹的hard。

Note: Limits are not projected.

  Actuation  
有些joint是被spring和motor驱动的。这种模拟的开销比简单用force驱动的要大,它要求有更多的 stable control ,更多细节参看D6和revolute joint的文档。

Note: The force generated by actuation is not included in the force reported by the solver, nor does it contribute towards exceeding the joint’s breakage force threshold.

  3 Fixed Joint  
image:: ../images/fixedJoint.png

The fixed joint has no additional characteristics.

  4 Spherical Joint  
image:: ../images/sphericalJoint.png

A spherical joint constrains a point on each actor to be coincident.

The spherical joint supports a cone limit, which constrains the direction of the x-axis of actor1’s constraint frame. The axis of the limit cone is the x-axis of actor0’s constraint frame, and the allowed limit values are the maximum rotation around the the y- and z- axes of that frame. Different values for the y- and z- axes may be specified, in which case the limit takes the form of an elliptical angular cone:
joint->setLimitCone(PxJointLimitCone(PxPi/2, PxPi/60.01f);
joint
->setSphericalJointFlag(PxSphericalJointFlag::eLIMIT_ENABLED, true);

Note that very small or highly elliptical limit cones may result in solver jitter.

Note Visualization of the limit surface can help considerably in understanding its shape.

  5 Revolute Joint  
image:: ../images/revoluteJoint.png

A revolute joint removes all but a single rotational degree of freedom from two objects. The axis along which the two bodies may rotate is specified by the common origin of the joint frames and their common x-axis. In theory, all origin points along the axis of rotation are equivalent, but simulation stability is best in practice when the point is near where the bodies are closest.

The joint supports a rotational limit with upper and lower extents. The angle is zero where the y- and z- axes of the joint frames are coincident, and increases moving from the y-axis towards the z-axis:
joint->setLimit(PxJointLimitPair(-PxPi/4, PxPi/40.01f);
joint
->setRevoluteJointFlag(PxRevoluteJointFlag::eLIMIT_ENABLED, true);

The joint also supports a motor which drives the relative angular velocity of the two actors towards a user-specified target velocity. The magnitude of the force applied by the motor may be limited to a specified maximum:
joint->setDriveVelocity(10.0f);
joint
->setRevoluteJointFlag(PxRevoluteJointFlag::eDRIVE_ENABLED, true);

By default, when the angular velocity at the joint exceeds the target velocity the motor acts as a brake; a freespin flag disables this braking behavior

  6 Prismatic Joint  
image:: ../images/prismaticJoint.png

A prismatic joint prevents all rotational motion, but allows the origin of actor1’s constraint frame to move freely along the x-axis of actor0’s constraint frame. The primatic joint supports a single limit with upper and lower bounds on the distance between the two constraint frames’ origin points:
joint->setLimit(PxJointLimitPair(-10.0f20.0f0.01f);
joint
->setPrismaticJointFlag(PxPrismaticJointFlag::eLIMIT_ENABLED, true);

  7 Distance Joint  
image:: ../images/distanceJoint.png

The distance joint keeps the origins of the constraint frames within a certain range of distance. The range may have both upper and lower bounds, which are enabled separately by flags:
joint->setMaxDistance(10.0f);
joint
->setDistanceJointFlag(eMAX_DISTANCE_ENABLED, true);

In addition, when the joint reaches the limits of its range motion beyond this distance may either be entirely prevented by the solver, or pushed back towards its range with an implicit spring, for which spring and damping paramters may be specified.

  8 D6 Joint  
  Locking and Unlocking Axes  
D6是最复杂的标准Joint. 它默认表现的像fixed Joint,两个物体像黏在一起一样运动。但使用Joint的setMotion方法,你可以设置允许旋转和平移。
d6joint->setMotion(PxD6Axis::eX, PxD6Motion::eFREE);

如果设置了平移自由translational degrees of freedom,即允许actor1的原点沿着actor0的constraint frame定义的轴移动。

旋转自由Rotational degrees of freedom分为两种:扭twist (around the x-axis of actor0’s constraint frame);和摆 swing (around the y- and z- axes.) 通过控制twist和swing参数的开关,可以得到很多效果:
  1. if just a single degree of angular freedom is unlocked, the result is always equivalent to a revolute joint. It is recommended that if just one angular freedom is unlocked, it should be the twist degree, because the joint has various configuration options and optimizations that are designed for this case. 
  2. if both swing degrees of freedom are unlocked but the twist degree remains locked, the result is a zero-twist joint. The x-axis of actor1 swings freely away from the x-axis of actor0 but twists to minimize the rotation required to align the two frames. This creates a kind of isotropic universal joint which avoids the problems of the usual ‘engineering style’ universal joint (see below) that is sometimes used as a kind of twist constraint. There is a nasty singularity at π radians (180 degrees) swing, so a swing limit should be used to avoid the singularity. 
  3. if one swing and one twist degree of freedom are unlocked but the remaining swing is kept locked, a zero-swing joint results (often also called a universal joint.) If for example the SWING1 (y-axis rotation) is unlocked, the x-axis of actor1 is constrained to remain orthogonal to the z-axis of actor0. In character applications, this joint can be used to model an elbow swing joint incorporating the twist freedom of the lower arm or a knee swing joint incorporating the twist freedom of the lower leg. In vehicle applications, these joints can be used as ‘steered wheel’ joints in which the child actor is the wheel, free to rotate about its twist axis, while the free swing axis in the parent acts as the steering axis. Care must be taken with this combination because of anisotropic behavior and singularities (beware the dreaded gimbal lock) at angles of π/2 radians (90 degrees), making the zero-twist joint a better behaved alternative for most use cases. 
  4. if all three angular degrees are unlocked, the result is equivalent to a spherical joint. 
有三种PhysX2的joint在physX3已经木有了,但你可以酱来实现他们。

  • The cylindrical joint (with axis along the common x-axis of the two constraint frames) is given by the combination:
d6joint->setMotion(PxD6Axis::eX,     PxD6Motion::eFREE);
d6joint
->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
  • the point-on-plane joint (with plane axis along the x-axis of actor0’s constraint frame) is given by the combination:
d6joint->setMotion(PxD6Axis::eY,      PxD6Motion::eFREE);
d6joint
->setMotion(PxD6Axis::eZ,      PxD6Motion::eFREE);
d6joint
->setMotion(PxD6Axis::eTWIST,  PxD6Motion::eFREE);
d6joint
->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
d6joint
->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
  • the point-on-line joint (with axis along the x-axis of actor0’s constraint frame) is given by the combination:
d6joint->setMotion(PxD6Axis::eX,      PxD6Motion::eFREE);
d6joint
->setMotion(PxD6Axis::eTWIST,  PxD6Motion::eFREE);
d6joint
->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
d6joint
->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);

  Limits  
除了可以定义轴是自由还是锁定( axis is free or locked), 还可以定义其受限范围limit. D6有三种limit,并且可以组合使用。

A single linear limit with only an upper bound is used to constrain any of the translational degrees of freedom. The limit constrains the distance between the origins of the constraint frames when projected onto these axes. For example, the combination:
d6joint->setMotion(PxD6Axis::eX, PxD6Motion::eFREE);
d6joint
->setMotion(PxD6Axis::eY, PxD6Motion::eLIMITED);
d6joint
->setMotion(PxD6Axis::eZ, PxD6Motion::eLIMITED);
d6joint
->setLinearLimit(PxJointLimit(1.0f0.1f));

constrains the y- and z- coordinates of actor1’s constraint frame to lie within the unit disc. Since the x-axis is unconstrained, the effect is to constrain the origin of actor1’s constraint frame to lie within a cylinder of radius 1 extending along the x-axis of actor0’s constraint frame.

The twist degree of freedom is limited by a pair limit with upper and lower bounds, identical to the limit of the revolute joint.

If both swing degrees of freedom are limited, a limit cone is generated, identical to the limit of the spherical joint. As with the spherical joint, very small or highly elliptical limit cones may result in solver jitter.

If only one swing degree of freedom is limited, the corresponding angle from the cone limit is used to limit rotation. If the other swing degree is locked, the maximum value of the limit is π radians (180 degrees). If the other swing degree is free, the maximum value of the limit is π/2 radians (90 degrees.)

  Drives  
D6有1个linear drive model, 和2个angular drive models. The drive is a proportional derivative drive, which applies a force as follows:

force = spring * (targetPosition - position) + damping * (targetVelocity - velocity)

The drive model 也可以代替force用来引起加速。Acceleration drive 调整比force drive要容易些。

linear drive model 有如下参数: 
  • 目标位置,在actor0的constraint frame中定义。target position, specified in actor0’s constraint frame 
  • 目标速度,也定义在actor0的constraint frame中。target velocity, specified in actor0’s constraint frame 
  • 弹性?spring 
  • 阻尼。damping 
  • 能提供的最大力。forceLimit - the maximum force the drive can apply 
  • 加速标志。acceleration drive flag 
它会以设置的阻尼和倔强系数stiffness?往目标位置运动。A physical lag due to the inertia of the driven body acting through the drive spring will occur; therefore, sudden step changes will result over a number of time steps. Physical lag can be reduced by stiffening the spring or supplying a velocity target.

如果位置固定目标速度为0, a position drive will spring about that drive position with the specified springing/damping characteristics:
// set all translational degrees free

d6joint
->setMotion(PxD6Axis::eX, PxD6Motion::eFREE);
d6joint
->setMotion(PxD6Axis::eY, PxD6Motion::eFREE);
d6joint
->setMotion(PxD6Axis::eZ, PxD6Motion::eFREE);

// set all translation degrees driven:

PxD6Drive drive(
10.0f-20.0f, PX_MAX_F32, true);
d6joint
->setDrive(PxD6JointDrive::eX, drive);
d6joint
->setDrive(PxD6JointDrive::eY, drive);
d6joint
->setDrive(PxD6JointDrive::eZ, drive);

//Drive the joint to the local(actor[0]) origin - since no angular dofs are free, the angular part of the transform is ignored

d6joint
->setDrivePosition(PxTransform::createIdentity());
d6joint
->setDriveVelocity(PxVec3::createZero());

Angular drive和linear drive完全不同,angular drive木有一种简单直接的方式用以描述它相对于奇点(singularities)是怎么自由运动的, 因此D6 joint提供了两种angular drive models——扭摆 和 球面插值SLERP (Spherical Linear Interpolation).

这俩angular drive model最大的区别在于他们使用四元数的方式。SLERP中直接使用四元数,扭摆模型里面会吧四元数分解成blabla. 扭摆模型多数情况下的行为都是比较一致的,但要注意180度的摆动,这时候actor并不会沿着两个角度之间的最短弧线运动(球体表面的最短路径). SLERP模型总是会让actor沿着最短对角弧运动。

只有有任何一个方向的角度不能改变, SLERP drive 参数就会被忽略。当所有方向上都是角度自由,and parameters are set for multiple angular drives, the SLERP parameters will be used.

The angular drive model has the following parameters:
  • 角速度,定义在actor0的constraint frame。An angular velocity target specified relative to actor0’s constraint frame 
  • 目标姿态。定义在同上。An orientation target specified relative to actor0’s constraint frame 
  • SLERP或扭摆drive的配置。drive specifications for SLERP (slerpDrive), swing (swingDrive) and twist (twistDrive): 
    • 弹性。spring - amount of torque needed to move the joint to its target orientation proportional to the angle from the target (not used for a velocity drive). 
    • 阻尼。damping - applied to the drive spring (used to smooth out oscillations about the drive target). 
    • 那啥。forceLimit - maximum torque applied when driving towards a velocity target (not used for an orientation drive) 
    • 那啥。acceleration drive flag 
Best results will be achieved when the drive target inputs are consistent with the joint freedom and limit constraints.
原文地址:https://www.cnblogs.com/mumuliang/p/2068652.html