๐Ÿ“ปThe Town Radio System

gayatri kumargayatri kumar
6 min read

๐ŸŽฏ The Big Idea

In Robot Town so far:

  • ๐Ÿค– Each bot could speak, but to no one in particular.

  • ๐Ÿ“ข Now weโ€™re building a public radio system โ€” a topic โ€” where a bot can announce things.

  • ๐Ÿง Any bot that wants to listen just needs to tune in to the topic.

Now, weโ€™ll only build the broadcaster โ€” the publisher.


๐Ÿ—๏ธ What Are Topics in ROS2?

Imagine a radio station in the town square:

  • A bot publishes (announces) something to a topic

  • Anyone subscribed to that topic hears it

In ROS2:

  • Topics are named message channels

  • Bots publish messages to these channels

  • Others can subscribe to them (we'll do that in the next article!)


๐Ÿ“ฆ Letโ€™s Build WeatherBot

Our new robot will:

  • Live in its own house (weather_bot)

  • Publish temperature updates to a topic called /weather

  • Use ROS2 messages (std_msgs.msg.String)


๐Ÿ  Step 1: Create the weather_bot Package

Navigate to your workspace:

cd ~/robot_town_ws/src
ros2 pkg create --build-type ament_python weather_bot --dependencies rclpy std_msgs

New workspace layout:

robot_town_ws/
โ””โ”€โ”€ src/
    โ”œโ”€โ”€ mayor_bot/
    โ”œโ”€โ”€ door_bot/
    โ”œโ”€โ”€ chatter_bot/
    โ”œโ”€โ”€ greeter_bot/
    โ””โ”€โ”€ weather_bot/
        โ””โ”€โ”€ weather_bot/

๐Ÿ“ Step 2: Create the Publisher Node

Create a new Python file:

touch ~/robot_town_ws/src/weather_bot/weather_bot/weather_publisher.py

And paste this code:

import rclpy
from rclpy.node import Node
from std_msgs.msg import String
import random

class WeatherBot(Node):
    def __init__(self):
        # Initialize the node with the name 'weather_bot'
        super().__init__('weather_bot')

        # Create a publisher object to send messages on the 'weather' topic
        # Parameters explained:
        #   - String: the type of message we will publish (std_msgs/String)
        #   - 'weather': the name of the topic where messages are published
        #   - 10: the queue size or history depth for outgoing messages; 
        #         if messages are sent faster than the receiver can handle, 
        #         this limits how many messages are buffered before dropping
        self.publisher = self.create_publisher(String, 'weather', 10)

        # Create a timer that triggers the publish_weather method every 2 seconds
        # Parameters explained:
        #   - 2.0: interval in seconds between timer callbacks
        #   - self.publish_weather: the callback function to execute on timer
        self.timer = self.create_timer(2.0, self.publish_weather)

        # Log an informational message that WeatherBot has started broadcasting
        # Explanation of chained function:
        #   self.get_logger() returns the node's logging interface
        #   .info() sends an info-level message to the console/output
        self.get_logger().info("WeatherBot is now broadcasting on /weather")

    def publish_weather(self):
        # Generate a random integer temperature between 15 and 35 (inclusive)
        temp = random.randint(15, 35)

        # Create a new String message instance to hold our temperature data
        message = String()

        # Set the 'data' field of the message with a formatted temperature string
        message.data = f"Current temperature: {temp}ยฐC"

        # Publish the message to the 'weather' topic using the publisher
        # Explanation: The publisher sends the message so any subscribers
        # listening on 'weather' will receive this update
        self.publisher.publish(message)

        # Log the announcement using the node's logger (similar chaining as above)
        self.get_logger().info(f"๐Ÿ“ป Announced: {message.data}")

def main(args=None):
    rclpy.init(args=args)
    node = WeatherBot()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

๐Ÿง  Code Breakdown (In Plain Town-Speakโ„ข)

CodeWhat It Does
self.publisher = create_publisher(...)Installs a loudspeaker in the town square
self.timer = create_timer(...)Says something every 2 seconds
random.randint(...)Fakes a temperature sensor
String()ROS2 message that holds simple text
publisher.publish(message)Shouts on the /weather topic
rclpy.spin(node)Keeps the bot alive and running

๐Ÿ”ง Step 3: Update setup.py

Open weather_bot/setup.py, and add this to entry_points:

entry_points={
    'console_scripts': [
        'weather_publisher = weather_bot.weather_publisher:main',
    ],
},

This gives us an easy terminal command to run the bot.


๐Ÿ”จ Step 4: Build the Town Again

cd ~/robot_town_ws
colcon build
source install/setup.bash

Why source again? It refreshes your terminal with the latest commands from the new build โ€” like reloading a new map in the control center.


๐Ÿงช Step 5: Run WeatherBot

Make sure your workspace is built and sourced:

cd ~/robot_town_ws
source install/setup.bash

Then run the bot using its entry point:

ros2 run weather_bot weather_publisher

You should see something like:

[INFO] [weather_bot]: WeatherBot is now broadcasting on /weather
[INFO] [weather_bot]: ๐Ÿ“ป Announced: Current temperature: 21ยฐC
[INFO] [weather_bot]: ๐Ÿ“ป Announced: Current temperature: 19ยฐC
...

๐ŸŽ‰ Congratulations!
Your bot is now shouting into the town square every few seconds, broadcasting weather reports!


๐Ÿ” Step 6: Spy on the Radio (Without a Listener)

Even without a subscriber bot, we can eavesdrop using ros2 topic echo.

Open a new WSL terminal, source the workspace again:

cd ~/robot_town_ws
source install/setup.bash

Now run:

ros2 topic echo /weather

Youโ€™ll see live messages:

data: 'Current temperature: 25ยฐC'
---
data: 'Current temperature: 30ยฐC'
---

๐Ÿง  This is like a radio technician tuning into the broadcast, just to see whatโ€™s being aired.


๐Ÿ“ก Step 7: Explore Other Topic Commands

Letโ€™s explore a few more diagnostic tools ROS2 gives us:

๐Ÿงพ List All Topics

ros2 topic list

Output:

/weather
/parameter_events
/rosout

/weather is your broadcast. The others are ROS2 internals โ€” like system logs and configs.


๐Ÿ“ฆ Check the Message Type of a Topic

ros2 topic info /weather

Output:

Type: std_msgs/msg/String
Publisher count: 1
Subscriber count: 0

You can see how many bots are publishing or listening.


๐Ÿงฐ Folder Recap: Robot Town So Far

Hereโ€™s how your Robot Town is shaping up:

robot_town_ws/
โ””โ”€โ”€ src/
    โ”œโ”€โ”€ mayor_bot/       --> Greets citizens
    โ”œโ”€โ”€ door_bot/        --> Opens/closes the door
    โ”œโ”€โ”€ greeter_bot/     --> Friendly greeter
    โ”œโ”€โ”€ chatter_bot/     --> Chatty bot, says hi
    โ””โ”€โ”€ weather_bot/     --> Publishes weather updates

Each folder is a house for a bot, and each bot does its job as part of town life.


๐Ÿ—๏ธ Mini Project: Expand WeatherBot

Hereโ€™s your challenge! ๐Ÿงช

  • ๐Ÿ’ก Add humidity to the broadcast!

  • ๐Ÿ“ฆ Format: "Current temperature: 28ยฐC | Humidity: 56%"

  • ๐Ÿ“ป Then run ros2 topic echo /weather and see the full broadcast message!

๐ŸŒŸ Bonus: Try making the bot publish every random interval instead of a fixed 2 seconds. Use random.uniform(1.0, 5.0) for delays!


๐ŸŽ“ What Weโ€™ve Learned

ConceptTown AnalogyROS2 Term
Public radio systemTown square loudspeakerTopic
Bot speaking on radioAnnouncing infoPublisher
Message formatRadio sentencestd_msgs/msg/String
Peeking into messagesTuning into radioros2 topic echo

๐Ÿ‘‚ Coming Up Next: Listening Ears (Subscribing to Topics)

What if your bots had ears to hear the town radio? In this next article, weโ€™ll give our bots the power to listen by subscribing to ROS2 topics. Meet ListenerBot, tuning in to WeatherBotโ€™s broadcasts to stay informed.
Our fun mini project features UmbrellaBot, which springs into action and opens its umbrella whenever rain is announced. Get ready to make your bots truly reactive! โ˜”๐Ÿ‘‚


Ready to give robots ears as well as voices? ๐Ÿ‘‚๐Ÿ”Š
Letโ€™s build our first listener bot next!

10
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