Skip to content

kc-ml2/text_nav_sim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

text_nav_sim

Gazebo simulation for text-based indoor robot navigation. TurtleBot3 Waffle (RGB-D camera) + text sign/ad banner models in a house environment.

Package Structure

text_nav_sim/
├── launch/
│   ├── sim_mapping.launch.py        # Phase 1: SLAM mapping + OCR
│   ├── sim_navigation.launch.py     # Phase 2A: Nav2 + slam_toolbox localization
│   └── sim_navigation_amcl.launch.py # Phase 2B: Nav2 + map_server + AMCL
├── config/
│   ├── slam_toolbox_mapping.yaml    # SLAM async mapping mode
│   ├── slam_toolbox_localization.yaml # SLAM localization mode
│   └── nav2_sim_params.yaml         # Nav2 stack parameters
├── worlds/
│   └── turtlebot3_house_signs.world # 15m x 10.5m house with signs
├── models/
│   ├── turtlebot3_waffle_rgbd/      # Robot with RGB-D camera
│   ├── turtlebot3_house/            # Static house structure
│   ├── text_sign_*/                 # 10 room name signs
│   └── ad_banner_*/                 # 4 advertisement banners
├── scripts/
│   ├── generate_sign_textures.py    # Texture generator (PIL)
│   ├── sign_tour_node.py            # Automated tour visiting all signs
│   └── depth_f32_to_u16_node.py     # Depth format converter
├── urdf/
│   └── turtlebot3_waffle_rgbd.urdf
└── rviz/
    ├── sim_mapping.rviz
    └── sim_navigation.rviz

Dependencies

  • ROS2 Humble
  • gazebo_ros, turtlebot3_gazebo
  • slam_toolbox, nav2_bringup
  • textmap, text_nav_bridge, navocr
  • Python: Pillow (texture generation)

Build

source /opt/ros/humble/setup.bash
colcon build --packages-select text_nav_sim
source install/setup.bash

Usage

Phase 1: Mapping

SLAM mapping + NavOCR text detection + textmap landmark recording. Drive the robot with teleop or the automated tour to explore the environment.

# Terminal 1: Launch mapping
ros2 launch text_nav_sim sim_mapping.launch.py

# Terminal 2: Manual teleop
ros2 run turtlebot3_teleop teleop_keyboard

# Terminal 2 (alternative): Automated sign tour
ros2 run text_nav_sim sign_tour_node.py --ros-args -p use_sim_time:=true

When the tour completes, save the map before pressing Ctrl+C:

# Terminal 3: Create save directory
mkdir -p ~/map/<DIR>

# Save occupancy grid (.pgm + .yaml)
ros2 run nav2_map_server map_saver_cli -f ~/map/<DIR>/map \
  --ros-args -p map_subscribe_transient_local:=true

# Save slam_toolbox serialized map (.posegraph + .data, for Phase 2A)
ros2 service call /slam_toolbox/serialize_map \
  slam_toolbox/srv/SerializePoseGraph \
  "{filename: /home/sehyeon/map/<DIR>/map}"

The exact commands with the timestamped directory are printed at launch. Press Ctrl+C after saving. Landmarks are auto-saved on shutdown.

~/map/2026-04-08_14-30-25/
  map.pgm           # Occupancy grid image
  map.yaml          # map_server metadata
  map.posegraph     # slam_toolbox serialized map
  map.data          # slam_toolbox serialized data
  landmarks.yaml    # Text landmark positions

Launch arguments:

Argument Default Description
use_sim_time true Use simulation clock
landmark_save_path ~/map/<timestamp>/landmarks.yaml Path to save detected landmarks

Nodes launched in Phase 1:

  • Gazebo (house + signs world)
  • robot_state_publisher
  • slam_toolbox (async mapping)
  • depth_converter (32FC1 -> 16UC1)
  • navocr_node (text detection + OCR)
  • textmap_node (landmark mapping)
  • RViz

Phase 2: Navigation

Autonomous text-based navigation using the map and landmarks saved in Phase 1. Two launch files are available depending on map format.

Option A: slam_toolbox localization (requires .posegraph)

ros2 launch text_nav_sim sim_navigation.launch.py \
  landmark_file:=~/map/DIR/landmarks.yaml \
  map_file:=~/map/DIR/map
Argument Default Description
use_sim_time true Use simulation clock
landmark_file (required) Path to landmarks.yaml from Phase 1
map_file "" Path to slam_toolbox serialized map (without extension)

Option B: map_server + AMCL (requires .pgm/.yaml only)

ros2 launch text_nav_sim sim_navigation_amcl.launch.py \
  landmark_file:=~/map/DIR/landmarks.yaml \
  map_yaml_file:=~/map/DIR/map.yaml
Argument Default Description
use_sim_time true Use simulation clock
landmark_file (required) Path to landmarks.yaml from Phase 1
map_yaml_file (required) Path to map.yaml from Phase 1

