๐๏ธThe Town Newspaper


๐๏ธ Scene in Robot Town
Today in Robot Town, we meet GuardBot, the watchful town guardian.
He strolls through the lanes, making notes like:
โPatrolling Sector A.โ
โSaw someone suspicious near the bakery.โ
โBattery low.โ
These notes arenโt for show โ theyโre vital logs that help maintain order, fix issues, and understand behavior.
๐ What is Logging in ROS2?
In ROS2, logging is a way for nodes to print meaningful information while they run. It helps us:
Understand the state of a node
Debug problems
Track what happened and when
Just like town records help solve mysteries, logs help developers debug and optimize bots.
๐ฆ Letโs Add GuardBot to Our Town
Weโll add a new package named guard_bot
.
๐ Folder Structure So Far:
Your workspace might now look like:
robot_town_ws/
โโโ src/
โโโ mayor_bot/ # from Article 1
โโโ door_bot/ # from Article 2
โโโ chatter_bot/ # from Article 3
โโโ weather_bot/ # from Article 4
โโโ umbrella_bot/ # from Article 5
โโโ mood_bot/ # from Article 6
โโโ guard_bot/ # ๐ our new logger
๐๏ธ Step 1: Create the Package
cd ~/robot_town_ws/src
ros2 pkg create --build-type ament_python guard_bot
๐ Step 2: Add the Guard Script
Edit guard_bot/guard_bot/guard_
watch.py
:
import rclpy
from rclpy.node import Node
class GuardBot(Node):
def __init__(self):
# Initialize the node with the name 'guard_bot'
super().__init__('guard_bot')
# Log an info-level message indicating GuardBot has started patrolling
# get_logger() returns the logging interface of the node
# info() sends a message with "info" severity level, usually visible in default logging
self.get_logger().info('GuardBot is now patrolling ๐ก๏ธ')
# Create a timer that calls the patrol method every 2 seconds
# Parameters:
# - 2.0: interval in seconds between calls
# - self.patrol: callback function to execute each interval
self.create_timer(2.0, self.patrol)
def patrol(self):
# Log an informational message about GuardBot's current patrol area
self.get_logger().info('Patrolling the north sector.')
# Log a debug-level message about scanning heat signatures
# Debug messages are typically hidden by default and shown only when debug logging is enabled
self.get_logger().debug('Checking heat signatures...')
# Log a warning-level message indicating suspicious activity nearby
self.get_logger().warn('Suspicious activity near bakery!')
# Log an error-level message warning that battery levels are critically low
self.get_logger().error('Battery dropping quickly!')
def main(args=None):
rclpy.init(args=args)
bot = GuardBot()
rclpy.spin(bot)
bot.destroy_node()
rclpy.shutdown()
Logging Levels:
info()
โ normal status messages visible by default.debug()
โ detailed info for developers, hidden unless debug mode is on.warn()
โ alerts about potential problems.error()
โ serious issues requiring attention.
Timer: Regularly calls
patrol
so GuardBot logs its activity periodically.Logger: Helps monitor what the bot is doing in real time.
๐ Step 3: Update setup.py
Make sure your setup.py
includes:
entry_points={
'console_scripts': [
'watch = guard_bot.guard_watch:main',
],
},
โ๏ธ Step 4: Build & Source
cd ~/robot_town_ws
colcon build
source install/setup.bash
โถ๏ธ Step 5: Run the Guard
ros2 run guard_bot watch
๐ Output:
[INFO] [guard_bot]: GuardBot is now patrolling ๐ก๏ธ
[INFO] [guard_bot]: Patrolling the north sector.
[WARN] [guard_bot]: Suspicious activity near bakery!
[ERROR] [guard_bot]: Battery dropping quickly!
๐ฆ What Just Happened?
Letโs understand the types of logs we saw:
Log Level | Meaning |
info | Normal updates |
warn | Something might go wrong |
error | Something is going wrong |
debug | Detailed output for developers (hidden unless enabled) |
๐ Learning Check (Optional Exercise)
Change
patrol
to log random locations or events.Try logging the current time or a counter.
Add a second logger line thatโs only
debug
. See if it prints.
๐ง Quick Recap
We built a guard_bot
package and created a bot that logs information at different levels using ROS2โs built-in logger.
Now letโs level up GuardBot's diary with:
Logging values and variables
Setting log levels
Simulating a full town day log
Making logs easier to read
๐ Logging Variables and Events
Letโs say GuardBot sees a new robot every 3 seconds. We want to log which one.
Update guard_
watch.py
:
import random
class GuardBot(Node):
def __init__(self):
super().__init__('guard_bot')
self.get_logger().info('GuardBot is now patrolling ๐ก๏ธ')
self.robot_names = ['MuffinBot', 'DoorBot', 'WeatherBot', 'UmbrellaBot']
self.create_timer(3.0, self.observe)
def observe(self):
seen = random.choice(self.robot_names)
battery_level = random.randint(10, 100)
self.get_logger().info(f'Saw {seen} on patrol.')
self.get_logger().info(f'Battery at {battery_level}%')
if battery_level < 20:
self.get_logger().warn('Battery running low!')
๐ฆ Sample Output:
[INFO] [guard_bot]: Saw MuffinBot on patrol.
[INFO] [guard_bot]: Battery at 18%
[WARN] [guard_bot]: Battery running low!
๐๏ธ Controlling the Log Level
Sometimes we want to filter logs. For example, hide debug
logs unless weโre troubleshooting.
You can set environment variables before running:
# Enable buffered logging output for better performance and smoother logs
export RCUTILS_LOGGING_BUFFERED_STREAM=1
# Set the minimum log severity level to INFO
# This means logs with severity INFO, WARN, ERROR, and FATAL will be shown
# DEBUG logs will be hidden unless this is set to DEBUG
export RCUTILS_LOGGING_SEVERITY_THRESHOLD=INFO # Options: DEBUG, INFO, WARN, ERROR, FATAL
# Run the 'watch' executable from the 'guard_bot' package
# This starts the GuardBot node and begins its logging patrol activity
ros2 run guard_bot watch
This will only show logs at or above INFO.
You can also configure this per node using launch files or code (covered in advanced topics later).
๐ Log Level Summary
Log Level | Use When... |
DEBUG | For developers, internal checks |
INFO | Normal updates and progress |
WARN | Something looks off, but still running |
ERROR | Something broke, needs fixing |
FATAL | Node canโt continue, will shut down |
๐งช Mini Project: A Day in Robot Town
Letโs log GuardBotโs entire day, hour-by-hour:
class GuardBot(Node):
def __init__(self):
super().__init__('guard_bot')
self.get_logger().info('Starting daily patrol log.')
self.hour = 6 # Start at 6 AM
self.create_timer(1.5, self.patrol_hour)
def patrol_hour(self):
if self.hour >= 22:
self.get_logger().info('Patrol ended. Logging off.')
rclpy.shutdown()
return
self.get_logger().info(f"[{self.hour}:00] Patrolling Sector {random.choice(['A', 'B', 'C'])}")
if random.random() < 0.2:
self.get_logger().warn('Saw something suspicious... Logging for review.')
if self.hour == 12:
self.get_logger().info('Lunch break.')
if self.hour == 18:
self.get_logger().info('Evening patrol begins.')
self.hour += 1
๐งพ Output might look like:
[INFO] [guard_bot]: [6:00] Patrolling Sector B
[INFO] [guard_bot]: [7:00] Patrolling Sector C
[WARN] [guard_bot]: Saw something suspicious... Logging for review.
[INFO] [guard_bot]: [12:00] Lunch break.
...
๐ Real-World Relevance
In real robots:
Logs help debug problems during missions
Engineers check logs to diagnose issues
Logs can be sent to external systems or files for analysis
We'll explore log files and external tools later in the advanced series.
๐ Final Folder Structure
Your workspace should look like this:
robot_town_ws/
โโโ src/
โโโ mayor_bot/
โโโ door_bot/
โโโ chatter_bot/
โโโ weather_bot/
โโโ umbrella_bot/
โโโ mood_bot/
โโโ guard_bot/
โโโ guard_bot/
โ โโโ guard_watch.py
โโโ package.xml
โโโ setup.py
๐ง Try It Yourself!
๐ Logging Exercise Ideas:
Add a log message when GuardBot sees a specific bot (e.g.
MuffinBot
).Track how long the bot has been patrolling.
Log a made-up error if a suspicious activity occurs multiple times.
๐ฎ Whatโs Next?
In the next article, weโll understand how workspaces actually work behind the scenes:
๐ Home Directory Magic (Understanding Workspaces)
Just like each bot has a home (package), Robot Town itself lives inside a structured workspace. But what makes that workspace tick?
Subscribe to my newsletter
Read articles from gayatri kumar directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by