Add PID+gravity controller
authorWalter Fetter Lages <w.fetter@ieee.org>
Wed, 28 Nov 2018 21:47:43 +0000 (19:47 -0200)
committerWalter Fetter Lages <w.fetter@ieee.org>
Wed, 28 Nov 2018 21:47:43 +0000 (19:47 -0200)
Change computed_torque_control.* to comuted_torque_controller.*.

13 files changed:
wam_controllers/CMakeLists.txt
wam_controllers/config/computed_torque_control.yaml [deleted file]
wam_controllers/config/computed_torque_controller.yaml [new file with mode: 0644]
wam_controllers/config/pid_plus_gravity_controller.yaml [new file with mode: 0644]
wam_controllers/include/wam_controllers/computed_torque_controller.h
wam_controllers/include/wam_controllers/pid_plus_gravity_controller.h [new file with mode: 0644]
wam_controllers/launch/computed_torque.launch
wam_controllers/launch/gazebo_pid_plus_gravity.launch [new file with mode: 0644]
wam_controllers/launch/pid_plus_gravity.launch [new file with mode: 0644]
wam_controllers/package.xml
wam_controllers/src/computed_torque_controller.cpp
wam_controllers/src/pid_plus_gravity_controller.cpp [new file with mode: 0644]
wam_controllers/wam_controllers_plugins.xml

