constraint_jla_impl.h
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 #ifndef COB_TWIST_CONTROLLER_CONSTRAINTS_CONSTRAINT_JLA_IMPL_H
19 #define COB_TWIST_CONTROLLER_CONSTRAINTS_CONSTRAINT_JLA_IMPL_H
20 
21 #include <sstream>
22 #include <string>
23 #include <vector>
24 #include <limits>
25 #include <ros/ros.h>
26 
27 #include <boost/shared_ptr.hpp>
28 #include <boost/pointer_cast.hpp>
29 
30 #include <kdl/chainjnttojacsolver.hpp>
31 #include <kdl/jntarray.hpp>
32 
35 
38 
40 
41 /* BEGIN JointLimitAvoidance ************************************************************************************/
42 template <typename T_PARAMS, typename PRIO>
44 {
45  std::ostringstream oss;
46  oss << this->member_inst_cnt_;
47  oss << "_Joint#";
48  oss << this->constraint_params_.joint_idx_;
49  oss << "_";
50  oss << this->priority_;
51  std::string taskid = "JointLimitAvoidance_" + oss.str();
52  return taskid;
53 }
54 
55 template <typename T_PARAMS, typename PRIO>
57 {
58  return this->partial_values_.transpose();
59 }
60 
61 template <typename T_PARAMS, typename PRIO>
63 {
64  return Eigen::VectorXd::Identity(1, 1) * this->derivative_value_;
65 }
66 
67 template <typename T_PARAMS, typename PRIO>
69 {
70  const ConstraintParams& params = this->constraint_params_.params_;
71  const LimiterParams& limiter_params = this->constraint_params_.limiter_params_;
72  const int32_t joint_idx = this->constraint_params_.joint_idx_;
73  const double limit_min = limiter_params.limits_min[joint_idx];
74  const double limit_max = limiter_params.limits_max[joint_idx];
75  const double joint_pos = this->joint_states_.current_q_(joint_idx);
76 
77  this->abs_delta_max_ = std::abs(limit_max - joint_pos);
78  this->rel_max_ = std::abs(this->abs_delta_max_ / limit_max);
79 
80  this->abs_delta_min_ = std::abs(joint_pos - limit_min);
81  this->rel_min_ = std::abs(this->abs_delta_min_ / limit_min);
82 
83  const double rel_val = this->rel_max_ < this->rel_min_ ? this->rel_max_ : this->rel_min_;
84 
85  this->calcValue();
86  this->calcPartialValues();
87  this->calcDerivativeValue();
88 
89  // Compute prediction
90  const double pred_delta_max = std::abs(limit_max - this->jnts_prediction_.q(joint_idx));
91  const double pred_rel_max = std::abs(pred_delta_max / limit_max);
92  const double pred_delta_min = std::abs(this->jnts_prediction_.q(joint_idx) - limit_min);
93  const double pred_rel_min = std::abs(pred_delta_min / limit_min);
94  const double pred_rel_val = pred_rel_max < pred_rel_min ? pred_rel_max : pred_rel_min;
95 
96  const double activation = params.thresholds.activation;
97  const double critical = params.thresholds.critical;
98 
99  if (this->state_.getCurrent() == CRITICAL && pred_rel_val < rel_val)
100  {
101  ROS_WARN_STREAM(this->getTaskId() << ": Current state is CRITICAL but prediction is smaller than current rel_val -> Stay in CRIT.");
102  }
103  else if (rel_val < critical || pred_rel_val < critical)
104  {
105  this->state_.setState(CRITICAL); // always highest task -> avoid HW destruction.
106  }
107  else
108  {
109  this->state_.setState(DANGER); // always active task -> avoid HW destruction.
110  }
111 }
112 
113 template <typename T_PARAMS, typename PRIO>
115 {
116  const ConstraintParams& params = this->constraint_params_.params_;
117  const double activation_threshold = params.thresholds.activation;
118  const double activation_buffer_region = params.thresholds.activation_with_buffer; // [%]
119 
120  double activation_gain;
121  const double rel_delta = this->rel_min_ < this->rel_max_ ? this->rel_min_ : this->rel_max_;
122 
123  if (rel_delta < activation_threshold)
124  {
125  activation_gain = 1.0;
126  }
127  else if (rel_delta < activation_buffer_region)
128  {
129  activation_gain = 0.5 * (1.0 + cos(M_PI * (rel_delta - activation_threshold) / (activation_buffer_region - activation_threshold)));
130  }
131  else
132  {
133  activation_gain = 0.0;
134  }
135 
136  if (activation_gain < 0.0)
137  {
138  activation_gain = 0.0;
139  }
140 
141  return activation_gain;
142 }
143 
145 template <typename T_PARAMS, typename PRIO>
146 double JointLimitAvoidance<T_PARAMS, PRIO>::getSelfMotionMagnitude(const Eigen::MatrixXd& particular_solution, const Eigen::MatrixXd& homogeneous_solution) const
147 {
148  return this->constraint_params_.params_.k_H;
149 }
150 
152 template <typename T_PARAMS, typename PRIO>
154 {
155  const LimiterParams& limiter_params = this->constraint_params_.limiter_params_;
156  const int32_t joint_idx = this->constraint_params_.joint_idx_;
157  std::vector<double> limits_min = limiter_params.limits_min;
158  std::vector<double> limits_max = limiter_params.limits_max;
159  const double joint_pos = this->joint_states_.current_q_(joint_idx);
160 
161  double nom = pow(limits_max[joint_idx] - limits_min[joint_idx], 2.0);
162  double denom = (limits_max[joint_idx] - joint_pos) * (joint_pos - limits_min[joint_idx]);
163 
164  this->last_value_ = this->value_;
165  this->value_ = std::abs(denom) > ZERO_THRESHOLD ? nom / denom : nom / DIV0_SAFE;
166 }
167 
169 template <typename T_PARAMS, typename PRIO>
171 {
172  this->derivative_value_ = -0.1 * this->value_;
173 }
174 
176 template <typename T_PARAMS, typename PRIO>
178 {
179  const LimiterParams& limiter_params = this->constraint_params_.limiter_params_;
180  const double joint_pos = this->joint_states_.current_q_(this->constraint_params_.joint_idx_);
181  const double joint_vel = this->joint_states_.current_q_dot_(this->constraint_params_.joint_idx_);
182  const double limits_min = limiter_params.limits_min[this->constraint_params_.joint_idx_];
183  const double limits_max = limiter_params.limits_max[this->constraint_params_.joint_idx_];
184  Eigen::VectorXd partial_values = Eigen::VectorXd::Zero(this->jacobian_data_.cols());
185 
186  const double min_delta = (joint_pos - limits_min);
187  const double max_delta = (limits_max - joint_pos);
188  const double nominator = (2.0 * joint_pos - limits_min - limits_max) * (limits_max - limits_min) * (limits_max - limits_min);
189  const double denom = 4.0 * min_delta * min_delta * max_delta * max_delta;
190 
191  partial_values(this->constraint_params_.joint_idx_) = std::abs(denom) > ZERO_THRESHOLD ? nominator / denom : nominator / DIV0_SAFE;
192  this->partial_values_ = partial_values;
193 }
194 /* END JointLimitAvoidance **************************************************************************************/
195 
196 /* BEGIN JointLimitAvoidanceMid ************************************************************************************/
197 template <typename T_PARAMS, typename PRIO>
199 {
200  std::ostringstream oss;
201  oss << this->member_inst_cnt_;
202  oss << "_";
203  oss << this->priority_;
204  std::string taskid = "JointLimitAvoidanceMid_" + oss.str();
205  return taskid;
206 }
207 
208 template <typename T_PARAMS, typename PRIO>
210 {
211  this->calcValue();
212  this->calcDerivativeValue();
213  this->calcPartialValues();
214 }
215 
216 template <typename T_PARAMS, typename PRIO>
218 {
219  return 1.0;
220 }
221 
223 template <typename T_PARAMS, typename PRIO>
224 double JointLimitAvoidanceMid<T_PARAMS, PRIO>::getSelfMotionMagnitude(const Eigen::MatrixXd& particular_solution, const Eigen::MatrixXd& homogeneous_solution) const
225 {
226  return this->constraint_params_.params_.k_H;
227 }
228 
230 template <typename T_PARAMS, typename PRIO>
232 {
233  const LimiterParams& limiter_params = this->constraint_params_.limiter_params_;
234  std::vector<double> limits_min = limiter_params.limits_min;
235  std::vector<double> limits_max = limiter_params.limits_max;
236  const KDL::JntArray joint_pos = this->joint_states_.current_q_;
237  double H_q = 0.0;
238  for (uint8_t i = 0; i < joint_pos.rows() ; ++i)
239  {
240  double jnt_pos_with_step = joint_pos(i);
241  double nom = pow(limits_max[i] - limits_min[i], 2.0);
242  double denom = (limits_max[i] - jnt_pos_with_step) * (jnt_pos_with_step - limits_min[i]);
243  H_q += nom / denom;
244  }
245 
246  this->value_ = H_q / 4.0;
247 }
248 
250 template <typename T_PARAMS, typename PRIO>
252 {
253  ros::Time now = ros::Time::now();
254  double cycle = (now - this->last_time_).toSec();
255  this->last_time_ = now;
256 
257  if (cycle > 0.0)
258  {
259  this->derivative_value_ = (this->value_ - this->last_value_) / cycle;
260  }
261  else
262  {
263  this->derivative_value_ = (this->value_ - this->last_value_) / DEFAULT_CYCLE;
264  }
265 }
266 
268 template <typename T_PARAMS, typename PRIO>
270 {
271  const LimiterParams& limiter_params = this->constraint_params_.limiter_params_;
272  const KDL::JntArray joint_pos = this->joint_states_.current_q_;
273  std::vector<double> limits_min = limiter_params.limits_min;
274  std::vector<double> limits_max = limiter_params.limits_max;
275 
276  uint8_t vec_rows = static_cast<uint8_t>(joint_pos.rows());
277  Eigen::VectorXd partial_values = Eigen::VectorXd::Zero(this->jacobian_data_.cols());
278 
279  for (uint8_t i = 0; i < vec_rows; ++i) // max limiting the arm joints but not the extensions.
280  {
281  double min_delta = joint_pos(i) - limits_min[i];
282  double max_delta = limits_max[i] - joint_pos(i);
283  if (min_delta * max_delta < 0.0)
284  {
285  ROS_WARN_STREAM("Limit of joint " << int(i) << " reached: " << std::endl
286  << "pos=" << joint_pos(i) << ";lim_min=" << limits_min[i] << ";lim_max=" << limits_max[i]);
287  }
288 
289  // Liegeois method can also be found in Chan paper ISSN 1042-296X [Page 288]
290  double limits_mid = 1.0 / 2.0 * (limits_max[i] + limits_min[i]);
291  double nominator = joint_pos(i) - limits_mid;
292  double denom = pow(limits_max[i] - limits_min[i], 2.0);
293  partial_values(i) = nominator / denom;
294  }
295 
296  this->partial_values_ = partial_values;
297 }
298 /* END JointLimitAvoidanceMid ************************************************************************************/
299 
300 /* BEGIN JointLimitAvoidanceIneq ************************************************************************************/
301 template <typename T_PARAMS, typename PRIO>
303 {
304  std::ostringstream oss;
305  oss << this->member_inst_cnt_;
306  oss << "_";
307  oss << this->priority_;
308  std::string taskid = "JointLimitAvoidanceIneq_" + oss.str();
309  return taskid;
310 }
311 
312 template <typename T_PARAMS, typename PRIO>
314 {
315  return this->partial_values_.transpose();
316 }
317 
318 template <typename T_PARAMS, typename PRIO>
320 {
321  return Eigen::VectorXd::Identity(1, 1) * this->derivative_value_;
322 }
323 
324 template <typename T_PARAMS, typename PRIO>
326 {
327  const ConstraintParams& params = this->constraint_params_.params_;
328  const LimiterParams& limiter_params = this->constraint_params_.limiter_params_;
329  const int32_t joint_idx = this->constraint_params_.joint_idx_;
330  const double limit_min = limiter_params.limits_min[joint_idx];
331  const double limit_max = limiter_params.limits_max[joint_idx];
332  const double joint_pos = this->joint_states_.current_q_(joint_idx);
333 
334  this->abs_delta_max_ = std::abs(limit_max - joint_pos);
335  this->rel_max_ = std::abs(this->abs_delta_max_ / limit_max);
336 
337  this->abs_delta_min_ = std::abs(joint_pos - limit_min);
338  this->rel_min_ = std::abs(this->abs_delta_min_ / limit_min);
339 
340  const double rel_val = this->rel_max_ < this->rel_min_ ? this->rel_max_ : this->rel_min_;
341 
342  this->calcValue();
343  this->calcPartialValues();
344  this->calcDerivativeValue();
345 
346  // Compute prediction
347  const double pred_delta_max = std::abs(limit_max - this->jnts_prediction_.q(joint_idx));
348  const double pred_rel_max = std::abs(pred_delta_max / limit_max);
349 
350  const double pred_delta_min = std::abs(this->jnts_prediction_.q(joint_idx) - limit_min);
351  const double pred_rel_min = std::abs(pred_delta_min / limit_min);
352 
353  this->prediction_value_ = pred_rel_max < pred_rel_min ? pred_rel_max : pred_rel_min;
354 
355  double activation = params.thresholds.activation;
356  double critical = params.thresholds.critical;
357 
358  if (this->state_.getCurrent() == CRITICAL && this->prediction_value_ < rel_val)
359  {
360  ROS_WARN_STREAM(this->getTaskId() << ": Current state is CRITICAL but prediction is smaller than current rel_val -> Stay in CRIT.");
361  }
362  else if (rel_val < critical || this->prediction_value_ < critical)
363  {
364  if (this->prediction_value_ < critical)
365  {
366  ROS_WARN_STREAM(this->getTaskId() << ": pred_val < critical!!!");
367  }
368 
369  this->state_.setState(CRITICAL);
370  }
371  else
372  {
373  this->state_.setState(DANGER); // GPM always active!
374  }
375 }
376 
377 template <typename T_PARAMS, typename PRIO>
379 {
380  const ConstraintParams& params = this->constraint_params_.params_;
381  const double activation_threshold = params.thresholds.activation; // [%]
382  const double activation_buffer_region = params.thresholds.activation_with_buffer; // [%]
383  double activation_gain;
384  double rel_delta;
385 
386  if (this->abs_delta_max_ > this->abs_delta_min_)
387  {
388  rel_delta = this->rel_min_;
389  }
390  else
391  {
392  // nearer to max limit
393  rel_delta = this->rel_max_;
394  }
395 
396  if (rel_delta < activation_threshold)
397  {
398  activation_gain = 1.0;
399  }
400  else if (rel_delta < activation_buffer_region)
401  {
402  activation_gain = 0.5 * (1.0 + cos(M_PI * (rel_delta - activation_threshold) / (activation_buffer_region - activation_threshold)));
403  }
404  else
405  {
406  activation_gain = 0.0;
407  }
408 
409  if (activation_gain < 0.0)
410  {
411  activation_gain = 0.0;
412  }
413 
414  return activation_gain;
415 }
416 
418 template <typename T_PARAMS, typename PRIO>
419 double JointLimitAvoidanceIneq<T_PARAMS, PRIO>::getSelfMotionMagnitude(const Eigen::MatrixXd& particular_solution, const Eigen::MatrixXd& homogeneous_solution) const
420 {
421  double factor;
422  const ConstraintParams& params = this->constraint_params_.params_;
423  if (this->abs_delta_max_ > this->abs_delta_min_ && this->rel_min_ > 0.0)
424  {
425  factor = (params.thresholds.activation * 1.1 / this->rel_min_) - 1.0;
426  }
427  else
428  {
429  if (this->rel_max_ > 0.0)
430  {
431  factor = (params.thresholds.activation * 1.1 / this->rel_max_) - 1.0;
432  }
433  else
434  {
435  factor = 1.0;
436  }
437  }
438 
439  double k_H = factor * params.k_H;
440  return k_H;
441 }
442 
444 template <typename T_PARAMS, typename PRIO>
446 {
447  const LimiterParams& limiter_params = this->constraint_params_.limiter_params_;
448  int32_t joint_idx = this->constraint_params_.joint_idx_;
449  double limit_min = limiter_params.limits_min[joint_idx];
450  double limit_max = limiter_params.limits_max[joint_idx];
451 
452  double joint_pos = this->joint_states_.current_q_(joint_idx);
453 
454  this->last_value_ = this->value_;
455  this->value_ = (limit_max - joint_pos) * (joint_pos - limit_min);
456 }
457 
459 template <typename T_PARAMS, typename PRIO>
461 {
462  this->derivative_value_ = 0.1 * this->value_;
463 }
464 
466 template <typename T_PARAMS, typename PRIO>
468 {
469  const LimiterParams& limiter_params = this->constraint_params_.limiter_params_;
470  int32_t joint_idx = this->constraint_params_.joint_idx_;
471  double limit_min = limiter_params.limits_min[joint_idx];
472  double limit_max = limiter_params.limits_max[joint_idx];
473  double joint_pos = this->joint_states_.current_q_(joint_idx);
474  Eigen::VectorXd partial_values = Eigen::VectorXd::Zero(this->jacobian_data_.cols());
475 
476  partial_values(this->constraint_params_.joint_idx_) = -2.0 * joint_pos + limit_max + limit_min;
477  this->partial_values_ = partial_values;
478 }
479 /* END JointLimitAvoidanceIneq **************************************************************************************/
480 
481 #endif // COB_TWIST_CONTROLLER_CONSTRAINTS_CONSTRAINT_JLA_IMPL_H
void calcDerivativeValue()
Calculate derivative of values.
virtual Eigen::MatrixXd getTaskJacobian() const
std::vector< double > limits_min
virtual std::string getTaskId() const
void calcPartialValues()
Calculates values of the gradient of the cost function.
virtual Eigen::VectorXd getTaskDerivatives() const
virtual double getSelfMotionMagnitude(const Eigen::MatrixXd &particular_solution, const Eigen::MatrixXd &homogeneous_solution) const
Returns a value for k_H to weight the partial values for e.g. GPM.
virtual Eigen::MatrixXd getTaskJacobian() const
void calcValue()
Calculate values of the JLA cost function.
unsigned int rows() const
virtual void calculate()
virtual double getSelfMotionMagnitude(const Eigen::MatrixXd &particular_solution, const Eigen::MatrixXd &homogeneous_solution) const
Returns a value for k_H to weight the partial values for e.g. GPM.
void calcValue()
Calculate values of the JLA cost function.
virtual Eigen::VectorXd getTaskDerivatives() const
void calcValue()
Calculate values of the JLA cost function.
void calcDerivativeValue()
Simple first order differential equation for exponential increase (move away from limit!) ...
#define ROS_WARN_STREAM(args)
virtual double getActivationGain() const
INLINE Rall1d< T, V, S > pow(const Rall1d< T, V, S > &arg, double m)
#define DEFAULT_CYCLE
std::vector< double > limits_max
void calcPartialValues()
Calculates values of the gradient of the cost function.
virtual std::string getTaskId() const
virtual std::string getTaskId() const
virtual double getActivationGain() const
static Time now()
#define ZERO_THRESHOLD
void calcDerivativeValue()
Calculate derivative of values.
virtual double getSelfMotionMagnitude(const Eigen::MatrixXd &particular_solution, const Eigen::MatrixXd &homogeneous_solution) const
Returns a value for k_H to weight the partial values for e.g. GPM.
virtual double getActivationGain() const
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
void calcPartialValues()
Calculates values of the gradient of the cost function.


cob_twist_controller
Author(s): Felix Messmer , Marco Bezzon , Christoph Mark , Francisco Moreno
autogenerated on Mon May 1 2023 02:50:29