00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef COB_TWIST_CONTROLLER_CONSTRAINTS_CONSTRAINT_JLA_IMPL_H
00019 #define COB_TWIST_CONTROLLER_CONSTRAINTS_CONSTRAINT_JLA_IMPL_H
00020
00021 #include <sstream>
00022 #include <string>
00023 #include <vector>
00024 #include <limits>
00025 #include <ros/ros.h>
00026
00027 #include <boost/shared_ptr.hpp>
00028 #include <boost/pointer_cast.hpp>
00029
00030 #include <kdl/chainjnttojacsolver.hpp>
00031 #include <kdl/jntarray.hpp>
00032
00033 #include "cob_twist_controller/constraints/constraint.h"
00034 #include "cob_twist_controller/constraints/constraint_params.h"
00035
00036 #include "cob_twist_controller/damping_methods/damping.h"
00037 #include "cob_twist_controller/inverse_jacobian_calculations/inverse_jacobian_calculation.h"
00038
00039 #include <eigen_conversions/eigen_kdl.h>
00040
00041
00042 template <typename T_PARAMS, typename PRIO>
00043 std::string JointLimitAvoidance<T_PARAMS, PRIO>::getTaskId() const
00044 {
00045 std::ostringstream oss;
00046 oss << this->member_inst_cnt_;
00047 oss << "_Joint#";
00048 oss << this->constraint_params_.joint_idx_;
00049 oss << "_";
00050 oss << this->priority_;
00051 std::string taskid = "JointLimitAvoidance_" + oss.str();
00052 return taskid;
00053 }
00054
00055 template <typename T_PARAMS, typename PRIO>
00056 Eigen::MatrixXd JointLimitAvoidance<T_PARAMS, PRIO>::getTaskJacobian() const
00057 {
00058 return this->partial_values_.transpose();
00059 }
00060
00061 template <typename T_PARAMS, typename PRIO>
00062 Eigen::VectorXd JointLimitAvoidance<T_PARAMS, PRIO>::getTaskDerivatives() const
00063 {
00064 return Eigen::VectorXd::Identity(1, 1) * this->derivative_value_;
00065 }
00066
00067 template <typename T_PARAMS, typename PRIO>
00068 void JointLimitAvoidance<T_PARAMS, PRIO>::calculate()
00069 {
00070 const ConstraintParams& params = this->constraint_params_.params_;
00071 const LimiterParams& limiter_params = this->constraint_params_.limiter_params_;
00072 const int32_t joint_idx = this->constraint_params_.joint_idx_;
00073 const double limit_min = limiter_params.limits_min[joint_idx];
00074 const double limit_max = limiter_params.limits_max[joint_idx];
00075 const double joint_pos = this->joint_states_.current_q_(joint_idx);
00076
00077 this->abs_delta_max_ = std::abs(limit_max - joint_pos);
00078 this->rel_max_ = std::abs(this->abs_delta_max_ / limit_max);
00079
00080 this->abs_delta_min_ = std::abs(joint_pos - limit_min);
00081 this->rel_min_ = std::abs(this->abs_delta_min_ / limit_min);
00082
00083 const double rel_val = this->rel_max_ < this->rel_min_ ? this->rel_max_ : this->rel_min_;
00084
00085 this->calcValue();
00086 this->calcPartialValues();
00087 this->calcDerivativeValue();
00088
00089
00090 const double pred_delta_max = std::abs(limit_max - this->jnts_prediction_.q(joint_idx));
00091 const double pred_rel_max = std::abs(pred_delta_max / limit_max);
00092 const double pred_delta_min = std::abs(this->jnts_prediction_.q(joint_idx) - limit_min);
00093 const double pred_rel_min = std::abs(pred_delta_min / limit_min);
00094 const double pred_rel_val = pred_rel_max < pred_rel_min ? pred_rel_max : pred_rel_min;
00095
00096 const double activation = params.thresholds.activation;
00097 const double critical = params.thresholds.critical;
00098
00099 if (this->state_.getCurrent() == CRITICAL && pred_rel_val < rel_val)
00100 {
00101 ROS_WARN_STREAM(this->getTaskId() << ": Current state is CRITICAL but prediction is smaller than current rel_val -> Stay in CRIT.");
00102 }
00103 else if (rel_val < critical || pred_rel_val < critical)
00104 {
00105 this->state_.setState(CRITICAL);
00106 }
00107 else
00108 {
00109 this->state_.setState(DANGER);
00110 }
00111 }
00112
00113 template <typename T_PARAMS, typename PRIO>
00114 double JointLimitAvoidance<T_PARAMS, PRIO>::getActivationGain() const
00115 {
00116 const ConstraintParams& params = this->constraint_params_.params_;
00117 const double activation_threshold = params.thresholds.activation;
00118 const double activation_buffer_region = params.thresholds.activation_with_buffer;
00119
00120 double activation_gain;
00121 const double rel_delta = this->rel_min_ < this->rel_max_ ? this->rel_min_ : this->rel_max_;
00122
00123 if (rel_delta < activation_threshold)
00124 {
00125 activation_gain = 1.0;
00126 }
00127 else if (rel_delta < activation_buffer_region)
00128 {
00129 activation_gain = 0.5 * (1.0 + cos(M_PI * (rel_delta - activation_threshold) / (activation_buffer_region - activation_threshold)));
00130 }
00131 else
00132 {
00133 activation_gain = 0.0;
00134 }
00135
00136 if (activation_gain < 0.0)
00137 {
00138 activation_gain = 0.0;
00139 }
00140
00141 return activation_gain;
00142 }
00143
00145 template <typename T_PARAMS, typename PRIO>
00146 double JointLimitAvoidance<T_PARAMS, PRIO>::getSelfMotionMagnitude(const Eigen::MatrixXd& particular_solution, const Eigen::MatrixXd& homogeneous_solution) const
00147 {
00148 return this->constraint_params_.params_.k_H;
00149 }
00150
00152 template <typename T_PARAMS, typename PRIO>
00153 void JointLimitAvoidance<T_PARAMS, PRIO>::calcValue()
00154 {
00155 const LimiterParams& limiter_params = this->constraint_params_.limiter_params_;
00156 const int32_t joint_idx = this->constraint_params_.joint_idx_;
00157 std::vector<double> limits_min = limiter_params.limits_min;
00158 std::vector<double> limits_max = limiter_params.limits_max;
00159 const double joint_pos = this->joint_states_.current_q_(joint_idx);
00160
00161 double nom = pow(limits_max[joint_idx] - limits_min[joint_idx], 2.0);
00162 double denom = (limits_max[joint_idx] - joint_pos) * (joint_pos - limits_min[joint_idx]);
00163
00164 this->last_value_ = this->value_;
00165 this->value_ = std::abs(denom) > ZERO_THRESHOLD ? nom / denom : nom / DIV0_SAFE;
00166 }
00167
00169 template <typename T_PARAMS, typename PRIO>
00170 void JointLimitAvoidance<T_PARAMS, PRIO>::calcDerivativeValue()
00171 {
00172 this->derivative_value_ = -0.1 * this->value_;
00173 }
00174
00176 template <typename T_PARAMS, typename PRIO>
00177 void JointLimitAvoidance<T_PARAMS, PRIO>::calcPartialValues()
00178 {
00179 const LimiterParams& limiter_params = this->constraint_params_.limiter_params_;
00180 const double joint_pos = this->joint_states_.current_q_(this->constraint_params_.joint_idx_);
00181 const double joint_vel = this->joint_states_.current_q_dot_(this->constraint_params_.joint_idx_);
00182 const double limits_min = limiter_params.limits_min[this->constraint_params_.joint_idx_];
00183 const double limits_max = limiter_params.limits_max[this->constraint_params_.joint_idx_];
00184 Eigen::VectorXd partial_values = Eigen::VectorXd::Zero(this->jacobian_data_.cols());
00185
00186 const double min_delta = (joint_pos - limits_min);
00187 const double max_delta = (limits_max - joint_pos);
00188 const double nominator = (2.0 * joint_pos - limits_min - limits_max) * (limits_max - limits_min) * (limits_max - limits_min);
00189 const double denom = 4.0 * min_delta * min_delta * max_delta * max_delta;
00190
00191 partial_values(this->constraint_params_.joint_idx_) = std::abs(denom) > ZERO_THRESHOLD ? nominator / denom : nominator / DIV0_SAFE;
00192 this->partial_values_ = partial_values;
00193 }
00194
00195
00196
00197 template <typename T_PARAMS, typename PRIO>
00198 std::string JointLimitAvoidanceMid<T_PARAMS, PRIO>::getTaskId() const
00199 {
00200 std::ostringstream oss;
00201 oss << this->member_inst_cnt_;
00202 oss << "_";
00203 oss << this->priority_;
00204 std::string taskid = "JointLimitAvoidanceMid_" + oss.str();
00205 return taskid;
00206 }
00207
00208 template <typename T_PARAMS, typename PRIO>
00209 void JointLimitAvoidanceMid<T_PARAMS, PRIO>::calculate()
00210 {
00211 this->calcValue();
00212 this->calcDerivativeValue();
00213 this->calcPartialValues();
00214 }
00215
00216 template <typename T_PARAMS, typename PRIO>
00217 double JointLimitAvoidanceMid<T_PARAMS, PRIO>::getActivationGain() const
00218 {
00219 return 1.0;
00220 }
00221
00223 template <typename T_PARAMS, typename PRIO>
00224 double JointLimitAvoidanceMid<T_PARAMS, PRIO>::getSelfMotionMagnitude(const Eigen::MatrixXd& particular_solution, const Eigen::MatrixXd& homogeneous_solution) const
00225 {
00226 return this->constraint_params_.params_.k_H;
00227 }
00228
00230 template <typename T_PARAMS, typename PRIO>
00231 void JointLimitAvoidanceMid<T_PARAMS, PRIO>::calcValue()
00232 {
00233 const LimiterParams& limiter_params = this->constraint_params_.limiter_params_;
00234 std::vector<double> limits_min = limiter_params.limits_min;
00235 std::vector<double> limits_max = limiter_params.limits_max;
00236 const KDL::JntArray joint_pos = this->joint_states_.current_q_;
00237 double H_q = 0.0;
00238 for (uint8_t i = 0; i < joint_pos.rows() ; ++i)
00239 {
00240 double jnt_pos_with_step = joint_pos(i);
00241 double nom = pow(limits_max[i] - limits_min[i], 2.0);
00242 double denom = (limits_max[i] - jnt_pos_with_step) * (jnt_pos_with_step - limits_min[i]);
00243 H_q += nom / denom;
00244 }
00245
00246 this->value_ = H_q / 4.0;
00247 }
00248
00250 template <typename T_PARAMS, typename PRIO>
00251 void JointLimitAvoidanceMid<T_PARAMS, PRIO>::calcDerivativeValue()
00252 {
00253 ros::Time now = ros::Time::now();
00254 double cycle = (now - this->last_time_).toSec();
00255 this->last_time_ = now;
00256
00257 if (cycle > 0.0)
00258 {
00259 this->derivative_value_ = (this->value_ - this->last_value_) / cycle;
00260 }
00261 else
00262 {
00263 this->derivative_value_ = (this->value_ - this->last_value_) / DEFAULT_CYCLE;
00264 }
00265 }
00266
00268 template <typename T_PARAMS, typename PRIO>
00269 void JointLimitAvoidanceMid<T_PARAMS, PRIO>::calcPartialValues()
00270 {
00271 const LimiterParams& limiter_params = this->constraint_params_.limiter_params_;
00272 const KDL::JntArray joint_pos = this->joint_states_.current_q_;
00273 std::vector<double> limits_min = limiter_params.limits_min;
00274 std::vector<double> limits_max = limiter_params.limits_max;
00275
00276 uint8_t vec_rows = static_cast<uint8_t>(joint_pos.rows());
00277 Eigen::VectorXd partial_values = Eigen::VectorXd::Zero(this->jacobian_data_.cols());
00278
00279 for (uint8_t i = 0; i < vec_rows; ++i)
00280 {
00281 double min_delta = joint_pos(i) - limits_min[i];
00282 double max_delta = limits_max[i] - joint_pos(i);
00283 if (min_delta * max_delta < 0.0)
00284 {
00285 ROS_WARN_STREAM("Limit of joint " << int(i) << " reached: " << std::endl
00286 << "pos=" << joint_pos(i) << ";lim_min=" << limits_min[i] << ";lim_max=" << limits_max[i]);
00287 }
00288
00289
00290 double limits_mid = 1.0 / 2.0 * (limits_max[i] + limits_min[i]);
00291 double nominator = joint_pos(i) - limits_mid;
00292 double denom = pow(limits_max[i] - limits_min[i], 2.0);
00293 partial_values(i) = nominator / denom;
00294 }
00295
00296 this->partial_values_ = partial_values;
00297 }
00298
00299
00300
00301 template <typename T_PARAMS, typename PRIO>
00302 std::string JointLimitAvoidanceIneq<T_PARAMS, PRIO>::getTaskId() const
00303 {
00304 std::ostringstream oss;
00305 oss << this->member_inst_cnt_;
00306 oss << "_";
00307 oss << this->priority_;
00308 std::string taskid = "JointLimitAvoidanceIneq_" + oss.str();
00309 return taskid;
00310 }
00311
00312 template <typename T_PARAMS, typename PRIO>
00313 Eigen::MatrixXd JointLimitAvoidanceIneq<T_PARAMS, PRIO>::getTaskJacobian() const
00314 {
00315 return this->partial_values_.transpose();
00316 }
00317
00318 template <typename T_PARAMS, typename PRIO>
00319 Eigen::VectorXd JointLimitAvoidanceIneq<T_PARAMS, PRIO>::getTaskDerivatives() const
00320 {
00321 return Eigen::VectorXd::Identity(1, 1) * this->derivative_value_;
00322 }
00323
00324 template <typename T_PARAMS, typename PRIO>
00325 void JointLimitAvoidanceIneq<T_PARAMS, PRIO>::calculate()
00326 {
00327 const ConstraintParams& params = this->constraint_params_.params_;
00328 const LimiterParams& limiter_params = this->constraint_params_.limiter_params_;
00329 const int32_t joint_idx = this->constraint_params_.joint_idx_;
00330 const double limit_min = limiter_params.limits_min[joint_idx];
00331 const double limit_max = limiter_params.limits_max[joint_idx];
00332 const double joint_pos = this->joint_states_.current_q_(joint_idx);
00333
00334 this->abs_delta_max_ = std::abs(limit_max - joint_pos);
00335 this->rel_max_ = std::abs(this->abs_delta_max_ / limit_max);
00336
00337 this->abs_delta_min_ = std::abs(joint_pos - limit_min);
00338 this->rel_min_ = std::abs(this->abs_delta_min_ / limit_min);
00339
00340 const double rel_val = this->rel_max_ < this->rel_min_ ? this->rel_max_ : this->rel_min_;
00341
00342 this->calcValue();
00343 this->calcPartialValues();
00344 this->calcDerivativeValue();
00345
00346
00347 const double pred_delta_max = std::abs(limit_max - this->jnts_prediction_.q(joint_idx));
00348 const double pred_rel_max = std::abs(pred_delta_max / limit_max);
00349
00350 const double pred_delta_min = std::abs(this->jnts_prediction_.q(joint_idx) - limit_min);
00351 const double pred_rel_min = std::abs(pred_delta_min / limit_min);
00352
00353 this->prediction_value_ = pred_rel_max < pred_rel_min ? pred_rel_max : pred_rel_min;
00354
00355 double activation = params.thresholds.activation;
00356 double critical = params.thresholds.critical;
00357
00358 if (this->state_.getCurrent() == CRITICAL && this->prediction_value_ < rel_val)
00359 {
00360 ROS_WARN_STREAM(this->getTaskId() << ": Current state is CRITICAL but prediction is smaller than current rel_val -> Stay in CRIT.");
00361 }
00362 else if (rel_val < critical || this->prediction_value_ < critical)
00363 {
00364 if (this->prediction_value_ < critical)
00365 {
00366 ROS_WARN_STREAM(this->getTaskId() << ": pred_val < critical!!!");
00367 }
00368
00369 this->state_.setState(CRITICAL);
00370 }
00371 else
00372 {
00373 this->state_.setState(DANGER);
00374 }
00375 }
00376
00377 template <typename T_PARAMS, typename PRIO>
00378 double JointLimitAvoidanceIneq<T_PARAMS, PRIO>::getActivationGain() const
00379 {
00380 const ConstraintParams& params = this->constraint_params_.params_;
00381 const double activation_threshold = params.thresholds.activation;
00382 const double activation_buffer_region = params.thresholds.activation_with_buffer;
00383 double activation_gain;
00384 double rel_delta;
00385
00386 if (this->abs_delta_max_ > this->abs_delta_min_)
00387 {
00388 rel_delta = this->rel_min_;
00389 }
00390 else
00391 {
00392
00393 rel_delta = this->rel_max_;
00394 }
00395
00396 if (rel_delta < activation_threshold)
00397 {
00398 activation_gain = 1.0;
00399 }
00400 else if (rel_delta < activation_buffer_region)
00401 {
00402 activation_gain = 0.5 * (1.0 + cos(M_PI * (rel_delta - activation_threshold) / (activation_buffer_region - activation_threshold)));
00403 }
00404 else
00405 {
00406 activation_gain = 0.0;
00407 }
00408
00409 if (activation_gain < 0.0)
00410 {
00411 activation_gain = 0.0;
00412 }
00413
00414 return activation_gain;
00415 }
00416
00418 template <typename T_PARAMS, typename PRIO>
00419 double JointLimitAvoidanceIneq<T_PARAMS, PRIO>::getSelfMotionMagnitude(const Eigen::MatrixXd& particular_solution, const Eigen::MatrixXd& homogeneous_solution) const
00420 {
00421 double factor;
00422 const ConstraintParams& params = this->constraint_params_.params_;
00423 if (this->abs_delta_max_ > this->abs_delta_min_ && this->rel_min_ > 0.0)
00424 {
00425 factor = (params.thresholds.activation * 1.1 / this->rel_min_) - 1.0;
00426 }
00427 else
00428 {
00429 if (this->rel_max_ > 0.0)
00430 {
00431 factor = (params.thresholds.activation * 1.1 / this->rel_max_) - 1.0;
00432 }
00433 else
00434 {
00435 factor = 1.0;
00436 }
00437 }
00438
00439 double k_H = factor * params.k_H;
00440 return k_H;
00441 }
00442
00444 template <typename T_PARAMS, typename PRIO>
00445 void JointLimitAvoidanceIneq<T_PARAMS, PRIO>::calcValue()
00446 {
00447 const LimiterParams& limiter_params = this->constraint_params_.limiter_params_;
00448 int32_t joint_idx = this->constraint_params_.joint_idx_;
00449 double limit_min = limiter_params.limits_min[joint_idx];
00450 double limit_max = limiter_params.limits_max[joint_idx];
00451
00452 double joint_pos = this->joint_states_.current_q_(joint_idx);
00453
00454 this->last_value_ = this->value_;
00455 this->value_ = (limit_max - joint_pos) * (joint_pos - limit_min);
00456 }
00457
00459 template <typename T_PARAMS, typename PRIO>
00460 void JointLimitAvoidanceIneq<T_PARAMS, PRIO>::calcDerivativeValue()
00461 {
00462 this->derivative_value_ = 0.1 * this->value_;
00463 }
00464
00466 template <typename T_PARAMS, typename PRIO>
00467 void JointLimitAvoidanceIneq<T_PARAMS, PRIO>::calcPartialValues()
00468 {
00469 const LimiterParams& limiter_params = this->constraint_params_.limiter_params_;
00470 int32_t joint_idx = this->constraint_params_.joint_idx_;
00471 double limit_min = limiter_params.limits_min[joint_idx];
00472 double limit_max = limiter_params.limits_max[joint_idx];
00473 double joint_pos = this->joint_states_.current_q_(joint_idx);
00474 Eigen::VectorXd partial_values = Eigen::VectorXd::Zero(this->jacobian_data_.cols());
00475
00476 partial_values(this->constraint_params_.joint_idx_) = -2.0 * joint_pos + limit_max + limit_min;
00477 this->partial_values_ = partial_values;
00478 }
00479
00480
00481 #endif // COB_TWIST_CONTROLLER_CONSTRAINTS_CONSTRAINT_JLA_IMPL_H