Skip to content

Commit 5f1d1bc

Browse files
committed
feat: enhance Kuka Cartesian Impedance Controller with CLIK and update README
2 parents 8669d91 + 6f79522 commit 5f1d1bc

File tree

6 files changed

+170
-294
lines changed

6 files changed

+170
-294
lines changed

README.md

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,75 @@
1+
# Kuka Cartesian Impedance Controller
12
![build badge](https://github.com/lucabeber/effort_controller/actions/workflows/humble.yml/badge.svg)
23
![build badge](https://github.com/lucabeber/effort_controller/actions/workflows/jazzy.yml/badge.svg)
34
![build badge](https://github.com/lucabeber/effort_controller/actions/workflows/rolling.yml/badge.svg)
45

56

67
This branch implements command the joint configuration to the [lbr_stack](https://github.com/idra-lab/lbr_fri_ros2_stack) KUKA hardware interface so it allows `Cartesian Impedance Control` as well as `Joint Position Control` depending on the command input chosen as `client_command_mode` in the hardware interface.
78

8-
Check out their use in the KUKA LBR example [here](https://github.com/idra-lab/kuka_impedance)!
9+
This controller is designed to be used with the KUKA FRI in `POSITION` command mode. To switch FRI Command Mode you need to update the following line in the `LBRServer.java` application, chosing between the two controller.
10+
```
11+
% for cartesian impedance control
12+
control_mode_ = new CartesianImpedanceControlMode(0, 0, 0, 0, 0, 0, 0);
13+
```
14+
```
15+
% for cartesian impedance control
16+
control_mode_ = new PositionControlMode();
17+
```
918

19+
|Supported Controller Options| FRI Command Mode | FRI Controller Mode |
20+
|----------------------------|--------------------|--------------------------------|
21+
|Cartesian Impedance Control |`POSITION` | `CartesianImpedanceControlMode`|
22+
|Kinematics control |`POSITION` | `PositionControlMode` |
23+
24+
Check out how to use this controller in our KUKA LBR example [here](https://github.com/idra-lab/kuka_impedance)!
1025
The structure of the code and some libraries have been taken from the repo [Cartesian Controllers](https://github.com/fzi-forschungszentrum-informatik/cartesian_controllers).
26+
27+
28+
#### Parameters:
29+
Below is an example `controller_manager.yaml` for a controller specific configuration.
30+
31+
```yaml
32+
controller_manager:
33+
ros__parameters:
34+
update_rate: 500 # Hz
35+
36+
kuka_cartesian_impedance_controller:
37+
type: kuka_cartesian_impedance_controller/KukaCartesianImpedanceController
38+
39+
# More controller instances here
40+
# ...
41+
42+
/**/kuka_cartesian_impedance_controller:
43+
ros__parameters:
44+
max_linear_velocity: 0.3
45+
max_angular_velocity: 0.3
46+
end_effector_link: "lbr_link_ee"
47+
robot_base_link: "lbr_link_0"
48+
compliance_ref_link: "lbr_link_ee"
49+
command_interfaces:
50+
- effort
51+
state_interfaces:
52+
- position
53+
- velocity
54+
joints:
55+
- lbr_A1
56+
- lbr_A2
57+
- lbr_A3
58+
- lbr_A4
59+
- lbr_A5
60+
- lbr_A6
61+
- lbr_A7
62+
63+
# More controllers here
64+
```
65+
#### Nullspace target configuration
66+
The target nullspace configuration can be set in `kuka_cartesian_impedance_controller.cpp` by modifying the `m_q_ns` array. The values are in radians and correspond to the desired joint angles for the nullspace configuration.:
67+
```
68+
m_q_ns(0) = deg2rad(0.0);
69+
m_q_ns(1) = deg2rad(40.0);
70+
m_q_ns(2) = deg2rad(0.0);
71+
m_q_ns(3) = deg2rad(-72.6);
72+
m_q_ns(4) = deg2rad(0.0);
73+
m_q_ns(5) = deg2rad(80.05);
74+
m_q_ns(6) = deg2rad(0.0);
75+
```

effort_controller_base/include/effort_controller_base/effort_controller_base.h

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,8 @@
1212
#include <hardware_interface/loaned_command_interface.hpp>
1313
#include <hardware_interface/loaned_state_interface.hpp>
1414
#include <kdl/chain.hpp>
15-
#include <kdl/chaindynparam.hpp>
1615
#include <kdl/chainfksolverpos_recursive.hpp>
17-
#include <kdl/chainfksolvervel_recursive.hpp>
18-
#include <kdl/chainiksolverpos_lma.hpp>
19-
#include <kdl/chainiksolverpos_nr_jl.hpp>
20-
#include <kdl/chainiksolvervel_pinv.hpp>
21-
#include <kdl/chainiksolvervel_pinv_nso.hpp>
16+
#include <kdl/chainjnttojacsolver.hpp>
2217
#include <kdl/frames.hpp>
2318
#include <kdl/jacobian.hpp>
2419
#include <kdl/jntarray.hpp>
@@ -179,18 +174,12 @@ class EffortControllerBase : public controller_interface::ControllerInterface {
179174
std::shared_ptr<KDL::ChainJntToJacSolver> m_jnt_to_jac_solver;
180175
std::shared_ptr<KDL::TreeFkSolverPos_recursive> m_forward_kinematics_solver;
181176
std::shared_ptr<KDL::ChainFkSolverPos_recursive> m_fk_solver;
182-
std::shared_ptr<KDL::ChainIkSolverPos_NR_JL> m_ik_solver;
183-
184-
std::shared_ptr<KDL::ChainIkSolverVel_pinv_nso> m_ik_solver_vel_nso;
185-
186-
std::shared_ptr<KDL::ChainIkSolverVel_pinv> m_ik_solver_vel;
187-
std::shared_ptr<KDL::ChainDynParam> m_dyn_solver;
177+
KDL::JntArray m_q_ns;
178+
KDL::JntArray m_weights;
188179

189180
/**
190181
* @brief Allow users to choose the IK solver type on startup
191182
*/
192-
// std::shared_ptr<pluginlib::ClassLoader<IKSolver> > m_solver_loader;
193-
// std::shared_ptr<IKSolver> m_ik_solver;
194183

195184
// Dynamic parameters
196185
std::string m_end_effector_link;
@@ -237,7 +226,6 @@ class EffortControllerBase : public controller_interface::ControllerInterface {
237226
KDL::JntArray m_joint_effort_limits;
238227
double m_delta_tau_max;
239228

240-
bool m_kuka_hw;
241229
};
242230

243231
} // namespace effort_controller_base

effort_controller_base/src/effort_controller_base.cpp

Lines changed: 22 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,10 @@ EffortControllerBase::on_configure(
188188
// Initialize effort limits
189189
m_joint_effort_limits.resize(m_joint_number);
190190

191+
// initialize postural task
192+
m_q_ns.resize(m_joint_number);
193+
m_weights.resize(m_joint_number);
194+
191195
// Parse joint limits
192196
m_upper_pos_limits.resize(m_joint_number);
193197
m_lower_pos_limits.resize(m_joint_number);
@@ -231,39 +235,23 @@ EffortControllerBase::on_configure(
231235
m_forward_kinematics_solver.reset(new KDL::TreeFkSolverPos_recursive(tmp));
232236
m_fk_solver.reset(new KDL::ChainFkSolverPos_recursive(m_robot_chain));
233237

234-
m_ik_solver_vel.reset(new KDL::ChainIkSolverVel_pinv(m_robot_chain));
235-
236-
m_ik_solver.reset(new KDL::ChainIkSolverPos_NR_JL(
237-
m_robot_chain, m_lower_pos_limits, m_upper_pos_limits, *m_fk_solver,
238-
*m_ik_solver_vel, 100, 1e-6));
239-
240-
// m_ik_solver.reset(new KDL::ChainIkSolverPos_LMA(m_robot_chain, 1e-4, 1000,
241-
// 1e-6));
242-
243-
KDL::JntArray q_ns(m_joint_number), weights(m_joint_number);
244-
q_ns(0) = 0.0;
245-
q_ns(1) = 0.78;
246-
q_ns(2) = 0.0;
247-
q_ns(3) = -1.57;
248-
q_ns(4) = 0.0;
249-
q_ns(5) = -0.78;
250-
q_ns(6) = 0.0;
251-
252-
weights(0) = 1.0;
253-
weights(1) = 1.0;
254-
weights(2) = 1.0;
255-
weights(3) = 1.0;
256-
weights(4) = 1.0;
257-
weights(5) = 1.0;
258-
weights(6) = 1.0;
259-
260-
m_ik_solver_vel_nso.reset(
261-
new KDL::ChainIkSolverVel_pinv_nso(m_robot_chain, q_ns, weights));
262-
263-
m_jnt_to_jac_solver.reset(new KDL::ChainJntToJacSolver(m_robot_chain));
264-
m_dyn_solver.reset(new KDL::ChainDynParam(m_robot_chain, grav));
265-
RCLCPP_INFO(get_node()->get_logger(),
266-
"Finished initializing kinematics solvers");
238+
auto deg2rad = [](double deg) { return deg * M_PI / 180.0; };
239+
240+
m_q_ns(0) = deg2rad(0.0);
241+
m_q_ns(1) = deg2rad(40.0);
242+
m_q_ns(2) = deg2rad(0.0);
243+
m_q_ns(3) = deg2rad(-72.6);
244+
m_q_ns(4) = deg2rad(0.0);
245+
m_q_ns(5) = deg2rad(80.05);
246+
m_q_ns(6) = deg2rad(0.0);
247+
248+
m_weights(0) = 1.0;
249+
m_weights(1) = 1.0;
250+
m_weights(2) = 1.0;
251+
m_weights(3) = 1.0;
252+
m_weights(4) = 1.0;
253+
m_weights(5) = 1.0;
254+
m_weights(6) = 1.0;
267255

268256
RCLCPP_INFO_STREAM(get_node()->get_logger(), "Robot Chain: ");
269257
for (unsigned int i = 0; i < m_robot_chain.getNrOfSegments(); ++i) {
@@ -304,6 +292,7 @@ EffortControllerBase::on_configure(
304292
m_old_joint_velocities.data.setZero();
305293
m_simulated_joint_motion.resize(m_joint_number);
306294

295+
307296
RCLCPP_INFO(get_node()->get_logger(), "Finished Base on_configure");
308297
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::
309298
CallbackReturn::SUCCESS;
@@ -388,37 +377,16 @@ void EffortControllerBase::writeJointEffortCmds(
388377
if (target_joint_positions(i) + 2 * max_velocity > m_upper_pos_limits(i)) {
389378
// set equal to current
390379
target_joint_positions(i) = m_upper_pos_limits(i) - 2 * max_velocity - eps;
391-
// RCLCPP_INFO(get_node()->get_logger(),
392-
// "Joint %s target is out of limits, setting to %f",
393-
// m_joint_names[i].c_str(), m_joint_positions(i));
394380
} else if (target_joint_positions(i) - 2 * max_velocity <
395381
m_lower_pos_limits(i)) {
396382
// set equal to current
397383
target_joint_positions(i) = m_lower_pos_limits(i) + 2 * max_velocity + eps;
398-
// RCLCPP_INFO(get_node()->get_logger(),
399-
// "Joint %s target is out of limits, setting to %f",
400-
// m_joint_names[i].c_str(), m_joint_positions(i));
401384
}
402385

403386
m_joint_cmd_pos_handles[i].get().set_value(target_joint_positions(i));
404387
}
405388
}
406389

407-
void EffortControllerBase::computeIKSolution(
408-
const KDL::Frame &desired_pose, ctrl::VectorND &simulated_joint_positions) {
409-
// Invese kinematics
410-
int ret = m_ik_solver->CartToJnt(m_joint_positions, desired_pose,
411-
m_simulated_joint_motion);
412-
413-
// Check if solution was found
414-
if (ret < 0) {
415-
RCLCPP_ERROR(get_node()->get_logger(), "Could not find IK solution");
416-
return;
417-
}
418-
419-
simulated_joint_positions = m_simulated_joint_motion.data;
420-
}
421-
422390
ctrl::Vector6D
423391
EffortControllerBase::displayInBaseLink(const ctrl::Vector6D &vector,
424392
const std::string &from) {

kuka_cartesian_impedance_controller/README.md

Lines changed: 0 additions & 58 deletions
This file was deleted.

kuka_cartesian_impedance_controller/kuka_cartesian_impedance_controller_plugin.xml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
type="kuka_cartesian_impedance_controller::KukaCartesianImpedanceController"
55
base_class_type="controller_interface::ControllerInterface">
66
<description>
7-
Steer your robot's end-effector with forces and torques.
8-
It's ideal for teleoperation with contacts.
7+
Cartesian impedance control for FRI implemented with closed-loop inverse kinematics (CLIK).
98
</description>
109
</class>
11-
1210
</library>

0 commit comments

Comments
 (0)