Coppelia Kinematics Routines (auxiliary API)The Coppelia Kinematics Routines is a collection of C++ functions that allow to solve forward/inverse kinematics tasks for any type of mechanism (redundant/non-redundant, containing nested loops, etc.). Those functions give CoppeliaSim its kinematics calculation capability. You can embedd and use the Coppelia Kinematics Routines in your stand-alone application, which then can programmatically set up complex kinematics tasks in two different ways: Refer also to the Coppelia Kinematics Routines C++ API documentation: The Coppelia Kinematics Routines source code is not directly part of CoppeliaSim, and carries separate licensing conditions. Refer to the source code for details, and contact us.
The idea is to normally build your kinematic task inside of CoppeliaSim via the GUI, then to export the kinematic content of a scene [Menu bar --> File --> Export --> Kinematics content...], which can then be imported and used via the Coppelia Kinematics Routines. A minimalistic application using this approach could look like: #include "ik.h"
int main(int argc, char* argv[])
{
// Read the exported kinematic file:
FILE *file;
file=fopen("robot.ik","rb");
if (file)
{
fseek(file,0,SEEK_END);
unsigned long fl=ftell(file);
int dataLength=(int)fl;
fseek(file,0,SEEK_SET);
std::vector<unsigned char> data;
data.resize(dataLength);
fread((char*)&data[0],dataLength,1,file);
fclose(file);
// Initialize the environment and import the kinematic data:
ikCreateEnvironment();
ikLoad(&data[0],dataLength);
// Get some handles from the robot model:
int motorHandles[7];
ikGetObjectHandle("robot_joint1",motorHandles+0);
ikGetObjectHandle("robot_joint2",motorHandles+1);
ikGetObjectHandle("robot_joint3",motorHandles+2);
ikGetObjectHandle("robot_joint4",motorHandles+3);
ikGetObjectHandle("robot_joint5",motorHandles+4);
ikGetObjectHandle("robot_joint6",motorHandles+5);
ikGetObjectHandle("robot_joint7",motorHandles+6);
int targetHandle;
ikGetObjectHandle("robot_target",&targetHandle);
int baseHandle;
ikGetObjectHandle("LBR_iiwa_7_R800",&baseHandle);
// Get the initial target dummy transformation, of the robot:
C7Vector initTargetTransf;
ikGetObjectTransformation(targetHandle,baseHandle,&initTargetTransf);
simReal v=0.0;
while (true)
{
// Slightly modify the position of the target dummy:
v+=simReal(0.01)
C7Vector targetTransf(initTargetTransf);
targetTransf.X(2)+=simReal(sin(v)*0.1);
ikSetObjectTransformation(targetHandle,baseHandle,&targetTransf);
// calculate IK:
ikHandleIkGroup(ik_handle_all);
// Read the corresponding robot joint angles and do something with them:
simReal config[7];
for (int i=0;i<7;i++)
ikGetJointPosition(motorHandles[i],config+i);
}
ikEraseEnvironment();
}
return(0);
}
Refer also to the following examples: standAloneKinematicsDemo1, standAloneKinematicsDemo2, standAloneKinematicsDemo3. Those demo applications use the Coppelia Kinematics Routines described here, combined with the legacy remote API functionality to control different robots in inverse/forward kinematics mode. The demo scenes standAloneKinematicsDemo1.ttt, standAloneKinematicsDemo2.ttt and standAloneKinematicsDemo3.ttt launch the standAloneKinematicsDemo1, standAloneKinematicsDemo2 and respectively standAloneKinematicsDemo3 applications automatically.
Follow the method below to perform kinematic calculations from within your own external application: #include "ik.h"
int main(int argc, char* argv[])
{
// Create the IK environment:
ikCreateEnvironment();
// Create a simple 3 DoF kinematic chain:
int tipHandle,targetHandle;
int joint1Handle,joint2Handle,joint3Handle;
ikCreateJoint(nullptr,ik_jointtype_revolute,&joint1Handle);
ikCreateJoint(nullptr,ik_jointtype_revolute,&joint2Handle);
C7Vector tr(C4Vector(1.57,0.0,0.0),C3Vector::zeroVector);
ikSetObjectTransformation(joint2Handle,-1,&tr);
ikSetObjectParent(joint2Handle,joint1Handle,true);
ikCreateJoint(nullptr,ik_jointtype_revolute,&joint3Handle);
tr.X=C3Vector(0.0,0.0,0.2);
ikSetObjectTransformation(joint3Handle,-1,&tr);
ikSetObjectParent(joint3Handle,joint2Handle,true);
ikCreateDummy(nullptr,&tipHandle);
tr.Q.clear();
tr.X=C3Vector(0.0,0.0,0.4);
ikSetObjectTransformation(tipHandle,-1,&tr);
ikSetObjectParent(tipHandle,joint3Handle,true);
ikCreateDummy(nullptr,&targetHandle);
ikSetObjectTransformation(targetHandle,-1,&tr);
ikSetLinkedDummy(tipHandle,targetHandle);
// we now have: joint1 --> joint2 --> joint3 --> tipDummy <...> targetDummy
// Create an IK group that constrains the chain tip to follow (in position)
// the target dummy:
int ikGroup;
ikCreateIkGroup(nullptr,&ikGroup);
int ikElementIndex;
ikAddIkElement(ikGroup,tipHandle,&ikElementIndex);
ikSetIkElementConstraints(ikGroup,ikElementIndex,ik_constraint_position);
ikGetObjectTransformation(targetHandle,-1,&tr);
while (true)
{
// Slightly move the target dummy:
tr.X=tr.X+C3Vector(0.001,0.002,-0.0001);
ikSetObjectTransformation(targetHandle,-1,&tr)
// Solve IK:
int result;
ikHandleIkGroup(ikGroup,&result);
if (result==ik_result_fail)
break;
// Read joint values:
simReal joint1Angle,joint2Angle,joint3Angle;
ikGetJointPosition(joint1Handle,&joint1Angle);
ikGetJointPosition(joint2Handle,&joint2Angle);
ikGetJointPosition(joint3Handle,&joint3Angle);
}
return(0);
}
Recommended topics |