diff --git a/idl/hpp/corbaserver/rbprm/rbprmbuilder.idl b/idl/hpp/corbaserver/rbprm/rbprmbuilder.idl
index 23813b02a63d703fb4839391a2b313c412fe685c..7abb2138cf402134d876557d59962129b09db9d2 100644
--- a/idl/hpp/corbaserver/rbprm/rbprmbuilder.idl
+++ b/idl/hpp/corbaserver/rbprm/rbprmbuilder.idl
@@ -67,6 +67,32 @@ module hpp
              in string packageName, in string modelName,
              in string urdfSuffix, in string srdfSuffix)
       raises (Error);
+
+    /// Create a RbprmFullBody object
+    /// The device automatically has an anchor joint called "base_joint" as
+    /// root joint.
+    /// \param trunkRobotName the name of the robot trunk used for collision.
+    /// \param rootJointType type of root joint among "anchor", "freeflyer",
+    /// "planar",
+    /// \param packageName Name of the ROS package containing the model,
+    /// \param modelName Name of the package containing the model
+    /// \param urdfSuffix suffix for urdf file,
+    ///
+    /// The ros url are built as follows:
+    /// "package://${packageName}/urdf/${modelName}${urdfSuffix}.urdf"
+    /// "package://${packageName}/srdf/${modelName}${srdfSuffix}.srdf"
+    ///
+    void loadFullBodyRobot (in string trunkRobotName, in string rootJointType,
+             in string packageName, in string modelName,
+             in string urdfSuffix, in string srdfSuffix)
+      raises (Error);
+
+    /// Get Sample configuration
+    /// \return dofArray Array of degrees of freedom.
+    floatSeq getSampleConfig(in string sampleName, in unsigned short sampleId) raises (Error);
+
+    void addLimb(in string limb, in unsigned short samples, in double resolution) raises (Error);
+
   }; // interface Robot
   }; // module rbprm
   }; // module corbaserver
