πŸ€–Practice Day

gayatri kumargayatri kumar
9 min read

🎑 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 LearnedRole in Today’s Project
PackagesEach bot has its own house (code base)
NodesEvery bot has a brain
Publishers & SubscribersBots talk and listen
MessagesBots speak the same language
Launch FilesTown-wide schedule to start everything
LoggingEach bot keeps a diary during the event
WorkspacesOne 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 NameRole
MayorBotStarts the festival (publisher)
DanceBotDances when signaled
LightBotLights up when dancing starts
UmbrellaBotOpens umbrella if cloudy
WeatherBotPublishes the weather forecast

Today, we’ll:

  • Plan the folder structure

  • Set up a brand new package for DanceBot

  • Reconnect WeatherBot and UmbrellaBot using pub-sub

  • Review 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 DanceBot actually dance (publish steps)

  • Connect it with LightBot and others

  • Create a launch file for the performance


🧠 Concept Reinforcement

ConceptFestival Analogy
PublisherAnnouncer on stage
SubscriberBots listening from the wings
NodeBot brain executing its act
Launch FileStage Manager calling cues
WorkspaceRehearsal 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:

  • DanceBot announcing dance moves

  • LightBot flashing lights for each move

  • UmbrellaBot reacting to WeatherBot'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

BotFunction
DanceBotPublishes dance moves
LightBotReacts to dance moves with lights
WeatherBotPublishes rain/sun info
UmbrellaBotOpens 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:

  • MayorBot opens the festival with a speech

  • TrafficBot guides crowds

  • A 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:

SkillBotArticle
ROS2 PackagesDoorBot, MayorBot1–2
NodesChatterBot3
PublishersWeatherBot4
SubscribersUmbrellaBot5
Custom MessagesEmojiBot6
LoggingGuardBot7
WorkspacesTown Layout8
Launch FilesMaster Launch9
SimulationEveryone Together10 πŸŽ‰

✨ 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. πŸ₯‚πŸ€–πŸŽ†

0
Subscribe to my newsletter

Read articles from gayatri kumar directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

gayatri kumar
gayatri kumar