GithubHelp home page GithubHelp logo

thecomet / ik Goto Github PK

View Code? Open in Web Editor NEW
486.0 16.0 69.0 1.68 MB

Minimal Inverse Kinematics library

License: MIT License

CMake 5.65% C 74.34% C++ 11.93% Shell 0.44% Python 6.36% Verilog 1.28%
inverse-kinematics solver animation inverse-kinematics-library wiki-page calculations python-bindings algorithm-library ik 3d

ik's Introduction

Inverse Kinematics Library

An implementation of the FABRIK solver. Specialized 2-bone and 1-bone solvers are also included.

See the wiki page for details on how to use it

Building

You can build the project as follows using the default settings:

mkdir build && cd build
cmake ../
make -j8
make install

For a detailed list of all of the build options, see the wiki page On POSIX systems, you can enable malloc()/free() wrappers with -DIK_MEMORY_DEBUGGING=ON and you can further enable memory backtraces with -DIK_MEMORY_BACKTRACE=ON.

Unit tests and benchmarks are also included, those can be enabled with -DIK_TESTS=ON and -DIK_BENCHMARKS=ON, respectively.

Overview

IK (Inverse kinematics) can be useful in many situations ranging from procedural animation to small adjustments of animation. Simply put, IK is used when you want to position the tips of a hierarchichal structure at a known location and need to calculate all of the rotations of the parent joints to achieve this.

Here is an example of foot placement being adjusted according to inclination.

Click to see image

Here is another example of the paw of a dog being placed at a location using IK.

Supported features are

  • Solving arbitrary trees (including disjoint trees) with any number of end effectors.
  • Matching target rotations as well as target positions.
  • Calculation of joint rotations, useful for skinned characters.
  • Specifying chain length for each effector.
  • Conversion between local and global space.
  • Weighted end effectors to facilitate transitioning between the solved and initial transforms.
  • Nlerp of weighted end effectors to make transitioning look more natural.
  • Logging.
  • Dumping trees to DOT format.

Features being worked on are

  • Weighted segments.
  • Joint constraints and constraint callbacks.
  • Bone skipping.
  • Mass/Spring/Damper solver.

All of the code was written in C89 and has no dependencies other than the C standard library. Memory debugging facilities are in place to track memory leaks. On linux, backtraces can be generated to the respective malloc() and free() calls.

Example usage

Here is a minimal working example that probably satisfies your needs.

#include <ik/ik.h>

int main()
{
    /* Create a solver using the FABRIK algorithm */
    struct ik_solver_t* solver = ik.solver.create(IK_FABRIK);

    /* Create a simple 3-bone structure */
    struct ik_node_t* root = solver->node->create(0);
    struct ik_node_t* child1 = solver->node->create_child(1, root);
    struct ik_node_t* child2 = solver->node->create_child(2, child1);
    struct ik_node_t* child3 = solver->node->create_child(3, child2);

    /* Set node positions in local space so they form a straight line in the Y direction*/
    child1->position = ik.vec3.vec3(0, 10, 0);
    child2->position = ik.vec3.vec3(0, 10, 0);
    child3->position = ik.vec3.vec3(0, 10, 0);

    /* Attach an effector at the end */
    struct ik_effector_t* eff = solver->effector->create();
    solver->effector->attach(eff, child3);

    /* set the target position of the effector to be somewhere within range */
    eff->target_position = ik.vec3.vec3(2, -3, 5);

    /* We want to calculate rotations as well as positions */
    solver->flags |= IK_ENABLE_TARGET_ROTATIONS;

    /* Assign our tree to the solver, rebuild data and calculate solution */
    ik.solver.set_tree(solver, root);
    ik.solver.rebuild_data(solver);
    ik.solver.solve(solver);
}

See the wiki page for details on how to use it

ik's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ik's Issues

Target has an offset when setting chain_length

When I set the effector->chain_length to something smaller than number of nodes-2, the solution has a constant offset to my specified effector->target_position. And this offset gets bigger with smaller chain_lengths.

Am I doing something wrong or is this a bug?
I am using the latest master branch.

should iterate_affected_nodes be used ?

I just want to get each frame's result, should i use iterate_affected_nodes?
in my opinion, the easiest way is get tree's all child node's position? is it?

Cannot compile sample code

Hi,