diff --git a/script/load2.py b/script/load2.py
deleted file mode 100644
index 4fb7bf8d1078c7c69373c00a5f35e8668ff99c65..0000000000000000000000000000000000000000
--- a/script/load2.py
+++ /dev/null
@@ -1,58 +0,0 @@
-from hpp.corbaserver.rbprm.rbprmbuilder import Builder
-from hpp.gepetto import Viewer
-
-rootJointType = 'freeflyer'
-packageName = 'hpp-rbprm-corba'
-meshPackageName = 'hpp-rbprm-corba'
-urdfName = 'box'
-urdfNameRom = 'box_rom'
-urdfSuffix = ""
-srdfSuffix = ""
-
-rbprmBuilder = Builder ()
-
-rbprmBuilder.loadModel(urdfName, urdfNameRom, rootJointType, meshPackageName, packageName, urdfSuffix, srdfSuffix)
-rbprmBuilder.setJointBounds ("base_joint_xyz", [0, 2, -2, 0, 0, 1.5])
-
-#~ from hpp.corbaserver.rbprm. import ProblemSolver
-from hpp.corbaserver.rbprm.problem_solver import ProblemSolver
-
-ps = ProblemSolver( rbprmBuilder )
-
-r = Viewer (ps)
-
-q_init = rbprmBuilder.getCurrentConfig ()
-q_goal = q_init [::]
-q_init [0:3] = [0, -0.5, 0.4]
-
-#~ rank = rbprmBuilder.rankInConfiguration ['torso_lift_joint']
-#~ q_init [rank] = 0.2
-r (q_init)
-
-q_goal [0:3] = [1, -0.5, 1]
-#~ q_goal [0:3] = [-3.2, 0, 3]
-#~ rank = rbprmBuilder.rankInConfiguration ['l_shoulder_lift_joint']
-#~ q_goal [rank] = 0.5
-#~ rank = rbprmBuilder.rankInConfiguration ['l_elbow_flex_joint']
-#~ q_goal [rank] = -0.5
-#~ rank = rbprmBuilder.rankInConfiguration ['r_shoulder_lift_joint']
-#~ q_goal [rank] = 0.5
-#~ rank = rbprmBuilder.rankInConfiguration ['r_elbow_flex_joint']
-#~ q_goal [rank] = -0.5
-r (q_goal)
-
-r.loadObstacleModel (packageName, "scene", "car")
-
-ps.setInitialConfig (q_init)
-ps.addGoalConfig (q_goal)
-
-ps.client.problem.selectConFigurationShooter("RbprmShooter")
-
-ps.solve ()
-
-
-from hpp.gepetto import PathPlayer
-pp = PathPlayer (rbprmBuilder.client.basic, r)
-
-pp (0)
-
diff --git a/script/loadfullbody.py b/script/loadfullbody.py
new file mode 100644
index 0000000000000000000000000000000000000000..2df2ed8a81c5dbfe20006b63eb3058b45703dcdb
--- /dev/null
+++ b/script/loadfullbody.py
@@ -0,0 +1,33 @@
+from hpp.corbaserver.rbprm.rbprmbuilder import Builder
+from hpp.gepetto import Viewer
+
+rootJointType = 'freeflyer'
+packageName = 'hpp-rbprm-corba'
+meshPackageName = 'hpp-rbprm-corba'
+urdfName = 'box'
+urdfNameRom = 'box_rom'
+urdfSuffix = ""
+srdfSuffix = ""
+
+rbprmBuilder = Builder ()
+
+rbprmBuilder.loadFullBodyModel(urdfName, urdfNameRom, rootJointType, meshPackageName, packageName, urdfSuffix, srdfSuffix)
+rbprmBuilder.setJointBounds ("base_joint_xyz", [0, 2, -2, 0, -1, 1.5])
+
+#~ from hpp.corbaserver.rbprm. import ProblemSolver
+from hpp.corbaserver.rbprm.problem_solver import ProblemSolver
+
+ps = ProblemSolver( rbprmBuilder )
+
+r = Viewer (ps)
+
+q_init = rbprmBuilder.getCurrentConfig ()
+q_goal = q_init [::]
+q_init [0:3] = [0, -0.5, 0.3]
+q_goal = [0, -0.5, -0.2, -0.501544,0.431183, 0.662926, -0.350804]
+r (q_goal)
+
+
+ps.setInitialConfig (q_init)
+ps.addGoalConfig (q_goal)
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 38f58e75f3df3f77dfaa92196b8a3e681568316c..9dfcbbbe5bc5c125f8f9c937c9d7688f8a1eba27 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -119,6 +119,7 @@ INSTALL(
   FILES
 	${CMAKE_CURRENT_SOURCE_DIR}/hpp/corbaserver/rbprm/client.py
 	${CMAKE_CURRENT_SOURCE_DIR}/hpp/corbaserver/rbprm/rbprmbuilder.py
+        ${CMAKE_CURRENT_SOURCE_DIR}/hpp/corbaserver/rbprm/rbprmfullbody.py
 	${CMAKE_CURRENT_SOURCE_DIR}/hpp/corbaserver/rbprm/problem_solver.py
   DESTINATION ${PYTHON_SITELIB}/hpp/corbaserver/rbprm
   )
diff --git a/src/hpp/corbaserver/rbprm/rbprmbuilder.py b/src/hpp/corbaserver/rbprm/rbprmbuilder.py
index 9a47066e71f9d20665b2cc706b95aa63a4e7409a..0370e8e753ae0c8300e1225a2bfc083217b6d312 100644
--- a/src/hpp/corbaserver/rbprm/rbprmbuilder.py
+++ b/src/hpp/corbaserver/rbprm/rbprmbuilder.py
@@ -72,6 +72,29 @@ class Builder (object):
 			rankInConfiguration += self.client.basic.robot.getJointConfigSize (j)
 			self.rankInVelocity [j] = rankInVelocity
 			rankInVelocity += self.client.basic.robot.getJointNumberDof (j)
