diff --git a/CMakeLists.txt b/CMakeLists.txt
index 52d36559fc41ccba74e5d9dca7a7e82bb9ae09de..9393ca70c6604a5b4fa86c66554cbbf0d710063b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -134,6 +134,7 @@ SET(${PROJECT_NAME}_MULTIBODY_HEADERS
   )
 
 SET(${PROJECT_NAME}_ALGORITHM_HEADERS
+  algorithm/aba.hpp
   algorithm/rnea.hpp
   algorithm/crba.hpp
   algorithm/jacobian.hpp
diff --git a/src/algorithm/aba.hpp b/src/algorithm/aba.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..12e9c8869d5b6f84b1b19e86172e550016905d78
--- /dev/null
+++ b/src/algorithm/aba.hpp
@@ -0,0 +1,243 @@
+//
+// Copyright (c) 2015 CNRS
+//
+// This file is part of Pinocchio
+// Pinocchio is free software: you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation, either version
+// 3 of the License, or (at your option) any later version.
+//
+// Pinocchio is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Lesser Public License for more details. You should have
+// received a copy of the GNU Lesser General Public License along with
+// Pinocchio If not, see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef __se3_aba_hpp__
+#define __se3_aba_hpp__
+
+#include "pinocchio/multibody/visitor.hpp"
+#include "pinocchio/multibody/model.hpp"
+
+namespace se3
+{
+  inline const Eigen::VectorXd &
+  aba(const Model & model,
+      Data & data,
+      const Eigen::VectorXd & q,
+      const Eigen::VectorXd & v,
+      const Eigen::VectorXd & tau);
+
+} // namespace se3
+
+/* --- Details -------------------------------------------------------------------- */
+namespace se3
+{
+  struct AbaForwardStep1 : public fusion::JointVisitor<AbaForwardStep1>
+  {
+    typedef boost::fusion::vector<const se3::Model &,
+                                  se3::Data &,
+                                  const Model::Index,
+                                  const Eigen::VectorXd &,
+                                  const Eigen::VectorXd &
+                                  > ArgsType;
+
+    JOINT_VISITOR_INIT(AbaForwardStep1);
+
+    template<typename JointModel>
+    static void algo(const se3::JointModelBase<JointModel> & jmodel,
+                    se3::JointDataBase<typename JointModel::JointData> & jdata,
+                    const se3::Model & model,
+                    se3::Data & data,
+                    const Model::Index i,
+                    const Eigen::VectorXd & q,
+                    const Eigen::VectorXd & v)
+    {
+      using namespace Eigen;
+      using namespace se3;
+
+      jmodel.calc(jdata.derived(),q,v);
+
+      const Model::Index & parent = model.parents[i];
+      data.liMi[i] = model.jointPlacements[i] * jdata.M();
+
+      data.v[i] = jdata.v();
+
+      if (parent>0)
+      {
+        data.oMi[i] = data.oMi[parent] * data.liMi[i];
+        data.v[i] += data.liMi[i].actInv(data.v[parent]);
+      }
+      else
+        data.oMi[i] = data.liMi[i];
+
+      data.a[i] = jdata.c() + (data.v[i] ^ jdata.v());
+
+      data.Yaba[i] = model.inertias[i].matrix();
+      data.f[i] = model.inertias[i].vxiv(data.v[i]); // -f_ext
+    }
+
+  };
+
+  struct AbaBackwardStep : public fusion::JointVisitor<AbaBackwardStep>
+  {
+    typedef boost::fusion::vector<const Model &,
+    Data &,
+    const Model::Index>  ArgsType;
+
+    JOINT_VISITOR_INIT(AbaBackwardStep);
+
+    template<typename JointModel>
+    static void algo(const JointModelBase<JointModel> & jmodel,
+                     JointDataBase<typename JointModel::JointData> & jdata,
+                     const Model & model,
+                     Data & data,
+                     const Model::Index i)
+    {
+      const Model::Index & parent  = model.parents[i];
+      Inertia::Matrix6 & Ia = data.Yaba[i];
+
+      jmodel.jointVelocitySelector(data.u) -= jdata.S().transpose()*data.f[i];
+      jmodel.calc_aba(jdata.derived(), Ia, parent > 0);
+      jmodel.jointVelocitySelector(data.ddq) = jdata.Dinv() * jmodel.jointVelocitySelector(data.u);
+
+      if (parent > 0)
+      {
+        Force & pa = data.f[i];
+        pa.toVector() += Ia * data.a[i].toVector() + jdata.UDinv() * jmodel.jointVelocitySelector(data.u);
+        data.Yaba[parent] += SE3actOn(data.liMi[i], Ia);
+        data.f[parent] += data.liMi[i].act(pa);
+      }
+
+//      Data::Matrix6x & U = data.U_aba[i];
+//      Eigen::MatrixXd & D_inv = data.D_inv_aba[i];
+//
+////      const ConstraintXd::DenseBase S = ((ConstraintXd)jdata.S()).matrix();
+//
+//      U = data.Yaba[i] * ((ConstraintXd)jdata.S()).matrix();
+////      U = Data::Matrix6x::Zero(6, JointModelBase<JointModel>::NV);
+//      D_inv = (jdata.S().transpose() * U.block(0,0,U.rows(), U.cols())).inverse();
+////      D_inv = Eigen::MatrixXd::Zero(JointModelBase<JointModel>::NV, JointModelBase<JointModel>::NV);
+//      jmodel.jointVelocitySelector(data.tau) -= jdata.S().transpose()*data.f[i];
+//      if(parent>0)
+//      {
+//        Inertia::Matrix6 & Ia = data.Yaba[i];
+//        Force & pa = data.f[i];
+//
+//        Ia -= U * D_inv * U.transpose();
+//
+//        pa.toVector() += Ia * data.a[i].toVector() + U * D_inv * jmodel.jointVelocitySelector(data.tau);
+////        Inertia::Matrix6 tmp = data.liMi[i].inverse().toActionMatrix();
+////        data.Yaba[parent].triangularView<Eigen::Upper>() += tmp.transpose() * Ia.selfadjointView<Eigen::Upper>() * tmp;
+//        data.Yaba[parent] += SE3actOn(data.liMi[i], Ia);
+//        data.f[parent] += data.liMi[i].act(pa);
+//      }
+    }
+
+    inline static Inertia::Matrix6 SE3actOn(const SE3 & M, const Inertia::Matrix6 & I)
+    {
+      typedef Inertia::Matrix6 Matrix6;
+      typedef SE3::Matrix3 Matrix3;
+      typedef SE3::Vector3 Vector3;
+      typedef Eigen::Block<const Matrix6,3,3> constBlock3;
+      typedef Eigen::Block<Matrix6,3,3> Block3;
+
+      const constBlock3 & Ai = I.block<3,3> (Inertia::LINEAR, Inertia::LINEAR);
+      const constBlock3 & Bi = I.block<3,3> (Inertia::LINEAR, Inertia::ANGULAR);
+      const constBlock3 & Di = I.block<3,3> (Inertia::ANGULAR, Inertia::ANGULAR);
+
+      const Matrix3 & R = M.rotation();
+      const Vector3 & t = M.translation();
+
+      Matrix6 res;
+      Block3 Ao = res.block<3,3> (Inertia::LINEAR, Inertia::LINEAR);
+      Block3 Bo = res.block<3,3> (Inertia::LINEAR, Inertia::ANGULAR);
+      Block3 Co = res.block<3,3> (Inertia::ANGULAR, Inertia::LINEAR);
+      Block3 Do = res.block<3,3> (Inertia::ANGULAR, Inertia::ANGULAR);
+
+      Ao = R*Ai*R.transpose();
+      Bo = R*Bi*R.transpose();
+      Do.row(0) = t.cross(Bo.col(0));
+      Do.row(1) = t.cross(Bo.col(1));
+      Do.row(2) = t.cross(Bo.col(2));
+
+      Co.col(0) = t.cross(Ao.col(0));
+      Co.col(1) = t.cross(Ao.col(1));
+      Co.col(2) = t.cross(Ao.col(2));
+      Co += Bo.transpose();
+
+      Bo = Co.transpose();
+      Do.col(0) += t.cross(Bo.col(0));
+      Do.col(1) += t.cross(Bo.col(1));
+      Do.col(2) += t.cross(Bo.col(2));
+      Do += R*Di*R.transpose();
+      return res;
+    }
+  };
+
+  struct AbaForwardStep2 : public fusion::JointVisitor<AbaForwardStep2>
+  {
+    typedef boost::fusion::vector<const se3::Model &,
+    se3::Data &,
+    const Model::Index
+    > ArgsType;
+
+    JOINT_VISITOR_INIT(AbaForwardStep2);
+
+    template<typename JointModel>
+    static void algo(const se3::JointModelBase<JointModel> & jmodel,
+                    se3::JointDataBase<typename JointModel::JointData> & jdata,
+                    const se3::Model & model,
+                    se3::Data & data,
+                    const Model::Index i)
+    {
+      using namespace Eigen;
+      using namespace se3;
+
+      const Model::Index & parent = model.parents[i];
+
+      data.a[i] += data.liMi[i].actInv(data.a[parent]);
+      jmodel.jointVelocitySelector(data.ddq) -= jdata.UDinv().transpose() * data.a[i].toVector();
+
+      data.a[i] += jdata.S() * jmodel.jointVelocitySelector(data.ddq);
+    }
+
+  };
+
+  inline const Eigen::VectorXd &
+  aba(const Model & model,
+      Data & data,
+      const Eigen::VectorXd & q,
+      const Eigen::VectorXd & v,
+      const Eigen::VectorXd & tau)
+  {
+    data.v[0].setZero();
+    data.a[0] = -model.gravity;
+    data.u = tau;
+
+    for(Model::Index i=1;i<(Model::Index)model.nbody;++i)
+    {
+      AbaForwardStep1::run(model.joints[i],data.joints[i],
+                           AbaForwardStep1::ArgsType(model,data,i,q,v));
+    }
+
+    for( Model::Index i=(Model::Index)model.nbody-1;i>0;--i )
+    {
+      AbaBackwardStep::run(model.joints[i],data.joints[i],
+                           AbaBackwardStep::ArgsType(model,data,i));
+
+    }
+
+    for(Model::Index i=1;i<(Model::Index)model.nbody;++i)
+    {
+      AbaForwardStep2::run(model.joints[i],data.joints[i],
+                           AbaForwardStep2::ArgsType(model,data,i));
+    }
+
+    return data.ddq;
+  }
+} // namespace se3
+
+#endif // ifndef __se3_aba_hpp__
diff --git a/src/multibody/model.hpp b/src/multibody/model.hpp
index b6638903fd12e3a8ee2549ece75c4b867b249aa2..a0c6a8db72cc261849d910a339b3195c0d612691 100644
--- a/src/multibody/model.hpp
+++ b/src/multibody/model.hpp
@@ -159,6 +159,7 @@ namespace se3
     
     /// \brief Vector of absolute joint placements (wrt the world).
     std::vector<SE3> oMi;
+
     /// \brief Vector of relative joint placements (wrt the body parent).
     std::vector<SE3> liMi;
     
@@ -178,6 +179,16 @@ namespace se3
     
     /// \brief The joint space inertia matrix (a square matrix of dim model.nv).
     Eigen::MatrixXd M;
+    
+    /// \brief The joint accelerations computed from ABA
+    Eigen::VectorXd ddq;
+    
+    // ABA internal data
+    /// \brief Inertia matrix of the subtree expressed as dense matrix [ABA]
+    std::vector<Inertia::Matrix6> Yaba;
+    
+    /// \brief Intermediate quantity corresponding to apparent torque [ABA]
+    Eigen::VectorXd u;
 
     std::vector<Matrix6x> Fcrb;           // Spatial forces set, used in CRBA
 
diff --git a/src/multibody/model.hxx b/src/multibody/model.hxx
index 904caceb1e850b17f163794fc1ede546cc078221..c00afe20ad8909b822c3b4b53e71d3b6ac7ad0e0 100644
--- a/src/multibody/model.hxx
+++ b/src/multibody/model.hxx
@@ -256,6 +256,9 @@ namespace se3
     ,oMof((std::size_t)ref.nOperationalFrames)
     ,Ycrb((std::size_t)ref.nbody)
     ,M(ref.nv,ref.nv)
+    ,ddq(ref.nv)
+    ,Yaba((std::size_t)ref.nbody)
+    ,u(ref.nv)
     ,Fcrb((std::size_t)ref.nbody)
     ,lastChild((std::size_t)ref.nbody)
     ,nvSubtree((std::size_t)ref.nbody)