From a30396af7bcbdb9db7341b51ad883195d106ca5d Mon Sep 17 00:00:00 2001
From: Gabriele Buondonno <gbuondon@laas.fr>
Date: Fri, 7 Dec 2018 18:37:00 +0100
Subject: [PATCH] test joint control

---
 CMakeLists.txt                                |  1 +
 .../joint-position-controller.hh              | 14 +++---
 .../create_entities_utils.py                  |  9 +++-
 .../test/test_jointControl.py                 | 35 +++++++++++++++
 src/joint-position-controller.cpp             | 43 +++++++++++++------
 unittest/python/test_control.py               | 20 ++++-----
 6 files changed, 89 insertions(+), 33 deletions(-)
 create mode 100644 python/sot_talos_balance/test/test_jointControl.py

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8b750c5..657a25e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -143,6 +143,7 @@ IF(BUILD_PYTHON_INTERFACE)
   IF(BUILD_TEST)
     INSTALL(FILES python/${SOTTALOSBALANCE_PYNAME}/test/__init__.py
                   python/${SOTTALOSBALANCE_PYNAME}/test/test_jointTrajGen.py
+                  python/${SOTTALOSBALANCE_PYNAME}/test/test_jointControl.py
                   DESTINATION ${PYTHON_SITELIB}/${SOTTALOSBALANCE_PYNAME}/test)
   ENDIF(BUILD_TEST)
 ENDIF(BUILD_PYTHON_INTERFACE)
diff --git a/include/sot/talos_balance/joint-position-controller.hh b/include/sot/talos_balance/joint-position-controller.hh
index 63113d5..52f1f9e 100644
--- a/include/sot/talos_balance/joint-position-controller.hh
+++ b/include/sot/talos_balance/joint-position-controller.hh
@@ -60,14 +60,15 @@ namespace dynamicgraph {
         /* --- CONSTRUCTOR ---- */
         JointPositionController( const std::string & name );
 
-        void init(const Eigen::VectorXd & Kp);
+        void init(const unsigned & n);
 
         /* --- SIGNALS --- */
-        DECLARE_SIGNAL_IN(q, Eigen::VectorXd);
-        DECLARE_SIGNAL_IN(qDes, Eigen::VectorXd);
-        DECLARE_SIGNAL_IN(dqDes, Eigen::VectorXd);
+        DECLARE_SIGNAL_IN(Kp, dynamicgraph::Vector);
+        DECLARE_SIGNAL_IN(state, dynamicgraph::Vector);
+        DECLARE_SIGNAL_IN(qDes, dynamicgraph::Vector);
+        DECLARE_SIGNAL_IN(dqDes, dynamicgraph::Vector);
 
-        DECLARE_SIGNAL_OUT(dqRef, Eigen::VectorXd);
+        DECLARE_SIGNAL_OUT(dqRef, dynamicgraph::Vector);
 
         /* --- COMMANDS --- */
         /* --- ENTITY INHERITANCE --- */
@@ -79,8 +80,9 @@ namespace dynamicgraph {
         }
 
       protected:
+        int m_n;
         bool m_initSucceeded;    /// true if the entity has been successfully initialized
-        Eigen::VectorXd m_Kp;
+        dynamicgraph::Vector m_Kp;
 
       }; // class JointPositionController
 
diff --git a/python/sot_talos_balance/create_entities_utils.py b/python/sot_talos_balance/create_entities_utils.py
index 2372170..079664f 100644
--- a/python/sot_talos_balance/create_entities_utils.py
+++ b/python/sot_talos_balance/create_entities_utils.py
@@ -1,11 +1,18 @@
 from sot_talos_balance.nd_trajectory_generator import NdTrajectoryGenerator
+from sot_talos_balance.joint_position_controller import JointPositionController
+
 from dynamic_graph import plug
 
 N_JOINTS = 32;
 
 def create_joint_trajectory_generator(dt):
     jtg = NdTrajectoryGenerator("jtg");
-    jtg.initial_value.value = tuple(32*[0.0]);
+    jtg.initial_value.value = tuple(N_JOINTS*[0.0]);
     jtg.trigger.value = 1.0;
     jtg.init(dt, N_JOINTS);
     return jtg;
