constraint_jla_impl.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *   http://www.apache.org/licenses/LICENSE-2.0
00009 
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
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 /* BEGIN JointLimitAvoidance ************************************************************************************/
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     // Compute prediction
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);  // always highest task -> avoid HW destruction.
00106     }
00107     else
00108     {
00109         this->state_.setState(DANGER);  // always active task -> avoid HW destruction.
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 /* END JointLimitAvoidance **************************************************************************************/
00195 
00196 /* BEGIN JointLimitAvoidanceMid ************************************************************************************/
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)  // max limiting the arm joints but not the extensions.
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         // Liegeois method can also be found in Chan paper ISSN 1042-296X [Page 288]
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 /* END JointLimitAvoidanceMid ************************************************************************************/
00299 
00300 /* BEGIN JointLimitAvoidanceIneq ************************************************************************************/
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     // Compute prediction
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);  // GPM always active!
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         // nearer to max limit
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 /* END JointLimitAvoidanceIneq **************************************************************************************/
00480 
00481 #endif  // COB_TWIST_CONTROLLER_CONSTRAINTS_CONSTRAINT_JLA_IMPL_H


cob_twist_controller
Author(s): Felix Messmer , Marco Bezzon , Christoph Mark , Francisco Moreno
autogenerated on Thu Jun 6 2019 21:19:26