joint_group_position_controller.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2008, Willow Garage, Inc.
5  * Copyright (c) 2012, hiDOF, Inc.
6  * Copyright (c) 2013, PAL Robotics, S.L.
7  * Copyright (c) 2014, Fraunhofer IPA
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * * Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * * Redistributions in binary form must reproduce the above
17  * copyright notice, this list of conditions and the following
18  * disclaimer in the documentation and/or other materials provided
19  * with the distribution.
20  * * Neither the name of the Willow Garage nor the names of its
21  * contributors may be used to endorse or promote products derived
22  * from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *********************************************************************/
37 
40 #include <angles/angles.h>
41 
42 namespace effort_controllers
43 {
44 
60 
62  {
63  // List of controlled joints
64  std::string param_name = "joints";
65  if(!n.getParam(param_name, joint_names_))
66  {
67  ROS_ERROR_STREAM("Failed to getParam '" << param_name << "' (namespace: " << n.getNamespace() << ").");
68  return false;
69  }
70  n_joints_ = joint_names_.size();
71 
72  if(n_joints_ == 0){
73  ROS_ERROR_STREAM("List of joint names is empty.");
74  return false;
75  }
76 
77  // Get URDF
79  if (!urdf.initParam("robot_description"))
80  {
81  ROS_ERROR("Failed to parse urdf file");
82  return false;
83  }
84 
86 
87  for(unsigned int i=0; i<n_joints_; i++)
88  {
89  const auto& joint_name = joint_names_[i];
90 
91  try
92  {
93  joints_.push_back(hw->getHandle(joint_name));
94  }
96  {
97  ROS_ERROR_STREAM("Exception thrown: " << e.what());
98  return false;
99  }
100 
101  urdf::JointConstSharedPtr joint_urdf = urdf.getJoint(joint_name);
102  if (!joint_urdf)
103  {
104  ROS_ERROR("Could not find joint '%s' in urdf", joint_name.c_str());
105  return false;
106  }
107  joint_urdfs_.push_back(joint_urdf);
108 
109  // Load PID Controller using gains set on parameter server
110  if (!pid_controllers_[i].init(ros::NodeHandle(n, joint_name + "/pid")))
111  {
112  ROS_ERROR_STREAM("Failed to load PID parameters from " << joint_name + "/pid");
113  return false;
114  }
115  }
116 
117  commands_buffer_.writeFromNonRT(std::vector<double>(n_joints_, 0.0));
118 
119  sub_command_ = n.subscribe<std_msgs::Float64MultiArray>("command", 1, &JointGroupPositionController::commandCB, this);
120  return true;
121  }
122 
124  {
125  std::vector<double> & commands = *commands_buffer_.readFromRT();
126  for(unsigned int i=0; i<n_joints_; i++)
127  {
128  double command_position = commands[i];
129 
130  double error; //, vel_error;
131  double commanded_effort;
132 
133  double current_position = joints_[i].getPosition();
134 
135  // Make sure joint is within limits if applicable
136  enforceJointLimits(command_position, i);
137 
138  // Compute position error
139  if (joint_urdfs_[i]->type == urdf::Joint::REVOLUTE)
140  {
142  current_position,
143  command_position,
144  joint_urdfs_[i]->limits->lower,
145  joint_urdfs_[i]->limits->upper,
146  error);
147  }
148  else if (joint_urdfs_[i]->type == urdf::Joint::CONTINUOUS)
149  {
150  error = angles::shortest_angular_distance(current_position, command_position);
151  }
152  else //prismatic
153  {
154  error = command_position - current_position;
155  }
156 
157  // Set the PID error and compute the PID command with nonuniform
158  // time step size.
159  commanded_effort = pid_controllers_[i].computeCommand(error, period);
160 
161  joints_[i].setCommand(commanded_effort);
162  }
163  }
164 
165  void JointGroupPositionController::commandCB(const std_msgs::Float64MultiArrayConstPtr& msg)
166  {
167  if(msg->data.size()!=n_joints_)
168  {
169  ROS_ERROR_STREAM("Dimension of command (" << msg->data.size() << ") does not match number of joints (" << n_joints_ << ")! Not executing!");
170  return;
171  }
172  commands_buffer_.writeFromNonRT(msg->data);
173  }
174 
175  void JointGroupPositionController::enforceJointLimits(double &command, unsigned int index)
176  {
177  // Check that this joint has applicable limits
178  if (joint_urdfs_[index]->type == urdf::Joint::REVOLUTE || joint_urdfs_[index]->type == urdf::Joint::PRISMATIC)
179  {
180  if( command > joint_urdfs_[index]->limits->upper ) // above upper limnit
181  {
182  command = joint_urdfs_[index]->limits->upper;
183  }
184  else if( command < joint_urdfs_[index]->limits->lower ) // below lower limit
185  {
186  command = joint_urdfs_[index]->limits->lower;
187  }
188  }
189  }
190 
191 } // namespace
192 
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
std::vector< hardware_interface::JointHandle > joints_
void commandCB(const std_msgs::Float64MultiArrayConstPtr &msg)
Forward command controller for a set of effort controlled joints (torque or force).
JointGroupPositionController()
Forward command controller for a set of effort controlled joints (torque or force).
void enforceJointLimits(double &command, unsigned int index)
void writeFromNonRT(const T &data)
void update(const ros::Time &, const ros::Duration &)
const char * what() const noexcept override
bool getParam(const std::string &key, std::string &s) const
URDF_EXPORT bool initParam(const std::string &param)
realtime_tools::RealtimeBuffer< std::vector< double > > commands_buffer_
JointHandle getHandle(const std::string &name)
const std::string & getNamespace() const
#define ROS_ERROR_STREAM(args)
bool init(hardware_interface::EffortJointInterface *hw, ros::NodeHandle &n)
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
#define ROS_ERROR(...)
def shortest_angular_distance(from_angle, to_angle)
def shortest_angular_distance_with_large_limits(from_angle, to_angle, left_limit, right_limit)


effort_controllers
Author(s): Vijay Pradeep
autogenerated on Fri Feb 3 2023 03:19:08