/ cartesian_controller_base / src / DampedLeastSquaresSolver.cpp
DampedLeastSquaresSolver.cpp
  1  ////////////////////////////////////////////////////////////////////////////////
  2  // Copyright 2019 FZI Research Center for Information Technology
  3  //
  4  // Redistribution and use in source and binary forms, with or without
  5  // modification, are permitted provided that the following conditions are met:
  6  //
  7  // 1. Redistributions of source code must retain the above copyright notice,
  8  // this list of conditions and the following disclaimer.
  9  //
 10  // 2. Redistributions in binary form must reproduce the above copyright notice,
 11  // this list of conditions and the following disclaimer in the documentation
 12  // and/or other materials provided with the distribution.
 13  //
 14  // 3. Neither the name of the copyright holder nor the names of its
 15  // contributors may be used to endorse or promote products derived from this
 16  // software without specific prior written permission.
 17  //
 18  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 19  // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 20  // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 21  // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 22  // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 23  // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 24  // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 25  // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 26  // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 27  // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 28  // POSSIBILITY OF SUCH DAMAGE.
 29  ////////////////////////////////////////////////////////////////////////////////
 30  
 31  //-----------------------------------------------------------------------------
 32  /*!\file    DampedLeastSquaresSolver.cpp
 33   *
 34   * \author  Stefan Scherzinger <scherzin@fzi.de>
 35   * \date    2020/03/27
 36   *
 37   */
 38  //-----------------------------------------------------------------------------
 39  
 40  #include <cartesian_controller_base/DampedLeastSquaresSolver.h>
 41  
 42  #include <pluginlib/class_list_macros.hpp>
 43  
 44  /**
 45   * \class cartesian_controller_base::DampedLeastSquaresSolver
 46   *
 47   * Users may explicitly specify this solver with \a "damped_least_squares" as \a
 48   * ik_solver in their controllers.yaml configuration file for each controller:
 49   *
 50   * \code{.yaml}
 51   * <name_of_your_controller>:
 52   *   ros__parameters:
 53   *     ik_solver: "damped_least_squares"
 54   *     ...
 55   *
 56   *     solver:
 57   *         ...
 58   *         damped_least_squares:
 59   *             alpha: 0.5
 60   * \endcode
 61   *
 62   */
 63  PLUGINLIB_EXPORT_CLASS(cartesian_controller_base::DampedLeastSquaresSolver,
 64                         cartesian_controller_base::IKSolver)
 65  
 66  namespace cartesian_controller_base
 67  {
 68  DampedLeastSquaresSolver::DampedLeastSquaresSolver() : m_alpha(0.001) {}
 69  
 70  DampedLeastSquaresSolver::~DampedLeastSquaresSolver() {}
 71  
 72  trajectory_msgs::msg::JointTrajectoryPoint DampedLeastSquaresSolver::getJointControlCmds(
 73    rclcpp::Duration period, const ctrl::Vector6D & net_force)
 74  {
 75    // Compute joint jacobian
 76    KDL::Twist twist;
 77    twist.vel.x(net_force(0));
 78    twist.vel.y(net_force(1));
 79    twist.vel.z(net_force(2));
 80    twist.rot.x(net_force(3));
 81    twist.rot.y(net_force(4));
 82    twist.rot.z(net_force(5));
 83  
 84    // Compute joint velocities according to:
 85    // \f$ \dot{q} = ( J^T J + \alpha^2 I )^{-1} J^T f \f$
 86    ctrl::MatrixND identity;
 87    identity.setIdentity(m_number_joints, m_number_joints);
 88    m_handle->get_parameter(m_params + ".alpha", m_alpha);
 89  
 90    m_current_velocities.data =
 91      (m_jnt_jacobian.data.transpose() * m_jnt_jacobian.data + m_alpha * m_alpha * identity)
 92        .inverse() *
 93      m_jnt_jacobian.data.transpose() * net_force;
 94  
 95    // Integrate once, starting with zero motion
 96    m_current_positions.data =
 97      m_last_positions.data + 0.5 * m_current_velocities.data * period.seconds();
 98  
 99    // Make sure positions stay in allowed margins
100    applyJointLimits();
101  
102    // Apply results
103    trajectory_msgs::msg::JointTrajectoryPoint control_cmd;
104    for (int i = 0; i < m_number_joints; ++i)
105    {
106      control_cmd.positions.push_back(m_current_positions(i));
107      control_cmd.velocities.push_back(m_current_velocities(i));
108  
109      // Accelerations should be left empty. Those values will be interpreted
110      // by most hardware joint drivers as max. tolerated values. As a
111      // consequence, the robot will move very slowly.
112    }
113    control_cmd.time_from_start = period;  // valid for this duration
114  
115    // Update for the next cycle
116    m_last_positions = m_current_positions;
117  
118    return control_cmd;
119  }
120  
121  bool DampedLeastSquaresSolver::init(std::shared_ptr<rclcpp_lifecycle::LifecycleNode> nh,
122                                      const KDL::Chain & chain,
123                                      const KDL::JntArray & upper_pos_limits,
124                                      const KDL::JntArray & lower_pos_limits)
125  {
126    IKSolver::init(nh, chain, upper_pos_limits, lower_pos_limits);
127  
128    m_jnt_jacobian_solver.reset(new KDL::ChainJntToJacSolver(m_chain));
129    m_jnt_jacobian.resize(m_number_joints);
130  
131    auto_declare(m_params + ".alpha", 1.0);
132  
133    return true;
134  }
135  
136  }  // namespace cartesian_controller_base