diff --git a/include/darwin_kinematics.h b/include/darwin_kinematics.h
new file mode 100755
index 0000000000000000000000000000000000000000..783781e8a49a95ab0aecd55691071913b5096959
--- /dev/null
+++ b/include/darwin_kinematics.h
@@ -0,0 +1,24 @@
+#ifndef _DARWIN_KINEMATICS_H
+#define _DARWIN_KINEMATICS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "stm32f1xx.h"
+
+#define DARWIN_PELVIS_LENGTH               29.0 //mm
+#define DARWIN_LEG_SIDE_OFFSET             37.0 //mm
+#define DARWIN_THIGH_LENGTH                93.0 //mm
+#define DARWIN_CALF_LENGTH                 93.0 //mm
+#define DARWIN_ANKLE_LENGTH                33.5 //mm
+#define DARWIN_LEG_LENGTH                  (DARWIN_THIGH_LENGTH + DARWIN_CALF_LENGTH + DARWIN_ANKLE_LENGTH) //mm (THIGH_LENGTH + CALF_LENGTH + ANKLE_LENGTH)
+
+// public functions
+uint8_t darwin_leg_ik(float *out, float x, float y, float z, float a, float b, float c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/darwin_math.h b/include/darwin_math.h
new file mode 100755
index 0000000000000000000000000000000000000000..82ef927c3d8c6a225cfe6c18086c37e10ea5d4a6
--- /dev/null
+++ b/include/darwin_math.h
@@ -0,0 +1,70 @@
+#ifndef _DARWIN_MATH_H
+#define _DARWIN_MATH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "stm32f1xx.h"
+
+#define   PI    3.14159
+
+typedef struct{
+  float x;
+  float y;
+  float z;
+}TPoint3D;
+
+// point public functions
+void point3d_init(TPoint3D *point);
+void point3d_load(TPoint3D *point, float x, float y, float z);
+void point3d_copy(TPoint3D *point_dst, TPoint3D *point_src);
+
+typedef struct {
+  float x;
+  float y;
+  float z;
+}TVector3D;
+
+// vector public functions
+void vector3d_init(TVector3D *vector);
+void vector3d_load(TVector3D *vector, float x, float y, float z);
+void vector3d_copy(TVector3D *vector_dst, TVector3D *vector_src);
+float vector3d_length(TVector3D *vector);
+
+enum{
+  m00=0,
+  m01,
+  m02,
+  m03,
+  m10,
+  m11,
+  m12,
+  m13,
+  m20,
+  m21,
+  m22,
+  m23,
+  m30,
+  m31,
+  m32,
+  m33,
+};
+
+typedef struct{
+  float coef[16];
+}TMatrix3D;
+
+// matrix public functions
+void matrix3d_init(TMatrix3D *matrix);
+void matrix3d_copy(TMatrix3D *matrix_dst, TMatrix3D *matrix_src);
+void matrix3d_identity(TMatrix3D *matrix);
+uint8_t matrix3d_inverse(TMatrix3D *org, TMatrix3D *inv);
+void matrix3d_set_transform(TMatrix3D *matrix, TPoint3D *point, TVector3D *vector);
+void matrix3d_mult(TMatrix3D *dst,TMatrix3D *a,TMatrix3D *b);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/darwin_kinematics.c b/src/darwin_kinematics.c
new file mode 100755
index 0000000000000000000000000000000000000000..a60ca577c8c7529d72d3d5d012f44eede9e65e10
--- /dev/null
+++ b/src/darwin_kinematics.c
@@ -0,0 +1,82 @@
+#include "darwin_kinematics.h"
+#include "darwin_math.h"
+#include <math.h>
+
+uint8_t darwin_leg_ik(float *out, float x, float y, float z, float a, float b, float c)
+{
+  TMatrix3D Tad, Tda, Tcd, Tdc, Tac;
+  TVector3D vec,orientation;
+  TPoint3D position;
+  float _Rac, _Acos, _Atan, _k, _l, _m, _n, _s, _c, _theta;
+
+  vector3d_load(&orientation,a * 180.0 / PI, b * 180.0 / PI, c * 180.0 / PI);
+  point3d_load(&position,x, y, z - DARWIN_LEG_LENGTH);
+  matrix3d_set_transform(&Tad,&position,&orientation);
+
+  vec.x = x + Tad.coef[2] * DARWIN_ANKLE_LENGTH;
+  vec.y = y + Tad.coef[6] * DARWIN_ANKLE_LENGTH;
+  vec.z = (z - DARWIN_LEG_LENGTH) + Tad.coef[10] * DARWIN_ANKLE_LENGTH;
+
+  // Get Knee
+  _Rac = vector3d_length(&vec);
+  _Acos = acos((_Rac * _Rac - DARWIN_THIGH_LENGTH * DARWIN_THIGH_LENGTH - DARWIN_CALF_LENGTH * DARWIN_CALF_LENGTH) / (2 * DARWIN_THIGH_LENGTH * DARWIN_CALF_LENGTH));
+  if(isnan(_Acos) == 1)
+    return 0x00;;
+  *(out + 3) = _Acos;
+
+  // Get Ankle Roll
+  Tda = Tad;
+  if(matrix3d_inverse(&Tda,&Tda) == 0x00)
+    return 0x00;
+  _k = sqrt(Tda.coef[7] * Tda.coef[7] + Tda.coef[11] * Tda.coef[11]);
+  _l = sqrt(Tda.coef[7] * Tda.coef[7] + (Tda.coef[11] - DARWIN_ANKLE_LENGTH) * (Tda.coef[11] - DARWIN_ANKLE_LENGTH));
+  _m = (_k * _k - _l * _l - DARWIN_ANKLE_LENGTH * DARWIN_ANKLE_LENGTH) / (2 * _l * DARWIN_ANKLE_LENGTH);
+  if(_m > 1.0)
+    _m = 1.0;
+  else if(_m < -1.0)
+    _m = -1.0;
+  _Acos = acos(_m);
+  if(isnan(_Acos) == 1)
+    return 0x00;
+  if(Tda.coef[7] < 0.0)
+    *(out + 5) = -_Acos;
+  else
+    *(out + 5) = _Acos;
+  // Get Hip Yaw
+  vector3d_load(&orientation,*(out + 5) * 180.0 / PI, 0, 0);
+  point3d_load(&position,0, 0, -DARWIN_ANKLE_LENGTH);
+  matrix3d_set_transform(&Tcd,&position,&orientation);
+  Tdc = Tcd;
+  if(matrix3d_inverse(&Tdc,&Tdc) == 0x00)
+    return 0x00;
+  matrix3d_mult(&Tac,&Tad,&Tdc);
+  _Atan = atan2(-Tac.coef[1] , Tac.coef[5]);
+  if(isinf(_Atan) == 1)
+    return 0x00;
+  *(out) = _Atan;
+
+  // Get Hip Roll
+  _Atan = atan2(Tac.coef[9], -Tac.coef[1] * sin(*(out)) + Tac.coef[5] * cos(*(out)));
+  if(isinf(_Atan) == 1)
+    return 0x00;
+  *(out + 1) = _Atan;
+
+  // Get Hip Pitch and Ankle Pitch
+  _Atan = atan2(Tac.coef[2] * cos(*(out)) + Tac.coef[6] * sin(*(out)), Tac.coef[0] * cos(*(out)) + Tac.coef[4] * sin(*(out)));
+  if(isinf(_Atan) == 1)
+    return 0x00;
+  _theta = _Atan;
+  _k = sin(*(out + 3)) * DARWIN_CALF_LENGTH;
+  _l = -DARWIN_THIGH_LENGTH - cos(*(out + 3)) * DARWIN_CALF_LENGTH;
+  _m = cos(*(out)) * vec.x + sin(*(out)) * vec.y;
+  _n = cos(*(out + 1)) * vec.z + sin(*(out)) * sin(*(out + 1)) * vec.x - cos(*(out)) * sin(*(out + 1)) * vec.y;
+  _s = (_k * _n + _l * _m) / (_k * _k + _l * _l);
+  _c = (_n - _k * _s) / _l;
+  _Atan = atan2(_s, _c);
+  if(isinf(_Atan) == 1)
+    return 0x00;
+  *(out + 2) = _Atan;
+  *(out + 4) = _theta - *(out + 3) - *(out + 2);
+
+  return 0x01;
+}
diff --git a/src/darwin_math.c b/src/darwin_math.c
new file mode 100755
index 0000000000000000000000000000000000000000..e76646357603c96cf91e2dc5994c9fea00f1971d
--- /dev/null
+++ b/src/darwin_math.c
@@ -0,0 +1,237 @@
+#include "darwin_math.h"
+#include <math.h>
+
+// point functions
+void point3d_init(TPoint3D *point)
+{
+  point->x=0.0;
+  point->y=0.0;
+  point->z=0.0;
+}
+
+void point3d_load(TPoint3D *point, float x, float y,float z)
+{
+  point->x=x;
+  point->y=y;
+  point->z=z;  
+}
+
+void point3d_copy(TPoint3D *point_dst, TPoint3D *point_src)
+{
+  point_dst->x=point_src->x;
+  point_dst->y=point_src->y;
+  point_dst->z=point_src->z;
+}
+
+// vector functions
+void vector3d_init(TVector3D *vector)
+{
+  vector->x=0.0;
+  vector->y=0.0;
+  vector->z=0.0;
+}
+
+void vector3d_load(TVector3D *vector, float x, float y, float z)
+{
+  vector->x=x;
+  vector->y=y;
+  vector->z=z;
+}
+
+void vector3d_copy(TVector3D *vector_dst, TVector3D *vector_src)
+{
+  vector_dst->x=vector_src->x;
+  vector_dst->y=vector_src->y;
+  vector_dst->z=vector_src->z;
+}
+
+float vector3d_length(TVector3D *vector)
+{
+  return sqrt(vector->x*vector->x + vector->y*vector->y + vector->z*vector->z); 
+}
+
+// matrix functions
+void matrix3d_init(TMatrix3D *matrix)
+{
+   matrix3d_identity(matrix);
+}
+
+void matrix3d_copy(TMatrix3D *matrix_dst, TMatrix3D *matrix_src)
+{
+  matrix_dst->coef[m00]=matrix_src->coef[m00];
+  matrix_dst->coef[m01]=matrix_src->coef[m01];
+  matrix_dst->coef[m02]=matrix_src->coef[m02];
+  matrix_dst->coef[m03]=matrix_src->coef[m03];
+  matrix_dst->coef[m10]=matrix_src->coef[m10];
+  matrix_dst->coef[m11]=matrix_src->coef[m11];
+  matrix_dst->coef[m12]=matrix_src->coef[m12];
+  matrix_dst->coef[m13]=matrix_src->coef[m13];
+  matrix_dst->coef[m20]=matrix_src->coef[m20];
+  matrix_dst->coef[m21]=matrix_src->coef[m21];
+  matrix_dst->coef[m22]=matrix_src->coef[m22];
+  matrix_dst->coef[m23]=matrix_src->coef[m23];
+  matrix_dst->coef[m30]=matrix_src->coef[m30];
+  matrix_dst->coef[m31]=matrix_src->coef[m31];
+  matrix_dst->coef[m32]=matrix_src->coef[m32];
+  matrix_dst->coef[m33]=matrix_src->coef[m33];
+}
+
+void matrix3d_zero(TMatrix3D *matrix)
+{
+  matrix->coef[m00]=0.0;
+  matrix->coef[m01]=0.0;
+  matrix->coef[m02]=0.0;
+  matrix->coef[m03]=0.0;
+  matrix->coef[m10]=0.0;
+  matrix->coef[m11]=0.0;
+  matrix->coef[m12]=0.0;
+  matrix->coef[m13]=0.0;
+  matrix->coef[m20]=0.0;
+  matrix->coef[m21]=0.0;
+  matrix->coef[m22]=0.0;
+  matrix->coef[m23]=0.0;
+  matrix->coef[m30]=0.0;
+  matrix->coef[m31]=0.0;
+  matrix->coef[m32]=0.0;
+  matrix->coef[m33]=0.0;
+}
+
+void matrix3d_identity(TMatrix3D *matrix)
+{
+  matrix->coef[m00]=1.0;
+  matrix->coef[m01]=0.0;
+  matrix->coef[m02]=0.0;
+  matrix->coef[m03]=0.0;
+  matrix->coef[m10]=0.0;
+  matrix->coef[m11]=1.0;
+  matrix->coef[m12]=0.0;
+  matrix->coef[m13]=0.0;
+  matrix->coef[m20]=0.0;
+  matrix->coef[m21]=0.0;
+  matrix->coef[m22]=1.0;
+  matrix->coef[m23]=0.0;
+  matrix->coef[m30]=0.0;
+  matrix->coef[m31]=0.0;
+  matrix->coef[m32]=0.0;
+  matrix->coef[m33]=1.0;
+}
+
+uint8_t matrix3d_inverse(TMatrix3D *org, TMatrix3D *inv)
+{
+  TMatrix3D src, tmp;
+  float det;
+  uint8_t i;
+
+  /* transpose matrix */
+  for (i = 0; i < 4; i++)
+  {
+    src.coef[i] = org->coef[i*4];
+    src.coef[i + 4] = org->coef[i*4 + 1];
+    src.coef[i + 8] = org->coef[i*4 + 2];
+    src.coef[i + 12] = org->coef[i*4 + 3];
+  }
+
+  /* calculate pairs for first 8 elements (cofactors) */
+  tmp.coef[0] = src.coef[10] * src.coef[15];
+  tmp.coef[1] = src.coef[11] * src.coef[14];
+  tmp.coef[2] = src.coef[9] * src.coef[15];
+  tmp.coef[3] = src.coef[11] * src.coef[13];
+  tmp.coef[4] = src.coef[9] * src.coef[14];
+  tmp.coef[5] = src.coef[10] * src.coef[13];
+  tmp.coef[6] = src.coef[8] * src.coef[15];
+  tmp.coef[7] = src.coef[11] * src.coef[12];
+  tmp.coef[8] = src.coef[8] * src.coef[14];
+  tmp.coef[9] = src.coef[10] * src.coef[12];
+  tmp.coef[10] = src.coef[8] * src.coef[13];
+  tmp.coef[11] = src.coef[9] * src.coef[12];
+  /* calculate first 8 elements (cofactors) */
+  inv->coef[0] = (tmp.coef[0]*src.coef[5] + tmp.coef[3]*src.coef[6] + tmp.coef[4]*src.coef[7]) - (tmp.coef[1]*src.coef[5] + tmp.coef[2]*src.coef[6] + tmp.coef[5]*src.coef[7]);
+  inv->coef[1] = (tmp.coef[1]*src.coef[4] + tmp.coef[6]*src.coef[6] + tmp.coef[9]*src.coef[7]) - (tmp.coef[0]*src.coef[4] + tmp.coef[7]*src.coef[6] + tmp.coef[8]*src.coef[7]);
+  inv->coef[2] = (tmp.coef[2]*src.coef[4] + tmp.coef[7]*src.coef[5] + tmp.coef[10]*src.coef[7]) - (tmp.coef[3]*src.coef[4] + tmp.coef[6]*src.coef[5] + tmp.coef[11]*src.coef[7]);
+  inv->coef[3] = (tmp.coef[5]*src.coef[4] + tmp.coef[8]*src.coef[5] + tmp.coef[11]*src.coef[6]) - (tmp.coef[4]*src.coef[4] + tmp.coef[9]*src.coef[5] + tmp.coef[10]*src.coef[6]);
+  inv->coef[4] = (tmp.coef[1]*src.coef[1] + tmp.coef[2]*src.coef[2] + tmp.coef[5]*src.coef[3]) - (tmp.coef[0]*src.coef[1] + tmp.coef[3]*src.coef[2] + tmp.coef[4]*src.coef[3]);
+  inv->coef[5] = (tmp.coef[0]*src.coef[0] + tmp.coef[7]*src.coef[2] + tmp.coef[8]*src.coef[3]) - (tmp.coef[1]*src.coef[0] + tmp.coef[6]*src.coef[2] + tmp.coef[9]*src.coef[3]);
+  inv->coef[6] = (tmp.coef[3]*src.coef[0] + tmp.coef[6]*src.coef[1] + tmp.coef[11]*src.coef[3]) - (tmp.coef[2]*src.coef[0] + tmp.coef[7]*src.coef[1] + tmp.coef[10]*src.coef[3]);
+  inv->coef[7] = (tmp.coef[4]*src.coef[0] + tmp.coef[9]*src.coef[1] + tmp.coef[10]*src.coef[2]) - (tmp.coef[5]*src.coef[0] + tmp.coef[8]*src.coef[1] + tmp.coef[11]*src.coef[2]);
+  /* calculate pairs for second 8 elements (cofactors) */
+  tmp.coef[0] = src.coef[2]*src.coef[7];
+  tmp.coef[1] = src.coef[3]*src.coef[6];
+  tmp.coef[2] = src.coef[1]*src.coef[7];
+  tmp.coef[3] = src.coef[3]*src.coef[5];
+  tmp.coef[4] = src.coef[1]*src.coef[6];
+  tmp.coef[5] = src.coef[2]*src.coef[5];
+  //Streaming SIMD Extensions - Inverse of 4x4 Matrix 8
+  tmp.coef[6] = src.coef[0]*src.coef[7];
+  tmp.coef[7] = src.coef[3]*src.coef[4];
+  tmp.coef[8] = src.coef[0]*src.coef[6];
+  tmp.coef[9] = src.coef[2]*src.coef[4];
+  tmp.coef[10] = src.coef[0]*src.coef[5];
+  tmp.coef[11] = src.coef[1]*src.coef[4];
+  /* calculate second 8 elements (cofactors) */
+  inv->coef[8] = (tmp.coef[0]*src.coef[13] + tmp.coef[3]*src.coef[14] + tmp.coef[4]*src.coef[15]) - (tmp.coef[1]*src.coef[13] + tmp.coef[2]*src.coef[14] + tmp.coef[5]*src.coef[15]);
+  inv->coef[9] = (tmp.coef[1]*src.coef[12] + tmp.coef[6]*src.coef[14] + tmp.coef[9]*src.coef[15]) - (tmp.coef[0]*src.coef[12] + tmp.coef[7]*src.coef[14] + tmp.coef[8]*src.coef[15]);
+  inv->coef[10] = (tmp.coef[2]*src.coef[12] + tmp.coef[7]*src.coef[13] + tmp.coef[10]*src.coef[15]) - (tmp.coef[3]*src.coef[12] + tmp.coef[6]*src.coef[13] + tmp.coef[11]*src.coef[15]);
+  inv->coef[11] = (tmp.coef[5]*src.coef[12] + tmp.coef[8]*src.coef[13] + tmp.coef[11]*src.coef[14]) - (tmp.coef[4]*src.coef[12] + tmp.coef[9]*src.coef[13] + tmp.coef[10]*src.coef[14]);
+  inv->coef[12] = (tmp.coef[2]*src.coef[10] + tmp.coef[5]*src.coef[11] + tmp.coef[1]*src.coef[9]) - (tmp.coef[4]*src.coef[11] + tmp.coef[0]*src.coef[9] + tmp.coef[3]*src.coef[10]);
+  inv->coef[13] = (tmp.coef[8]*src.coef[11] + tmp.coef[0]*src.coef[8] + tmp.coef[7]*src.coef[10]) - (tmp.coef[6]*src.coef[10] + tmp.coef[9]*src.coef[11] + tmp.coef[1]*src.coef[8]);
+  inv->coef[14] = (tmp.coef[6]*src.coef[9] + tmp.coef[11]*src.coef[11] + tmp.coef[3]*src.coef[8]) - (tmp.coef[10]*src.coef[11] + tmp.coef[2]*src.coef[8] + tmp.coef[7]*src.coef[9]);
+  inv->coef[15] = (tmp.coef[10]*src.coef[10] + tmp.coef[4]*src.coef[8] + tmp.coef[9]*src.coef[9]) - (tmp.coef[8]*src.coef[9] + tmp.coef[11]*src.coef[10] + tmp.coef[5]*src.coef[8]);
+  /* calculate determinant */
+  det = src.coef[0]*inv->coef[0] + src.coef[1]*inv->coef[1] + src.coef[2]*inv->coef[2] + src.coef[3]*inv->coef[3];
+  /* calculate matrix inverse */
+  if (det == 0)
+  {
+    det = 0;
+    return 0x00;
+  }
+  else
+  {
+    det = 1 / det;
+  }
+
+  for (i = 0; i < 16; i++)
+    inv->coef[i]*=det;
+
+  return 0x01;
+}
+
+void matrix3d_set_transform(TMatrix3D *matrix, TPoint3D *point, TVector3D *vector)
+{
+  float Cx = cos(vector->x * 3.141592 / 180.0);
+  float Cy = cos(vector->y * 3.141592 / 180.0);
+  float Cz = cos(vector->z * 3.141592 / 180.0);
+  float Sx = sin(vector->x * 3.141592 / 180.0);
+  float Sy = sin(vector->y * 3.141592 / 180.0);
+  float Sz = sin(vector->z * 3.141592 / 180.0);
+
+  matrix3d_identity(matrix);
+  matrix->coef[0] = Cz * Cy;
+  matrix->coef[1] = Cz * Sy * Sx - Sz * Cx;
+  matrix->coef[2] = Cz * Sy * Cx + Sz * Sx;
+  matrix->coef[3] = point->x;
+  matrix->coef[4] = Sz * Cy;
+  matrix->coef[5] = Sz * Sy * Sx + Cz * Cx;
+  matrix->coef[6] = Sz * Sy * Cx - Cz * Sx;
+  matrix->coef[7] = point->y;
+  matrix->coef[8] = -Sy;
+  matrix->coef[9] = Cy * Sx;
+  matrix->coef[10] = Cy * Cx;
+  matrix->coef[11] = point->z;
+}
+
+void matrix3d_mult(TMatrix3D *dst,TMatrix3D *a,TMatrix3D *b)
+{
+  uint8_t i,j,c;
+
+  matrix3d_zero(dst);
+  for(j = 0; j < 4; j++)
+  {
+    for(i = 0; i < 4; i++)
+    {
+      for(c = 0; c < 4; c++)
+      {
+         dst->coef[j*4+i] += a->coef[j*4+c] * b->coef[c*4+i];
+      }
+    }
+  }
+}