pr2_base_controller.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2009, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of the Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 /*
35  * Author: Sachin Chitta and Matthew Piccoli
36  */
37 
40 
42 
43 namespace controller {
44 
45  const static double EPS = 1e-5;
46 
47 Pr2BaseController::Pr2BaseController()
48 {
49  //init variables
50  cmd_vel_.linear.x = 0;
51  cmd_vel_.linear.y = 0;
52  cmd_vel_.angular.z = 0;
53 
54  desired_vel_.linear.x = 0;
55  desired_vel_.linear.y = 0;
56  desired_vel_.angular.z = 0;
57 
58  cmd_vel_t_.linear.x = 0;
59  cmd_vel_t_.linear.y = 0;
60  cmd_vel_t_.angular.z = 0;
61 
62  new_cmd_available_ = false;
63  last_publish_time_ = ros::Time(0.0);
64 
65  pthread_mutex_init(&pr2_base_controller_lock_, NULL);
66 }
67 
68 Pr2BaseController::~Pr2BaseController()
69 {
70  cmd_sub_.shutdown();
71  cmd_sub_deprecated_.shutdown();
72 }
73 
74 bool Pr2BaseController::init(pr2_mechanism_model::RobotState *robot, ros::NodeHandle &n)
75 {
76  if(!base_kin_.init(robot,n))
77  return false;
78  node_ = n;
79  state_publisher_.reset(new realtime_tools::RealtimePublisher<pr2_mechanism_controllers::BaseControllerState>(n, base_kin_.name_ + "/state", 1));
80 
81  int num_joints = base_kin_.num_wheels_ + base_kin_.num_casters_;
82  state_publisher_->msg_.joint_names.resize(num_joints);
83  state_publisher_->msg_.joint_velocity_measured.resize(num_joints);
84  state_publisher_->msg_.joint_effort_measured.resize(num_joints);
85  state_publisher_->msg_.joint_velocity_commanded.resize(num_joints);
86  state_publisher_->msg_.joint_effort_commanded.resize(num_joints);
87  state_publisher_->msg_.joint_velocity_error.resize(num_joints);
88  state_publisher_->msg_.joint_effort_error.resize(num_joints);
89 
90  //Get params from param server
91  node_.param<double> ("max_translational_velocity", max_translational_velocity_,0.5);
92  node_.param<double> ("max_rotational_velocity", max_rotational_velocity_, 10.0); //0.5
93  node_.param<double> ("max_translational_acceleration/x", max_accel_.linear.x, .2);
94  node_.param<double> ("max_translational_acceleration/y", max_accel_.linear.y, .2);
95  node_.param<double> ("max_rotational_acceleration", max_accel_.angular.z, 10.0); //0.2
96 
97  node_.param<double> ("kp_caster_steer", kp_caster_steer_, 80.0);
98  node_.param<double> ("timeout", timeout_, 1.0);
99  node_.param<double> ("state_publish_rate", state_publish_rate_,2.0);
100  if(state_publish_rate_ <= 0.0)
101  {
102  publish_state_ = false;
103  state_publish_time_ = 0.0;
104  }
105  else
106  {
107  publish_state_ = true;
108  state_publish_time_ = 1.0/state_publish_rate_;
109  }
110 
111  // cmd_sub_deprecated_ = root_handle_.subscribe<geometry_msgs::Twist>("cmd_vel", 1, &Pr2BaseController::commandCallback, this);
112  cmd_sub_ = node_.subscribe<geometry_msgs::Twist>("command", 1, &Pr2BaseController::commandCallback, this);
113 
114  //casters
115  caster_controller_.resize(base_kin_.num_casters_);
116  caster_position_pid_.resize(base_kin_.num_casters_);
117  for(int i = 0; i < base_kin_.num_casters_; i++)
118  {
119  control_toolbox::Pid p_i_d;
120  state_publisher_->msg_.joint_names[i] = base_kin_.caster_[i].joint_name_;
121  if(!p_i_d.init(ros::NodeHandle(node_, base_kin_.caster_[i].joint_name_+"/velocity_controller")))
122  {
123  ROS_ERROR("Could not initialize pid for %s",base_kin_.caster_[i].joint_name_.c_str());
124  return false;
125  }
126 
127  if(!caster_position_pid_[i].init(ros::NodeHandle(node_, base_kin_.caster_[i].joint_name_+"/position_controller")))
128  {
129  ROS_ERROR("Could not initialize position pid controller for %s",base_kin_.caster_[i].joint_name_.c_str());
130  return false;
131  }
132  caster_controller_[i].reset(new JointVelocityController());
133  if(!caster_controller_[i]->init(base_kin_.robot_state_, base_kin_.caster_[i].joint_name_, p_i_d))
134  {
135  ROS_ERROR("Could not initialize pid for %s",base_kin_.caster_[i].joint_name_.c_str());
136  return false;
137  }
138  if (!caster_controller_[i]->joint_state_->calibrated_)
139  {
140  ROS_ERROR("Caster joint \"%s\" not calibrated (namespace: %s)",
141  base_kin_.caster_[i].joint_name_.c_str(), node_.getNamespace().c_str());
142  return false;
143  }
144  }
145  //wheels
146  wheel_controller_.resize(base_kin_.num_wheels_);
147  for(int j = 0; j < base_kin_.num_wheels_; j++)
148  {
149  control_toolbox::Pid p_i_d;
150  state_publisher_->msg_.joint_names[j + base_kin_.num_casters_] = base_kin_.wheel_[j].joint_name_;
151  if(!p_i_d.init(ros::NodeHandle(node_,base_kin_.wheel_[j].joint_name_)))
152  {
153  ROS_ERROR("Could not initialize pid for %s",base_kin_.wheel_[j].joint_name_.c_str());
154  return false;
155  }
156  wheel_controller_[j].reset(new JointVelocityController());
157  if(!wheel_controller_[j]->init(base_kin_.robot_state_, base_kin_.wheel_[j].joint_name_, p_i_d))
158  {
159  ROS_ERROR("Could not initialize joint velocity controller for %s",base_kin_.wheel_[j].joint_name_.c_str());
160  return false;
161  }
162  }
163  for(int i = 0; i < base_kin_.num_casters_; ++i)
164  {
165  if(!base_kin_.caster_[i].joint_->calibrated_)
166  {
167  ROS_ERROR("The Base controller could not start because the casters were not calibrated. Relaunch the base controller after you see the caster calibration finish.");
168  return false; // Casters are not calibrated
169  }
170  }
171 
172  if (!((filters::MultiChannelFilterBase<double>&)caster_vel_filter_).configure(base_kin_.num_casters_, std::string("caster_velocity_filter"), node_)){
173  ROS_ERROR("BaseController: could not configure velocity filters for casters");
174  return false;
175  }
176  filtered_velocity_.resize(base_kin_.num_casters_);
177  return true;
178 }
179 
180 // Set the base velocity command
181 void Pr2BaseController::setCommand(const geometry_msgs::Twist &cmd_vel)
182 {
183  double vel_mag = sqrt(cmd_vel.linear.x * cmd_vel.linear.x + cmd_vel.linear.y * cmd_vel.linear.y);
184  double clamped_vel_mag = filters::clamp(vel_mag,-max_translational_velocity_, max_translational_velocity_);
185  if(vel_mag > EPS)
186  {
187  cmd_vel_t_.linear.x = cmd_vel.linear.x * clamped_vel_mag / vel_mag;
188  cmd_vel_t_.linear.y = cmd_vel.linear.y * clamped_vel_mag / vel_mag;
189  }
190  else
191  {
192  cmd_vel_t_.linear.x = 0.0;
193  cmd_vel_t_.linear.y = 0.0;
194  }
195  cmd_vel_t_.angular.z = filters::clamp(cmd_vel.angular.z, -max_rotational_velocity_, max_rotational_velocity_);
196  cmd_received_timestamp_ = base_kin_.robot_state_->getTime();
197 
198  ROS_DEBUG("BaseController:: command received: %f %f %f",cmd_vel.linear.x,cmd_vel.linear.y,cmd_vel.angular.z);
199  ROS_DEBUG("BaseController:: command current: %f %f %f", cmd_vel_.linear.x,cmd_vel_.linear.y,cmd_vel_.angular.z);
200  ROS_DEBUG("BaseController:: clamped vel: %f", clamped_vel_mag);
201  ROS_DEBUG("BaseController:: vel: %f", vel_mag);
202 
203  for(int i=0; i < (int) base_kin_.num_wheels_; i++)
204  {
205  ROS_DEBUG("BaseController:: wheel speed cmd:: %d %f",i,(base_kin_.wheel_[i].direction_multiplier_*base_kin_.wheel_[i].wheel_speed_cmd_));
206  }
207  for(int i=0; i < (int) base_kin_.num_casters_; i++)
208  {
209  ROS_DEBUG("BaseController:: caster speed cmd:: %d %f",i,(base_kin_.caster_[i].steer_velocity_desired_));
210  }
211  new_cmd_available_ = true;
212 }
213 
214 geometry_msgs::Twist Pr2BaseController::interpolateCommand(const geometry_msgs::Twist &start, const geometry_msgs::Twist &end, const geometry_msgs::Twist &max_rate, const double &dT)
215 {
216  geometry_msgs::Twist result;
217  geometry_msgs::Twist alpha;
218  double delta(0), max_delta(0);
219 
220  delta = end.linear.x - start.linear.x;
221  max_delta = max_rate.linear.x * dT;
222  if(fabs(delta) <= max_delta || max_delta < EPS)
223  alpha.linear.x = 1;
224  else
225  alpha.linear.x = max_delta / fabs(delta);
226 
227  delta = end.linear.y - start.linear.y;
228  max_delta = max_rate.linear.y * dT;
229  if(fabs(delta) <= max_delta || max_delta < EPS)
230  alpha.linear.y = 1;
231  else
232  alpha.linear.y = max_delta / fabs(delta);
233 
234  delta = end.angular.z - start.angular.z;
235  max_delta = max_rate.angular.z * dT;
236  if(fabs(delta) <= max_delta || max_delta < EPS)
237  alpha.angular.z = 1;
238  else
239  alpha.angular.z = max_delta / fabs(delta);
240 
241  double alpha_min = alpha.linear.x;
242  if(alpha.linear.y < alpha_min)
243  alpha_min = alpha.linear.y;
244  if(alpha.angular.z < alpha_min)
245  alpha_min = alpha.angular.z;
246 
247  result.linear.x = start.linear.x + alpha_min * (end.linear.x - start.linear.x);
248  result.linear.y = start.linear.y + alpha_min * (end.linear.y - start.linear.y);
249  result.angular.z = start.angular.z + alpha_min * (end.angular.z - start.angular.z);
250  return result;
251 }
252 
253 geometry_msgs::Twist Pr2BaseController::getCommand()// Return the current velocity command
254 {
255  geometry_msgs::Twist cmd_vel;
256  pthread_mutex_lock(&pr2_base_controller_lock_);
257  cmd_vel.linear.x = cmd_vel_.linear.x;
258  cmd_vel.linear.y = cmd_vel_.linear.y;
259  cmd_vel.angular.z = cmd_vel_.angular.z;
260  pthread_mutex_unlock(&pr2_base_controller_lock_);
261  return cmd_vel;
262 }
263 
264 void Pr2BaseController::starting()
265 {
266  last_time_ = base_kin_.robot_state_->getTime();
267  cmd_received_timestamp_ = base_kin_.robot_state_->getTime();
268  for(int i = 0; i < base_kin_.num_casters_; i++)
269  {
270  caster_controller_[i]->starting();
271  }
272  for(int j = 0; j < base_kin_.num_wheels_; j++)
273  {
274  wheel_controller_[j]->starting();
275  }
276 }
277 
278 void Pr2BaseController::update()
279 {
280  ros::Time current_time = base_kin_.robot_state_->getTime();
281  double dT = std::min<double>((current_time - last_time_).toSec(), base_kin_.MAX_DT_);
282 
283  if(new_cmd_available_)
284  {
285  if(pthread_mutex_trylock(&pr2_base_controller_lock_) == 0)
286  {
287  desired_vel_.linear.x = cmd_vel_t_.linear.x;
288  desired_vel_.linear.y = cmd_vel_t_.linear.y;
289  desired_vel_.angular.z = cmd_vel_t_.angular.z;
290  new_cmd_available_ = false;
291  pthread_mutex_unlock(&pr2_base_controller_lock_);
292  }
293  }
294 
295  if((current_time - cmd_received_timestamp_).toSec() > timeout_)
296  {
297  cmd_vel_.linear.x = 0;
298  cmd_vel_.linear.y = 0;
299  cmd_vel_.angular.z = 0;
300  }
301  else
302  cmd_vel_ = interpolateCommand(cmd_vel_, desired_vel_, max_accel_, dT);
303 
304  computeJointCommands(dT);
305 
306  setJointCommands();
307 
308  updateJointControllers();
309 
310  if(publish_state_)
311  publishState(current_time);
312 
313  last_time_ = current_time;
314 
315 }
316 
317 void Pr2BaseController::publishState(const ros::Time &time)
318 {
319  if((time - last_publish_time_).toSec() < state_publish_time_)
320  {
321  return;
322  }
323 
324  if(state_publisher_->trylock())
325  {
326  state_publisher_->msg_.command.linear.x = cmd_vel_.linear.x;
327  state_publisher_->msg_.command.linear.y = cmd_vel_.linear.y;
328  state_publisher_->msg_.command.angular.z = cmd_vel_.angular.z;
329 
330  for(int i = 0; i < base_kin_.num_casters_; i++)
331  {
332  state_publisher_->msg_.joint_names[i] = base_kin_.caster_[i].joint_name_;
333  state_publisher_->msg_.joint_velocity_measured[i] = base_kin_.caster_[i].joint_->velocity_;
334  state_publisher_->msg_.joint_velocity_commanded[i]= base_kin_.caster_[i].steer_velocity_desired_;
335  state_publisher_->msg_.joint_velocity_error[i] = base_kin_.caster_[i].joint_->velocity_ - base_kin_.caster_[i].steer_velocity_desired_;
336 
337  state_publisher_->msg_.joint_effort_measured[i] = base_kin_.caster_[i].joint_->measured_effort_;
338  state_publisher_->msg_.joint_effort_commanded[i] = base_kin_.caster_[i].joint_->commanded_effort_;
339  state_publisher_->msg_.joint_effort_error[i] = base_kin_.caster_[i].joint_->measured_effort_ - base_kin_.caster_[i].joint_->commanded_effort_;
340  }
341  for(int i = 0; i < base_kin_.num_wheels_; i++)
342  {
343  state_publisher_->msg_.joint_names[i+base_kin_.num_casters_] = base_kin_.wheel_[i].joint_name_;
344  state_publisher_->msg_.joint_velocity_measured[i+base_kin_.num_casters_] = base_kin_.wheel_[i].wheel_speed_actual_;
345  state_publisher_->msg_.joint_velocity_commanded[i+base_kin_.num_casters_]= base_kin_.wheel_[i].wheel_speed_error_;
346  state_publisher_->msg_.joint_velocity_error[i+base_kin_.num_casters_] = base_kin_.wheel_[i].wheel_speed_cmd_;
347 
348  state_publisher_->msg_.joint_effort_measured[i+base_kin_.num_casters_] = base_kin_.wheel_[i].joint_->measured_effort_;
349  state_publisher_->msg_.joint_effort_commanded[i+base_kin_.num_casters_] = base_kin_.wheel_[i].joint_->commanded_effort_;
350  state_publisher_->msg_.joint_effort_error[i+base_kin_.num_casters_] = base_kin_.wheel_[i].joint_->measured_effort_ - base_kin_.wheel_[i].joint_->commanded_effort_;
351  }
352  state_publisher_->unlockAndPublish();
353  last_publish_time_ = time;
354  }
355 }
356 
357 void Pr2BaseController::computeJointCommands(const double &dT)
358 {
359  base_kin_.computeWheelPositions();
360 
361  computeDesiredCasterSteer(dT);
362 
363  computeDesiredWheelSpeeds();
364 }
365 
366 void Pr2BaseController::setJointCommands()
367 {
368  setDesiredCasterSteer();
369 
370  setDesiredWheelSpeeds();
371 }
372 
373 void Pr2BaseController::computeDesiredCasterSteer(const double &dT)
374 {
375  geometry_msgs::Twist result;
376 
377  double steer_angle_desired(0.0), steer_angle_desired_m_pi(0.0);
378  double error_steer(0.0), error_steer_m_pi(0.0);
379  double trans_vel = sqrt(cmd_vel_.linear.x * cmd_vel_.linear.x + cmd_vel_.linear.y * cmd_vel_.linear.y);
380 
381  for(int i = 0; i < base_kin_.num_casters_; i++)
382  {
383  filtered_velocity_[i] = 0.0 - base_kin_.caster_[i].joint_->velocity_;
384  }
385  caster_vel_filter_.update(filtered_velocity_,filtered_velocity_);
386 
387  for(int i = 0; i < base_kin_.num_casters_; i++)
388  {
389  result = base_kin_.pointVel2D(base_kin_.caster_[i].offset_, cmd_vel_);
390  if(trans_vel < EPS && fabs(cmd_vel_.angular.z) < EPS)
391  {
392  steer_angle_desired = base_kin_.caster_[i].steer_angle_stored_;
393  }
394  else
395  {
396  steer_angle_desired = atan2(result.linear.y, result.linear.x);
397  base_kin_.caster_[i].steer_angle_stored_ = steer_angle_desired;
398  }
399  steer_angle_desired_m_pi = angles::normalize_angle(steer_angle_desired + M_PI);
400  error_steer = angles::shortest_angular_distance(
401  base_kin_.caster_[i].joint_->position_,
402  steer_angle_desired);
403  error_steer_m_pi = angles::shortest_angular_distance(
404  base_kin_.caster_[i].joint_->position_,
405  steer_angle_desired_m_pi);
406 
407  if(fabs(error_steer_m_pi) < fabs(error_steer))
408  {
409  error_steer = error_steer_m_pi;
410  steer_angle_desired = steer_angle_desired_m_pi;
411  }
412  // base_kin_.caster_[i].steer_velocity_desired_ = -kp_caster_steer_ * error_steer;
413  base_kin_.caster_[i].steer_velocity_desired_ = caster_position_pid_[i].computeCommand(
414  error_steer,
415  filtered_velocity_[i],
416  ros::Duration(dT));
417  base_kin_.caster_[i].caster_position_error_ = error_steer;
418  }
419 }
420 
421 void Pr2BaseController::setDesiredCasterSteer()
422 {
423  for(int i = 0; i < base_kin_.num_casters_; i++)
424  {
425  caster_controller_[i]->setCommand(base_kin_.caster_[i].steer_velocity_desired_);
426  }
427 }
428 
429 void Pr2BaseController::computeDesiredWheelSpeeds()
430 {
431  geometry_msgs::Twist wheel_point_velocity;
432  geometry_msgs::Twist wheel_point_velocity_projected;
433  geometry_msgs::Twist wheel_caster_steer_component;
434  geometry_msgs::Twist caster_2d_velocity;
435 
436  caster_2d_velocity.linear.x = 0;
437  caster_2d_velocity.linear.y = 0;
438  caster_2d_velocity.angular.z = 0;
439 
440  double steer_angle_actual = 0;
441  for(int i = 0; i < (int) base_kin_.num_wheels_; i++)
442  {
443  base_kin_.wheel_[i].updatePosition();
444  caster_2d_velocity.angular.z = base_kin_.wheel_[i].parent_->steer_velocity_desired_;
445  steer_angle_actual = base_kin_.wheel_[i].parent_->joint_->position_;
446  wheel_point_velocity = base_kin_.pointVel2D(base_kin_.wheel_[i].position_, cmd_vel_);
447  wheel_caster_steer_component = base_kin_.pointVel2D(base_kin_.wheel_[i].offset_, caster_2d_velocity);
448 
449  double costh = cos(-steer_angle_actual);
450  double sinth = sin(-steer_angle_actual);
451 
452  wheel_point_velocity_projected.linear.x = costh * wheel_point_velocity.linear.x - sinth * wheel_point_velocity.linear.y;
453  wheel_point_velocity_projected.linear.y = sinth * wheel_point_velocity.linear.x + costh * wheel_point_velocity.linear.y;
454  base_kin_.wheel_[i].wheel_speed_cmd_ = (wheel_point_velocity_projected.linear.x + wheel_caster_steer_component.linear.x) / (base_kin_.wheel_[i].wheel_radius_);
455  }
456 }
457 
458 void Pr2BaseController::setDesiredWheelSpeeds()
459 {
460  for(int i = 0; i < (int) base_kin_.num_wheels_; i++)
461  {
462  wheel_controller_[i]->setCommand(base_kin_.wheel_[i].direction_multiplier_ * base_kin_.wheel_[i].wheel_speed_cmd_);
463  }
464 }
465 
466 void Pr2BaseController::updateJointControllers()
467 {
468  for(int i = 0; i < base_kin_.num_wheels_; i++)
469  wheel_controller_[i]->update();
470  for(int i = 0; i < base_kin_.num_casters_; i++)
471  caster_controller_[i]->update();
472 }
473 
474 void Pr2BaseController::commandCallback(const geometry_msgs::TwistConstPtr& msg)
475 {
476  pthread_mutex_lock(&pr2_base_controller_lock_);
477  base_vel_msg_ = *msg;
478  this->setCommand(base_vel_msg_);
479  pthread_mutex_unlock(&pr2_base_controller_lock_);
480 }
481 } // namespace
PLUGINLIB_EXPORT_CLASS(my_controller_ns::MyControllerClass, pr2_controller_interface::Controller)
void update(const std::string &key, const XmlRpc::XmlRpcValue &v)
static const double EPS
bool init(const ros::NodeHandle &n, const bool quiet=false)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
static const T & clamp(const T &a, const T &b, const T &c)
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
def normalize_angle(angle)
INLINE Rall1d< T, V, S > atan2(const Rall1d< T, V, S > &y, const Rall1d< T, V, S > &x)
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
#define ROS_ERROR(...)
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
def shortest_angular_distance(from_angle, to_angle)
#define ROS_DEBUG(...)


pr2_mechanism_controllers
Author(s): Sachin Chita, John Hsu, Melonee Wise
autogenerated on Mon Jun 10 2019 14:26:33