commit 74f568d5c9cf844ed58911537cdeaf36ad08eb00 Author: chyoo Date: Tue Sep 22 09:48:32 2026 +0900 feat: add Yahboom control module for LMS diff --git a/.autonomy-studio-module.json b/.autonomy-studio-module.json new file mode 100644 index 0000000..33c4029 --- /dev/null +++ b/.autonomy-studio-module.json @@ -0,0 +1,8 @@ +{ + "sourceType": "GIT", + "name": "NAV2-Yahboom-Control", + "category": "Control", + "dockerImage": "future-nav2:humble-yahboom", + "packageName": "yahboom_control", + "launchFile": "control.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..40f345f --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# NAV2-Yahboom-Control + +LMS 전용 템플릿 저장소입니다. 설치 폴더: `[lms-nav2-yahboom-control]yahboom_control_v1.0.0_ws` + +- 패키지: `yahboom_control` +- 런치: `control.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_control/CMakeLists.txt b/src/yahboom_control/CMakeLists.txt new file mode 100644 index 0000000..119411b --- /dev/null +++ b/src/yahboom_control/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.8) +project(yahboom_control) +find_package(ament_cmake REQUIRED) +install(DIRECTORY launch params DESTINATION share/${PROJECT_NAME}) +ament_package() diff --git a/src/yahboom_control/launch/control.launch.py b/src/yahboom_control/launch/control.launch.py new file mode 100644 index 0000000..a240333 --- /dev/null +++ b/src/yahboom_control/launch/control.launch.py @@ -0,0 +1,25 @@ +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_control") + params = os.path.join(share, "params", "control.yaml") + nodes = [["nav2_controller","controller_server","controller_server"],["nav2_behaviors","behavior_server","behavior_server"]] + actions = [] + for package, executable, name in nodes: + actions.append(Node( + package=package, executable=executable, name=name, output="screen", + parameters=[params], + remappings=[("odom", "/odom")], + )) + actions.append(Node( + package="nav2_lifecycle_manager", executable="lifecycle_manager", + name="lifecycle_manager_yahboom_control", output="screen", + parameters=[{"use_sim_time": False, "autostart": True, + "node_names": [name for _, _, name in nodes]}], + )) + return LaunchDescription(actions) diff --git a/src/yahboom_control/package.xml b/src/yahboom_control/package.xml new file mode 100644 index 0000000..44c9dbf --- /dev/null +++ b/src/yahboom_control/package.xml @@ -0,0 +1,14 @@ + + + yahboom_control + 1.0.0 + Yahboom LMS control module, adapted from hkit_yahboom_ws. + FutureDrive + Apache-2.0 + ament_cmake + launch + launch_ros + ament_index_python + nav2_bringup + ament_cmake + diff --git a/src/yahboom_control/params/control.yaml b/src/yahboom_control/params/control.yaml new file mode 100644 index 0000000..a2d4d0c --- /dev/null +++ b/src/yahboom_control/params/control.yaml @@ -0,0 +1,151 @@ +controller_server: + ros__parameters: + use_sim_time: false + controller_frequency: 20.0 + min_x_velocity_threshold: 0.001 + min_y_velocity_threshold: 0.001 + min_theta_velocity_threshold: 0.001 + progress_checker_plugin: progress_checker + controller_plugins: + - FollowPath + progress_checker: + plugin: nav2_controller::SimpleProgressChecker + required_movement_radius: 0.5 + movement_time_allowance: 10.0 + goal_checker: + plugin: nav2_controller::SimpleGoalChecker + xy_goal_tolerance: 0.25 + yaw_goal_tolerance: 0.25 + stateful: true + FollowPath: + plugin: dwb_core::DWBLocalPlanner + debug_trajectory_details: true + min_vel_x: 0.0 + min_vel_y: 0.0 + max_vel_x: 0.2 + max_vel_y: 0.0 + max_vel_theta: 1.0 + min_speed_xy: 0.0 + max_speed_xy: 0.2 + min_speed_theta: 0.0 + acc_lim_x: 2.5 + acc_lim_y: 0.0 + acc_lim_theta: 3.2 + decel_lim_x: -2.5 + decel_lim_y: 0.0 + decel_lim_theta: -3.2 + vx_samples: 20 + vy_samples: 5 + vtheta_samples: 20 + sim_time: 1.7 + linear_granularity: 0.05 + angular_granularity: 0.025 + transform_tolerance: 0.2 + xy_goal_tolerance: 0.25 + trans_stopped_velocity: 0.01 + short_circuit_trajectory_evaluation: true + stateful: true + critics: + - RotateToGoal + - Oscillation + - BaseObstacle + - GoalAlign + - PathAlign + - PathDist + - GoalDist + BaseObstacle.scale: 0.02 + PathAlign.scale: 32.0 + PathAlign.forward_point_distance: 0.1 + GoalAlign.scale: 24.0 + GoalAlign.forward_point_distance: 0.1 + PathDist.scale: 32.0 + GoalDist.scale: 24.0 + RotateToGoal.scale: 32.0 + RotateToGoal.slowing_factor: 5.0 + RotateToGoal.lookahead_time: -1.0 + goal_checker_plugins: + - goal_checker + odom_topic: /odom +local_costmap: + local_costmap: + ros__parameters: + update_frequency: 5.0 + publish_frequency: 2.0 + global_frame: odom + robot_base_frame: base_footprint + use_sim_time: false + rolling_window: true + width: 3 + height: 3 + resolution: 0.05 + robot_radius: 0.1 + plugins: + - obstacle_layer + - voxel_layer + - inflation_layer + inflation_layer: + plugin: nav2_costmap_2d::InflationLayer + cost_scaling_factor: 5.0 + inflation_radius: 0.6 + obstacle_layer: + plugin: nav2_costmap_2d::ObstacleLayer + enabled: true + observation_sources: scan + scan: + topic: /scan + max_obstacle_height: 2.0 + clearing: true + marking: true + data_type: LaserScan + voxel_layer: + plugin: nav2_costmap_2d::VoxelLayer + enabled: true + publish_voxel_map: true + origin_z: 0.0 + z_resolution: 0.05 + z_voxels: 16 + max_obstacle_height: 2.0 + mark_threshold: 0 + observation_sources: scan + scan: + topic: /scan + max_obstacle_height: 2.0 + clearing: true + marking: true + data_type: LaserScan + raytrace_max_range: 3.0 + raytrace_min_range: 0.0 + obstacle_max_range: 2.5 + obstacle_min_range: 0.0 + static_layer: + map_subscribe_transient_local: true + always_send_full_costmap: true + local_costmap_client: + ros__parameters: + use_sim_time: false + local_costmap_rclcpp_node: + ros__parameters: + use_sim_time: false +behavior_server: + ros__parameters: + use_sim_time: false + costmap_topic: local_costmap/costmap_raw + footprint_topic: local_costmap/published_footprint + cycle_frequency: 10.0 + behavior_plugins: + - spin + - backup + - wait + spin: + plugin: nav2_behaviors/Spin + backup: + plugin: nav2_behaviors/BackUp + wait: + plugin: nav2_behaviors/Wait + global_frame: odom + robot_base_frame: base_footprint + transform_tolerance: 0.2 + simulate_ahead_time: 2.0 + max_rotational_vel: 0.2 + min_rotational_vel: 0.0 + rotational_acc_lim: 0.2 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"