Skip to content

Commit a971b49

Browse files
Implemented proper elbow handling
1 parent aed9087 commit a971b49

17 files changed

+250
-77
lines changed

include/franky/elbow_state.hpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#pragma once
2+
3+
#include <optional>
4+
#include <array>
5+
6+
namespace franky {
7+
8+
/**
9+
* @brief Flip direction of a joint.
10+
*/
11+
enum class FlipDirection {
12+
kNegative = -1,
13+
kNeutral = 0,
14+
kPositive = 1
15+
};
16+
17+
/**
18+
* @brief Elbow state of the robot.
19+
*
20+
* This class encapsulates the elbow state of a robot, which comprises the position of the 3rd joint
21+
* and the flip direction of the 4th joint. For details see
22+
* https://frankaemika.github.io/libfranka/0.15.0/structfranka_1_1RobotState.html#a43485841c427d70e7f36a912cc3116d1
23+
*/
24+
class ElbowState {
25+
public:
26+
/**
27+
* @brief Construct an elbow state with the given joint position and optional flip direction.
28+
*
29+
* @param joint_3_pos The position of the 3rd joint.
30+
* @param joint_4_flip The flip direction of the 4th joint.
31+
*/
32+
explicit ElbowState(double joint_3_pos, std::optional<FlipDirection> joint_4_flip = std::nullopt)
33+
: joint_3_pos_(joint_3_pos), joint_4_flip_(joint_4_flip) {}
34+
35+
/**
36+
* @brief Construct an elbow state from an array containing joint position and flip direction.
37+
*
38+
* @param elbow_state The joint position and flip direction as a double array.
39+
*/
40+
explicit ElbowState(const std::array<double, 2>& elbow_state)
41+
: joint_3_pos_(elbow_state[0]),
42+
joint_4_flip_([&]() -> std::optional<FlipDirection> {
43+
if (elbow_state[1] < 0.0) {
44+
return FlipDirection::kNegative;
45+
} else if (elbow_state[1] == 0.0) {
46+
return FlipDirection::kNeutral;
47+
} else {
48+
return FlipDirection::kPositive;
49+
}
50+
}()) {}
51+
52+
ElbowState(const ElbowState&) = default;
53+
ElbowState() = default;
54+
55+
/**
56+
* @brief Get the joint position and flip direction as an array.
57+
*
58+
* @param default_flip_direction The default flip direction to use if not explicitly set.
59+
* @return std::array containing the joint position and flip direction.
60+
*/
61+
[[nodiscard]] inline std::array<double, 2> to_array(
62+
FlipDirection default_flip_direction = FlipDirection::kNegative) const {
63+
return {joint_3_pos_, static_cast<double>(joint_4_flip_.value_or(default_flip_direction))};
64+
}
65+
66+
/**
67+
* @brief The position of the 3rd joint.
68+
*/
69+
[[nodiscard]] inline double joint_3_pos() const { return joint_3_pos_; }
70+
71+
/**
72+
* @brief The flip direction of the 4th joint.
73+
*/
74+
[[nodiscard]] inline std::optional<FlipDirection> joint_4_flip() const { return joint_4_flip_; }
75+
76+
private:
77+
double joint_3_pos_{0.0};
78+
std::optional<FlipDirection> joint_4_flip_{std::nullopt};
79+
};
80+
81+
} // namespace franky

include/franky/motion/cartesian_velocity_waypoint_motion.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ class CartesianVelocityWaypointMotion : public VelocityWaypointMotion<franka::Ca
5252
[[nodiscard]] std::tuple<Vector7d, Vector7d, Vector7d> getAbsoluteInputLimits() const override;
5353

5454
[[nodiscard]] franka::CartesianVelocities getControlSignal(
55-
const franka::Duration &time_step, const ruckig::InputParameter<7> &input_parameter) override;
55+
const franka::RobotState &robot_state,
56+
const franka::Duration &time_step,
57+
const std::optional<franka::CartesianVelocities> &previous_command,
58+
const ruckig::InputParameter<7> &input_parameter) override;
5659

