Introduction
In this detailed guide, we will explore how to set up and automatically play music in ROS 2 (Robot Operating System) on Ubuntu 22.04. We will use the ROS media package, which includes the necessary nodes and tools for playing music and handling media files. The purpose of this tutorial is not to create a status robot speaker but rather to focus on the process of setting up and playing music in ROS 2 on Ubuntu 22.04.
Prerequisites
Before we begin, ensure that you have the following prerequisites installed:
- Ubuntu 22.04
- ROS 2 Desktop-Full installation (Installation Guide)
Setting Up the Environment
First, we need to set up the environment for our ROS 2 project. Create a new workspace and source the setup.bash file:
$ mkdir -p ~/ros_music_ws/src
$ cd ~/ros_music_ws
$ wget https://raw.githubusercontent.com/ros/rosdistro/rolling/ros.repos
$ sudo apt-get install ros--desktop-full ros--ros-base ros--media
$ sudo apt-get install python3-rosdep python3-colcon-common-msgs
$ rosdep init
$ rosdep update
$ colcon build
$ source install/setup.bash
Creating the ROS 2 Music Player Node
Next, we will create a new ROS 2 node to play music. Create a new package named "music_player" and add the following files:
$ mkdir -p ~/ros_music_ws/src/music_player
$ cd ~/ros_music_ws/src/music_player
$ touch CMakeLists.txt package.xml
Edit the "package.xml" file:
A ROS 2 node for playing music.
rclpy
media
rclpy
media
Writing the ROS 2 Music Player Node Code
Now, write the code for the music player node. Create a new file named "player.py" inside the "src/music_player" directory:
#!/usr/bin/env python3 import rclpy from rclpy.node import Node from rclpy.qos import QoSProfile from rclpy.action import ActionServer, Action from rclpy.qos import QoSProfile as qos_profile from media_msgs.msg import MediaItemclass MusicPlayer(Node):
Initialize ROS 2 node
def init(self): super().init('music_player') self.create_action_server() self.create_timer(1.0, self.play_music)
Set up action server
self.action_server = self.create_action_server('play_music', PlayMusic, self) self.get_logger().info('Action server ready.')
Set up timer
self.timer = self.create_timer(1.0, self.play_music) self.get_logger().info('Timer set up.')
Set up subscriber
self.subscription = self.create_subscription(MediaItem, 'media_items', self.handle_media_items, 10) self.get_logger().info('Subscriber set up.')
def create_action_server(self): self.action = self.create_action(PlayMusic, 'play_music') self.action_server = self.create_action_server(self.action, 'play_music')
def handle_media_items(self, msg): self.get_logger().info(f'Received media item: {msg.filename}') self.media_item = msg
def play_music(self): if self.media_item: self.get_logger().info('Playing music...') self.media_player = self.create_media_player(self.media_item.filename) self.media_player.play() self.media_player.on_done = self.media_player_done self.media_player.start() self.media_item = None else: self.get_logger().info('No media item to play.')
def media_player_done(self, event): self.get_logger().info('Media player finished.') self.media_player = None
def create_media_player(self, filename): media_player = self.create_node('media_player') media_player.get_logger().info(f'Creating media player for file: {filename}') media_player.get_logger().info('Media player initialized.') media_player.get_logger().info('Playing media...') media_player.create_media_player().set_media_file(filename) media_player.create_media_player().play() return media_player
class PlayMusic(Action): def init(self, node): super().init(node)
def execute(self, goal): self.get_logger().info('Executing play music action.') self.get_logger().info(f'Playing media item: {goals.media_item.filename}') self.node.play_music() self.set_succeeded()
def cancel(self): self.get_logger().info('Cancelling play music action.') self.set_aborted()
def del(self): self.get_logger().info('Cleaning up play music action.')
def create(node, action_class): return action_class(node)
def main(args=None): rclpy.init(args=args) node = MusicPlayer() rclpy.spin(node) node.destroy_node() rclpy.shutdown()
if name == 'main': main()
Building and Running the ROS 2 Music Player Node
Build and run the music player node:
$ cd ~/ros_music_ws
$ colcon build
$ . install/setup.bash
$ ros2 run music_player music_player.py
Publishing Media Items
To test the music player node, we will create a separate node to publish media items. Create a new package named "media_publisher" and add the following files:
$ mkdir -p ~/ros_music_ws/src/media_publisher
$ cd ~/ros_music_ws/src/media_publisher
$ touch CMakeLists.txt package.xml
Edit the "package.xml" file:
A ROS 2 node for publishing media items.
rclpy
rclpy
media
Writing the ROS 2 Media Publisher Node Code
Create a new file named "publisher.py" inside the "src/media_publisher" directory:
#!/usr/bin/env python3 import rclpy from rclpy.node import Node from rclpy.qos import QoSProfile from media_msgs.msg import MediaItemclass MediaPublisher(Node): def init(self): super().init('media_publisher') self.publisher = self.create_publisher(MediaItem, 'media_items', 10) self.get_logger().info('Media publisher initialized.') self.get_logger().info('Publishing media item...') self.media_item = MediaItem() self.media_item.filename = 'test.mp3' self.publisher.publish(self.media_item) self.create_timer(1.0, self.publish_media_item)
def publish_media_item(self): self.media_item.filename = 'test2.mp3' self.publisher.publish(self.media_item)
def main(args=None): rclpy.init(args=args) node = MediaPublisher() rclpy.spin(node) node.destroy_node() rclpy.shutdown()
if name == 'main': main()
Building and Running the ROS 2 Media Publisher Node
Build and run the media publisher node:
$ cd ~/ros_music_ws
$ colcon build
$ . install/setup.bash
$ ros2 run media_publisher publisher.py
Testing the ROS 2 Music Player Node
Now, test the music player node by running it in a new terminal:
$ cd ~/ros_music_ws
$ colcon build
$ . install/setup.bash
$ ros2 run music_player music_player.py
Summary and References
In this guide, we learned how to set up and automatically play music in ROS 2 on Ubuntu 22.04 using the ROS media package. We created a new ROS 2 node for playing music and another node for publishing media items. This tutorial demonstrated the process of creating, building, and running ROS 2 nodes.
For further reading: