Franky 1.1.0
A High-Level Motion API for Franka
Loading...
Searching...
No Matches
waypoint_motion.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <optional>
4#include <ruckig/ruckig.hpp>
5
7
8namespace franky {
9
13struct MotionPlannerException : std::runtime_error {
14 using std::runtime_error::runtime_error;
15};
16
35template <typename TargetType>
36struct Waypoint {
38
40
41 std::optional<franka::Duration> minimum_time{std::nullopt};
42
43 franka::Duration hold_target_duration{0};
44
45 std::optional<franka::Duration> max_total_duration{std::nullopt};
46};
47
58template <typename ControlSignalType, typename WaypointType, typename TargetType>
59class WaypointMotion : public Motion<ControlSignalType> {
60 static_assert(
61 std::is_base_of_v<Waypoint<TargetType>, WaypointType>, "WaypointType must inherit from Waypoint<TargetType>");
62
63 public:
69 explicit WaypointMotion(std::vector<WaypointType> waypoints, bool return_when_finished = true)
70 : waypoints_(std::move(waypoints)), return_when_finished_(return_when_finished), prev_result_() {}
71
72 protected:
73 void initImpl(const RobotState &robot_state, const std::optional<ControlSignalType> &previous_command) override {
74 target_reached_time_ = std::nullopt;
75 waypoint_started_time_ = franka::Duration(0);
76
77 waypoint_iterator_ = waypoints_.begin();
79 if (waypoint_iterator_ != waypoints_.end()) {
80 checkWaypoint(*waypoint_iterator_);
81 setNewWaypoint(robot_state, previous_command, *waypoint_iterator_, input_parameter_);
82 setInputLimits(*waypoint_iterator_, input_parameter_);
83 prev_result_ = ruckig::Result::Working;
84 } else {
85 prev_result_ = ruckig::Result::Finished;
86 }
87 }
88
90 const RobotState &robot_state, franka::Duration time_step, franka::Duration rel_time, franka::Duration abs_time,
91 const std::optional<ControlSignalType> &previous_command) override {
92 const auto expected_time_step = franka::Duration(1);
94 // In this case, we missed a couple of steps for some reason. Hence,
95 // extrapolate the way the robot does if it does not receive data
96 // (constant acceleration model). See
97 // https://frankaemika.github.io/docs/libfranka.html#under-the-hood
98 extrapolateMotion(robot_state, time_step - expected_time_step, input_parameter_, output_parameter_);
99 output_parameter_.pass_to_input(input_parameter_);
100 }
101
102 auto max_time_reached = false;
103 if (waypoint_iterator_ != waypoints_.end() && waypoint_iterator_->max_total_duration.has_value()) {
104 max_time_reached = rel_time - waypoint_started_time_ >= waypoint_iterator_->max_total_duration.value();
105 }
106
107 if (prev_result_ == ruckig::Finished || max_time_reached) {
108 if (!target_reached_time_.has_value()) {
109 target_reached_time_ = rel_time;
110 }
111 if (waypoint_iterator_ != waypoints_.end()) {
112 auto hold_target_duration = waypoint_iterator_->hold_target_duration;
113 if (waypoint_iterator_ + 1 == waypoints_.end()) {
114 // Allow cooldown of motion, so that the low-pass filter has time to
115 // adjust to target values
116 hold_target_duration = std::max(hold_target_duration, franka::Duration(10));
117 }
118 if (rel_time - target_reached_time_.value() >= hold_target_duration || max_time_reached) {
119 target_reached_time_ = std::nullopt;
120 ++waypoint_iterator_;
121 if (waypoint_iterator_ != waypoints_.end()) {
122 checkWaypoint(*waypoint_iterator_);
123 setNewWaypoint(robot_state, previous_command, *waypoint_iterator_, input_parameter_);
124 setInputLimits(*waypoint_iterator_, input_parameter_);
125 waypoint_started_time_ = rel_time;
126 }
127 }
128 }
129 if (waypoint_iterator_ == waypoints_.end()) {
131 if (!return_when_finished_) return command;
132 return franka::MotionFinished(command);
133 }
134 }
135
136 assert(waypoint_iterator_ != waypoints_.end());
137
138 prev_result_ = trajectory_generator_.update(input_parameter_, output_parameter_);
139 if (prev_result_ == ruckig::Result::Working || prev_result_ == ruckig::Result::Finished) {
140 // This is a workaround to prevent NaNs from popping up. Must be some bug
141 // in ruckig.
142 for (int i = 0; i < 7; i++) {
143 if (!input_parameter_.enabled[i]) {
144 output_parameter_.new_position[i] = 0.0;
145 output_parameter_.new_velocity[i] = 0.0;
146 output_parameter_.new_acceleration[i] = 0.0;
147 }
148 }
149 output_parameter_.pass_to_input(input_parameter_);
150 } else {
151 throw MotionPlannerException("Motion planner failed with error code " + std::to_string(prev_result_));
152 }
153
154 return getControlSignal(robot_state, time_step, previous_command, input_parameter_);
155 };
156
157 virtual void initWaypointMotion(
158 const RobotState &robot_state, const std::optional<ControlSignalType> &previous_command,
159 ruckig::InputParameter<7> &input_parameter) = 0;
160
161 virtual void setNewWaypoint(
162 const RobotState &robot_state, const std::optional<ControlSignalType> &previous_command,
163 const WaypointType &new_waypoint, ruckig::InputParameter<7> &input_parameter) = 0;
164
165 virtual void extrapolateMotion(
166 const RobotState &robot_state, const franka::Duration &time_step,
167 const ruckig::InputParameter<7> &input_parameter, ruckig::OutputParameter<7> &output_parameter) const = 0;
168
169 virtual void checkWaypoint(const WaypointType &waypoint) const {}
170
171 [[nodiscard]] virtual std::tuple<Vector7d, Vector7d, Vector7d> getAbsoluteInputLimits() const = 0;
172
174 const RobotState &robot_state, const franka::Duration &time_step,
175 const std::optional<ControlSignalType> &previous_command, const ruckig::InputParameter<7> &input_parameter) = 0;
176
177 virtual void setInputLimits(const WaypointType &waypoint, ruckig::InputParameter<7> &input_parameter) const = 0;
178
179 private:
180 std::vector<WaypointType> waypoints_;
181 bool return_when_finished_{true};
182
183 ruckig::Ruckig<7> trajectory_generator_{Robot::control_rate};
184 ruckig::Result prev_result_;
185 ruckig::InputParameter<7> input_parameter_;
186 ruckig::OutputParameter<7> output_parameter_;
187
188 typename std::vector<WaypointType>::iterator waypoint_iterator_;
189
190 std::optional<franka::Duration> target_reached_time_;
191 franka::Duration waypoint_started_time_;
192};
193
194} // namespace franky
Base class for motions.
Definition motion.hpp:24
Relative dynamics factors.
Definition relative_dynamics_factor.hpp:13
static constexpr double control_rate
Definition robot.hpp:147
A motion following multiple waypoints in a time-optimal way. Works with arbitrary initial conditions.
Definition waypoint_motion.hpp:59
virtual void extrapolateMotion(const RobotState &robot_state, const franka::Duration &time_step, const ruckig::InputParameter< 7 > &input_parameter, ruckig::OutputParameter< 7 > &output_parameter) const =0
virtual void initWaypointMotion(const RobotState &robot_state, const std::optional< ControlSignalType > &previous_command, ruckig::InputParameter< 7 > &input_parameter)=0
virtual void setInputLimits(const WaypointType &waypoint, ruckig::InputParameter< 7 > &input_parameter) const =0
WaypointMotion(std::vector< WaypointType > waypoints, bool return_when_finished=true)
Definition waypoint_motion.hpp:69
virtual void checkWaypoint(const WaypointType &waypoint) const
Definition waypoint_motion.hpp:169
virtual ControlSignalType getControlSignal(const RobotState &robot_state, const franka::Duration &time_step, const std::optional< ControlSignalType > &previous_command, const ruckig::InputParameter< 7 > &input_parameter)=0
virtual void setNewWaypoint(const RobotState &robot_state, const std::optional< ControlSignalType > &previous_command, const WaypointType &new_waypoint, ruckig::InputParameter< 7 > &input_parameter)=0
void initImpl(const RobotState &robot_state, const std::optional< ControlSignalType > &previous_command) override
Definition waypoint_motion.hpp:73
ControlSignalType nextCommandImpl(const RobotState &robot_state, franka::Duration time_step, franka::Duration rel_time, franka::Duration abs_time, const std::optional< ControlSignalType > &previous_command) override
Definition waypoint_motion.hpp:89
virtual std::tuple< Vector7d, Vector7d, Vector7d > getAbsoluteInputLimits() const =0
Definition dynamics_limit.cpp:8
std::array< double, dims > toStdD(const Eigen::Matrix< double, dims, 1 > &vector)
Definition util.hpp:18
ControlSignalType
Type of control signal.
Definition control_signal_type.hpp:8
Exception thrown if the motion planner fails.
Definition waypoint_motion.hpp:13
Full state of the robot.
Definition robot_state.hpp:23
A waypoint with a target and optional parameters.
Definition waypoint_motion.hpp:36
std::optional< franka::Duration > max_total_duration
Definition waypoint_motion.hpp:45
franka::Duration hold_target_duration
Definition waypoint_motion.hpp:43
TargetType target
Definition waypoint_motion.hpp:37
RelativeDynamicsFactor relative_dynamics_factor
Definition waypoint_motion.hpp:39
std::optional< franka::Duration > minimum_time
Definition waypoint_motion.hpp:41