Skip to content

Commit e05abe6

Browse files
Juliajmergify[bot]
authored andcommitted
Add utility node to transform wrench messages for a list of frames (#2021)
(cherry picked from commit 3d03572) # Conflicts: # doc/release_notes.rst # force_torque_sensor_broadcaster/CMakeLists.txt
1 parent 72cbca8 commit e05abe6

File tree

10 files changed

+1134
-0
lines changed

10 files changed

+1134
-0
lines changed

doc/release_notes.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Release Notes: Galactic to Humble
44
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
55
This list summarizes the changes between Galactic (previous) and Humble (current) releases. Bugfixes are not included in this list.
66

7+
<<<<<<< HEAD
78
.. note::
89

910
This list was created in July 2024, earlier changes may not be included.
@@ -63,3 +64,10 @@ steering_controllers_library
6364
gpio_controllers
6465
************************
6566
* The GPIO command controller was added 🎉 (`#1251 <https://github.com/ros-controls/ros2_controllers/pull/1251>`_).
67+
=======
68+
This list summarizes important changes between Kilted Kaiju (previous) and Lyrical Luth (current) releases.
69+
70+
force_torque_sensor_broadcaster
71+
*******************************
72+
* Added support for transforming Wrench messages to a given list of target frames. This is useful when applications need force/torque data in their preferred coordinate frames. (`#2021 <https://github.com/ros-controls/ros2_controllers/pull/2021/files>`__).
73+
>>>>>>> 3d03572 (Add utility node to transform wrench messages for a list of frames (#2021))

force_torque_sensor_broadcaster/CMakeLists.txt

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ set(THIS_PACKAGE_INCLUDE_DEPENDS
1414
rclcpp
1515
rclcpp_lifecycle
1616
realtime_tools
17+
tf2
18+
tf2_ros
19+
tf2_geometry_msgs
1720
)
1821

1922
find_package(ament_cmake REQUIRED)
@@ -26,6 +29,10 @@ generate_parameter_library(force_torque_sensor_broadcaster_parameters
2629
src/force_torque_sensor_broadcaster_parameters.yaml
2730
)
2831

32+
generate_parameter_library(wrench_transformer_parameters
33+
src/wrench_transformer_parameters.yaml
34+
)
35+
2936
add_library(force_torque_sensor_broadcaster SHARED
3037
src/force_torque_sensor_broadcaster.cpp
3138
)
@@ -46,6 +53,37 @@ target_compile_definitions(force_torque_sensor_broadcaster PRIVATE "FORCE_TORQUE
4653
pluginlib_export_plugin_description_file(
4754
controller_interface force_torque_sensor_broadcaster.xml)
4855

56+
# Wrench transformer library
57+
add_library(wrench_transformer SHARED
58+
src/wrench_transformer.cpp
59+
)
60+
target_compile_features(wrench_transformer PUBLIC cxx_std_17)
61+
target_include_directories(wrench_transformer PUBLIC
62+
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
63+
$<INSTALL_INTERFACE:include/force_torque_sensor_broadcaster>
64+
)
65+
target_link_libraries(wrench_transformer PUBLIC
66+
wrench_transformer_parameters
67+
rclcpp::rclcpp
68+
tf2::tf2
69+
tf2_ros::tf2_ros
70+
tf2_geometry_msgs::tf2_geometry_msgs
71+
${geometry_msgs_TARGETS}
72+
)
73+
74+
# Wrench transformer executable
75+
add_executable(wrench_transformer_node
76+
src/wrench_transformer_main.cpp
77+
)
78+
target_compile_features(wrench_transformer_node PUBLIC cxx_std_17)
79+
target_include_directories(wrench_transformer_node PUBLIC
80+
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
81+
$<INSTALL_INTERFACE:include/force_torque_sensor_broadcaster>
82+
)
83+
target_link_libraries(wrench_transformer_node PUBLIC
84+
wrench_transformer
85+
)
86+
4987
if(BUILD_TESTING)
5088
find_package(ament_cmake_gmock REQUIRED)
5189
find_package(controller_manager REQUIRED)
@@ -72,8 +110,24 @@ if(BUILD_TESTING)
72110
target_link_libraries(test_force_torque_sensor_broadcaster
73111
force_torque_sensor_broadcaster
74112
)
113+
<<<<<<< HEAD
75114
ament_target_dependencies(test_force_torque_sensor_broadcaster
76115
hardware_interface
116+
=======
117+
118+
ament_add_gmock(test_wrench_transformer test/test_wrench_transformer.cpp)
119+
target_compile_features(test_wrench_transformer PUBLIC cxx_std_17)
120+
target_include_directories(test_wrench_transformer PRIVATE include)
121+
target_compile_definitions(test_wrench_transformer PRIVATE
122+
TEST_FILES_DIRECTORY="${CMAKE_CURRENT_SOURCE_DIR}/test")
123+
target_link_libraries(test_wrench_transformer
124+
wrench_transformer
125+
tf2_ros::tf2_ros
126+
)
127+
128+
add_library(dummy_filter SHARED
129+
test/dummy_filter.cpp
130+
>>>>>>> 3d03572 (Add utility node to transform wrench messages for a list of frames (#2021))
77131
)
78132
endif()
79133

@@ -85,12 +139,22 @@ install(
85139
TARGETS
86140
force_torque_sensor_broadcaster
87141
force_torque_sensor_broadcaster_parameters
142+
wrench_transformer
143+
wrench_transformer_parameters
88144
EXPORT export_force_torque_sensor_broadcaster
89145
RUNTIME DESTINATION bin
90146
ARCHIVE DESTINATION lib
91147
LIBRARY DESTINATION lib
92148
)
93149

150+
# Install executable to lib/<package_name> for launch files to find it
151+
install(
152+
TARGETS
153+
wrench_transformer_node
154+
EXPORT export_force_torque_sensor_broadcaster
155+
RUNTIME DESTINATION lib/force_torque_sensor_broadcaster
156+
)
157+
94158
ament_export_targets(export_force_torque_sensor_broadcaster HAS_LIBRARY_TARGET)
95159
ament_export_dependencies(${THIS_PACKAGE_INCLUDE_DEPENDS})
96160
ament_package()

force_torque_sensor_broadcaster/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,9 @@ Controller to publish state of force-torque sensors.
66
Pluginlib-Library: force_torque_sensor_broadcaster
77

88
Plugin: force_torque_sensor_broadcaster/ForceTorqueSensorBroadcaster (controller_interface::ControllerInterface)
9+
10+
Wrench Transformer Node
11+
-----------------------
12+
The package also provides a standalone ROS 2 node ``wrench_transformer_node`` that transforms wrench messages from the force_torque_sensor_broadcaster to different target frames using TF2. This allows applications to receive force/torque data in their preferred coordinate frames.
13+
14+
See the user documentation for details on configuration and usage.

force_torque_sensor_broadcaster/doc/userdoc.rst

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,39 @@ An example parameter file for this controller can be found in `the test director
2626

2727
.. literalinclude:: ../test/force_torque_sensor_broadcaster_params.yaml
2828
:language: yaml
29+
30+
Wrench Transformer Node
31+
-----------------------
32+
The package provides a standalone ROS 2 node ``wrench_transformer_node`` that transforms wrench messages published by the ``ForceTorqueSensorBroadcaster`` controller to different target frames using TF2. This is useful when applications need force/torque data in coordinate frames other than the sensor frame.
33+
34+
The node subscribes to wrench messages from the broadcaster (either raw or filtered) and publishes transformed versions to separate topics for each target frame.
35+
36+
Usage
37+
^^^^^
38+
The wrench transformer node can be launched as a standalone executable:
39+
40+
.. code-block:: bash
41+
42+
ros2 run force_torque_sensor_broadcaster wrench_transformer_node
43+
44+
Wrench Transformer Parameters
45+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46+
The wrench transformer uses the `generate_parameter_library <https://github.com/PickNikRobotics/generate_parameter_library>`_ to handle its parameters. The parameter `definition file for the wrench transformer <https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/force_torque_sensor_broadcaster/src/wrench_transformer_parameters.yaml>`_ contains descriptions for all the parameters.
47+
48+
Full list of parameters:
49+
50+
.. generate_parameter_library_details:: ../src/wrench_transformer_parameters.yaml
51+
52+
Topics
53+
^^^^^^
54+
The node subscribes to:
55+
56+
- ``~/wrench`` (raw wrench messages). To subscribe to filtered wrench messages, use topic remapping: ``ros2 run ... --ros-args -r ~/wrench:=<namespace>/wrench_filtered``
57+
58+
The node publishes:
59+
60+
- ``<namespace>/<target_frame>/wrench`` for each target frame specified in ``target_frames``
61+
62+
- If the node is in the root namespace (``/``), the namespace defaults to the node name (e.g., ``/fts_wrench_transformer/<target_frame>/wrench``)
63+
- If the input topic is remapped to a filtered topic (contains "filtered" in the name), the output topics automatically append ``_filtered`` suffix (e.g., ``<namespace>/<target_frame>/wrench_filtered``)
64+
- This allows users to distinguish between transformed raw wrench data and transformed filtered wrench data
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Copyright (c) 2025, 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+
/*
16+
* Authors: Julia Jia
17+
*/
18+
19+
#ifndef FORCE_TORQUE_SENSOR_BROADCASTER__WRENCH_TRANSFORMER_HPP_
20+
#define FORCE_TORQUE_SENSOR_BROADCASTER__WRENCH_TRANSFORMER_HPP_
21+
22+
#include <memory>
23+
#include <string>
24+
#include <unordered_map>
25+
#include <vector>
26+
27+
#include "geometry_msgs/msg/wrench_stamped.hpp"
28+
#include "rclcpp/rclcpp.hpp"
29+
#include "tf2_geometry_msgs/tf2_geometry_msgs.hpp"
30+
#include "tf2_ros/buffer.hpp"
31+
#include "tf2_ros/transform_listener.hpp"
32+
33+
// auto-generated by generate_parameter_library
34+
#include "force_torque_sensor_broadcaster/wrench_transformer_parameters.hpp"
35+
36+
namespace force_torque_sensor_broadcaster
37+
{
38+
39+
class WrenchTransformer : public rclcpp::Node
40+
{
41+
public:
42+
explicit WrenchTransformer(const rclcpp::NodeOptions & options = rclcpp::NodeOptions());
43+
44+
void init();
45+
46+
~WrenchTransformer() = default;
47+
48+
private:
49+
void wrench_callback(const geometry_msgs::msg::WrenchStamped::SharedPtr msg);
50+
bool transform_wrench(
51+
const geometry_msgs::msg::WrenchStamped & input_wrench, const std::string & target_frame,
52+
geometry_msgs::msg::WrenchStamped & output_wrench);
53+
54+
void setup_subscriber();
55+
void setup_publishers();
56+
57+
/**
58+
* Normalize namespace for topic construction.
59+
* If namespace is empty or root ("/"), returns node name with leading "/".
60+
* Otherwise, normalizes namespace to start with "/" and not end with "/".
61+
* @return Normalized namespace string
62+
*/
63+
std::string normalize_namespace_for_topics() const;
64+
65+
std::shared_ptr<force_torque_wrench_transformer::ParamListener> param_listener_;
66+
force_torque_wrench_transformer::Params params_;
67+
68+
rclcpp::Subscription<geometry_msgs::msg::WrenchStamped>::SharedPtr wrench_subscriber_;
69+
std::unordered_map<std::string, rclcpp::Publisher<geometry_msgs::msg::WrenchStamped>::SharedPtr>
70+
transformed_wrench_publishers_;
71+
72+
std::shared_ptr<tf2_ros::Buffer> tf_buffer_;
73+
std::shared_ptr<tf2_ros::TransformListener> tf_listener_;
74+
75+
std::string input_topic_;
76+
std::string output_topic_suffix_; // e.g., "" or "_filtered" based on input topic
77+
std::vector<std::string> target_frames_;
78+
};
79+
80+
// Function to run wrench transformer (extracted from main for testability)
81+
int run_wrench_transformer(int argc, char ** argv);
82+
83+
} // namespace force_torque_sensor_broadcaster
84+
85+
#endif // FORCE_TORQUE_SENSOR_BROADCASTER__WRENCH_TRANSFORMER_HPP_

force_torque_sensor_broadcaster/package.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
<depend>rclcpp_lifecycle</depend>
3131
<depend>realtime_tools</depend>
3232
<depend>generate_parameter_library</depend>
33+
<depend>tf2</depend>
34+
<depend>tf2_ros</depend>
35+
<depend>tf2_geometry_msgs</depend>
3336

3437
<test_depend>ament_cmake_gmock</test_depend>
3538
<test_depend>controller_manager</test_depend>

0 commit comments

Comments
 (0)