# ROSMASTER R2 TG30 Race Course README
This README matches the current state of this workspace as of 2026-04-20.
It is written for a real ROSMASTER R2 running ROS Melodic.
This workspace is set up to:
- Bring up the Yahboom R2 base, odometry, joystick, and robot TF
- Start a forward-tilted TG30 LiDAR
- Build a map with Cartographer
- Save waypoints for a path
- Localize on a saved map with AMCL
- Drive the path using Pure Pursuit plus Follow The Gap (FTG)
Main custom package:
r2_tg30_race
Main Yahboom packages used with it:
yahboomcar_bringupyahboomcar_descriptionyahboomcar_navyahboomcar_ctrl
Use this as the real-car bringup launch:
roslaunch yahboomcar_nav laser_bringup.launchThat launch starts:
- base driver
- odometry
- joystick
- LiDAR driver
robot_descriptionrobot_state_publisher
Do not start two LiDAR drivers at the same time.
The LiDAR mount transform is now owned by the URDF, not by a static TF node in r2_tg30_race.
Current TF path:
yahboomcar_R2.urdf.xacro -> robot_description -> robot_state_publisher -> /tf
Relevant file:
src/yahboomcar_description/urdf/yahboomcar_R2.urdf.xacro
Current LiDAR assumptions:
- frame:
laser_link - about
5.2 inforward of the rear axle center - about
6.0 inabove the rear axle center - pitched forward about
5 degrees
If yahboomcar_nav laser_bringup.launch is not running, you may be missing the base and LiDAR TF tree.
This workspace is for ROS Melodic.
The custom r2_tg30_race scripts were cleaned up for Python 2.7 / Melodic style.
Many older Yahboom demo scripts were also switched from python3 shebangs to python2, but some third-party libraries in vision packages may still be difficult to run on Python 2. The main race stack is the part that was cleaned up intentionally.
Example workspace:
~/yahboomcar_wsBuild:
cd ~/yahboomcar_ws
catkin_makeMake all Python scripts under src executable:
find ~/yahboomcar_ws/src -type f -name "*.py" -exec chmod +x {} \;Source every terminal:
source ~/yahboomcar_ws/devel/setup.bashTo source the workspace automatically in new terminals, add this to ~/.bashrc:
echo "source ~/yahboomcar_ws/devel/setup.bash" >> ~/.bashrc
source ~/.bashrcThis workspace now includes a Linux-side smoke-test script at the workspace root:
test_stack.sh
Use it on the real ROS Melodic machine after you build the workspace:
cd ~/yahboomcar_ws
chmod +x test_stack.sh
./test_stack.shIf you already saved a map and want the AMCL smoke test too:
./test_stack.sh --map ~/yahboomcar_ws/src/r2_tg30_race/maps/driveway_course.yamlWhat it checks:
catkin_make- xacro expansion of the R2 URDF
- launch-file parse checks for the main TG30 launches
- live no-hardware smoke launches for Cartographer, racing stack, and AMCL when a map is available
- expected nodes and key private params in
r2_tg30_race
It writes logs under:
test_logs/
You can use Codex CLI to read this workspace, edit files, and check code from the terminal.
Simple idea:
- open a terminal in the workspace
- start Codex CLI
- tell it what you want in plain English
- let it inspect the code before editing
Start in the workspace root:
cd ~/yahboomcar_wsStart Codex CLI:
codexGood first prompts:
Inspect this ROS workspace. Do not edit anything yet. Tell me what packages control LiDAR, mapping, localization, joystick, motor control, URDF, and navigation.Check r2_tg30_race for obvious launch, TF, or topic problems. Do not edit yet.Review README_4_20_26.md and clean up stale instructions.
If you want Codex to edit code, say exactly what you want changed:
Update r2_tg30_race to use Cartographer instead of gmapping.Add a mode light in the upper-right corner of the screen: red for manual, green for Pure Pursuit, blue for FTG.Tune follow_the_gap.yaml and steering_modifier.yaml so the car stays on the sidewalk and treats grass edges like barriers.
If you want Codex to check code without changing anything, say that clearly:
Inspect only. Do not edit anything yet.Review this launch file and tell me what might break.Check whether this package still depends on Noetic features.
If you want Codex to run checks on the Linux ROS machine, use prompts like:
Run the smoke test script and summarize the results.Check whether /scan, /odom, /joy, and base_link to laser_link are alive after bringup.Review the Cartographer launch and tell me if it stays up.
Helpful rule:
- if you only want an explanation, say
do not edit - if you want changes made, say
go ahead and edit - if you want safety first, say
show me the files and risks before changing anything
Codex works best when the request is short and specific.
Good:
Explain what racing_stack.launch does at an 8th grade level.Update the README to match the current TG30 setup.Find where the LiDAR TF is coming from.
Less good:
fix everything
When you are using the Linux robot computer, Codex can also help you run:
catkin_makeroslaunchrostopicrosnodetest_stack.sh
That makes it useful for both editing code and checking whether the ROS stack is actually working.
After base bringup and TG30 bringup, these should exist:
/scan/joy/odom/tf
Quick checks:
rostopic echo -n 1 /scan
rostopic echo -n 1 /joy
rostopic echo -n 1 /odomIf one is missing, fix that first before mapping or racing.
r2_tg30_race now maps with Cartographer, not gmapping.
Primary launch:
roslaunch r2_tg30_race mapping_cartographer.launch start_driver:=false scan_topic:=/scan obstacle_scan_topic:=/scan_obstaclesCompatibility alias:
roslaunch r2_tg30_race mapping_gmapping.launch start_driver:=false scan_topic:=/scan obstacle_scan_topic:=/scan_obstaclesThat old launch name now points to Cartographer internally.
Recommended mapping startup:
source ~/yahboomcar_ws/devel/setup.bash
roslaunch yahboomcar_nav laser_bringup.launchsource ~/yahboomcar_ws/devel/setup.bash
roslaunch r2_tg30_race mapping_cartographer.launch start_driver:=false scan_topic:=/scan obstacle_scan_topic:=/scan_obstaclesOptional RViz:
source ~/yahboomcar_ws/devel/setup.bash
roslaunch r2_tg30_race view_mapping.launchThe TG30 RViz layouts were tuned for a top-down follow view:
- bright green
scan_obstaclespoints to make grass edges and sidewalk boundaries easier to see - the car model centered in view
- the race line shown in yellow when it is available
- AMCL red arrows in localization and racing views
What mapping_cartographer.launch does:
- starts TG30 only if
start_driver:=true - runs
scan_cleanup.launch - creates
/scan_obstacles - feeds
/scan_obstaclesinto Cartographer
Save the map:
mkdir -p ~/yahboomcar_ws/src/r2_tg30_race/maps
rosrun map_server map_saver -f ~/yahboomcar_ws/src/r2_tg30_race/maps/driveway_courseThat creates:
driveway_course.pgmdriveway_course.yaml
Important files:
src/r2_tg30_race/launch/mapping_cartographer.launchsrc/yahboomcar_nav/scripts/yahboomcar.lua
Current package dependency:
cartographer_ros
Old dependency removed from r2_tg30_race:
slam_gmapping
Record waypoints while driving slowly:
source ~/yahboomcar_ws/devel/setup.bash
rosrun r2_tg30_race waypoint_extractor.py _yaml_file:=/home/$USER/yahboomcar_ws/src/r2_tg30_race/waypoints/waypoints.yaml _path_topic:=/waypoint_path _sample_distance:=0.40What it does:
- listens to
/odom - saves a waypoint about every
0.40 m - writes the YAML file while you drive
Manual mark topic:
/waypoint_mark
Example:
rostopic pub /waypoint_mark std_msgs/Empty -1For a loop, you usually need to add the first waypoint again at the end of waypoints.yaml.
Why:
pure_pursuit_twist.pytreats the last waypoint like the finish line- when it gets close enough, it stops
Rule of thumb:
- one-way route: do not repeat the first point
- loop route: repeat the first point at the end
The racing stack starts this automatically, but you can test it alone:
source ~/yahboomcar_ws/devel/setup.bash
rosrun r2_tg30_race waypoint_map_builder.py _yaml_file:=/home/$USER/yahboomcar_ws/src/r2_tg30_race/waypoints/waypoints.yaml _path_topic:=/race_pathCheck:
rostopic echo -n 1 /race_pathUse this after you already have a saved map:
Stop mapping_cartographer.launch before starting AMCL.
Do not run Cartographer and AMCL at the same time on the real car. Cartographer is for building the map. AMCL is for localizing on a map you already saved.
source ~/yahboomcar_ws/devel/setup.bash
roslaunch yahboomcar_nav laser_bringup.launchsource ~/yahboomcar_ws/devel/setup.bash
roslaunch r2_tg30_race localization_amcl.launch start_driver:=false map_file:=/home/$USER/yahboomcar_ws/src/r2_tg30_race/maps/driveway_course.yaml scan_topic:=/scan obstacle_scan_topic:=/scan_obstaclesOptional RViz:
source ~/yahboomcar_ws/devel/setup.bash
roslaunch r2_tg30_race view_localization.launchUse RViz 2D Pose Estimate if needed.
racing_stack.launch is the main path-driving mode.
Recommended startup:
source ~/yahboomcar_ws/devel/setup.bash
roslaunch yahboomcar_nav laser_bringup.launchsource ~/yahboomcar_ws/devel/setup.bash
roslaunch r2_tg30_race racing_stack.launch start_driver:=false scan_topic:=/scan obstacle_scan_topic:=/scan_obstacles waypoint_yaml:=/home/$USER/yahboomcar_ws/src/r2_tg30_race/waypoints/waypoints.yaml use_ackermann_bridge:=trueOptional RViz:
source ~/yahboomcar_ws/devel/setup.bash
roslaunch r2_tg30_race view_racing.launchview_racing.launch now also starts a small 2 in x 2 in mode light in the upper-right corner of the screen.
Color meaning:
- red: manual control
- green: Pure Pursuit is the main active mode
- blue: FTG is taking over because nearby obstacles make the safety blend favor FTG
If you want RViz without the mode light:
roslaunch r2_tg30_race view_racing.launch show_mode_indicator:=falseWhat racing_stack.launch includes:
waypoint_map_builder.pypublishes/race_pathpure_pursuit_twist.pypublishes/cmd_vel_auto_rawjoy_deadman.pypublishes/auto_enablecmdvel_gate.pygates/cmd_vel_auto_rawinto/cmd_vel_autofollow_the_gap.pypublishes/cmd_vel_ftg_rawsteering_modifier.pyblends Pure Pursuit and FTG into/cmd_vel_safetytwist_muxpublishes final/cmd_veltwist_to_ackermann.pycan publish/ackermann_cmd
Current deadman setup:
- topic:
/joy - output:
/auto_enable - button index:
5
Check it:
rostopic echo /auto_enableExpected behavior:
- hold button:
data: true - release button:
data: false
Check these before real motion:
rostopic echo -n 1 /race_path
rostopic echo /auto_enable
rostopic echo /cmd_vel_auto_raw
rostopic echo /cmd_vel_auto
rostopic echo /cmd_vel_ftg_raw
rostopic echo /cmd_vel_safety
rostopic echo /cmd_vel
rostopic echo /ackermann_cmdsrc/r2_tg30_race/config/pure_pursuit.yaml
Current key values:
lookahead_distance: 0.65base_speed: 0.45max_speed: 0.70goal_tolerance: 0.30
src/r2_tg30_race/config/follow_the_gap.yaml
Current sidewalk-oriented values:
danger_distance: 1.10stop_distance: 0.45front_angle_deg: 110.0bubble_radius_idx: 14gap_threshold: 0.70max_speed: 0.40min_speed: 0.10
src/r2_tg30_race/config/steering_modifier.yaml
Current sidewalk-oriented values:
danger_distance: 1.10stop_distance: 0.45blend_distance: 1.60clear_path_speed_scale: 0.90danger_speed_scale: 0.25max_linear_x: 0.45front_fov_deg: 110.0
The mode light uses the same steering-modifier distance thresholds to decide when to show green versus blue.
src/r2_tg30_race/config/scan_filters.yamlsrc/r2_tg30_race/config/pointcloud_to_laserscan.yaml
These are the main files that decide whether curb and grass-edge returns are kept or filtered out.
src/r2_tg30_race/config/ackermann_bridge.yaml
Important values:
wheelbase: 0.26max_steering_angle: 0.45steering_sign: 1.0
If steering is backwards, change steering_sign to -1.0.
roscorerosbag play --clock ~/yahboomcar_ws/src/r2_tg30_race/bags/driveway_run.bagIf needed:
rosparam set use_sim_time trueThen launch mapping, localization, or racing tools.
roslaunch r2_tg30_race octomap.launchThis uses /scan_cloud.
- Stop racing, mapping, or localization launches
- Stop RViz
- Stop rosbag recording
- Stop
yahboomcar_nav laser_bringup.launch - Stop
roscoreif you started it
Fix:
- check LiDAR cable and power
- check TG30 port and baudrate
- check that you started
yahboomcar_nav laser_bringup.launch
Fix:
- check joystick connection
- check
yahboomcar_nav laser_bringup.launch
Fix:
- the base driver is not publishing odometry yet
- Pure Pursuit and AMCL both need
/odom
Fix:
- check button index
5 - watch
/joyand see which button changes
Fix:
- make sure you launched
view_racing.launch - if needed, install
python-tkon the Melodic machine - if you do not want the light, run
show_mode_indicator:=false
Fix:
- for a loop track, add the first waypoint to the end of the file
Fix:
- change
steering_signinackermann_bridge.yaml
Fix:
- adjust physical tilt a little
- adjust
scan_filters.yaml - adjust
pointcloud_to_laserscan.yaml - drive slower while mapping
Fix:
- make sure
yahboomcar_nav laser_bringup.launchis running - make sure
robot_state_publisheris alive
- Bring up the car:
roslaunch yahboomcar_nav laser_bringup.launch- Make a map:
roslaunch r2_tg30_race mapping_cartographer.launch start_driver:=false scan_topic:=/scan obstacle_scan_topic:=/scan_obstacles- Save the map:
rosrun map_server map_saver -f ~/yahboomcar_ws/src/r2_tg30_race/maps/driveway_course-
Stop Cartographer before switching to AMCL localization.
-
Record waypoints:
rosrun r2_tg30_race waypoint_extractor.py _yaml_file:=/home/$USER/yahboomcar_ws/src/r2_tg30_race/waypoints/waypoints.yaml-
For a loop, add the first waypoint to the end of the file.
-
Start AMCL localization if you want to drive on the saved map.
-
Run the race stack:
roslaunch r2_tg30_race racing_stack.launch start_driver:=false scan_topic:=/scan obstacle_scan_topic:=/scan_obstacles waypoint_yaml:=/home/$USER/yahboomcar_ws/src/r2_tg30_race/waypoints/waypoints.yaml use_ackermann_bridge:=true- Hold the deadman button and test slowly while watching
/auto_enable,/cmd_vel, and/ackermann_cmd.
If view_racing.launch is open, also watch the upper-right mode light:
- red for manual
- green for PP
- blue for FTG
Current real-car recommendation:
- Use
yahboomcar_nav laser_bringup.launchfor base, odometry, joystick, and LiDAR bringup - Use
mapping_cartographer.launchfor mapping - Use
localization_amcl.launchfor saved-map localization - Use
racing_stack.launchfor path driving