diff --git a/.gitignore b/.gitignore
index 491eaf4280c8a721323b763e5d548507ad8cf9d4..8339c71a25aa5d350133714045b58fe709b39702 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
 bin/
 lib/
 build/
+build-rel/
 
 # temp files
 .*~
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 571175132aa2995b6cceecfcf5ea6ee9a0ade444..fd0e02cbcfc8f248a5653356332ca5511b9ef226 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,12 +1,41 @@
 cmake_minimum_required(VERSION 2.6)
 project(spline)
+INCLUDE(cmake/base.cmake)
+INCLUDE(cmake/python.cmake)
 
+SET(PROJECT_NAME spline)
+SET(PROJECT_DESCRIPTION
+	 "template based classes for creating and manipulating spline and bezier curves. Comes with extra options specific to end-effector trajectories in robotics."
+ )
+SET(PROJECT_URL "")
 
 set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/build/")
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/bin/")
+set(LIBRARY_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib/")
+# Disable -Werror on Unix for now.
+SET(CXX_DISABLE_WERROR True)
+SET(CMAKE_VERBOSE_MAKEFILE True)
 
 find_package(Eigen3 REQUIRED)
 include_directories(${EIGEN3_INCLUDE_DIR})
 
+SETUP_PROJECT()
+
+OPTION (BUILD_PYTHON_INTERFACE "Build the python binding" ON)
+IF(BUILD_PYTHON_INTERFACE)
+# search for python
+	FINDPYTHON(2.7 REQUIRED)
+	find_package( PythonLibs 2.7 REQUIRED )
+	include_directories( ${PYTHON_INCLUDE_DIRS} )
+
+	find_package( Boost COMPONENTS python REQUIRED )
+	include_directories( ${Boost_INCLUDE_DIR} )
+
+	add_subdirectory (python)
+
+ENDIF(BUILD_PYTHON_INTERFACE)
+
 add_subdirectory (src/tests/spline_test)
 
+
+SETUP_PROJECT_FINALIZE()
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..51dde9504ca3c4e6b35873cc2523784418eefe29
--- /dev/null
+++ b/python/CMakeLists.txt
@@ -0,0 +1,24 @@
+cmake_minimum_required( VERSION 2.8 )
+
+include_directories("${EIGEN3_INCLUDE_DIR}")
+
+ADD_REQUIRED_DEPENDENCY("eigenpy")
+
+include_directories("${PROJECT_SOURCE_DIR}/include")
+FILE(GLOB_RECURSE HeaderFiles "${PROJECT_SOURCE_DIR}/include/spline/*.h")
+
+# Define the wrapper library that wraps our library
+add_library( spline SHARED spline_python.cpp )
+#~ target_link_libraries( centroidal_dynamics ${Boost_LIBRARIES} ${PROJECT_NAME} )
+# don't prepend wrapper library name with lib
+set_target_properties( spline PROPERTIES PREFIX "" )
+
+IF(APPLE)
+	# We need to change the extension for python bindings
+	SET_TARGET_PROPERTIES(spline PROPERTIES SUFFIX ".so")
+ENDIF(APPLE)
+PKG_CONFIG_USE_DEPENDENCY(spline eigenpy)
+
+INSTALL(
+	FILES ${LIBRARY_OUTPUT_PATH}spline.so	DESTINATION ${PYTHON_SITELIB}
+)
diff --git a/python/spline_python.cpp b/python/spline_python.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7338e8da9ccdae97493f766bbb160379343dee0c
--- /dev/null
+++ b/python/spline_python.cpp
@@ -0,0 +1,119 @@
+#include "spline/bezier_curve.h"
+
+#include <vector>
+
+#include <eigenpy/memory.hpp>
+#include <eigenpy/eigenpy.hpp>
+
+#include <boost/python.hpp>
+
+/*** TEMPLATE SPECIALIZATION FOR PYTHON ****/
+typedef double real;
+typedef Eigen::Vector3d point_t;
+typedef Eigen::Matrix<real, Eigen::Dynamic,3> point_list_t;
+typedef std::vector<point_t,Eigen::aligned_allocator<point_t> >  t_point_t;
+typedef std::pair<real, point_t> Waypoint;
+typedef std::vector<Waypoint> T_Waypoint;
+
+typedef spline::bezier_curve  <real, real, 3, true, point_t> bezier_t;
+/*** TEMPLATE SPECIALIZATION FOR PYTHON ****/
+
+EIGENPY_DEFINE_STRUCT_ALLOCATOR_SPECIALIZATION(bezier_t)
+
+namespace spline
+{
+using namespace boost::python;
+
+t_point_t vectorFromEigenArray(const point_list_t& array)
+{
+    t_point_t res;
+    for(int i =0;i<array.rows();++i)
+        res.push_back(array.row(i));
+    return res;
+}
+
+bezier_t* wrapBezierConstructor(const point_list_t& array)
+{
+    t_point_t asVector = vectorFromEigenArray(array);
+    return new bezier_t(asVector.begin(), asVector.end());
+}
+
+
+bezier_t* wrapBezierConstructorBounds(const point_list_t& array, const real lb, const real ub)
+{
+    t_point_t asVector = vectorFromEigenArray(array);
+    return new bezier_t(asVector.begin(), asVector.end(), lb, ub);
+}
+
+BOOST_PYTHON_MODULE(spline)
+{
+    /** BEGIN eigenpy init**/
+    eigenpy::enableEigenPy();
+
+    eigenpy::enableEigenPySpecific<point_t,point_t>();
+    eigenpy::enableEigenPySpecific<point_list_t,point_list_t>();
+    /*eigenpy::exposeAngleAxis();
+    eigenpy::exposeQuaternion();*/
+
+
+    class_<bezier_t>
+        ("bezier", no_init)
+            .def("__init__", make_constructor(&wrapBezierConstructor))
+            .def("__init__", make_constructor(&wrapBezierConstructorBounds))
+            .def("min", &bezier_t::min)
+            .def("max", &bezier_t::max)
+            .def("__call__", &bezier_t::operator())
+        ;
+
+
+    /** END eigenpy init**/
+
+    /** BEGIN enum types **/
+  /*#ifdef CLP_FOUND
+    enum_<SolverLP>("SolverLP")
+            .value("SOLVER_LP_QPOASES", SOLVER_LP_QPOASES)
+            .value("SOLVER_LP_CLP", SOLVER_LP_CLP)
+            .export_values();
+  #else
+    enum_<SolverLP>("SolverLP")
+            .value("SOLVER_LP_QPOASES", SOLVER_LP_QPOASES)
+            .export_values();
+  #endif
+
+
+    enum_<EquilibriumAlgorithm>("EquilibriumAlgorithm")
+            .value("EQUILIBRIUM_ALGORITHM_LP", EQUILIBRIUM_ALGORITHM_LP)
+            .value("EQUILIBRIUM_ALGORITHM_LP2", EQUILIBRIUM_ALGORITHM_LP2)
+            .value("EQUILIBRIUM_ALGORITHM_DLP", EQUILIBRIUM_ALGORITHM_DLP)
+            .value("EQUILIBRIUM_ALGORITHM_PP", EQUILIBRIUM_ALGORITHM_PP)
+            .value("EQUILIBRIUM_ALGORITHM_IP", EQUILIBRIUM_ALGORITHM_IP)
+            .value("EQUILIBRIUM_ALGORITHM_DIP", EQUILIBRIUM_ALGORITHM_DIP)
+            .export_values();
+
+    enum_<LP_status>("LP_status")
+            .value("LP_STATUS_UNKNOWN", LP_STATUS_UNKNOWN)
+            .value("LP_STATUS_OPTIMAL", LP_STATUS_OPTIMAL)
+            .value("LP_STATUS_INFEASIBLE", LP_STATUS_INFEASIBLE)
+            .value("LP_STATUS_UNBOUNDED", LP_STATUS_UNBOUNDED)
+            .value("LP_STATUS_MAX_ITER_REACHED", LP_STATUS_MAX_ITER_REACHED)
+            .value("LP_STATUS_ERROR", LP_STATUS_ERROR)
+            .export_values();*/
+
+    /** END enum types **/
+
+    /*bool (Equilibrium::*setNewContacts)
+            (const MatrixX3ColMajor&, const MatrixX3ColMajor&, const double, const EquilibriumAlgorithm) = &Equilibrium::setNewContacts;
+
+    class_<Equilibrium>("Equilibrium", init<std::string, double, unsigned int, optional <SolverLP, bool, const unsigned int, const bool> >())
+            .def("useWarmStart", &Equilibrium::useWarmStart)
+            .def("setUseWarmStart", &Equilibrium::setUseWarmStart)
+            .def("getName", &Equilibrium::getName)
+            .def("getAlgorithm", &Equilibrium::getAlgorithm)
+            .def("setNewContacts", setNewContacts)
+            .def("computeEquilibriumRobustness", wrapComputeQuasiEquilibriumRobustness)
+            .def("computeEquilibriumRobustness", wrapComputeEquilibriumRobustness)
+            .def("getPolytopeInequalities", wrapGetPolytopeInequalities)
+    ;*/
+}
+
+} // namespace spline
diff --git a/python/test/test.py b/python/test/test.py
new file mode 100644
index 0000000000000000000000000000000000000000..38e3766aac38ca1ff81a8e01ff4d97de0b509fa9
--- /dev/null
+++ b/python/test/test.py
@@ -0,0 +1,6 @@
+from spline import bezier
+
+from numpy import matrix
+
+a = bezier(matrix([[1.,2.,3.],[4.,5.,6.]]))
+a = bezier(matrix([[1.,2.,3.],[4.,5.,6.]]), -1., 3.)