Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions battery_state_broadcaster/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Changelog for package battery_state_broadcaster
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


The entries below refer to the standalone `ipa320/ros_battery_monitoring <https://github.com/ipa320/ros_battery_monitoring>`_ package,
from which this broadcaster originates.

1.1.0 (2025-09-26)
------------------
* address deprecations in ros2_control for kilted
* Don't make a temporary copy of semantic component (`#9 <https://github.com/ipa320/ros_battery_monitoring/pull/9>`_)
* Contributors: Christoph Froehlich, Jonas Otto

1.0.2 (2025-06-01)
------------------
* Replace ament_target_dependencies with target_link_libraries (`#6 <https://github.com/ipa320/ros_battery_monitoring/issues/6>`_)
* Contributors: Alejandro Hernandez Cordero, Jonas Otto

1.0.1 (2025-02-06)
------------------
* fix realtime_tools include
* Contributors: Jonas Otto

1.0.0 (2024-08-14)
------------------
* initial release
* Contributors: Jonas Otto
104 changes: 104 additions & 0 deletions battery_state_broadcaster/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
cmake_minimum_required(VERSION 3.10)
project(battery_state_broadcaster)

find_package(ros2_control_cmake REQUIRED)
set_compiler_options()
export_windows_symbols()

set(THIS_PACKAGE_INCLUDE_DEPENDS
control_msgs
controller_interface
hardware_interface
generate_parameter_library
pluginlib
rclcpp
rclcpp_lifecycle
rcpputils
realtime_tools
sensor_msgs
)

find_package(ament_cmake REQUIRED)
find_package(backward_ros REQUIRED)
foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS})
find_package(${Dependency} REQUIRED)
endforeach()
add_compile_definitions(RCPPUTILS_VERSION_MAJOR=${rcpputils_VERSION_MAJOR})
add_compile_definitions(RCPPUTILS_VERSION_MINOR=${rcpputils_VERSION_MINOR})

generate_parameter_library(battery_state_broadcaster_parameters
src/battery_state_broadcaster_parameters.yaml
)

add_library(
battery_state_broadcaster
SHARED
src/battery_state_broadcaster.cpp
)

target_compile_features(battery_state_broadcaster PUBLIC cxx_std_17)
target_include_directories(battery_state_broadcaster
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include/battery_state_broadcaster>
)
target_link_libraries(battery_state_broadcaster PUBLIC
battery_state_broadcaster_parameters
controller_interface::controller_interface
hardware_interface::hardware_interface
pluginlib::pluginlib
rclcpp::rclcpp
rclcpp_lifecycle::rclcpp_lifecycle
rcpputils::rcpputils
realtime_tools::realtime_tools
${control_msgs_TARGETS}
${sensor_msgs_TARGETS}
${builtin_interfaces_TARGETS})


pluginlib_export_plugin_description_file(
controller_interface battery_state_broadcaster.xml)

if(BUILD_TESTING)
find_package(ament_cmake_gmock REQUIRED)
find_package(controller_manager REQUIRED)
find_package(hardware_interface REQUIRED)
find_package(ros2_control_test_assets REQUIRED)

add_definitions(-DTEST_FILES_DIRECTORY="${CMAKE_CURRENT_SOURCE_DIR}/test")
ament_add_gmock(test_load_battery_state_broadcaster test/test_load_battery_state_broadcaster.cpp)
target_include_directories(test_load_battery_state_broadcaster PRIVATE include)
target_link_libraries(test_load_battery_state_broadcaster
battery_state_broadcaster
controller_manager::controller_manager
hardware_interface::hardware_interface
rclcpp::rclcpp
ros2_control_test_assets::ros2_control_test_assets
)

add_rostest_with_parameters_gmock(test_battery_state_broadcaster
test/test_battery_state_broadcaster.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/battery_state_broadcaster_params.yaml)
target_include_directories(test_battery_state_broadcaster PRIVATE include)
target_link_libraries(test_battery_state_broadcaster
battery_state_broadcaster
)
endif()

install(
DIRECTORY include/
DESTINATION include/battery_state_broadcaster
)
install(
TARGETS
battery_state_broadcaster
battery_state_broadcaster_parameters
EXPORT export_battery_state_broadcaster
RUNTIME DESTINATION bin
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
)

ament_export_targets(export_battery_state_broadcaster HAS_LIBRARY_TARGET)
ament_export_dependencies(${THIS_PACKAGE_INCLUDE_DEPENDS})
ament_package()
9 changes: 9 additions & 0 deletions battery_state_broadcaster/battery_state_broadcaster.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<library path="battery_state_broadcaster">
<class name="battery_state_broadcaster/BatteryStateBroadcaster"
type="battery_state_broadcaster::BatteryStateBroadcaster" base_class_type="controller_interface::ControllerInterface">
<description>
This controller publishes the individual battery state of each battery as control_msgs/BatteryStateArray messages.
It also publishes the aggregated battery state of all batteries as a single sensor_msgs/BatteryState message.
</description>
</class>
</library>
144 changes: 144 additions & 0 deletions battery_state_broadcaster/doc/userdoc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/battery_state_broadcaster/doc/userdoc.rst