Nodes launched in Phase 2:

  • Gazebo (same world)
  • robot_state_publisher
  • slam_toolbox (Option A) or map_server + AMCL (Option B)
  • Nav2 navigation stack (controller, planner, behavior, bt_navigator, smoother, velocity_smoother, waypoint_follower)
  • text_nav_bridge_node (landmark -> Nav2 goal)
  • RViz

Important: Always kill previous Gazebo processes before relaunching:

killall -9 gzserver gzclient

Testing Navigation

Send a text command to navigate to a landmark:

ros2 topic pub --once /text_nav/command std_msgs/msg/String "data: 'Kitchen'"

text_nav_bridge matches the command against landmarks from Phase 1 and sends a Nav2 goal.

Automated Sign Tour

sign_tour_node.py drives the robot through all 14 signs and banners automatically. The route avoids walls and cabinets, and navigates through doorways. All signs are placed on the shorter wall of their room to maximize viewing distance.

ros2 run text_nav_sim sign_tour_node.py --ros-args -p use_sim_time:=true

Tour order: Exit(+Open) -> Office -> Bathroom -> Storage(+Tidy) -> Living Room -> Closet -> Kitchen(+Chef) -> Laundry -> Bedroom -> Garage(+Tools)

Sign+Ad pairs are viewed together from 2.5m+ so both fit in the camera FOV. The table, table_marble, cafe_table, and cafe_table_0 have been removed from the house model to prevent robot collision. Floor obstacle boxes (0.5x0.5x0.4m) are placed in large open rooms to provide LIDAR features for SLAM loop closure. The Dining/Living Room area uses a perimeter loop for maximum occupancy grid coverage.

Parameters:

Parameter Default Description
max_linear_vel 0.26 Maximum forward speed (m/s)
max_angular_vel 1.0 Maximum rotation speed (rad/s)
position_tolerance 0.25 Waypoint arrival threshold (m)
heading_tolerance 0.1 Heading alignment threshold (rad)
linear_kp 0.5 Proportional gain for linear velocity
angular_kp 2.0 Proportional gain for angular velocity
pause_scale 1.0 Multiplier for pause duration at each sign

Models

Text Signs (10)

Room name signs. Black text on white background, mounted at Z=1.8m.

Key Display Text Size (m)
exit Exit 0.6 x 0.25
kitchen Kitchen 0.8 x 0.25
bathroom Bathroom 0.8 x 0.25
bedroom Bedroom 0.8 x 0.25
office Office 0.8 x 0.25
garage Garage 0.8 x 0.25
closet Closet 0.8 x 0.25
living_room Living Room 1.0 x 0.25
laundry Laundry 0.8 x 0.25
storage Storage Room 1.0 x 0.25

Ad Banners (4)

Vertical advertisement banners (0.3 x 0.6m), mounted at Z=1.9m. Low-contrast text (blended toward background color) to suppress OCR detection. Subtitles on top, title on bottom.

Key Title Subtitles Background
chef CHEF FRESH MEALS, DAILY SPECIALS, HOME COOKING Red
tidy TIDY ORGANIZE, SMART STORAGE, CLEAN SPACE Green
tools TOOLS POWER DRILL, HAND SAW, WRENCH SET Blue
open OPEN 24 HOURS, EVERYDAY, WELCOME Brown

Robot: turtlebot3_waffle_rgbd

TurtleBot3 Waffle with RGB-D camera.

Sensor Specs
RGB Camera 640x480, 60 FOV, 15Hz
Depth 0.05-8.0m range
LIDAR 360 samples, 0.12-3.5m, 5Hz
IMU 200Hz 6-axis

Camera pose: (0.069, -0.047, 1.490) from base_footprint, pitch 12 deg upward.

Texture Generation

scripts/generate_sign_textures.py auto-generates all sign and banner textures.

cd src/text_nav_sim
python3 scripts/generate_sign_textures.py

Run this script after modifying texture settings. Must be run before colcon build for changes to be installed.

Ad Banner Texture Parameters

Parameter Value Description
BANNER_TITLE_FONT_SIZE 30 Title font size (px)
BANNER_SUBTITLE_FONT_SIZE 22 Subtitle font size (px)
BANNER_SEPARATOR_Y_RATIO 0.62 Separator position (ratio from top)
BANNER_TEXT_BLEND_RATIO 0.35 Text-background color blend (0=bg color, 1=white)

Depth Format Conversion

Gazebo RGB-D camera outputs 32FC1 (float32, meters). textmap expects 16UC1 (uint16, millimeters). depth_f32_to_u16_node.py performs the conversion.

  • Input: /camera/rgbd_camera/depth/image_raw (32FC1)
  • Output: /camera/depth/image_rect_raw (16UC1)

Troubleshooting

spawn_entity.py hangs / odom frame does not exist

Previous gzserver is still running. Kill it before relaunching:

killall -9 gzserver gzclient; pkill -9 -f ros2

conda Python conflict

If (base) conda environment is active, spawn_entity.py fails due to Python version mismatch (needs 3.10, not 3.13). Deactivate conda first:

conda deactivate

About

Gazebo simulation for text-based indoor robot navigation (TurtleBot3 + text signs)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors