Frankx  0.2.0
A High-Level Motion API for Franka
motion_impedance_generator.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <franka/duration.h>
4 #include <franka/robot_state.h>
5 
9 
10 
11 namespace frankx {
12  using namespace movex;
13 
14 template<class RobotType>
16  double time {0.0}, motion_init_time {0.0};
17  RobotType* robot;
18 
19  Eigen::Matrix<double, 6, 6> stiffness, damping;
21  Eigen::Vector3d position_d;
22  Eigen::Quaterniond orientation_d;
23 
24  franka::RobotState initial_state;
25  franka::Model* model;
26 
30 
31  explicit ImpedanceMotionGenerator(RobotType* robot, const Affine& frame, ImpedanceMotion& motion, MotionData& data): robot(robot), frame(frame), motion(motion), data(data) {
32  if (motion.type == ImpedanceMotion::Type::Joint) {
33  throw std::runtime_error("joint impedance is not implemented yet.");
34  }
35 
36  stiffness.setZero();
37  stiffness.topLeftCorner(3, 3) << motion.translational_stiffness * Eigen::MatrixXd::Identity(3, 3);
38  stiffness.bottomRightCorner(3, 3) << motion.rotational_stiffness * Eigen::MatrixXd::Identity(3, 3);
39  damping.setZero();
40  damping.topLeftCorner(3, 3) << 2.0 * sqrt(motion.translational_stiffness) * Eigen::MatrixXd::Identity(3, 3);
41  damping.bottomRightCorner(3, 3) << 2.0 * sqrt(motion.rotational_stiffness) * Eigen::MatrixXd::Identity(3, 3);
42 
43  initial_state = robot->readOnce();
44  model = new franka::Model(robot->loadModel());
45 
46  initial_affine = Affine(initial_state.O_T_EE);
47  position_d = Eigen::Vector3d(initial_affine.translation());
48  orientation_d = Eigen::Quaterniond(initial_affine.quaternion());
49  }
50 
51  void init(const franka::RobotState& robot_state, franka::Duration period) {
52  Eigen::Affine3d transform(Eigen::Matrix4d::Map(robot_state.O_T_EE.data()));
53  motion.target = Affine(transform);
54  motion.is_active = true;
55  }
56 
57  franka::Torques operator()(const franka::RobotState& robot_state, franka::Duration period) {
58  time += period.toSec();
59  if (time == 0.0) {
60  init(robot_state, period);
61  }
62 
63  std::array<double, 7> coriolis_array = model->coriolis(robot_state);
64  std::array<double, 42> jacobian_array = model->zeroJacobian(franka::Frame::kEndEffector, robot_state);
65 
66  Eigen::Map<const Eigen::Matrix<double, 7, 1>> coriolis(coriolis_array.data());
67  Eigen::Map<const Eigen::Matrix<double, 6, 7>> jacobian(jacobian_array.data());
68  Eigen::Map<const Eigen::Matrix<double, 7, 1>> q(robot_state.q.data());
69  Eigen::Map<const Eigen::Matrix<double, 7, 1>> dq(robot_state.dq.data());
70  Eigen::Affine3d transform(Eigen::Matrix4d::Map(robot_state.O_T_EE.data()));
71  Eigen::Vector3d position(transform.translation());
72  Eigen::Quaterniond orientation(transform.linear());
73 
74  Eigen::Matrix<double, 6, 1> error;
75  error.head(3) << position - position_d;
76 
77  if (orientation_d.coeffs().dot(orientation.coeffs()) < 0.0) {
78  orientation.coeffs() << -orientation.coeffs();
79  }
80 
81  Eigen::Quaterniond error_quaternion(orientation.inverse() * orientation_d);
82  error.tail(3) << error_quaternion.x(), error_quaternion.y(), error_quaternion.z();
83  error.tail(3) << -transform.linear() * error.tail(3);
84 
85  Eigen::VectorXd wrench_cartesian(6), tau_task(7), tau_d(7);
86  wrench_cartesian = -stiffness * error - damping * (jacobian * dq);
87 
88  // Force constraints
89  for (const auto force_constraint : motion.force_constraints) {
90  switch (force_constraint.first) {
92  wrench_cartesian(0) = force_constraint.second;
93  } break;
95  wrench_cartesian(1) = force_constraint.second;
96  } break;
98  wrench_cartesian(2) = force_constraint.second;
99  } break;
100  }
101  }
102 
103  tau_task << jacobian.transpose() * wrench_cartesian;
104  tau_d << tau_task + coriolis;
105 
106  std::array<double, 7> tau_d_array{};
107  Eigen::VectorXd::Map(&tau_d_array[0], 7) = tau_d;
108 
109 #ifdef WITH_PYTHON
110  if (robot->stop_at_python_signal && Py_IsInitialized() && PyErr_CheckSignals() == -1) {
111  motion.is_active = false;
112  return franka::MotionFinished(franka::Torques(tau_d_array));
113  }
114 #endif
115 
116  if (motion.should_finish) {
117  motion.is_active = false;
118  return franka::MotionFinished(franka::Torques(tau_d_array));
119  }
120 
121  // Update target with target motion
122  switch (motion.target_motion) {
124  position_d = motion.exponential_decay * motion.target.translation() + (1.0 - motion.exponential_decay) * position_d;
125  orientation_d = orientation_d.slerp(motion.exponential_decay, motion.target.quaternion());
126  } break;
128  if (!motion.linear_motion.initialized) {
129  initial_affine = Affine(Eigen::Affine3d(Eigen::Matrix4d::Map(initial_state.O_T_EE.data())));
130  motion_init_time = time;
131  motion.linear_motion.initialized = true;
132  }
133 
134  double transition_parameter = (time - motion_init_time) / (motion.linear_motion.duration);
135  if (transition_parameter <= 1.0) { // [ms] to [s]
136  motion.target = initial_affine.slerp(motion.linear_motion.relative_target * initial_affine, transition_parameter);
137  position_d = motion.target.translation();
138  orientation_d = motion.target.quaternion();
139  } else if (motion.linear_motion.finish_after && transition_parameter > motion.linear_motion.finish_wait_factor) { // Wait a bit longer to stop
140  motion.should_finish = true;
141  }
142  } break;
144  if (!motion.spiral_motion.initialized) {
145  motion_init_time = time;
146  motion.spiral_motion.initialized = true;
147  }
148 
149  double time_diff = motion_init_time - time;
150  // target = spiral_motion.center * Affine(0, 0, 0, 2 * pi * spiral_motion.revolutions_per_second * time) * Affine(spiral_motion.radius_increment_per_revolution * time);
151  // position_d = target.translation();
152  // orientation_d = target.quaternion();
153  } break;
154  }
155 
156  return franka::Torques(tau_d_array);
157  }
158 };
159 
160 } // namespace frankx
frankx::ImpedanceMotionGenerator::frame
Affine frame
Definition: motion_impedance_generator.hpp:27
frankx::MotionGenerator
Definition: motion_generator.hpp:19
movex::ImpedanceMotion::TargetMotion::Spiral
@ Spiral
frankx::ImpedanceMotionGenerator::stiffness
Eigen::Matrix< double, 6, 6 > stiffness
Definition: motion_impedance_generator.hpp:19
frankx
Definition: __init__.py:1
movex::ImpedanceMotion::target
Affine target
Definition: motion_impedance.hpp:60
robot_state.hpp
frankx::ImpedanceMotionGenerator::robot
RobotType * robot
Definition: motion_impedance_generator.hpp:17
frankx::ImpedanceMotionGenerator::ImpedanceMotionGenerator
ImpedanceMotionGenerator(RobotType *robot, const Affine &frame, ImpedanceMotion &motion, MotionData &data)
Definition: motion_impedance_generator.hpp:31
frankx::ImpedanceMotionGenerator::initial_state
franka::RobotState initial_state
Definition: motion_impedance_generator.hpp:24
movex::ImpedanceMotion::SpiralTargetMotion::initialized
bool initialized
Definition: motion_impedance.hpp:43
movex::ImpedanceMotion::TargetMotion::Linear
@ Linear
movex::ImpedanceMotion::LinearTargetMotion::finish_after
bool finish_after
Definition: motion_impedance.hpp:35
movex::ImpedanceMotion::spiral_motion
SpiralTargetMotion spiral_motion
Definition: motion_impedance.hpp:51
frankx::ImpedanceMotionGenerator::operator()
franka::Torques operator()(const franka::RobotState &robot_state, franka::Duration period)
Definition: motion_impedance_generator.hpp:57
movex::ImpedanceMotion::LinearTargetMotion::finish_wait_factor
double finish_wait_factor
Definition: motion_impedance.hpp:36
movex::ImpedanceMotion::LinearTargetMotion::initialized
bool initialized
Definition: motion_impedance.hpp:34
frankx::ImpedanceMotionGenerator::init
void init(const franka::RobotState &robot_state, franka::Duration period)
Definition: motion_impedance_generator.hpp:51
movex::ImpedanceMotion::TargetMotion::Exponential
@ Exponential
movex::ImpedanceMotion
Definition: motion_impedance.hpp:15
movex::ImpedanceMotion::exponential_decay
double exponential_decay
Definition: motion_impedance.hpp:49
movex::ImpedanceMotion::translational_stiffness
const double translational_stiffness
Definition: motion_impedance.hpp:56
motion_impedance.hpp
motion_data.hpp
frankx::ImpedanceMotionGenerator::orientation_d
Eigen::Quaterniond orientation_d
Definition: motion_impedance_generator.hpp:22
movex::ImpedanceMotion::type
Type type
Definition: motion_impedance.hpp:46
movex::ImpedanceMotion::Axis::Z
@ Z
movex::MotionData
Definition: motion_data.hpp:8
frankx::ImpedanceMotionGenerator::data
MotionData & data
Definition: motion_impedance_generator.hpp:29
movex::ImpedanceMotion::force_constraints
std::map< Axis, double > force_constraints
Definition: motion_impedance.hpp:53
movex::ImpedanceMotion::LinearTargetMotion::relative_target
Affine relative_target
Definition: motion_impedance.hpp:32
frankx::Affine
affx::Affine Affine
Definition: motion_generator.hpp:15
frankx::ImpedanceMotionGenerator
Definition: motion_impedance_generator.hpp:15
frankx::ImpedanceMotionGenerator::initial_affine
Affine initial_affine
Definition: motion_impedance_generator.hpp:20
frankx::ImpedanceMotionGenerator::position_d
Eigen::Vector3d position_d
Definition: motion_impedance_generator.hpp:21
movex::ImpedanceMotion::Type::Joint
@ Joint
movex::ImpedanceMotion::LinearTargetMotion::duration
double duration
Definition: motion_impedance.hpp:33
movex::ImpedanceMotion::is_active
bool is_active
Definition: motion_impedance.hpp:61
frankx::ImpedanceMotionGenerator::model
franka::Model * model
Definition: motion_impedance_generator.hpp:25
movex::ImpedanceMotion::linear_motion
LinearTargetMotion linear_motion
Definition: motion_impedance.hpp:50
movex::ImpedanceMotion::target_motion
TargetMotion target_motion
Definition: motion_impedance.hpp:48
movex::ImpedanceMotion::Axis::X
@ X
movex
Definition: motion_impedance.hpp:13
frankx::ImpedanceMotionGenerator::motion
ImpedanceMotion & motion
Definition: motion_impedance_generator.hpp:28
movex::ImpedanceMotion::should_finish
bool should_finish
Definition: motion_impedance.hpp:62
movex::ImpedanceMotion::Axis::Y
@ Y
movex::ImpedanceMotion::rotational_stiffness
const double rotational_stiffness
Definition: motion_impedance.hpp:57