I was trying to build devel branch and run the example on my Mac (https://github.com/TheComet/ik#example-usage).
CMake works, make -j8 works and make install is error free as well.
But I cut'n pasted the example code and just tried to compile it on the command line, but it does not compile.
With the c++ command I get that ik is not declared:

$ c++ -std=c++17 -I ../install/include/  main.c
main.c:5:9: error: use of undeclared identifier 'ik'
    if (ik.init() != IK_OK)

And in C:

clang -I ../install/include/  main.c
main.c:5:16: error: called object type '<dependent type>' is not a function or function pointer
    if (ik.init() != IK_OK)

I didn't change the default value of IK_API_NAME, but I also explicitely set it to 'ik', nothing changed.

Here are the only changes I've made to devel:

  • there were some obsolete path to include/public/ that cause make install to fail
  • uname command line differs on Mac
$ git diff
diff --git a/ik/CMakeLists.txt b/ik/CMakeLists.txt
index 918c007..02765a9 100644
--- a/ik/CMakeLists.txt
+++ b/ik/CMakeLists.txt
@@ -78,7 +78,8 @@ set (IK_COMPILER ${CMAKE_C_COMPILER_ID})
 find_program (UNAME_PROGRAM uname)
 if (UNAME_PROGRAM)
     execute_process (
-        COMMAND ${UNAME_PROGRAM} -ormpi
+        #COMMAND ${UNAME_PROGRAM} -ormpi
+        COMMAND ${UNAME_PROGRAM}  -r -m -p
         OUTPUT_VARIABLE IK_HOST_COMPUTER)
     string (REPLACE "\n" "" IK_HOST_COMPUTER ${IK_HOST_COMPUTER})
 else ()
@@ -452,8 +453,8 @@ install (
     RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
 install (
     DIRECTORY
-        "include/public/ik"
-        "${CMAKE_CURRENT_BINARY_DIR}/include/public/ik"
+        "include/ik"
+        "${CMAKE_CURRENT_BINARY_DIR}/include/ik"
     DESTINATION
         ${CMAKE_INSTALL_INCLUDEDIR})

Thanks for your help.

How to set and get the rotation of each joint

Hi there,

I would like to use your library for my inverse kinematics of Ergonomic project ,however the instructions are not very clear for a beginner.Mainly lie in the input and output of rotations.The questions can be listed as follows:
1、Before ik.solver.solve(solver),should we set the rotations of root->rotation and target->rotation in global space ?
At the same time,should we set the rotation of child->rotation in local space?
2、After ik.solver.solve(solver),I want to get the rotation of each joint in order to realize the inverse kinematics,but I don't know whether the rotation that I get is a global rotation or a local rotation?
3、After ik.solver.solve(solver),whether the joint's rotation that I get is a delta rotation?

What's more,I have tried several forms of input and output of rotations, but the result is always unsatisfactory.Look forward to hearing from you.

Better Documentation for Building

Hi there,

I have a noob request. I would like to use your library for my arduino project however build instructions are not very clear for a beginner.

I couldn't run the example on my project.

Running the example code

Hi!

I would like to try to use your software in my school project. For this project in need to make a robot arm move to a specific coordinate. After ready the wiki i wanted to try out the example code form the README file. I ran into some issue's

  1. So i started my virtual machine with an ubuntu 18.04 image.
  2. I ran the required commands
mkdir build && cd build
cmake ../
make -j8
sudo make install
  1. Then i made a new file in another directory and executed the example code from the README with the following command
    sudo g++ -o mytest test.cpp

It did not comple an gave the following errors:

test.cpp: In function ‘int main()’:
test.cpp:10:66: error: invalid conversion from ‘int’ to ‘ik_node_t*’ [-fpermissive]
     struct ik_node_t* child1 = solver->node->create_child(1, root);
                                                                  ^
test.cpp:10:66: error: invalid conversion from ‘ik_node_t*’ to ‘uint32_t {aka unsigned int}’ [-fpermissive]
test.cpp:11:68: error: invalid conversion from ‘int’ to ‘ik_node_t*’ [-fpermissive]
     struct ik_node_t* child2 = solver->node->create_child(2, child1);
                                                                    ^
test.cpp:11:68: error: invalid conversion from ‘ik_node_t*’ to ‘uint32_t {aka unsigned int}’ [-fpermissive]
test.cpp:12:68: error: invalid conversion from ‘int’ to ‘ik_node_t*’ [-fpermissive]
     struct ik_node_t* child3 = solver->node->create_child(3, child2);
                                                                    ^
test.cpp:12:68: error: invalid conversion from ‘ik_node_t*’ to ‘uint32_t {aka unsigned int}’ [-fpermissive]
test.cpp:31:15: error: ‘const struct ik_solver_interface_t’ has no member named ‘rebuild_data’; did you mean ‘rebuild’?
     ik.solver.rebuild_data(solver);
               ^~~~~~~~~~~~
               rebuild

I tried fixing it, but no succes.

  1. Then i tried the example code form Tutorial 2.0
    This gave these errors:
test.cpp: In function ‘int main()’:
test.cpp:4:5: error: ‘ik_init’ was not declared in this scope
     ik_init();
     ^~~~~~~
test.cpp:5:5: error: ‘ik_log_init’ was not declared in this scope
     ik_log_init();
     ^~~~~~~~~~~
test.cpp:8:43: error: ‘ik_uid’ was not declared in this scope
     struct ik_node* base = ik_node_create(ik_uid(0));
                                           ^~~~~~
test.cpp:8:43: note: suggested alternative: ‘ik_node’
     struct ik_node* base = ik_node_create(ik_uid(0));
                                           ^~~~~~
                                           ik_node
test.cpp:8:28: error: ‘ik_node_create’ was not declared in this scope
     struct ik_node* base = ik_node_create(ik_uid(0));
                            ^~~~~~~~~~~~~~
test.cpp:8:28: note: suggested alternative: ‘ik_node_t’
     struct ik_node* base = ik_node_create(ik_uid(0));
                            ^~~~~~~~~~~~~~
                            ik_node_t
test.cpp:9:5: error: ‘IK_INCREF’ was not declared in this scope
     IK_INCREF(base); /* Always have to take ownership of root node */
     ^~~~~~~~~

the list goes on.

I probably made a mistake while setting everything up. mabey i have to put the file i want to compile somewhere specific?
Could you tell me how i can compile one of the examples?

How to use the Python bindings?

I'm interested in running the FABRIK solver from Python, but the bindings don't seem to work. I'm unable to initialize the solver (it seems that the call to the initializer is commented out) and other classes as well. Do you have any pointers on how to make it work?

How work "eff->target_position"?

Please help me, I cannot understand how the effector position works.
For example, if I want to place child3 in world coordinates (30,30,0), what coordinates should I set for the effector?

ik

Correct sample

Example in description is outdated.

Correct example:

	/* Create a solver using the FABRIK algorithm */
struct ik_solver_t* solver = ik.solver.create(IK_FABRIK);

/* Create a simple 3-bone structure */
struct ik_node_t* root = solver->node->create(0);
struct ik_node_t* child1 = solver->node->create_child(root, 1);
struct ik_node_t* child2 = solver->node->create_child(child1, 2);
struct ik_node_t* child3 = solver->node->create_child(child2, 3);

/* Set node positions in local space so they form a straight line in the Y direction*/
child1->position = ik.vec3.vec3(0, 10, 0);
child2->position = ik.vec3.vec3(0, 10, 0);
child3->position = ik.vec3.vec3(0, 10, 0);

/* Attach an effector at the end */
struct ik_effector_t* eff = solver->effector->create();
solver->effector->attach(eff, child3);

/* set the target position of the effector to be somewhere within range */
eff->target_position = ik.vec3.vec3(2, -3, 5);

/* We want to calculate rotations as well as positions */
solver->flags |= IK_ENABLE_TARGET_ROTATIONS;

/* Assign our tree to the solver, rebuild data and calculate solution */
ik.solver.set_tree(solver, root);
ik.solver.rebuild(solver);
ik.solver.solve(solver);

ik.solver.rebuild_data(solver); -> ik.solver.rebuild(solver);
struct ik_node_t* child1 = solver->node->create_child(1, root); -> struct ik_node_t* child1 = solver->node->create_child(root, 1);

Obtaining Joint Angles

How to I obtain the joint angles in Radians or Degrees from this library, so that I can use it for a Robot Arm?

the algorithm is diffcult to use

the doc is poor and hard to understand, and there is little example code.
the code crash after 2 or 3 frames loop.
I wonder how to set each frame input and get each frame output?
what the MyGameNode mean in doc? If i should create another tree named MyGameNode?

How to implement Hinge Constraints?

Hey, I noticed that constraints don't seem to be implemented yet, I would like to try implementing it.
Would hinge constraints just be clamping angles of the quaternion or is it more complicated to do correctly?
https://github.com/TheComet/ik/blob/devel/ik/src/constraint.c#L35

This fabrik IK library is pretty useful and I'm using the version from Urho3D as a standalone, I was wondering if any insight could be provided on what parts of the this ik library need finishing and how to conceptually do so; Like implementing hinge constraints.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.