joint_limits_interface.h
Go to the documentation of this file.
1 // Copyright (C) 2013, PAL Robotics S.L.
3 // Copyright (c) 2008, Willow Garage, Inc.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 // * Redistributions of source code must retain the above copyright notice,
8 // this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright
10 // notice, this list of conditions and the following disclaimer in the
11 // documentation and/or other materials provided with the distribution.
12 // * Neither the name of PAL Robotics S.L. nor the names of its
13 // contributors may be used to endorse or promote products derived from
14 // this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 // POSSIBILITY OF SUCH DAMAGE.
28 
30 
31 #ifndef JOINT_LIMITS_INTERFACE_JOINT_LIMITS_INTERFACE_H
32 #define JOINT_LIMITS_INTERFACE_JOINT_LIMITS_INTERFACE_H
33 
34 #include <algorithm>
35 #include <cassert>
36 #include <cmath>
37 #include <limits>
38 
39 #include <ros/duration.h>
40 
43 
46 
47 namespace joint_limits_interface
48 {
49 
50 namespace internal
51 {
52 
53 template<typename T>
54 T saturate(const T val, const T min_val, const T max_val)
55 {
56  return std::min(std::max(val, min_val), max_val);
57 }
58 
59 }
60 
64 {
65 public:
67  {
68  jh_ = jh;
69  limits_ = limits;
70 
71  if (limits_.has_position_limits)
72  {
73  min_pos_limit_ = limits_.min_position;
74  max_pos_limit_ = limits_.max_position;
75  }
76  else
77  {
78  min_pos_limit_ = -std::numeric_limits<double>::max();
79  max_pos_limit_ = std::numeric_limits<double>::max();
80  }
81 
82  prev_cmd_ = std::numeric_limits<double>::quiet_NaN();
83  }
84 
86  std::string getName() const {return jh_.getName();}
87 
93  void enforceLimits(const ros::Duration& period)
94  {
95  if (std::isnan(prev_cmd_))
96  prev_cmd_ = jh_.getPosition();
97 
98  double min_pos, max_pos;
99  if (limits_.has_velocity_limits)
100  {
101  const double delta_pos = limits_.max_velocity * period.toSec();
102  min_pos = std::max(prev_cmd_ - delta_pos, min_pos_limit_);
103  max_pos = std::min(prev_cmd_ + delta_pos, max_pos_limit_);
104  }
105  else
106  {
107  min_pos = min_pos_limit_;
108  max_pos = max_pos_limit_;
109  }
110 
111  const double cmd = internal::saturate(jh_.getCommand(), min_pos, max_pos);
112  jh_.setCommand(cmd);
113  prev_cmd_ = cmd;
114  }
115 
119  void reset(){
120  prev_cmd_ = std::numeric_limits<double>::quiet_NaN();
121  }
122 
123 private:
126  double min_pos_limit_, max_pos_limit_;
127  double prev_cmd_;
128 };
129 
160 // TODO: Leverage %Reflexxes Type II library for acceleration limits handling?
162 {
163 public:
165  : prev_cmd_(std::numeric_limits<double>::quiet_NaN())
166  {}
167 
169  const JointLimits& limits,
170  const SoftJointLimits& soft_limits)
171  : jh_(jh),
172  limits_(limits),
173  soft_limits_(soft_limits),
174  prev_cmd_(std::numeric_limits<double>::quiet_NaN())
175  {
176  if (!limits.has_velocity_limits)
177  {
178  throw JointLimitsInterfaceException("Cannot enforce limits for joint '" + getName() +
179  "'. It has no velocity limits specification.");
180  }
181  }
182 
184  std::string getName() const {return jh_.getName();}
185 
192  void enforceLimits(const ros::Duration& period)
193  {
194  assert(period.toSec() > 0.0);
195 
196  using internal::saturate;
197 
198  // Current position
199  // TODO: Doc!
200  if (std::isnan(prev_cmd_)) {prev_cmd_ = jh_.getPosition();} // Happens only once at initialization
201  const double pos = prev_cmd_;
202 
203  // Velocity bounds
204  double soft_min_vel;
205  double soft_max_vel;
206 
207  if (limits_.has_position_limits)
208  {
209  // Velocity bounds depend on the velocity limit and the proximity to the position limit
210  soft_min_vel = saturate(-soft_limits_.k_position * (pos - soft_limits_.min_position),
211  -limits_.max_velocity,
212  limits_.max_velocity);
213 
214  soft_max_vel = saturate(-soft_limits_.k_position * (pos - soft_limits_.max_position),
215  -limits_.max_velocity,
216  limits_.max_velocity);
217  }
218  else
219  {
220  // No position limits, eg. continuous joints
221  soft_min_vel = -limits_.max_velocity;
222  soft_max_vel = limits_.max_velocity;
223  }
224 
225  // Position bounds
226  const double dt = period.toSec();
227  double pos_low = pos + soft_min_vel * dt;
228  double pos_high = pos + soft_max_vel * dt;
229 
230  if (limits_.has_position_limits)
231  {
232  // This extra measure safeguards against pathological cases, like when the soft limit lies beyond the hard limit
233  pos_low = std::max(pos_low, limits_.min_position);
234  pos_high = std::min(pos_high, limits_.max_position);
235  }
236 
237  // Saturate position command according to bounds
238  const double pos_cmd = saturate(jh_.getCommand(),
239  pos_low,
240  pos_high);
241  jh_.setCommand(pos_cmd);
242 
243  // Cache variables
244  prev_cmd_ = jh_.getCommand();
245  }
246 
250  void reset(){
251  prev_cmd_ = std::numeric_limits<double>::quiet_NaN();
252  }
253 
254 private:
258 
259  double prev_cmd_;
260 };
261 
265 {
266 public:
268  : jh_(jh)
269  , limits_(limits)
270  {
271  if (!limits.has_velocity_limits)
272  {
273  throw JointLimitsInterfaceException("Cannot enforce limits for joint '" + getName() +
274  "'. It has no velocity limits specification.");
275  }
276  if (!limits.has_effort_limits)
277  {
278  throw JointLimitsInterfaceException("Cannot enforce limits for joint '" + getName() +
279  "'. It has no efforts limits specification.");
280  }
281  }
282 
284  std::string getName() const {return jh_.getName();}
285 
289  void enforceLimits(const ros::Duration& /* period */)
290  {
291  double min_eff = -limits_.max_effort;
292  double max_eff = limits_.max_effort;
293 
294  if (limits_.has_position_limits)
295  {
296  const double pos = jh_.getPosition();
297  if (pos < limits_.min_position)
298  min_eff = 0;
299  else if (pos > limits_.max_position)
300  max_eff = 0;
301  }
302 
303  const double vel = jh_.getVelocity();
304  if (vel < -limits_.max_velocity)
305  min_eff = 0;
306  else if (vel > limits_.max_velocity)
307  max_eff = 0;
308 
309  jh_.setCommand(internal::saturate(jh_.getCommand(), min_eff, max_eff));
310  }
311 
312 private:
315 };
316 
319 // TODO: This class is untested!. Update unit tests accordingly.
321 {
322 public:
324 
326  const JointLimits& limits,
327  const SoftJointLimits& soft_limits)
328  : jh_(jh),
329  limits_(limits),
330  soft_limits_(soft_limits)
331  {
332  if (!limits.has_velocity_limits)
333  {
334  throw JointLimitsInterfaceException("Cannot enforce limits for joint '" + getName() +
335  "'. It has no velocity limits specification.");
336  }
337  if (!limits.has_effort_limits)
338  {
339  throw JointLimitsInterfaceException("Cannot enforce limits for joint '" + getName() +
340  "'. It has no effort limits specification.");
341  }
342  }
343 
345  std::string getName() const {return jh_.getName();}
346 
352  void enforceLimits(const ros::Duration& /*period*/)
353  {
354  using internal::saturate;
355 
356  // Current state
357  const double pos = jh_.getPosition();
358  const double vel = jh_.getVelocity();
359 
360  // Velocity bounds
361  double soft_min_vel;
362  double soft_max_vel;
363 
364  if (limits_.has_position_limits)
365  {
366  // Velocity bounds depend on the velocity limit and the proximity to the position limit
367  soft_min_vel = saturate(-soft_limits_.k_position * (pos - soft_limits_.min_position),
368  -limits_.max_velocity,
369  limits_.max_velocity);
370 
371  soft_max_vel = saturate(-soft_limits_.k_position * (pos - soft_limits_.max_position),
372  -limits_.max_velocity,
373  limits_.max_velocity);
374  }
375  else
376  {
377  // No position limits, eg. continuous joints
378  soft_min_vel = -limits_.max_velocity;
379  soft_max_vel = limits_.max_velocity;
380  }
381 
382  // Effort bounds depend on the velocity and effort bounds
383  const double soft_min_eff = saturate(-soft_limits_.k_velocity * (vel - soft_min_vel),
384  -limits_.max_effort,
385  limits_.max_effort);
386 
387  const double soft_max_eff = saturate(-soft_limits_.k_velocity * (vel - soft_max_vel),
388  -limits_.max_effort,
389  limits_.max_effort);
390 
391  // Saturate effort command according to bounds
392  const double eff_cmd = saturate(jh_.getCommand(),
393  soft_min_eff,
394  soft_max_eff);
395  jh_.setCommand(eff_cmd);
396  }
397 
398 private:
402 };
403 
404 
407 {
408 public:
410 
412  : jh_(jh),
413  limits_(limits)
414  {
415  if (!limits.has_velocity_limits)
416  {
417  throw JointLimitsInterfaceException("Cannot enforce limits for joint '" + getName() +
418  "'. It has no velocity limits specification.");
419  }
420  }
421 
423  std::string getName() const {return jh_.getName();}
424 
429  void enforceLimits(const ros::Duration& period)
430  {
431  using internal::saturate;
432 
433  // Velocity bounds
434  double vel_low;
435  double vel_high;
436 
437  if (limits_.has_acceleration_limits)
438  {
439  assert(period.toSec() > 0.0);
440  const double vel = jh_.getVelocity();
441  const double dt = period.toSec();
442 
443  vel_low = std::max(vel - limits_.max_acceleration * dt, -limits_.max_velocity);
444  vel_high = std::min(vel + limits_.max_acceleration * dt, limits_.max_velocity);
445  }
446  else
447  {
448  vel_low = -limits_.max_velocity;
449  vel_high = limits_.max_velocity;
450  }
451 
452  // Saturate velocity command according to limits
453  const double vel_cmd = saturate(jh_.getCommand(),
454  vel_low,
455  vel_high);
456  jh_.setCommand(vel_cmd);
457  }
458 
459 private:
462 };
463 
466 {
467 public:
469  const SoftJointLimits& soft_limits)
470  {
471  jh_ = jh;
472  limits_ = limits;
473  soft_limits_ = soft_limits;
474  if (limits.has_velocity_limits)
475  max_vel_limit_ = limits.max_velocity;
476  else
477  max_vel_limit_ = std::numeric_limits<double>::max();
478  }
479 
481  std::string getName() const {return jh_.getName();}
482 
488  void enforceLimits(const ros::Duration& period)
489  {
490  using internal::saturate;
491 
492  double min_vel, max_vel;
493  if (limits_.has_position_limits)
494  {
495  // Velocity bounds depend on the velocity limit and the proximity to the position limit.
496  const double pos = jh_.getPosition();
497  min_vel = saturate(-soft_limits_.k_position * (pos - soft_limits_.min_position),
498  -max_vel_limit_, max_vel_limit_);
499  max_vel = saturate(-soft_limits_.k_position * (pos - soft_limits_.max_position),
500  -max_vel_limit_, max_vel_limit_);
501  }
502  else
503  {
504  min_vel = -max_vel_limit_;
505  max_vel = max_vel_limit_;
506  }
507 
508  if (limits_.has_acceleration_limits)
509  {
510  const double vel = jh_.getVelocity();
511  const double delta_t = period.toSec();
512  min_vel = std::max(vel - limits_.max_acceleration * delta_t, min_vel);
513  max_vel = std::min(vel + limits_.max_acceleration * delta_t, max_vel);
514  }
515 
516  jh_.setCommand(saturate(jh_.getCommand(), min_vel, max_vel));
517  }
518 
519 private:
524 };
525 
535 template <class HandleType>
537 {
538 public:
539  HandleType getHandle(const std::string& name)
540  {
541  // Rethrow exception with a meaningful type
542  try
543  {
545  }
546  catch(const std::logic_error& e)
547  {
548  throw JointLimitsInterfaceException(e.what());
549  }
550  }
551 
555  void enforceLimits(const ros::Duration& period)
556  {
558  for (ItratorType it = this->resource_map_.begin(); it != this->resource_map_.end(); ++it)
559  {
560  it->second.enforceLimits(period);
561  }
562  }
563  /*\}*/
564 };
565 
567 class PositionJointSaturationInterface : public JointLimitsInterface<PositionJointSaturationHandle> {
568 public:
572  void reset()
573  {
575  for (ItratorType it = this->resource_map_.begin(); it != this->resource_map_.end(); ++it)
576  {
577  it->second.reset();
578  }
579  }
580  /*\}*/
581 };
582 
584 class PositionJointSoftLimitsInterface : public JointLimitsInterface<PositionJointSoftLimitsHandle> {
585 public:
589  void reset()
590  {
592  for (ItratorType it = this->resource_map_.begin(); it != this->resource_map_.end(); ++it)
593  {
594  it->second.reset();
595  }
596  }
597  /*\}*/
598 };
599 
601 class EffortJointSaturationInterface : public JointLimitsInterface<EffortJointSaturationHandle> {};
602 
604 class EffortJointSoftLimitsInterface : public JointLimitsInterface<EffortJointSoftLimitsHandle> {};
605 
607 class VelocityJointSaturationInterface : public JointLimitsInterface<VelocityJointSaturationHandle> {};
608 
610 class VelocityJointSoftLimitsInterface : public JointLimitsInterface<VelocityJointSoftLimitsHandle> {};
611 
612 }
613 
614 #endif
VelocityJointSaturationHandle(const hardware_interface::JointHandle &jh, const JointLimits &limits)
string cmd
void enforceLimits(const ros::Duration &)
Enforce position, velocity, and effort limits for a joint that is not subject to soft limits...
std::string getName(void *handle)
PositionJointSaturationHandle(const hardware_interface::JointHandle &jh, const JointLimits &limits)
PositionJointSoftLimitsHandle(const hardware_interface::JointHandle &jh, const JointLimits &limits, const SoftJointLimits &soft_limits)
A handle used to enforce position and velocity limits of a position-controlled joint that does not ha...
void enforceLimits(const ros::Duration &period)
Enforce limits for all managed handles.
A handle used to enforce position, velocity, and effort limits of an effort-controlled joint that doe...
void enforceLimits(const ros::Duration &period)
Enforce position, velocity, and acceleration limits for a velocity-controlled joint subject to soft l...
A handle used to enforce position, velocity, and acceleration limits of a velocity-controlled joint...
ResourceHandle getHandle(const std::string &name)
void reset()
Reset state, in case of mode switch or e-stop.
VelocityJointSoftLimitsHandle(const hardware_interface::JointHandle &jh, const JointLimits &limits, const SoftJointLimits &soft_limits)
void enforceLimits(const ros::Duration &period)
Enforce joint velocity and acceleration limits.
EffortJointSoftLimitsHandle(const hardware_interface::JointHandle &jh, const JointLimits &limits, const SoftJointLimits &soft_limits)
HandleType getHandle(const std::string &name)
A handle used to enforce position and velocity limits of a position-controlled joint.
An exception related to a JointLimitsInterface.
Interface for enforcing joint limits.
A handle used to enforce velocity and acceleration limits of a velocity-controlled joint...
void reset()
Reset state, in case of mode switch or e-stop.
void enforceLimits(const ros::Duration &)
Enforce position, velocity and effort limits for a joint subject to soft limits.
T saturate(const T val, const T min_val, const T max_val)
A handle used to enforce position, velocity and effort limits of an effort-controlled joint...
void enforceLimits(const ros::Duration &period)
Enforce position and velocity limits for a joint subject to soft limits.
EffortJointSaturationHandle(const hardware_interface::JointHandle &jh, const JointLimits &limits)
void enforceLimits(const ros::Duration &period)
Enforce position and velocity limits for a joint that is not subject to soft limits.


joint_limits_interface
Author(s): Adolfo Rodriguez Tsouroukdissian
autogenerated on Mon Apr 20 2020 03:52:12