index 87c2c9e..bf0ae5b 100644 (file)
@@ -105,6 +105,7 @@ include_directories(include
 ## Declare a cpp library
 add_library(wam_controllers
   src/computed_torque_controller.cpp
+  src/pid_plus_gravity_controller.cpp
 )
 
 ## Declare a cpp executable
@@ -117,7 +118,7 @@ add_library(wam_controllers
 ## Specify libraries to link a library or executable target against
 target_link_libraries(${PROJECT_NAME}
   ${catkin_LIBRARIES}
-  ${orocos-kdl_LIBRARIES}
+  ${orocos_kdl_LIBRARIES}
   ${kdl_parser_LIBRARIES}
 )
 
diff --git a/wam_controllers/config/computed_torque_control.yaml b/wam_controllers/config/computed_torque_control.yaml
deleted file mode 100644 (file)
index 4343844..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-wam:
-    joint_state_controller:
-      type: joint_state_controller/JointStateController
-      publish_rate: 100
-
-    computed_torque_controller:
-      type: wam_controllers/ComputedTorqueController
-      joints:
-        - wam_joint_1
-        - wam_joint_2
-        - wam_joint_3
-        - wam_joint_4
-        - wam_joint_5
-        - wam_joint_6
-        - wam_joint_7
diff --git a/wam_controllers/config/computed_torque_controller.yaml b/wam_controllers/config/computed_torque_controller.yaml
new file mode 100644 (file)
index 0000000..d9f19ab
--- /dev/null
@@ -0,0 +1,31 @@
+wam:
+    joint_state_controller:
+      type: joint_state_controller/JointStateController
+      publish_rate: 100
+
+    computed_torque_controller:
+      type: effort_controllers/ComputedTorqueController
+      joints:
+        - wam_joint_1
+        - wam_joint_2
+        - wam_joint_3
+        - wam_joint_4
+        - wam_joint_5
+        - wam_joint_6
+        - wam_joint_7
+      Kp: [25.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 
+          0.0, 25.0, 0.0, 0.0, 0.0, 0.0, 0.0, 
+          0.0, 0.0, 25.0, 0.0, 0.0, 0.0, 0.0, 
+          0.0, 0.0, 0.0, 25.0, 0.0, 0.0, 0.0, 
+          0.0, 0.0, 0.0, 0.0, 25.0, 0.0, 0.0, 
+          0.0, 0.0, 0.0, 0.0, 0.0, 25.0, 0.0, 
+          0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 25.0]
+      Kd: [10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 
+          0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 
+          0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 
+          0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 
+          0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 0.0, 
+          0.0, 0.0, 0.0, 0.0, 0.0, 10.0, 0.0, 
+          0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 10.0]
+      gravity: {x: 0.0, y: 0.0, z: -9.8}
+      chain: {root: "wam_origin", tip: "wam_tool_plate"}
diff --git a/wam_controllers/config/pid_plus_gravity_controller.yaml b/wam_controllers/config/pid_plus_gravity_controller.yaml
new file mode 100644 (file)
index 0000000..b7b7d59
--- /dev/null
@@ -0,0 +1,32 @@
+wam:
+    joint_state_controller:
+      type: joint_state_controller/JointStateController
+      publish_rate: 250
+
+    pid_plus_gravity_controller:
+      type: effort_controllers/PidPlusGravityController
+      joints:
+        - wam_joint_1
+        - wam_joint_2
+        - wam_joint_3
+        - wam_joint_4
+        - wam_joint_5
+        - wam_joint_6
+        - wam_joint_7
+# PID parameters from /etc/barrett/wam7w.conf
+      wam_joint_1:
+        pid: {p: 900.0, i: 2.5, d: 10.0, i_clamp: 25.0}
+      wam_joint_2:
+        pid: {p: 2500.0, i: 5.0, d: 20.0, i_clamp: 20.0}
+      wam_joint_3:
+        pid: {p: 600.0, i: 2.0, d: 5.0, i_clamp: 15.0}
+      wam_joint_4:
+        pid: {p: 500.0, i: 0.5, d: 2.0, i_clamp: 15.0}
+      wam_joint_5:
+        pid: {p: 50.0, i: 0.5, d: 0.5, i_clamp: 5.0}
+      wam_joint_6:
+        pid: {p: 50.0, i: 0.5, d: 0.5, i_clamp: 5.0}
+      wam_joint_7:
+        pid: {p: 8.0, i: 0.1, d: 0.05, i_clamp: 5.0}
+      gravity: {x: 0.0, y: 0.0, z: -9.8}
+      chain: {root: "wam_origin", tip: "wam_tool_plate"}
index 2bbbe22..15fe88a 100644 (file)
@@ -1,3 +1,24 @@
+/******************************************************************************
+                          ROS wam_controllers Package
+                           Computed Torque  Controller
+          Copyright (C) 2013..2017 Walter Fetter Lages <w.fetter@ieee.org>
+
+        This program is free software: you can redistribute it and/or modify
+        it under the terms of the GNU General Public License as published by
+        the Free Software Foundation, either version 3 of the License, or
+        (at your option) any later version.
+
+        This program 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 Public License for more details.
+
+        You should have received a copy of the GNU General Public License
+        along with this program.  If not, see
+        <http://www.gnu.org/licenses/>.
+        
+*******************************************************************************/
+
 #ifndef WAM_CONTROLLERS_COMPUTED_TORQUE_CONTROLLER_H
 #define WAM_CONTROLLERS_COMPUTED_TORQUE_CONTROLLER_H
 
 #include <kdl_parser/kdl_parser.hpp>
 #include <kdl/chainidsolver_recursive_newton_euler.hpp>
 
-namespace wam_controllers
+namespace effort_controllers
 {
        class ComputedTorqueController: public controller_interface::
                Controller<hardware_interface::EffortJointInterface>
        {
                ros::NodeHandle node_;
 
-               hardware_interface::EffortJointInterface *robot_;
+               hardware_interface::EffortJointInterface *hw_;
                std::vector<hardware_interface::JointHandle> joints_;
+               int nJoints_;
 
                ros::Subscriber sub_command_;
                        
@@ -53,7 +75,7 @@ namespace wam_controllers
                ComputedTorqueController(void);
                ~ComputedTorqueController(void);
                
-               bool init(hardware_interface::EffortJointInterface *robot,
+               bool init(hardware_interface::EffortJointInterface *hw,
                        ros::NodeHandle &n);
                void starting(const ros::Time& time);
                void update(const ros::Time& time,const ros::Duration& duration);
diff --git a/wam_controllers/include/wam_controllers/pid_plus_gravity_controller.h b/wam_controllers/include/wam_controllers/pid_plus_gravity_controller.h
new file mode 100644 (file)
index 0000000..2fcfe45
--- /dev/null
@@ -0,0 +1,75 @@
+/******************************************************************************
+                           ROS wam_controllers Package
+                        PID+Gravity Compensation Controller
+          Copyright (C) 2017 Walter Fetter Lages <w.fetter@ieee.org>
+
+        This program is free software: you can redistribute it and/or modify
+        it under the terms of the GNU General Public License as published by
+        the Free Software Foundation, either version 3 of the License, or
+        (at your option) any later version.
+
+        This program 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 Public License for more details.
+
+        You should have received a copy of the GNU General Public License
+        along with this program.  If not, see
+        <http://www.gnu.org/licenses/>.
+        
+*******************************************************************************/
+
+#ifndef WAM_CONTROLLERS_PID_PLUS_GRAVITY_CONTROLLER_H
+#define WAM_CONTROLLERS_PID_PLUS_GRAVITY_CONTROLLER_H
+
+#include <cstddef>
+#include <vector>
+#include <string>
+
+#include <ros/node_handle.h>
+#include <hardware_interface/joint_command_interface.h>
+#include <control_toolbox/pid.h>
+#include <controller_interface/controller.h>
+#include <trajectory_msgs/JointTrajectoryPoint.h>
+#include <sensor_msgs/JointState.h>
+
+#include <Eigen/Core>
+
+#include <kdl/frames.hpp>
+#include <kdl_parser/kdl_parser.hpp>
+#include <kdl/chaindynparam.hpp>
+
+namespace effort_controllers
+{
+       class PidPlusGravityController: public controller_interface::
+               Controller<hardware_interface::EffortJointInterface>
+       {
+               ros::NodeHandle node_;
+
+               hardware_interface::EffortJointInterface *hw_;
+               std::vector<hardware_interface::JointHandle> joints_;
+
+               ros::Subscriber sub_command_;
+                       
+               KDL::ChainDynParam *chainParam_;
+                               
+               KDL::JntArray q_;
+               KDL::JntArray qr_;
+               KDL::JntArray gravity_;
+               
+               std::vector<control_toolbox::Pid> pid_;
+               
+               void commandCB(const trajectory_msgs::JointTrajectoryPoint::ConstPtr 
+                       &referencePoint);
+               
+               public:
+               PidPlusGravityController(void);
+               ~PidPlusGravityController(void);
+               
+               bool init(hardware_interface::EffortJointInterface *hw,
+                       ros::NodeHandle &n);
+               void starting(const ros::Time& time);
+               void update(const ros::Time& time,const ros::Duration& duration);
+       };
+}
+#endif
index ddcf49b..c452826 100644 (file)
@@ -1,5 +1,5 @@
 <launch>
-       <rosparam file="$(find wam_controllers)/config/computed_torque_control.yaml"
+       <rosparam file="$(find wam_controllers)/config/computed_torque_controller.yaml"
                command="load"/>
 
        <node name="controller_spawner" pkg="controller_manager" type="spawner"
diff --git a/wam_controllers/launch/gazebo_pid_plus_gravity.launch b/wam_controllers/launch/gazebo_pid_plus_gravity.launch
new file mode 100644 (file)
index 0000000..9d63288
--- /dev/null
@@ -0,0 +1,19 @@
+<launch>
+       <arg name="paused" default="true"/>
+       <arg name="headless" default="false"/>
+       <arg name="use_sim_time" default="true"/>
+       <arg name="table" default="true"/>
+       <arg name="bhand" default="false"/>
+       
+
+       <include file="$(find wam_description)/launch/gazebo.launch" >
+               <arg name="paused" value="$(arg paused)"/>
+               <arg name="headless" value="$(arg headless)"/>
+               <arg name="use_sim_time" value="$(arg use_sim_time)"/>
+               <arg name="table" value="$(arg table)"/>
+               <arg name="bhand" value="$(arg bhand)"/>
+       </include>
+
+       <include file="$(find wam_controllers)/launch/pid_plus_gravity.launch" />
+
+</launch>
diff --git a/wam_controllers/launch/pid_plus_gravity.launch b/wam_controllers/launch/pid_plus_gravity.launch
new file mode 100644 (file)
index 0000000..c0005a0
--- /dev/null
@@ -0,0 +1,9 @@
+<launch>
+       <rosparam file="$(find wam_controllers)/config/pid_plus_gravity_controller.yaml"
+               command="load"/>
+
+       <node name="controller_spawner" pkg="controller_manager" type="spawner"
+               respawn="false" output="screen" ns="wam"
+               args="joint_state_controller pid_plus_gravity_controller" >
+       </node>
+</launch>
index 118d020..819d207 100644 (file)
   <build_depend>urdf</build_depend>
   <build_depend>cmake_modules</build_depend>
   
-  <run_depend>cmake_modules</run_depend>
   <run_depend>controller_interface</run_depend>
   <run_depend>controller_manager</run_depend>
   <run_depend>control_msgs</run_depend>
-  <run_depend> joint_state_controller</run_depend>
+  <run_depend>joint_state_controller</run_depend>
   <run_depend>urdf</run_depend>
   <run_depend>kdl_parser</run_depend>
 
@@ -67,4 +66,4 @@
     <!-- Other tools can request additional information be placed here -->
     <controller_interface plugin="${prefix}/wam_controllers_plugins.xml"/>
   </export>
-</package>
\ No newline at end of file
+</package>
index c880ed0..5165310 100644 (file)
@@ -1,17 +1,30 @@
+/******************************************************************************
+                          ROS wam_controllers Package
+                           Computed Torque  Controller
+          Copyright (C) 2013..2017 Walter Fetter Lages <w.fetter@ieee.org>
+
+        This program is free software: you can redistribute it and/or modify
+        it under the terms of the GNU General Public License as published by
+        the Free Software Foundation, either version 3 of the License, or
+        (at your option) any later version.
+
+        This program 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 Public License for more details.
+
+        You should have received a copy of the GNU General Public License
+        along with this program.  If not, see
+        <http://www.gnu.org/licenses/>.
+        
+*******************************************************************************/
+
 #include <sys/mman.h>
 
 #include <wam_controllers/computed_torque_controller.h>
 #include <pluginlib/class_list_macros.h>
 
-#include <kdl/frames.hpp>
-#include <kdl_parser/kdl_parser.hpp>
-#include <kdl/chainidsolver_recursive_newton_euler.hpp>
-
-#define Ts 0.8
-#define Xi 1.0
-#define Wn (4.0/Ts/Xi)
-
-namespace wam_controllers
+namespace effort_controllers
 {      
        ComputedTorqueController::ComputedTorqueController(void):
                q(0),dq(0),v(0),qr(0),dqr(0),ddqr(0),torque(0),fext(0)
@@ -24,12 +37,12 @@ namespace wam_controllers
        }
                
        bool ComputedTorqueController::
-               init(hardware_interface::EffortJointInterface *robot,ros::NodeHandle &n)
+               init(hardware_interface::EffortJointInterface *hw,ros::NodeHandle &n)
        {
                node_=n;
-               robot_=robot;
+               hw_=hw;
                
-               XmlRpc::XmlRpcValue joint_names;
+               std::vector<std::string> joint_names;
                if(!node_.getParam("joints",joint_names))
                {
                        ROS_ERROR("No 'joints' in controller. (namespace: %s)",
@@ -37,28 +50,21 @@ namespace wam_controllers
                        return false;
                }
                
-               if(joint_names.getType() != XmlRpc::XmlRpcValue::TypeArray)
-               {
-                       ROS_ERROR("'joints' is not a struct. (namespace: %s)",
-                               node_.getNamespace().c_str());
-                       return false;
-               }
+               nJoints_=joint_names.size();            
                
-               for(int i=0; i < joint_names.size();i++)
+               for(int i=0; i < nJoints_;i++)
                {
-                       XmlRpc::XmlRpcValue &name_value=joint_names[i];
-                       if(name_value.getType() != XmlRpc::XmlRpcValue::TypeString)
+                       try
                        {
-                               ROS_ERROR("joints are not strings. (namespace: %s)",
-                                       node_.getNamespace().c_str());
+                               joints_.push_back(hw->getHandle(joint_names[i]));
+                       }
+                       catch(const hardware_interface::HardwareInterfaceException& e)
+                       {
+                               ROS_ERROR_STREAM("Exception thrown: " << e.what());
                                return false;
                        }
-                       
-                       hardware_interface::JointHandle j=robot->
-                               getHandle((std::string)name_value);
-                       joints_.push_back(j);
                }
-               sub_command_=node_.subscribe("command",1000,
+               sub_command_=node_.subscribe("command",1,
                        &ComputedTorqueController::commandCB, this);
                
                std::string robot_desc_string;
@@ -75,17 +81,31 @@ namespace wam_controllers
                        return false;
                }
                
+               std::string chainRoot;
+               if(!node_.getParam("chain/root",chainRoot))
+                {
+                       ROS_ERROR("Could not find 'chain_root' parameter.");
+                       return false;
+               }
+               
+               std::string chainTip;
+               if(!node_.getParam("chain/tip",chainTip))
+                {
+                       ROS_ERROR("Could not find 'chain/tip' parameter.");
+                       return false;
+               }
+               
                KDL::Chain chain;
-               if (!tree.getChain("wam_origin","wam_tool_plate",chain)) 
+               if (!tree.getChain(chainRoot,chainTip,chain)) 
                {
                        ROS_ERROR("Failed to get chain from KDL tree.");
                        return false;
                }
                
                KDL::Vector g;
-               node_.param("/gazebo/gravity_x",g[0],0.0);
-               node_.param("/gazebo/gravity_y",g[1],0.0);
-               node_.param("/gazebo/gravity_z",g[2],-9.8);
+               node_.param("gravity/x",g[0],0.0);
+               node_.param("gravity/y",g[1],0.0);
+               node_.param("gravity/z",g[2],-9.8);
 
                if((idsolver=new KDL::ChainIdSolver_RNE(chain,g)) == NULL)
                {
@@ -93,30 +113,42 @@ namespace wam_controllers
                        return false;
                }
 
-               q.resize(chain.getNrOfJoints());
-               dq.resize(chain.getNrOfJoints());
-               v.resize(chain.getNrOfJoints());
-               qr.resize(chain.getNrOfJoints());
-               dqr.resize(chain.getNrOfJoints());
-               ddqr.resize(chain.getNrOfJoints());
-               torque.resize(chain.getNrOfJoints());
+               q.resize(nJoints_);
+               dq.resize(nJoints_);
+               v.resize(nJoints_);
+               qr.resize(nJoints_);
+               dqr.resize(nJoints_);
+               ddqr.resize(nJoints_);
+               torque.resize(nJoints_);
 
                fext.resize(chain.getNrOfSegments());
                
-               Kp.resize(chain.getNrOfJoints(),chain.getNrOfJoints());
-               Kd.resize(chain.getNrOfJoints(),chain.getNrOfJoints());
+               Kp.resize(nJoints_,nJoints_);
+               Kd.resize(nJoints_,nJoints_);
+               
+               std::vector<double> KpVec;
+               if(!node_.getParam("Kp",KpVec))
+               {
+                       ROS_ERROR("No 'Kp' in controller %s.",node_.getNamespace().c_str());
+                       return false;
+               }
+               Kp=Eigen::Map<Eigen::MatrixXd>(KpVec.data(),nJoints_,nJoints_);
+               
+               std::vector<double> KdVec;
+               if(!node_.getParam("Kd",KdVec))
+               {
+                       ROS_ERROR("No 'Kd' in controller %s.",node_.getNamespace().c_str());
+                       return false;
+               }
+               Kd=Eigen::Map<Eigen::MatrixXd>(KdVec.data(),nJoints_,nJoints_);
                
                return true;
        }
        
        void ComputedTorqueController::starting(const ros::Time& time)
        {
-               Kp.setZero();
-               Kd.setZero();
-               for(unsigned int i=0;i < joints_.size();i++)
+               for(unsigned int i=0;i < nJoints_;i++)
                {
-                       Kp(i,i)=Wn*Wn;
-                       Kd(i,i)=2.0*Xi*Wn;
                        q(i)=joints_[i].getPosition();
                        dq(i)=joints_[i].getVelocity();
                }
@@ -138,7 +170,7 @@ namespace wam_controllers
        void ComputedTorqueController::update(const ros::Time& time,
                const ros::Duration& duration)
        {
-               for(unsigned int i=0;i < joints_.size();i++)
+               for(unsigned int i=0;i < nJoints_;i++)
                {
                        q(i)=joints_[i].getPosition();
                        dq(i)=joints_[i].getVelocity();
@@ -149,14 +181,14 @@ namespace wam_controllers
                if(idsolver->CartToJnt(q,dq,v,fext,torque) < 0)
                        ROS_ERROR("KDL inverse dynamics solver failed.");
                
-               for(unsigned int i=0;i < joints_.size();i++)
+               for(unsigned int i=0;i < nJoints_;i++)
                        joints_[i].setCommand(torque(i));
        }
        
        void ComputedTorqueController::commandCB(const trajectory_msgs::
                JointTrajectoryPoint::ConstPtr &referencePoint)
        {
-               for(unsigned int i=0;i < qr.rows();i++)
+               for(unsigned int i=0;i < nJoints_;i++)
                {
                        qr(i)=referencePoint->positions[i];
                        dqr(i)=referencePoint->velocities[i];
@@ -165,5 +197,5 @@ namespace wam_controllers
        }
 }
 
-PLUGINLIB_EXPORT_CLASS(wam_controllers::ComputedTorqueController,
+PLUGINLIB_EXPORT_CLASS(effort_controllers::ComputedTorqueController,
         controller_interface::ControllerBase)
diff --git a/wam_controllers/src/pid_plus_gravity_controller.cpp b/wam_controllers/src/pid_plus_gravity_controller.cpp
new file mode 100644 (file)
index 0000000..e144ba1
--- /dev/null
@@ -0,0 +1,173 @@
+/******************************************************************************
+                           ROS wam_controllers Package
+                        PID+Gravity Compensation Controller
+          Copyright (C) 2017 Walter Fetter Lages <w.fetter@ieee.org>
+
+        This program is free software: you can redistribute it and/or modify
+        it under the terms of the GNU General Public License as published by
+        the Free Software Foundation, either version 3 of the License, or
+        (at your option) any later version.
+
+        This program 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 Public License for more details.
+
+        You should have received a copy of the GNU General Public License
+        along with this program.  If not, see
+        <http://www.gnu.org/licenses/>.
+        
+*******************************************************************************/
+
+#include <sys/mman.h>
+
+#include <wam_controllers/pid_plus_gravity_controller.h>
+#include <pluginlib/class_list_macros.h>
+
+namespace effort_controllers
+{      
+       PidPlusGravityController::PidPlusGravityController(void):
+               q_(0),qr_(0),gravity_(0)
+       {
+       }
+       
+       PidPlusGravityController::~PidPlusGravityController(void)
+       {
+               sub_command_.shutdown();
+       }
+               
+       bool PidPlusGravityController::
+               init(hardware_interface::EffortJointInterface *hw,ros::NodeHandle &n)
+       {
+               node_=n;
+               hw_=hw;
+               
+               std::vector<std::string> joint_names;
+               if(!node_.getParam("joints",joint_names))
+               {
+                       ROS_ERROR("No 'joints' in controller. (namespace: %s)",
+                               node_.getNamespace().c_str());
+                       return false;
+               }
+
+               pid_.resize(joint_names.size());
+
+               for(int i=0; i < joint_names.size();i++)
+               {
+                       try
+                       {
+                               joints_.push_back(hw->getHandle(joint_names[i]));
+                       }
+                       catch(const hardware_interface::HardwareInterfaceException& e)
+                       {
+                               ROS_ERROR_STREAM("Exception thrown: " << e.what());
+                               return false;
+                       }
+                       if(!pid_[i].init(ros::NodeHandle(node_,joint_names[i]+"/pid")))
+                       {
+                               ROS_ERROR_STREAM("Failed to load PID parameters from " << joint_names[i] + "/pid");
+                               return false;
+                       }
+               }
+
+               sub_command_=node_.subscribe("command",1,
+                       &PidPlusGravityController::commandCB, this);
+               
+               std::string robot_desc_string;
+               if(!node_.getParam("/robot_description",robot_desc_string))
+                {
+                       ROS_ERROR("Could not find '/robot_description'.");
+                       return false;
+               }
+               
+               KDL::Tree tree;
+               if (!kdl_parser::treeFromString(robot_desc_string,tree))
+               {
+                       ROS_ERROR("Failed to construct KDL tree.");
+                       return false;
+               }
+               
+               std::string chainRoot;
+               if(!node_.getParam("chain/root",chainRoot))
+                {
+                       ROS_ERROR("Could not find 'chain_root' parameter.");
+                       return false;
+               }
+               
+               std::string chainTip;
+               if(!node_.getParam("chain/tip",chainTip))
+                {
+                       ROS_ERROR("Could not find 'chain/tip' parameter.");
+                       return false;
+               }
+               
+               KDL::Chain chain;
+               if (!tree.getChain(chainRoot,chainTip,chain)) 
+               {
+                       ROS_ERROR("Failed to get chain from KDL tree.");
+                       return false;
+               }
+               
+               KDL::Vector g;
+               node_.param("gravity/x",g[0],0.0);
+               node_.param("gravity/y",g[1],0.0);
+               node_.param("gravity/z",g[2],-9.8);
+               
+               if((chainParam_=new KDL::ChainDynParam(chain,g)) == NULL)
+               {
+                       ROS_ERROR("Failed to create ChainDynParam.");
+                       return false;
+               }
+
+               q_.resize(chain.getNrOfJoints());
+               qr_.resize(chain.getNrOfJoints());
+               gravity_.resize(chain.getNrOfJoints());
+               
+               return true;
+       }
+       
+       void PidPlusGravityController::starting(const ros::Time& time)
+       {
+               for(unsigned int i=0;i < joints_.size();i++)
+                       q_(i)=joints_[i].getPosition();
+                qr_=q_;
+               
+                struct sched_param param;
+                param.sched_priority=sched_get_priority_max(SCHED_FIFO);
+                if(sched_setscheduler(0,SCHED_FIFO,&param) == -1)
+                {
+                        ROS_WARN("Failed to set real-time scheduler.");
+                        return;
+                }
+                if(mlockall(MCL_CURRENT|MCL_FUTURE) == -1)
+                        ROS_WARN("Failed to lock memory.");
+       }
+       
+       void PidPlusGravityController::update(const ros::Time& time,
+               const ros::Duration& duration)
+       {
+               for(unsigned int i=0;i < joints_.size();i++)
+                       q_(i)=joints_[i].getPosition();
+                       
+               if(chainParam_->JntToGravity(q_,gravity_) < 0)
+                       ROS_ERROR("KDL dynamics solver failed.");
+               
+               for(unsigned int i=0;i < joints_.size();i++)
+                       joints_[i].setCommand(gravity_(i)+pid_[i].computeCommand(qr_(i)-q_(i),duration));
+       }
+       
+       void PidPlusGravityController::commandCB(const trajectory_msgs::
+               JointTrajectoryPoint::ConstPtr &referencePoint)
+       {
+               if(referencePoint->positions.size()!=qr_.rows())
+               { 
+                       ROS_ERROR_STREAM("Dimension of command (" << referencePoint->positions.size() << ") does not match number of joints (" << qr_.rows() << ")!");
+                       return; 
+               }
+               for(unsigned int i=0;i < qr_.rows();i++)
+                       qr_(i)=referencePoint->positions[i];
+       }
+}
+
+PLUGINLIB_EXPORT_CLASS(effort_controllers::PidPlusGravityController,
+        controller_interface::ControllerBase)
index cc65b0d..aac31df 100644 (file)
@@ -1,15 +1,27 @@
 <library path="lib/libwam_controllers">
 
-  <class name="wam_controllers/ComputedTorqueController"
-    type="wam_controllers::ComputedTorqueController"
+  <class name="effort_controllers/ComputedTorqueController"
+    type="effort_controllers::ComputedTorqueController"
     base_class_type="controller_interface::ControllerBase">
     <description>
       The ComputedTorqueController implements a computed torque controller
       in joint space for the Barrett WAM dynamic model.  The reference
       inputs (command in the ROS nomenclature) are joint positions,
-      velocities and accelerations.  This typf of controller expects an
+      velocities and accelerations.  This type of controller expects an
       EffortJointInterface type of hardware interface.
     </description>
   </class>
+  
+    <class name="effort_controllers/PidPlusGravityController"
+    type="effort_controllers::PidPlusGravityController"
+    base_class_type="controller_interface::ControllerBase">
+    <description>
+      The PidPlusGravityController implements a PID controller with gravity
+      compensation in joint space for the Barrett WAM dynamic model.  The
+      reference inputs (command in the ROS nomenclature) are joint
+      positions.  This type of controller expects an EffortJointInterface
+      type of hardware interface.
+    </description>
+  </class>
 
 </library>