Frankx  0.2.0
A High-Level Motion API for Franka
motion_waypoint_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 #include <ruckig/ruckig.hpp>
10 
11 
12 namespace frankx {
13  using namespace movex;
14  using Affine = affx::Affine;
15 
16 template<class RobotType>
18  ruckig::Ruckig<RobotType::degrees_of_freedoms> trajectory_generator {RobotType::control_rate};
19  ruckig::InputParameter<RobotType::degrees_of_freedoms> input_para;
20  ruckig::OutputParameter<RobotType::degrees_of_freedoms> output_para;
21  ruckig::Result result;
22 
24  std::vector<Waypoint>::iterator waypoint_iterator;
25  bool waypoint_has_elbow {false};
26 
29  double old_elbow;
30  double time {0.0};
31  RobotType* robot;
32 
36 
37  bool set_target_at_zero_time {true};
38 
39  const size_t cooldown_iterations {5};
40  size_t current_cooldown_iteration {0};
41 
42  explicit WaypointMotionGenerator(RobotType* robot, const Affine& frame, WaypointMotion& motion, MotionData& data): robot(robot), frame(frame), motion(motion), current_motion(motion), data(data) { }
43 
44  void reset() {
45  time = 0.0;
46  current_cooldown_iteration = 0;
47  set_target_at_zero_time = false;
48  }
49 
50  void init(const franka::RobotState& robot_state, franka::Duration period) {
51  franka::CartesianPose initial_cartesian_pose(robot_state.O_T_EE_c, robot_state.elbow_c);
52  Affine initial_pose(initial_cartesian_pose.O_T_EE);
53 
54  Vector7d initial_vector = initial_pose.vector_with_elbow(initial_cartesian_pose.elbow[0]);
55  Vector7d initial_velocity = (Vector7d() << robot_state.O_dP_EE_c[0], robot_state.O_dP_EE_c[1], robot_state.O_dP_EE_c[2], robot_state.O_dP_EE_c[3], robot_state.O_dP_EE_c[4], robot_state.O_dP_EE_c[5], robot_state.delbow_c[0]).finished();
56 
57  old_affine = initial_pose;
58  old_vector = initial_vector;
59  old_elbow = old_vector(6);
60 
61  input_para.current_position = toStd(initial_vector);
62  input_para.current_velocity = toStd(initial_velocity);
63  input_para.current_acceleration = toStd(Vector7d::Zero());
64 
65  input_para.enabled = MotionGenerator::VectorCartRotElbow(true, true, true);
66  setInputLimits(input_para, robot, data);
67 
68  if (set_target_at_zero_time) {
69  waypoint_iterator = current_motion.waypoints.begin();
70 
71  const auto current_waypoint = *waypoint_iterator;
72  waypoint_has_elbow = current_waypoint.elbow.has_value();
73  auto target_position_vector = current_waypoint.getTargetVector(frame, old_affine, old_elbow);
74 
75  input_para.enabled = {true, true, true, true, true, true, waypoint_has_elbow};
76  input_para.target_position = toStd(target_position_vector);
77  input_para.target_velocity = toStd(Vector7d::Zero());
78  setInputLimits(input_para, robot, current_waypoint, data);
79 
80  old_affine = current_waypoint.getTargetAffine(frame, old_affine);
81  old_vector = target_position_vector;
82  old_elbow = old_vector(6);
83  }
84  }
85 
86  franka::CartesianPose operator()(const franka::RobotState& robot_state, franka::Duration period) {
87  time += period.toSec();
88  if (time == 0.0) {
89  init(robot_state, period);
90  }
91 
92  for (auto& reaction : data.reactions) {
93  if (reaction.has_fired) {
94  continue;
95  }
96 
97  if (reaction.condition(MotionGenerator::convertState(robot_state), time)) {
98  std::cout << "[frankx] reaction fired." << std::endl;
99  reaction.has_fired = true;
100 
101  bool new_motion = false;
102 
103  if (reaction.waypoint_action.has_value()) {
104  new_motion = true;
105  current_motion = reaction.waypoint_action.value()(MotionGenerator::convertState(robot_state), time);
106  } else if (reaction.waypoint_motion.has_value()) {
107  new_motion = true;
108  current_motion = *(reaction.waypoint_motion.value());
109  } else {
110  robot->stop();
111  }
112 
113  if (new_motion) {
114  waypoint_iterator = current_motion.waypoints.begin();
115 
116  franka::CartesianPose current_cartesian_pose(robot_state.O_T_EE_c, robot_state.elbow_c);
117  Affine current_pose(current_cartesian_pose.O_T_EE);
118  auto current_vector = current_pose.vector_with_elbow(current_cartesian_pose.elbow[0]);
119  old_affine = current_pose;
120  old_vector = current_vector;
121  old_elbow = old_vector(6);
122 
123  const auto current_waypoint = *waypoint_iterator;
124  waypoint_has_elbow = current_waypoint.elbow.has_value();
125  auto target_position_vector = current_waypoint.getTargetVector(Affine(), old_affine, old_elbow);
126 
127  input_para.enabled = {true, true, true, true, true, true, waypoint_has_elbow};
128  input_para.target_position = toStd(target_position_vector);
129  input_para.target_velocity = toStd(Vector7d::Zero());
130  setInputLimits(input_para, robot, current_waypoint, data);
131 
132  old_affine = current_waypoint.getTargetAffine(Affine(), old_affine);
133  old_vector = target_position_vector;
134  old_elbow = old_vector(6);
135  } else {
136  return franka::MotionFinished(MotionGenerator::CartesianPose(input_para.current_position, waypoint_has_elbow));
137  }
138  }
139  }
140 
141 #ifdef WITH_PYTHON
142  if (robot->stop_at_python_signal && Py_IsInitialized() && PyErr_CheckSignals() == -1) {
143  robot->stop();
144  }
145 #endif
146 
147  const int steps = std::max<int>(period.toMSec(), 1);
148  for (int i = 0; i < steps; i++) {
149  result = trajectory_generator.update(input_para, output_para);
150 
151  if (motion.reload || result == ruckig::Result::Finished) {
152  bool has_new_waypoint {false};
153 
154  if (waypoint_iterator != current_motion.waypoints.end()) {
155  ++waypoint_iterator;
156  has_new_waypoint = (waypoint_iterator != current_motion.waypoints.end());
157  }
158 
159  if (motion.return_when_finished && waypoint_iterator >= current_motion.waypoints.end()) {
160  // Allow cooldown of motion, so that the low-pass filter has time to adjust to target values
161  if (current_cooldown_iteration < cooldown_iterations) {
162  current_cooldown_iteration += 1;
163  return MotionGenerator::CartesianPose(input_para.target_position, waypoint_has_elbow);
164  }
165 
166  return franka::MotionFinished(MotionGenerator::CartesianPose(input_para.target_position, waypoint_has_elbow));
167 
168  } else if (motion.reload) {
169  current_motion = motion;
170  waypoint_iterator = current_motion.waypoints.begin();
171  motion.reload = false;
172  current_motion.reload = false;
173  has_new_waypoint = true;
174  }
175 
176  if (has_new_waypoint) {
177  const auto current_waypoint = *waypoint_iterator;
178  waypoint_has_elbow = current_waypoint.elbow.has_value();
179  auto target_position_vector = current_waypoint.getTargetVector(frame, old_affine, old_elbow);
180 
181  input_para.enabled = {true, true, true, true, true, true, waypoint_has_elbow};
182  input_para.target_position = toStd(target_position_vector);
183  input_para.target_velocity = toStd(Vector7d::Zero());
184  setInputLimits<RobotType>(input_para, robot, current_waypoint, data);
185 
186  old_affine = current_waypoint.getTargetAffine(frame, old_affine);
187  old_vector = target_position_vector;
188  old_elbow = old_vector(6);
189  }
190 
191  } else if (result == ruckig::Result::Error) {
192  std::cout << "[frankx robot] Invalid inputs:" << std::endl;
193  return franka::MotionFinished(MotionGenerator::CartesianPose(input_para.current_position, waypoint_has_elbow));
194  }
195 
196  output_para.pass_to_input(input_para);
197  }
198 
199  return MotionGenerator::CartesianPose(output_para.new_position, waypoint_has_elbow);
200  }
201 };
202 
203 } // namespace frankx
frankx::WaypointMotionGenerator::old_vector
Vector7d old_vector
Definition: motion_waypoint_generator.hpp:27
frankx::MotionGenerator
Definition: motion_generator.hpp:19
frankx::MotionGenerator::convertState
static movex::RobotState< 7 > convertState(const franka::RobotState &franka)
Definition: motion_generator.hpp:52
frankx
Definition: __init__.py:1
frankx::WaypointMotionGenerator::robot
RobotType * robot
Definition: motion_waypoint_generator.hpp:31
frankx::WaypointMotionGenerator::WaypointMotionGenerator
WaypointMotionGenerator(RobotType *robot, const Affine &frame, WaypointMotion &motion, MotionData &data)
Definition: motion_waypoint_generator.hpp:42
frankx::WaypointMotionGenerator::motion
WaypointMotion & motion
Definition: motion_waypoint_generator.hpp:34
robot_state.hpp
frankx::WaypointMotionGenerator::data
MotionData & data
Definition: motion_waypoint_generator.hpp:35
frankx::WaypointMotionGenerator::old_affine
Affine old_affine
Definition: motion_waypoint_generator.hpp:28
movex::WaypointMotion::return_when_finished
bool return_when_finished
Definition: motion_waypoint.hpp:20
frankx::WaypointMotionGenerator::input_para
ruckig::InputParameter< RobotType::degrees_of_freedoms > input_para
Definition: motion_waypoint_generator.hpp:19
movex::WaypointMotion::waypoints
std::vector< Waypoint > waypoints
Definition: motion_waypoint.hpp:22
frankx::WaypointMotionGenerator::old_elbow
double old_elbow
Definition: motion_waypoint_generator.hpp:29
motion_data.hpp
frankx::WaypointMotionGenerator::init
void init(const franka::RobotState &robot_state, franka::Duration period)
Definition: motion_waypoint_generator.hpp:50
frankx::WaypointMotionGenerator::output_para
ruckig::OutputParameter< RobotType::degrees_of_freedoms > output_para
Definition: motion_waypoint_generator.hpp:20
movex::WaypointMotion::reload
bool reload
Definition: motion_waypoint.hpp:19
motion_waypoint.hpp
movex::MotionData
Definition: motion_data.hpp:8
movex::WaypointMotion
Definition: motion_waypoint.hpp:16
frankx::WaypointMotionGenerator
Definition: motion_waypoint_generator.hpp:17
frankx::Affine
affx::Affine Affine
Definition: motion_generator.hpp:15
frankx::WaypointMotionGenerator::current_motion
WaypointMotion current_motion
Definition: motion_waypoint_generator.hpp:23
frankx::WaypointMotionGenerator::result
ruckig::Result result
Definition: motion_waypoint_generator.hpp:21
frankx::WaypointMotionGenerator::frame
Affine frame
Definition: motion_waypoint_generator.hpp:33
movex
Definition: motion_impedance.hpp:13
frankx::WaypointMotionGenerator::reset
void reset()
Definition: motion_waypoint_generator.hpp:44
frankx::WaypointMotionGenerator::waypoint_iterator
std::vector< Waypoint >::iterator waypoint_iterator
Definition: motion_waypoint_generator.hpp:24
frankx::MotionGenerator::CartesianPose
static franka::CartesianPose CartesianPose(const Vector7d &vector, bool include_elbow=true)
Definition: motion_generator.hpp:20
frankx::WaypointMotionGenerator::operator()
franka::CartesianPose operator()(const franka::RobotState &robot_state, franka::Duration period)
Definition: motion_waypoint_generator.hpp:86
frankx::Vector7d
Eigen::Matrix< double, 7, 1 > Vector7d
Definition: motion_generator.hpp:17
movex::MotionData::reactions
std::vector< Reaction > reactions
Definition: motion_data.hpp:12
frankx::MotionGenerator::VectorCartRotElbow
static std::array< T, 7 > VectorCartRotElbow(T cart, T rot, T elbow)
Definition: motion_generator.hpp:37