Skip to content

Commit bed6d1d

Browse files
authored
Merge branch 'master' into feature/swerve-drive-controller
2 parents 253f5d0 + 76f96ca commit bed6d1d

File tree

10 files changed

+220
-84
lines changed

10 files changed

+220
-84
lines changed

.github/workflows/rolling-semi-binary-build-win.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ jobs:
2727
uses: ros-controls/ros2_control_ci/.github/workflows/reusable-ros-tooling-win-build.yml@master
2828
with:
2929
ros_distro: rolling
30-
pixi_dependencies: typeguard jinja2 boost compilers
30+
pixi_dependencies: typeguard jinja2 boost compilers octomap
3131
ninja_packages: rsl
3232
target_cmake_args: -DBUILD_TESTING=OFF

doc/migration.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ Migration Guides: Kilted Kaiju to Lyrical Luth
44
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
55
This list summarizes important changes between Kilted Kaiju (previous) and Lyrical Luth (current) releases, where changes to user code might be necessary.
66

7+
joint_state_broadcaster
8+
*****************************
9+
* Removed interfaces with other data types than double for publishing to ``dynamic_joint_states``. (`#2115 <https://github.com/ros-controls/ros2_controllers/pull/2115>`_).
10+
Use a custom controller for publishing non-double interfaces.
11+
712
effort_controllers
813
*****************************
914
* ``effort_controllers/JointGroupEffortController`` is deprecated. Use :ref:`forward_command_controller <forward_command_controller_userdoc>` instead by adding the ``interface_name`` parameter and set it to ``effort``. (`#1913 <https://github.com/ros-controls/ros2_controllers/pull/1913>`_).

doc/release_notes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ joint_state_broadcaster
2727
************************
2828
* Make all parameters read-only (the never got re-evaluated after initialization anyways). (`#2064 <https://github.com/ros-controls/ros2_controllers/pull/2064>`_)
2929
* Added parameter ``publish_dynamic_joint_states`` to enable/disable publishing of dynamic joint states. (`#2064 <https://github.com/ros-controls/ros2_controllers/pull/2064>`_)
30+
* Removed interfaces with other data types than double for publishing to ``dynamic_joint_states``. (`#2115 <https://github.com/ros-controls/ros2_controllers/pull/2115>`_)
3031

3132
omni_wheel_drive_controller
3233
*****************************

