Skip to content

Commit 899e8e3

Browse files
committed
fix(franka,controllers): fix osc vibration and trajectory jumping
This commit resolves two issues in the franka controllers: 1. OSC Vibration: The order of torque limiting operations in osc() and joint_controller() was reversed. Torques are now first clamped by TorqueSafetyGuardFn (with new per-joint limits) and then rate-limited. This improves stability. TorqueSafetyGuardFn was also enhanced to support per-joint min/max torque arrays. 2. Trajectory Jumping: The reset() methods in LinearPoseTrajInterpolator and LinearJointPositionTrajInterpolator were refactored. They now correctly use the robot's current position as the start for new trajectories, eliminating abrupt jumps. Redundant internal state variables were removed. 3. adds avoidance forces and removes hard push away from the limits.
1 parent 5828820 commit 899e8e3

2 files changed

Lines changed: 55 additions & 61 deletions

File tree

extensions/rcs_fr3/src/hw/Franka.cpp

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,14 @@ void PInverse(const Eigen::MatrixXd &M, Eigen::MatrixXd &M_inv,
147147
M_inv = Eigen::MatrixXd(svd.matrixV() * S_inv * svd.matrixU().transpose());
148148
}
149149

150-
void TorqueSafetyGuardFn(std::array<double, 7> &tau_d_array, double min_torque,
151-
double max_torque) {
150+
void TorqueSafetyGuardFn(std::array<double, 7> &tau_d_array,
151+
const std::array<double, 7> &min_torques,
152+
const std::array<double, 7> &max_torques) {
152153
for (size_t i = 0; i < tau_d_array.size(); i++) {
153-
if (tau_d_array[i] < min_torque) {
154-
tau_d_array[i] = min_torque;
155-
} else if (tau_d_array[i] > max_torque) {
156-
tau_d_array[i] = max_torque;
154+
if (tau_d_array[i] < min_torques[i]) {
155+
tau_d_array[i] = min_torques[i];
156+
} else if (tau_d_array[i] > max_torques[i]) {
157+
tau_d_array[i] = max_torques[i];
157158
}
158159
}
159160
}
@@ -419,18 +420,20 @@ void Franka::osc() {
419420
dist2joint_max = joint_max_.matrix() - q;
420421
dist2joint_min = q - joint_min_.matrix();
421422

423+
double activation_distance = 0.25;
422424
for (int i = 0; i < 7; i++) {
423-
if (dist2joint_max[i] < 0.25 && dist2joint_max[i] > 0.1)
424-
avoidance_force[i] += -avoidance_weights_[i] * dist2joint_max[i];
425-
if (dist2joint_min[i] < 0.25 && dist2joint_min[i] > 0.1)
426-
avoidance_force[i] += avoidance_weights_[i] * dist2joint_min[i];
425+
if (dist2joint_max[i] < activation_distance) {
426+
avoidance_force[i] +=
427+
-avoidance_weights_[i] *
428+
(1 / std::max(dist2joint_max[i], 0.001) - 1 / activation_distance);
429+
}
430+
if (dist2joint_min[i] < activation_distance) {
431+
avoidance_force[i] +=
432+
avoidance_weights_[i] *
433+
(1 / std::max(dist2joint_min[i], 0.001) - 1 / activation_distance);
434+
}
427435
}
428436
tau_d << tau_d + Nullspace * avoidance_force;
429-
for (int i = 0; i < 7; i++) {
430-
if (dist2joint_max[i] < 0.1 && tau_d[i] > 0.) tau_d[i] = 0.;
431-
if (dist2joint_min[i] < 0.1 && tau_d[i] < 0.) tau_d[i] = 0.;
432-
}
433-
434437
std::array<double, 7> tau_d_array{};
435438
Eigen::VectorXd::Map(&tau_d_array[0], 7) = tau_d;
436439

@@ -439,14 +442,16 @@ void Franka::osc() {
439442
std::chrono::high_resolution_clock::now();
440443
auto time = std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1);
441444

445+
// clamp the torques to a safe range.
446+
std::array<double, 7> min_torques = {-10.0, -10.0, -10.0, -10.0,
447+
-5.0, -5.0, -5.0};
448+
std::array<double, 7> max_torques = {10.0, 10.0, 10.0, 10.0, 5.0, 5.0, 5.0};
449+
TorqueSafetyGuardFn(tau_d_array, min_torques, max_torques);
450+
451+
// limit the rate of change of the clamped torques.
442452
std::array<double, 7> tau_d_rate_limited = franka::limitRate(
443453
franka::kMaxTorqueRate, tau_d_array, robot_state.tau_J_d);
444454

445-
// deoxys/config/control_config.yml
446-
double min_torque = -5;
447-
double max_torque = 5;
448-
TorqueSafetyGuardFn(tau_d_rate_limited, min_torque, max_torque);
449-
450455
return tau_d_rate_limited;
451456
});
452457
}
@@ -514,16 +519,31 @@ void Franka::joint_controller() {
514519

515520
tau_d << Kp.cwiseProduct(joint_pos_error) - Kd.cwiseProduct(dq);
516521

522+
// Add joint avoidance potential
523+
Eigen::Array<double, 7, 1> avoidance_weights;
524+
avoidance_weights << 1., 1., 1., 1., 1., 10., 10.;
525+
Eigen::Matrix<double, 7, 1> avoidance_force;
526+
avoidance_force.setZero();
517527
Eigen::Matrix<double, 7, 1> dist2joint_max;
518528
Eigen::Matrix<double, 7, 1> dist2joint_min;
519529

520530
dist2joint_max = joint_max_.matrix() - q;
521531
dist2joint_min = q - joint_min_.matrix();
522532

533+
double activation_distance = 0.25;
523534
for (int i = 0; i < 7; i++) {
524-
if (dist2joint_max[i] < 0.1 && tau_d[i] > 0.) tau_d[i] = 0.;
525-
if (dist2joint_min[i] < 0.1 && tau_d[i] < 0.) tau_d[i] = 0.;
535+
if (dist2joint_max[i] < activation_distance) {
536+
avoidance_force[i] +=
537+
-avoidance_weights[i] *
538+
(1 / std::max(dist2joint_max[i], 0.001) - 1 / activation_distance);
539+
}
540+
if (dist2joint_min[i] < activation_distance) {
541+
avoidance_force[i] +=
542+
avoidance_weights[i] *
543+
(1 / std::max(dist2joint_min[i], 0.001) - 1 / activation_distance);
544+
}
526545
}
546+
tau_d << tau_d + avoidance_force;
527547

528548
std::array<double, 7> tau_d_array{};
529549
Eigen::VectorXd::Map(&tau_d_array[0], 7) = tau_d;
@@ -533,14 +553,17 @@ void Franka::joint_controller() {
533553
std::chrono::high_resolution_clock::now();
534554
auto time = std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1);
535555

556+
// deoxys/config/control_config.yml
557+
// First clamp the torques to a safe range.
558+
std::array<double, 7> min_torques = {-10.0, -10.0, -10.0, -10.0,
559+
-5.0, -5.0, -5.0};
560+
std::array<double, 7> max_torques = {10.0, 10.0, 10.0, 10.0, 5.0, 5.0, 5.0};
561+
TorqueSafetyGuardFn(tau_d_array, min_torques, max_torques);
562+
563+
// Then limit the rate of change of the clamped torques.
536564
std::array<double, 7> tau_d_rate_limited = franka::limitRate(
537565
franka::kMaxTorqueRate, tau_d_array, robot_state.tau_J_d);
538566

539-
// deoxys/config/control_config.yml
540-
double min_torque = -5;
541-
double max_torque = 5;
542-
TorqueSafetyGuardFn(tau_d_rate_limited, min_torque, max_torque);
543-
544567
return tau_d_rate_limited;
545568
});
546569
}

