소스 정보
- 저장소
- MIUAV/vibe-coding-ros2
- 최근 소스 활동
- 2026년 4월 3일 16:37
- 감지된 SKILL.md 언어
- 판별 불가
- 스타
- 26
- 포크
- 2
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/MIUAV/vibe-coding-ros2 --skill slam명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SKILL.md 표시 중
SOC 직업 분류 기준
| name | slam |
| description | SLAM 算法技能 - LaserSLAM、VisualSLAM、RTAB-Map、Cartographer、GMapping |
| argument-hint | SLAM OR slam OR 地图构建 OR laser slam OR visual slam OR 同步定位与建图 |
| user-invocable | true |
同步定位与建图(Simultaneous Localization and Mapping)
当需要以下帮助时使用此技能:
| 类型 | 传感器 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| GMapping | 激光雷达 | 计算量小 | 精度一般 | 室内、小场景 |
| Cartographer | 激光雷达 | 高精度、实时 | 资源消耗大 | 室内+室外 |
| RTAB-Map | 深度相机 | 闭环检测强 | 内存消耗大 | 大场景 |
| ORB-SLAM3 | 单目/立体 | 多地图 | 需要纹理 | 室内有纹理 |
| LIO-SAM | LiDAR+IMU | 高精度 | 需 IMU | 室外复杂地形 |
// laser_slam_node.cpp
#include <rclcpp/rclcpp.hpp>
#include <sensor_msgs/msg/laser_scan.hpp>
#include <nav_msgs/msg/odometry.hpp>
#include <tf2_ros/transform_broadcaster.h>
class LaserSlamNode : public rclcpp::Node
{
public:
LaserSlamNode() : Node("laser_slam")
{
// ── 激光雷达订阅 ───────────────────────
scan_sub_ = this->create_subscription<sensor_msgs::msg::LaserScan>(
"/scan", 10,
[this](const sensor_msgs::msg::LaserScan::SharedPtr msg) {
this->laser_callback(msg);
}
);
// ── 里程计订阅 ───────────────────────
odom_sub_ = this->create_subscription<nav_msgs::msg::Odometry>(
"/odom", 10,
[this](const nav_msgs::msg::Odometry::SharedPtr msg) {
this->odom_callback(msg);
}
);
// ── TF 广播 ─────────────────────────
tf_broadcaster_ = std::make_unique<tf2_ros::TransformBroadcaster>(*this);
// ── SLAM 初始化 ──────────────────────
slam_ = std::make_unique<GridSlam>(GridSlam::Params{
.particle_count = 30,
.map_resolution = 0.05,
.range_max =
});
(->(), );
}
:
{
pose = odom_queue_.();
slam_->(scan, pose);
();
(pose);
}
{
odom_queue_.(odom->pose.pose);
(odom_queue_.() > ) odom_queue_.();
}
std::unique_ptr<GridSlam> slam_;
std::deque<geometry_msgs::msg::Pose> odom_queue_;
rclcpp::Subscription<sensor_msgs::msg::LaserScan>::SharedPtr scan_sub_;
rclcpp::Subscription<nav_msgs::msg::Odometry>::SharedPtr odom_sub_;
std::unique_ptr<tf2_ros::TransformBroadcaster> tf_broadcaster_;
};
# laser_slam.launch.py
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
package="laser_slam",
executable="laser_slam_node",
name="laser_slam",
parameters=[{
"particle_count": 30,
"map_resolution": 0.05,
"range_max": 30.0,
"publish_map": True,
"publish_tf": True,
}],
remappings=[
("/scan", "/front_laser/scan"),
("/odom", "/robot_odom"),
],
),
])
-- cartographer.lua
INCLUDE "map_builder.lua"
INCLUDE "trajectory_builder.lua"
MAP_BUILDER = {
map_builder_pub_sub_state = true,
}
TRAJECTORY_BUILDER = {
trajectory_builder_2d = {
scan_matcher_config = {
occupied_space_weight = 20.0,
resolution = 0.05,
},
},
}
# cartographer.launch.py
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
package="cartographer_ros",
executable="cartographer_node",
name="cartographer",
parameters=[{"configuration_directory": "/path/to/config"},
{"configuration_basename": "cartographer.lua"}],
remappings=[
("/scan", "/front_laser/scan"),
],
),
Node(
package="cartographer_ros",
executable="cartographer_occupancy_grid_node",
name="occupancy_grid_node",
),
])
// visual_slam_node.cpp — RTAB-Map 视觉 SLAM
#include <rtabmap_ros/rtabmap.h>
class VisualSlamNode : public rclcpp::Node
{
public:
VisualSlamNode() : Node("visual_slam")
{
// 深度相机话题
rtabmap_.init(this, "visual_slam");
// 订阅深度相机 + RGB
depth_sub_ = this->create_subscription<sensor_msgs::msg::Image>(
"/depth/image_rect_raw", 1,
[this](const sensor_msgs::msg::Image::SharedPtr img) {
rtabmap_.processDepth(img);
}
);
rgb_sub_ = this->create_subscription<sensor_msgs::msg::Image>(
"/rgb/image_rect_color", 1,
[this](const sensor_msgs::msg::Image::SharedPtr img) {
rtabmap_.processRGBD(img);
}
);
}
};
□ 激光雷达数据格式正确(/scan)
□ TF 树正确(map → odom → base_link)
□ 里程计话题已连接(/odom)
□ 地图分辨率合理(室内: 0.02-0.05m,室外: 0.05-0.1m)
□ 实时性满足(SLAM 处理 < 100ms/帧)
□ 地图更新频率合理(5-10Hz)
□ 定位精度 < 0.1m
□ 闭环检测工作正常(如使用 RTAB-Map)
□ 栅格地图覆盖率 > 80%
| 问题 | 原因 | 解决 |
|---|---|---|
| 地图漂移 | 里程计累计误差 | 添加 IMU 融合 / 闭环检测 |
| 定位丢失 | 激光雷达数据质量差 | 清洁传感器 / 调整参数 |
| 实时性差 | 计算量过大 | 减少粒子数 / 降低分辨率 |
| 地图空洞 | 传感器视角不足 | 增加激光雷达数量 |
| 闭环失败 | 场景重复性高 | 使用视觉 SLAM 辅助闭环 |
| 指标 | 目标 | 测量方法 |
|---|---|---|
| 处理延迟 | < 50ms/帧 | 记录回调耗时 |
| 定位精度 | < 0.1m | 与已知地图对比 |
| 地图分辨率 | 0.02-0.1m | 检查栅格大小 |
| TF 延迟 | < 10ms | ros2 topic delay /tf |
| 内存占用 | < 2GB | top / htop |