Пример #1
0
        /**
         *      This method is used to compute the torques that mimick the effect of applying a force on
         *      a rigid body, at some point. It works best if the end joint is connected to something that
         *      is grounded, otherwise (I think) this is just an approximation.
         *
         *      This function works by making use of the formula:
         *
         *      t = J' * f, where J' is dp/dq, where p is the position where the force is applied, q is
         *      'sorta' the relative orientation between links. It makes the connection between the velocity
         *      of the point p and the relative angular velocities at each joint. Here's an example of how to compute it.
         *
         *      Assume: p = pBase + R1 * v1 + R2 * v2, where R1 is the matrix from link 1 to whatever pBase is specified in,
         *              and R2 is the rotation matrix from link 2 to whatever pBase is specified in, v1 is the point from link 1's
         *              origin to link 2's origin (in link 1 coordinates), and v2 is the vector from origin of link 2 to p
         *              (in link 2 coordinates).
         *
         *              dp/dt = d(R1 * v1)/dt + d(R2 * v2)/dt = d R1/dt * v1 + d R2/dt * v2, and dR/dt = wx * R, where wx is
         *              the cross product matrix associated with the angular velocity w
         *              so dp/dt = w1x * R1 * v1 + w2x * R2 * v2, and w2 = w1 + wRel
         *
         *              = [-(R1*v1 + R2*v2)x   -(R2*v1)x ] [w1   wRel]', so the first matrix is the Jacobian.
         *              The first entry is the cross product matrix of the vector (in 'global' coordinates) from the
         *              origin of link 1 to p, and the second entry is the vector (in 'global' coordinates) from
         *              the origin of link 2 to p (and therein lies the general way of writing this).
         */
        public void computeJointTorquesEquivalentToForce(CWJoint start, Vector3 pLocal, Vector3 fGlobal, CWJoint end)
        {
            //starting from the start joint, going towards the end joint, get the origin of each link, in world coordinates,
            //and compute the vector to the global coordinates of pLocal.

            CWJoint currentJoint = start;
            Vector3 tmpV;
            Vector3 pGlobal = start.getChild().getWorldCoordinatesPoint(pLocal);

            while (currentJoint != end)
            {
                //if (currentJoint == null)
                //throwError("VirtualModelController::computeJointTorquesEquivalentToForce --> end was not a parent of start...");
                tmpV = pGlobal - currentJoint.getParent().getWorldCoordinatesPoint(currentJoint.getParentJointPosition());
                Vector3 tmpT = Vector3.Cross(tmpV, fGlobal);
                torques[currentJoint.getId()] = ((float)torques[currentJoint.getId()]) - tmpT.z;
                currentJoint = currentJoint.getParent().getParentJoint();
            }

            //and we just have to do it once more for the end joint, if it's not NULL
            if (end != null)
            {
                tmpV = pGlobal - currentJoint.getParent().getWorldCoordinatesPoint(currentJoint.getParentJointPosition());
                //torques[currentJoint.getId()] = ((float)torques[currentJoint.getId()]) - Vector3.Cross(tmpV, fGlobal).z;
            }
        }
Пример #2
0
        /**
         *      This method returns a scalar that is the ammount of feedback that needs to be added to a trajectory. It is a function of the
         *      phase in the controller's state (between 0 and 1), the vector between the stance foot and the center of mass, and the velocity of
         *      the center of mass.
         */
        override public float getFeedbackContribution(SimBiController con, CWJoint j, float phi, Vector3 d, Vector3 v)
        {
            CWRigidBody theBody;
            //Vector3 tmpP;
            float offset = 0;

            if (j != null)
            {
                theBody = j.getChild();
            }
            else
            {
                theBody = con.getCharacter().getRoot();
            }

            //we might want to initialize it (or add to it) some default value in case we are trying to control its projection
            offset = 0;
            float dToUse = Vector3.Dot(MathLib.getComplexConjugate(theBody.getOrientation()) * con.getDoubleStanceCOMError(), feedbackProjectionAxis);

            if (dToUse < dMin)
            {
                dToUse = dMin;
            }
            if (dToUse > dMax)
            {
                dToUse = dMax;
            }

            float vToUse = Vector3.Dot(MathLib.getComplexConjugate(theBody.getOrientation()) * con.getComVelocity(), feedbackProjectionAxis);

            if (vToUse < vMin)
            {
                vToUse = vMin;
            }
            if (vToUse > vMax)
            {
                vToUse = vMax;
            }

            float err = (dToUse * cd - vToUse * cv + offset);

            float result = err * totalMultiplier;

            //if (j)
            //	tprintf("%s gets: %lf\n", j->getName(), result);
            //	else
            //tprintf("root gets: %lf\n", result);

            if (result < minFeedbackValue)
            {
                result = minFeedbackValue;
            }
            if (result > maxFeedbackValue)
            {
                result = maxFeedbackValue;
            }

            //	if (j == NULL && cv > 0.4)
            //		logPrint("%lf\t%lf\t%lf\t%lf\t%lf\t%lf\n", theBody->getLocalCoordinates(con->COMOffset).dotProductWith(feedbackProjectionAxis), dToUse, theBody->getLocalCoordinates(con->comVelocity).dotProductWith(feedbackProjectionAxis), vToUse, result, forceRatioWeight);

            return(result);
        }