include/rcs/LinearPoseTrajInterpolator.h

Lines changed: 5 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,24 @@ class LinearPoseTrajInterpolator {
1010
Eigen::Vector3d p_start_;
1111
Eigen::Vector3d p_goal_;
1212
Eigen::Vector3d last_p_t_;
13-
Eigen::Vector3d prev_p_goal_;
1413

1514
Eigen::Quaterniond q_start_;
1615
Eigen::Quaterniond q_goal_;
1716
Eigen::Quaterniond last_q_t_;
18-
Eigen::Quaterniond prev_q_goal_;
1917

2018
double dt_;
2119
double last_time_;
2220
double max_time_;
2321
double start_time_;
2422
bool start_;
25-
bool first_goal_;
2623

2724
public:
2825
inline LinearPoseTrajInterpolator()
2926
: dt_(0.),
3027
last_time_(0.),
3128
max_time_(1.),
3229
start_time_(0.),
33-
start_(false),
34-
first_goal_(true){};
30+
start_(false){};
3531

3632
inline ~LinearPoseTrajInterpolator(){};
3733

@@ -49,22 +45,8 @@ class LinearPoseTrajInterpolator {
4945

5046
start_ = false;
5147

52-
if (first_goal_) {
53-
p_start_ = p_start;
54-
q_start_ = q_start;
55-
56-
prev_p_goal_ = p_start;
57-
prev_q_goal_ = q_start;
58-
first_goal_ = false;
59-
} else {
60-
// If the goal is already set, use prev goal as the starting point of
61-
// interpolation.
62-
prev_p_goal_ = p_goal_;
63-
prev_q_goal_ = q_goal_;
64-
65-
p_start_ = prev_p_goal_;
66-
q_start_ = prev_q_goal_;
67-
}
48+
p_start_ = p_start;
49+
q_start_ = q_start;
6850

6951
p_goal_ = p_goal;
7052
q_goal_ = q_goal;
@@ -104,14 +86,12 @@ class LinearJointPositionTrajInterpolator {
10486
Vector7d q_goal_;
10587

10688
Vector7d last_q_t_;
107-
Vector7d prev_q_goal_;
10889

10990
double dt_;
11091
double last_time_;
11192
double max_time_;
11293
double start_time_;
11394
bool start_;
114-
bool first_goal_;
11595

11696
double interpolation_fraction_; // fraction of actual interpolation within an
11797
// interval
@@ -122,8 +102,7 @@ class LinearJointPositionTrajInterpolator {
122102
last_time_(0.),
123103
max_time_(1.),
124104
start_time_(0.),
125-
start_(false),
126-
first_goal_(true){};
105+
start_(false){};
127106

128107
inline ~LinearJointPositionTrajInterpolator(){};
129108

@@ -141,15 +120,7 @@ class LinearJointPositionTrajInterpolator {
141120

142121
start_ = false;
143122

144-
if (first_goal_) {
145-
q_start_ = q_start;
146-
prev_q_goal_ = q_start;
147-
first_goal_ = false;
148-
// std::cout << "First goal of the interpolation" << std::endl;
149-
} else {
150-
prev_q_goal_ = q_goal_;
151-
q_start_ = prev_q_goal_;
152-
}
123+
q_start_ = q_start;
153124
q_goal_ = q_goal;
154125
};
155126

0 commit comments

Comments
 (0)