RTRoboticsTools.in

ROS2 Launch File Generator

Pick the nodes you need and generate a bringup launch file and a controller launch file as a starting point — including the Gazebo resource-path exports that avoid the classic "mesh not found" / nothing-loads errors, and correctly-sequenced controller spawners.

Bringup launch file

Custom nodes

A blank starting point for any node this tool doesn't know about — fill in the package/executable, rename it, add params, and it'll drop straight into the generated file.

Controller launch file

Controllers to spawn

joint_state_broadcaster is always included first. Add the controller names exactly as they appear in your controllers.yaml — each one gets its own spawner, chained to start only after the previous one finishes (spawning them all at once can race against controller_manager and fail).

Before you run these:

  • Make sure your CMakeLists.txt actually installs the urdf/, rviz/, and config/ directories (install(DIRECTORY urdf rviz config DESTINATION share/${PROJECT_NAME})) — a very common reason these paths "don't exist" is that they were never copied into the install space.
  • Don't run joint_state_publisher and a real/simulated joint_state_broadcaster at the same time — they'll both try to publish /joint_states.
  • These two files cover bringup + controllers only — planner/controller-server, nav2, and MoveIt config aren't generated here.
#!/usr/bin/env python3
"""Bringup launch file for my_robot_description, generated by RoboticsTools.in's ROS2 Launch File Generator."""
 
import os
 
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument, AppendEnvironmentVariable, IncludeLaunchDescription
from launch.conditions import IfCondition
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import Command, LaunchConfiguration, PathJoinSubstitution
from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageShare
 
def generate_launch_description():
pkg_share = FindPackageShare('my_robot_description')
xacro_path = PathJoinSubstitution([pkg_share, 'urdf/robot.xacro'])
 
# Gazebo needs to find this package's meshes/models via package:// URIs, or you'll get
# "mesh not found" / nothing-loads errors. This adds the share directory's parent to
# Gazebo's resource search path without clobbering anything you've already sourced.
set_gz_resource_path = AppendEnvironmentVariable(
'GZ_SIM_RESOURCE_PATH',
PathJoinSubstitution([pkg_share, os.pardir]),
)
 
robot_description = {'robot_description': Command(['xacro ', xacro_path])}
 
rviz_config_path = PathJoinSubstitution([pkg_share, 'rviz/config.rviz'])
 
robot_state_publisher_node = Node(
package='robot_state_publisher',
executable='robot_state_publisher',
output='screen',
parameters=[robot_description, {'use_sim_time': LaunchConfiguration('use_sim_time')}],
)
 
gazebo = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
PathJoinSubstitution([FindPackageShare('ros_gz_sim'), 'launch', 'gz_sim.launch.py'])
),
launch_arguments={'gz_args': ['-r ', LaunchConfiguration('world')]}.items(),
condition=IfCondition(LaunchConfiguration('use_gazebo')),
)
 
spawn_robot_node = Node(
package='ros_gz_sim',
executable='create',
output='screen',
parameters=[{
'name': 'my_robot',
'topic': '/robot_description',
'x': LaunchConfiguration('x'),
'y': LaunchConfiguration('y'),
'z': LaunchConfiguration('z'),
'Y': LaunchConfiguration('yaw'),
}],
condition=IfCondition(LaunchConfiguration('use_gazebo')),
)
 
rviz_node = Node(
package='rviz2',
executable='rviz2',
name='rviz2',
output='screen',
arguments=['-d', rviz_config_path],
condition=IfCondition(LaunchConfiguration('use_rviz')),
)
 
return LaunchDescription([
DeclareLaunchArgument('use_sim_time', default_value='true', description='Use simulation (Gazebo) clock'),
DeclareLaunchArgument('use_gazebo', default_value='true', description='Launch Gazebo and spawn the robot'),
DeclareLaunchArgument('world', default_value='empty.sdf', description='Gazebo world file (bundled with ros_gz_sim, or an absolute path)'),
DeclareLaunchArgument('x', default_value='0', description='Spawn X position (m)'),
DeclareLaunchArgument('y', default_value='0', description='Spawn Y position (m)'),
DeclareLaunchArgument('z', default_value='0.1', description='Spawn Z position (m)'),
DeclareLaunchArgument('yaw', default_value='0', description='Spawn yaw (rad)'),
DeclareLaunchArgument('use_rviz', default_value='true', description='Launch RViz'),
set_gz_resource_path,
robot_state_publisher_node,
gazebo,
spawn_robot_node,
rviz_node,
])