svenzva_dynamics.cpp
Go to the documentation of this file.
1 // Software License Agreement (BSD License)
2 //
3 // Copyright (c) 2017 Svenzva Robotics
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions
8 // are met:
9 //
10 // * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 // * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following
14 // disclaimer in the documentation and/or other materials provided
15 // with the distribution.
16 // * Neither the name of Svenzva Robotics LLC nor the names of its
17 // contributors may be used to endorse or promote products derived
18 // from this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 
34 #include <ros/ros.h>
35 #include <ros/package.h>
36 #include <stdlib.h>
37 #include <cmath>
38 
39 #include <kdl/frames.hpp>
40 #include <kdl/chainfksolverpos_recursive.hpp>
41 #include <kdl/chainidsolver_recursive_newton_euler.hpp>
42 #include <kdl/chainiksolvervel_pinv.hpp>
43 
44 #include <sensor_msgs/JointState.h>
45 
46 
47 /*
48  * SvenzvaDynamics is a ROS component that is used in Kinesthetic Teaching of the Revel robot.
49  *
50  * Given the current robot state, this class uses a dynamic model to estimate the gravity load
51  * on each joint due to the robot's own physical characteristics.
52  *
53  * This class has many opportunities for fine-tuning parameters if the force estimation is inaccurate.
54  */
55 
56 sensor_msgs::JointState joint_states;
59 unsigned int mNumJnts = 6;
60 // Get some joint pos, vel, acc values
65 sensor_msgs::JointState model_states;
66 bool first_run = true;
68 
69 double alpha = 0.5;
70 
71 void js_cb(const sensor_msgs::JointState::ConstPtr& msg){
72  for(unsigned int i = 0; i < msg->effort.size(); i++){
73  joint_states.effort[i] = msg->effort[i] * alpha + (1.0 - alpha) * joint_states.effort[i];
74  }
75  joint_states.position = msg->position;
76  //joint_states = *msg;
77 }
78 
79 /*
80  * tau given q and the system dynamics
81  */
83  KDL::Wrenches jnt_wrenches;
84  for (unsigned int i = 0; i < mNumJnts; i++) {
85  jnt_q(i) = joint_states.position[i];
86  jnt_qd(i) = 0.0;
87  jnt_qdd(i) = 0.0;
88  KDL::Wrench wr = KDL::Wrench();
89  if( !first_run) {
90  int gr = 1;
91  double diff = model_states.effort[i] - joint_states.effort[i];
92  double frc = 0.0;
93 
94  frc = -1 * (diff) * gr;
95 
96  KDL::Vector force(0, frc, 0);
97  wr.torque = force;
98  jnt_wrenches.push_back(wr);
99  }
100  else{
101  jnt_wrenches.push_back(KDL::Wrench());
102  }
103  }
104 
105  first_run = false;
106  // Compute Dynamics
107  int ret = gcSolver->CartToJnt(jnt_q, jnt_qd, jnt_qdd, jnt_wrenches,jnt_taugc);
109  if (ret < 0){
110  ROS_ERROR("KDL: inverse dynamics ERROR");
111  ROS_ERROR("%d", ret);
112  }
113  else{
114  int divisor = 1;
115  for( unsigned int i = 0; i < mNumJnts; i++){
116  //Compute the error in the model vs present output torques
117  if( i == 1){
118  //spring function: y= -0.000012159725010x^3 + 0.001933370127203x^2 + 0.002502918014389x + 0.075320089110718
119  double spring_offset = (-0.0001215972501*std::pow(joint_states.position[i], 3)) + (0.0019337012*std::pow(joint_states.position[i], 2)) + (0.0025029181439*joint_states.position[i]) + 0.0753200891107 ;
120  jnt_taugc(i) = jnt_taugc(i) - spring_offset;
121  }
122 
123  if (i == 0)
124  divisor = 10000;
125  if (i == 1 || i == 2)
126  divisor = 7;
127  else if (i == 3)
128  divisor = 3;
129  else if (i == 4)
130  divisor = 4;
131  model_states.effort[i] = jnt_taugc(i) / divisor;
132  }
133  }
134  tau_pub.publish(model_states);
135 }
136 
137 int main(int argc, char** argv){
138  ros::init(argc, argv, "svenzva_dynamics");
139  int mNumJntsRegistered = 6;
140  std::vector<std::string> joint_names_ar;
141  std::string chain_end = "link_";
142  ros::NodeHandle n;
143 
144  // if a custom build, get the number of motors present and resize arrays
145  // to make KDL happy.
146  // Note that a customized robot will need accurate parameters in its URDF in order for grvity
147  // compensation to be accurate. These changes simply allow KDL to not throw errors.
148  if (n.getParam("num_motors_present", mNumJntsRegistered))
149  {
150  mNumJnts = std::min(mNumJntsRegistered, 6);
155  }
156  else
157  {
158  ROS_INFO("SvenzvaDynamics failed to find num joints parameter. Using default.");
159  }
160 
161  for(unsigned int i = 0; i < mNumJnts+1; i++)
162  joint_states.effort.push_back(0.0);
163 
164  ros::Subscriber js_sub = n.subscribe("joint_states", 1, js_cb);
165  ros::Publisher tau_pub = n.advertise<sensor_msgs::JointState>("/revel/model_efforts/", 1);
166  ros::Rate update_rate = ros::Rate(10);
167  std::string path = ros::package::getPath("svenzva_description");
168  std::string full_path = path + "/robots/svenzva_arm.urdf";
169  ROS_INFO("Loading model from %s", full_path.c_str());
170 
171  kdl_parser::treeFromFile(full_path, my_tree);
172 
173  if (!kdl_parser::treeFromFile(full_path, my_tree)){
174  ROS_ERROR("Failed to construct kdl tree");
175  return false;
176  }
177  chain_end.append(std::to_string(mNumJnts));
178  my_tree.getChain("base_link", chain_end.c_str(), chain);
179  ROS_INFO("Kinematic chain expects %d joints", chain.getNrOfJoints());
180 
181  KDL::Vector gravity(0.0, 0.0, -9.81);
182  gcSolver = new KDL::ChainIdSolver_RNE(chain, gravity);
183 
184 
185  /*
186  * Publish the expected torque according to the dynamic model
187  */
188  ros::spinOnce();
189  ros::Duration(5).sleep();
190  update_rate.sleep();
191  while(ros::ok()){
192  ros::spinOnce();
193  feel_efforts(tau_pub);
194  update_rate.sleep();
195  }
196 
197  return 0;
198 
199 }
KDL::JntArray jnt_taugc(mNumJnts)
KDL::Tree my_tree
void publish(const boost::shared_ptr< M > &message) const
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
void feel_efforts(ros::Publisher tau_pub)
bool sleep() const
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
Vector torque
bool first_run
KDL::JntArray jnt_qd(mNumJnts)
sensor_msgs::JointState joint_states
KDL::Chain chain
#define ROS_INFO(...)
KDL::JntArray jnt_qdd(mNumJnts)
ROSCPP_DECL bool ok()
int CartToJnt(const JntArray &q, const JntArray &q_dot, const JntArray &q_dotdot, const Wrenches &f_ext, JntArray &torques)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
unsigned int getNrOfJoints() const
KDL_PARSER_PUBLIC bool treeFromFile(const std::string &file, KDL::Tree &tree)
void js_cb(const sensor_msgs::JointState::ConstPtr &msg)
sensor_msgs::JointState model_states
ROSLIB_DECL std::string getPath(const std::string &package_name)
void resize(unsigned int newSize)
std::vector< Wrench > Wrenches
bool getChain(const std::string &chain_root, const std::string &chain_tip, Chain &chain) const
bool getParam(const std::string &key, std::string &s) const
int main(int argc, char **argv)
KDL::ChainIdSolver_RNE * gcSolver
ROSCPP_DECL void spinOnce()
unsigned int mNumJnts
KDL::JntArray jnt_q(mNumJnts)
#define ROS_ERROR(...)
double alpha


svenzva_drivers
Author(s): Max Svetlik
autogenerated on Wed Oct 28 2020 03:31:27