🚨Powering Bots Up Together

gayatri kumargayatri kumar
7 min read

πŸŒ… Robot Town Needs an Alarm Clock

So far, you've been waking each bot up manually like:

ros2 run weather_bot announcer
ros2 run mood_bot feel

Imagine doing that for 10 bots every morning!
That’s like manually waking each robot in town by knocking on their doors one at a time. 😫

Enter: Launch Files πŸš€

They're like the town alarm system β€” start all bots on a schedule, with one press of a button!


🧠 Analogy: Launch File = Town Sunrise Schedule

Think of a launch file as Robot Town's daily startup plan.

At sunrise, it:

  • Rings every robot’s morning bell

  • Starts specific bots with predefined roles

  • Maybe even tells them what to do

It’s written in Python and managed using launch from launch_ros.


πŸ—οΈ Step 1: Set Up a New Package: town_starter

Let’s create a dedicated package just to manage town-wide startup routines.

cd ~/robot_town_ws/src
ros2 pkg create --build-type ament_python --dependencies rclpy launch launch_ros town_starter

This gives:

town_starter/
β”œβ”€β”€ town_starter/
β”‚   └── __init__.py
β”œβ”€β”€ setup.py
β”œβ”€β”€ package.xml

Let’s also create a launch/ folder inside town_starter/:

mkdir -p town_starter/launch
touch town_starter/launch/start_town.py

πŸ› οΈ Step 2: Add Our New Bots – TrafficBot & LightBot

We’ll quickly stub out two new packages β€” we’ll build their logic in Part 2.

ros2 pkg create --build-type ament_python --node-name light_control light_bot
ros2 pkg create --build-type ament_python --node-name traffic_manager traffic_bot

Folder structure now looks like this:

robot_town_ws/
└── src/
    β”œβ”€β”€ ...
    β”œβ”€β”€ traffic_bot/
    β”œβ”€β”€ light_bot/
    └── town_starter/
        β”œβ”€β”€ launch/
        β”‚   └── start_town.py

πŸ§ͺ Step 3: Launch File Basics (Wake-up Schedule)

Let’s write a Python-based launch file inside start_town.py. For now, it’ll just print hello messages β€” we’ll link to the real bots in Part 2.

# Import the LaunchDescription class to define what this launch file will do
from launch import LaunchDescription

# Import the Node action to describe nodes to be launched
from launch_ros.actions import Node

# Function required by ROS2 launch system; it returns the launch setup
def generate_launch_description():
    return LaunchDescription([
        # First node: Launches the 'light_control' executable from the 'light_bot' package
        Node(
            package='light_bot',            # The name of the ROS2 package
            executable='light_control',     # The name of the executable to run
            name='light_bot'                # The name this node will take in the ROS2 graph
        ),

        # Second node: Launches the 'traffic_manager' executable from the 'traffic_bot' package
        Node(
            package='traffic_bot',          # The name of the ROS2 package
            executable='traffic_manager',   # The name of the executable to run
            name='traffic_bot'              # The name this node will take in the ROS2 graph
        )
    ])

🧠 Explanation:

  • Node(...) tells ROS2 to start a node

  • package is your bot’s package name

  • executable is what to run (as defined in setup.py)

  • name is how ROS2 will refer to it in logs and tools

This file acts like:

πŸ—“οΈ β€œStart light_bot and traffic_bot now.”


πŸ“ Step 4: Update setup.py to Include the Launch File

In town_starter/setup.py, add:

import os
from glob import glob
from setuptools import setup

# Define the name of the package
package_name = 'town_starter'

setup(
    name=package_name,  # Name of the package used for installation and discovery
    ...
    data_files=[
        # Install the package.xml file into the share directory of the package
        ('share/' + package_name, ['package.xml']),

        # Install all .py files from the 'launch' folder into the launch folder in the share directory
        # glob('launch/*.py') finds all Python launch files in the local 'launch' folder
        ('share/' + package_name + '/launch', glob('launch/*.py')),
    ],
    ...
)

This makes sure the launch file is installed correctly during the build.


πŸ§ͺ Step 5: Build the Whole Town Again

From your root workspace:

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

πŸš€ Step 6: Try Launching It (No Real Bots Yet!)

We can test the launch file even though our bots don’t do anything yet.

ros2 launch town_starter start_town.py

Expected output (or error if bots not built yet):

[INFO] [launch_ros.actions.Node]: light_bot started
[INFO] [launch_ros.actions.Node]: traffic_bot started

πŸŽ‰ Launch file is in place β€” our bots will respond once their logic is wired in Part 2.


πŸ“Œ Mini Map: Where Are We?

robot_town_ws/
└── src/
    β”œβ”€β”€ mayor_bot/
    β”œβ”€β”€ door_bot/
    β”œβ”€β”€ chatter_bot/
    β”œβ”€β”€ ...
    β”œβ”€β”€ traffic_bot/
    β”œβ”€β”€ light_bot/
    └── town_starter/
        └── launch/
            └── start_town.py

πŸ“Œ Summary So Far

ConceptWhat It Means in Robot Town
launch fileMaster schedule to start multiple bots
Node(...)Tells which bot to launch
ros2 launchRuns the schedule
town_starterPackage that holds launch files

