
๐ก Welcome to the Festival Grounds!
Robot Town is buzzing. ๐๏ธ The square is lit up. The bots have all been practicing their routines and today... itโs Performance Day!
Think of this as a robotics parade: each bot has a role โ one speaks, one listens, one dances, one makes announcements. But they need coordination. Thatโs our job!
๐ง Recalling What We Know
Before we begin, letโs quickly look at what weโve learned so far and how itโll help today:
| What We Learned | Role in Todayโs Project |
| Packages | Each bot has its own house (code base) |
| Nodes | Every bot has a brain |
| Publishers & Subscribers | Bots talk and listen |
| Messages | Bots speak the same language |
| Launch Files | Town-wide schedule to start everything |
| Logging | Each bot keeps a diary during the event |
| Workspaces | One central hub where everything connects |
Everything we do in this project will rely on these foundational skills.
๐ฆ Our Festival Line-Up
Weโll have the following bots ready for showtime:
| Bot Name | Role |
MayorBot | Starts the festival (publisher) |
DanceBot | Dances when signaled |
LightBot | Lights up when dancing starts |
UmbrellaBot | Opens umbrella if cloudy |
WeatherBot | Publishes the weather forecast |
Today, weโll:
Plan the folder structure
Set up a brand new package for
DanceBotReconnect
WeatherBotandUmbrellaBotusing pub-subReview how this connects to earlier bots
๐๏ธ Organizing the Workspace
Weโll use the same workspace we've been using:
robot_town_ws/
โโโ src/
โโโ mayor_bot/
โโโ door_bot/
โโโ chatter_bot/
โโโ weather_bot/
โโโ umbrella_bot/
โโโ light_bot/
โโโ traffic_bot/
โโโ town_starter/
โโโ dance_bot/ <-- ๐บ Our new star!
Letโs now create dance_bot.
๐บ Creating DanceBot
Open your terminal in the workspace:
cd ~/robot_town_ws/src
ros2 pkg create --build-type ament_python dance_bot
Update the setup.py in dance_bot/:
entry_points={
'console_scripts': [
'dance_node = dance_bot.dance_node:main',
],
},
Then create the bot's brain file:
cd dance_bot/dance_bot
touch dance_node.py
And edit dance_node.py:
import rclpy
from rclpy.node import Node
class DanceBot(Node):
def __init__(self):
super().__init__('dance_bot')
self.get_logger().info("๐บ DanceBot is warmed up and waiting to groove!")
def main(args=None):
rclpy.init(args=args)
node = DanceBot()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
This is a basic node โ it doesnโt dance yet, but itโs ready.
๐ฆ๏ธ Rewiring WeatherBot and UmbrellaBot
Now, let's make sure our previous bots are ready for the festival too.
weather_bot/weather_bot/weather_publisher.py (Publishes weather updates)
from std_msgs.msg import String
self.weather_pub = self.create_publisher(String, 'weather', 10)
self.timer = self.create_timer(2.0, self.send_weather)
def send_weather(self):
forecast = "rainy" # hardcoded for now
self.weather_pub.publish(String(data=forecast))
self.get_logger().info(f"๐ง๏ธ Weather today: {forecast}")
umbrella_bot/umbrella_bot/umbrella_listener.py (Subscribes and reacts)
from std_msgs.msg import String
self.subscriber = self.create_subscription(String, 'weather', self.reaction, 10)
def reaction(self, msg):
if msg.data == "rainy":
self.get_logger().info("โ๏ธ UmbrellaBot: Rain detected! Opening umbrella.")
else:
self.get_logger().info("โ๏ธ UmbrellaBot: All clear.")
๐งช Build and Test
Back in the root of your workspace:
cd ~/robot_town_ws
colcon build
source install/setup.bash
Now test the bots individually:
ros2 run weather_bot weather_publisher
ros2 run umbrella_bot umbrella_listener
ros2 run dance_bot dance_node
You should see:
WeatherBot reporting rain
UmbrellaBot opening its umbrella
DanceBot logging its readiness
๐ What Weโve Set Up
A new bot ready to perform
Old bots rewired to join the show
All bots live in a clean workspace
Next, weโll:
Make
DanceBotactually dance (publish steps)Connect it with
LightBotand othersCreate a launch file for the performance
๐ง Concept Reinforcement
| Concept | Festival Analogy |
| Publisher | Announcer on stage |
| Subscriber | Bots listening from the wings |
| Node | Bot brain executing its act |
| Launch File | Stage Manager calling cues |
| Workspace | Rehearsal space where all bots live |
๐ชฉ Let the Dance Begin: Making DanceBot Groove
Right now, DanceBot just logs a message. Letโs give it real dance steps โ published in sequence, which other bots can react to!
Step 1: Define the Dance Steps
Update dance_node.py inside dance_bot/dance_bot/:
from std_msgs.msg import String
import random
class DanceBot(Node):
def __init__(self):
super().__init__('dance_bot')
self.publisher_ = self.create_publisher(String, 'dance_moves', 10)
self.timer = self.create_timer(2.0, self.dance_step)
self.moves = ["step_left", "step_right", "spin", "jump"]
self.get_logger().info("๐บ DanceBot is grooving!")
def dance_step(self):
move = random.choice(self.moves)
msg = String()
msg.data = move
self.publisher_.publish(msg)
self.get_logger().info(f"๐บ DanceBot: Performing move '{move}'")
๐บ This bot is now broadcasting dance moves on the dance_moves topic.
๐ก LightBot Joins the Stage
Letโs bring in LightBot, who reacts to dance steps and flashes lights for each move!
Create this file: light_bot/light_bot/light_listener.py
from std_msgs.msg import String
class LightBot(Node):
def __init__(self):
super().__init__('light_bot')
self.subscriber = self.create_subscription(String, 'dance_moves', self.react_to_dance, 10)
self.get_logger().info("๐ก LightBot: Ready to sync with DanceBot.")
def react_to_dance(self, msg):
self.get_logger().info(f"๐ก LightBot: Flashing lights for '{msg.data}' move!")
And update the entry point in light_bot/setup.py:
entry_points={
'console_scripts': [
'light_listener = light_bot.light_listener:main',
],
},
๐ง Rebuild and Source
cd ~/robot_town_ws
colcon build
source install/setup.bash
๐งช Try the Choreography!
In three terminals:
ros2 run dance_bot dance_node
ros2 run light_bot light_listener
ros2 run weather_bot weather_publisher
ros2 run umbrella_bot umbrella_listener
๐ Youโll see:
DanceBotannouncing dance movesLightBotflashing lights for each moveUmbrellaBotreacting toWeatherBot's forecast
Our town square is ALIVE. ๐
๐ฌ Letโs Launch the Show
Now weโll write a launch file to run everything together. Weโll use town_starter as our launch package (already created earlier in Article 9).
Create festival_launch.py inside town_starter/town_starter/:
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(package='dance_bot', executable='dance_node', output='screen'),
Node(package='light_bot', executable='light_listener', output='screen'),
Node(package='weather_bot', executable='weather_publisher', output='screen'),
Node(package='umbrella_bot', executable='umbrella_listener', output='screen'),
])
Update the entry point in town_starter/setup.py:
entry_points={
'console_scripts': [
'festival_launch = town_starter.festival_launch:generate_launch_description',
],
},
And update town_starter/launch/festival_launch.py:
mkdir -p town_starter/launch
cp town_starter/town_starter/festival_launch.py town_starter/launch/festival_launch.py
Rebuild:
colcon build
source install/setup.bash
Now launch the entire festival!
ros2 launch town_starter festival_launch.py
๐ All bots now start together. The town square becomes a stage with lights, announcements, reactions, and dances.
๐ Quick Summary
| Bot | Function |
| DanceBot | Publishes dance moves |
| LightBot | Reacts to dance moves with lights |
| WeatherBot | Publishes rain/sun info |
| UmbrellaBot | Opens umbrella if it's rainy |
Weโve connected four bots using pure pub/sub logic and launch orchestration.
๐ ๏ธ What You Practiced
Custom logic inside publishers & subscribers
Coordinated behavior using ROS2 topics
Random events and fun choreography
Launch files to sync multiple bots
Real-world robotics communication patterns
๐ก Next Stop: The Big Finale!
Weโre not done yet.
Now, we go BIG:
MayorBotopens the festival with a speechTrafficBotguides crowdsA new bot joins with music (hint:
DJBot)Emoji Mood Updates from each bot
And a closing message from the mayor
This will use custom messages, logs, and full launch orchestration.
Grab your tickets. The final performance is about to begin. ๐๏ธ๐ค๐ถ
๐๏ธ Welcome to the Festival Square
Citizens of Robot Town gather in the town square, ready to perform!
The Mayor takes the stageโฆ
๐๏ธ 1. MayorBot Announces the Start
Package: mayor_bot
File: announcer.py
from rclpy.node import Node
from std_msgs.msg import String
class MayorBot(Node):
def __init__(self):
super().__init__('mayor_bot')
self.publisher_ = self.create_publisher(String, 'festival_announcement', 10)
self.timer = self.create_timer(5.0, self.announce)
self.messages = [
"๐ข Welcome to the Robot Town Festival!",
"๐ Let the performances begin!",
"๐ค Celebrate communication and cooperation!"
]
self.index = 0
def announce(self):
if self.index < len(self.messages):
msg = String()
msg.data = self.messages[self.index]
self.publisher_.publish(msg)
self.get_logger().info(f"MayorBot announces: {msg.data}")
self.index += 1
๐ง 2. DJBot Responds with Music
Package: dj_bot
File: dj_node.py
from rclpy.node import Node
from std_msgs.msg import String
class DJBot(Node):
def __init__(self):
super().__init__('dj_bot')
self.subscription = self.create_subscription(String, 'festival_announcement', self.react, 10)
def react(self, msg):
self.get_logger().info(f"๐ต DJBot plays a beat after: '{msg.data}' โ ๐ถ boom boom BOP!")
๐ญ 3. EmojiBot Shares Mood Updates
Custom Message (already built in Article 6):
# bot_interfaces/msg/Mood.msg
string bot_name
string mood
Package: emoji_bot
File: emoji_node.py
from bot_interfaces.msg import Mood
from rclpy.node import Node
import random
class EmojiBot(Node):
def __init__(self):
super().__init__('emoji_bot')
self.publisher_ = self.create_publisher(Mood, 'mood_updates', 10)
self.timer = self.create_timer(3.0, self.send_mood)
self.moods = ['๐', '๐ฅณ', '๐ค', '๐บ', '๐']
def send_mood(self):
msg = Mood()
msg.bot_name = 'EmojiBot'
msg.mood = random.choice(self.moods)
self.publisher_.publish(msg)
self.get_logger().info(f"EmojiBot: {msg.bot_name} feels {msg.mood}")
๐ 4. MoodListener Records the Town's Vibes
Package: mood_listener
File: mood_listener.py
from bot_interfaces.msg import Mood
from rclpy.node import Node
class MoodListener(Node):
def __init__(self):
super().__init__('mood_listener')
self.subscription = self.create_subscription(Mood, 'mood_updates', self.react, 10)
def react(self, msg):
self.get_logger().info(f"๐ MoodListener: {msg.bot_name} is feeling {msg.mood}")
๐ 5. Launch the Festival!
In your town_starter/launch/festival_finale.py:
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(package='mayor_bot', executable='announcer', output='screen'),
Node(package='dj_bot', executable='dj_node', output='screen'),
Node(package='emoji_bot', executable='emoji_node', output='screen'),
Node(package='mood_listener', executable='mood_listener', output='screen'),
Node(package='dance_bot', executable='dance_node', output='screen'),
Node(package='light_bot', executable='light_listener', output='screen'),
Node(package='weather_bot', executable='weather_publisher', output='screen'),
Node(package='umbrella_bot', executable='umbrella_listener', output='screen'),
])
Now run the full town festival:
cd ~/robot_town_ws
colcon build
source install/setup.bash
ros2 launch town_starter festival_finale.py
๐ Festival Output (Sample)
[mayor_bot] ๐ข MayorBot announces: Welcome to the Robot Town Festival!
[dj_bot] ๐ต DJBot plays a beat after: 'Welcome to the Robot Town Festival!' โ ๐ถ boom boom BOP!
[emoji_bot] EmojiBot: EmojiBot feels ๐ฅณ
[mood_listener] ๐ MoodListener: EmojiBot is feeling ๐ฅณ
[weather_bot] ๐ค๏ธ WeatherBot: It's raining โ
[umbrella_bot] โ๏ธ UmbrellaBot: Rain detected! Opening umbrella...
[dance_bot] ๐ DanceBot spins!
[light_bot] ๐ก LightBot sees: It's raining โ โ Turning on warm lights
[mayor_bot] ๐ MayorBot announces: Let the performances begin!
[dj_bot] ๐ต DJBot plays a beat after: 'Let the performances begin!' โ ๐ถ boom boom BOP!
๐ Grand Recap
This festival showcased everything weโve built:
| Skill | Bot | Article |
| ROS2 Packages | DoorBot, MayorBot | 1โ2 |
| Nodes | ChatterBot | 3 |
| Publishers | WeatherBot | 4 |
| Subscribers | UmbrellaBot | 5 |
| Custom Messages | EmojiBot | 6 |
| Logging | GuardBot | 7 |
| Workspaces | Town Layout | 8 |
| Launch Files | Master Launch | 9 |
| Simulation | Everyone Together | 10 ๐ |
โจ Whatโs Next?
Robot Town is thriving. But weโve only scratched the surface!
In the next set of articles, weโll explore:
๐ ๏ธ Services (Bots asking others to perform tasks)
๐ง Parameters (Bot configuration)
๐น๏ธ Lifecycle nodes (Controlled state machines)
๐๏ธ RViz2 and simulation tools
๐ข TurtleBot and physical robot control
Stay tuned. The next chapter of Robot Town is just around the corner.
For nowโฆ enjoy the afterparty. ๐ฅ๐ค๐



