In this tutorial, I will show you how to create a simulated battery state publisher in ROS 2. My goal is to publish a sensor_msgs/BatteryState message to a topic named /battery_status.
The application that we will develop in this tutorial can be used as a template for a number of real-world robotic applications…the most important being:
- Autonomous docking at a charging station once the battery level gets below a certain threshold.
- ROS 2 Foxy Fitzroy installed on Ubuntu Linux 20.04 or newer. I am using ROS 2 Galactic, which is the latest version of ROS 2 as of the date of this post.
- You have already created a ROS 2 workspace. The name of our workspace is “dev_ws”, which stands for “development workspace.”
- You have Python 3.7 or higher.
You can find the files for this post here on my Google Drive.
In this implementation, I want the float32 percentage variable of the sensor_msgs/BatteryState message to start off as 1.0 and gradually decrease. 1.0 indicates a full battery at 100% charge.
In a real-life application, we could have a condition plugin that listens to the /battery_status topic and returns SUCCESS when the battery percentage is lower than a specified value, and FAILURE otherwise.
Create the Battery State Publisher Node
Open a terminal window, and move to your package.
Create a folder for battery state.
Open a new Python program called battery_state_pub.py.
Add this code.
#!/usr/bin/env python3 """ Description: Publish the battery state at a specific time interval ------- Publishing Topics: /battery_status – sensor_msgs/BatteryState ------- Subscription Topics: None ------- Author: Addison Sears-Collins Website: AutomaticAddison.com Date: November 10, 2021 """ import rclpy # Import the ROS client library for Python from rclpy.node import Node # Enables the use of rclpy's Node class from sensor_msgs.msg import BatteryState # Enable use of the sensor_msgs/BatteryState message type class BatteryStatePublisher(Node): """ Create a BatteryStatePublisher class, which is a subclass of the Node class. The class publishes the battery state of an object at a specific time interval. """ def __init__(self): """ Class constructor to set up the node """ # Initiate the Node class's constructor and give it a name super().__init__('battery_state_pub') # Create publisher(s) # This node publishes the state of the battery. # Maximum queue size of 10. self.publisher_battery_state = self.create_publisher(BatteryState, '/battery_status', 10) # Time interval in seconds timer_period = 5.0 self.timer = self.create_timer(timer_period, self.get_battery_state) # Initialize battery level self.battery_voltage = 9.0 # Initialize the battery voltage level self.percent_charge_level = 1.0 # Initialize the percentage charge level self.decrement_factor = 0.99 # Used to reduce battery level each cycle def get_battery_state(self): """ Callback function. This function gets called at the specific time interval. We decrement the battery charge level to simulate a real-world battery. """ msg = BatteryState() # Create a message of this type msg.voltage = self.battery_voltage msg.percentage = self.percent_charge_level self.publisher_battery_state.publish(msg) # Publish BatteryState message # Decrement the battery state self.battery_voltage = self.battery_voltage * self.decrement_factor self.percent_charge_level = self.percent_charge_level * self.decrement_factor def main(args=None): # Initialize the rclpy library rclpy.init(args=args) # Create the node battery_state_pub = BatteryStatePublisher() # Spin the node so the callback function is called. # Publish any pending messages to the topics. rclpy.spin(battery_state_pub) # Destroy the node explicitly # (optional - otherwise it will be done automatically # when the garbage collector destroys the node object) battery_state_pub.destroy_node() # Shutdown the ROS client library for Python rclpy.shutdown() if __name__ == '__main__': main()
Save the code, and close the file.
Change the access permissions on the file.
chmod +x battery_state_pub.py
Build the Package
Now we build the package.
Run the Node
Open a new terminal, and run the node:
ros2 run two_wheeled_robot battery_state_pub.py
Check out the current ROS topics.
ros2 topic list
Check the output on the /battery_status topic by opening a new terminal window and typing:
ros2 topic echo /battery_status
Here is the output:
That’s it! Keep building!