allegroNode.cpp
Go to the documentation of this file.
00001 /*
00002  * allegroNode.cpp
00003  *
00004  *  Created on: Feb 15, 2013
00005  *  Authors: Alex ALSPACH
00006  */
00007  
00008 // JOINT SPACE VELOCITY SATURATION CONTROL
00009 // Using  timer callback
00010 
00012 // WARNING: THIS CONTROL CODE IS UNDER DEVELOPMENT ///
00013 // USE AT YOUR OWN RISK                            ///
00015  
00016 #include <iostream>
00017 #include <boost/thread/thread.hpp>
00018 #include <boost/date_time.hpp>
00019 #include <boost/thread/locks.hpp>
00020 
00021 #include "ros/ros.h"
00022 #include "ros/service.h"
00023 #include "ros/service_server.h"
00024 #include "sensor_msgs/JointState.h"
00025 #include "std_msgs/String.h"
00026 #include "std_msgs/Float32.h"
00027 
00028 #include <stdio.h>
00029 #include <math.h>
00030 #include <algorithm>    // for std::min
00031 #include <iostream>
00032 #include <string>
00033 
00034 #include "controlAllegroHand.h"
00035 
00036 
00037 #define RADIANS_TO_DEGREES(radians) ((radians) * (180.0 / M_PI))
00038 #define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
00039 
00040 
00041 // Topics
00042 #define JOINT_STATE_TOPIC "/allegroHand/joint_states"
00043 #define JOINT_CMD_TOPIC "/allegroHand/joint_cmd"
00044 #define EXT_CMD_TOPIC "/allegroHand/external_cmd"
00045 
00046 #define JOINT_DESIRED_TOPIC "/allegroHand/joint_desired_states"
00047 #define JOINT_CURRENT_TOPIC "/allegroHand/joint_current_states"
00048 
00049 
00050 double desired_position[DOF_JOINTS]                             = {0.0};
00051 double current_position[DOF_JOINTS]                     = {0.0};
00052 double previous_position[DOF_JOINTS]                    = {0.0};
00053 double current_position_filtered[DOF_JOINTS]    = {0.0};
00054 double previous_position_filtered[DOF_JOINTS]   = {0.0};
00055 
00056 double desired_velocity[DOF_JOINTS]                             = {0.0};
00057 double current_velocity[DOF_JOINTS]                     = {0.0};
00058 double previous_velocity[DOF_JOINTS]                    = {0.0};
00059 double current_velocity_filtered[DOF_JOINTS]    = {0.0};
00060 
00061 double desired_torque[DOF_JOINTS]                               = {0.0};
00062 
00063 
00064 double v[DOF_JOINTS]                                                    = {0.0};        
00065 
00066 
00067 double k_p[DOF_JOINTS]                          = { 1200.0,  1200.0,  1200.0, 1200.0,   // Default P Gains for Velocity Saturation Controller
00068                                                                                 1200.0,  1200.0,  1200.0, 1200.0,       // These gains are loaded if the 'gains_velSat.yaml' file is not loaded.
00069                                                                                 1200.0,  1200.0,  1200.0, 1200.0,
00070                                                                             1200.0,  1200.0,  1200.0, 1200.0 };
00071 
00072 double k_d[DOF_JOINTS]                          = {  140.0,   140.0,   140.0,   140.0,  // Default D Gains for Velocity Saturation Controller
00073                                                                                  140.0,   140.0,   140.0,   140.0,      // These gains are loaded if the 'gains_velSat.yaml' file is not loaded.
00074                                                                                  140.0,   140.0,   140.0,   140.0,
00075                                                                                  140.0,   140.0,   140.0,   140.0 };
00076 
00077                          
00078 double v_max[DOF_JOINTS]                                = {  10.0,   10.0,   10.0,   10.0,      // Velocity limits 
00079                                                                                          10.0,   10.0,   10.0,   10.0,  // With a max of 10rad/s, 6rad/s is achieved
00080                                                                                          10.0,   10.0,   10.0,   10.0,  // within the ~90 degree range of each finger joint.
00081                                                                                      10.0,   10.0,   10.0,   10.0 };// These values are loaded if the 'gains_velSat.yaml' file is not loaded.   
00082                                                                                                                                                                                                                                                  
00083 
00084 double home_pose[DOF_JOINTS]            = {   0.0,  -10.0,   45.0,   45.0,      // Default (HOME) position (degrees)
00085                                                                                   0.0,  -10.0,   45.0,   45.0,          // This position is loaded and set upon system start
00086                                                                                   5.0,   -5.0,   50.0,   45.0,          // if no 'initial_position.yaml' parameter is loaded.
00087                                                                              60.0,   25.0,   15.0,   45.0 };
00088 
00089 
00090 std::string pGainParams[DOF_JOINTS] = { "~gains_velSat/p/j00", "~gains_velSat/p/j01", "~gains_velSat/p/j02", "~gains_velSat/p/j03", 
00091                                                                                 "~gains_velSat/p/j10", "~gains_velSat/p/j11", "~gains_velSat/p/j12", "~gains_velSat/p/j13",
00092                                                                                 "~gains_velSat/p/j20", "~gains_velSat/p/j21", "~gains_velSat/p/j22", "~gains_velSat/p/j23", 
00093                                                                                 "~gains_velSat/p/j30", "~gains_velSat/p/j31", "~gains_velSat/p/j32", "~gains_velSat/p/j33"};
00094 
00095 std::string dGainParams[DOF_JOINTS] = { "~gains_velSat/d/j00", "~gains_velSat/d/j01", "~gains_velSat/d/j02", "~gains_velSat/d/j03", 
00096                                                                                 "~gains_velSat/d/j10", "~gains_velSat/d/j11", "~gains_velSat/d/j12", "~gains_velSat/d/j13",
00097                                                                                 "~gains_velSat/d/j20", "~gains_velSat/d/j21", "~gains_velSat/d/j22", "~gains_velSat/d/j23", 
00098                                                                                 "~gains_velSat/d/j30", "~gains_velSat/d/j31", "~gains_velSat/d/j32", "~gains_velSat/d/j33"};
00099                                                                                 
00100 std::string vMaxParams[DOF_JOINTS] = {  "~gains_velSat/v_max/j00", "~gains_velSat/v_max/j01", "~gains_velSat/v_max/j02", "~gains_velSat/v_max/j03", 
00101                                                                                 "~gains_velSat/v_max/j10", "~gains_velSat/v_max/j11", "~gains_velSat/v_max/j12", "~gains_velSat/v_max/j13",
00102                                                                                 "~gains_velSat/v_max/j20", "~gains_velSat/v_max/j21", "~gains_velSat/v_max/j22", "~gains_velSat/v_max/j23", 
00103                                                                                 "~gains_velSat/v_max/j30", "~gains_velSat/v_max/j31", "~gains_velSat/v_max/j32", "~gains_velSat/v_max/j33"};                                                                            
00104                                                                                 
00105 std::string initialPosition[DOF_JOINTS] = {     "~initial_position/j00", "~initial_position/j01", "~initial_position/j02", "~initial_position/j03", 
00106                                                                                         "~initial_position/j10", "~initial_position/j11", "~initial_position/j12", "~initial_position/j13",
00107                                                                                         "~initial_position/j20", "~initial_position/j21", "~initial_position/j22", "~initial_position/j23", 
00108                                                                                         "~initial_position/j30", "~initial_position/j31", "~initial_position/j32", "~initial_position/j33"};                                                                                            
00109 
00110 
00111 std::string jointNames[DOF_JOINTS]      = {    "joint_0.0",    "joint_1.0",    "joint_2.0",   "joint_3.0" , 
00112                                                                                    "joint_4.0",    "joint_5.0",    "joint_6.0",   "joint_7.0" , 
00113                                                                                    "joint_8.0",    "joint_9.0",    "joint_10.0",  "joint_11.0", 
00114                                                                                    "joint_12.0",   "joint_13.0",   "joint_14.0",  "joint_15.0" };
00115 
00116 
00117 
00118 int frame = 0;
00119 
00120 // Flags
00121 int lEmergencyStop = 0;
00122 
00123 boost::mutex *mutex;
00124 
00125 // ROS Messages
00126 ros::Publisher joint_state_pub;
00127 ros::Publisher joint_desired_state_pub;
00128 ros::Publisher joint_current_state_pub;
00129 
00130 ros::Subscriber joint_cmd_sub;                          // Handles external joint command (eg. sensor_msgs/JointState)
00131 ros::Subscriber external_cmd_sub;                       // Handles any other type of eternal command (eg. std_msgs/String)
00132 sensor_msgs::JointState msgJoint_desired;       // Desired Position, Desired Velocity, Desired Torque
00133 sensor_msgs::JointState msgJoint_current;       // Current Position, Current Velocity, NOTE: Current Torque Unavailable
00134 sensor_msgs::JointState msgJoint;                       // Collects most relavent information in one message: Current Position, Current Velocity, Control Torque
00135 std::string  ext_cmd;
00136 
00137 // ROS Time
00138 ros::Time tstart;
00139 ros::Time tnow;
00140 
00141 double secs;
00142 double dt;
00143 
00144 // Initialize CAN device                
00145 controlAllegroHand *canDevice;
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153 // Called when a desired joint position message is received
00154 void SetjointCallback(const sensor_msgs::JointState& msg)
00155 {
00156         mutex->lock();
00157         for(int i=0;i<DOF_JOINTS;i++) desired_position[i] = msg.position[i];
00158         mutex->unlock();        
00159 }
00160 
00161 
00162 // Called when an external (string) message is received
00163 void extCmdCallback(const std_msgs::String::ConstPtr& msg)
00164 {
00165         ROS_INFO("CTRL: Processing external command");
00166         ext_cmd = msg->data.c_str();
00167 
00168         // Compare the message received to an expected input
00169         if (ext_cmd.compare("comparisonString") == 0)
00170         {
00171                 // Do something
00172         }    
00173         else
00174         {
00175                 // Do something else
00176         }       
00177 }
00178 
00179 
00180 
00181 
00182 
00183 
00184 // In case of the Allegro Hand, this callback is processed
00185 // every 0.003 seconds
00186 void timerCallback(const ros::TimerEvent& event)
00187 {
00188 
00189         // Calculate loop time;
00190         tnow = ros::Time::now();
00191         dt = 1e-9*(tnow - tstart).nsec;
00192         tstart = tnow;
00193         
00194         //dt = 0.003;
00195         
00196         //if ((1/dt)>400){
00197         //printf("%f\n",(1/dt-333.33333));
00198         //printf("%f\n",(dt));
00199         //}
00200                 
00201         // save last iteration info
00202         for(int i=0; i<DOF_JOINTS; i++)
00203         {
00204                 previous_position[i] = current_position[i];
00205                 previous_position_filtered[i] = current_position_filtered[i];
00206                 previous_velocity[i] = current_velocity[i];
00207         }
00208                 
00209                 
00210 /*  ================================= 
00211     =       CAN COMMUNICATION       = 
00212     ================================= */        
00213         canDevice->setTorque(desired_torque);           // WRITE joint torque
00214         lEmergencyStop = canDevice->update();           // Returns -1 in case of an error
00215         canDevice->getJointInfo(current_position);      // READ current joint positions
00216 
00217 
00218                 
00219                 
00220                                 
00221         // Stop program and shutdown node when Allegro Hand is switched off
00222         if( lEmergencyStop < 0 )
00223         {
00224                 ROS_ERROR("\n\nAllegro Hand Node is Shutting Down! (Emergency Stop)\n");
00225                 ros::shutdown();
00226         }
00227 
00228 
00229 
00230 /*  ================================= 
00231     =       LOWPASS FILTERING       =   
00232     ================================= */
00233         for(int i=0; i<DOF_JOINTS; i++)    
00234         {
00235         current_position_filtered[i] = (0.6*current_position_filtered[i]) + (0.198*previous_position[i]) + (0.198*current_position[i]);
00236                 current_velocity[i] = (current_position_filtered[i] - previous_position_filtered[i]) / dt;
00237                 current_velocity_filtered[i] = (0.6*current_velocity_filtered[i]) + (0.198*previous_velocity[i]) + (0.198*current_velocity[i]);
00238         }
00239         
00240         
00241 /*  ================================= 
00242     =       VELOCITY SATURATION     =   
00243     ================================= */
00244     // maxVelocity = 10 rad/s (dead to home) -> 13 rad/s (envelope) is a high max
00245     // maxTorque = 0.7 N.m
00246     
00247         for(int i=0; i<DOF_JOINTS; i++)    
00248         {
00249                 desired_velocity[i] = (k_p[i]/k_d[i])*(desired_position[i] - current_position_filtered[i]);
00250                 v[i] = std::min( 1.0, v_max[i]/fabs(desired_velocity[i]) );     // absolute value for floats
00251         }               
00252         
00253         
00254         
00255 /*  ================================= 
00256     =        POSITION CONTROL       =   
00257     ================================= */
00258     if(frame>100) // give the low pass filters 100 iterations (0.03s) to build up good data.
00259     {   
00260                 for(int i=0; i<DOF_JOINTS; i++)    
00261                 {
00262                         desired_torque[i] = -k_d[i]*( current_velocity_filtered[i] - v[i]*desired_velocity[i] );
00263                         desired_torque[i] = desired_torque[i]/800.0;
00264                 }
00265         }               
00266 
00267 
00268                 
00269         // PUBLISH current position, velocity and effort (torque)
00270         msgJoint.header.stamp                           = tnow;
00271         msgJoint_desired.header.stamp           = tnow;
00272         msgJoint_current.header.stamp           = tnow; 
00273         for(int i=0; i<DOF_JOINTS; i++)
00274         {
00275                 msgJoint.position[i]                    = current_position_filtered[i];
00276                 msgJoint.velocity[i]                    = current_velocity_filtered[i];
00277                 msgJoint.effort[i]                              = desired_torque[i];
00278                 
00279                 msgJoint_desired.position[i]    = desired_position[i];
00280                 msgJoint_desired.velocity[i]    = desired_velocity[i]*v[i];
00281                 msgJoint_desired.effort[i]              = desired_torque[i];
00282                 
00283                 msgJoint_current.position[i]    = current_position_filtered[i];
00284                 msgJoint_current.velocity[i]    = current_velocity_filtered[i];
00285                 msgJoint_current.effort[i]              = desired_torque[i];    // Just for plotting. Not actually current torque,
00286         }
00287         
00288         /*
00289         // Use this temrinal command to view relevant data
00290         rxplot /allegroHand/joint_desired_states/position[5],/allegroHand/joint_current_states/position[5] /allegroHand/joint_desired_states/velocity[5],/allegroHand/joint_current_states/velocity[5] /allegroHand/joint_current_states/effort[5]
00291         */
00292         
00293         joint_state_pub.publish(msgJoint);
00294         joint_desired_state_pub.publish(msgJoint_desired);
00295         joint_current_state_pub.publish(msgJoint_current);
00296                 
00297         frame++;
00298         
00299 
00300 } // end timerCallback
00301 
00302 
00303 
00304 
00305 
00306 
00307 
00308 
00309 int main(int argc, char** argv)
00310 {
00311 
00312         using namespace std;
00313         
00314         ros::init(argc, argv, "allegro_hand_core");
00315         ros::Time::init();
00316         
00317         ros::NodeHandle nh;
00318         
00319         
00320         // Setup timer callback (ALLEGRO_CONTROL_TIME_INTERVAL = 0.003)
00321         ros::Timer timer = nh.createTimer(ros::Duration(0.003), timerCallback);
00322 
00323         mutex = new boost::mutex();
00324 
00325         // Publisher and Subscribers
00326         joint_state_pub = nh.advertise<sensor_msgs::JointState>(JOINT_STATE_TOPIC, 3);
00327         joint_desired_state_pub = nh.advertise<sensor_msgs::JointState>(JOINT_DESIRED_TOPIC, 3);
00328         joint_current_state_pub = nh.advertise<sensor_msgs::JointState>(JOINT_CURRENT_TOPIC, 3);
00329         
00330         joint_cmd_sub = nh.subscribe(JOINT_CMD_TOPIC, 3, SetjointCallback);
00331         external_cmd_sub = nh.subscribe(EXT_CMD_TOPIC, 1, extCmdCallback);
00332         
00333         // Create arrays 16 long for each of the four joint state components
00334         msgJoint.position.resize(DOF_JOINTS);
00335         msgJoint.velocity.resize(DOF_JOINTS);
00336         msgJoint.effort.resize(DOF_JOINTS);
00337         msgJoint.name.resize(DOF_JOINTS);
00338         
00339         msgJoint_desired.position.resize(DOF_JOINTS);
00340         msgJoint_desired.velocity.resize(DOF_JOINTS);
00341         msgJoint_desired.effort.resize(DOF_JOINTS);
00342         msgJoint_desired.name.resize(DOF_JOINTS);
00343         
00344         msgJoint_current.position.resize(DOF_JOINTS);
00345         msgJoint_current.velocity.resize(DOF_JOINTS);
00346         msgJoint_current.effort.resize(DOF_JOINTS);
00347         msgJoint_current.name.resize(DOF_JOINTS);
00348 
00349 
00350         // Joint names (for use with joint_state_publisher GUI - matches URDF)
00351         for(int i=0; i<DOF_JOINTS; i++) msgJoint.name[i] = jointNames[i];       
00352         
00353         
00354         // Get Allegro Hand information from parameter server
00355         // This information is found in the Hand-specific "zero.yaml" file from the allegro_hand_description package    
00356         string robot_name, whichHand, manufacturer, origin, serial;
00357         double version;
00358         ros::param::get("~hand_info/robot_name",robot_name);
00359         ros::param::get("~hand_info/which_hand",whichHand);
00360         ros::param::get("~hand_info/manufacturer",manufacturer);
00361         ros::param::get("~hand_info/origin",origin);
00362         ros::param::get("~hand_info/serial",serial);
00363         ros::param::get("~hand_info/version",version);
00364 
00365 
00366         // set gains via gains_velSat.yaml or to defaul values
00367         if (ros::param::has("~gains_velSat"))
00368         {
00369                 ROS_INFO("CTRL: Velocity Saturation gains loaded from param server.");
00370                 for(int i=0; i<DOF_JOINTS; i++)
00371                 {
00372                         ros::param::get(pGainParams[i], k_p[i]);
00373                         ros::param::get(dGainParams[i], k_d[i]);
00374                         ros::param::get(vMaxParams[i],  v_max[i]);
00375                         //printf("%f ", k_p[i]);
00376                 }
00377                 //printf("\n");
00378         }
00379         else
00380         {
00381                 // gains will be loaded every control iteration
00382                 ROS_WARN("CTRL: Velocity Satuartion gains not loaded.\nCheck launch file is loading /parameters/gains_velSat.yaml\nLoading default Vel. Sat. gains...");
00383         }
00384 
00385 
00386         // set initial position via initial_position.yaml or to defaul values
00387         if (ros::param::has("~initial_position"))
00388         {
00389                 ROS_INFO("\n\nCTRL: Initial Pose loaded from param server.\n");
00390                 for(int i=0; i<DOF_JOINTS; i++)
00391                 {
00392                         ros::param::get(initialPosition[i], desired_position[i]);
00393                         desired_position[i] = DEGREES_TO_RADIANS(desired_position[i]);
00394                 }
00395         }
00396         else
00397         {
00398                 ROS_WARN("\n\nCTRL: Initial postion not loaded.\nCheck launch file is loading /parameters/initial_position.yaml\nloading Home position instead...\n");
00399                 // Home position
00400                 for(int i=0; i<DOF_JOINTS; i++) desired_position[i] = DEGREES_TO_RADIANS(home_pose[i]);                                                                         
00401         }
00402 
00403 
00404         // Initialize CAN device
00405         canDevice = new controlAllegroHand();
00406         canDevice->init();
00407         usleep(3000);
00408         
00409         // Dump Allegro Hand information to the terminal        
00410         cout << endl << endl << robot_name << " v" << version << endl << serial << " (" << whichHand << ")" << endl << manufacturer << endl << origin << endl << endl;
00411 
00412         // Start ROS time
00413         tstart = ros::Time::now();
00414 
00415         // Starts control loop, message pub/subs and all other callbacks
00416         ros::spin();                    
00417 
00418         // Clean shutdown: shutdown node, shutdown can, be polite.
00419         nh.shutdown();
00420         delete canDevice;
00421         printf("\nAllegro Hand Node has been shut down. Bye!\n\n");
00422         return 0;
00423         
00424 }
00425 
00426 


allegro_hand_core_velSat
Author(s): Alex Alspach (SimLab), Seungsu Kim (EPFL)
autogenerated on Mon Jan 6 2014 11:02:59