From 93fb5f87ba7283a6a494f6bea310f5b40e1508f9 Mon Sep 17 00:00:00 2001 From: chyoo Date: Thu, 6 Aug 2026 14:07:45 +0900 Subject: [PATCH] feat: let Gazebo spawn MKMini --- src/nav2_turtlebot_simulator/CMakeLists.txt | 2 +- .../launch/simulator.launch.py | 69 ++++++++++++------- .../models/mkmini_gazebo/model.config | 7 ++ .../models/mkmini_gazebo/model.sdf | 44 ++++++++++++ 4 files changed, 98 insertions(+), 24 deletions(-) create mode 100644 src/nav2_turtlebot_simulator/models/mkmini_gazebo/model.config create mode 100644 src/nav2_turtlebot_simulator/models/mkmini_gazebo/model.sdf diff --git a/src/nav2_turtlebot_simulator/CMakeLists.txt b/src/nav2_turtlebot_simulator/CMakeLists.txt index 4c70be9..a11cfc3 100644 --- a/src/nav2_turtlebot_simulator/CMakeLists.txt +++ b/src/nav2_turtlebot_simulator/CMakeLists.txt @@ -3,6 +3,6 @@ project(nav2_turtlebot_simulator) find_package(ament_cmake REQUIRED) -install(DIRECTORY launch worlds DESTINATION share/${PROJECT_NAME}) +install(DIRECTORY launch worlds models DESTINATION share/${PROJECT_NAME}) ament_package() diff --git a/src/nav2_turtlebot_simulator/launch/simulator.launch.py b/src/nav2_turtlebot_simulator/launch/simulator.launch.py index 9c2e5d8..2fcb20d 100644 --- a/src/nav2_turtlebot_simulator/launch/simulator.launch.py +++ b/src/nav2_turtlebot_simulator/launch/simulator.launch.py @@ -5,7 +5,7 @@ import xml.etree.ElementTree as ET from ament_index_python.packages import get_package_share_directory from launch import LaunchDescription -from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription, OpaqueFunction +from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription, OpaqueFunction, SetEnvironmentVariable from launch.conditions import IfCondition from launch.launch_description_sources import PythonLaunchDescriptionSource from launch.substitutions import LaunchConfiguration @@ -233,6 +233,7 @@ def launch_gazebo(context): gazebo_ros_dir = get_package_share_directory('gazebo_ros') world = LaunchConfiguration('world').perform(context) render_mode = LaunchConfiguration('render_mode').perform(context).strip().lower() + platform = LaunchConfiguration('platform').perform(context).strip().lower() if render_mode not in {'flat', 'full'}: raise RuntimeError('render_mode must be either flat or full') @@ -247,7 +248,47 @@ def launch_gazebo(context): 'worlds', world, ) + + if platform in {'turtlebot3', 'turtlebot3_burger', 'burger'}: + entity_name = 'turtlebot3_burger_3d_lidar' + model_path = os.path.join(gazebo_dir, 'models', 'turtlebot3_burger', 'model.sdf') + model_directory = os.path.join(gazebo_dir, 'models') + static_transforms = [ + Node( + package='tf2_ros', + executable='static_transform_publisher', + name='turtlebot3_base_link_tf', + arguments=[ + '--x', '0', '--y', '0', '--z', '0.01', + '--roll', '0', '--pitch', '0', '--yaw', '0', + '--frame-id', 'base_footprint', '--child-frame-id', 'base_link', + ], + ), + Node( + package='tf2_ros', + executable='static_transform_publisher', + name='turtlebot3_laser_tf', + arguments=[ + '--x', '-0.032', '--y', '0', '--z', '0.171', + '--roll', '0', '--pitch', '0', '--yaw', '0', + '--frame-id', 'base_link', '--child-frame-id', 'base_scan', + ], + ), + ] + elif platform in {'mkmini', 'mk-mini'}: + entity_name = 'mkmini_gazebo' + model_directory = os.path.join(simulator_dir, 'models') + model_path = os.path.join(model_directory, 'mkmini_gazebo', 'model.sdf') + static_transforms = [] + else: + raise RuntimeError('platform must be turtlebot3 or mkmini') + + existing_model_path = os.environ.get('GAZEBO_MODEL_PATH', '') return [ + SetEnvironmentVariable( + name='GAZEBO_MODEL_PATH', + value=os.pathsep.join(part for part in (model_directory, existing_model_path) if part), + ), IncludeLaunchDescription( PythonLaunchDescriptionSource(os.path.join(gazebo_ros_dir, 'launch', 'gzserver.launch.py')), launch_arguments={ @@ -259,14 +300,15 @@ def launch_gazebo(context): package='gazebo_ros', executable='spawn_entity.py', arguments=[ - '-entity', 'turtlebot3_burger_3d_lidar', - '-file', os.path.join(gazebo_dir, 'models', 'turtlebot3_burger', 'model.sdf'), + '-entity', entity_name, + '-file', model_path, '-x', LaunchConfiguration('x_pose').perform(context), '-y', LaunchConfiguration('y_pose').perform(context), '-z', '0.01', ], output='screen', ), + *static_transforms, ] @@ -276,29 +318,10 @@ def generate_launch_description(): DeclareLaunchArgument('gui', default_value='false'), DeclareLaunchArgument('world', default_value='turtlebot3_world.world'), DeclareLaunchArgument('render_mode', default_value='flat'), + DeclareLaunchArgument('platform', default_value='turtlebot3'), DeclareLaunchArgument('x_pose', default_value='-2.0'), DeclareLaunchArgument('y_pose', default_value='-0.5'), OpaqueFunction(function=launch_gazebo), - Node( - package='tf2_ros', - executable='static_transform_publisher', - name='turtlebot3_base_link_tf', - arguments=[ - '--x', '0', '--y', '0', '--z', '0.01', - '--roll', '0', '--pitch', '0', '--yaw', '0', - '--frame-id', 'base_footprint', '--child-frame-id', 'base_link', - ], - ), - Node( - package='tf2_ros', - executable='static_transform_publisher', - name='turtlebot3_laser_tf', - arguments=[ - '--x', '-0.032', '--y', '0', '--z', '0.171', - '--roll', '0', '--pitch', '0', '--yaw', '0', - '--frame-id', 'base_link', '--child-frame-id', 'base_scan', - ], - ), IncludeLaunchDescription( PythonLaunchDescriptionSource(os.path.join(gazebo_ros_dir, 'launch', 'gzclient.launch.py')), condition=IfCondition(LaunchConfiguration('gui')), diff --git a/src/nav2_turtlebot_simulator/models/mkmini_gazebo/model.config b/src/nav2_turtlebot_simulator/models/mkmini_gazebo/model.config new file mode 100644 index 0000000..f50fbe0 --- /dev/null +++ b/src/nav2_turtlebot_simulator/models/mkmini_gazebo/model.config @@ -0,0 +1,7 @@ + + + mkmini_gazebo + 1.0 + model.sdf + Lightweight Ackermann MK-mini model for Gazebo learning runs. + diff --git a/src/nav2_turtlebot_simulator/models/mkmini_gazebo/model.sdf b/src/nav2_turtlebot_simulator/models/mkmini_gazebo/model.sdf new file mode 100644 index 0000000..5d59150 --- /dev/null +++ b/src/nav2_turtlebot_simulator/models/mkmini_gazebo/model.sdf @@ -0,0 +1,44 @@ + + + + + 0 0 0.16 0 0 0 + + + 38.02.02.63.2 + 0 0 0.16 0 0 01.05 0.70 0.32 + 0 0 0.16 0 0 01.05 0.70 0.320.12 0.20 0.25 10.12 0.35 0.42 1 + 0.56 0 0.23 0 0 00.06 0.42 0.100.95 0.65 0.08 10.95 0.65 0.08 1 + + + 0.30 0 0 0 0 01.00.010.010.01 + base_linkfront_fork0 0 1-0.50.5 + + 0.30 0 0 0 0 01.20.020.010.020 0 0 1.5708 0 00.140.180 0 0 1.5708 0 00.140.180.04 0.04 0.04 10.04 0.04 0.04 1 + front_forkfront_drive_wheel0 1 0 + + -0.30 0.36 0 0 0 01.00.020.010.020 0 0 1.5708 0 00.140.100 0 0 1.5708 0 00.140.100.04 0.04 0.04 10.04 0.04 0.04 1 + base_linkrear_left_wheel0 1 0 + + -0.30 -0.36 0 0 0 01.00.020.010.020 0 0 1.5708 0 00.140.100 0 0 1.5708 0 00.140.100.04 0.04 0.04 10.04 0.04 0.04 1 + base_linkrear_right_wheel0 1 0 + + 0 0 0.52 0 0 00.20.0010.0010.001 + 0.0750.100.85 0.12 0.10 10.85 0.12 0.10 1 + true10false3601-3.141593.14159161-0.260.260.2018.00.02~/out:=/carla/hero/lidar_filteredsensor_msgs/PointCloud2os_lidar + + base_linkos_lidar + + + cmd_vel:=/cmd_velodom:=/odom_custom + front_steering_jointfront_drive_joint + rear_left_jointrear_right_joint + 0.720.280.28 + 120.01.50.8 + truetruetrue + odombase_link + + +