cartesian_controller_base.h
  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    cartesian_controller_base.h
 33   *
 34   * \author  Stefan Scherzinger <scherzin@fzi.de>
 35   * \date    2017/07/27
 36   *
 37   */
 38  //-----------------------------------------------------------------------------
 39  
 40  #ifndef CARTESIAN_CONTROLLER_BASE_H_INCLUDED
 41  #define CARTESIAN_CONTROLLER_BASE_H_INCLUDED
 42  
 43  #include <cartesian_controller_base/IKSolver.h>
 44  #include <cartesian_controller_base/SpatialPDController.h>
 45  #include <cartesian_controller_base/Utility.h>
 46  #include <realtime_tools/realtime_publisher.h>
 47  
 48  #include <controller_interface/controller_interface.hpp>
 49  #include <functional>
 50  #include <geometry_msgs/msg/pose_stamped.hpp>
 51  #include <geometry_msgs/msg/twist_stamped.hpp>
 52  #include <geometry_msgs/msg/wrench_stamped.hpp>
 53  #include <hardware_interface/loaned_command_interface.hpp>
 54  #include <hardware_interface/loaned_state_interface.hpp>
 55  #include <kdl/treefksolverpos_recursive.hpp>
 56  #include <memory>
 57  #include <pluginlib/class_loader.hpp>
 58  #include <rclcpp/rclcpp.hpp>
 59  #include <string>
 60  #include <trajectory_msgs/msg/joint_trajectory_point.hpp>
 61  #include <vector>
 62  
 63  #include "ROS2VersionConfig.h"
 64  #include "rclcpp_lifecycle/lifecycle_node.hpp"
 65  
 66  namespace cartesian_controller_base
 67  {
 68  /**
 69   * @brief Base class for each cartesian controller
 70   *
 71   * This class implements a common forward dynamics based solver for Cartesian
 72   * end effector error correction. Different child class controllers will define
 73   * what this error represents and should call \ref computeJointControlCmds with
 74   * that error.  The control commands are sent to the hardware with \ref
 75   * writeJointControlCmds.
 76   *
 77   */
 78  class CartesianControllerBase : public controller_interface::ControllerInterface
 79  {
 80  public:
 81    CartesianControllerBase();
 82    virtual ~CartesianControllerBase(){};
 83  
 84    virtual controller_interface::InterfaceConfiguration command_interface_configuration()
 85      const override;
 86  
 87    virtual controller_interface::InterfaceConfiguration state_interface_configuration()
 88      const override;
 89  
 90    virtual LifecycleNodeInterface::CallbackReturn on_init() override;
 91  
 92    rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn on_configure(
 93      const rclcpp_lifecycle::State & previous_state) override;
 94  
 95    rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn on_activate(
 96      const rclcpp_lifecycle::State & previous_state) override;
 97  
 98    rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn on_deactivate(
 99      const rclcpp_lifecycle::State & previous_state) override;
100  
101    rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn on_shutdown(
102      const rclcpp_lifecycle::State & previous_state) override;
103  
104  protected:
105    /**
106       * @brief Write joint control commands to the real hardware
107       *
108       * Depending on the hardware interface used, this is either joint positions
109       * or velocities.
110       */
111    void writeJointControlCmds();
112  
113    /**
114       * @brief Compute one control step using forward dynamics simulation
115       *
116       * Check \ref ForwardDynamicsSolver for details.
117       *
118       * @param error The error to minimize
119       * @param period The period for this control cycle
120       */
121    void computeJointControlCmds(const ctrl::Vector6D & error, const rclcpp::Duration & period);
122  
123    /**
124       * @brief Display the given vector in the given robot base link
125       *
126       * @param vector The quantity to transform
127       * @param from The reference frame where the quantity was formulated
128       *
129       * @return The quantity in the robot base frame
130       */
131    ctrl::Vector6D displayInBaseLink(const ctrl::Vector6D & vector, const std::string & from);
132  
133    /**
134       * @brief Display the given tensor in the robot base frame
135       *
136       * @param tensor The quantity to transform
137       * @param from The reference frame where the quantity was formulated
138       *
139       * @return The quantity in the robot base frame
140       */
141    ctrl::Matrix6D displayInBaseLink(const ctrl::Matrix6D & tensor, const std::string & from);
142  
143    /**
144       * @brief Display a given vector in a new reference frame
145       *
146       * The vector is assumed to be given in the robot base frame.
147       *
148       * @param vector The quantity to transform
149       * @param to The reference frame in which to formulate the quantity
150       *
151       * @return The quantity in the new frame
152       */
153    ctrl::Vector6D displayInTipLink(const ctrl::Vector6D & vector, const std::string & to);
154  
155    /**
156       * @brief Check if specified links are part of the robot chain
157       *
158       * @param s Link to check for existence
159       *
160       * @return True if existent, false otherwise
161       */
162    bool robotChainContains(const std::string & s)
163    {
164      for (const auto & segment : this->m_robot_chain.segments)
165      {
166        if (segment.getName() == s)
167        {
168          return true;
169        }
170      }
171      return false;
172    }
173  
174    /**
175     * @brief Helper method to check the controller's state during input callbacks
176     *
177     * @return True if the controller is active, false otherwise
178     */
179    bool isActive() const { return m_active; };
180  
181    KDL::Chain m_robot_chain;
182  
183    std::shared_ptr<KDL::TreeFkSolverPos_recursive> m_forward_kinematics_solver;
184  
185    /**
186       * @brief Allow users to choose the IK solver type on startup
187       */
188    std::shared_ptr<pluginlib::ClassLoader<IKSolver>> m_solver_loader;
189    std::shared_ptr<IKSolver> m_ik_solver;
190  
191    // Dynamic parameters
192    std::string m_end_effector_link;
193    std::string m_robot_base_link;
194    int m_iterations;
195  
196    std::vector<std::reference_wrapper<hardware_interface::LoanedStateInterface>>
197      m_joint_state_pos_handles;
198  
199  protected:
200    /**
201       * @brief Stop joint motion when in velocity control
202       */
203    void stopCurrentMotion()
204    {
205      for (size_t i = 0; i < m_joint_cmd_vel_handles.size(); ++i)
206      {
207        m_joint_cmd_vel_handles[i].get().set_value(0.0);
208      }
209    }
210  
211    /**
212       * @brief Publish the controller's end-effector pose and twist
213       *
214       * The data are w.r.t. the specified robot base link.
215       * If this function is called after `computeJointControlCmds()` has
216       * been called, then the controller's internal state represents the state
217       * right after the error computation, and corresponds to the new target
218       * state that will be send to the actuators in this control cycle.
219       */
220    void publishStateFeedback();
221  
222    realtime_tools::RealtimePublisherSharedPtr<geometry_msgs::msg::PoseStamped>
223      m_feedback_pose_publisher;
224    realtime_tools::RealtimePublisherSharedPtr<geometry_msgs::msg::TwistStamped>
225      m_feedback_twist_publisher;
226  
227    std::vector<std::string> m_cmd_interface_types;
228    std::vector<std::reference_wrapper<hardware_interface::LoanedCommandInterface>>
229      m_joint_cmd_pos_handles;
230    std::vector<std::reference_wrapper<hardware_interface::LoanedCommandInterface>>
231      m_joint_cmd_vel_handles;
232  
233    std::vector<std::string> m_joint_names;
234    trajectory_msgs::msg::JointTrajectoryPoint m_simulated_joint_motion;
235    SpatialPDController m_spatial_controller;
236    ctrl::Vector6D m_cartesian_input;
237  
238    // Against multi initialization in multi inheritance scenarios
239    bool m_initialized = {false};
240    bool m_configured = {false};
241    bool m_active = {false};
242  
243    // Dynamic parameters
244    double m_error_scale;
245    std::string m_robot_description;
246  };
247  
248  }  // namespace cartesian_controller_base
249  
250  #endif