diff --git a/scripts/hpp_wholebody_motion/export/openHRP.py b/scripts/hpp_wholebody_motion/export/openHRP.py
index 5e98c7b3a8d912261a531e739cd3cd259a5024fe..716cd961ba9219e6fcbff1a76086147324f5aa25 100644
--- a/scripts/hpp_wholebody_motion/export/openHRP.py
+++ b/scripts/hpp_wholebody_motion/export/openHRP.py
@@ -10,10 +10,13 @@ import numpy as np
 from rospkg import RosPack
 #import tsid # required for robot wrapper ! FIXME
 from pinocchio.robot_wrapper import RobotWrapper
+from hpp_wholebody_motion.utils.computation_tools import *
 
 class Struct():
     None
     
+DT = 0.005
+    
 # hardcoded ID for HRP-2 : 
 ff = range(7)
 chest = range(7,9)
@@ -24,13 +27,29 @@ l_leg = range(25,31)
 r_leg = range(31,37)
 
 
-def computeResultTrajectory(robot, t_t, q_t, v_t, a_t):
-
+def computeResultTrajectory(robot,cs, q_t_list, v_t_list, a_t_list):
+    # start by adapting the time step between the IK and the the one of open hrp (0.005)
+    assert DT>= cfg.IK_dt and "The dt used when computing q(t) must be superior or equal to 0.005 for this export."
+    assert (DT % cfg.IK_dt)==0 and "The dt used when computing q(t) must be a multiple of 0.005."
+    n = int(DT/cfg.IK_dt)
+    N_ik = len(q_t_list)
+    N = N_ik/n
+    #print "Export openHRP, ratio between dt :  ",n
+    #print "Num point for IK : ",N_ik
+    #print "Num point for openHRP : ",N
+    q_t = np.matrix(np.zeros([q_t_list[0].shape[0],N]))
+    v_t = np.matrix(np.zeros([v_t_list[0].shape[0],N]))
+    a_t = np.matrix(np.zeros([a_t_list[0].shape[0],N]))
+    for i in range(N):
+        q_t[:,i] = q_t_list[i*n] 
+        v_t[:,i] = v_t_list[i*n]    
+        a_t[:,i] = a_t_list[i*n]       
+    # build timeline vector : 
+    t_t = [i*DT for i in range(q_t.shape[1])]
+    #print "timeline size : ",len(t_t)
     model = robot.model
     data = robot.data
 
-    N = q_t.shape[1]
-
     ZMP_t = np.matrix(np.zeros([3,N]))
     waist_t = np.matrix(np.zeros([3,N]))
     pcom_t = np.matrix(np.empty([3,N]))
@@ -78,14 +97,7 @@ def computeResultTrajectory(robot, t_t, q_t, v_t, a_t):
         #phi0 = oXi_s * (M[:6,:] * a + b[:6])
         tau_t[:,k] = data.tau
         phi0 = data.oMi[1].act(se3.Force(data.tau[:6]))
-
-        wrench_t[:,k] = phi0.vector
-
-        forces = wrench_t[:3,k]
-        torques = wrench_t[3:,k]
-
-        ZMP_t[0,k] = -torques[1]/forces[2]
-        ZMP_t[1,k] = torques[0]/forces[2]
+        ZMP_t[:,k] = shiftZMPtoFloorAltitude(cs,t_t[k],phi0)
 
         waist_t[:,k] = robot.data.oMi[1].translation
         waist_orientation_t[:,k] = matrixToRpy(robot.data.oMi[1].rotation)
@@ -164,11 +176,12 @@ def generateOpenHRPMotion(robot, data, path, project_name):
             line += delim + str(vector[k,0])
 
         return line
-
-    timeline = data.t_t - data.t_t[0]
+    
+    timeline = data.t_t
     N = len(timeline)
