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:

  • Setting up a kinematic task from exported kinematic content: by first building your kinematics task in CoppeliaSim, exporting its kinematic content, and importing it into your application.
  • Setting up a kinematic task from scratch: by building your kinematics task from scratch directly in your application
  • Refer also to the Coppelia Kinematics Routines C++ API documentation:

  • Coppelia Kinematics Routines C++ API list (in alphabetical order)
  • Coppelia Kinematics Routines C++ API list (by category)
  • 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.


    Setting up a kinematic task from exported kinematic content

    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.


    Setting up a kinematic task from scratch

    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

  • Forward/inverse kinematics overview
  • The kinematics plugin for CoppeliaSim