joint_state_broadcaster/src/joint_state_broadcaster.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,14 @@ bool JointStateBroadcaster::init_joint_data()
236236
HW_IF_POSITION, HW_IF_VELOCITY, HW_IF_EFFORT};
237237
for (auto si = state_interfaces_.crbegin(); si != state_interfaces_.crend(); si++)
238238
{
239+
if (si->get_data_type() != hardware_interface::HandleDataType::DOUBLE)
240+
{
241+
RCLCPP_WARN(
242+
get_node()->get_logger(),
243+
"State interface '%s' of joint '%s' has non-double data type and will be ignored.",
244+
si->get_interface_name().c_str(), si->get_prefix_name().c_str());
245+
continue;
246+
}
239247
const std::string prefix_name = si->get_prefix_name();
240248
// initialize map if name is new
241249
if (name_if_value_mapping_.count(prefix_name) == 0)
@@ -305,6 +313,10 @@ void JointStateBroadcaster::init_auxiliary_data()
305313
mapped_values_.clear();
306314
for (auto i = 0u; i < state_interfaces_.size(); ++i)
307315
{
316+
if (state_interfaces_[i].get_data_type() != hardware_interface::HandleDataType::DOUBLE)
317+
{
318+
continue;
319+
}
308320
std::string interface_name = state_interfaces_[i].get_interface_name();
309321
if (map_interface_to_joint_state_.count(interface_name) > 0)
310322
{
@@ -399,13 +411,17 @@ bool JointStateBroadcaster::use_all_available_interfaces() const
399411
controller_interface::return_type JointStateBroadcaster::update(
400412
const rclcpp::Time & time, const rclcpp::Duration & /*period*/)
401413
{
414+
size_t map_index = 0u;
402415
for (auto i = 0u; i < state_interfaces_.size(); ++i)
403416
{
404-
// no retries, just try to get the latest value once
405-
const auto & opt = state_interfaces_[i].get_optional(0);
406-
if (opt.has_value())
417+
if (state_interfaces_[i].get_data_type() == hardware_interface::HandleDataType::DOUBLE)
407418
{
408-
*mapped_values_[i] = opt.value();
419+
// no retries, just try to get the latest value once
420+
const auto & opt = state_interfaces_[i].get_optional(0);
421+
if (opt.has_value())
422+
{
423+
*mapped_values_[map_index++] = opt.value();
424+
}
409425
}
410426
}
411427

joint_state_broadcaster/test/test_joint_state_broadcaster.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,3 +1324,68 @@ TEST_F(JointStateBroadcasterTest, ExtraJointStatePublishTest)
13241324
ASSERT_EQ(dynamic_joint_state_msg.header.frame_id, frame_id_);
13251325
ASSERT_THAT(dynamic_joint_state_msg.joint_names, SizeIs(NUM_JOINTS));
13261326
}
1327+
1328+
TEST_F(JointStateBroadcasterTest, NoThrowWithBooleanInterfaceTest)
1329+
{
1330+
const std::string JOINT_NAME = joint_names_[0];
1331+
const std::string IF_NAME = "is_moving";
1332+
SetUpStateBroadcaster({JOINT_NAME}, {IF_NAME});
1333+
1334+
init_broadcaster_and_set_parameters("", {JOINT_NAME}, {IF_NAME});
1335+
1336+
std::vector<LoanedStateInterface> state_ifs;
1337+
state_ifs.emplace_back(joint_1_moving_state_);
1338+
state_broadcaster_->assign_interfaces({}, std::move(state_ifs));
1339+
1340+
// configure and activate ok
1341+
ASSERT_EQ(state_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS);
1342+
ASSERT_EQ(state_broadcaster_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS);
1343+
1344+
// update should not throw
1345+
ASSERT_NO_THROW(
1346+
state_broadcaster_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)));
1347+
1348+
const auto & dynamic_joint_state_msg = state_broadcaster_->dynamic_joint_state_msg_;
1349+
ASSERT_EQ(dynamic_joint_state_msg.header.frame_id, frame_id_);
1350+
ASSERT_THAT(dynamic_joint_state_msg.joint_names, IsEmpty());
1351+
}
1352+
1353+
TEST_F(JointStateBroadcasterTest, NoThrowWithBooleanAndDoubleInterfaceTest)
1354+
{
1355+
const std::string JOINT_NAME = joint_names_[0];
1356+
const std::string IF_NAME = "is_moving";
1357+
SetUpStateBroadcaster({JOINT_NAME}, {IF_NAME});
1358+
1359+
init_broadcaster_and_set_parameters("", {JOINT_NAME}, {IF_NAME});
1360+
1361+
std::vector<LoanedStateInterface> state_ifs;
1362+
state_ifs.emplace_back(joint_1_moving_state_);
1363+
state_ifs.emplace_back(joint_1_pos_state_);
1364+
state_ifs.emplace_back(joint_1_vel_state_);
1365+
state_ifs.emplace_back(joint_1_eff_state_);
1366+
state_broadcaster_->assign_interfaces({}, std::move(state_ifs));
1367+
1368+
// configure and activate ok
1369+
ASSERT_EQ(state_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS);
1370+
ASSERT_EQ(state_broadcaster_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS);
1371+
1372+
// update should not throw
1373+
ASSERT_NO_THROW(
1374+
state_broadcaster_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)));
1375+
1376+
const auto & dynamic_joint_state_msg = state_broadcaster_->dynamic_joint_state_msg_;
1377+
ASSERT_EQ(dynamic_joint_state_msg.header.frame_id, frame_id_);
1378+
ASSERT_THAT(dynamic_joint_state_msg.joint_names, SizeIs(1))
1379+
<< "Boolean interface should be skipped";
1380+
ASSERT_THAT(dynamic_joint_state_msg.interface_values, SizeIs(1));
1381+
1382+
ASSERT_THAT(
1383+
dynamic_joint_state_msg.interface_values[0].interface_names,
1384+
ElementsAreArray({HW_IF_POSITION, HW_IF_VELOCITY, HW_IF_EFFORT}));
1385+
1386+
// joint states
1387+
ASSERT_THAT(state_broadcaster_->joint_state_msg_.name, ElementsAreArray({joint_names_[0]}));
1388+
ASSERT_THAT(state_broadcaster_->joint_state_msg_.position, SizeIs(1));
1389+
ASSERT_THAT(state_broadcaster_->joint_state_msg_.velocity, SizeIs(1));
1390+
ASSERT_THAT(state_broadcaster_->joint_state_msg_.effort, SizeIs(1));
1391+
}

joint_state_broadcaster/test/test_joint_state_broadcaster.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ class FriendJointStateBroadcaster : public joint_state_broadcaster::JointStateBr
5050
FRIEND_TEST(JointStateBroadcasterTest, TestCustomInterfaceMapping);
5151
FRIEND_TEST(JointStateBroadcasterTest, TestCustomInterfaceMappingUpdate);
5252
FRIEND_TEST(JointStateBroadcasterTest, ExtraJointStatePublishTest);
53+
FRIEND_TEST(JointStateBroadcasterTest, NoThrowWithBooleanInterfaceTest);
54+
FRIEND_TEST(JointStateBroadcasterTest, NoThrowWithBooleanAndDoubleInterfaceTest);
5355
};
5456