+
+def create_joint_controller(Kp):
+    controller = JointPositionController("posctrl")
+    controller.Kp.value = Kp
+    return controller
diff --git a/python/sot_talos_balance/test/test_jointControl.py b/python/sot_talos_balance/test/test_jointControl.py
new file mode 100644
index 0000000..dd9f15c
--- /dev/null
+++ b/python/sot_talos_balance/test/test_jointControl.py
@@ -0,0 +1,35 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-1
+from sot_talos_balance.create_entities_utils import create_joint_trajectory_generator
+from sot_talos_balance.create_entities_utils import create_joint_controller
+from dynamic_graph import plug
+from time import sleep
+import os
+
+def main(robot,gain):
+    N_JOINTS = 32
+    Kp = N_JOINTS*[gain]
+    dt = robot.timeStep
+
+    robot.traj_gen   = create_joint_trajectory_generator(dt)
+    robot.device.control.value = N_JOINTS*[0.0]
+
+    robot.controller = create_joint_controller(Kp)
+
+    plug(robot.traj_gen.x,    robot.controller.qDes)
+    plug(robot.traj_gen.dx,   robot.controller.dqDes)
+
+    plug(robot.device.state,    robot.controller.state)
+
+    plug(robot.controller.dqRef,    robot.device.control)
+
+    robot.controller.init(N_JOINTS)
+
+    sleep(1.0)
+    os.system('rosservice call /start_dynamic_graph')
+    sleep(1.0)
+    robot.traj_gen.move(31,-1.0,1.0)
+    sleep(1.1)
+    robot.traj_gen.startSinusoid(31,3.0,2.0)
+    sleep(10.0)
+    robot.traj_gen.stop(31)
diff --git a/src/joint-position-controller.cpp b/src/joint-position-controller.cpp
index 7202831..22b4e72 100644
--- a/src/joint-position-controller.cpp
+++ b/src/joint-position-controller.cpp
@@ -36,7 +36,7 @@ namespace dynamicgraph
 //Size to be aligned                                      "-------------------------------------------------------"
 #define PROFILE_JOINTPOSITIONCONTROLLER_DQREF_COMPUTATION "JointPositionController: dqRef computation             "
 
-#define INPUT_SIGNALS     m_qSIN << m_qDesSIN << m_dqDesSIN
+#define INPUT_SIGNALS     m_KpSIN << m_stateSIN << m_qDesSIN << m_dqDesSIN
 
 #define OUTPUT_SIGNALS m_dqRefSOUT
 
@@ -53,10 +53,11 @@ namespace dynamicgraph
       /* ------------------------------------------------------------------- */
       JointPositionController::JointPositionController(const std::string& name)
                       : Entity(name)
-                      , CONSTRUCT_SIGNAL_IN(q, Eigen::VectorXd)
-                      , CONSTRUCT_SIGNAL_IN(qDes, Eigen::VectorXd)
-                      , CONSTRUCT_SIGNAL_IN(dqDes, Eigen::VectorXd)
-                      , CONSTRUCT_SIGNAL_OUT(dqRef, Eigen::VectorXd, INPUT_SIGNALS)
+                      , CONSTRUCT_SIGNAL_IN(Kp, dynamicgraph::Vector)
+                      , CONSTRUCT_SIGNAL_IN(state, dynamicgraph::Vector)
+                      , CONSTRUCT_SIGNAL_IN(qDes, dynamicgraph::Vector)
+                      , CONSTRUCT_SIGNAL_IN(dqDes, dynamicgraph::Vector)
+                      , CONSTRUCT_SIGNAL_OUT(dqRef, dynamicgraph::Vector, INPUT_SIGNALS)
                       , m_initSucceeded(false)
       {
         Entity::signalRegistration( INPUT_SIGNALS << OUTPUT_SIGNALS );
@@ -65,14 +66,20 @@ namespace dynamicgraph
         addCommand("init", makeCommandVoid1(*this, &JointPositionController::init, docCommandVoid1("Initialize the entity.","Control gains")));
       }
 
