Franky  0.9.1
A High-Level Motion API for Franka
robot.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <future>
4 #include <variant>
5 #include <exception>
6 #include <stdexcept>
7 #include <optional>
8 #include <franka/control_types.h>
9 #include <franka/duration.h>
10 #include <franka/exception.h>
11 #include <franka/model.h>
12 #include <franka/robot.h>
13 #include <franka/robot_state.h>
14 
15 #include "franky/types.hpp"
16 #include "franky/robot_pose.hpp"
19 #include "franky/kinematics.hpp"
21 #include "franky/motion/motion.hpp"
22 #include "franky/scope_guard.hpp"
24 #include "franky/util.hpp"
26 #include "franky/joint_state.hpp"
27 
28 namespace franky {
29 
36 struct InvalidMotionTypeException : public std::runtime_error {
37  using std::runtime_error::runtime_error;
38 };
39 
45 class Robot : public franka::Robot {
46  public:
47  template<size_t dims>
48  using ScalarOrArray = std::variant<double, std::array<double, dims>, Eigen::Vector<double, dims>>;
49 
53  struct Params {
59 
64 
69 
73  franka::ControllerMode controller_mode{franka::ControllerMode::kJointImpedance};
74 
78  franka::RealtimeConfig realtime_config{franka::RealtimeConfig::kEnforce};
79  };
80 
85  {{
86  {0.0, 0.333, 0.0},
87  {-M_PI / 2, 0.0, 0.0},
88  {M_PI / 2, 0.316, 0.0},
89  {M_PI / 2, 0.0, 0.0825},
90  {-M_PI / 2, 0.384, -0.0825},
91  {M_PI / 2, 0.0, 0.0},
92  {M_PI / 2, 0.0, 0.088}}},
93  Affine().fromPositionOrientationScale(
94  Eigen::Vector3d(0, 0, 0.107),
95  Euler(M_PI / 4, 0, M_PI),
96  Eigen::Matrix<double, 3, 1>::Ones())
97  );
98 
100  static constexpr double max_translation_velocity{1.7};
101 
103  static constexpr double max_rotation_velocity{2.5};
104 
106  static constexpr double max_elbow_velocity{2.175};
107 
109  static constexpr double max_translation_acceleration{13.0};
110 
112  static constexpr double max_rotation_acceleration{25.0};
113 
115  static constexpr double max_elbow_acceleration{10.0};
116 
118  static constexpr double max_translation_jerk{6500.0};
119 
121  static constexpr double max_rotation_jerk{12500.0};
122 
124  static constexpr double max_elbow_jerk{5000.0};
125 
127  static constexpr std::array<double, 7>
129  {2.175, 2.175, 2.175, 2.175, 2.610, 2.610, 2.610}
130  };
131 
133  static constexpr std::array<double, 7>
135  {15.0, 7.5, 10.0, 12.5, 15.0, 20.0, 20.0}
136  };
137 
139  static constexpr std::array<double, 7>
141  {7500.0, 3750.0, 5000.0, 6250.0, 7500.0, 10000.0, 10000.0}
142  };
143 
145  static constexpr size_t degrees_of_freedoms{7};
146 
148  static constexpr double control_rate{0.001};
149 
153  explicit Robot(const std::string &fci_hostname);
154 
159  explicit Robot(const std::string &fci_hostname, const Params &params);
160 
161  using franka::Robot::setCollisionBehavior;
162 
170  const ScalarOrArray<7> &torque_threshold,
171  const ScalarOrArray<6> &force_threshold);
172 
182  const ScalarOrArray<7> &lower_torque_threshold,
183  const ScalarOrArray<7> &upper_torque_threshold,
184  const ScalarOrArray<6> &lower_force_threshold,
185  const ScalarOrArray<6> &upper_force_threshold);
186 
208  const ScalarOrArray<7> &lower_torque_threshold_acceleration,
209  const ScalarOrArray<7> &upper_torque_threshold_acceleration,
210  const ScalarOrArray<7> &lower_torque_threshold_nominal,
211  const ScalarOrArray<7> &upper_torque_threshold_nominal,
212  const ScalarOrArray<6> &lower_force_threshold_acceleration,
213  const ScalarOrArray<6> &upper_force_threshold_acceleration,
214  const ScalarOrArray<6> &lower_force_threshold_nominal,
215  const ScalarOrArray<6> &upper_force_threshold_nominal);
216 
221  bool recoverFromErrors();
222 
227  [[nodiscard]] bool hasErrors();
228 
233  [[nodiscard]] inline RobotPose currentPose() {
234  return currentCartesianState().pose();
235  }
236 
241  [[nodiscard]] inline RobotVelocity currentCartesianVelocity() {
242  return currentCartesianState().velocity();
243  }
244 
249  [[nodiscard]] inline CartesianState currentCartesianState() {
250  auto s = state();
251  return {{Affine(Eigen::Matrix4d::Map(s.O_T_EE.data())), s.elbow[0]},
252  RobotVelocity(franka::CartesianVelocities(s.O_dP_EE_c, s.delbow_c))};
253  }
254 
259  [[nodiscard]] JointState currentJointState();
260 
265  [[nodiscard]] Vector7d currentJointPositions();
266 
271  [[nodiscard]] Vector7d currentJointVelocities();
272 
277  [[nodiscard]] franka::RobotState state();
278 
284 
290 
294  [[nodiscard]] bool is_in_control();
295 
299  [[nodiscard]] std::string fci_hostname() const;
300 
304  [[nodiscard]] std::optional<ControlSignalType> current_control_signal_type();
305 
309  inline bool joinMotion() {
310  std::unique_lock<std::mutex> lock(control_mutex_);
311  return joinMotionUnsafe(lock);
312  }
313 
321  template<class Rep, class Period>
322  inline bool joinMotion(const std::chrono::duration<Rep, Period> &timeout) {
323  std::unique_lock<std::mutex> lock(control_mutex_);
324  return joinMotionUnsafe<Rep, Period>(lock, timeout);
325  }
326 
332  [[nodiscard]]
333  inline bool pollMotion() {
334  return joinMotion(std::chrono::milliseconds(0));
335  }
336 
337  // These helper functions are needed as the implicit template deduction does not work on subclasses of Motion
338 
344  inline void move(const std::shared_ptr<Motion<franka::CartesianPose>> &motion, bool async = false) {
345  moveInternal<franka::CartesianPose>(motion, [this](const ControlFunc<franka::CartesianPose> &m) {
346  control(m, params_.controller_mode);
347  }, async);
348  }
349 
355  inline void move(const std::shared_ptr<Motion<franka::CartesianVelocities>> &motion, bool async = false) {
356  moveInternal<franka::CartesianVelocities>(motion, [this](const ControlFunc<franka::CartesianVelocities> &m) {
357  control(m, params_.controller_mode);
358  }, async);
359  }
360 
366  inline void move(const std::shared_ptr<Motion<franka::JointPositions>> &motion, bool async = false) {
367  moveInternal<franka::JointPositions>(motion, [this](const ControlFunc<franka::JointPositions> &m) {
368  control(m, params_.controller_mode);
369  }, async);
370  }
371 
377  inline void move(const std::shared_ptr<Motion<franka::JointVelocities>> &motion, bool async = false) {
378  moveInternal<franka::JointVelocities>(motion, [this](const ControlFunc<franka::JointVelocities> &m) {
379  control(m, params_.controller_mode);
380  }, async);
381  }
382 
388  inline void move(const std::shared_ptr<Motion<franka::Torques>> &motion, bool async = false) {
389  moveInternal<franka::Torques>(motion, [this](const ControlFunc<franka::Torques> &m) {
390  control(m);
391  }, async);
392  }
393 
400  [[nodiscard]] static Vector7d inverseKinematics(const Affine &target, const Vector7d &q0);
401 
407  [[nodiscard]] static Affine forwardKinematics(const Vector7d &q);
408 
409  private:
410  template<typename ControlSignalType>
411  using ControlFunc = std::function<ControlSignalType(const franka::RobotState &, franka::Duration)>;
412  using MotionGeneratorVariant = std::variant<
413  std::nullopt_t,
419  >;
420 
422  std::string fci_hostname_;
423  Params params_;
424  franka::RobotState current_state_;
425  std::mutex state_mutex_;
426  std::mutex control_mutex_;
427  std::condition_variable control_finished_condition_;
428  std::exception_ptr control_exception_;
429  std::thread control_thread_;
430  MotionGeneratorVariant motion_generator_{std::nullopt};
431  bool motion_generator_running_{false};
432 
433  [[nodiscard]] bool is_in_control_unsafe() const;
434 
435  template<class Rep = long, class Period = std::ratio<1>>
436  bool joinMotionUnsafe(
437  std::unique_lock<std::mutex> &lock,
438  const std::optional<std::chrono::duration<Rep, Period>> &timeout = std::nullopt) {
439  while (motion_generator_running_) {
440  if (timeout.has_value()) {
441  if (control_finished_condition_.wait_for(lock, timeout.value()) == std::cv_status::timeout) {
442  return false;
443  }
444  } else {
445  control_finished_condition_.wait(lock);
446  }
447  }
448  if (control_thread_.joinable())
449  control_thread_.join();
450  if (control_exception_ != nullptr) {
451  auto control_exception = control_exception_;
452  control_exception_ = nullptr;
453  std::rethrow_exception(control_exception);
454  }
455  return true;
456  }
457 
458  template<typename ControlSignalType>
459  void moveInternal(
460  const std::shared_ptr<Motion<ControlSignalType>> &motion,
461  const std::function<void(const ControlFunc<ControlSignalType> &)> &control_func_executor,
462  bool async) {
463  {
464  std::unique_lock<std::mutex> lock(control_mutex_);
465  if (is_in_control_unsafe() && motion_generator_running_) {
466  if (!std::holds_alternative<MotionGenerator<ControlSignalType>>(motion_generator_)) {
467  throw InvalidMotionTypeException("The type of motion cannot change during runtime. Please ensure that the "
468  "previous motion finished before using a new type of motion.");
469  } else {
470  std::get<MotionGenerator<ControlSignalType>>(motion_generator_).updateMotion(motion);
471  }
472  } else {
473  joinMotionUnsafe(lock);
474 
475  motion_generator_.emplace<MotionGenerator<ControlSignalType>>(this, motion);
476  auto motion_generator = &std::get<MotionGenerator<ControlSignalType>>(motion_generator_);
477  motion_generator->registerUpdateCallback(
478  [this](const franka::RobotState &robot_state, franka::Duration duration, double time) {
479  std::lock_guard<std::mutex> lock(this->state_mutex_);
480  current_state_ = robot_state;
481  });
482  motion_generator_running_ = true;
483  control_thread_ = std::thread(
484  [this, control_func_executor, motion_generator]() {
485  try {
486  bool done = false;
487  while (!done) {
488  control_func_executor(
489  [motion_generator](const franka::RobotState &rs, franka::Duration d) {
490  return (*motion_generator)(rs, d);
491  });
492  std::unique_lock<std::mutex> lock(control_mutex_);
493 
494  // This code is just for the case that a new motion is set just after the old one terminates. If this
495  // happens, we need to continue with this motion, unless an exception occurs.
496  done = !motion_generator->has_new_motion();
497  if (motion_generator->has_new_motion()) {
498  motion_generator->resetTimeUnsafe();
499  } else {
500  done = true;
501  motion_generator_running_ = false;
502  control_finished_condition_.notify_all();
503  }
504  }
505  } catch (...) {
506  std::unique_lock<std::mutex> lock(control_mutex_);
507  control_exception_ = std::current_exception();
508  motion_generator_running_ = false;
509  control_finished_condition_.notify_all();
510  }
511  }
512  );
513  }
514  }
515  if (!async)
516  joinMotion();
517  }
518 
519  template<size_t dims>
520  std::array<double, dims> expand(const ScalarOrArray<dims> &input) {
521  if (std::holds_alternative<std::array<double, dims >>(input)) {
522  return std::get<std::array<double, dims >>(input);
523  } else if (std::holds_alternative<Eigen::Vector<double, dims >>(input)) {
524  return toStd<dims>(std::get<Eigen::Vector<double, dims >>(input));
525  } else {
526  std::array<double, dims> output;
527  std::fill(output.begin(), output.end(), std::get<double>(input));
528  return output;
529  }
530  }
531 };
532 
533 } // namespace franky
Definition: cartesian_state.hpp:17
RobotPose pose() const
Definition: cartesian_state.hpp:60
RobotVelocity velocity() const
Definition: cartesian_state.hpp:67
Joint state of a robot.
Definition: joint_state.hpp:17
Helper class for handling motions and reactions.
Definition: motion_generator.hpp:30
Relative dynamics factors.
Definition: relative_dynamics_factor.hpp:13
A class representing a Franka robot.
Definition: robot.hpp:45
static constexpr double max_elbow_velocity
Definition: robot.hpp:106
bool joinMotion(const std::chrono::duration< Rep, Period > &timeout)
Wait for the current motion to finish with a timeout. Throw any exceptions that occurred during the m...
Definition: robot.hpp:322
std::optional< ControlSignalType > current_control_signal_type()
The type of the current control signal.
Definition: robot.cpp:129
static constexpr double max_elbow_jerk
Definition: robot.hpp:124
static Affine forwardKinematics(const Vector7d &q)
Calculate the forward kinematics for the given joint positions.
Definition: robot.cpp:40
std::string fci_hostname() const
The hostname of the robot.
Definition: robot.cpp:125
Vector7d currentJointVelocities()
Returns the current joint velocities of the robot.
Definition: robot.cpp:36
bool joinMotion()
Wait for the current motion to finish. Throw any exceptions that occurred during the motion.
Definition: robot.hpp:309
static constexpr double control_rate
Definition: robot.hpp:148
std::variant< double, std::array< double, dims >, Eigen::Vector< double, dims > > ScalarOrArray
Definition: robot.hpp:48
void move(const std::shared_ptr< Motion< franka::JointVelocities >> &motion, bool async=false)
Execute the given motion.
Definition: robot.hpp:377
RelativeDynamicsFactor relative_dynamics_factor()
Returns the current global relative dynamics factor of the robot.
Definition: robot.cpp:145
void move(const std::shared_ptr< Motion< franka::JointPositions >> &motion, bool async=false)
Execute the given motion.
Definition: robot.hpp:366
Vector7d currentJointPositions()
Returns the current joint positions of the robot.
Definition: robot.cpp:32
CartesianState currentCartesianState()
Returns the current cartesian state of the robot.
Definition: robot.hpp:249
static constexpr double max_rotation_acceleration
Definition: robot.hpp:112
bool recoverFromErrors()
Calls the automatic error recovery of the robot and returns whether the recovery was successful.
Definition: robot.cpp:22
static constexpr std::array< double, 7 > max_joint_acceleration
Definition: robot.hpp:134
void move(const std::shared_ptr< Motion< franka::Torques >> &motion, bool async=false)
Execute the given motion.
Definition: robot.hpp:388
void move(const std::shared_ptr< Motion< franka::CartesianPose >> &motion, bool async=false)
Execute the given motion.
Definition: robot.hpp:344
static constexpr double max_translation_velocity
Definition: robot.hpp:100
franka::RobotState state()
Returns the current state of the robot.
Definition: robot.cpp:68
const KinematicChain< 7 > kinematics
The kinematic chain of the robot.
Definition: robot.hpp:84
bool is_in_control()
Whether the robot is currently in control, i.e. a motion is being executed.
Definition: robot.cpp:120
JointState currentJointState()
Returns the current joint state of the robot.
Definition: robot.cpp:27
void setCollisionBehavior(const ScalarOrArray< 7 > &torque_threshold, const ScalarOrArray< 6 > &force_threshold)
Set the collision behavior of the robot.
Definition: robot.cpp:79
Robot(const std::string &fci_hostname)
Connects to a robot at the given FCI IP address.
Definition: robot.cpp:11
static constexpr double max_rotation_velocity
Definition: robot.hpp:103
void move(const std::shared_ptr< Motion< franka::CartesianVelocities >> &motion, bool async=false)
Execute the given motion.
Definition: robot.hpp:355
static constexpr size_t degrees_of_freedoms
Definition: robot.hpp:145
static constexpr std::array< double, 7 > max_joint_jerk
Definition: robot.hpp:140
static Vector7d inverseKinematics(const Affine &target, const Vector7d &q0)
Calculate the inverse kinematics for the given target pose.
Definition: robot.cpp:44
RobotVelocity currentCartesianVelocity()
Returns the current cartesian velocity of the robot.
Definition: robot.hpp:241
void setRelativeDynamicsFactor(const RelativeDynamicsFactor &relative_dynamics_factor)
Sets the global relative dynamics factor of the robot.
Definition: robot.cpp:150
bool hasErrors()
Returns whether the robot has errors.
Definition: robot.cpp:18
RobotPose currentPose()
Returns the current pose of the robot.
Definition: robot.hpp:233
static constexpr std::array< double, 7 > max_joint_velocity
Definition: robot.hpp:128
static constexpr double max_rotation_jerk
Definition: robot.hpp:121
static constexpr double max_translation_acceleration
Definition: robot.hpp:109
static constexpr double max_elbow_acceleration
Definition: robot.hpp:115
static constexpr double max_translation_jerk
Definition: robot.hpp:118
bool pollMotion()
Check whether the robot is still in motion. This function is non-blocking and returns immediately....
Definition: robot.hpp:333
Cartesian pose of a robot.
Definition: robot_pose.hpp:16
Cartesian velocity of a robot.
Definition: robot_velocity.hpp:18
Definition: gripper.cpp:3
Eigen::Vector< double, 7 > Vector7d
Definition: types.hpp:9
ControlSignalType
Type of control signal.
Definition: control_signal_type.hpp:8
@ CartesianVelocities
Definition: control_signal_type.hpp:12
Eigen::EulerAngles< double, Eigen::EulerSystemXYZ > Euler
Definition: types.hpp:11
Eigen::Affine3d Affine
Definition: types.hpp:13
Exception thrown when an invalid motion type is used.
Definition: robot.hpp:36
Global parameters for the robot.
Definition: robot.hpp:53
RelativeDynamicsFactor relative_dynamics_factor
Definition: robot.hpp:58
double default_force_threshold
Definition: robot.hpp:68
franka::ControllerMode controller_mode
Definition: robot.hpp:73
franka::RealtimeConfig realtime_config
Definition: robot.hpp:78
double default_torque_threshold
Definition: robot.hpp:63