5557
class JointStateBroadcasterTest : public ::testing::Test
@@ -122,6 +124,10 @@ class JointStateBroadcasterTest : public ::testing::Test
122124
std::make_shared<hardware_interface::StateInterface>(
123125
joint_names_[0], custom_interface_name_, &custom_joint_value_);
124126

127+
hardware_interface::StateInterface::SharedPtr joint_1_moving_state_ =
128+
std::make_shared<hardware_interface::StateInterface>(
129+
joint_names_[0], "is_moving", "bool", "false");
130+
125131
std::vector<hardware_interface::StateInterface::SharedPtr> test_interfaces_;
126132

127133
std::unique_ptr<FriendJointStateBroadcaster> state_broadcaster_;

joint_trajectory_controller/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ generate_parameter_library(joint_trajectory_controller_parameters
3737
add_library(joint_trajectory_controller SHARED
3838
src/joint_trajectory_controller.cpp
3939
src/trajectory.cpp
40+
src/validate_jtc_parameters.cpp
4041
)
4142
target_compile_features(joint_trajectory_controller PUBLIC cxx_std_17)
4243
if(WIN32)

joint_trajectory_controller/include/joint_trajectory_controller/validate_jtc_parameters.hpp

Lines changed: 18 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -24,79 +24,26 @@
2424

2525
namespace joint_trajectory_controller
2626
{
27-
tl::expected<void, std::string> command_interface_type_combinations(
28-
rclcpp::Parameter const & parameter)
29-
{
30-
auto const & interface_types = parameter.as_string_array();
31-
32-
// Check if command interfaces combination is valid. Valid combinations are:
33-
// 1. effort
34-
// 2. velocity
35-
// 3. position [velocity, [acceleration]]
36-
// 4. position, effort
37-
38-
if (
39-
rsl::contains<std::vector<std::string>>(interface_types, "velocity") &&
40-
interface_types.size() > 1 &&
41-
!rsl::contains<std::vector<std::string>>(interface_types, "position"))
42-
{
43-
return tl::make_unexpected(
44-
"'velocity' command interface can be used either alone or 'position' "
45-
"command interface has to be present");
46-
}
47-
48-
if (
49-
rsl::contains<std::vector<std::string>>(interface_types, "acceleration") &&
50-
(!rsl::contains<std::vector<std::string>>(interface_types, "velocity") &&
51-
!rsl::contains<std::vector<std::string>>(interface_types, "position")))
52-
{
53-
return tl::make_unexpected(
54-
"'acceleration' command interface can only be used if 'velocity' and "
55-
"'position' command interfaces are present");
56-
}
57-
58-
if (
59-
rsl::contains<std::vector<std::string>>(interface_types, "effort") &&
60-
!(interface_types.size() == 1 ||
61-
(interface_types.size() == 2 &&
62-
rsl::contains<std::vector<std::string>>(interface_types, "position"))))
63-
{
64-
return tl::make_unexpected(
65-
"'effort' command interface has to be used alone or with a 'position' interface");
66-
}
67-
68-
return {};
69-
}
7027

28+
/**
29+
* \brief Validate command interface type combinations for joint trajectory controller.
30+
*
31+
* \param[in] parameter The rclcpp parameter containing the command interface types.
32+
* \return tl::expected<void, std::string> An empty expected on success, or an error message on
33+
* failure.
34+
*/
35+
tl::expected<void, std::string> command_interface_type_combinations(
36+
rclcpp::Parameter const & parameter);
37+
38+
/**
39+
* \brief Validate state interface type combinations for joint trajectory controller.
40+
*
41+
* \param[in] parameter The rclcpp parameter containing the state interface types.
42+
* \return tl::expected<void, std::string> An empty expected on success, or an error message on
43+
* failure.
44+
*/
7145
tl::expected<void, std::string> state_interface_type_combinations(
72-
rclcpp::Parameter const & parameter)
73-
{
74-
auto const & interface_types = parameter.as_string_array();
75-
76-
// Valid combinations are
77-
// 1. position [velocity, [acceleration]]
78-
79-
if (
80-
rsl::contains<std::vector<std::string>>(interface_types, "velocity") &&
81-
!rsl::contains<std::vector<std::string>>(interface_types, "position"))
82-
{
83-
return tl::make_unexpected(
84-
"'velocity' state interface cannot be used if 'position' interface "
85-
"is missing.");
86-
}
87-
88-
if (
89-
rsl::contains<std::vector<std::string>>(interface_types, "acceleration") &&
90-
(!rsl::contains<std::vector<std::string>>(interface_types, "position") ||
91-
!rsl::contains<std::vector<std::string>>(interface_types, "velocity")))
92-
{
93-
return tl::make_unexpected(
94-
"'acceleration' state interface cannot be used if 'position' and 'velocity' "
95-
"interfaces are not present.");
96-
}
97-
98-
return {};
99-
}
46+
rclcpp::Parameter const & parameter);
10047

10148
} // namespace joint_trajectory_controller
10249

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// Copyright (c) 2022 ros2_control Development Team
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "joint_trajectory_controller/validate_jtc_parameters.hpp"
16+
17+
namespace joint_trajectory_controller
18+
{
19+
20+
tl::expected<void, std::string> command_interface_type_combinations(
21+
rclcpp::Parameter const & parameter)
22+
{
23+
auto const & interface_types = parameter.as_string_array();
24+
25+
// Check if command interfaces combination is valid. Valid combinations are:
26+
// 1. effort
27+
// 2. velocity
28+
// 3. position [velocity, [acceleration]]
29+
// 4. position, effort
30+
31+
if (
32+
rsl::contains<std::vector<std::string>>(interface_types, "velocity") &&
33+
interface_types.size() > 1 &&
34+
!rsl::contains<std::vector<std::string>>(interface_types, "position"))
35+
{
36+
return tl::make_unexpected(
37+
"'velocity' command interface can be used either alone or 'position' "
38+
"command interface has to be present");
39+
}
40+
41+
if (
42+
rsl::contains<std::vector<std::string>>(interface_types, "acceleration") &&
43+
(!rsl::contains<std::vector<std::string>>(interface_types, "velocity") &&
44+
!rsl::contains<std::vector<std::string>>(interface_types, "position")))
45+
{
46+
return tl::make_unexpected(
47+
"'acceleration' command interface can only be used if 'velocity' and "
48+
"'position' command interfaces are present");
49+
}
50+
51+
if (
52+
rsl::contains<std::vector<std::string>>(interface_types, "effort") &&
53+
!(interface_types.size() == 1 ||
54+
(interface_types.size() == 2 &&
55+
rsl::contains<std::vector<std::string>>(interface_types, "position"))))
56+
{
57+
return tl::make_unexpected(
58+
"'effort' command interface has to be used alone or with a 'position' interface");
59+
}
60+
61+
return {};
62+
}
63+
64+
tl::expected<void, std::string> state_interface_type_combinations(
65+
rclcpp::Parameter const & parameter)
66+
{
67+
auto const & interface_types = parameter.as_string_array();
68+
69+
// Valid combinations are
70+
// 1. position [velocity, [acceleration]]
71+
72+
if (
73+
rsl::contains<std::vector<std::string>>(interface_types, "velocity") &&
74+
!rsl::contains<std::vector<std::string>>(interface_types, "position"))
75+
{
76+
return tl::make_unexpected(
77+
"'velocity' state interface cannot be used if 'position' interface "
78+
"is missing.");
79+
}
80+
81+
if (
82+
rsl::contains<std::vector<std::string>>(interface_types, "acceleration") &&
83+
(!rsl::contains<std::vector<std::string>>(interface_types, "position") ||
84+
!rsl::contains<std::vector<std::string>>(interface_types, "velocity")))
85+
{
86+
return tl::make_unexpected(
87+
"'acceleration' state interface cannot be used if 'position' and 'velocity' "
88+
"interfaces are not present.");
89+
}
90+
91+
return {};
92+
}
93+
94+
} // namespace joint_trajectory_controller