-      void JointPositionController::init(const Eigen::VectorXd & Kp)
+      void JointPositionController::init(const unsigned & n)
       {
+        if(n<1)
+          return SEND_MSG("n must be at least 1", MSG_TYPE_ERROR);
+        if(!m_KpSIN.isPlugged())
+          return SEND_MSG("Init failed: signal Kp is not plugged", MSG_TYPE_ERROR);
+        if(!m_stateSIN.isPlugged())
+          return SEND_MSG("Init failed: signal q is not plugged", MSG_TYPE_ERROR);
         if(!m_qDesSIN.isPlugged())
-          return SEND_MSG("Init failed: signal firstAddend is not plugged", MSG_TYPE_ERROR);
+          return SEND_MSG("Init failed: signal qDes is not plugged", MSG_TYPE_ERROR);
         if(!m_dqDesSIN.isPlugged())
-          return SEND_MSG("Init failed: signal secondAddend is not plugged", MSG_TYPE_ERROR);
+          return SEND_MSG("Init failed: signal dqDes is not plugged", MSG_TYPE_ERROR);
 
-        m_Kp = Kp;
+        m_n = n;
         m_initSucceeded = true;
       }
 
@@ -80,7 +87,7 @@ namespace dynamicgraph
       /* --- SIGNALS ------------------------------------------------------- */
       /* ------------------------------------------------------------------- */
 
-      DEFINE_SIGNAL_OUT_FUNCTION(dqRef, Eigen::VectorXd)
+      DEFINE_SIGNAL_OUT_FUNCTION(dqRef, dynamicgraph::Vector)
       {
         if(!m_initSucceeded)
         {
@@ -90,11 +97,19 @@ namespace dynamicgraph
 
         getProfiler().start(PROFILE_JOINTPOSITIONCONTROLLER_DQREF_COMPUTATION);
 
-        Eigen::VectorXd q = m_qSIN(iter);
-        Eigen::VectorXd qDes = m_qDesSIN(iter);
-        Eigen::VectorXd dqDes = m_dqDesSIN(iter);
+        const Vector & state = m_stateSIN(iter);
+        const Vector & qDes = m_qDesSIN(iter);
+        const Vector & dqDes = m_dqDesSIN(iter);
+        const Vector & Kp = m_KpSIN(iter);
 
-        s = dqDes + m_Kp.cwiseProduct(qDes-q);
+        assert(state.size()==m_n+6 && "Unexpected size of signal state");
+        assert(qDes.size()==m_n    && "Unexpected size of signal qDes");
+        assert(dqDes.size()==m_n   && "Unexpected size of signal dqDes");
+        assert(Kp.size()==m_n      && "Unexpected size of signal Kp");
+
+        const Vector & q = state.tail(m_n);
+
+        s = dqDes + Kp.cwiseProduct(qDes-q);
 
         getProfiler().stop(PROFILE_JOINTPOSITIONCONTROLLER_DQREF_COMPUTATION);
 
diff --git a/unittest/python/test_control.py b/unittest/python/test_control.py
index 3a7af4a..4683767 100644
--- a/unittest/python/test_control.py
+++ b/unittest/python/test_control.py
@@ -9,24 +9,20 @@ print(controller.commands())
 print("\nSignals (at creation):")
 controller.displaySignals()
 
-controller.q.value = (0.0,0.0)
-controller.qDes.value = (1.0,1.0)
-controller.dqDes.value = (0.0,0.0)
+N_JOINTS = 2
 
-Kp = (10.0,10.0)
+controller.Kp.value = tuple(N_JOINTS*[10.0])
+controller.state.value = tuple([0.0]*6 + N_JOINTS*[0.0])
+controller.qDes.value = tuple(N_JOINTS*[1.0])
+controller.dqDes.value = tuple(N_JOINTS*[0.0])
 
-controller.init(Kp)
+controller.init(N_JOINTS)
 
 controller.dqRef.recompute(1)
 
-print( "\nKp: %s" % (Kp,) )
-
-print( "\nq: %s" % (controller.q.value,) )
+print( "\nKp: %s" % (controller.Kp.value,) )
+print( "\nq: %s" % (controller.state.value,) )
 print( "qDes: %s" % (controller.qDes.value,) )
 print( "dqDes: %s" % (controller.dqDes.value,) )
 
 print( "\ndqRef: %s" % (controller.dqRef.value,) )
-
-#print( "\nInputs: %f, %f" % (ex.firstAddend.value, ex.secondAddend.value) )
-#print( "Output: %f" % ex.sum.value )
-
-- 
GitLab