joint_impedance_example_controller.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017 Franka Emika GmbH
2 // Use of this source code is governed by the Apache-2.0 license, see LICENSE
4 
5 #include <cmath>
6 #include <memory>
7 
10 #include <ros/ros.h>
11 
12 #include <franka/robot_state.h>
13 
15 
17  ros::NodeHandle& node_handle) {
18  std::string arm_id;
19  if (!node_handle.getParam("arm_id", arm_id)) {
20  ROS_ERROR("JointImpedanceExampleController: Could not read parameter arm_id");
21  return false;
22  }
23  if (!node_handle.getParam("radius", radius_)) {
25  "JointImpedanceExampleController: No parameter radius, defaulting to: " << radius_);
26  }
27  if (std::fabs(radius_) < 0.005) {
28  ROS_INFO_STREAM("JointImpedanceExampleController: Set radius to small, defaulting to: " << 0.1);
29  radius_ = 0.1;
30  }
31 
32  if (!node_handle.getParam("vel_max", vel_max_)) {
34  "JointImpedanceExampleController: No parameter vel_max, defaulting to: " << vel_max_);
35  }
36  if (!node_handle.getParam("acceleration_time", acceleration_time_)) {
38  "JointImpedanceExampleController: No parameter acceleration_time, defaulting to: "
40  }
41 
42  std::vector<std::string> joint_names;
43  if (!node_handle.getParam("joint_names", joint_names) || joint_names.size() != 7) {
44  ROS_ERROR(
45  "JointImpedanceExampleController: Invalid or no joint_names parameters provided, aborting "
46  "controller init!");
47  return false;
48  }
49 
50  if (!node_handle.getParam("k_gains", k_gains_) || k_gains_.size() != 7) {
51  ROS_ERROR(
52  "JointImpedanceExampleController: Invalid or no k_gain parameters provided, aborting "
53  "controller init!");
54  return false;
55  }
56 
57  if (!node_handle.getParam("d_gains", d_gains_) || d_gains_.size() != 7) {
58  ROS_ERROR(
59  "JointImpedanceExampleController: Invalid or no d_gain parameters provided, aborting "
60  "controller init!");
61  return false;
62  }
63 
64  double publish_rate(30.0);
65  if (!node_handle.getParam("publish_rate", publish_rate)) {
66  ROS_INFO_STREAM("JointImpedanceExampleController: publish_rate not found. Defaulting to "
67  << publish_rate);
68  }
69  rate_trigger_ = franka_hw::TriggerRate(publish_rate);
70 
71  if (!node_handle.getParam("coriolis_factor", coriolis_factor_)) {
72  ROS_INFO_STREAM("JointImpedanceExampleController: coriolis_factor not found. Defaulting to "
73  << coriolis_factor_);
74  }
75 
76  auto* model_interface = robot_hw->get<franka_hw::FrankaModelInterface>();
77  if (model_interface == nullptr) {
79  "JointImpedanceExampleController: Error getting model interface from hardware");
80  return false;
81  }
82  try {
83  model_handle_ = std::make_unique<franka_hw::FrankaModelHandle>(
84  model_interface->getHandle(arm_id + "_model"));
87  "JointImpedanceExampleController: Exception getting model handle from interface: "
88  << ex.what());
89  return false;
90  }
91 
92  auto* cartesian_pose_interface = robot_hw->get<franka_hw::FrankaPoseCartesianInterface>();
93  if (cartesian_pose_interface == nullptr) {
95  "JointImpedanceExampleController: Error getting cartesian pose interface from hardware");
96  return false;
97  }
98  try {
99  cartesian_pose_handle_ = std::make_unique<franka_hw::FrankaCartesianPoseHandle>(
100  cartesian_pose_interface->getHandle(arm_id + "_robot"));
103  "JointImpedanceExampleController: Exception getting cartesian pose handle from interface: "
104  << ex.what());
105  return false;
106  }
107 
108  auto* effort_joint_interface = robot_hw->get<hardware_interface::EffortJointInterface>();
109  if (effort_joint_interface == nullptr) {
111  "JointImpedanceExampleController: Error getting effort joint interface from hardware");
112  return false;
113  }
114  for (size_t i = 0; i < 7; ++i) {
115  try {
116  joint_handles_.push_back(effort_joint_interface->getHandle(joint_names[i]));
119  "JointImpedanceExampleController: Exception getting joint handles: " << ex.what());
120  return false;
121  }
122  }
123  torques_publisher_.init(node_handle, "torque_comparison", 1);
124 
125  std::fill(dq_filtered_.begin(), dq_filtered_.end(), 0);
126 
127  return true;
128 }
129 
131  initial_pose_ = cartesian_pose_handle_->getRobotState().O_T_EE_d;
132 }
133 
135  const ros::Duration& period) {
136  if (vel_current_ < vel_max_) {
137  vel_current_ += period.toSec() * std::fabs(vel_max_ / acceleration_time_);
138  }
139  vel_current_ = std::fmin(vel_current_, vel_max_);
140 
141  angle_ += period.toSec() * vel_current_ / std::fabs(radius_);
142  if (angle_ > 2 * M_PI) {
143  angle_ -= 2 * M_PI;
144  }
145 
146  double delta_y = radius_ * (1 - std::cos(angle_));
147  double delta_z = radius_ * std::sin(angle_);
148 
149  std::array<double, 16> pose_desired = initial_pose_;
150  pose_desired[13] += delta_y;
151  pose_desired[14] += delta_z;
152  cartesian_pose_handle_->setCommand(pose_desired);
153 
154  franka::RobotState robot_state = cartesian_pose_handle_->getRobotState();
155  std::array<double, 7> coriolis = model_handle_->getCoriolis();
156  std::array<double, 7> gravity = model_handle_->getGravity();
157 
158  double alpha = 0.99;
159  for (size_t i = 0; i < 7; i++) {
160  dq_filtered_[i] = (1 - alpha) * dq_filtered_[i] + alpha * robot_state.dq[i];
161  }
162 
163  std::array<double, 7> tau_d_calculated;
164  for (size_t i = 0; i < 7; ++i) {
165  tau_d_calculated[i] = coriolis_factor_ * coriolis[i] +
166  k_gains_[i] * (robot_state.q_d[i] - robot_state.q[i]) +
167  d_gains_[i] * (robot_state.dq_d[i] - dq_filtered_[i]);
168  }
169 
170  // Maximum torque difference with a sampling rate of 1 kHz. The maximum torque rate is
171  // 1000 * (1 / sampling_time).
172  std::array<double, 7> tau_d_saturated = saturateTorqueRate(tau_d_calculated, robot_state.tau_J_d);
173 
174  for (size_t i = 0; i < 7; ++i) {
175  joint_handles_[i].setCommand(tau_d_saturated[i]);
176  }
177 
179  std::array<double, 7> tau_j = robot_state.tau_J;
180  std::array<double, 7> tau_error;
181  double error_rms(0.0);
182  for (size_t i = 0; i < 7; ++i) {
183  tau_error[i] = last_tau_d_[i] - tau_j[i];
184  error_rms += std::sqrt(std::pow(tau_error[i], 2.0)) / 7.0;
185  }
186  torques_publisher_.msg_.root_mean_square_error = error_rms;
187  for (size_t i = 0; i < 7; ++i) {
188  torques_publisher_.msg_.tau_commanded[i] = last_tau_d_[i];
189  torques_publisher_.msg_.tau_error[i] = tau_error[i];
190  torques_publisher_.msg_.tau_measured[i] = tau_j[i];
191  }
193  }
194 
195  for (size_t i = 0; i < 7; ++i) {
196  last_tau_d_[i] = tau_d_saturated[i] + gravity[i];
197  }
198 }
199 
201  const std::array<double, 7>& tau_d_calculated,
202  const std::array<double, 7>& tau_J_d) { // NOLINT (readability-identifier-naming)
203  std::array<double, 7> tau_d_saturated{};
204  for (size_t i = 0; i < 7; i++) {
205  double difference = tau_d_calculated[i] - tau_J_d[i];
206  tau_d_saturated[i] = tau_J_d[i] + std::max(std::min(difference, kDeltaTauMax), -kDeltaTauMax);
207  }
208  return tau_d_saturated;
209 }
210 
211 } // namespace franka_example_controllers
212 
std::string arm_id
std::unique_ptr< franka_hw::FrankaCartesianPoseHandle > cartesian_pose_handle_
void update(const ros::Time &, const ros::Duration &period) override
std::array< double, 7 > q_d
#define M_PI
std::array< std::string, 7 > joint_names
realtime_tools::RealtimePublisher< JointTorqueComparison > torques_publisher_
std::array< double, 7 > saturateTorqueRate(const std::array< double, 7 > &tau_d_calculated, const std::array< double, 7 > &tau_J_d)
std::array< double, 7 > q
std::array< double, 7 > dq
bool init(hardware_interface::RobotHW *robot_hw, ros::NodeHandle &node_handle) override
std::array< double, 7 > dq_d
void init(const ros::NodeHandle &node, const std::string &topic, int queue_size, bool latched=false)
#define ROS_INFO_STREAM(args)
std::array< double, 7 > tau_J_d
bool getParam(const std::string &key, std::string &s) const
PLUGINLIB_EXPORT_CLASS(moveit_fake_controller_manager::MoveItFakeControllerManager, moveit_controller_manager::MoveItControllerManager)
#define ROS_ERROR_STREAM(args)
#define ROS_ERROR(...)
std::array< double, 7 > tau_J


franka_example_controllers
Author(s): Franka Emika GmbH
autogenerated on Fri Oct 23 2020 03:47:17