+			
+	def loadFullBodyModel (self, urdfName, rootJointType, packageName, meshPackageName, urdfSuffix, srdfSuffix):
+		self.client.rbprm.rbprm.loadloadFullBodyRobot(urdfName, rootJointType, packageName, urdfNamerom, urdfSuffix, srdfSuffix)
+		self.name = urdfName
+		self.displayName = urdfName
+		self.tf_root = "base_link"
+		self.rootJointType = rootJointType
+		self.jointNames = self.client.basic.robot.getJointNames ()
+		self.allJointNames = self.client.basic.robot.getAllJointNames ()
+		self.client.basic.robot.meshPackageName = meshPackageName
+		self.meshPackageName = meshPackageName
+		self.rankInConfiguration = dict ()
+		self.rankInVelocity = dict ()
+		self.packageName = packageName
+		self.urdfName = urdfName
+		self.urdfSuffix = urdfSuffix
+		self.srdfSuffix = srdfSuffix
+		rankInConfiguration = rankInVelocity = 0
+		for j in self.jointNames:
+			self.rankInConfiguration [j] = rankInConfiguration
+			rankInConfiguration += self.client.basic.robot.getJointConfigSize (j)
+			self.rankInVelocity [j] = rankInVelocity
+			rankInVelocity += self.client.basic.robot.getJointNumberDof (j)
 
 	## Init RbprmShooter
     #
@@ -81,6 +104,8 @@ class Builder (object):
         return self.client.rbprm.rbprm.initshooter ()
     ## \}
 
+
+
    ## \name Degrees of freedom
     #  \{
 
