๐ Letโs Build Our First Robot Home

Table of contents
- ๐๏ธ Welcome to the Construction Site
- ๐งฑ Step 1: Navigate to the Town Plot (Your Workspace)
- ๐งฐ Step 2: Letโs Lay the Foundation โ Create the Package
- ๐๏ธ Folder Structure Breakdown
- ๐ช Step 3: Add a Script โ Make the DoorBot Alive
- ๐ ๏ธ Step 4: Update setup.py with Entry Point
- ๐งฝ Step 5: Clean Workspace & Build
- ๐ What Youโve Built So Far
- ๐ฆ Recap of Where We Are
- ๐ Letโs Add a Function to the DoorBot
- ๐ Flowchart: Life of a ROS 2 Node in a Package
- ๐ก When You Have Multiple Robot Homes
- ๐งณ What Goes Inside a Package?
- ๐ง When Would You Use Multiple Workspaces?
- ๐งช Mini Project: Build a Smarter DoorBot
- โ What You Learned in This Article
- ๐ Up Next: Talking Bots!

๐๏ธ Welcome to the Construction Site
In Robot Town, every robot lives in its own home, and that home is a ROS 2 package.
Think of it like this:
๐๏ธ Robot Town
โโโ MayorBot (Package)
โ โโโ Kitchen (Python Scripts)
โ โโโ Address Plate (setup.py)
โ โโโ Blueprints (package.xml)
โ โโโ Front Door (Entry Point)
This article will walk you through building one such home โ DoorBotโs house. It will respond when called, like a voice-controlled door.
๐งฑ Step 1: Navigate to the Town Plot (Your Workspace)
Head to your workspaceโs src
directory:
cd ~/robot_town_ws/src
This is where all the robot homes (packages) live.
๐งฐ Step 2: Letโs Lay the Foundation โ Create the Package
Weโll use the ros2 pkg create
tool to generate our new home for DoorBot.
ros2 pkg create --build-type ament_python door_bot
What this command does:
Creates a folder named
door_bot
Sets it up for Python-based code (
ament_python
is the build system)Adds essential files like
setup.py
andpackage.xml
๐๏ธ Folder Structure Breakdown
Hereโs what we get:
door_bot/
โโโ door_bot/ โ Actual code lives here (like the robot's rooms)
โ โโโ __init__.py
โโโ package.xml โ Identity card: describes the robot and its dependencies
โโโ setup.cfg โ Wiring instructions for installing
โโโ setup.py โ The robotโs front door: used to launch it
โโโ resource/
โโโ door_bot โ Used internally to register your package
โ ๏ธ Wait, why is there a
door_bot
insidedoor_bot
?
The outer folder is the house, and the inner folder contains the rooms (Python files).
ROS 2 expects your code inside this second-level directory.
๐ช Step 3: Add a Script โ Make the DoorBot Alive
Navigate to the code folder:
cd door_bot/door_bot
Create a file named door.py
:
touch door.py
Paste this simple code in:
# Import the core ROS2 Python interface
import rclpy
# Import the base class used to create ROS2 nodes
from rclpy.node import Node
# ๐ช DoorBot is a friendly gatekeeper in Robot Town!
# This node just starts up and announces it's ready.
class DoorBot(Node):
def __init__(self):
# Initialize the node with the name 'door_bot'
super().__init__('door_bot')
# Log a message to show that the DoorBot is active
self.get_logger().info("๐ช DoorBot: Ready at your service!")
# ๐ Main function โ the entrance point for this ROS2 program
def main(args=None):
# Initialize the ROS2 Python client library
rclpy.init(args=args)
# Create an instance of our DoorBot node
node = DoorBot()
# Keep the node running so it can continue to operate
rclpy.spin(node)
# Clean up the node when shutting down
node.destroy_node()
# Shut down the ROS2 client library
rclpy.shutdown()
๐ง Whatโs Going On Here?
Line | Meaning |
import rclpy | ROS 2 Python client library |
Node | Base class for all bots in ROS 2 |
self.get_logger().info(...) | Print messages in ROS-style |
rclpy.spin(node) | Keeps the bot running until stopped |
This is a minimal living bot. It doesnโt do much โ just wakes up and announces itself.
๐ ๏ธ Step 4: Update setup.py
with Entry Point
Entry points = main switches to activate your bots.
Edit setup.py
:
entry_points={
'console_scripts': [
# ๐๏ธ Create a terminal command named 'door'
# When you run `ros2 run door_bot door`, it executes the `main()` function
# from the `door.py` file inside the `door_bot` package.
'door = door_bot.door:main',
],
},
This tells ROS 2:
โWhen someone runs
ros2 run door_bot door
, go todoor.py
and runmain()
.โ
๐งฝ Step 5: Clean Workspace & Build
Go back to the root of your workspace:
cd ~/robot_town_ws
colcon build
After building, source the environment:
source install/setup.bash
๐ง Wait, what is colcon build
doing?
Itโs like a contractor assembling the robot house:
Collects all packages in
src
Installs them in
install/
Generates necessary files (including the
entry_points
!)
๐ Why source install/setup.bash
?
This โconnects the power gridโ โ it tells your terminal:
โHereโs where the new bots live. You can now run them.โ
๐ What Youโve Built So Far
A real ROS 2 package named
door_bot
With a basic executable script
That runs like this:
ros2 run door_bot door
Youโll see:
[INFO] [door_bot]: ๐ช DoorBot: Ready at your service!
๐ฆ Recap of Where We Are
So far, you've:
Created a ROS 2 package named
door_bot
Added a Python script with a basic bot (
DoorBot
)Understood how
colcon build
andsetup.bash
workLaunched your bot using
ros2 run
Now, weโll decorate the home, make the bot do something real, and understand how this house fits in the larger neighborhood (aka: multiple packages in a workspace).
๐ Letโs Add a Function to the DoorBot
Just logging a message is coolโฆ but letโs go a step further.
Letโs make DoorBot respond to a knock.
๐ช Update door.py
like this:
# Import the core ROS2 Python client library
import rclpy
# Import the base Node class so we can create our own node
from rclpy.node import Node
# ๐ช DoorBot is now more than just polite โ it opens the door on a schedule!
class DoorBot(Node):
def __init__(self):
# Initialize the node with the name 'door_bot'
super().__init__('door_bot')
# Let the town know DoorBot is up and running
self.get_logger().info("๐ช DoorBot: Ready at your service!")
# ๐ Create a timer that calls the open_door method every 5 seconds
self.timer = self.create_timer(5.0, self.open_door)
# ๐ช This function simulates the door opening โ it gets called by the timer
def open_door(self):
self.get_logger().info("๐ช DoorBot: The door opens... creaaak!")
# ๐ This is the starting point of the program
def main(args=None):
# Initialize the ROS2 Python communication system
rclpy.init(args=args)
# Create an instance of DoorBot
node = DoorBot()
# Keep DoorBot alive and responding
rclpy.spin(node)
# Cleanup when shutting down
node.destroy_node()
rclpy.shutdown()
๐ง Whatโs Happening Now?
Line | Purpose |
self.create_timer(5.0, self.open _door) | Run open_door() every 5 seconds |
open_door() | Custom function that simulates door opening |
Now your bot is alive and responsive โ it's performing actions on its own. This is a basic intro to ROS 2's timer system (like scheduled jobs inside your bot).
๐ Flowchart: Life of a ROS 2 Node in a Package
t+---------------------+
| colcon build |
+---------------------+
โ
+---------------------+
| install/setup.bash |
+---------------------+
โ
+---------------------+
| ros2 run door_bot door |
+---------------------+
โ
+---------------------+
| 1. rclpy.init() |
| 2. Node created |
| 3. Timer starts |
| 4. Callback runs every X |
+---------------------+
๐ก When You Have Multiple Robot Homes
Letโs say DoorBot gets neighbors: light_bot
, cleaner_bot
, etc.
Your workspace will look like this:
robot_town_ws/
โโโ src/
โ โโโ door_bot/
โ โโโ light_bot/
โ โโโ cleaner_bot/
โโโ build/
โโโ install/
โโโ log/
Each package (house) goes into src/
.
Then:
cd ~/robot_town_ws
colcon build
source install/setup.bash
All bots will be built together and powered on via sourcing.
Now, running any of them is as easy as:
ros2 run light_bot sparkle
ros2 run cleaner_bot sweep
๐ก Tip: Always cd
into the root of your workspace before building.
๐งณ What Goes Inside a Package?
File/Folder | Role |
package.xml | Metadata, like the robotโs name and dependencies |
setup.py | The robot's launcher file (entry points) |
setup.cfg | Additional setup info |
resource/ | Internal ID marker |
<package>/<script>.py | Your actual botโs brain ๐ง |
๐ง When Would You Use Multiple Workspaces?
Sometimes, your robot grows too big. You may want:
Separate workspaces for different teams (navigation, sensors)
An overlay workspace to test new features without breaking stable code
In those cases:
mkdir -p ~/nav_ws/src
mkdir -p ~/vision_ws/src
Each workspace is built and sourced independently.
๐งช Mini Project: Build a Smarter DoorBot
๐ฏ Goal: Add a feature that lets DoorBot greet the user by name.
Add this to __init__
:
# ๐ Declare a parameter called 'guest_name' with a default value of 'friend'
# This allows us to customize who DoorBot greets using launch files or CLI!
self.declare_parameter('guest_name', 'friend')
Update open_door()
:
def open_door(self):
# ๐๏ธ Retrieve the current value of the 'guest_name' parameter
name = self.get_parameter('guest_name').get_parameter_value().string_value
# ๐ค Greet the guest by name when the door opens
self.get_logger().info(f"๐ช DoorBot: Welcome in, {name}!")
How the parameter retrieval is working broken down:
def open_door(self):
# ๐ First, get the parameter object named 'guest_name' from the node's parameter server
param = self.get_parameter('guest_name')
# The parameter object contains the value wrapped in a ParameterValue message
# ๐ฆ Extract the actual value from the parameter object
# get_parameter_value() returns a ParameterValue object, which can hold different types
param_value = param.get_parameter_value()
# ๐ฏ Since we expect a string parameter, access the string_value attribute to get the plain string
name = param_value.string_value
# ๐ Now, use the node's logger to print out an informational message
# get_logger() returns the node's logging interface which manages output formatting and verbosity
logger = self.get_logger()
# โน๏ธ info() is a method of the logger used for informational-level logs
# It prints the message to the console (or wherever the ROS2 logging is configured to send output)
logger.info(f"๐ช DoorBot: Welcome in, {name}!")
Now run like this:
ros2 run door_bot door --ros-args -p guest_name:=Alice
๐ฆ Congrats โ you've now:
Declared a ROS 2 parameter
Passed it from the command line
Customized your botโs behavior
โ What You Learned in This Article
What a ROS 2 package is and how to create one
Folder structure explained like a real-world house
Wrote a Python node with a timer
Built with
colcon
, launched withros2 run
Understood multiple packages in a single workspace
Declared and used parameters in ROS 2
๐ Up Next: Talking Bots!
๐ The next stop in Robot Town is all about Nodes โ your bots' walkie-talkies.
Weโll build a ChatterBot
that gossips every second and eventually introduce two bots that talk to each other across houses.
Subscribe to my newsletter
Read articles from gayatri kumar directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by