-    dt = 0.005
-    timeline = np.linspace(0., (N-1)*dt, N) 
+    print "in generateOpenHRPMotion, N= ",N
+    dt = DT
+ 
     delim = " "
     eol = "\n"
 
@@ -260,10 +273,10 @@ def writeKinematicsData(robot, data, path, project_name):
 
         return line
 
-    timeline = data.t_t - data.t_t[0]
+    timeline = data.t_t
     N = len(timeline)
-    dt = 0.005
-    timeline = np.linspace(0., (N-1)*dt, N) 
+    print "in write kinematic, number of points : ",N
+    dt = DT
     delim = " "
     eol = "\n"
 
@@ -309,10 +322,8 @@ def writeKinematicsData(robot, data, path, project_name):
     print "write file : ",filename_acc
 
 
-def export(q_t,v_t,a_t,t_t = None):
-    if not t_t :
-        t_t = [i*cfg.IK_dt for i in range(len(q_t))]
-    assert len(q_t) == len(v_t) and len(q_t) == len(a_t) and len(q_t) == len(t_t) and "all states vector must have the same size"
+def export(cs,q_t,v_t,a_t):
+    assert len(q_t) == len(v_t) and len(q_t) == len(a_t) and "all states vector must have the same size"
     rp = RosPack()
     urdf = rp.get_path(cfg.Robot.packageName)+'/urdf/'+cfg.Robot.urdfName+cfg.Robot.urdfSuffix+'.urdf'
     if cfg.WB_VERBOSE:
@@ -321,35 +332,9 @@ def export(q_t,v_t,a_t,t_t = None):
     robot = RobotWrapper(urdf, se3.StdVec_StdString(), se3.JointModelFreeFlyer(), False)
     if cfg.WB_VERBOSE:
         print "robot loaded in export OpenHRP"    
-    # convert list of states to matrices (line : value, col : id)
-    N = len(q_t)
-    q_t_mat = np.matrix(np.zeros([q_t[0].shape[0],N]))
-    v_t_mat = np.matrix(np.zeros([v_t[0].shape[0],N]))
-    a_t_mat = np.matrix(np.zeros([a_t[0].shape[0],N]))
-    t_t_mat = np.matrix(t_t)
-    for i in range(N):
-        q_t_mat[:,i] = q_t[i] 
-        v_t_mat[:,i] = v_t[i]    
-        a_t_mat[:,i] = a_t[i]    
-    
-    
-    results_sot = computeResultTrajectory(robot, t_t_mat, q_t_mat, v_t_mat, a_t_mat)
-    """
-    ZMP_t = results_sot.ZMP_t.copy()
-    pcom_t = results_sot.pcom_t
-    # Set zmp trajectory to be the reference one
-    Wrench_ref_trajectory = DifferentiableEuclidianTrajectory()
-    Wrench_ref_trajectory.computeFromPoints(trajs.time_t,F0_t,0*F0_t)
-
-    Wrench_trajectory = DifferentiableEuclidianTrajectory()
-    Wrench_trajectory.computeFromPoints(np.asmatrix(results_sot.t_t),results_sot.wrench_t,0*results_sot.wrench_t)
-
-    ZMP_ref_t = computeRefZMP(cs,results_sot.t_t,Wrench_ref_trajectory)
-    ZMP_t = computeRefZMP(cs,results_sot.t_t,Wrench_trajectory)
-    
-    results_sot.ZMP_t[:,:] = ZMP_t
-    """
+  
+    results = computeResultTrajectory(robot,cs, q_t, v_t, a_t)
     path = cfg.EXPORT_PATH+"/openHRP"
-    q_openhrp_l = generateOpenHRPMotion(robot, results_sot, path, cfg.DEMO_NAME)
-    writeKinematicsData(robot, results_sot, path, cfg.DEMO_NAME)
+    q_openhrp_l = generateOpenHRPMotion(robot, results, path, cfg.DEMO_NAME)
+    writeKinematicsData(robot, results, path, cfg.DEMO_NAME)
     