diff --git a/src/hpp/corbaserver/rbprm/rbprmfullbody.py b/src/hpp/corbaserver/rbprm/rbprmfullbody.py
new file mode 100644
index 0000000000000000000000000000000000000000..3c2a821c905e8b557faaa4d59e2901005af3d30a
--- /dev/null
+++ b/src/hpp/corbaserver/rbprm/rbprmfullbody.py
@@ -0,0 +1,257 @@
+#!/usr/bin/env python
+# Copyright (c) 2014 CNRS
+# Author: Steve Tonneau
+#
+# This file is part of hpp-rbprm-corba.
+# hpp-rbprm-corba 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.
+#
+# hpp-manipulation-corba 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
+# hpp-manipulation-corba.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+from hpp.corbaserver.rbprm import Client as RbprmClient
+from hpp.corbaserver import Client as BasicClient
+
+## Corba clients to the various servers
+#
+class CorbaClient:
+    """
+    Container for corba clients to various interfaces.
+    """
+    def __init__ (self):
+        self.basic = BasicClient ()
+        self.rbprm = RbprmClient ()
+
+## Load and handle a RbprmDevice robot for rbprm planning
+#
+#  A RbprmDevice robot is a set of two robots. One for the 
+#  trunk of the robot, one for the range of motion
+class Builder (object):
+    ## Constructor
+    # \param trunkName name of the first robot that is loaded now,
+    # \param romName name of the first robot that is loaded now,
+    # \param rootJointType type of root joint among ("freeflyer", "planar",
+    #        "anchor"),
+    # \param load whether to actually load urdf files. Set to no if you only
+    #        want to initialize a corba client to an already initialized
+    #        problem.
+    def __init__ (self, load = True):
+        self.tf_root = "base_link"
+        self.rootJointType = dict()
+        self.client = CorbaClient ()
+        self.load = load
+			
+	def loadFullBodyModel (self, urdfName, rootJointType, packageName, meshPackageName, urdfSuffix, srdfSuffix):
+		self.client.rbprm.rbprm.loadloadFullBodyRobot(urdfName, rootJointType, packageName, urdfNamerom, urdfSuffix, srdfSuffix)
+		self.name = urdfName
+		self.displayName = urdfName
+		self.tf_root = "base_link"
+		self.rootJointType = rootJointType
+		self.jointNames = self.client.basic.robot.getJointNames ()
+		self.allJointNames = self.client.basic.robot.getAllJointNames ()
+		self.client.basic.robot.meshPackageName = meshPackageName
+		self.meshPackageName = meshPackageName
+		self.rankInConfiguration = dict ()
+		self.rankInVelocity = dict ()
+		self.packageName = packageName
+		self.urdfName = urdfName
+		self.urdfSuffix = urdfSuffix
+		self.srdfSuffix = srdfSuffix
+		rankInConfiguration = rankInVelocity = 0
+		for j in self.jointNames:
+			self.rankInConfiguration [j] = rankInConfiguration
+			rankInConfiguration += self.client.basic.robot.getJointConfigSize (j)
+			self.rankInVelocity [j] = rankInVelocity
+			rankInVelocity += self.client.basic.robot.getJointNumberDof (j)
+
+   ## \name Degrees of freedom
+    #  \{
+
+    ## Get size of configuration
+    # \return size of configuration
+    def getConfigSize (self):
+        return self.client.basic.robot.getConfigSize ()
+
+    # Get size of velocity
+    # \return size of velocity
+    def getNumberDof (self):
+        return self.client.basic.robot.getNumberDof ()
+    ## \}
+
+    ## \name Joints
+    #\{
+
+    ## Get joint names in the same order as in the configuration.
+    def getJointNames (self):
+        return self.client.basic.robot.getJointNames ()
+
+    ## Get joint names in the same order as in the configuration.
+    def getAllJointNames (self):
+        return self.client.basic.robot.getAllJointNames ()
+
+    ## Get joint position.
+    def getJointPosition (self, jointName):
+        return self.client.basic.robot.getJointPosition (jointName)
+
+    ## Set static position of joint in its parent frame
+    def setJointPosition (self, jointName, position):
+        return self.client.basic.robot.setJointPosition (jointName, position)
+
+    ## Get joint number degrees of freedom.
+    def getJointNumberDof (self, jointName):
+        return self.client.basic.robot.getJointNumberDof (jointName)
+
+    ## Get joint number config size.
+    def getJointConfigSize (self, jointName):
+        return self.client.basic.robot.getJointConfigSize (jointName)
+
+    ## set bounds for the joint
+    def setJointBounds (self, jointName, inJointBound):
+        return self.client.basic.robot.setJointBounds (jointName, inJointBound)
+
+    ## Set bounds on the translation part of the freeflyer joint.
+    #
+    #  Valid only if the robot has a freeflyer joint.
+    def setTranslationBounds (self, xmin, xmax, ymin, ymax, zmin, zmax):
+        self.client.basic.robot.setJointBounds \
+            (self.displayName + "base_joint_x", [xmin, xmax])
+        self.client.basic.robot.setJointBounds \
+            (self.displayName + "base_joint_y", [ymin, ymax])
+        self.client.basic.robot.setJointBounds \
+            (self.displayName + "base_joint_z", [zmin, zmax])
+
+    ## Get link position in joint frame
+    #
+    # Joints are oriented in a different way as in urdf standard since
+    # rotation and uni-dimensional translation joints act around or along
+    # their x-axis. This method returns the position of the urdf link in
+    # world frame.
+    #
+    # \param jointName name of the joint
+    # \return position of the link in world frame.
+    def getLinkPosition (self, jointName):
+        return self.client.basic.robot.getLinkPosition (jointName)
+
+    ## Get link name
+    #
+    # \param jointName name of the joint,
+    # \return name of the link.
+    def getLinkName (self, jointName):
+        return self.client.basic.robot.getLinkName (jointName)
+    ## \}
+
+    ## \name Access to current configuration
+    #\{
+
+    ## Set current configuration of composite robot
+    #
+    #  \param q configuration of the composite robot
+    def setCurrentConfig (self, q):
+        self.client.basic.robot.setCurrentConfig (q)
+
+    ## Get current configuration of composite robot
+    #
+    #  \return configuration of the composite robot
+    def getCurrentConfig (self):
+        return self.client.basic.robot.getCurrentConfig ()
+
+    ## Shoot random configuration
+    #  \return dofArray Array of degrees of freedom.
+    def shootRandomConfig(self):
+        return self.client.basic.robot.shootRandomConfig ()
+
+    ## \}
+
+    ## \name Bodies
+    #  \{
+
+    ##  Get the list of objects attached to a joint.
+    #  \param inJointName name of the joint.
+    #  \return list of names of CollisionObject attached to the body.
+    def getJointInnerObjects (self, jointName):
+        return self.client.basic.robot.getJointInnerObjects (jointName)
+
+
+    ##  Get list of collision objects tested with the body attached to a joint
+    #  \param inJointName name of the joint.
+    #  \return list of names of CollisionObject
+    def getJointOuterObjects (self, jointName):
+        return self.client.basic.robot.getJointOuterObjects (jointName)
+
+    ## Get position of robot object
+    #  \param objectName name of the object.
+    #  \return transformation as a hpp.Transform object
+    def getObjectPosition (self, objectName):
+        return Transform (self.client.basic.robot.getObjectPosition
+                          (objectName))
+
+    ## \brief Remove an obstacle from outer objects of a joint body
+    #
+    #  \param objectName name of the object to remove,
+    #  \param jointName name of the joint owning the body,
+    #  \param collision whether collision with object should be computed,
+    #  \param distance whether distance to object should be computed.
+    def removeObstacleFromJoint (self, objectName, jointName, collision,
+                                 distance):
+        return self.client.basic.obstacle.removeObstacleFromJoint \
+            (objectName, jointName, collision, distance)
+
+
+    ## \}
+
+    ## \name Collision checking and distance computation
+    # \{
+
+    ## Test collision with obstacles and auto-collision.
+    #
+    # Check whether current configuration of robot is valid by calling
+    # CkwsDevice::collisionTest ().
+    # \return whether configuration is valid
+    # \note Deprecated. Use isConfigValid instead.
+    def collisionTest (self):
+        print "Deprecated. Use isConfigValid instead"
+        return self.client.basic.robot.collisionTest ()
+
+    ## Check the validity of a configuration.
+    #
+    # Check whether a configuration of robot is valid.
+    # \param cfg a configuration
+    # \return whether configuration is valid
+    def isConfigValid (self, cfg):
+        return self.client.basic.robot.isConfigValid (cfg)
+
+    ## Compute distances between bodies and obstacles
+    #
+    # \return list of distances,
+    # \return names of the objects belonging to a body
+    # \return names of the objects tested with inner objects,
+    # \return  closest points on the body,
+    # \return  closest points on the obstacles
+    # \note outer objects for a body can also be inner objects of another
+    # body.
+    def distancesToCollision (self):
+        return self.client.basic.robot.distancesToCollision ()
+    ## \}
+
+    ## \}
+    ## \name Mass and inertia
+    # \{
+
+    ## Get mass of robot
+    def getMass (self):
+        return self.client.basic.robot.getMass ()
+
+    ## Get position of center of mass
+    def getCenterOfMass (self):
+        return self.client.basic.robot.getCenterOfMass ()
+    ## Get Jacobian of the center of mass
+    def getJacobianCenterOfMass (self):
+        return self.client.basic.robot.getJacobianCenterOfMass ()
+    ##\}
diff --git a/src/rbprmbuilder.impl.cc b/src/rbprmbuilder.impl.cc
index 734e16c4a61681e88bcd50e3cf8f8ad71ed45e1d..d6c1bebe16614cba76013f4f462294ce7a92c16c 100644
--- a/src/rbprmbuilder.impl.cc
+++ b/src/rbprmbuilder.impl.cc
@@ -34,6 +34,7 @@ namespace hpp {
     RbprmBuilder::RbprmBuilder ()
     : POA_hpp::corbaserver::rbprm::RbprmBuilder()
     , romLoaded_(false)
+    , fullBodyLoaded_(false)
     , bindShooter_()
     {
         // NOTHING
@@ -98,6 +99,76 @@ namespace hpp {
         }
     }
 
+    void RbprmBuilder::loadFullBodyRobot(const char* robotName,
+         const char* rootJointType,
+         const char* packageName,
+         const char* modelName,
+         const char* urdfSuffix,
+         const char* srdfSuffix) throw (hpp::Error)
+    {
+        try
+        {
+            model::DevicePtr_t device = model::Device::create (robotName);
+            hpp::model::urdf::loadRobotModel (romDevice_,
+                    std::string (rootJointType),
+                    std::string (packageName),
+                    std::string (modelName),
+                    std::string (urdfSuffix),
+                    std::string (srdfSuffix));
+            fullBody_ = rbprm::RbPrmFullBody::create(device);
+        }
+        catch (const std::exception& exc)
+        {
+            hppDout (error, exc.what ());
+            throw hpp::Error (exc.what ());
+        }
+        fullBodyLoaded_ = true;
+    }
+
+
+    hpp::floatSeq* RbprmBuilder::getSampleConfig(const char* limb, unsigned short sampleId) throw (hpp::Error)
+    {
+        if(!fullBodyLoaded_)
+            throw Error ("No full body robot was loaded");
+        const T_Limb& limbs = fullBody_->GetLimbs();
+        T_Limb::const_iterator lit = limbs.find(std::string(limb));
+        if(lit == limbs.end())
+        {
+            std::string err("No limb " + std::string(limb) + "was defined for robot" + fullBody_->device_->name());
+            throw Error (err.c_str());
+        }
+        const RbPrmLimbPtr_t& limbPtr = lit->second;
+        hpp::floatSeq *dofArray;
+        Eigen::VectorXd config = fullBody_->device_->currentConfiguration ();
+        if(sampleId > limbPtr->sampleContainer_.samples_.size())
+        {
+            std::string err("Limb " + std::string(limb) + "does not have samples.");
+            throw Error (err.c_str());
+        }
+        const sampling::Sample& sample = limbPtr->sampleContainer_.samples_[sampleId];
+        size_t ric = sample.startRank_;
+        config.tail(ric) = sample.configuration_;
+        dofArray = new hpp::floatSeq();
+        dofArray->length(_CORBA_ULong(config.rows()));
+        for(std::size_t i=0; i< _CORBA_ULong(config.rows()); i++)
+          (*dofArray)[(_CORBA_ULong)i] = config [i];
+        return dofArray;
+    }
+
+    void RbprmBuilder::addLimb(const char* limb, unsigned short samples, double resolution) throw (hpp::Error)
+    {
+        if(!fullBodyLoaded_)
+            throw Error ("No full body robot was loaded");
+        try
+        {
+            fullBody_->AddLimb(std::string(limb),samples,resolution);
+        }
+        catch(std::runtime_error& e)
+        {
+            throw Error(e.what());
+        }
+    }
+
     namespace
     {
         hpp::core::PathValidationPtr_t createPathValidation (const hpp::model::DevicePtr_t& robot, const hpp::model::value_type& val)
diff --git a/src/rbprmbuilder.impl.hh b/src/rbprmbuilder.impl.hh
index eedf7d1015ff34d453e58c4ac430312e3b3523f4..3b324399df953e63da44eab818d0c1153e083cc3 100644
--- a/src/rbprmbuilder.impl.hh
+++ b/src/rbprmbuilder.impl.hh
@@ -21,6 +21,7 @@
 # include <hpp/core/problem-solver.hh>
 # include "rbprmbuilder.hh"
 # include <hpp/rbprm/rbprm-device.hh>
+# include <hpp/rbprm/rbprm-fullbody.hh>
 # include <hpp/rbprm/rbprm-shooter.hh>
 # include <hpp/rbprm/rbprm-validation.hh>
 
@@ -66,6 +67,18 @@ namespace hpp {
                  const char* urdfSuffix,
                  const char* srdfSuffix) throw (hpp::Error);
 
+
+        virtual void loadFullBodyRobot (const char* robotName,
+                 const char* rootJointType,
+                 const char* packageName,
+                 const char* modelName,
+                 const char* urdfSuffix,
+                 const char* srdfSuffix) throw (hpp::Error);
+
+        virtual hpp::floatSeq* getSampleConfig(const char* limb, unsigned short sampleId) throw (hpp::Error);
+
+        virtual void addLimb(const char* limb, unsigned short samples, double resolution) throw (hpp::Error);
+
         public:
         void SetProblemSolver (hpp::core::ProblemSolverPtr_t problemSolver);
 
@@ -75,7 +88,9 @@ namespace hpp {
 
         private:
         model::DevicePtr_t romDevice_;
+        rbprm::RbPrmFullBodyPtr_t fullBody_;
         bool romLoaded_;
+        bool fullBodyLoaded_;
         BindShooter bindShooter_;
       }; // class RobotBuilder
     } // namespace impl