Skip to content

Commit 1d96350

Browse files
committed
fix the soft limiting logic and add respective tests
1 parent 7f8ab33 commit 1d96350

File tree

2 files changed

+47
-16
lines changed

2 files changed

+47
-16
lines changed

joint_limits/src/joint_soft_limiter.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,13 @@ bool JointSoftLimiter::on_enforce(
9696
double soft_max_vel = std::numeric_limits<double>::infinity();
9797
double position = std::numeric_limits<double>::infinity();
9898

99-
if (prev_command_.has_position() && std::isfinite(prev_command_.position.value()))
99+
if (actual.has_position())
100100
{
101-
position = prev_command_.position.value();
101+
position = actual.position.value();
102102
}
103-
else if (actual.has_position())
103+
else if (prev_command_.has_position() && std::isfinite(prev_command_.position.value()))
104104
{
105-
position = actual.position.value();
105+
position = prev_command_.position.value();
106106
}
107107

108108
if (hard_limits.has_velocity_limits)
@@ -122,15 +122,17 @@ bool JointSoftLimiter::on_enforce(
122122
-soft_joint_limits.k_position * (position - soft_joint_limits.max_position),
123123
-hard_limits.max_velocity, hard_limits.max_velocity);
124124

125-
if ((position < hard_limits.min_position) || (position > hard_limits.max_position))
125+
if (
126+
(position < (hard_limits.min_position - internal::POSITION_BOUNDS_TOLERANCE)) ||
127+
(position > (hard_limits.max_position + internal::POSITION_BOUNDS_TOLERANCE)))
126128
{
127129
soft_min_vel = 0.0;
128130
soft_max_vel = 0.0;
129131
}
130132
else if (
131133
(position < soft_joint_limits.min_position) || (position > soft_joint_limits.max_position))
132134
{
133-
constexpr double soft_limit_reach_velocity = 1.0 * (M_PI / 180.0);
135+
const double soft_limit_reach_velocity = 1.0 * (M_PI / 180.0);
134136
soft_min_vel = std::copysign(soft_limit_reach_velocity, soft_min_vel);
135137
soft_max_vel = std::copysign(soft_limit_reach_velocity, soft_max_vel);
136138
}

joint_limits/test/test_joint_soft_limiter.cpp

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,11 @@ TEST_F(JointSoftLimiterTest, check_desired_position_only_cases)
214214
desired_state_.position = 2.0;
215215
ASSERT_TRUE(joint_limiter_->enforce(actual_state_, desired_state_, period));
216216
EXPECT_NEAR(desired_state_.position.value(), 1.0, COMMON_THRESHOLD);
217+
actual_state_.position = 0.95;
218+
desired_state_.position = 2.0;
219+
ASSERT_TRUE(joint_limiter_->enforce(actual_state_, desired_state_, period));
220+
EXPECT_NEAR(desired_state_.position.value(), 1.95, COMMON_THRESHOLD);
221+
actual_state_.position = 1.5;
217222
desired_state_.position = 2.0;
218223
ASSERT_FALSE(joint_limiter_->enforce(actual_state_, desired_state_, period));
219224
EXPECT_NEAR(desired_state_.position.value(), 2.0, COMMON_THRESHOLD);
@@ -228,34 +233,58 @@ TEST_F(JointSoftLimiterTest, check_desired_position_only_cases)
228233
desired_state_.position = 2.0;
229234
ASSERT_TRUE(joint_limiter_->enforce(actual_state_, desired_state_, period));
230235
EXPECT_NEAR(desired_state_.position.value(), 1.0, COMMON_THRESHOLD);
236+
actual_state_.position = 0.45;
237+
desired_state_.position = 2.0;
238+
ASSERT_TRUE(joint_limiter_->enforce(actual_state_, desired_state_, period));
239+
EXPECT_NEAR(desired_state_.position.value(), 1.45, COMMON_THRESHOLD);
240+
actual_state_.position = 0.95;
231241
desired_state_.position = 2.0;
232242
ASSERT_TRUE(joint_limiter_->enforce(actual_state_, desired_state_, period));
233243
EXPECT_NEAR(desired_state_.position.value(), 1.5, COMMON_THRESHOLD);
234244

235-
soft_limits.k_position = 2.0;
245+
// The case of no actual position feedback
246+
soft_limits.k_position = 0.5;
236247
soft_limits.max_position = 1.5;
237248
soft_limits.min_position = -1.5;
238249
ASSERT_TRUE(Init(limits, soft_limits));
239-
desired_state_.position = 2.0;
240-
ASSERT_TRUE(joint_limiter_->enforce(actual_state_, desired_state_, period));
241-
EXPECT_NEAR(desired_state_.position.value(), 1.0, COMMON_THRESHOLD);
250+
actual_state_.position = std::nullopt;
251+
desired_state_.position = 0.2;
252+
ASSERT_FALSE(joint_limiter_->enforce(actual_state_, desired_state_, period));
253+
EXPECT_NEAR(desired_state_.position.value(), 0.2, COMMON_THRESHOLD);
254+
auto prev_command_state = desired_state_;
255+
while (desired_state_.position.value() < (soft_limits.max_position - COMMON_THRESHOLD))
256+
{
257+
desired_state_.position = 2.0;
258+
double expected_pos =
259+
prev_command_state.position.value() +
260+
(soft_limits.max_position - prev_command_state.position.value()) * soft_limits.k_position;
261+
ASSERT_TRUE(joint_limiter_->enforce(actual_state_, desired_state_, period));
262+
EXPECT_NEAR(desired_state_.position.value(), expected_pos, COMMON_THRESHOLD);
263+
prev_command_state = desired_state_;
264+
}
242265
desired_state_.position = 2.0;
243266
ASSERT_TRUE(joint_limiter_->enforce(actual_state_, desired_state_, period));
244267
EXPECT_NEAR(desired_state_.position.value(), 1.5, COMMON_THRESHOLD);
245268

269+
// More generic test case
246270
soft_limits.k_position = 0.5;
247271
soft_limits.max_position = 2.0;
248272
soft_limits.min_position = -2.0;
249273
ASSERT_TRUE(Init(limits, soft_limits));
250274
desired_state_.position = 2.0;
251275
ASSERT_TRUE(joint_limiter_->enforce(actual_state_, desired_state_, period));
252276
EXPECT_NEAR(desired_state_.position.value(), 1.0, COMMON_THRESHOLD);
253-
desired_state_.position = 2.0;
254-
ASSERT_TRUE(joint_limiter_->enforce(actual_state_, desired_state_, period));
255-
EXPECT_NEAR(desired_state_.position.value(), 1.5, COMMON_THRESHOLD);
256-
desired_state_.position = 2.0;
257-
ASSERT_TRUE(joint_limiter_->enforce(actual_state_, desired_state_, period));
258-
EXPECT_NEAR(desired_state_.position.value(), 1.75, COMMON_THRESHOLD);
277+
actual_state_.position = 0.2;
278+
while (actual_state_.position.value() < (desired_state_.position.value() - COMMON_THRESHOLD))
279+
{
280+
desired_state_.position = 2.0;
281+
double expected_pos =
282+
actual_state_.position.value() +
283+
(soft_limits.max_position - actual_state_.position.value()) * soft_limits.k_position;
284+
ASSERT_TRUE(joint_limiter_->enforce(actual_state_, desired_state_, period));
285+
EXPECT_NEAR(desired_state_.position.value(), expected_pos, COMMON_THRESHOLD);
286+
actual_state_.position = expected_pos;
287+
}
259288

260289
// Now test when there are no position limits and soft limits, then the desired position is not
261290
// saturated

0 commit comments

Comments
 (0)