cartesian_impedance_controller.cpp
Go to the documentation of this file.
1 /*
2 Reference:
3  https://github.com/frankaemika/franka_ros/blob/develop/franka_example_controllers/src/cartesian_impedance_example_controller.cpp
4 */
5 
7 
8 #include <cmath>
9 #include <memory>
10 
12 #include <franka/robot_state.h>
14 #include <ros/ros.h>
15 
17 #include <ros/console.h>
18 
19 namespace serl_franka_controllers {
20 
22  ros::NodeHandle& node_handle) {
23  std::vector<double> cartesian_stiffness_vector;
24  std::vector<double> cartesian_damping_vector;
25  publisher_franka_jacobian_.init(node_handle, "franka_jacobian", 1);
26 
27  sub_equilibrium_pose_ = node_handle.subscribe(
28  "equilibrium_pose", 20, &CartesianImpedanceController::equilibriumPoseCallback, this,
29  ros::TransportHints().reliable().tcpNoDelay());
30 
31  std::string arm_id;
32  if (!node_handle.getParam("arm_id", arm_id)) {
33  ROS_ERROR_STREAM("CartesianImpedanceController: Could not read parameter arm_id");
34  return false;
35  }
36  std::vector<std::string> joint_names;
37  if (!node_handle.getParam("joint_names", joint_names) || joint_names.size() != 7) {
38  ROS_ERROR(
39  "CartesianImpedanceController: Invalid or no joint_names parameters provided, "
40  "aborting controller init!");
41  return false;
42  }
43 
44  auto* model_interface = robot_hw->get<franka_hw::FrankaModelInterface>();
45  if (model_interface == nullptr) {
47  "CartesianImpedanceController: Error getting model interface from hardware");
48  return false;
49  }
50  try {
51  model_handle_ = std::make_unique<franka_hw::FrankaModelHandle>(
52  model_interface->getHandle(arm_id + "_model"));
55  "CartesianImpedanceController: Exception getting model handle from interface: "
56  << ex.what());
57  return false;
58  }
59 
60  auto* state_interface = robot_hw->get<franka_hw::FrankaStateInterface>();
61  if (state_interface == nullptr) {
63  "CartesianImpedanceController: Error getting state interface from hardware");
64  return false;
65  }
66  try {
67  state_handle_ = std::make_unique<franka_hw::FrankaStateHandle>(
68  state_interface->getHandle(arm_id + "_robot"));
71  "CartesianImpedanceController: Exception getting state handle from interface: "
72  << ex.what());
73  return false;
74  }
75 
76  auto* effort_joint_interface = robot_hw->get<hardware_interface::EffortJointInterface>();
77  if (effort_joint_interface == nullptr) {
79  "CartesianImpedanceController: Error getting effort joint interface from hardware");
80  return false;
81  }
82  for (size_t i = 0; i < 7; ++i) {
83  try {
84  joint_handles_.push_back(effort_joint_interface->getHandle(joint_names[i]));
87  "CartesianImpedanceController: Exception getting joint handles: " << ex.what());
88  return false;
89  }
90  }
91 
93  ros::NodeHandle(node_handle.getNamespace() + "dynamic_reconfigure_compliance_param_node");
94 
95  dynamic_server_compliance_param_ = std::make_unique<
96  dynamic_reconfigure::Server<serl_franka_controllers::compliance_paramConfig>>(
97 
100  boost::bind(&CartesianImpedanceController::complianceParamCallback, this, _1, _2));
101 
102  position_d_.setZero();
103  orientation_d_.coeffs() << 0.0, 0.0, 0.0, 1.0;
104  position_d_target_.setZero();
105  orientation_d_target_.coeffs() << 0.0, 0.0, 0.0, 1.0;
106 
107  cartesian_stiffness_.setZero();
108  cartesian_damping_.setZero();
109 
110  return true;
111 }
112 
114  // compute initial velocity with jacobian and set x_attractor and q_d_nullspace
115  // to initial configuration
116  franka::RobotState initial_state = state_handle_->getRobotState();
117  // get jacobian
118  std::array<double, 42> jacobian_array =
119  model_handle_->getZeroJacobian(franka::Frame::kEndEffector);
120  // convert to eigen
121  Eigen::Map<Eigen::Matrix<double, 7, 1>> q_initial(initial_state.q.data());
122  Eigen::Affine3d initial_transform(Eigen::Matrix4d::Map(initial_state.O_T_EE.data()));
123 
124  // set equilibrium point to current state
125  position_d_ = initial_transform.translation();
126  orientation_d_ = Eigen::Quaterniond(initial_transform.linear());
127  position_d_target_ = initial_transform.translation();
128  orientation_d_target_ = Eigen::Quaterniond(initial_transform.linear());
129 
130  // set nullspace equilibrium configuration to initial q
131  q_d_nullspace_ = q_initial;
132 }
133 
135  const ros::Duration& /*period*/) {
136  // get state variables
137  franka::RobotState robot_state = state_handle_->getRobotState();
138  std::array<double, 7> coriolis_array = model_handle_->getCoriolis();
140  model_handle_->getZeroJacobian(franka::Frame::kEndEffector);
141  publishZeroJacobian(time);
142  Eigen::Map<Eigen::Matrix<double, 7, 1>> coriolis(coriolis_array.data());
143  Eigen::Map<Eigen::Matrix<double, 6, 7>> jacobian(jacobian_array.data());
144  Eigen::Map<Eigen::Matrix<double, 7, 1>> q(robot_state.q.data());
145  Eigen::Map<Eigen::Matrix<double, 7, 1>> dq(robot_state.dq.data());
146  Eigen::Map<Eigen::Matrix<double, 7, 1>> tau_J_d( // NOLINT (readability-identifier-naming)
147  robot_state.tau_J_d.data());
148  Eigen::Affine3d transform(Eigen::Matrix4d::Map(robot_state.O_T_EE.data()));
149  Eigen::Vector3d position(transform.translation());
150  Eigen::Quaterniond orientation(transform.linear());
151 
152  // compute error to desired pose
153  // Clip translational error
154  error_.head(3) << position - position_d_;
155  for (int i = 0; i < 3; i++) {
156  error_(i) = std::min(std::max(error_(i), translational_clip_min_(i)), translational_clip_max_(i));
157  }
158 
159  // orientation error
160  if (orientation_d_.coeffs().dot(orientation.coeffs()) < 0.0) {
161  orientation.coeffs() << -orientation.coeffs();
162  }
163  // "difference" quaternion
164  Eigen::Quaterniond error_quaternion(orientation.inverse() * orientation_d_);
165  error_.tail(3) << error_quaternion.x(), error_quaternion.y(), error_quaternion.z();
166  // Transform to base frame
167  // Clip rotation error
168  error_.tail(3) << -transform.linear() * error_.tail(3);
169  for (int i = 0; i < 3; i++) {
170  error_(i+3) = std::min(std::max(error_(i+3), rotational_clip_min_(i)), rotational_clip_max_(i));
171  }
172 
173  error_i.head(3) << (error_i.head(3) + error_.head(3)).cwiseMax(-0.1).cwiseMin(0.1);
174  error_i.tail(3) << (error_i.tail(3) + error_.tail(3)).cwiseMax(-0.3).cwiseMin(0.3);
175 
176  // compute control
177  // allocate variables
178  Eigen::VectorXd tau_task(7), tau_nullspace(7), tau_d(7);
179 
180  // pseudoinverse for nullspace handling
181  // kinematic pseuoinverse
182  Eigen::MatrixXd jacobian_transpose_pinv;
183  pseudoInverse(jacobian.transpose(), jacobian_transpose_pinv);
184 
185  tau_task << jacobian.transpose() *
186  (-cartesian_stiffness_ * error_ - cartesian_damping_ * (jacobian * dq) - Ki_ * error_i);
187 
188  Eigen::Matrix<double, 7, 1> dqe;
189  Eigen::Matrix<double, 7, 1> qe;
190 
191  qe << q_d_nullspace_ - q;
192  qe.head(1) << qe.head(1) * joint1_nullspace_stiffness_;
193  dqe << dq;
194  dqe.head(1) << dqe.head(1) * 2.0 * sqrt(joint1_nullspace_stiffness_);
195  tau_nullspace << (Eigen::MatrixXd::Identity(7, 7) -
196  jacobian.transpose() * jacobian_transpose_pinv) *
197  (nullspace_stiffness_ * qe -
198  (2.0 * sqrt(nullspace_stiffness_)) * dqe);
199  // Desired torque
200  tau_d << tau_task + tau_nullspace + coriolis;
201  // Saturate torque rate to avoid discontinuities
202  tau_d << saturateTorqueRate(tau_d, tau_J_d);
203 
204  for (size_t i = 0; i < 7; ++i) {
205  joint_handles_[i].setCommand(tau_d(i));
206  }
207 
208  // update parameters changed online either through dynamic reconfigure or through the interactive
209  // target by filtering
221 }
222 
225  for (size_t i = 0; i < jacobian_array.size(); i++) {
226  publisher_franka_jacobian_.msg_.zero_jacobian[i] = jacobian_array[i];
227  }
229  }
230 }
231 
232 
234  const Eigen::Matrix<double, 7, 1>& tau_d_calculated,
235  const Eigen::Matrix<double, 7, 1>& tau_J_d) { // NOLINT (readability-identifier-naming)
236  Eigen::Matrix<double, 7, 1> tau_d_saturated{};
237  for (size_t i = 0; i < 7; i++) {
238  double difference = tau_d_calculated[i] - tau_J_d[i];
239  tau_d_saturated[i] =
240  tau_J_d[i] + std::max(std::min(difference, delta_tau_max_), -delta_tau_max_);
241  }
242  return tau_d_saturated;
243 }
244 
246  serl_franka_controllers::compliance_paramConfig& config,
247  uint32_t /*level*/) {
248  cartesian_stiffness_target_.setIdentity();
249  cartesian_stiffness_target_.topLeftCorner(3, 3)
250  << config.translational_stiffness * Eigen::Matrix3d::Identity();
251  cartesian_stiffness_target_.bottomRightCorner(3, 3)
252  << config.rotational_stiffness * Eigen::Matrix3d::Identity();
253  cartesian_damping_target_.setIdentity();
254  // Damping ratio = 1
255  cartesian_damping_target_.topLeftCorner(3, 3)
256  << config.translational_damping * Eigen::Matrix3d::Identity();
257  cartesian_damping_target_.bottomRightCorner(3, 3)
258  << config.rotational_damping * Eigen::Matrix3d::Identity();
259 
260  nullspace_stiffness_target_ = config.nullspace_stiffness;
261  joint1_nullspace_stiffness_target_ = config.joint1_nullspace_stiffness;
262 
263  translational_clip_min_ << -config.translational_clip_neg_x, -config.translational_clip_neg_y, -config.translational_clip_neg_z;
264  translational_clip_max_ << config.translational_clip_x, config.translational_clip_y, config.translational_clip_z;
265  rotational_clip_min_ << -config.rotational_clip_neg_x, -config.rotational_clip_neg_y, -config.rotational_clip_neg_z;
266  rotational_clip_max_ << config.rotational_clip_x, config.rotational_clip_y, config.rotational_clip_z;
267 
268  Ki_target_.setIdentity();
269  Ki_target_.topLeftCorner(3, 3)
270  << config.translational_Ki * Eigen::Matrix3d::Identity();
271  Ki_target_.bottomRightCorner(3, 3)
272  << config.rotational_Ki * Eigen::Matrix3d::Identity();
273 }
274 
276  const geometry_msgs::PoseStampedConstPtr& msg) {
277  position_d_target_ << msg->pose.position.x, msg->pose.position.y, msg->pose.position.z;
278  error_i.setZero();
279  Eigen::Quaterniond last_orientation_d_target(orientation_d_target_);
280  orientation_d_target_.coeffs() << msg->pose.orientation.x, msg->pose.orientation.y,
281  msg->pose.orientation.z, msg->pose.orientation.w;
282  if (last_orientation_d_target.coeffs().dot(orientation_d_target_.coeffs()) < 0.0) {
283  orientation_d_target_.coeffs() << -orientation_d_target_.coeffs();
284  }
285 }
286 
287 } // namespace serl_franka_controllers
288 
serl_franka_controllers
Definition: cartesian_impedance_controller.h:25
PLUGINLIB_EXPORT_CLASS
PLUGINLIB_EXPORT_CLASS(moveit_fake_controller_manager::MoveItFakeControllerManager, moveit_controller_manager::MoveItControllerManager)
serl_franka_controllers::CartesianImpedanceController::publishZeroJacobian
void publishZeroJacobian(const ros::Time &time)
Definition: cartesian_impedance_controller.cpp:223
serl_franka_controllers::CartesianImpedanceController::cartesian_stiffness_target_
Eigen::Matrix< double, 6, 6 > cartesian_stiffness_target_
Definition: cartesian_impedance_controller.h:54
cartesian_impedance_controller.h
serl_franka_controllers::CartesianImpedanceController::joint_handles_
std::vector< hardware_interface::JointHandle > joint_handles_
Definition: cartesian_impedance_controller.h:44
serl_franka_controllers::CartesianImpedanceController::publisher_franka_jacobian_
realtime_tools::RealtimePublisher< serl_franka_controllers::ZeroJacobian > publisher_franka_jacobian_
Definition: cartesian_impedance_controller.h:80
serl_franka_controllers::CartesianImpedanceController::rotational_clip_min_
Eigen::Matrix< double, 3, 1 > rotational_clip_min_
Definition: cartesian_impedance_controller.h:63
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(args)
serl_franka_controllers::CartesianImpedanceController::jacobian_array
std::array< double, 42 > jacobian_array
Definition: cartesian_impedance_controller.h:45
pseudo_inversion.h
hardware_interface::HardwareInterfaceException::what
const char * what() const noexcept override
hardware_interface::InterfaceManager::get
T * get()
ros::NodeHandle::getParam
bool getParam(const std::string &key, bool &b) const
ros.h
serl_franka_controllers::CartesianImpedanceController::sub_equilibrium_pose_
ros::Subscriber sub_equilibrium_pose_
Definition: cartesian_impedance_controller.h:83
serl_franka_controllers::CartesianImpedanceController::complianceParamCallback
void complianceParamCallback(serl_franka_controllers::compliance_paramConfig &config, uint32_t level)
Definition: cartesian_impedance_controller.cpp:245
serl_franka_controllers::CartesianImpedanceController::error_
Eigen::Matrix< double, 6, 1 > error_
Definition: cartesian_impedance_controller.h:67
ros::TransportHints
serl_franka_controllers::CartesianImpedanceController::equilibriumPoseCallback
void equilibriumPoseCallback(const geometry_msgs::PoseStampedConstPtr &msg)
Definition: cartesian_impedance_controller.cpp:275
serl_franka_controllers::CartesianImpedanceController::rotational_clip_max_
Eigen::Matrix< double, 3, 1 > rotational_clip_max_
Definition: cartesian_impedance_controller.h:64
realtime_tools::RealtimePublisher::init
void init(const ros::NodeHandle &node, const std::string &topic, int queue_size, bool latched=false)
serl_franka_controllers::CartesianImpedanceController::joint1_nullspace_stiffness_target_
double joint1_nullspace_stiffness_target_
Definition: cartesian_impedance_controller.h:51
transform
template Halfspace< double > transform(const Halfspace< double > &a, const Transform3< double > &tf)
serl_franka_controllers::CartesianImpedanceController::cartesian_damping_target_
Eigen::Matrix< double, 6, 6 > cartesian_damping_target_
Definition: cartesian_impedance_controller.h:56
serl_franka_controllers::CartesianImpedanceController::joint1_nullspace_stiffness_
double joint1_nullspace_stiffness_
Definition: cartesian_impedance_controller.h:50
serl_franka_controllers::CartesianImpedanceController::Ki_
Eigen::Matrix< double, 6, 6 > Ki_
Definition: cartesian_impedance_controller.h:57
class_list_macros.h
controller_interface::ControllerBase
console.h
serl_franka_controllers::CartesianImpedanceController::Ki_target_
Eigen::Matrix< double, 6, 6 > Ki_target_
Definition: cartesian_impedance_controller.h:58
serl_franka_controllers::CartesianImpedanceController::q_d_nullspace_
Eigen::Matrix< double, 7, 1 > q_d_nullspace_
Definition: cartesian_impedance_controller.h:65
realtime_tools::RealtimePublisher::unlockAndPublish
void unlockAndPublish()
hardware_interface::RobotHW
controller_base.h
serl_franka_controllers::CartesianImpedanceController::delta_tau_max_
const double delta_tau_max_
Definition: cartesian_impedance_controller.h:52
serl_franka_controllers::CartesianImpedanceController::position_d_target_
Eigen::Vector3d position_d_target_
Definition: cartesian_impedance_controller.h:70
arm_id
std::string arm_id
ROS_ERROR
#define ROS_ERROR(...)
realtime_tools::RealtimePublisher::msg_
Msg msg_
serl_franka_controllers::CartesianImpedanceController::translational_clip_max_
Eigen::Matrix< double, 3, 1 > translational_clip_max_
Definition: cartesian_impedance_controller.h:62
serl_franka_controllers::CartesianImpedanceController
Definition: cartesian_impedance_controller.h:27
serl_franka_controllers::CartesianImpedanceController::nullspace_stiffness_
double nullspace_stiffness_
Definition: cartesian_impedance_controller.h:48
franka_hw::FrankaStateInterface
hardware_interface::EffortJointInterface
realtime_tools::RealtimePublisher::trylock
bool trylock()
serl_franka_controllers::CartesianImpedanceController::orientation_d_
Eigen::Quaterniond orientation_d_
Definition: cartesian_impedance_controller.h:69
ros::NodeHandle::subscribe
Subscriber subscribe(const std::string &topic, uint32_t queue_size, const boost::function< void(C)> &callback, const VoidConstPtr &tracked_object=VoidConstPtr(), const TransportHints &transport_hints=TransportHints())
serl_franka_controllers::CartesianImpedanceController::dynamic_reconfigure_compliance_param_node_
ros::NodeHandle dynamic_reconfigure_compliance_param_node_
Definition: cartesian_impedance_controller.h:76
q
q
serl_franka_controllers::CartesianImpedanceController::starting
void starting(const ros::Time &) override
Definition: cartesian_impedance_controller.cpp:113
serl_franka_controllers::CartesianImpedanceController::error_i
Eigen::Matrix< double, 6, 1 > error_i
Definition: cartesian_impedance_controller.h:68
franka_hw::FrankaModelInterface
hardware_interface::HardwareInterfaceException
serl_franka_controllers::CartesianImpedanceController::dynamic_server_compliance_param_
std::unique_ptr< dynamic_reconfigure::Server< serl_franka_controllers::compliance_paramConfig > > dynamic_server_compliance_param_
Definition: cartesian_impedance_controller.h:75
serl_franka_controllers::CartesianImpedanceController::cartesian_stiffness_
Eigen::Matrix< double, 6, 6 > cartesian_stiffness_
Definition: cartesian_impedance_controller.h:53
serl_franka_controllers::CartesianImpedanceController::init
bool init(hardware_interface::RobotHW *robot_hw, ros::NodeHandle &node_handle) override
Definition: cartesian_impedance_controller.cpp:21
ros::Time
joint_names
std::array< std::string, 7 > joint_names
serl_franka_controllers::CartesianImpedanceController::saturateTorqueRate
Eigen::Matrix< double, 7, 1 > saturateTorqueRate(const Eigen::Matrix< double, 7, 1 > &tau_d_calculated, const Eigen::Matrix< double, 7, 1 > &tau_J_d)
Definition: cartesian_impedance_controller.cpp:233
serl_franka_controllers::CartesianImpedanceController::orientation_d_target_
Eigen::Quaterniond orientation_d_target_
Definition: cartesian_impedance_controller.h:71
serl_franka_controllers::CartesianImpedanceController::update
void update(const ros::Time &, const ros::Duration &period) override
Definition: cartesian_impedance_controller.cpp:134
ros::NodeHandle::getNamespace
const std::string & getNamespace() const
serl_franka_controllers::CartesianImpedanceController::translational_clip_min_
Eigen::Matrix< double, 3, 1 > translational_clip_min_
Definition: cartesian_impedance_controller.h:61
serl_franka_controllers::CartesianImpedanceController::state_handle_
std::unique_ptr< franka_hw::FrankaStateHandle > state_handle_
Definition: cartesian_impedance_controller.h:42
ros::Duration
config
config
serl_franka_controllers::CartesianImpedanceController::cartesian_damping_
Eigen::Matrix< double, 6, 6 > cartesian_damping_
Definition: cartesian_impedance_controller.h:55
serl_franka_controllers::CartesianImpedanceController::position_d_
Eigen::Vector3d position_d_
Definition: cartesian_impedance_controller.h:66
ros::NodeHandle
serl_franka_controllers::CartesianImpedanceController::filter_params_
double filter_params_
Definition: cartesian_impedance_controller.h:47
serl_franka_controllers::pseudoInverse
void pseudoInverse(const Eigen::MatrixXd &M_, Eigen::MatrixXd &M_pinv_, bool damped=true)
Definition: pseudo_inversion.h:16
serl_franka_controllers::CartesianImpedanceController::model_handle_
std::unique_ptr< franka_hw::FrankaModelHandle > model_handle_
Definition: cartesian_impedance_controller.h:43
serl_franka_controllers::CartesianImpedanceController::nullspace_stiffness_target_
double nullspace_stiffness_target_
Definition: cartesian_impedance_controller.h:49


serl_franka_controllers
Author(s): Jianlan Luo, Charles Xu
autogenerated on Fri Feb 9 2024 03:09:57