5760
private:
5861
Affine ee_frame_;

include/franky/motion/cartesian_waypoint_motion.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,10 @@ class CartesianWaypointMotion : public PositionWaypointMotion<franka::CartesianP
5454
[[nodiscard]] std::tuple<Vector7d, Vector7d, Vector7d> getAbsoluteInputLimits() const override;
5555

5656
[[nodiscard]] franka::CartesianPose getControlSignal(
57-
const franka::Duration &time_step, const ruckig::InputParameter<7> &input_parameter) override;
57+
const franka::RobotState &robot_state,
58+
const franka::Duration &time_step,
59+
const std::optional<franka::CartesianPose> &previous_command,
60+
const ruckig::InputParameter<7> &input_parameter) override;
5861

5962
private:
6063
CartesianState target_state_;

include/franky/motion/joint_velocity_waypoint_motion.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ class JointVelocityWaypointMotion : public VelocityWaypointMotion<franka::JointV
4545
[[nodiscard]] std::tuple<Vector7d, Vector7d, Vector7d> getAbsoluteInputLimits() const override;
4646

4747
[[nodiscard]] franka::JointVelocities getControlSignal(
48-
const franka::Duration &time_step, const ruckig::InputParameter<7> &input_parameter) override;
48+
const franka::RobotState &robot_state,
49+
const franka::Duration &time_step,
50+
const std::optional<franka::JointVelocities> &previous_command,
51+
const ruckig::InputParameter<7> &input_parameter) override;
4952
};
5053

5154
} // namespace franky

include/franky/motion/joint_waypoint_motion.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ class JointWaypointMotion : public PositionWaypointMotion<franka::JointPositions
4343
[[nodiscard]] std::tuple<Vector7d, Vector7d, Vector7d> getAbsoluteInputLimits() const override;
4444

4545
[[nodiscard]] franka::JointPositions getControlSignal(
46-
const franka::Duration &time_step, const ruckig::InputParameter<7> &input_parameter) override;
46+
const franka::RobotState &robot_state,
47+
const franka::Duration &time_step,
48+
const std::optional<franka::JointPositions> &previous_command,
49+
const ruckig::InputParameter<7> &input_parameter) override;
4750
};
4851

4952
} // namespace franky

include/franky/motion/waypoint_motion.hpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,10 @@ class WaypointMotion : public Motion<ControlSignalType> {
103103
}
104104
}
105105
if (waypoint_iterator_ == waypoints_.end()) {
106-
auto output_pose = getControlSignal(sub_step, input_parameter_);
106+
auto command = getControlSignal(robot_state, time_step, previous_command, input_parameter_);
107107
if (!return_when_finished_)
108-
return output_pose;
109-
return franka::MotionFinished(output_pose);
108+
return command;
109+
return franka::MotionFinished(command);
110110
} else {
111111
checkWaypoint(*waypoint_iterator_);
112112
setNewWaypoint(robot_state, previous_command, *waypoint_iterator_, input_parameter_);
@@ -123,7 +123,7 @@ class WaypointMotion : public Motion<ControlSignalType> {
123123
}
124124
}
125125

126-
return getControlSignal(sub_step, input_parameter_);
126+
return getControlSignal(robot_state, time_step, previous_command, input_parameter_);
127127
};
128128

