CMatrix* CIkRoutine::getJacobian(CikEl* ikElement,C4X4Matrix& tooltipTransf,std::vector<int>* rowJointIDs,std::vector<int>* rowJointStages)
{	// rowJointIDs is NULL by default. If not null, it will contain the ids of the joints
	// corresponding to the rows of the jacobian.
	// Return value NULL means that is ikElement is either inactive, either invalid
	// tooltipTransf is the cumulative transformation matrix of the tooltip,
	// computed relative to the base!
	// The temporary joint parameters need to be initialized before calling this function!
	// We check if the ikElement's base is in the chain and that tooltip is valid!
	CDummy* tooltip=ct::objCont->getDummy(ikElement->getTooltip());
	if (tooltip==NULL)
	{ // Should normally never happen!
		ikElement->setActive(false);
		return(NULL);
	}
	C3DObject* base=ct::objCont->getObject(ikElement->getBase());
	if ( (base!=NULL)&&(!tooltip->isObjectParentedWith(base)) )
	{ // This case can happen (when the base's parenting was changed for instance)
		ikElement->setBase(-1);
		ikElement->setActive(false);
		return(NULL);
	}

	// We check the number of degrees of freedom and prepare the rowJointIDs vector:
	C3DObject* iterat=tooltip;
	int doF=0;
	while (iterat!=base)
	{
		iterat=iterat->getParent();
		if ( (iterat!=NULL)&&(iterat!=base) )
		{
			if (iterat->getObjectType()==sim_object_joint_type)
			{
				if ( (((CJoint*)iterat)->getJointMode()==sim_jointmode_ik)||(((CJoint*)iterat)->getJointMode()==sim_jointmode_ikdependent) )
				{
					int d=((CJoint*)iterat)->getDoFs();
					for (int i=d-1;i>=0;i--)
					{
						if (rowJointIDs!=NULL)
						{
							rowJointIDs->push_back(iterat->getID());
							rowJointStages->push_back(i);
						}
					}
					doF+=d;
				}
			}
		}
	}
	CMatrix* J=new CMatrix(6,(unsigned char)doF);
	std::vector<C4X4FullMatrix*> jMatrices;
	for (int i=0;i<(doF+1);i++)
	{
		C4X4FullMatrix* matr=new C4X4FullMatrix();
		if (i==0)
			(*matr).setIdentity();
		else
			(*matr).clear();
		jMatrices.push_back(matr);
	}

	// Now we go from tip to base:
	iterat=tooltip;
	C4X4FullMatrix buff;
	buff.setIdentity();
	int positionCounter=0;
	C4X4FullMatrix d0;
	C4X4FullMatrix dp;
	C4X4FullMatrix paramPart;
	CJoint* lastJoint=NULL;
	int indexCnt=-1;
	int indexCntLast=-1;
	while (iterat!=base)
	{
		C3DObject* nextIterat=iterat->getParent();
		C7Vector local;
		if (iterat->getObjectType()==sim_object_joint_type)
		{
			if ( (((CJoint*)iterat)->getJointMode()!=sim_jointmode_ik)&&(((CJoint*)iterat)->getJointMode()!=sim_jointmode_ikdependent) )
				local=iterat->getLocalTransformation(true);
			else
			{
				CJoint* it=(CJoint*)iterat;
				if (it->getJointType()==sim_joint_spherical_subtype)
				{
					if (indexCnt==-1)
						indexCnt=it->getDoFs()-1;
					it->getLocalTransformationExPart1(local,indexCnt--,true);
					if (indexCnt!=-1)
						nextIterat=iterat; // We keep the same object! (but indexCnt has decreased)
				}
				else
					local=iterat->getLocalTransformationPart1(true);
			}
		}
		else
			local=iterat->getLocalTransformation(true); 

		buff=C4X4FullMatrix(local.getMatrix())*buff;
		iterat=nextIterat;
		bool activeJoint=false;
		if (iterat!=NULL) // Following lines recently changed!
		{
			if (iterat->getObjectType()==sim_object_joint_type) 
				activeJoint=( (((CJoint*)iterat)->getJointMode()==sim_jointmode_ik)||(((CJoint*)iterat)->getJointMode()==sim_jointmode_ikdependent) );
		}
		if ( (iterat==base)||activeJoint )
		{	// If base is NULL then the second part is not evaluated (iterat->getObjectType())
			if (positionCounter==0)
			{	// Here we have the first part (from tooltip to first joint)
				d0=buff;
				dp.clear();
				multiply(d0,dp,0,jMatrices);
			}
			else
			{	// Here we have a joint:
				if (lastJoint->getJointType()==sim_joint_revolute_subtype)
				{
					buildDeltaZRotation(d0,dp,lastJoint->getScrewPitch());
					multiply(d0,dp,positionCounter,jMatrices);
					paramPart.buildZRotation(lastJoint->getPosition(true));
				}
				else if (lastJoint->getJointType()==sim_joint_prismatic_subtype)
				{
					buildDeltaZTranslation(d0,dp);
					multiply(d0,dp,positionCounter,jMatrices);
					paramPart.buildTranslation(0.0f,0.0f,lastJoint->getPosition(true));
				}
				else 
				{ // Spherical joint part!
					buildDeltaZRotation(d0,dp,0.0f);
					multiply(d0,dp,positionCounter,jMatrices);
					if (indexCntLast==-1)
						indexCntLast=lastJoint->getDoFs()-1;
					paramPart.buildZRotation(lastJoint->getTempParameterEx(indexCntLast--));
				}
				d0=buff*paramPart;
				dp.clear();
				multiply(d0,dp,0,jMatrices);
			}
			buff.setIdentity();
			lastJoint=(CJoint*)iterat;
			positionCounter++;
		}
	}

	int alternativeBaseForConstraints=ikElement->getAlternativeBaseForConstraints();
	if (alternativeBaseForConstraints!=-1)
	{
		CDummy* alb=ct::objCont->getDummy(alternativeBaseForConstraints);
		if (alb!=NULL)
		{ // We want everything relative to the alternativeBaseForConstraints dummy orientation!
			C7Vector alternativeBase(alb->getCumulativeTransformationPart1(true));
			C7Vector currentBase;
			currentBase.setIdentity();
			if (base!=NULL)
				currentBase=base->getCumulativeTransformation(true); // could be a joint, we want also the joint intrinsic transformation part!
			C4X4FullMatrix correction((alternativeBase.getInverse()*currentBase).getMatrix());
			dp.clear();
			multiply(correction,dp,0,jMatrices);
		}
	}

	// The x-, y- and z-component:
	for (int i=0;i<doF;i++)
	{
		(*J)(0,i)=(*jMatrices[1+i])(0,3);
		(*J)(1,i)=(*jMatrices[1+i])(1,3);
		(*J)(2,i)=(*jMatrices[1+i])(2,3);
	}
	// We divide all delta components (to avoid distorsions)...
	for (int i=0;i<doF;i++)
		(*jMatrices[1+i])/=IK_DIVISION_FACTOR;
	// ...and add the cumulative transform to the delta-components:
	for (int i=0;i<doF;i++)
		(*jMatrices[1+i])+=(*jMatrices[0]);
	// We also copy the cumulative transform to 'tooltipTransf':
	tooltipTransf=(*jMatrices[0]);
	// Now we extract the delta Euler components:
	C4X4FullMatrix mainInverse(*jMatrices[0]);
	mainInverse.invert();
	C4X4FullMatrix tmp;
	// Alpha-, Beta- and Gamma-components:
	for (int i=0;i<doF;i++)
	{
		tmp=mainInverse*(*jMatrices[1+i]);
		C3Vector euler(tmp.getEulerAngles());
		(*J)(3,i)=euler(0);
		(*J)(4,i)=euler(1);
		(*J)(5,i)=euler(2);
	}


	// We free the memory allocated for each joint variable:
	for (int i=0;i<int(jMatrices.size());i++)
		delete jMatrices[i];
	return(J);
}
Beispiel #2
0
//Write
void urdfLink::createLink(bool hideCollisionLinks,bool convexDecomposeNonConvexCollidables,bool createVisualIfNone,bool& showConvexDecompositionDlg)
{
	std::string txt("Creating link '"+name+"'...");
	printToConsole(txt.c_str());

    //visuals.clear();

    // Visuals
    for (int i=0; i<visuals.size(); i++) {
        urdfElement &visual = visuals[i];
        
        if(!visual.meshFilename.empty())
        {
            std::string fname(visual.meshFilename);
            bool exists=true;
            bool useAlt=false;
            if (!simDoesFileExist(fname.c_str()))
            {
                fname=visual.meshFilename_alt;
                exists=simDoesFileExist(fname.c_str());
                useAlt=true;
            }

            if (!exists)
                printToConsole("ERROR: the mesh file could not be found.");
            else
                visual.n = simImportShape(visual.meshExtension,fname.c_str(),0,0.0001f,1.0);

            if (!visual.n)
            {
                if (!useAlt)
                    txt="ERROR: failed to create the mesh '"+visual.meshFilename+"' with extension type "+boost::lexical_cast<std::string>(visual.meshExtension);
                else
                    txt="ERROR: failed to create the mesh '"+visual.meshFilename+"' or '"+visual.meshFilename_alt+"' with extension type "+boost::lexical_cast<std::string>(visual.meshExtension);
                printToConsole(txt.c_str());
            }
            else
                visual.n = scaleShapeIfRequired(visual.n,visual.mesh_scaling);
        }
        else if (!isArrayEmpty(visual.sphere_size))
            visual.n = simCreatePureShape( 1,1+2+16, visual.sphere_size, mass, NULL);
        else if (!isArrayEmpty(visual.cylinder_size))
            visual.n = simCreatePureShape( 2,1+2+16, visual.cylinder_size, mass, NULL);
        else if (!isArrayEmpty(visual.box_size))
            visual.n = simCreatePureShape( 0,1+2+16, visual.box_size, mass, NULL);
    }

    //collisions.clear();
    //mass=0.1;

	//collision
    for (int i=0; i<collisions.size(); i++) {
        urdfElement &collision = collisions[i];

        if(!collision.meshFilename.empty())
        { 	
            std::string fname(collision.meshFilename);
            bool exists=true;
            bool useAlt=false;
            if (!simDoesFileExist(fname.c_str()))
            {
                fname=collision.meshFilename_alt;
                exists=simDoesFileExist(fname.c_str());
                useAlt=true;
            }

            if (!exists)
                printToConsole("ERROR: the mesh file could not be found");
            else
                collision.n = simImportShape(collision.meshExtension,fname.c_str(),0,0.0001f,1.0);

            if (collision.n == -1)
            {
                if (!useAlt)
                    txt="ERROR: failed to create the mesh '"+collision.meshFilename+"' with extension type "+boost::lexical_cast<std::string>(collision.meshExtension);
                else
                    txt="ERROR: failed to create the mesh '"+collision.meshFilename+"' or '"+collision.meshFilename_alt+"' with extension type "+boost::lexical_cast<std::string>(collision.meshExtension);
                printToConsole(txt.c_str());
            }
            else
            {
                collision.n=scaleShapeIfRequired(collision.n,collision.mesh_scaling);
                if (createVisualIfNone&&(visuals.size()==0))
                { // We create a visual from the collision shape (before it gets morphed hereafter):
                    simRemoveObjectFromSelection(sim_handle_all,-1);
                    simAddObjectToSelection(sim_handle_single,collision.n);
                    simCopyPasteSelectedObjects();
                    addVisual();
                    currentVisual().n = simGetObjectLastSelection();
                }
                int p;
                int convInts[5]={1,500,200,0,0}; // 3rd value from 100 to 500 on 5/2/2014
                float convFloats[5]={100.0f,30.0f,0.25f,0.0f,0.0f};
                if ( convexDecomposeNonConvexCollidables&&(simGetObjectIntParameter(collision.n,3017,&p)>0)&&(p==0) )
                {
                    int aux=1+4+8+16+64;
                    if (showConvexDecompositionDlg)
                        aux=1+2+8+16+64;
                    showConvexDecompositionDlg=false;
                    simConvexDecompose(collision.n,aux,convInts,convFloats); // we generate convex shapes!
                }
                simSetObjectIntParameter(collision.n,3003,!inertiaPresent); // we make it non-static if there is an inertia
                simSetObjectIntParameter(collision.n,3004,1); // we make it respondable since it is a collision object
            }

        }
        else if (!isArrayEmpty(collision.sphere_size))
            collision.n = simCreatePureShape( 1,1+2+4+8+16*(!inertiaPresent), collision.sphere_size, mass, NULL);
        else if (!isArrayEmpty(collision.cylinder_size))
            collision.n = simCreatePureShape( 2,1+2+4+8+16*(!inertiaPresent), collision.cylinder_size, mass, NULL);
        else if (!isArrayEmpty(collision.box_size))
            collision.n = simCreatePureShape( 0,1+2+4+8+16*(!inertiaPresent), collision.box_size, mass, NULL);
    }

    // Hack to draw COM in the collision layer
    /*
    addCollision();
    currentCollision().xyz[0] = inertial_xyz[0];
    currentCollision().xyz[1] = inertial_xyz[1];
    currentCollision().xyz[0] = inertial_xyz[2];
    currentCollision().rpy[0] = 1.5;
    float dummySize[3]={0.01f,0.01f,0.01f};
    currentCollision().n = simCreatePureShape( 1,1+2+16, dummySize, mass, NULL);
    */
    
    // Grouping collisions shapes
    nLinkCollision = groupShapes(collisions);

	// Inertia
	if (inertiaPresent)
	{
        C3Vector euler;

		if (nLinkCollision==-1)
		{ // we do not have a collision object. Let's create a dummy collision object, since inertias can't exist on their own in V-REP:
			float dummySize[3]={0.01f,0.01f,0.01f};
			//nLinkCollision = simCreatePureShape( 1,1+2+4, dummySize, mass, NULL); // we make it non-respondable!
            nLinkCollision = simCreatePureShape( 1,1+2+16, dummySize, mass, NULL);
		}

		C7Vector inertiaFrame;
		inertiaFrame.X.set(inertial_xyz);
		inertiaFrame.Q=getQuaternionFromRpy(inertial_rpy);
            
        //simSetObjectPosition(nLinkCollision,-1,inertiaFrame.X.data);
			
		//C7Vector collisionFrame;
		//collisionFrame.X.set(collision_xyz);
		//collisionFrame.Q=getQuaternionFromRpy(collision_rpy);
			
        C7Vector collisionFrame;
        simGetObjectPosition(nLinkCollision,-1,collisionFrame.X.data);
        simGetObjectOrientation(nLinkCollision,-1,euler.data);
		collisionFrame.Q.setEulerAngles(euler);

		//C4X4Matrix x((collisionFrame.getInverse()*inertiaFrame).getMatrix());
		C4X4Matrix x(inertiaFrame.getMatrix());
		float i[12]={x.M(0,0),x.M(0,1),x.M(0,2),x.X(0),x.M(1,0),x.M(1,1),x.M(1,2),x.X(1),x.M(2,0),x.M(2,1),x.M(2,2),x.X(2)};
		simSetShapeMassAndInertia(nLinkCollision,mass,inertia,C3Vector::zeroVector.data,i);
		//std::cout << "Mass: " << mass << std::endl;
	}
	else
	{
		if (nLinkCollision!=-1)
		{
			std::string txt("ERROR: found a collision object without inertia data for link '"+ name+"'. Is that link meant to be static?");
			printToConsole(txt.c_str());
		}
	}

	if (createVisualIfNone&&(visuals.size()==0)&&(nLinkCollision!=-1))
	{ // We create a visual from the collision shape (meshes were handled earlier):
        addVisual();
        urdfElement &visual = currentVisual();
		simRemoveObjectFromSelection(sim_handle_all,-1);
		simAddObjectToSelection(sim_handle_single,nLinkCollision);
		simCopyPasteSelectedObjects();
		visual.n=simGetObjectLastSelection();
		simSetObjectIntParameter(visual.n,3003,1); // we make it static since only visual
		simSetObjectIntParameter(visual.n,3004,0); // we make it non-respondable since only visual
	}

	// Set the respondable mask:
	if (nLinkCollision!=-1)
		simSetObjectIntParameter(nLinkCollision,3019,0xff00); // colliding with everything except with other objects in that tree hierarchy

    // Grouping shapes
    nLinkVisual = groupShapes(visuals);
	
    // Set the names, visibility, etc.:
	if (nLinkVisual!=-1)
	{
		setVrepObjectName(nLinkVisual,std::string(name+"_visual").c_str());
		const float specularDiffuse[3]={0.3f,0.3f,0.3f};
		if (nLinkCollision!=-1)
		{ // if we have a collision object, we attach the visual object to it, then forget the visual object
            C7Vector collisionFrame;
            C3Vector euler;
            simGetObjectPosition(nLinkCollision,-1,collisionFrame.X.data);
            simGetObjectOrientation(nLinkCollision,-1,euler.data);
            collisionFrame.Q.setEulerAngles(euler);
			 
            C7Vector visualFrame;
			simGetObjectPosition(nLinkVisual,-1,visualFrame.X.data);
			simGetObjectOrientation(nLinkVisual,-1,euler.data);
			visualFrame.Q.setEulerAngles(euler);

			C7Vector x(collisionFrame.getInverse()*visualFrame);

			simSetObjectPosition(nLinkVisual,-1,x.X.data);
			simSetObjectOrientation(nLinkVisual,-1,x.Q.getEulerAngles().data);
			simSetObjectParent(nLinkVisual,nLinkCollision,0);
		}
	}
	if (nLinkCollision!=-1)
	{
		setVrepObjectName(nLinkCollision,std::string(name+"_respondable").c_str());
		if (hideCollisionLinks)
			simSetObjectIntParameter(nLinkCollision,10,256); // we "hide" that object in layer 9
	}
}
Beispiel #3
0
CMatrix* CIKChain::getJacobian(CIKDummy* tooltip,C4X4Matrix& tooltipTransf,std::vector<CIKJoint*>& theRowJoints,int jointNbToExclude)
{	// theRowJoints will contain the IK-joint objects corresponding to the columns of the jacobian.
	// tooltipTransf is the cumulative transformation of the tooltip (aux. return value)
	// The temporary joint parameters need to be initialized before calling this function!

	// We check the number of degrees of freedom and prepare the theRowJoints vector:
	CIKObject* iterat=tooltip;
	int doF=0;
	while (iterat!=NULL)
	{
		iterat=iterat->parent;
		if ( (iterat!=NULL)&&(iterat->objectType==IK_JOINT_TYPE) )
		{
			if (((CIKJoint*)iterat)->active)
			{
				theRowJoints.push_back((CIKJoint*)iterat);
				doF++;
			}
		}
	}

	// Here we have to compensate for jointNbToExclude:
	if (jointNbToExclude>0)
	{	
		doF-=jointNbToExclude;
		if (doF<1)
		{ // Impossible to get a Jacobian in that case!
			theRowJoints.clear();
			return(NULL); 
		}
		theRowJoints.erase(theRowJoints.end()-jointNbToExclude,theRowJoints.end());
	}

	CMatrix* J=new CMatrix(6,(BYTE)doF);
	std::vector<C4X4FullMatrix*> jMatrices;
	jMatrices.reserve(doF+1);
	jMatrices.clear();
	for (int i=0;i<(doF+1);i++)
	{
		C4X4FullMatrix* matr=new C4X4FullMatrix();
		if (i==0)
			(*matr).setIdentity();
		else
			(*matr).clear();
		jMatrices.push_back(matr);
	}
	// Now we go from tip to base:
	iterat=tooltip;
	C4X4FullMatrix buff;
	buff.setIdentity();
	int positionCounter=0;
	C4X4FullMatrix d0;
	C4X4FullMatrix dp;
	C4X4FullMatrix paramPart;
	CIKJoint* lastJoint=NULL;
	int jointCounter=0;
	while (iterat!=NULL)
	{
		C7Vector local;

		if ((jointCounter<doF)&&((CIKJoint*)iterat)->active )
			local=iterat->getLocalTransformationPart1(true);
		else
			local=iterat->getLocalTransformation(true);
		if ( (iterat!=NULL)&&(iterat->objectType==IK_JOINT_TYPE)&&((CIKJoint*)iterat)->active )
			jointCounter++;


		buff=C4X4FullMatrix(local.getMatrix())*buff;
		iterat=iterat->parent;

		if ( (iterat==NULL)||((iterat->objectType==IK_JOINT_TYPE)&&((CIKJoint*)iterat)->active&&(positionCounter<doF)) )
		{
			if (positionCounter==0)
			{	// Here we have the first part (from tooltip to first joint)
				d0=buff;
				dp.clear();
				multiply(d0,dp,0,jMatrices);
			}
			else
			{	// Here we have a joint:
				if (lastJoint->revolute)
				{
					buildDeltaZRotation(d0,dp,lastJoint->screwPitch);
					multiply(d0,dp,positionCounter,jMatrices);
					paramPart.buildZRotation(lastJoint->tempParameter);
				}
				else
				{
					buildDeltaZTranslation(d0,dp);
					multiply(d0,dp,positionCounter,jMatrices);
					paramPart.buildTranslation(0.0f,0.0f,lastJoint->tempParameter);
				}
				d0=buff*paramPart;
				dp.clear();
				multiply(d0,dp,0,jMatrices);
			}
			buff.setIdentity();
			lastJoint=(CIKJoint*)iterat;
			positionCounter++;
		}
	}

	// The x-, y- and z-component:
	for (int i=0;i<doF;i++)
	{
		(*J)(0,i)=(*jMatrices[1+i])(0,3);
		(*J)(1,i)=(*jMatrices[1+i])(1,3);
		(*J)(2,i)=(*jMatrices[1+i])(2,3);
	}
	// We divide all delta components (to avoid distorsions)...
	for (int i=0;i<doF;i++)
		(*jMatrices[1+i])/=IK_DIVISION_FACTOR;
	// ...and add the cumulative transform to the delta-components:
	for (int i=0;i<doF;i++)
		(*jMatrices[1+i])+=(*jMatrices[0]);
	// We also copy the cumulative transform to 'tooltipTransf':
	tooltipTransf=(*jMatrices[0]);
	// Now we extract the delta Euler components:
	C4X4FullMatrix mainInverse(*jMatrices[0]);
	mainInverse.invert();
	C4X4FullMatrix tmp;
	// Alpha-, Beta- and Gamma-components:
	for (int i=0;i<doF;i++)
	{
		tmp=mainInverse*(*jMatrices[1+i]);
		C3Vector euler(tmp.getEulerAngles());
		(*J)(3,i)=euler(0);
		(*J)(4,i)=euler(1);
		(*J)(5,i)=euler(2);
	}
	// We free the memory allocated for each joint variable:
	for (int i=0;i<int(jMatrices.size());i++)
		delete jMatrices[i];

	// Now we have to combine columns which are linked to the same joints:
	for (int i=0;i<int(theRowJoints.size());i++)
	{
		CIKJoint* aJoint=theRowJoints[i];
		if (aJoint!=NULL)
		{
			for (int j=i+1;j<int(theRowJoints.size());j++)
			{
				CIKJoint* bJoint=theRowJoints[j];
				if (bJoint!=NULL)
				{
					if (aJoint==bJoint->avatarParent)
					{			
						for (int k=0;k<J->rows;k++)
							(*J)(k,i)+=(*J)(k,j);
						theRowJoints[j]=NULL; // We remove that joint
						break;
					}
					if (bJoint==aJoint->avatarParent)
					{			
						for (int k=0;k<J->rows;k++)
							(*J)(k,j)+=(*J)(k,i);
						theRowJoints[i]=NULL; // We remove that joint
						break;
					}
				}
			}
		}
	}
	// And now we create the new matrix and rowJoints:
	int colNb=0;
	std::vector<CIKJoint*> rowJointsCopy(theRowJoints);
	theRowJoints.clear();
	for (int i=0;i<int(rowJointsCopy.size());i++)
	{
		if (rowJointsCopy[i]!=NULL)
			colNb++;
	}
	CMatrix* oldMatrix=J;
	J=new CMatrix(oldMatrix->rows,colNb);
	int horizPos=0;
	for (int i=0;i<oldMatrix->cols;i++)
	{
		if (rowJointsCopy[i]!=NULL)
		{
			for (int j=0;j<oldMatrix->rows;j++)
				(*J)(j,horizPos)=(*oldMatrix)(j,i);
			theRowJoints.push_back(rowJointsCopy[i]);
			horizPos++;
		}
	}
	delete oldMatrix;
	return(J);
}