\ No newline at end of file
diff --git a/scripts/hpp_wholebody_motion/utils/computation_tools.py b/scripts/hpp_wholebody_motion/utils/computation_tools.py
new file mode 100644
index 0000000000000000000000000000000000000000..5d869b1bbe7251f2430951c37cbc5cfc11521544
--- /dev/null
+++ b/scripts/hpp_wholebody_motion/utils/computation_tools.py
@@ -0,0 +1,159 @@
+
+import numpy as np
+import pinocchio as se3
+from pinocchio import SE3, Motion,Force
+from hpp_wholebody_motion.utils.util import *
+import hpp_wholebody_motion.config as cfg
+### tools to compute zmp trajectory : ### 
+
+
+def pacthSameAltitude(M1,M2,eps=1e-3):
+    return abs(M1.translation[2] == M2.translation[2]) <= eps
+
+# compute an approximation of the floor altitude (used for the zmp reference)
+#Only consider the feet : 
+# - if only one feet in contact, return it's z coordinate
+# - if both feet in contact, make a linear interp between both feet altitude wrt to which feet will move next
+def computeFloorAltitude(cs,t):
+    id_phase = findPhase(cs,t)
+    phase = cs.contact_phases[id_phase]
+    RF_patch = phase.RF_patch
+    LF_patch = phase.LF_patch
+    Mrf = RF_patch.placement
+    Mlf = LF_patch.placement
+
+    if RF_patch.active and LF_patch.active:
+        if pacthSameAltitude(Mrf,Mlf):
+            floor_altitude = 0.5*(Mrf.translation+Mlf.translation)[2]
+        else:
+            # look for wich feet just created contact :
+            LF_moved = False
+            if id_phase > 0: #look for the inactive contact in the previous phase
+                pprev = cs.contact_phases[id_phase-1]
+                if not pprev.RF_patch.active: 
+                    LF_moved = False
+                elif not pprev.LF_patch.active:
+                    LF_moved = True
+                else:
+                    assert "Must never happened"                                    
+            else: #look for the inactive contact in the next phase and assume cyclic gait for the last couple of phases
+                pnext = cs.contact_phases[id_phase+1]
+                if not pnext.RF_patch.active:
+                    LF_moved = True
+                elif not pnext.LF_patch.active :
+                    LF_moved = False
+                else:
+                    assert "Must never happened"                
+            # linear interp of the altitude (from the feet which are going to move to the one that stay)
+            if LF_moved:
+                p0 = Mrf.translation[2]
+                p1 = Mlf.translation[2]
+            else:
+                p0 = Mlf.translation[2]
+                p1 = Mrf.translation[2]
+
+            t0 = phase.time_trajectory[0]
+            t1 = phase.time_trajectory[-1]
+            assert t0 < t1
+            s = (t - t0) / (t1-t0)
+            floor_altitude = p0 + s * (p1-p0)
+            pass
+    elif RF_patch.active:
+        floor_altitude = Mrf.translation[2]
+    elif LF_patch.active:
+        floor_altitude = Mlf.translation[2]
+    else:
+        assert "Must never happened"
+    return floor_altitude
+
+def shiftZMPtoFloorAltitude(cs,t,phi0):
+    Mshift = SE3.Identity()
+    shift = Mshift.translation  
+    floor_altitude = computeFloorAltitude(cs,t) 
+    floor_altitude -= cfg.Robot.dict_offset[cfg.Robot.rfoot].translation[2][0] # shift to join level, assume both feet have the same transform
+    shift[2] = floor_altitude
+    Mshift.translation = shift
+    
+    # apply transform to wrench : 
+    phi_floor = Mshift.actInv(phi0)
+    #compute zmp with transformed phi :
+    w = phi_floor.angular
+    f = phi_floor.linear
+    #print "Zx",-w[1]/f[2]
+    #print "Zy",w[0]/f[2]
+    #print floor_altitude
+    ZMP = np.matrix([float(-w[1]/f[2]),float(w[0]/f[2]),float(floor_altitude)]).T    
+    return ZMP
+    
+    
+# not generic ! only consider feet 
+# (not a problem as we only call it for openHRP)
+def computeRefZMP(cs,time_t,Wrench_traj):
+    
+    N = len(time_t)
+    ZMP_t = np.matrix(np.empty((3,N)))
+    Mshift = SE3.Identity()
+    shift = Mshift.translation
+
+    phase0 = cs.contact_phases[0]
+    phase1 = cs.contact_phases[1]
+
+    if phase1.RF_patch.active:
+        RF_SS_first = True
+    else:
+        RF_SS_first = False
+
+    for k,t in enumerate(time_t):
+
+        id_phase = findPhase(cs,t)
+        phase = cs.contact_phases[id_phase]
+        wrench = Wrench_traj(t)[0]
+        phi0 = Force(wrench)
+
+        RF_patch = phase.RF_patch
+        LF_patch = phase.LF_patch
+
+        Mrf = RF_patch.placement
+
+        Mlf = LF_patch.placement
+
+        if RF_patch.active and LF_patch.active:
+            if pacthSameAltitude(Mrf,Mlf):
+                floor_altitude = 0.5*(Mrf.translation+Mlf.translation)[2]
+            else:
+
+                if RF_SS_first:
+                    p0 = Mrf.translation[2]
+                    p1 = Mlf.translation[2]
+                else:
+                    p0 = Mlf.translation[2]
+                    p1 = Mrf.translation[2]
+
+                t0 = phase.time_trajectory[0]
+                t1 = phase.time_trajectory[-1]
+                assert t0 < t1
+                s = (t - t0) / (t1-t0)
+                floor_altitude = p0 + s * (p1-p0)
+                pass
+        elif RF_patch.active:
+            floor_altitude = Mrf.translation[2]
+        elif LF_patch.active:
+            floor_altitude = Mlf.translation[2]
+        else:
+            assert "Must never happened"
+
+
+        shift[2] = floor_altitude
+        Mshift.translation = shift
+
+        phi_floor = Mshift.actInv(phi0)
+        w = phi_floor.angular
+        f = phi_floor.linear
+        #print "Zx",-w[1]/f[2]
+        #print "Zy",w[0]/f[2]
+        #print floor_altitude
+        ZMP = np.matrix([float(-w[1]/f[2]),float(w[0]/f[2]),float(floor_altitude)]).T
+        ZMP_t[:,k] = ZMP
+
+    return ZMP_t
+
diff --git a/scripts/hpp_wholebody_motion/utils/util.py b/scripts/hpp_wholebody_motion/utils/util.py
index 95bf271efc80de2a6631810998bf6e83e614189e..82b898efeb11685014513318dff4174a60b5438a 100644
--- a/scripts/hpp_wholebody_motion/utils/util.py
+++ b/scripts/hpp_wholebody_motion/utils/util.py
@@ -21,4 +21,19 @@ def distPointLine(p_l,x1_l,x2_l):
     return norm(cross(p-x1,p-x2)) / norm(x2-x1)
     
     
-    
\ No newline at end of file
+
+def findPhase(cs,t):
+    phase0 = cs.contact_phases[0]
+    phasel = cs.contact_phases[-1]
+    if t <= phase0.time_trajectory[0]:
+        return 0
+    elif t >= phasel.time_trajectory[-1]:
+        return len(cs.contact_phases)-1
+
+
+    id = [k for k, phase in enumerate(cs.contact_phases) if t >= phase.time_trajectory[0] and t <= phase.time_trajectory[-1]]
+    assert len(id)>=1 or len(id) <= 2
+    if len(id) == 2:
+        return id[1]
+    else:
+        return id[0]
\ No newline at end of file