πŸ› οΈ Building the Bots We’ll Launch

So far, we have created a launch file but our bots didn’t do anything yet.

Now let’s give TrafficBot and LightBot some life β€” small tasks that make the town feel alive!


🚦 TrafficBot: Keeps an Eye on Town Roads

Navigate to the traffic bot package:

cd ~/robot_town_ws/src/traffic_bot/traffic_bot

Create a file named traffic_manager.py:

touch traffic_manager.py

Paste the following inside:

import rclpy
from rclpy.node import Node

class TrafficBot(Node):
    def __init__(self):
        super().__init__('traffic_bot')
        self.get_logger().info("πŸš— TrafficBot is monitoring intersections...")

def main(args=None):
    rclpy.init(args=args)
    bot = TrafficBot()
    rclpy.spin(bot)
    bot.destroy_node()
    rclpy.shutdown()

Update __init__.py:

from .traffic_manager import main

πŸ›  setup.py Changes for Executable

Inside traffic_bot/setup.py, update:

entry_points={
    'console_scripts': [
        'traffic_manager = traffic_bot.traffic_manager:main',
    ],
},

πŸ’‘ LightBot: Manages Street Lights

Now do the same for LightBot:

cd ~/robot_town_ws/src/light_bot/light_bot
touch light_control.py

Paste this:

import rclpy
from rclpy.node import Node

class LightBot(Node):
    def __init__(self):
        super().__init__('light_bot')
        self.get_logger().info("πŸ’‘ LightBot is turning on the town street lights!")

def main(args=None):
    rclpy.init(args=args)
    bot = LightBot()
    rclpy.spin(bot)
    bot.destroy_node()
    rclpy.shutdown()

Update __init__.py:

from .light_control import main

And in light_bot/setup.py:

entry_points={
    'console_scripts': [
        'light_control = light_bot.light_control:main',
    ],
},

πŸ“¦ Rebuild Robot Town!

Back at the root of your workspace:

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

πŸš€ Time to Launch the Whole Town!

Now run your launch file again:

ros2 launch town_starter start_town.py

And voila! You should see output like:

[light_bot] πŸ’‘ LightBot is turning on the town street lights!
[traffic_bot] πŸš— TrafficBot is monitoring intersections...

Your launch file just woke up two bots β€” one looking at traffic, the other lighting the roads. πŸŒƒπŸš¦


πŸ—‚οΈ Recap of Folder Structure

Here’s where we are now:

robot_town_ws/
└── src/
    β”œβ”€β”€ mayor_bot/
    β”œβ”€β”€ door_bot/
    β”œβ”€β”€ chatter_bot/
    β”œβ”€β”€ light_bot/
    β”‚   └── light_bot/
    β”‚       β”œβ”€β”€ __init__.py
    β”‚       └── light_control.py
    β”œβ”€β”€ traffic_bot/
    β”‚   └── traffic_bot/
    β”‚       β”œβ”€β”€ __init__.py
    β”‚       └── traffic_manager.py
    └── town_starter/
        β”œβ”€β”€ launch/
        β”‚   └── start_town.py

πŸ’‘ Concept Recap

TermMeaning in Robot Town
Launch FileCity-wide morning alarm system
Node(...)Schedule for which bot to start
ros2 launchThe command that starts the daily routine
LightBot & TrafficBotTwo bots now started by one command

🧠 What’s __init__.py Doing in This Case?

When you write this in traffic_bot/traffic_bot/__init__.py:

from .traffic_manager import main

You are making the main() function from traffic_manager.py importable from the entire package.

🧩 Why Are We Doing This?

Because of how ROS 2 uses entry points in the setup.py file!

Here’s an example you probably have in your setup.py:

entry_points={
    'console_scripts': [
        'traffic = traffic_bot:main',
    ],
},

This tells ROS 2:

β€œHey, when someone runs ros2 run traffic_bot traffic, go into the traffic_bot package and run the main() function.”

Now, for that to work:

  • The package (traffic_bot) must expose main() at the top level, and that’s exactly what __init__.py is doing.

  • __init__.py links the internal file (traffic_manager.py) to the package namespace, making main() visible like this:

      traffic_bot.main()
    

Think of traffic_manager.py as the control room, and __init__.py as the front desk of the TrafficBot Department.

When someone runs ros2 run traffic_bot traffic, they don’t walk all the way to the control room β€” they ask the front desk, and the desk says, β€œYup, go right ahead, here's main() from traffic_manager.”

TL;DR πŸ“

βœ… __init__.py re-exports main()
βœ… Enables ros2 run traffic_bot traffic to work
βœ… Keeps your code modular and clean


🎯 Mini Project Review

βœ… You’ve:

  • Created a launch file that starts multiple bots

  • Written basic functionality for two bots

  • Connected everything in one powerful command

Robot Town is starting to feel like a real city!


πŸ“’ What’s Next: The Robot Town Ledger β€” YAML & Launch Files Mastery

Ready to become the master of Robot Town’s command center? Next, we dive into YAML β€” the secret language behind launch files β€” and how to wield it to organize and control your bots with ease.
Unlock the full power of launching and configuring your robot crew like a true mayor! πŸ—‚οΈβœ¨πŸ€–

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