commit 54d7fd8d18fd5d24af361c5eb3c11fa3db5d036f Author: chyoo Date: Tue Sep 22 09:48:30 2026 +0900 feat: add Yahboom slam module for LMS diff --git a/.autonomy-studio-module.json b/.autonomy-studio-module.json new file mode 100644 index 0000000..6588b6c --- /dev/null +++ b/.autonomy-studio-module.json @@ -0,0 +1,8 @@ +{ + "sourceType": "GIT", + "name": "NAV2-Yahboom-Slam", + "category": "Localization", + "dockerImage": "future-nav2:humble-yahboom", + "packageName": "yahboom_slam", + "launchFile": "slam.launch.py" +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ecbae9e --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +build/ +install/ +log/ +__pycache__/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..00319b4 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# NAV2-Yahboom-Slam + +LMS 전용 템플릿 저장소입니다. 설치 폴더: `[lms-nav2-yahboom-slam]yahboom_slam_v1.0.0_ws` + +- 패키지: `yahboom_slam` +- 런치: `slam.launch.py` +- 이미지: `future-nav2:humble-yahboom` +- 앱의 야붐 실행기 지원이 반영되어야 합니다. +- 서버 과정의 야붐 전용 환경에 이 모듈과 이미지 아티팩트를 등록한 후 + LMS에서 설치 -> 빌드 -> 실행합니다. +- ROS_DOMAIN_ID는 ESP32 설정과 일치시킵니다. GPU 가속은 끕니다. +- 컨테이너 장치: 없음 +- SLAM과 Localization은 동시에 실행하지 않습니다. +- 실차 검증 전 소스입니다. 바퀴를 띄우고 비상정지와 명령 타임아웃을 확인하세요. + +원본 소스: https://github.com/KingKiser/hkit_yahboom_ws +작성자 박승휘, 원본 package.xml 저작자 Leo Cho, 원본 라이선스 표기 Apache 2.0. +재배포 전 자산 라이선스를 확인하세요. diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..7d66537 --- /dev/null +++ b/build.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -euo pipefail +MODULE_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +RUNTIME_ROOT="${AUTONOMY_STUDIO_RUNTIME_ROOT:-$HOME/autonomy-studio/runtime/nav2}" +FOLDER_NAME="$(basename "$MODULE_PATH")" +IMAGE="${NAV2_DOCKER_IMAGE:-future-nav2:humble-yahboom}" +exec bash "$RUNTIME_ROOT/docker/docker_build_nav2.sh" "$(dirname "$MODULE_PATH")" "$FOLDER_NAME" "$IMAGE" "${ROS_DOMAIN_ID:-20}" diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..ef2acf7 --- /dev/null +++ b/run.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -euo pipefail +MODULE_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +RUNTIME_ROOT="${AUTONOMY_STUDIO_RUNTIME_ROOT:-$HOME/autonomy-studio/runtime/nav2}" +FOLDER_NAME="$(basename "$MODULE_PATH")" +IMAGE="${NAV2_DOCKER_IMAGE:-future-nav2:humble-yahboom}" +ROS_PARAM='' +CONTAINER_NAME="${FOLDER_NAME#\[}" +CONTAINER_NAME="${CONTAINER_NAME/\]/-}" +CONTAINER_NAME="${CONTAINER_NAME%_ws}" +read -r -a DEFAULT_ARGS <<< "$ROS_PARAM" +exec bash "$RUNTIME_ROOT/docker/docker_run_nav2.sh" "$CONTAINER_NAME" "$(dirname "$MODULE_PATH")" "$FOLDER_NAME" "$IMAGE" "${ROS_DOMAIN_ID:-20}" "${GPU_ENABLED:-false}" "${DEFAULT_ARGS[@]}" "$@" diff --git a/src/yahboom_slam/CMakeLists.txt b/src/yahboom_slam/CMakeLists.txt new file mode 100644 index 0000000..77436d0 --- /dev/null +++ b/src/yahboom_slam/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.8) +project(yahboom_slam) +find_package(ament_cmake REQUIRED) +install(DIRECTORY launch params DESTINATION share/${PROJECT_NAME}) +ament_package() diff --git a/src/yahboom_slam/launch/slam.launch.py b/src/yahboom_slam/launch/slam.launch.py new file mode 100644 index 0000000..3102b93 --- /dev/null +++ b/src/yahboom_slam/launch/slam.launch.py @@ -0,0 +1,19 @@ +import os +from ament_index_python.packages import get_package_share_directory +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration +from launch_ros.actions import Node + +def generate_launch_description(): + share = get_package_share_directory("yahboom_slam") + return LaunchDescription([ + Node(package="cartographer_ros", executable="cartographer_node", + parameters=[{"use_sim_time": False}], output="screen", + arguments=["-configuration_directory", os.path.join(share, "params"), + "-configuration_basename", "yahboom_cartographer.lua"], + remappings=[("scan", "/scan"), ("odom", "/odom")]), + Node(package="cartographer_ros", executable="cartographer_occupancy_grid_node", + parameters=[{"use_sim_time": False}], output="screen", + arguments=["-resolution", "0.05", "-publish_period_sec", "1.0"]), + ]) diff --git a/src/yahboom_slam/package.xml b/src/yahboom_slam/package.xml new file mode 100644 index 0000000..3d57786 --- /dev/null +++ b/src/yahboom_slam/package.xml @@ -0,0 +1,14 @@ + + + yahboom_slam + 1.0.0 + Yahboom LMS slam module, adapted from hkit_yahboom_ws. + FutureDrive + Apache-2.0 + ament_cmake + launch + launch_ros + ament_index_python + cartographer_ros + ament_cmake + diff --git a/src/yahboom_slam/params/yahboom_cartographer.lua b/src/yahboom_slam/params/yahboom_cartographer.lua new file mode 100644 index 0000000..c98394e --- /dev/null +++ b/src/yahboom_slam/params/yahboom_cartographer.lua @@ -0,0 +1,67 @@ +include "map_builder.lua" +include "trajectory_builder.lua" +--001 +options = { + map_builder = MAP_BUILDER, + trajectory_builder = TRAJECTORY_BUILDER, + + map_frame = "map", + + -- /imu의 header.frame_id + tracking_frame = "base_footprint", + + -- 기존 wheel odometry가 odom_frame -> base_footprint를 발행하므로 + -- Cartographer는 map -> odom_frame을 발행 + published_frame = "odom", + odom_frame = "odom", + + -- 기존 /odom_raw 및 TF를 사용하므로 Cartographer가 + -- odom 프레임을 별도로 만들지 않음 + provide_odom_frame = false, + + publish_frame_projected_to_2d = true, + + -- /odom_raw 사용 + use_odometry = true, + + use_nav_sat = false, + use_landmarks = false, + + -- /scan 사용 + num_laser_scans = 1, + num_multi_echo_laser_scans = 0, + num_subdivisions_per_laser_scan = 1, + num_point_clouds = 0, + + lookup_transform_timeout_sec = 0.2, + + submap_publish_period_sec = 0.3, + pose_publish_period_sec = 5e-3, + trajectory_publish_period_sec = 30e-3, + + rangefinder_sampling_ratio = 1.0, + odometry_sampling_ratio = 1.0, + fixed_frame_pose_sampling_ratio = 1.0, + imu_sampling_ratio = 1.0, + landmarks_sampling_ratio = 1.0, +} + +MAP_BUILDER.use_trajectory_builder_2d = true + +-- /scan 스펙 +TRAJECTORY_BUILDER_2D.min_range = 0.12 +TRAJECTORY_BUILDER_2D.max_range = 8.0 +TRAJECTORY_BUILDER_2D.missing_data_ray_length = 3.0 + +-- /imu 사용 +TRAJECTORY_BUILDER_2D.use_imu_data = false + +TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching = true + +TRAJECTORY_BUILDER_2D.motion_filter.max_angle_radians = + math.rad(0.1) + +POSE_GRAPH.constraint_builder.min_score = 0.65 +POSE_GRAPH.constraint_builder.global_localization_min_score = 0.7 + +return options diff --git a/stop.sh b/stop.sh new file mode 100755 index 0000000..f439c76 --- /dev/null +++ b/stop.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -euo pipefail +MODULE_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +RUNTIME_ROOT="${AUTONOMY_STUDIO_RUNTIME_ROOT:-$HOME/autonomy-studio/runtime/nav2}" +FOLDER_NAME="$(basename "$MODULE_PATH")" +IMAGE="${NAV2_DOCKER_IMAGE:-future-nav2:humble-yahboom}" +CONTAINER_NAME="${FOLDER_NAME#\[}" +CONTAINER_NAME="${CONTAINER_NAME/\]/-}" +CONTAINER_NAME="${CONTAINER_NAME%_ws}" +docker stop -t 10 "$CONTAINER_NAME"