.. _battery_state_broadcaster_userdoc:

Battery State Broadcaster
--------------------------------
The *Battery State Broadcaster* publishes battery status information as ``sensor_msgs/msg/BatteryState`` messages.

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.

Interfaces
^^^^^^^^^^^

The broadcaster can read the following state interfaces from each configured battery:

- ``battery_voltage`` *(mandatory)* (double)
- ``battery_temperature`` *(optional)* (double)
- ``battery_current`` *(optional)* (double)
- ``battery_charge`` *(optional)* (double)
- ``battery_percentage`` *(optional)* (double)
- ``battery_power_supply_status`` *(optional)* (double)
- ``battery_power_supply_health`` *(optional)* (double)
- ``battery_present`` *(optional)* (bool)

Published Topics
^^^^^^^^^^^^^^^^^^

The broadcaster publishes two topics:

- ``~/raw_battery_states`` (``control_msgs/msg/BatteryStateArray``)
Publishes **per-battery state messages**, containing the raw values for each configured battery.

- ``~/battery_state`` (``sensor_msgs/msg/BatteryState``)
Publishes a **single aggregated battery message** representing the combined status across all batteries.

.. list-table::
:header-rows: 1

* - Field
- ``battery_state``
- ``raw_battery_states``
* - ``header.frame_id``
- Empty
- Battery name
* - ``voltage``
- Mean across all batteries
- From battery's ``battery_voltage`` interface *(mandatory)* (NaN if unmeasured)
* - ``temperature``
- Mean across batteries reporting temperature
- From battery's ``battery_temperature`` interface if enabled, otherwise nan.
* - ``current``
- Mean across batteries reporting current
- From battery's ``battery_current`` interface if enabled, otherwise nan.
* - ``charge``
- Sum across batteries reporting charge
- From battery's ``battery_charge`` interface if enabled, otherwise nan.
* - ``capacity``
- Sum across all batteries
- From battery's ``capacity`` parameter if provided, otherwise nan.
* - ``design_capacity``
- Sum across all batteries
- From battery's ``design_capacity`` parameter if provided, otherwise nan.
* - ``percentage``
- Mean across batteries reporting/calculating percentage
- From battery's ``battery_percentage`` interface if enabled, otherwise calculated from battery's ``minimum_voltage`` and ``maximum_voltage`` parameters.
* - ``power_supply_status``
- Highest reported enum value
- From battery's ``battery_power_supply_status`` interface if enabled, otherwise 0 (unknown).
* - ``power_supply_health``
- Highest reported enum value
- From battery's ``battery_power_supply_health`` interface if enabled, otherwise 0 (unknown).
* - ``power_supply_technology``
- Reported as-is if same across all batteries, otherwise set to *Unknown*
- From battery's ``power_supply_technology`` parameter if provided, otherwise 0 (unknown).
* - ``present``
- True
- From battery's ``battery_present`` interface if enabled, otherwise true if the battery voltage value is valid (not NaN and not 0.0).
* - ``cell_voltage``
- Empty
- Empty
* - ``cell_temperature``
- Empty
- Empty
* - ``location``
- All battery locations appended
- From battery's ``location`` parameter if provided, otherwise empty.
* - ``serial_number``
- All battery serial numbers appended
- From battery's ``serial_number`` parameter if provided, otherwise empty.


Parameters
^^^^^^^^^^^
This controller uses the `generate_parameter_library <https://github.com/PickNikRobotics/generate_parameter_library>`_ to manage parameters.
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.

List of parameters
=========================
.. generate_parameter_library_details:: ../src/battery_state_broadcaster_parameters.yaml

Example Parameter File
=========================

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>`_:

.. literalinclude:: ../test/battery_state_broadcaster_params.yaml
:language: yaml

Migration for ``ipa320/ros_battery_monitoring`` users
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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.

To adapt your setup to the new ``battery_state_broadcaster`` configuration:

1. Update your hardware interface name from ``voltage`` → ``battery_voltage``.

2. Convert your controller parameters from

.. code-block:: yaml

battery_state_broadcaster:
ros__parameters:
sensor_name: "battery_state"
design_capacity: 100.0
# https://github.com/ros2/common_interfaces/blob/rolling/sensor_msgs/msg/BatteryState.msg
power_supply_technology: 2

to:

.. code-block:: yaml

battery_state_broadcaster:
ros__parameters:
batteries: ["battery_state"]
battery_state:
design_capacity: 100.0
power_supply_technology: 2

**Notes**:

- Parameters must provide **either** sensor_name **or** batteries.
- If both are empty → the broadcaster will fail to configure.
- If both are set → the broadcaster will throw an error.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) 2025, b-robotized Group
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef BATTERY_STATE_BROADCASTER__BATTERYSTATEBROADCASTER_HPP_
#define BATTERY_STATE_BROADCASTER__BATTERYSTATEBROADCASTER_HPP_

#pragma message( \
"BatteryStateBroadcaster.hpp is deprecated, please use battery_state_broadcaster.hpp instead.")

#include "battery_state_broadcaster/battery_state_broadcaster.hpp"

#endif // BATTERY_STATE_BROADCASTER__BATTERYSTATEBROADCASTER_HPP_
Loading
Loading