diff --git a/src/vehicle_pkg/config/platforms/platform_mkmini.yaml b/src/vehicle_pkg/config/platforms/platform_mkmini.yaml
index 5a65343..9e6c0af 100755
--- a/src/vehicle_pkg/config/platforms/platform_mkmini.yaml
+++ b/src/vehicle_pkg/config/platforms/platform_mkmini.yaml
@@ -26,6 +26,12 @@ platform:
sim_sensor_driver: carla_lidar # sim_mode=true
sim_lidar: vanjee # CARLA 스폰 blueprint 정체성 (차량↔라이다 고정 페어링)
+ # Gazebo is an opt-in simulation backend (simulator:=gazebo). Keep the
+ # existing CARLA selections above as the default so existing runs are not
+ # changed.
+ gazebo_vehicle_driver: gazebo_mkmini_passthrough
+ gazebo_sensor_driver: gazebo_mkmini_lidar
+
# cross-workspace 규칙 키 (기존 {robot} 컨벤션 보존 — 다운스트림 무수정)
perception_profile: mkmini # → perception_{...}.yaml, tf_{...}.yaml, control_*_{...}.yaml
scan_topic: /scan
diff --git a/src/vehicle_pkg/config/sensor_drivers/sensor_driver_gazebo_mkmini_lidar.yaml b/src/vehicle_pkg/config/sensor_drivers/sensor_driver_gazebo_mkmini_lidar.yaml
new file mode 100644
index 0000000..6672cdf
--- /dev/null
+++ b/src/vehicle_pkg/config/sensor_drivers/sensor_driver_gazebo_mkmini_lidar.yaml
@@ -0,0 +1,14 @@
+# Gazebo publishes the simulated 3D point cloud directly to the topic used by
+# the current MK-mini perception and control configurations.
+sensor_driver:
+ name: gazebo_mkmini_lidar
+ display_name: Gazebo MK-mini 3D LiDAR
+ dimension: 3d
+ modes: [sim]
+ compatible_platforms: [mkmini]
+ scan_adapter: pointcloud_passthrough
+ driver_launch:
+ package: ""
+ launch: ""
+ speed_msg: none
+ bridge: {}
diff --git a/src/vehicle_pkg/config/vehicle_drivers/vehicle_driver_gazebo_mkmini_passthrough.yaml b/src/vehicle_pkg/config/vehicle_drivers/vehicle_driver_gazebo_mkmini_passthrough.yaml
new file mode 100644
index 0000000..dc50392
--- /dev/null
+++ b/src/vehicle_pkg/config/vehicle_drivers/vehicle_driver_gazebo_mkmini_passthrough.yaml
@@ -0,0 +1,10 @@
+# Gazebo MK-mini consumes Nav2 Twist messages directly through the Ackermann
+# plugin. This profile intentionally has no hardware driver or adapter.
+vehicle_driver:
+ name: gazebo_mkmini_passthrough
+ display_name: Gazebo MK-mini Twist passthrough
+ adapter: ""
+ driver_launch:
+ package: ""
+ launch: ""
+ adapter_params: {}
diff --git a/src/vehicle_pkg/launch/mkmini_gazebo.launch.py b/src/vehicle_pkg/launch/mkmini_gazebo.launch.py
new file mode 100644
index 0000000..2fbd6e4
--- /dev/null
+++ b/src/vehicle_pkg/launch/mkmini_gazebo.launch.py
@@ -0,0 +1,35 @@
+"""Opt-in Gazebo backend for the MK-mini vehicle profile."""
+
+import os
+
+from ament_index_python.packages import get_package_share_directory
+from launch import LaunchDescription
+from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription, SetEnvironmentVariable
+from launch.conditions import IfCondition
+from launch.launch_description_sources import PythonLaunchDescriptionSource
+from launch.substitutions import EnvironmentVariable, LaunchConfiguration
+
+
+def generate_launch_description():
+ pkg_share = get_package_share_directory('vehicle_pkg')
+ gazebo_share = get_package_share_directory('gazebo_ros')
+ model_dir = os.path.join(pkg_share, 'models')
+ world_path = os.path.join(pkg_share, 'worlds', 'mkmini_gazebo.world')
+ gui = LaunchConfiguration('gui')
+
+ return LaunchDescription([
+ DeclareLaunchArgument('gui', default_value='true'),
+ SetEnvironmentVariable(
+ name='GAZEBO_MODEL_PATH',
+ value=[model_dir, os.pathsep, EnvironmentVariable('GAZEBO_MODEL_PATH', default_value='')],
+ ),
+ IncludeLaunchDescription(
+ PythonLaunchDescriptionSource(os.path.join(gazebo_share, 'launch', 'gazebo.launch.py')),
+ launch_arguments={
+ 'world': world_path,
+ 'gui': gui,
+ 'verbose': 'false',
+ 'pause': 'false',
+ }.items(),
+ ),
+ ])
diff --git a/src/vehicle_pkg/launch/vehicle.launch.py b/src/vehicle_pkg/launch/vehicle.launch.py
index 12e61c8..1c9c267 100755
--- a/src/vehicle_pkg/launch/vehicle.launch.py
+++ b/src/vehicle_pkg/launch/vehicle.launch.py
@@ -24,6 +24,10 @@ from vehicle_pkg.profiles import resolve_plan
ARGUMENTS = [
DeclareLaunchArgument('sim_mode', default_value='false'),
+ # Empty keeps the existing platform profile behavior (MK-mini sim = CARLA).
+ # gazebo is opt-in so the real vehicle and current CARLA flows are unchanged.
+ DeclareLaunchArgument('simulator', default_value=''),
+ DeclareLaunchArgument('gui', default_value='true'),
DeclareLaunchArgument('lidar', default_value='ouster'), # carla spawn 용 (choices 완화)
DeclareLaunchArgument('level', default_value='None', choices=['None', '2d', '3d']),
DeclareLaunchArgument('platform', default_value='mkmini'),
@@ -46,6 +50,8 @@ ARGUMENTS = [
def build(context, *args, **kwargs):
sim_mode = LaunchConfiguration('sim_mode').perform(context)
+ simulator = LaunchConfiguration('simulator').perform(context)
+ gui = LaunchConfiguration('gui').perform(context)
lidar = LaunchConfiguration('lidar').perform(context)
level = LaunchConfiguration('level').perform(context)
platform = LaunchConfiguration('platform').perform(context)
@@ -69,7 +75,8 @@ def build(context, *args, **kwargs):
pkg_share, platform_name, sim_mode, vehicle_driver, sensor_driver,
extra_config_dirs=extra_config_dirs,
sensor_driver_params=sensor_driver_params,
- vehicle_driver_params=vehicle_driver_params)
+ vehicle_driver_params=vehicle_driver_params,
+ simulator=simulator)
sim = (sim_mode == 'true')
actions = []
@@ -90,6 +97,12 @@ def build(context, *args, **kwargs):
('spawn_imu', spawn_imu),
],
))
+ elif sim and plan['simulator'] == 'gazebo':
+ gazebo_launch = os.path.join(pkg_share, 'launch', 'mkmini_gazebo.launch.py')
+ actions.append(IncludeLaunchDescription(
+ PythonLaunchDescriptionSource(gazebo_launch),
+ launch_arguments=[('gui', gui)],
+ ))
elif not sim:
actions.append(Node(package='vehicle_pkg', executable='pub_clock',
name='pub_clock', output='screen'))
diff --git a/src/vehicle_pkg/models/mkmini_gazebo/model.config b/src/vehicle_pkg/models/mkmini_gazebo/model.config
new file mode 100644
index 0000000..f50fbe0
--- /dev/null
+++ b/src/vehicle_pkg/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/vehicle_pkg/models/mkmini_gazebo/model.sdf b/src/vehicle_pkg/models/mkmini_gazebo/model.sdf
new file mode 100644
index 0000000..5d59150
--- /dev/null
+++ b/src/vehicle_pkg/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
+
+
+
diff --git a/src/vehicle_pkg/package.xml b/src/vehicle_pkg/package.xml
index a977a2f..a4aabe8 100755
--- a/src/vehicle_pkg/package.xml
+++ b/src/vehicle_pkg/package.xml
@@ -13,6 +13,7 @@
yhs_can_interfaces
yhs_can_control
vanjee_lidar_sdk
+ gazebo_ros
ament_copyright
ament_flake8
diff --git a/src/vehicle_pkg/setup.py b/src/vehicle_pkg/setup.py
index e2be388..4d168e9 100755
--- a/src/vehicle_pkg/setup.py
+++ b/src/vehicle_pkg/setup.py
@@ -20,6 +20,8 @@ setup(
(os.path.join('share', package_name, 'config', 'platforms'), glob('config/platforms/*.yaml')),
(os.path.join('share', package_name, 'config', 'vehicle_drivers'), glob('config/vehicle_drivers/*.yaml')),
(os.path.join('share', package_name, 'config', 'sensor_drivers'), glob('config/sensor_drivers/*.yaml')),
+ (os.path.join('share', package_name, 'models', 'mkmini_gazebo'), glob('models/mkmini_gazebo/*')),
+ (os.path.join('share', package_name, 'worlds'), glob('worlds/*.world')),
],
install_requires=['setuptools'],
zip_safe=True,
diff --git a/src/vehicle_pkg/vehicle_pkg/profiles.py b/src/vehicle_pkg/vehicle_pkg/profiles.py
index 120ac8c..0e454b4 100755
--- a/src/vehicle_pkg/vehicle_pkg/profiles.py
+++ b/src/vehicle_pkg/vehicle_pkg/profiles.py
@@ -99,7 +99,7 @@ def _merge_params(prof, kind, raw_b64):
def resolve_plan(pkg_share, platform_name, sim_mode,
vehicle_driver_arg='', sensor_driver_arg='',
extra_config_dirs='', sensor_driver_params='',
- vehicle_driver_params=''):
+ vehicle_driver_params='', simulator=''):
"""platform/sim_mode/override 로 launch 플랜(dict) 해소. ROS 비의존.
sim_mode 는 'true'/'false' 문자열. override 가 빈 문자열이면 platform 기본값 사용.
@@ -113,7 +113,14 @@ def resolve_plan(pkg_share, platform_name, sim_mode,
extra_dirs = [d for d in str(extra_config_dirs).split(':') if d]
# 드라이버 이름 선택 (선택 source = platform 프로파일 데이터)
- if sim:
+ simulator_name = str(simulator).strip()
+ if simulator_name and not sim:
+ raise ValueError('[profiles] simulator override requires sim_mode:=true')
+
+ if sim and simulator_name == 'gazebo':
+ vd_name = P.get('gazebo_vehicle_driver', P['sim_vehicle_driver'])
+ sd_name = P.get('gazebo_sensor_driver', P['sim_sensor_driver'])
+ elif sim:
vd_name = P['sim_vehicle_driver']
sd_name = P['sim_sensor_driver']
else:
@@ -149,7 +156,7 @@ def resolve_plan(pkg_share, platform_name, sim_mode,
return {
'platform': P['name'],
- 'simulator': P.get('simulator', 'carla' if sim else 'real'),
+ 'simulator': simulator_name or P.get('simulator', 'carla' if sim else 'real'),
'drive_type': P['drive_type'],
'perception_profile': P.get('perception_profile', P['name']),
'lidar_frame': P.get('lidar_frame'),
diff --git a/src/vehicle_pkg/worlds/mkmini_gazebo.world b/src/vehicle_pkg/worlds/mkmini_gazebo.world
new file mode 100644
index 0000000..6283721
--- /dev/null
+++ b/src/vehicle_pkg/worlds/mkmini_gazebo.world
@@ -0,0 +1,21 @@
+
+
+
+ 0 0 -9.8
+
+ false
+ 0 0 10 0 0 0
+ 0.8 0.8 0.8 1
+ 0.2 0.2 0.2 1
+ -0.5 0.1 -0.9
+
+
+ true
+
+ 0 0 1100 100
+ 0 0 1100 1000.22 0.25 0.29 10.22 0.25 0.29 1
+
+
+ model://mkmini_gazebo
+
+