129129
virtual void initWaypointMotion(
@@ -142,7 +142,10 @@ class WaypointMotion : public Motion<ControlSignalType> {
142142
[[nodiscard]] virtual std::tuple<Vector7d, Vector7d, Vector7d> getAbsoluteInputLimits() const = 0;
143143

144144
[[nodiscard]] virtual ControlSignalType getControlSignal(
145-
const franka::Duration &time_step, const ruckig::InputParameter<7> &input_parameter) = 0;
145+
const franka::RobotState &robot_state,
146+
const franka::Duration &time_step,
147+
const std::optional<ControlSignalType> &previous_command,
148+
const ruckig::InputParameter<7> &input_parameter) = 0;
146149

147150
virtual void setInputLimits(const WaypointType &waypoint, ruckig::InputParameter<7> &input_parameter) const = 0;
148151

include/franky/robot.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ class Robot : public franka::Robot {
248248
*/
249249
[[nodiscard]] inline CartesianState currentCartesianState() {
250250
auto s = state();
251-
return {{Affine(Eigen::Matrix4d::Map(s.O_T_EE.data())), s.elbow[0]},
251+
return {{Affine(Eigen::Matrix4d::Map(s.O_T_EE.data())), ElbowState{s.elbow}},
252252
RobotVelocity(franka::CartesianVelocities(s.O_dP_EE_c, s.delbow_c))};
253253
}
254254

include/franky/robot_pose.hpp

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <franka/control_types.h>
66

77
#include "franky/types.hpp"
8+
#include "franky/elbow_state.hpp"
89

910
namespace franky {
1011

@@ -24,31 +25,33 @@ class RobotPose {
2425
#pragma clang diagnostic ignored "-Wimplicit-conversion"
2526
/**
2627
* @param end_effector_pose The pose of the end effector.
27-
* @param elbow_position The position of the elbow. Optional.
28+
* @param elbow_state The state of the elbow. Optional.
2829
*/
29-
RobotPose(Affine end_effector_pose, std::optional<double> elbow_position = std::nullopt);
30+
RobotPose(Affine end_effector_pose, std::optional<ElbowState> elbow_state = std::nullopt);
3031
#pragma clang diagnostic pop
3132

3233
/**
33-
* @param vector_repr The vector representation of the pose.
34-
* @param ignore_elbow Whether to ignore the elbow position. Default is false.
34+
* @param vector_repr The vector representation of the pose.
35+
* @param ignore_elbow Whether to ignore the elbow state. Default is false.
36+
* @param flip_direction The flip direction to use if the elbow is not ignored. Default is negative.
3537
*/
36-
explicit RobotPose(const Vector7d &vector_repr, bool ignore_elbow = false);
38+
explicit RobotPose(
39+
const Vector7d &vector_repr, bool ignore_elbow = false, FlipDirection flip_direction = FlipDirection::kNegative);
3740

3841
/**
3942
* @param vector_repr The vector representation of the pose.
40-
* @param elbow_position The position of the elbow. Optional.
43+
* @param elbow_state The state of the elbow. Optional.
4144
*/
42-
explicit RobotPose(const Vector6d &vector_repr, std::optional<double> elbow_position = std::nullopt);
45+
explicit RobotPose(const Vector6d &vector_repr, std::optional<ElbowState> elbow_state = std::nullopt);
4346

4447
/**
4548
* @param franka_pose The franka pose.
4649
*/
47-
explicit RobotPose(franka::CartesianPose franka_pose);
50+
explicit RobotPose(const franka::CartesianPose &franka_pose);
4851

4952
/**
5053
* @brief Get the vector representation of the pose, which consists of the end effector position and orientation
51-
* (as rotation vector) and the elbow position.
54+
* (as rotation vector) and the elbow position. Does not contain the flip component of the elbow state.
5255
*
5356
* @return The vector representation of the pose.
5457
*/
@@ -57,9 +60,11 @@ class RobotPose {
5760
/**
5861
* @brief Convert this pose to a franka pose.
5962
*
63+
* @param default_elbow_flip_direction The default flip direction to use if the elbow flip direction is not set.
6064
* @return The franka pose.
6165
*/
62-
[[nodiscard]] franka::CartesianPose as_franka_pose() const;
66+
[[nodiscard]] franka::CartesianPose as_franka_pose(
67+
FlipDirection default_elbow_flip_direction = FlipDirection::kNegative) const;
6368

6469
/**
6570
* @brief Transform this pose with a given affine transformation from the left side.
@@ -68,7 +73,7 @@ class RobotPose {
6873
* @return The transformed robot pose.
6974
*/
7075
[[nodiscard]] inline RobotPose leftTransform(const Affine &transform) const {
71-
return {transform * end_effector_pose_, elbow_position_};
76+
return {transform * end_effector_pose_, elbow_state_};
7277
}
7378

7479
/**
@@ -78,7 +83,7 @@ class RobotPose {
7883
* @return The transformed robot pose.
7984
*/
8085
[[nodiscard]] inline RobotPose rightTransform(const Affine &transform) const {
81-
return {end_effector_pose_ * transform, elbow_position_};
86+
return {end_effector_pose_ * transform, elbow_state_};
8287
}
8388

8489
/**
@@ -93,13 +98,13 @@ class RobotPose {
9398
}
9499

95100
/**
96-
* @brief Get the pose with a new elbow position.
101+
* @brief Get the pose with a new elbow state.
97102
*
98-
* @param elbow_position The new elbow position.
99-
* @return The pose with the new elbow position.
103+
* @param elbow_state The new elbow state.
104+
* @return The pose with the new elbow state.
100105
*/
101-
[[nodiscard]] inline RobotPose withElbowPosition(const std::optional<double> elbow_position) const {
102-
return {end_effector_pose_, elbow_position};
106+
[[nodiscard]] inline RobotPose withElbowState(const std::optional<ElbowState> elbow_state) const {
107+
return {end_effector_pose_, elbow_state};
103108
}
104109

105110
/**
@@ -112,17 +117,17 @@ class RobotPose {
112117
}
113118

114119
/**
115-
* @brief Get the elbow position.
120+
* @brief Get the elbow state.
116121
*
117-
* @return The elbow position.
122+
* @return The elbow state.
118123
*/
119-
[[nodiscard]] inline std::optional<double> elbow_position() const {
120-
return elbow_position_;
124+
[[nodiscard]] inline std::optional<ElbowState> elbow_state() const {
125+
return elbow_state_;
121126
}
122127

123128
private:
124129
Affine end_effector_pose_;
125-
std::optional<double> elbow_position_;
130+
std::optional<ElbowState> elbow_state_;
126131
};
127132

128133
inline RobotPose operator*(const RobotPose &robot_pose, const Affine &right_transform) {

include/franky/robot_velocity.hpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include "franky/types.hpp"
88
#include "franky/twist.hpp"
9+
#include "franky/elbow_state.hpp"
910

1011
namespace franky {
1112

@@ -59,12 +60,14 @@ class RobotVelocity {
5960
/**
6061
* @brief Get the franka velocity.
6162
*
62-
* @param elbow_position The elbow position to use. Note, that franka::CartesianVelocities contains the elbow
63-
* position and not the elbow velocity, contrary to RobotVelocity.
63+
* @param elbow_state The elbow state to use. Note, that franka::CartesianVelocities contains the
64+
* elbow state and not the elbow velocity, contrary to RobotVelocity.
65+
* @param default_elbow_flip_direction The default flip direction of the elbow if it is not set.
6466
* @return The franka velocity.
6567
*/
6668
[[nodiscard]] franka::CartesianVelocities as_franka_velocity(
67-
std::optional<double> elbow_position = std::nullopt) const;
69+
const std::optional<ElbowState> &elbow_state = std::nullopt,
70+
FlipDirection default_elbow_flip_direction = FlipDirection::kNegative) const;
6871

6972
/**
7073
* @brief Transform the frame of the velocity by applying the given affine transform.

python/bind_enums.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,9 @@ void bind_enums(py::module &m) {
3434
.value("Reflex", franka::RobotMode::kReflex)
3535
.value("UserStopped", franka::RobotMode::kUserStopped)
3636
.value("AutomaticErrorRecovery", franka::RobotMode::kAutomaticErrorRecovery);
37+
38+
py::enum_<FlipDirection>(m, "FlipDirection")
39+
.value("Negative", FlipDirection::kNegative)
40+
.value("Neutral", FlipDirection::kNeutral)
41+
.value("Positive", FlipDirection::kPositive);
3742
}

0 commit comments

Comments
 (0)