Skip to content

Commit bc333b7

Browse files
mergify[bot]christophfroehlichottojoahcordewentasah
authored
Add battery_state_broadcaster (backport #2086) (#2522)
Co-authored-by: Christoph Fröhlich <christophfroehlich@users.noreply.github.com> Co-authored-by: Jonas Otto <jonas.otto@ipa.fraunhofer.de> Co-authored-by: Alejandro Hernandez Cordero <ahcorde@gmail.com> Co-authored-by: Jonas Otto <jonas@jonasotto.com> Co-authored-by: Michal Sojka <michal.sojka@cvut.cz> Co-authored-by: Yara Shahin <58101871+YaraShahin@users.noreply.github.com> Co-authored-by: Bence Magyar <bence.magyar.robotics@gmail.com> Co-authored-by: Sai Kishor Kothakota <sai.kishor@pal-robotics.com>
1 parent 9f4c88c commit bc333b7

16 files changed

Lines changed: 1770 additions & 0 deletions
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2+
Changelog for package battery_state_broadcaster
3+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4+
5+
6+
The entries below refer to the standalone `ipa320/ros_battery_monitoring <https://github.com/ipa320/ros_battery_monitoring>`_ package,
7+
from which this broadcaster originates.
8+
9+
1.1.0 (2025-09-26)
10+
------------------
11+
* address deprecations in ros2_control for kilted
12+
* Don't make a temporary copy of semantic component (`#9 <https://github.com/ipa320/ros_battery_monitoring/pull/9>`_)
13+
* Contributors: Christoph Froehlich, Jonas Otto
14+
15+
1.0.2 (2025-06-01)
16+
------------------
17+
* Replace ament_target_dependencies with target_link_libraries (`#6 <https://github.com/ipa320/ros_battery_monitoring/issues/6>`_)
18+
* Contributors: Alejandro Hernandez Cordero, Jonas Otto
19+
20+
1.0.1 (2025-02-06)
21+
------------------
22+
* fix realtime_tools include
23+
* Contributors: Jonas Otto
24+
25+
1.0.0 (2024-08-14)
26+
------------------
27+
* initial release
28+
* Contributors: Jonas Otto
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
cmake_minimum_required(VERSION 3.10)
2+
project(battery_state_broadcaster)
3+
4+
find_package(ros2_control_cmake REQUIRED)
5+
set_compiler_options()
6+
export_windows_symbols()
7+
8+
set(THIS_PACKAGE_INCLUDE_DEPENDS
9+
control_msgs
10+
controller_interface
11+
hardware_interface
12+
generate_parameter_library
13+
pluginlib
14+
rclcpp
15+
rclcpp_lifecycle
16+
rcpputils
17+
realtime_tools
18+
sensor_msgs
19+
)
20+
21+
find_package(ament_cmake REQUIRED)
22+
find_package(backward_ros REQUIRED)
23+
foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS})
24+
find_package(${Dependency} REQUIRED)
25+
endforeach()
26+
add_compile_definitions(RCPPUTILS_VERSION_MAJOR=${rcpputils_VERSION_MAJOR})
27+
add_compile_definitions(RCPPUTILS_VERSION_MINOR=${rcpputils_VERSION_MINOR})
28+
29+
generate_parameter_library(battery_state_broadcaster_parameters
30+
src/battery_state_broadcaster_parameters.yaml
31+
)
32+
33+
add_library(
34+
battery_state_broadcaster
35+
SHARED
36+
src/battery_state_broadcaster.cpp
37+
)
38+
39+
target_compile_features(battery_state_broadcaster PUBLIC cxx_std_17)
40+
target_include_directories(battery_state_broadcaster
41+
PUBLIC
42+
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
43+
$<INSTALL_INTERFACE:include/battery_state_broadcaster>
44+
)
45+
target_link_libraries(battery_state_broadcaster PUBLIC
46+
battery_state_broadcaster_parameters
47+
controller_interface::controller_interface
48+
hardware_interface::hardware_interface
49+
pluginlib::pluginlib
50+
rclcpp::rclcpp
51+
rclcpp_lifecycle::rclcpp_lifecycle
52+
rcpputils::rcpputils
53+
realtime_tools::realtime_tools
54+
${control_msgs_TARGETS}
55+
${sensor_msgs_TARGETS}
56+
${builtin_interfaces_TARGETS})
57+
58+
59+
pluginlib_export_plugin_description_file(
60+
controller_interface battery_state_broadcaster.xml)
61+
62+
if(BUILD_TESTING)
63+
find_package(ament_cmake_gmock REQUIRED)
64+
find_package(controller_manager REQUIRED)
65+
find_package(hardware_interface REQUIRED)
66+
find_package(ros2_control_test_assets REQUIRED)
67+
68+
add_definitions(-DTEST_FILES_DIRECTORY="${CMAKE_CURRENT_SOURCE_DIR}/test")
69+
ament_add_gmock(test_load_battery_state_broadcaster test/test_load_battery_state_broadcaster.cpp)
70+
target_include_directories(test_load_battery_state_broadcaster PRIVATE include)
71+
target_link_libraries(test_load_battery_state_broadcaster
72+
battery_state_broadcaster
73+
controller_manager::controller_manager
74+
hardware_interface::hardware_interface
75+
rclcpp::rclcpp
76+
ros2_control_test_assets::ros2_control_test_assets
77+
)
78+
79+
add_rostest_with_parameters_gmock(test_battery_state_broadcaster
80+
test/test_battery_state_broadcaster.cpp
81+
${CMAKE_CURRENT_SOURCE_DIR}/test/battery_state_broadcaster_params.yaml)
82+
target_include_directories(test_battery_state_broadcaster PRIVATE include)
83+
target_link_libraries(test_battery_state_broadcaster
84+
battery_state_broadcaster
85+
)
86+
endif()
87+
88+
install(
89+
DIRECTORY include/
90+
DESTINATION include/battery_state_broadcaster
91+
)
92+
install(
93+
TARGETS
94+
battery_state_broadcaster
95+
battery_state_broadcaster_parameters
96+
EXPORT export_battery_state_broadcaster
97+
RUNTIME DESTINATION bin
98+
ARCHIVE DESTINATION lib
99+
LIBRARY DESTINATION lib
100+
)
101+
102+
ament_export_targets(export_battery_state_broadcaster HAS_LIBRARY_TARGET)
103+
ament_export_dependencies(${THIS_PACKAGE_INCLUDE_DEPENDS})
104+
ament_package()
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<library path="battery_state_broadcaster">
2+
<class name="battery_state_broadcaster/BatteryStateBroadcaster"
3+
type="battery_state_broadcaster::BatteryStateBroadcaster" base_class_type="controller_interface::ControllerInterface">
4+
<description>
5+
This controller publishes the individual battery state of each battery as control_msgs/BatteryStateArray messages.
6+
It also publishes the aggregated battery state of all batteries as a single sensor_msgs/BatteryState message.
7+
</description>
8+
</class>
9+
</library>
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/battery_state_broadcaster/doc/userdoc.rst
2+
3+
.. _battery_state_broadcaster_userdoc:
4+
5+
Battery State Broadcaster
6+
--------------------------------
7+
The *Battery State Broadcaster* publishes battery status information as ``sensor_msgs/msg/BatteryState`` messages.
8+
9+
It reads battery-related state interfaces from one or more batteries and exposes them in a standard ROS 2 message format. This allows easy integration with monitoring tools, logging systems, and higher-level decision-making nodes.
10+
11+
Interfaces
12+
^^^^^^^^^^^
13+
14+
The broadcaster can read the following state interfaces from each configured battery:
15+
16+
- ``battery_voltage`` *(mandatory)* (double)
17+
- ``battery_temperature`` *(optional)* (double)
18+
- ``battery_current`` *(optional)* (double)
19+
- ``battery_charge`` *(optional)* (double)
20+
- ``battery_percentage`` *(optional)* (double)
21+
- ``battery_power_supply_status`` *(optional)* (double)
22+
- ``battery_power_supply_health`` *(optional)* (double)
23+
- ``battery_present`` *(optional)* (bool)
24+
25+
Published Topics
26+
^^^^^^^^^^^^^^^^^^
27+
28+
The broadcaster publishes two topics:
29+
30+
- ``~/raw_battery_states`` (``control_msgs/msg/BatteryStateArray``)
31+
Publishes **per-battery state messages**, containing the raw values for each configured battery.
32+
33+
- ``~/battery_state`` (``sensor_msgs/msg/BatteryState``)
34+
Publishes a **single aggregated battery message** representing the combined status across all batteries.
35+
36+
.. list-table::
37+
:header-rows: 1
38+
39+
* - Field
40+
- ``battery_state``
41+
- ``raw_battery_states``
42+
* - ``header.frame_id``
43+
- Empty
44+
- Battery name
45+
* - ``voltage``
46+
- Mean across all batteries
47+
- From battery's ``battery_voltage`` interface *(mandatory)* (NaN if unmeasured)
48+
* - ``temperature``
49+
- Mean across batteries reporting temperature
50+
- From battery's ``battery_temperature`` interface if enabled, otherwise nan.
51+
* - ``current``
52+
- Mean across batteries reporting current
53+
- From battery's ``battery_current`` interface if enabled, otherwise nan.
54+
* - ``charge``
55+
- Sum across batteries reporting charge
56+
- From battery's ``battery_charge`` interface if enabled, otherwise nan.
57+
* - ``capacity``
58+
- Sum across all batteries
59+
- From battery's ``capacity`` parameter if provided, otherwise nan.
60+
* - ``design_capacity``
61+
- Sum across all batteries
62+
- From battery's ``design_capacity`` parameter if provided, otherwise nan.
63+
* - ``percentage``
64+
- Mean across batteries reporting/calculating percentage
65+
- From battery's ``battery_percentage`` interface if enabled, otherwise calculated from battery's ``minimum_voltage`` and ``maximum_voltage`` parameters.
66+
* - ``power_supply_status``
67+
- Highest reported enum value
68+
- From battery's ``battery_power_supply_status`` interface if enabled, otherwise 0 (unknown).
69+
* - ``power_supply_health``
70+
- Highest reported enum value
71+
- From battery's ``battery_power_supply_health`` interface if enabled, otherwise 0 (unknown).
72+
* - ``power_supply_technology``
73+
- Reported as-is if same across all batteries, otherwise set to *Unknown*
74+
- From battery's ``power_supply_technology`` parameter if provided, otherwise 0 (unknown).
75+
* - ``present``
76+
- True
77+
- From battery's ``battery_present`` interface if enabled, otherwise true if the battery voltage value is valid (not NaN and not 0.0).
78+
* - ``cell_voltage``
79+
- Empty
80+
- Empty
81+
* - ``cell_temperature``
82+
- Empty
83+
- Empty
84+
* - ``location``
85+
- All battery locations appended
86+
- From battery's ``location`` parameter if provided, otherwise empty.
87+
* - ``serial_number``
88+
- All battery serial numbers appended
89+
- From battery's ``serial_number`` parameter if provided, otherwise empty.
90+
91+
92+
Parameters
93+
^^^^^^^^^^^
94+
This controller uses the `generate_parameter_library <https://github.com/PickNikRobotics/generate_parameter_library>`_ to manage parameters.
95+
The parameter `definition file <https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/battery_state_broadcaster/src/battery_state_broadcaster_parameters.yaml>`_ contains the full list and descriptions.
96+
97+
List of parameters
98+
=========================
99+
.. generate_parameter_library_details:: ../src/battery_state_broadcaster_parameters.yaml
100+
101+
Example Parameter File
102+
=========================
103+
104+
An example parameter file for this controller is available in the `test directory <https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/battery_state_broadcaster/test/battery_state_broadcaster_params.yaml>`_:
105+
106+
.. literalinclude:: ../test/battery_state_broadcaster_params.yaml
107+
:language: yaml
108+
109+
Migration for ``ipa320/ros_battery_monitoring`` users
110+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
111+
112+
If you were previously using the ``battery_state_broadcaster`` from the ``ipa320/ros_battery_monitoring package``, you can switch directly to this package. The configuration style using ``sensor_name`` is still supported for backward compatibility, but it may be removed in a future release.
113+
114+
To adapt your setup to the new ``battery_state_broadcaster`` configuration:
115+
116+
1. Update your hardware interface name from ``voltage`` → ``battery_voltage``.
117+
118+
2. Convert your controller parameters from
119+
120+
.. code-block:: yaml
121+
122+
battery_state_broadcaster:
123+
ros__parameters:
124+
sensor_name: "battery_state"
125+
design_capacity: 100.0
126+
# https://github.com/ros2/common_interfaces/blob/rolling/sensor_msgs/msg/BatteryState.msg
127+
power_supply_technology: 2
128+
129+
to:
130+
131+
.. code-block:: yaml
132+
133+
battery_state_broadcaster:
134+
ros__parameters:
135+
batteries: ["battery_state"]
136+
battery_state:
137+
design_capacity: 100.0
138+
power_supply_technology: 2
139+
140+
**Notes**:
141+
142+
- Parameters must provide **either** sensor_name **or** batteries.
143+
- If both are empty → the broadcaster will fail to configure.
144+
- If both are set → the broadcaster will throw an error.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) 2025, b-robotized Group
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+
#ifndef BATTERY_STATE_BROADCASTER__BATTERYSTATEBROADCASTER_HPP_
16+
#define BATTERY_STATE_BROADCASTER__BATTERYSTATEBROADCASTER_HPP_
17+
18+
#pragma message( \
19+
"BatteryStateBroadcaster.hpp is deprecated, please use battery_state_broadcaster.hpp instead.")
20+
21+
#include "battery_state_broadcaster/battery_state_broadcaster.hpp"
22+
23+
#endif // BATTERY_STATE_BROADCASTER__BATTERYSTATEBROADCASTER_HPP_

0 commit comments

Comments
 (0)