๐Ÿ—ž๏ธThe Town Newspaper

gayatri kumargayatri kumar
6 min read

๐Ÿ™๏ธ 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 LevelMeaning
infoNormal updates
warnSomething might go wrong
errorSomething is going wrong
debugDetailed output for developers (hidden unless enabled)

๐Ÿ“š Learning Check (Optional Exercise)

  1. Change patrol to log random locations or events.

  2. Try logging the current time or a counter.

  3. 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 LevelUse When...
DEBUGFor developers, internal checks
INFONormal updates and progress
WARNSomething looks off, but still running
ERRORSomething broke, needs fixing
FATALNode 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?

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