stack_of_tasks_solver.cpp
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 #include <set>
19 
22 
23 Eigen::MatrixXd StackOfTasksSolver::solve(const Vector6d_t& in_cart_velocities,
24  const JointStates& joint_states)
25 {
28  double cycle = (now - this->last_time_).toSec();
29  this->last_time_ = now;
30 
31  Eigen::MatrixXd damped_pinv = pinv_calc_.calculate(this->params_, this->damping_, this->jacobian_data_);
32  Eigen::MatrixXd pinv = pinv_calc_.calculate(this->jacobian_data_);
33 
34  Eigen::MatrixXd particular_solution = damped_pinv * in_cart_velocities;
35 
36  Eigen::MatrixXd ident = Eigen::MatrixXd::Identity(pinv.rows(), this->jacobian_data_.cols());
37  Eigen::MatrixXd projector = ident - pinv * this->jacobian_data_;
38 
39  Eigen::MatrixXd projector_i = Eigen::MatrixXd::Identity(this->jacobian_data_.cols(), this->jacobian_data_.cols());
40  Eigen::VectorXd q_i = Eigen::VectorXd::Zero(this->jacobian_data_.cols());
41  Eigen::MatrixXd qdots_out = Eigen::MatrixXd::Zero(this->jacobian_data_.cols(), 1);
42 
43  Eigen::VectorXd sum_of_gradient = Eigen::VectorXd::Zero(this->jacobian_data_.cols());
44 
45  KDL::JntArrayVel predict_jnts_vel(joint_states.current_q_.rows());
46 
47  // predict next joint states!
48  for (int i = 0; i < joint_states.current_q_.rows(); ++i)
49  {
50  predict_jnts_vel.q(i) = particular_solution(i, 0) * cycle + joint_states.current_q_(i);
51  predict_jnts_vel.qdot(i) = particular_solution(i, 0);
52  }
53 
54  // First iteration: update constraint state and calculate the according GPM weighting (DANGER state)
55  double inv_sum_of_prionums = 0.0;
56  for (std::set<ConstraintBase_t>::iterator it = this->constraints_.begin(); it != this->constraints_.end(); ++it)
57  {
58  (*it)->update(joint_states, predict_jnts_vel, this->jacobian_data_);
59  const double constr_prio = (*it)->getPriorityAsNum();
60  if ((*it)->getState().getCurrent() == DANGER)
61  {
62  inv_sum_of_prionums += constr_prio > ZERO_THRESHOLD ? 1.0 / constr_prio : 1.0 / DIV0_SAFE;
63  }
64  }
65 
66  // Second iteration: Process constraints with sum of prios for active GPM constraints!
67  for (std::set<ConstraintBase_t>::iterator it = this->constraints_.begin(); it != this->constraints_.end(); ++it)
68  {
69  this->processState(it, projector, particular_solution, inv_sum_of_prionums, sum_of_gradient);
70  }
71 
72  sum_of_gradient = this->params_.k_H * sum_of_gradient; // "global" weighting for all constraints.
73 
75  {
77  }
78  else
79  {
80  this->in_cart_vel_damping_ = this->in_cart_vel_damping_ > 1.0 ? (this->in_cart_vel_damping_ - 1.0) : 1.0;
81  }
82 
83  const Vector6d_t scaled_in_cart_velocities = (1.0 / pow(this->in_cart_vel_damping_, 2.0)) * in_cart_velocities;
84  Task_t t(this->params_.priority_main, "Main task", this->jacobian_data_, scaled_in_cart_velocities);
85  t.tcp_ = this->params_;
87 
88  // ROS_INFO_STREAM("============== Task output ============= with main task damping: " << this->in_cart_vel_damping_);
91  {
92  Eigen::MatrixXd J_task = it->task_jacobian_;
93  Eigen::MatrixXd J_temp = J_task * projector_i;
94  Eigen::VectorXd v_task = it->task_;
95  Eigen::MatrixXd J_temp_inv = pinv_calc_.calculate(J_temp); //ToDo: Do we need damping here?
96  q_i = q_i + J_temp_inv * (v_task - J_task * q_i);
97  projector_i = projector_i - J_temp_inv * J_temp;
98  }
99 
100  qdots_out.col(0) = q_i + projector_i * sum_of_gradient;
101  return qdots_out;
102 }
103 
104 
105 void StackOfTasksSolver::processState(std::set<ConstraintBase_t>::iterator& it,
106  const Eigen::MatrixXd& projector,
107  const Eigen::MatrixXd& particular_solution,
108  double inv_sum_of_prios,
109  Eigen::VectorXd& sum_of_gradient)
110 {
111  Eigen::VectorXd q_dot_0 = (*it)->getPartialValues();
112  const double activation_gain = (*it)->getActivationGain();
113  Eigen::MatrixXd tmp_projection = projector * q_dot_0;
114  const double magnitude = (*it)->getSelfMotionMagnitude(particular_solution, tmp_projection);
115  ConstraintState cstate = (*it)->getState();
116 
117  const double constr_prio = (*it)->getPriorityAsNum();
118  const double inv_constr_prio = constr_prio > ZERO_THRESHOLD ? 1.0 / constr_prio : 1.0 / DIV0_SAFE;
119  // only necessary for GPM sum because task stack is already sorted according to PRIOs.
120  const double gpm_weighting = inv_constr_prio / inv_sum_of_prios;
121 
122  if (cstate.isTransition())
123  {
124  if (cstate.getCurrent() == CRITICAL)
125  {
126  // "global" weighting k_H for all constraint tasks.
127  Task_t t = (*it)->createTask();
128  double factor = activation_gain * std::abs(magnitude);
129  t.task_ = factor * t.task_;
131  this->task_stack_controller_.activateTask((*it)->getTaskId());
132  }
133  else if (cstate.getCurrent() == DANGER)
134  {
135  this->task_stack_controller_.deactivateTask((*it)->getTaskId());
136  sum_of_gradient += gpm_weighting * activation_gain * magnitude * q_dot_0; // smm adapted q_dot_0 vector
137  }
138  else
139  {
140  this->task_stack_controller_.deactivateTask((*it)->getTaskId());
141  }
142  }
143  else
144  {
145  if (cstate.getCurrent() == CRITICAL)
146  {
147  Task_t t = (*it)->createTask();
148  double factor = activation_gain * std::abs(magnitude); // task must be decided whether negative or not!
149  t.task_ = factor * t.task_;
151  }
152  else if (cstate.getCurrent() == DANGER)
153  {
154  sum_of_gradient += gpm_weighting * activation_gain * magnitude * q_dot_0; // smm adapted q_dot_0 vector
155  }
156  else
157  {
158  // just compute the particular solution
159  }
160  }
161 
162  if (cstate.getCurrent() > this->global_constraint_state_ )
163  {
164  this->global_constraint_state_ = cstate.getCurrent();
165  }
166 }
EN_ConstraintStates global_constraint_state_
double now()
EN_ConstraintStates getCurrent() const
unsigned int rows() const
boost::shared_ptr< DampingBase > damping_
References the current Jacobian (matrix data only).
Eigen::Matrix< double, 6, 1 > Vector6d_t
Matrix6Xd_t jacobian_data_
References the limiter parameters (up-to-date according to KinematicExtension).
virtual Eigen::MatrixXd solve(const Vector6d_t &in_cart_velocities, const JointStates &joint_states)
void processState(std::set< ConstraintBase_t >::iterator &it, const Eigen::MatrixXd &projector, const Eigen::MatrixXd &particular_solution, double inv_sum_of_prios, Eigen::VectorXd &sum_of_gradient)
TwistControllerParams tcp_
void addTask(Task< PRIO > t)
geometry_msgs::TransformStamped t
void activateTask(std::string task_id)
PInvBySVD pinv_calc_
The currently set damping method.
std::vector< Task< PRIO > >::iterator getTasksEnd()
const TwistControllerParams & params_
Set of constraints.
void deactivateTask(typename std::vector< Task< PRIO > >::iterator it)
std::set< ConstraintBase_t > constraints_
set inserts sorted (default less operator); if element has already been added it returns an iterator ...
std::vector< Task< PRIO > >::iterator beginTaskIter()
virtual Eigen::MatrixXd calculate(const Eigen::MatrixXd &jacobian) const
std::vector< Task< PRIO > >::iterator nextActiveTask()
#define START_CNT
INLINE Rall1d< T, V, S > pow(const Rall1d< T, V, S > &arg, double m)
static Time now()
TaskStackController_t & task_stack_controller_
An instance that helps solving the inverse of the Jacobian.
#define ZERO_THRESHOLD
Eigen::VectorXd task_
std::vector< Task_t >::iterator TaskSetIter_t


cob_twist_controller
Author(s): Felix Messmer , Marco Bezzon , Christoph Mark , Francisco Moreno
autogenerated on Thu Apr 8 2021 02:40:00