Esempio n. 1
0
Kinematic PMoveable::odeToKinematic()
{
    Kinematic k;
    dQuaternion q_result, q_result1, q_base;
    float norm;
    const dReal *b_info;
    const dReal *q_current = dBodyGetQuaternion(body);

    q_base[0] = 0; q_base[1] = 0; q_base[2] = 0; q_base[3] = 1;
    dQMultiply0(q_result1, q_current, q_base);
    dQMultiply2(q_result, q_result1, q_current);

    k.orientation_v = Vec3f(q_result[1], q_result[2], q_result[3]);
    norm = sqrt(q_result[1] * q_result[1] + q_result[3] * q_result[3]);

    if (norm == 0)
        k.orientation = 0;
    else
        k.orientation = atan2(q_result[1] / norm, q_result[3] / norm);

    b_info = dBodyGetPosition(body);
    k.pos = Vec3f(b_info[0], b_info[1], b_info[2]);
    b_info = dBodyGetLinearVel(body);
    k.vel = Vec3f(b_info[0], b_info[1], b_info[2]);

    return k;
}
Esempio n. 2
0
dReal
dxJointUniversal::getAngle2()
{
    if ( node[0].body )
    {
        // length 1 joint axis in global coordinates, from each body
        dVector3 ax1, ax2;
        dMatrix3 R;
        dQuaternion qcross, qq, qrel;

        getAxes( ax1, ax2 );

        // It should be possible to get both angles without explicitly
        // constructing the rotation matrix of the cross.  Basically,
        // orientation of the cross about axis1 comes from body 2,
        // about axis 2 comes from body 1, and the perpendicular
        // axis can come from the two bodies somehow.  (We don't really
        // want to assume it's 90 degrees, because in general the
        // constraints won't be perfectly satisfied, or even very well
        // satisfied.)
        //
        // However, we'd need a version of getHingeAngleFromRElativeQuat()
        // that CAN handle when its relative quat is rotated along a direction
        // other than the given axis.  What I have here works,
        // although it's probably much slower than need be.

        dRFrom2Axes( R, ax2[0], ax2[1], ax2[2], ax1[0], ax1[1], ax1[2] );
        dRtoQ( R, qcross );

        if ( node[1].body )
        {
            dQMultiply1( qq, node[1].body->q, qcross );
            dQMultiply2( qrel, qq, qrel2 );
        }
        else
        {
            // pretend joint->node[1].body->q is the identity
            dQMultiply2( qrel, qcross, qrel2 );
        }

        return - getHingeAngleFromRelativeQuat( qrel, axis2 );
    }
    return 0;
}
Esempio n. 3
0
void setFixedOrientation( dxJoint *joint, dxJoint::Info2 *info, dQuaternion qrel, int start_row )
{
    int s = info->rowskip;
    int start_index = start_row * s;

    // 3 rows to make body rotations equal
    info->J1a[start_index] = 1;
    info->J1a[start_index + s + 1] = 1;
    info->J1a[start_index + s*2+2] = 1;
    if ( joint->node[1].body )
    {
        info->J2a[start_index] = -1;
        info->J2a[start_index + s+1] = -1;
        info->J2a[start_index + s*2+2] = -1;
    }

    // compute the right hand side. the first three elements will result in
    // relative angular velocity of the two bodies - this is set to bring them
    // back into alignment. the correcting angular velocity is
    //   |angular_velocity| = angle/time = erp*theta / stepsize
    //                      = (erp*fps) * theta
    //    angular_velocity  = |angular_velocity| * u
    //                      = (erp*fps) * theta * u
    // where rotation along unit length axis u by theta brings body 2's frame
    // to qrel with respect to body 1's frame. using a small angle approximation
    // for sin(), this gives
    //    angular_velocity  = (erp*fps) * 2 * v
    // where the quaternion of the relative rotation between the two bodies is
    //    q = [cos(theta/2) sin(theta/2)*u] = [s v]

    // get qerr = relative rotation (rotation error) between two bodies
    dQuaternion qerr, e;
    if ( joint->node[1].body )
    {
        dQuaternion qq;
        dQMultiply1( qq, joint->node[0].body->q, joint->node[1].body->q );
        dQMultiply2( qerr, qq, qrel );
    }
    else
    {
        dQMultiply3( qerr, joint->node[0].body->q, qrel );
    }
    if ( qerr[0] < 0 )
    {
        qerr[1] = -qerr[1];  // adjust sign of qerr to make theta small
        qerr[2] = -qerr[2];
        qerr[3] = -qerr[3];
    }
    dMultiply0_331( e, joint->node[0].body->posr.R, qerr + 1 );  // @@@ bad SIMD padding!
    dReal k = info->fps * info->erp;
    info->c[start_row] = 2 * k * e[0];
    info->c[start_row+1] = 2 * k * e[1];
    info->c[start_row+2] = 2 * k * e[2];
}
Esempio n. 4
0
dReal getHingeAngle( dxBody *body1, dxBody *body2, dVector3 axis,
                     dQuaternion q_initial )
{
    // get qrel = relative rotation between the two bodies
    dQuaternion qrel;
    if ( body2 )
    {
        dQuaternion qq;
        dQMultiply1( qq, body1->q, body2->q );
        dQMultiply2( qrel, qq, q_initial );
    }
    else
    {
        // pretend body2->q is the identity
        dQMultiply3( qrel, body1->q, q_initial );
    }

    return getHingeAngleFromRelativeQuat( qrel, axis );
}
Esempio n. 5
0
void testQuaternionMultiply()
{
  HEADER;
  dMatrix3 RA,RB,RC,Rtest;
  dQuaternion qa,qb,qc;
  dReal diff,maxdiff=0;

  for (int i=0; i<100; i++) {
    makeRandomRotation (RB);
    makeRandomRotation (RC);
    dRtoQ (RB,qb);
    dRtoQ (RC,qc);

    dMultiply0 (RA,RB,RC,3,3,3);
    dQMultiply0 (qa,qb,qc);
    dQtoR (qa,Rtest);
    diff = dMaxDifference (Rtest,RA,3,3);
    if (diff > maxdiff) maxdiff = diff;

    dMultiply1 (RA,RB,RC,3,3,3);
    dQMultiply1 (qa,qb,qc);
    dQtoR (qa,Rtest);
    diff = dMaxDifference (Rtest,RA,3,3);
    if (diff > maxdiff) maxdiff = diff;

    dMultiply2 (RA,RB,RC,3,3,3);
    dQMultiply2 (qa,qb,qc);
    dQtoR (qa,Rtest);
    diff = dMaxDifference (Rtest,RA,3,3);
    if (diff > maxdiff) maxdiff = diff;

    dMultiply0 (RA,RC,RB,3,3,3);
    transpose3x3 (RA);
    dQMultiply3 (qa,qb,qc);
    dQtoR (qa,Rtest);
    diff = dMaxDifference (Rtest,RA,3,3);
    if (diff > maxdiff) maxdiff = diff;
  }
  printf ("\tmaximum difference = %e - %s\n",maxdiff,
	  (maxdiff > tol) ? "FAILED" : "passed");
}
Esempio n. 6
0
void
dxJointUniversal::getAngles( dReal *angle1, dReal *angle2 )
{
    if ( node[0].body )
    {
        // length 1 joint axis in global coordinates, from each body
        dVector3 ax1, ax2;
        dMatrix3 R;
        dQuaternion qcross, qq, qrel;

        getAxes( ax1, ax2 );

        // It should be possible to get both angles without explicitly
        // constructing the rotation matrix of the cross.  Basically,
        // orientation of the cross about axis1 comes from body 2,
        // about axis 2 comes from body 1, and the perpendicular
        // axis can come from the two bodies somehow.  (We don't really
        // want to assume it's 90 degrees, because in general the
        // constraints won't be perfectly satisfied, or even very well
        // satisfied.)
        //
        // However, we'd need a version of getHingeAngleFromRElativeQuat()
        // that CAN handle when its relative quat is rotated along a direction
        // other than the given axis.  What I have here works,
        // although it's probably much slower than need be.

        dRFrom2Axes( R, ax1[0], ax1[1], ax1[2], ax2[0], ax2[1], ax2[2] );

        dRtoQ( R, qcross );


        // This code is essentialy the same as getHingeAngle(), see the comments
        // there for details.

        // get qrel = relative rotation between node[0] and the cross
        dQMultiply1( qq, node[0].body->q, qcross );
        dQMultiply2( qrel, qq, qrel1 );

        *angle1 = getHingeAngleFromRelativeQuat( qrel, axis1 );

        // This is equivalent to
        // dRFrom2Axes(R, ax2[0], ax2[1], ax2[2], ax1[0], ax1[1], ax1[2]);
        // You see that the R is constructed from the same 2 axis as for angle1
        // but the first and second axis are swapped.
        // So we can take the first R and rapply a rotation to it.
        // The rotation is around the axis between the 2 axes (ax1 and ax2).
        // We do a rotation of 180deg.

        dQuaternion qcross2;
        // Find the vector between ax1 and ax2 (i.e. in the middle)
        // We need to turn around this vector by 180deg

        // The 2 axes should be normalize so to find the vector between the 2.
        // Add and devide by 2 then normalize or simply normalize
        //    ax2
        //    ^
        //    |
        //    |
        ///   *------------> ax1
        //    We want the vector a 45deg
        //
        // N.B. We don't need to normalize the ax1 and ax2 since there are
        //      normalized when we set them.

        // We set the quaternion q = [cos(theta), dir*sin(theta)] = [w, x, y, Z]
        qrel[0] = 0;                // equivalent to cos(Pi/2)
        qrel[1] = ax1[0] + ax2[0];  // equivalent to x*sin(Pi/2); since sin(Pi/2) = 1
        qrel[2] = ax1[1] + ax2[1];
        qrel[3] = ax1[2] + ax2[2];

        dReal l = dRecip( sqrt( qrel[1] * qrel[1] + qrel[2] * qrel[2] + qrel[3] * qrel[3] ) );
        qrel[1] *= l;
        qrel[2] *= l;
        qrel[3] *= l;

        dQMultiply0( qcross2, qrel, qcross );

        if ( node[1].body )
        {
            dQMultiply1( qq, node[1].body->q, qcross2 );
            dQMultiply2( qrel, qq, qrel2 );
        }
        else
        {
            // pretend joint->node[1].body->q is the identity
            dQMultiply2( qrel, qcross2, qrel2 );
        }

        *angle2 = - getHingeAngleFromRelativeQuat( qrel, axis2 );
    }
    else
    {
        *angle1 = 0;
        *angle2 = 0;
    }
}
Esempio n. 7
0
void SCylinderParts::set(dWorldID w, dSpaceID space)
{
	double radius = m_cmpnt.radius();
	double length = m_cmpnt.length();

// konao
	//LOG_MSG(("[SCylinderParts::set] ODE geom created (r, l)=(%f, %f) [%s:%d]\n", radius, length, __FILE__, __LINE__))
	// TODO: Ideally, cylinder should be constructed here. However, collision detection
	// between two cylinders could not be realized. So, Capsule is required
	// by okamoto@tome on 2011-10-12

	//dGeomID geom = dCreateCapsule(0, radius, length);
	dGeomID geom = dCreateCylinder(0, radius, length);

	m_odeobj = ODEObjectContainer::getInstance()->createODEObj
	(
		w,
		geom,
		0.9,
		0.01,
		0.5,
		0.5,
		0.8,
		0.001,
		0.0
	);


	dBodyID body = m_odeobj->body();
	dMass m;
	dMassSetZero(&m);
	//dMassSetCapsule(&m, DENSITY, 1, radius, length);
	dMassSetCylinder(&m, DENSITY, 1, radius, length); //TODO: mass of the cylinder should be configurable

	dMassAdjust(&m, m_mass);
	dBodySetMass(body, &m);
	dGeomSetOffsetPosition(geom, m_posx, m_posy, m_posz); // gap between ODE shape and body

	// set the long axis as y axis
	dReal offq[4] = {0.707, 0.707, 0.0, 0.0};
	dReal offq2[4] = {m_inirot.qw(), m_inirot.qx(), m_inirot.qy(), m_inirot.qz()};

	dQuaternion qua;
	dQMultiply2(qua, offq2, offq);
	dGeomSetOffsetQuaternion(geom, qua);
	//dGeomSetOffsetQuaternion(geom, offq2);

	//dReal tmpq[4] = {0.707, 0.0, 0.0, 0.707};
	//dGeomSetQuaternion(geom, tmpq);
	//dBodySetQuaternion(body, tmpq);
	
	/*TODO: Consideration is required whether this procedure is needed
	 * Reflection of orientation of the cylinder
	 * dMatrix3 R;
	 * dRFromAxisAndAngle(dMatrix3 R, dReal rx, dReal ry, dReal rz,  dReal angle)
	 * dRFromAxisAndAngle(R,x_axis,y_axis,z_axis,angleData);
	 * dBodySetRotation(body,R);  // Request of actual rotation
	*/

	// Not used, deleted by inamura
	// real part of the quaternion
	// double q = cos(angleData/2.0);
	// imaginary part of the quaternion
	// double i,j,k;
	// i = x_axis * sin(angleData/2.0);
	// j = y_axis * sin(angleData/2.0);
	// k = z_axis * sin(angleData/2.0);

	m_rot.setQuaternion(1.0, 0.0, 0.0, 0.0);

	dSpaceAdd(space, geom);
	dBodySetData(body, this);
}
Esempio n. 8
0
void SParts::calcPosition(Joint *currj, Joint *nextj, const Vector3d &anchorv, const Rotation &R)
{
	if (currj) {
		DUMP(("currj  = %s\n", currj->name()));
	}
	DUMP(("name = %s\n", name()));

	if (nextj) {
		DUMP(("nextj  = %s\n", nextj->name()));
	}
	DUMP(("anchorv = (%f, %f, %f)\n", anchorv.x(), anchorv.y(), anchorv.z()));

	{
		Vector3d v(m_pos.x(), m_pos.y(), m_pos.z());

		// Calculate shift vector from positoin/anchor/orientation
		if (currj) {
			v -= currj->getAnchor();
			DUMP(("parent anchor = %s (%f, %f, %f)\n",
				  currj->name(),
				  currj->getAnchor().x(),
				  currj->getAnchor().y(), currj->getAnchor().z()));
		}

		DUMP(("v1 = (%f, %f, %f)\n", v.x(), v.y(), v.z()));
		Rotation rr(R);
		if (currj) {
			rr *= currj->getRotation();
		}

		v.rotate(rr);
		DUMP(("v2 = (%f, %f, %f)\n", v.x(), v.y(), v.z()));

		v += anchorv;
		DUMP(("v3 = (%f, %f, %f)\n", v.x(), v.y(), v.z()));


		//DUMP(("v4 = (%f, %f, %f)\n", v.x(), v.y(), v.z()));
		setPosition(v);

		if(m_onGrasp) {

			dBodyID body = odeobj().body();
			//int num = dBodyGetNumJoints(body);

			// get grasp joint
			dJointID joint = dBodyGetJoint(body, 0);

			// get target body from joint
			dBodyID targetBody = dJointGetBody(joint, 1);
		  
			// get position of grasp target and parts
			const dReal *pos  = dBodyGetPosition(body);
			const dReal *tpos = dBodyGetPosition(targetBody);

			// Set if it is moved
			if(pos[0] != tpos[0] || pos[1] != tpos[1] || pos[2] != tpos[2]) {
				dBodySetPosition(targetBody, pos[0], pos[1], pos[2]);
			}

			// get position of grasp target and parts
			const dReal *qua  = dBodyGetQuaternion(body);
			const dReal *tqua = dBodyGetQuaternion(targetBody);

			// rotation from initial orientation
			dQuaternion rot;
			dQMultiply2(rot, qua, m_gini);

			// Set if it is rotated
			if(rot[0] != tqua[0] || rot[1] != tqua[1] || rot[2] != tqua[2] || rot[3] != tqua[3]) {
				dBodySetQuaternion(targetBody, rot);
			}
			//LOG_MSG(("target2 %d", targetBody));
			//LOG_MSG(("(%f, %f, %f)", tpos[0], tpos[1], tpos[2]));
			//LOG_MSG(("onGrasp!! num = %d, joint = %d", num));
		}
	}
	Rotation rr(R);
	rr *= m_rot;
	if (currj) {
		rr *= currj->getRotation();
	}
	setRotation(rr);

	if (!nextj) { return; }

	for (ChildC::iterator i=m_children.begin(); i!=m_children.end(); i++) {
		Child *child = *i;

		Rotation R_(R);
		if (currj) {
			R_ *= currj->getRotation();
		}

		Vector3d nextv;

		nextv = nextj->getAnchor();
		if (currj) {
			nextv -= currj->getAnchor();
		}
		nextv.rotate(R_);
		nextv += anchorv;

		DUMP(("nextv1 : (%f, %f, %f)\n", nextv.x(), nextv.y(), nextv.z()));
		// act in a case that multiple JOINTs are connected to one link
		if(strcmp(nextj->name(),child->currj->name()) == 0) {
			child->nextp->calcPosition(child->currj, child->nextj, nextv, R_);
		}
	}
}