import os from launch import LaunchDescription from launch.actions import IncludeLaunchDescription, ExecuteProcess from launch.launch_description_sources import PythonLaunchDescriptionSource from launch.substitutions import Command, LaunchConfiguration, PathJoinSubstitution from launch_ros.actions import Node from ament_index_python.packages import get_package_share_directory def generate_launch_description(): pkg_name = 'agv_pro_description' # Paths pkg_dir = get_package_share_directory(pkg_name) xacro_file = os.path.join(pkg_dir, 'urdf', 'agv_pro.xacro') world_file = os.path.join(pkg_dir, 'worlds', 'empty.world') # 创建一个空 world 即可 rviz_config = os.path.join(pkg_dir, 'rviz', 'agvpro_display.rviz') robot_description_content = Command(['xacro ', xacro_file]) robot_description = {'robot_description': robot_description_content} return LaunchDescription([ # Start Gazebo with empty world IncludeLaunchDescription( PythonLaunchDescriptionSource( [os.path.join(get_package_share_directory('gazebo_ros'), 'launch', 'gazebo.launch.py')] ), launch_arguments={'world': world_file}.items() ), # Spawn robot into Gazebo Node( package='gazebo_ros', executable='spawn_entity.py', arguments=['-topic', 'robot_description', '-entity', 'agv_pro'], output='screen' ), # Robot state publisher Node( package='robot_state_publisher', executable='robot_state_publisher', name='robot_state_publisher', output='screen', parameters=[robot_description] ), # Optionally publish joint states if not using controllers Node( package='joint_state_publisher', executable='joint_state_publisher', name='joint_state_publisher', output='screen', ), Node( package='controller_manager', executable='spawner', arguments=['joint_state_broadcaster'], output='screen', ), # RViz (optional, visualize TF & model) Node( package='rviz2', executable='rviz2', name='rviz2', output='screen', arguments=['-d', rviz_config], ), ])