steering_controllers_library/src/steering_controllers_library.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -290,14 +290,15 @@ controller_interface::CallbackReturn SteeringControllersLibrary::on_configure(
290290
odom_state_msg_.child_frame_id = base_frame_id;
291291
odom_state_msg_.pose.pose.position.z = 0;
292292

293-
auto & covariance = odom_state_msg_.twist.covariance;
294-
constexpr size_t NUM_DIMENSIONS = 6;
295-
for (size_t index = 0; index < 6; ++index)
296-
{
297-
// 0, 7, 14, 21, 28, 35
298-
const size_t diagonal_index = NUM_DIMENSIONS * index + index;
299-
covariance[diagonal_index] = params_.pose_covariance_diagonal[index];
300-
covariance[diagonal_index] = params_.twist_covariance_diagonal[index];
293+
const size_t NUM_DIMENSIONS = 6;
294+
auto & pose_cov = odom_state_msg_.pose.covariance;
295+
auto & twist_cov = odom_state_msg_.twist.covariance;
296+
for (size_t i = 0; i < NUM_DIMENSIONS; ++i)
297+
{
298+
// indices of the diagonal: 0, 7, 14, 21, 28, 35
299+
const size_t index = (NUM_DIMENSIONS + 1) * i;
300+
pose_cov[index] = params_.pose_covariance_diagonal[i];
301+
twist_cov[index] = params_.twist_covariance_diagonal[i];
301302
}
302303

303304
try

0 commit comments

Comments
 (0)