Skip to content

Commit 7061ac4

Browse files
authored
Fix the crashing joint limiters when used with multiple interfaces (#2371)
1 parent ce8d7c1 commit 7061ac4

File tree

7 files changed

+76
-64
lines changed

7 files changed

+76
-64
lines changed

hardware_interface/src/resource_manager.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -740,7 +740,7 @@ class ResourceStorage
740740
std::vector<joint_limits::SoftJointLimits> soft_limits;
741741
const std::vector<joint_limits::JointLimits> hard_limits{limits};
742742
joint_limits::JointInterfacesCommandLimiterData data;
743-
data.joint_name = joint_name;
743+
data.set_joint_name(joint_name);
744744
limiters_data_.insert({joint_name, data});
745745
// If the joint limits is found in the softlimits, then extract it
746746
if (hw_info.soft_limits.find(joint_name) != hw_info.soft_limits.end())
@@ -1025,7 +1025,7 @@ class ResourceStorage
10251025
{
10261026
is_limited = false;
10271027
joint_limits::JointInterfacesCommandLimiterData data;
1028-
data.joint_name = joint_name;
1028+
data.set_joint_name(joint_name);
10291029
update_joint_limiters_data(data.joint_name, state_interface_map_, data.actual);
10301030
if (interface_name == hardware_interface::HW_IF_POSITION)
10311031
{

joint_limits/include/joint_limits/data_structures.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ struct JointControlInterfacesData
7070
std::string to_string() const
7171
{
7272
std::string str;
73+
str += "Joint: '" + joint_name + "', ";
7374
if (has_position())
7475
{
7576
str += "position: " + std::to_string(position.value()) + ", ";
@@ -117,6 +118,15 @@ struct JointInterfacesCommandLimiterData
117118

118119
bool has_limited_data() const { return limited.has_data(); }
119120

121+
void set_joint_name(const std::string & name)
122+
{
123+
joint_name = name;
124+
actual.joint_name = name;
125+
command.joint_name = name;
126+
limited.joint_name = name;
127+
prev_command.joint_name = name;
128+
}
129+
120130
std::string to_string() const
121131
{
122132
return fmt::format(

joint_limits/include/joint_limits/joint_limits_helpers.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ constexpr double POSITION_BOUNDS_TOLERANCE = 0.002;
3232
constexpr double OUT_OF_BOUNDS_EXCEPTION_TOLERANCE = 0.0087;
3333
} // namespace internal
3434

35+
/**
36+
* @brief Updates the previous command with the desired command.
37+
* @param prev_command The previous command to update.
38+
* @param desired The desired command which is limited.
39+
*/
40+
void update_prev_command(
41+
const JointControlInterfacesData & desired, JointControlInterfacesData & prev_command);
42+
3543
/**
3644
* @brief Checks if a value is limited by the given limits.
3745
* @param value The value to check.

joint_limits/src/joint_limits_helpers.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,32 @@ void verify_actual_position_within_limits(
7272
}
7373
} // namespace internal
7474

75+
void update_prev_command(
76+
const JointControlInterfacesData & desired, JointControlInterfacesData & prev_command)
77+
{
78+
if (desired.has_position())
79+
{
80+
prev_command.position = desired.position;
81+
}
82+
if (desired.has_velocity())
83+
{
84+
prev_command.velocity = desired.velocity;
85+
}
86+
if (desired.has_effort())
87+
{
88+
prev_command.effort = desired.effort;
89+
}
90+
if (desired.has_acceleration())
91+
{
92+
prev_command.acceleration = desired.acceleration;
93+
}
94+
if (desired.has_jerk())
95+
{
96+
prev_command.jerk = desired.jerk;
97+
}
98+
prev_command.joint_name = desired.joint_name;
99+
}
100+
75101
bool is_limited(double value, double min, double max) { return value < min || value > max; }
76102

77103
PositionLimits compute_position_limits(

joint_limits/src/joint_range_limiter.cpp

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -61,45 +61,26 @@ bool JointSaturationLimiter<JointControlInterfacesData>::on_enforce(
6161
// The following conditional filling is needed for cases of having certain information missing
6262
if (!prev_command_.has_data())
6363
{
64-
if (actual.has_position())
64+
if (desired.has_position())
6565
{
66-
prev_command_.position = actual.position;
66+
prev_command_.position = actual.has_position() ? actual.position : desired.position;
6767
}
68-
else if (desired.has_position())
68+
if (desired.has_velocity())
6969
{
70-
prev_command_.position = desired.position;
70+
prev_command_.velocity = actual.has_velocity() ? actual.velocity : desired.velocity;
7171
}
72-
if (actual.has_velocity())
72+
if (desired.has_effort())
7373
{
74-
prev_command_.velocity = actual.velocity;
74+
prev_command_.effort = actual.has_effort() ? actual.effort : desired.effort;
7575
}
76-
else if (desired.has_velocity())
76+
if (desired.has_acceleration())
7777
{
78-
prev_command_.velocity = desired.velocity;
78+
prev_command_.acceleration =
79+
actual.has_acceleration() ? actual.acceleration : desired.acceleration;
7980
}
80-
if (actual.has_effort())
81+
if (desired.has_jerk())
8182
{
82-
prev_command_.effort = actual.effort;
83-
}
84-
else if (desired.has_effort())
85-
{
86-
prev_command_.effort = desired.effort;
87-
}
88-
if (actual.has_acceleration())
89-
{
90-
prev_command_.acceleration = actual.acceleration;
91-
}
92-
else if (desired.has_acceleration())
93-
{
94-
prev_command_.acceleration = desired.acceleration;
95-
}
96-
if (actual.has_jerk())
97-
{
98-
prev_command_.jerk = actual.jerk;
99-
}
100-
else if (desired.has_jerk())
101-
{
102-
prev_command_.jerk = desired.jerk;
83+
prev_command_.jerk = actual.has_jerk() ? actual.jerk : desired.jerk;
10384
}
10485
if (actual.has_data())
10586
{
@@ -159,7 +140,7 @@ bool JointSaturationLimiter<JointControlInterfacesData>::on_enforce(
159140
desired.jerk = std::clamp(desired.jerk.value(), -joint_limits.max_jerk, joint_limits.max_jerk);
160141
}
161142

162-
prev_command_ = desired;
143+
update_prev_command(desired, prev_command_);
163144

164145
return limits_enforced;
165146
}

joint_limits/src/joint_soft_limiter.cpp

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -44,45 +44,26 @@ bool JointSoftLimiter::on_enforce(
4444

4545
if (!prev_command_.has_data())
4646
{
47-
if (actual.has_position())
47+
if (desired.has_position())
4848
{
49-
prev_command_.position = actual.position;
49+
prev_command_.position = actual.has_position() ? actual.position : desired.position;
5050
}
51-
else if (desired.has_position())
51+
if (desired.has_velocity())
5252
{
53-
prev_command_.position = desired.position;
53+
prev_command_.velocity = actual.has_velocity() ? actual.velocity : desired.velocity;
5454
}
55-
if (actual.has_velocity())
55+
if (desired.has_effort())
5656
{
57-
prev_command_.velocity = actual.velocity;
57+
prev_command_.effort = actual.has_effort() ? actual.effort : desired.effort;
5858
}
59-
else if (desired.has_velocity())
59+
if (desired.has_acceleration())
6060
{
61-
prev_command_.velocity = desired.velocity;
61+
prev_command_.acceleration =
62+
actual.has_acceleration() ? actual.acceleration : desired.acceleration;
6263
}
63-
if (actual.has_effort())
64+
if (desired.has_jerk())
6465
{
65-
prev_command_.effort = actual.effort;
66-
}
67-
else if (desired.has_effort())
68-
{
69-
prev_command_.effort = desired.effort;
70-
}
71-
if (actual.has_acceleration())
72-
{
73-
prev_command_.acceleration = actual.acceleration;
74-
}
75-
else if (desired.has_acceleration())
76-
{
77-
prev_command_.acceleration = desired.acceleration;
78-
}
79-
if (actual.has_jerk())
80-
{
81-
prev_command_.jerk = actual.jerk;
82-
}
83-
else if (desired.has_jerk())
84-
{
85-
prev_command_.jerk = desired.jerk;
66+
prev_command_.jerk = actual.has_jerk() ? actual.jerk : desired.jerk;
8667
}
8768
if (actual.has_data())
8869
{
@@ -266,7 +247,7 @@ bool JointSoftLimiter::on_enforce(
266247
limits_enforced = true;
267248
}
268249

269-
prev_command_ = desired;
250+
update_prev_command(desired, prev_command_);
270251

271252
return limits_enforced;
272253
}

joint_limits/test/test_joint_soft_limiter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,7 @@ TEST_F(JointSoftLimiterTest, check_desired_effort_only_cases)
548548
limits.max_effort = 200.0;
549549
joint_limits::SoftJointLimits soft_limits;
550550
ASSERT_TRUE(Init(limits, soft_limits));
551+
last_commanded_state_ = {};
551552
ASSERT_TRUE(joint_limiter_->configure(last_commanded_state_));
552553

553554
// Reset the desired and actual states
@@ -651,6 +652,7 @@ TEST_F(JointSoftLimiterTest, check_desired_effort_only_cases)
651652
// Check with high values of k_velocity (hard limits should be considered)
652653
soft_limits.k_velocity = 5000.0;
653654
ASSERT_TRUE(Init(limits, soft_limits));
655+
last_commanded_state_ = {};
654656
ASSERT_TRUE(joint_limiter_->configure(last_commanded_state_));
655657

656658
for (auto act_pos :
@@ -674,6 +676,7 @@ TEST_F(JointSoftLimiterTest, check_desired_effort_only_cases)
674676
// Check with low values of k_velocity
675677
soft_limits.k_velocity = 300.0;
676678
ASSERT_TRUE(Init(limits, soft_limits));
679+
last_commanded_state_ = {};
677680
ASSERT_TRUE(joint_limiter_->configure(last_commanded_state_));
678681

679682
for (auto act_pos :
@@ -702,6 +705,7 @@ TEST_F(JointSoftLimiterTest, check_desired_effort_only_cases)
702705
soft_limits.min_position = -4.0;
703706
soft_limits.max_position = 4.0;
704707
ASSERT_TRUE(Init(limits, soft_limits));
708+
last_commanded_state_ = {};
705709
ASSERT_TRUE(joint_limiter_->configure(last_commanded_state_));
706710

707711
test_limit_enforcing(0.0, 0.5, 20.0, 20.0, false);
@@ -762,6 +766,7 @@ TEST_F(JointSoftLimiterTest, check_desired_effort_only_cases)
762766
soft_limits.min_position = -10.0;
763767
soft_limits.max_position = 10.0;
764768
ASSERT_TRUE(Init(limits, soft_limits));
769+
last_commanded_state_ = {};
765770
ASSERT_TRUE(joint_limiter_->configure(last_commanded_state_));
766771

767772
for (auto act_pos :
@@ -788,6 +793,7 @@ TEST_F(JointSoftLimiterTest, check_desired_effort_only_cases)
788793
soft_limits.min_position = -10.0;
789794
soft_limits.max_position = 10.0;
790795
ASSERT_TRUE(Init(limits, soft_limits));
796+
last_commanded_state_ = {};
791797
ASSERT_TRUE(joint_limiter_->configure(last_commanded_state_));
792798

793799
for (auto act_pos :

0 commit comments

Comments
 (0)