Changed: Header inclusion order corrected
[ode.git] / ode / src / joints / pu.cpp
blob31353abbf6f3d313d39d6ad4b55f6749d5b580b4
1 /*************************************************************************
2 * *
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
12 * file LICENSE.TXT. *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
15 * *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
20 * *
21 *************************************************************************/
24 #include "config.h"
25 #include "pu.h"
26 #include "joint_internal.h"
29 //****************************************************************************
30 // Prismatic and Universal
32 dxJointPU::dxJointPU( dxWorld *w ) :
33 dxJointUniversal( w )
35 // Default Position
36 // Y ^ Axis2
37 // ^ |
38 // / | ^ Axis1
39 // Z^ / | /
40 // | / Body 2 | / Body 1
41 // | / +---------+ | / +-----------+
42 // | / / /| | / / /|
43 // | / / / + _/ - / / +
44 // | / / /-/--------(_)----|--- /-----------/-------> AxisP
45 // | / +---------+ / - +-----------+ /
46 // | / | |/ | |/
47 // | / +---------+ +-----------+
48 // |/
49 // .-----------------------------------------> X
50 // |----------------->
51 // Anchor2 <--------------|
52 // Anchor1
55 // Setting member variables which are w.r.t body2
56 dSetZero( axis1, 4 );
57 axis1[1] = 1;
59 // Setting member variables which are w.r.t body2
60 dSetZero( anchor2, 4 );
61 dSetZero( axis2, 4 );
62 axis2[2] = 1;
64 dSetZero( axisP1, 4 );
65 axisP1[0] = 1;
67 dSetZero( qrel1, 4 );
68 dSetZero( qrel2, 4 );
71 limotP.init( world );
72 limot1.init( world );
73 limot2.init( world );
77 dReal dJointGetPUPosition( dJointID j )
79 dxJointPU* joint = ( dxJointPU* ) j;
80 dUASSERT( joint, "bad joint argument" );
81 checktype( joint, PU );
83 dVector3 q;
84 // get the offset in global coordinates
85 dMultiply0_331( q, joint->node[0].body->posr.R, joint->anchor1 );
87 if ( joint->node[1].body )
89 dVector3 anchor2;
91 // get the anchor2 in global coordinates
92 dMultiply0_331( anchor2, joint->node[1].body->posr.R, joint->anchor2 );
94 q[0] = (( joint->node[0].body->posr.pos[0] + q[0] ) -
95 ( joint->node[1].body->posr.pos[0] + anchor2[0] ) );
96 q[1] = (( joint->node[0].body->posr.pos[1] + q[1] ) -
97 ( joint->node[1].body->posr.pos[1] + anchor2[1] ) );
98 q[2] = (( joint->node[0].body->posr.pos[2] + q[2] ) -
99 ( joint->node[1].body->posr.pos[2] + anchor2[2] ) );
101 else
103 //N.B. When there is no body 2 the joint->anchor2 is already in
104 // global coordinates
106 q[0] = (( joint->node[0].body->posr.pos[0] + q[0] ) -
107 ( joint->anchor2[0] ) );
108 q[1] = (( joint->node[0].body->posr.pos[1] + q[1] ) -
109 ( joint->anchor2[1] ) );
110 q[2] = (( joint->node[0].body->posr.pos[2] + q[2] ) -
111 ( joint->anchor2[2] ) );
113 if ( joint->flags & dJOINT_REVERSE )
115 q[0] = -q[0];
116 q[1] = -q[1];
117 q[2] = -q[2];
121 dVector3 axP;
122 // get prismatic axis in global coordinates
123 dMultiply0_331( axP, joint->node[0].body->posr.R, joint->axisP1 );
125 return dCalcVectorDot3( axP, q );
129 dReal dJointGetPUPositionRate( dJointID j )
131 dxJointPU* joint = ( dxJointPU* ) j;
132 dUASSERT( joint, "bad joint argument" );
133 checktype( joint, PU );
135 if ( joint->node[0].body )
137 // We want to find the rate of change of the prismatic part of the joint
138 // We can find it by looking at the speed difference between body1 and the
139 // anchor point.
141 // r will be used to find the distance between body1 and the anchor point
142 dVector3 r;
143 dVector3 anchor2 = {0,0,0};
144 if ( joint->node[1].body )
146 // Find joint->anchor2 in global coordinates
147 dMultiply0_331( anchor2, joint->node[1].body->posr.R, joint->anchor2 );
149 r[0] = ( joint->node[0].body->posr.pos[0] -
150 ( anchor2[0] + joint->node[1].body->posr.pos[0] ) );
151 r[1] = ( joint->node[0].body->posr.pos[1] -
152 ( anchor2[1] + joint->node[1].body->posr.pos[1] ) );
153 r[2] = ( joint->node[0].body->posr.pos[2] -
154 ( anchor2[2] + joint->node[1].body->posr.pos[2] ) );
156 else
158 //N.B. When there is no body 2 the joint->anchor2 is already in
159 // global coordinates
160 // r = joint->node[0].body->posr.pos - joint->anchor2;
161 dSubtractVectors3( r, joint->node[0].body->posr.pos, joint->anchor2 );
164 // The body1 can have velocity coming from the rotation of
165 // the rotoide axis. We need to remove this.
167 // N.B. We do vel = r X w instead of vel = w x r to have vel negative
168 // since we want to remove it from the linear velocity of the body
169 dVector3 lvel1;
170 dCalcVectorCross3( lvel1, r, joint->node[0].body->avel );
172 // lvel1 += joint->node[0].body->lvel;
173 dAddVectors3( lvel1, lvel1, joint->node[0].body->lvel );
175 // Since we want rate of change along the prismatic axis
176 // get axisP1 in global coordinates and get the component
177 // along this axis only
178 dVector3 axP1;
179 dMultiply0_331( axP1, joint->node[0].body->posr.R, joint->axisP1 );
181 if ( joint->node[1].body )
183 // Find the contribution of the angular rotation to the linear speed
184 // N.B. We do vel = r X w instead of vel = w x r to have vel negative
185 // since we want to remove it from the linear velocity of the body
186 dVector3 lvel2;
187 dCalcVectorCross3( lvel2, anchor2, joint->node[1].body->avel );
189 // lvel1 -= lvel2 + joint->node[1].body->lvel;
190 dVector3 tmp;
191 dAddVectors3( tmp, lvel2, joint->node[1].body->lvel );
192 dSubtractVectors3( lvel1, lvel1, tmp );
194 return dCalcVectorDot3( axP1, lvel1 );
196 else
198 dReal rate = dCalcVectorDot3( axP1, lvel1 );
199 return ( (joint->flags & dJOINT_REVERSE) ? -rate : rate);
203 return 0.0;
208 void
209 dxJointPU::getSureMaxInfo( SureMaxInfo* info )
211 info->max_m = 6;
216 void
217 dxJointPU::getInfo1( dxJoint::Info1 *info )
219 info->m = 3;
220 info->nub = 3;
222 // powered needs an extra constraint row
224 // see if we're at a joint limit.
225 limotP.limit = 0;
226 if (( limotP.lostop > -dInfinity || limotP.histop < dInfinity ) &&
227 limotP.lostop <= limotP.histop )
229 // measure joint position
230 dReal pos = dJointGetPUPosition( this );
231 limotP.testRotationalLimit( pos ); // N.B. The function is ill named
234 if ( limotP.limit || limotP.fmax > 0 ) info->m++;
237 bool limiting1 = ( limot1.lostop >= -M_PI || limot1.histop <= M_PI ) &&
238 limot1.lostop <= limot1.histop;
239 bool limiting2 = ( limot2.lostop >= -M_PI || limot2.histop <= M_PI ) &&
240 limot2.lostop <= limot2.histop;
242 // We need to call testRotationLimit() even if we're motored, since it
243 // records the result.
244 limot1.limit = 0;
245 limot2.limit = 0;
246 if ( limiting1 || limiting2 )
248 dReal angle1, angle2;
249 getAngles( &angle1, &angle2 );
250 if ( limiting1 )
251 limot1.testRotationalLimit( angle1 );
252 if ( limiting2 )
253 limot2.testRotationalLimit( angle2 );
256 if ( limot1.limit || limot1.fmax > 0 ) info->m++;
257 if ( limot2.limit || limot2.fmax > 0 ) info->m++;
262 void
263 dxJointPU::getInfo2( dxJoint::Info2 *info )
265 const int s0 = 0;
266 const int s1 = info->rowskip;
267 const int s2 = 2 * s1;
269 const dReal k = info->fps * info->erp;
271 // pull out pos and R for both bodies. also get the `connection'
272 // vector pos2-pos1.
274 dReal *pos1, *pos2 = 0, *R1, *R2 = 0;
275 pos1 = node[0].body->posr.pos;
276 R1 = node[0].body->posr.R;
277 if ( node[1].body )
279 pos2 = node[1].body->posr.pos;
280 R2 = node[1].body->posr.R;
283 dVector3 axP; // Axis of the prismatic joint in global frame
284 dMultiply0_331( axP, R1, axisP1 );
286 // distance between the body1 and the anchor2 in global frame
287 // Calculated in the same way as the offset
288 dVector3 dist;
289 dVector3 wanchor2 = {0,0,0};
290 if ( node[1].body )
292 dMultiply0_331( wanchor2, R2, anchor2 );
293 dist[0] = wanchor2[0] + pos2[0] - pos1[0];
294 dist[1] = wanchor2[1] + pos2[1] - pos1[1];
295 dist[2] = wanchor2[2] + pos2[2] - pos1[2];
297 else
299 if (flags & dJOINT_REVERSE )
301 // Invert the sign of dist
302 dist[0] = pos1[0] - anchor2[0];
303 dist[1] = pos1[1] - anchor2[1];
304 dist[2] = pos1[2] - anchor2[2];
306 else
308 dist[0] = anchor2[0] - pos1[0];
309 dist[1] = anchor2[1] - pos1[1];
310 dist[2] = anchor2[2] - pos1[2];
314 dVector3 q; // Temporary axis vector
315 // Will be used at 2 places with 2 different meaning
317 // ======================================================================
318 // Work on the angular part (i.e. row 0)
321 // The axis perpendicular to both axis1 and axis2 should be the only unconstrained
322 // rotational axis, the angular velocity of the two bodies perpendicular to
323 // the rotoide axes should be equal. Thus the constraint equations are
324 // p*w1 - p*w2 = 0
325 // where p is a unit vector perpendicular to both axis1 and axis2
326 // and w1 and w2 are the angular velocity vectors of the two bodies.
327 dVector3 ax1, ax2;
328 getAxes( ax1, ax2 );
329 dReal val = dCalcVectorDot3( ax1, ax2 );
330 q[0] = ax2[0] - val * ax1[0];
331 q[1] = ax2[1] - val * ax1[1];
332 q[2] = ax2[2] - val * ax1[2];
334 dVector3 p;
335 dCalcVectorCross3( p, ax1, q );
336 dNormalize3( p );
338 // info->J1a[s0+i] = p[i];
339 dCopyVector3(( info->J1a ) + s0, p );
341 if ( node[1].body )
343 // info->J2a[s0+i] = -p[i];
344 dCopyNegatedVector3(( info->J2a ) + s0, p );
347 // compute the right hand side of the constraint equation. Set relative
348 // body velocities along p to bring the axes back to perpendicular.
349 // If ax1, ax2 are unit length joint axes as computed from body1 and
350 // body2, we need to rotate both bodies along the axis p. If theta
351 // is the angle between ax1 and ax2, we need an angular velocity
352 // along p to cover the angle erp * (theta - Pi/2) in one step:
354 // |angular_velocity| = angle/time = erp*(theta - Pi/2) / stepsize
355 // = (erp*fps) * (theta - Pi/2)
357 // if theta is close to Pi/2,
358 // theta - Pi/2 ~= cos(theta), so
359 // |angular_velocity| ~= (erp*fps) * (ax1 dot ax2)
361 info->c[0] = k * - val;
365 // ==========================================================================
366 // Work on the linear part (i.e rows 1 and 2)
368 // We want: vel2 = vel1 + w1 x c ... but this would
369 // result in three equations, so we project along the planespace vectors
370 // so that sliding along the axisP is disregarded.
372 // p1 + R1 dist' = p2 + R2 anchor2'
373 // v1 + w1 x R1 dist' + v_p = v2 + w2 x R2 anchor2'
374 // v_p is speed of prismatic joint (i.e. elongation rate)
375 // Since the constraints are perpendicular to v_p we have:
376 // e1 dot v_p = 0 and e2 dot v_p = 0
377 // e1 dot ( v1 + w1 x dist = v2 + w2 x anchor2 )
378 // e2 dot ( v1 + w1 x dist = v2 + w2 x anchor2 )
379 // ==
380 // e1 . v1 + e1 . w1 x dist = e1 . v2 + e1 . w2 x anchor2
381 // since a . (b x c) = - b . (a x c) = - (a x c) . b
382 // and a x b = - b x a
383 // e1 . v1 - e1 x dist . w1 - e1 . v2 - (- e1 x anchor2 . w2) = 0
384 // e1 . v1 + dist x e1 . w1 - e1 . v2 - anchor2 x e1 . w2 = 0
385 // Coeff for 1er line of: J1l => e1, J2l => -e1
386 // Coeff for 2er line of: J1l => e2, J2l => -ax2
387 // Coeff for 1er line of: J1a => dist x e1, J2a => - anchor2 x e1
388 // Coeff for 2er line of: J1a => dist x e2, J2a => - anchor2 x e2
389 // e1 and e2 are perpendicular to axP
390 // so e1 = ax1 and e2 = ax1 x axP
391 // N.B. ax2 is not always perpendicular to axP since it is attached to body 2
392 dCalcVectorCross3( q , ax1, axP );
394 dMultiply0_331( axP, R1, axisP1 );
396 dCalcVectorCross3(( info->J1a ) + s1, dist, ax1 );
397 dCalcVectorCross3(( info->J1a ) + s2, dist, q );
399 // info->J1l[s1+i] = ax[i];
400 dCopyVector3(( info->J1l ) + s1, ax1 );
402 // info->J1l[s2+i] = q[i];
403 dCopyVector3(( info->J1l ) + s2, q );
405 if ( node[1].body )
407 // Calculate anchor2 in world coordinate
409 // q x anchor2 instead of anchor2 x q since we want the negative value
410 dCalcVectorCross3(( info->J2a ) + s1, ax1, wanchor2 );
411 // The cross product is in reverse order since we want the negative value
412 dCalcVectorCross3(( info->J2a ) + s2, q, wanchor2 );
415 // info->J2l[s1+i] = -ax1[i];
416 dCopyNegatedVector3(( info->J2l ) + s1, ax1 );
417 // info->J2l[s2+i] = -ax1[i];
418 dCopyNegatedVector3(( info->J2l ) + s2, q );
423 // We want to make correction for motion not in the line of the axisP
424 // We calculate the displacement w.r.t. the anchor pt.
426 // compute the elements 1 and 2 of right hand side.
427 // We want to align the offset point (in body 2's frame) with the center of body 1.
428 // The position should be the same when we are not along the prismatic axis
429 dVector3 err;
430 dMultiply0_331( err, R1, anchor1 );
431 // err[i] = dist[i] - err[i];
432 dSubtractVectors3( err, dist, err );
433 info->c[1] = k * dCalcVectorDot3( ax1, err );
434 info->c[2] = k * dCalcVectorDot3( q, err );
436 int row = 3 + limot1.addLimot( this, info, 3, ax1, 1 );
437 row += limot2.addLimot( this, info, row, ax2, 1 );
439 if ( node[1].body || !(flags & dJOINT_REVERSE) )
440 limotP.addLimot( this, info, row, axP, 0 );
441 else
443 axP[0] = -axP[0];
444 axP[1] = -axP[1];
445 axP[2] = -axP[2];
446 limotP.addLimot ( this, info, row, axP, 0 );
450 void dJointSetPUAnchor( dJointID j, dReal x, dReal y, dReal z )
452 dxJointPU* joint = ( dxJointPU* ) j;
453 dUASSERT( joint, "bad joint argument" );
454 checktype( joint, PU );
455 setAnchors( joint, x, y, z, joint->anchor1, joint->anchor2 );
456 joint->computeInitialRelativeRotations();
460 * This function initialize the anchor and the relative position of each body
461 * as if body2 was at its current position + [dx,dy,dy].
462 * Ex:
463 * <PRE>
464 * dReal offset = 1;
465 * dVector3 dir;
466 * dJointGetPUAxis3(jId, dir);
467 * dJointSetPUAnchor(jId, 0, 0, 0);
468 * // If you request the position you will have: dJointGetPUPosition(jId) == 0
469 * dJointSetPUAnchorDelta(jId, 0, 0, 0, dir[X]*offset, dir[Y]*offset, dir[Z]*offset);
470 * // If you request the position you will have: dJointGetPUPosition(jId) == -offset
471 * </PRE>
473 * @param j The PU joint for which the anchor point will be set
474 * @param x The X position of the anchor point in world frame
475 * @param y The Y position of the anchor point in world frame
476 * @param z The Z position of the anchor point in world frame
477 * @param dx A delta to be added to the X position as if the anchor was set
478 * when body1 was at current_position[X] + dx
479 * @param dx A delta to be added to the Y position as if the anchor was set
480 * when body1 was at current_position[Y] + dy
481 * @param dx A delta to be added to the Z position as if the anchor was set
482 * when body1 was at current_position[Z] + dz
483 * @note Should have the same meaning as dJointSetSliderAxisDelta
485 void dJointSetPUAnchorDelta( dJointID j, dReal x, dReal y, dReal z,
486 dReal dx, dReal dy, dReal dz )
488 dxJointPU* joint = ( dxJointPU* ) j;
489 dUASSERT( joint, "bad joint argument" );
490 checktype( joint, PU );
492 if ( joint->node[0].body )
494 joint->node[0].body->posr.pos[0] += dx;
495 joint->node[0].body->posr.pos[1] += dy;
496 joint->node[0].body->posr.pos[2] += dz;
499 setAnchors( joint, x, y, z, joint->anchor1, joint->anchor2 );
501 if ( joint->node[0].body )
503 joint->node[0].body->posr.pos[0] -= dx;
504 joint->node[0].body->posr.pos[1] -= dy;
505 joint->node[0].body->posr.pos[2] -= dz;
508 joint->computeInitialRelativeRotations();
512 * \brief This function initialize the anchor and the relative position of each body
513 * such that dJointGetPUPosition will return the dot product of axis and [dx,dy,dy].
515 * The body 1 is moved to [-dx, -dy, -dx] then the anchor is set. This will be the
516 * position 0 for the prismatic part of the joint. Then the body 1 is moved to its
517 * original position.
519 * Ex:
520 * <PRE>
521 * dReal offset = 1;
522 * dVector3 dir;
523 * dJointGetPUAxis3(jId, dir);
524 * dJointSetPUAnchor(jId, 0, 0, 0);
525 * // If you request the position you will have: dJointGetPUPosition(jId) == 0
526 * dJointSetPUAnchorDelta(jId, 0, 0, 0, dir[X]*offset, dir[Y]*offset, dir[Z]*offset);
527 * // If you request the position you will have: dJointGetPUPosition(jId) == offset
528 * </PRE>
530 * @param j The PU joint for which the anchor point will be set
531 * @param x The X position of the anchor point in world frame
532 * @param y The Y position of the anchor point in world frame
533 * @param z The Z position of the anchor point in world frame
534 * @param dx A delta to be added to the X position as if the anchor was set
535 * when body1 was at current_position[X] + dx
536 * @param dx A delta to be added to the Y position as if the anchor was set
537 * when body1 was at current_position[Y] + dy
538 * @param dx A delta to be added to the Z position as if the anchor was set
539 * when body1 was at current_position[Z] + dz
540 * @note Should have the same meaning as dJointSetSliderAxisDelta
542 void dJointSetPUAnchorOffset( dJointID j, dReal x, dReal y, dReal z,
543 dReal dx, dReal dy, dReal dz )
545 dxJointPU* joint = ( dxJointPU* ) j;
546 dUASSERT( joint, "bad joint argument" );
547 checktype( joint, PU );
549 if (joint->flags & dJOINT_REVERSE)
551 dx = -dx;
552 dy = -dy;
553 dz = -dz;
556 if ( joint->node[0].body )
558 joint->node[0].body->posr.pos[0] -= dx;
559 joint->node[0].body->posr.pos[1] -= dy;
560 joint->node[0].body->posr.pos[2] -= dz;
563 setAnchors( joint, x, y, z, joint->anchor1, joint->anchor2 );
565 if ( joint->node[0].body )
567 joint->node[0].body->posr.pos[0] += dx;
568 joint->node[0].body->posr.pos[1] += dy;
569 joint->node[0].body->posr.pos[2] += dz;
572 joint->computeInitialRelativeRotations();
579 void dJointSetPUAxis1( dJointID j, dReal x, dReal y, dReal z )
581 dxJointPU* joint = ( dxJointPU* ) j;
582 dUASSERT( joint, "bad joint argument" );
583 checktype( joint, PU );
584 if ( joint->flags & dJOINT_REVERSE )
585 setAxes( joint, x, y, z, NULL, joint->axis2 );
586 else
587 setAxes( joint, x, y, z, joint->axis1, NULL );
588 joint->computeInitialRelativeRotations();
591 void dJointSetPUAxis2( dJointID j, dReal x, dReal y, dReal z )
593 dxJointPU* joint = ( dxJointPU* ) j;
594 dUASSERT( joint, "bad joint argument" );
595 checktype( joint, PU );
596 if ( joint->flags & dJOINT_REVERSE )
597 setAxes( joint, x, y, z, joint->axis1, NULL );
598 else
599 setAxes( joint, x, y, z, NULL, joint->axis2 );
600 joint->computeInitialRelativeRotations();
604 void dJointSetPUAxisP( dJointID id, dReal x, dReal y, dReal z )
606 dJointSetPUAxis3( id, x, y, z );
611 void dJointSetPUAxis3( dJointID j, dReal x, dReal y, dReal z )
613 dxJointPU* joint = ( dxJointPU* ) j;
614 dUASSERT( joint, "bad joint argument" );
615 checktype( joint, PU );
617 setAxes( joint, x, y, z, joint->axisP1, 0 );
619 joint->computeInitialRelativeRotations();
625 void dJointGetPUAngles( dJointID j, dReal *angle1, dReal *angle2 )
627 dxJointUniversal* joint = ( dxJointUniversal* ) j;
628 dUASSERT( joint, "bad joint argument" );
629 checktype( joint, PU );
630 if ( joint->flags & dJOINT_REVERSE )
631 joint->getAngles( angle2, angle1 );
632 else
633 joint->getAngles( angle1, angle2 );
637 dReal dJointGetPUAngle1( dJointID j )
639 dxJointUniversal* joint = ( dxJointUniversal* ) j;
640 dUASSERT( joint, "bad joint argument" );
641 checktype( joint, PU );
642 if ( joint->flags & dJOINT_REVERSE )
643 return joint->getAngle2();
644 else
645 return joint->getAngle1();
649 dReal dJointGetPUAngle2( dJointID j )
651 dxJointUniversal* joint = ( dxJointUniversal* ) j;
652 dUASSERT( joint, "bad joint argument" );
653 checktype( joint, PU );
654 if ( joint->flags & dJOINT_REVERSE )
655 return joint->getAngle1();
656 else
657 return joint->getAngle2();
661 dReal dJointGetPUAngle1Rate( dJointID j )
663 dxJointPU* joint = ( dxJointPU* ) j;
664 dUASSERT( joint, "bad joint argument" );
665 checktype( joint, PU );
667 if ( joint->node[0].body )
669 dVector3 axis;
671 if ( joint->flags & dJOINT_REVERSE )
672 getAxis2( joint, axis, joint->axis2 );
673 else
674 getAxis( joint, axis, joint->axis1 );
676 dReal rate = dCalcVectorDot3( axis, joint->node[0].body->avel );
677 if ( joint->node[1].body ) rate -= dCalcVectorDot3( axis, joint->node[1].body->avel );
678 return rate;
680 return 0;
684 dReal dJointGetPUAngle2Rate( dJointID j )
686 dxJointPU* joint = ( dxJointPU* ) j;
687 dUASSERT( joint, "bad joint argument" );
688 checktype( joint, PU );
690 if ( joint->node[0].body )
692 dVector3 axis;
694 if ( joint->flags & dJOINT_REVERSE )
695 getAxis( joint, axis, joint->axis1 );
696 else
697 getAxis2( joint, axis, joint->axis2 );
699 dReal rate = dCalcVectorDot3( axis, joint->node[0].body->avel );
700 if ( joint->node[1].body ) rate -= dCalcVectorDot3( axis, joint->node[1].body->avel );
701 return rate;
703 return 0;
707 void dJointSetPUParam( dJointID j, int parameter, dReal value )
709 dxJointPU* joint = ( dxJointPU* ) j;
710 dUASSERT( joint, "bad joint argument" );
711 checktype( joint, PU );
713 switch ( parameter & 0xff00 )
715 case dParamGroup1:
716 joint->limot1.set( parameter, value );
717 break;
718 case dParamGroup2:
719 joint->limot2.set( parameter & 0xff, value );
720 break;
721 case dParamGroup3:
722 joint->limotP.set( parameter & 0xff, value );
723 break;
727 void dJointGetPUAnchor( dJointID j, dVector3 result )
729 dxJointPU* joint = ( dxJointPU* ) j;
730 dUASSERT( joint, "bad joint argument" );
731 dUASSERT( result, "bad result argument" );
732 checktype( joint, PU );
734 if ( joint->node[1].body )
735 getAnchor2( joint, result, joint->anchor2 );
736 else
738 // result[i] = joint->anchor2[i];
739 dCopyVector3( result, joint->anchor2 );
743 void dJointGetPUAxis1( dJointID j, dVector3 result )
745 dxJointPU* joint = ( dxJointPU* ) j;
746 dUASSERT( joint, "bad joint argument" );
747 dUASSERT( result, "bad result argument" );
748 checktype( joint, PU );
749 if ( joint->flags & dJOINT_REVERSE )
750 getAxis2( joint, result, joint->axis2 );
751 else
752 getAxis( joint, result, joint->axis1 );
755 void dJointGetPUAxis2( dJointID j, dVector3 result )
757 dxJointPU* joint = ( dxJointPU* ) j;
758 dUASSERT( joint, "bad joint argument" );
759 dUASSERT( result, "bad result argument" );
760 checktype( joint, PU );
761 if ( joint->flags & dJOINT_REVERSE )
762 getAxis( joint, result, joint->axis1 );
763 else
764 getAxis2( joint, result, joint->axis2 );
768 * @brief Get the prismatic axis
769 * @ingroup joints
771 * @note This function was added for convenience it is the same as
772 * dJointGetPUAxis3
774 void dJointGetPUAxisP( dJointID id, dVector3 result )
776 dJointGetPUAxis3( id, result );
780 void dJointGetPUAxis3( dJointID j, dVector3 result )
782 dxJointPU* joint = ( dxJointPU* ) j;
783 dUASSERT( joint, "bad joint argument" );
784 dUASSERT( result, "bad result argument" );
785 checktype( joint, PU );
786 getAxis( joint, result, joint->axisP1 );
789 dReal dJointGetPUParam( dJointID j, int parameter )
791 dxJointPU* joint = ( dxJointPU* ) j;
792 dUASSERT( joint, "bad joint argument" );
793 checktype( joint, PU );
795 switch ( parameter & 0xff00 )
797 case dParamGroup1:
798 return joint->limot1.get( parameter );
799 break;
800 case dParamGroup2:
801 return joint->limot2.get( parameter & 0xff );
802 break;
803 case dParamGroup3:
804 return joint->limotP.get( parameter & 0xff );
805 break;
808 return 0;
812 dJointType
813 dxJointPU::type() const
815 return dJointTypePU;
819 size_t
820 dxJointPU::size() const
822 return sizeof( *this );
826 void
827 dxJointPU::setRelativeValues()
829 dVector3 anchor;
830 dJointGetPUAnchor(this, anchor);
831 setAnchors( this, anchor[0], anchor[1], anchor[2], anchor1, anchor2 );
833 dVector3 ax1, ax2, ax3;
834 dJointGetPUAxis1(this, ax1);
835 dJointGetPUAxis2(this, ax2);
836 dJointGetPUAxis3(this, ax3);
838 if ( flags & dJOINT_REVERSE )
840 setAxes( this, ax1[0], ax1[1], ax1[2], NULL, axis2 );
841 setAxes( this, ax2[0], ax2[1], ax2[2], axis1, NULL );
843 else
845 setAxes( this, ax1[0], ax1[1], ax1[2], axis1, NULL );
846 setAxes( this, ax2[0], ax2[1], ax2[2], NULL, axis2 );
850 setAxes( this, ax3[0], ax3[1], ax3[2], NULL, axisP1 );
852 computeInitialRelativeRotations();