ODE手册(6)关节类型和相关函数(中)
这一部分主要针对不同类型的关节,简单介绍一些相应的函数
6.4 关节参数设定函数
6.4.1 球窝关节(Ball and Socket)
如图 4所示即为球窝关节示意图:
图 4:球窝关节
void dJointSetBallAnchor (dJointID, dReal x, dReal y, dReal z);
设置关节的锚点位置。关节会努力保持每个刚体都连接在这一点上,函数输入的坐标指定为世界坐标。如果没有刚体连接到关节上,这个函数就不会起任何作用。
void dJointGetBallAnchor (dJointID, dVector3 result);
获取关节的锚点位置(世界坐标)。这个函数返回的是锚点在body1上的位置,当然如果关节的约束完美无缺的话,这个函数所返回的值和下面的函数(获取锚点在body2上的位置)返回的值就是一致的。
void dJointGetBallAnchor2 (dJointID, dVector3 reslut);
可以试想一下,球窝关节的作用就是尽力去保证dJointGetBallAnchor()的值和dJointGetBallAchor2()的值相等。如果关节的约束是理想的,这两个函数的返回值在舍入误差的范围之内必然是相等的。当然同时使用这两个函数就可以知道当前状态下关节之间(球和窝之间)分开的距离。
6.4.2 合页关节(Hinge)
如图 5所示即为合页关节示意图:
图 5:合页关节
默认轴心为:Axis 1:x=1, y=0, z=0
void dJointSetHingeAnchor (dJointID, dReal x, dReal y, dReal z);
设置合页的锚点参数。关节会努力保持每个刚体都连接在这一点上,输入坐标值指定为世界坐标。如果没有刚体连接到关节上,则此函数无效。
void dJointSetHingeAxis (dJointID, dReal x, dReal y, dReal z);
设置合页的轴心参数。如果没有刚体连接到关节上,则此函数无效。
void dJointGetHingeAnchor (dJointID, dVector3 result);
获取指定合页关节的锚点在世界坐标系中的位置。返回锚点在body1上的位置,如果关节的约束是理想的,其和锚点在body2上的位置是相同的。
void dJointGetHingeAnchor2 (dJointID, dVector3 result);
获取指定合页关节的锚点在世界坐标系中的位置。返回锚点在body2上的位置,如果关节的约束是理想的,其和dJointGetHingeAnchor函数的返回值是相同的。如果关节约束不理想,这两个值就会由轻微的差别。可以用来判断铰链连接的两个刚体分离的距离。
void dJointGetHingeAxis(dJointID, dVector3 result);
获取合页的轴心参数。
dReal dJointGetHingeAngle (dJointID);dReal dJointGetHingeAngleRate (djointID);
获取合页的角度和它对时间的导数。角度表示的是两个刚体时间的角度或者刚体和静态环境之间的角度,范围为[-pi,pi]。当合页的锚点或者轴心被设置后,就会检查两个刚体当前的连接角度并且这个角度必然是0。
6.4.3 插销关节(Slider)
如图 6所示即为插销关节示意图:
图 6:插销关节
默认轴心为:Axis:x=1, y=0, z=0
void dJointSetSliderAxis (dJointID, dReal x, dReal y, dReal z);
设置插销关节的轴心参数。
void dJointGetSliderAxis (dJointID, dVector3 result);
获取插销关节的轴心参数。
dReal dJointGetSliderPosition (dJointID);
dReal dJointGetSliderPositionRete (dJointID);
获取插销关节的线性位置(也就是滑动关节“伸展”)和其对时间的导数(伸展率)。如果轴心被设置为从body1指向body0,关节的位置和伸展率将会随着两个刚体之间距离的增长而增长。
6.4.4 万向轮关节(Universal)
如图 7 所示即为万向轮关节示意图:
图 7:万向轮关节
万向轮关节就像是一个球窝关节,只是多了一个额外约束自由旋转的角度。在body1上指定axis1,在body2上指定与axis1正交的axis2,万向轮关节会保障它们的正交性。换句话说,两个刚体的旋转方向的正交性和两根轴的的正交性是相同的。
在上图中,两个刚体被一个十字架连接起来。axis 1连接到body1上,axis2连接到body2上十字架保证了两根轴成90度夹角。所以如果你抓住body1并且扭动它,body2也会同时扭动。
当hinge-2关节的两根轴相互垂直是就等价于一个通用关节,并且在悬架处呈现出完美的刚性连接特性。
万向轮关节出现于汽车工业中,汽车的发动机产生一个沿着它自己的轴旋转的轴(驱动轴),在某种情况下你会需要去改变轴的方向。问题就来了,如果只是弯曲驱动轴,弯曲后的驱动轴是不能在绕着它自己的轴旋转的。所以如果把它从弯曲的位置截断,再插入一个万向轮关节就可以将这种约束施加到另一个轴上使得它能够和驱动轴旋转同样的角度。
这种关节的另一种应用就是用来连接一种简单的虚拟生物的肢体和身体。想象一个人伸直它的手臂,同时能够同时上下、前后移动它,但是不能绕着它自己的轴旋转。
默认轴心: Axis 1: x=1, y=0, z=0
Axis 2: x=0, y=1, z=0
需要特别注意的是,两根轴必须是正交的。如果将第一个轴的值设为第二个轴的值(反之亦然)就会导致在运行时出现错误,即使随后立即改变了第二个轴的值。
下面是一些与万向轮关节相关的函数:
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);
设置万向轮关节的锚点和轴心参数。axis1和axis2必须相互垂直。
void dJointGetUniversalAnchor (dJointID, dVector3 result);
获取指定铰链关节的锚点在世界坐标系中的位置,返回其在body1上的位置。如果约束是理想的,返回的值将会和锚点在body2上的位置相同。
void dJointGetUniversalAnchor2 (dJOintID, dVector3 result);
获取指定铰链关节的锚点在世界坐标系中的位置,返回其在body2上的位置。
void dJointGetUniversalAxis1 (dJointID, dVector3 result);
void dJointGetUniversalAxis2 (dJointID, dVector3 reslut);
获取万向轮关节的轴心参数。
dReal dJointGetUniversalAngle1 (dJointID);
dReal dJointGetUniversalAngle2 (dJointID);
dReal dJointGetUniversalAngles (dJointID, dReal *angle1, dReal *angle2);
dReal dJointGetUniversalAngle1Rate (dJointID);
dReal dJointGetUniversalAngle2Rate (dJointID);
获取万向轮关节的旋转角度以及其对时间的导数。角度表示一个刚体和十字架之间的角度,或者十字架和静态环境之间的角度,取值范围为[-pi,pi]。当万向轮关节的锚点或者轴心被设定之后,就会检查两个刚体当前的连接角度并且这个角度必然是0。
6.4.5 铰链-2关节(Hinge-2)
铰链-2关节示意图如图 8所示:
图 8:铰链-2关节
铰链-2关节如同两个合页关节以不用的轴心串联连接在一起。如上图所示的小车的转向轮,一个轴允许轮子进行转向,另一个轴则允许它进行旋转。铰链-2关节包含一个锚点和两根轴,axis1与body1相关(如果body1作为底盘的话,axis1将作为转向轴),axis2跟body2相关联(如果body2作为车轮的话,axis2将作为车轮轴)。
axis1可以被关节约束并且可以有一个发动机,而axis2只能有一个发动机。
axis1可以被定义为一个悬挂轴,也就是说它的约束可以沿着轴向压缩。
铰链-2关节的axis1轴和axis2轴是相互垂直的,就如同给万向轮关节添加了一个悬架。
它的默认轴心为:Axis 1:x=1, y=0, z=0; Axis 2:x=0, y=1, z=0
void dJointSetHinge2Anchor (dJointID, dReal x, dReal y, dReal z);
上面的函数用来设置hinge-d关节的锚点参数。锚点用于保持关节连接的各部分成为一个整体,坐标参数必须是世界坐标。如果没有刚体连接到关节上,使用这个函数就是无效的。
void dJointSetHinge2Axis1 (dJointID, dReal x, dReal y, dReal z);
void dJointSetHinge2Axis2 (dJointID, dReal x, dReal y, dReal z);
设置关节的轴心参数,axis1和axis2不能沿着同一条线。
void dJointGetHinge2Anchor (dJointID, dVector3 result);
void dJointGetHinge2Anchor2 (dJointID, dVector3 result);
上面两个函数分别用来获取锚点在body1和body2上的位置,返回的坐标为世界坐标。
void dJointGetHinge2Axis1 (dJointID, dVector3 result);
void dJointGetHinge2Axis2 (dJointID, dVector3 result);
获取hinge-2关节的轴心参数。
dReal dJointGetHinge2Angle1 (dJointID);
dReal dJointGetHinge2Angle1Rate (dJointID);
dReal dJointGetHinge2Angle2Rate (dJointID);
获取hinge-2关节的角度(绕axis1和axis2)及其对时间的导数。在设置了关节的的锚点或者轴心之后,系统会自行检查关节连接到刚体上的位置,以保证这两个夹角为0。
注意:当前还没有函数用于获取第二个角的值(即车轮绕其轴的转角)。
6.4.6 PR 关节(Prismatic and Rotoide)
PR关节即插销关节和合页关节的结合体,其示意图如下图所示:
图 9:PR关节
PR关节是插销(Slider)关节和合页关节(Hinge)的结合,它用于增加模拟中的刚体数量。通常你是不能将两个ODE关节直接连接在一起的,它们需要有一个刚体做中间媒介。这种类型的关节的一个应用实例就是可以用它创建一个液压活塞。
你可以通过设置这种关节的锚点来设置body2相对于合页关节的位置(就如同合页关节一般)。在这中关节被创建之后,系统会去计算body1和合页关节之间的偏移距离。通过查看关节的位置就会得到刚体的偏移位置。
第一个轴是插销轴,称为axis R,它的参数通过dParamX标志访问。
第二根轴是合页轴,称为axis P,它的参数通过dParamX2表示访问。
系统中默认的PR关节轴心为:Axis R:x=1, y=0, z=0; Axis P: x=0, y=1, z=0
void dJointSetPRAxis1 (dJointID, dReal x, dReal y, dReal z);
void dJointGetPRAxis1 (dJointID, dVector3 result);
设置/获取插销关节的轴心。
void dJointSetPRAxis2 (dJointID, dReal x, dReal y, dReal z);
void dJointGetPRAxis2 (dJointID, dVector3 result);
设置/获取合页关节的轴心。
void dJointSetPRAnchor (dJointID, dReal x, dReal y, dReal z);
void dJointGetPRAnchor (dJointID, dVector3 result);
设置PR关节的锚点,锚点坐标必须为世界坐标。如果没有body2连接到关节上,则使用这个函数时无效的。
dReal dJointGetPRPosition (dJointID);
获取PR关节的线性位置(也就是插销关节的扩展)。在关节的轴心被设置后,系统就会自行检查body1的当前位置和锚点,以保证该位置为0。它表示从body1到合页关节之间的长度:position = (Prismatic axis) dot_product [(body1 + offset) - (body2 + anchor2)]。需要注意的是axis P和axis R并不是平行的,因为这是一个新的关节。
6.4.7 PU关节(Prismatic-Universal)
PU关节示意图如图 10所示:
图 10:PU关节
PU关节是对插销关节和万向轮关节的结合,它提供一个自由度的平移和两个自由度的旋转。1号轴为万向轮的1号轴,可以通过dParamX1或者dParamX(不包括dParamFMax1)标志来访问它的参数。2号轴万向轮的2号轴,可以通过dParamX2(不包括dParamFMax2)标志来访问它的参数。3号轴是插销关节的轴,可以通过dParamX2标志来访问它的参数。
系统提供默认的轴心参数为:Axis 1:x=0, y=1, z=0; Axis 2:x=0, y=0, z=1; Axis 3:x=1, y=0, z=0
dReal dJointGetPUPosition (dJointID);
该函数用于获取PU关节的线性位置(也就是插销关节的伸展长度)。当锚点被设置后,系统会自行检查body1的当前位置和锚点的位置以确定PU关节的线性位置为0(initial_offset)。
position = {(Prismatic axis) dot_product [body1 - anchor]} - initial_offset
dReal dJointGetPUPositionRate (dJointID);
获取PU关节的线性位置对时间的导数。
void dJointSetPUAnchor (dJointID, dReal x, dReal y, dReal z);
void dJointGetPUAnchor (dJointID, dVector3 result);
设置PU关节的锚点参数,关节会保证body2和万向轮关节之间的距离固定不变。如果关节上没有连接body2则这个函数的使用将是无效的。
void dJointSetPUAnchorDelta (dJointID, dReal x, dReal y, dReal x, dReal dx, dReal dy, dReal dz);
设置PU关节的锚点以及每一个刚体之间的相对位置,假设body1在当前位置position + [dx, dy, dz](dz,dy,dz均为世界坐标系坐标)。就好像是在设置插销关节已经伸展或者压缩的长度。在设置锚点之后,如果调用了dJointGetPUPosition函数就会返回这样一个结果:sqrt(dx*dx + dy*dy + dz*dz) * Normalize[axis3 dot_product (dx,dy,dz)]
void dJointSetPUAxis1 (dJointID, dReal x, dReal y, dReal z);
void dJointGetPUAxis1 (dJointID, dVector3 result);
void dJointSetPUAxis2 (djointID, dReal x, dReal y, dReal z);
void dJointGetPUAxis2 (dJointID, dVector3 result);
设置/获取万向轮关节的轴心参数,axis1和axis2必须是相互垂直的。
void dJointSetPUAxis3 (dJointID, dReal x, dReal y, dReal z);
void dJointGetPUAxis3 (dJointID, dVector3 result);
设置/获取插销关节的轴心参数。
void dJointSetPUAxisP (dJointID, dReal x, dReal y, dReal z);
void dJointgetPUAxisP (dJointID, dVector3 result);
上面这组函数的作用和dJOintSetPUAxis3相同。
void dJointGetPUAngles (dJointID, dReal *angle1, dReal *angle2);
dReal dJointGetPUAngle1 (dJointID);
dReal dJointGetPUAngle2 (dJointID);
dReal dJointGetPUAngle1Rate (dJointID);
dReal dJOintGetPUAngle2Rate (dJointID);
获取万向轮关节的角度和其对时间的导数,角度表示刚体和十字架之间的角度,或者静态环境和十字架时间的角度,取值范围为[-pi,pi]。当万向轮的锚点或者轴心被设置之后,系统会自行检查关节所连接刚体的当前位置,以保证万向轮的角度为0。